使用phantomjs在本地文件上使用extjs代理进行ajax调用

时间:2012-08-13 11:04:23

标签: javascript unit-testing extjs jasmine phantomjs

我有一个基本的EXT JS商店,它使用代理来访问本地json文件。

e.g。

...
proxy: {
    type: 'ajax',
    api: {
        read: 'data/mydata.json'
    },
    reader: {
        type: 'json',
        root: 'datas',
        successProperty: 'success'
    }
} 
...

我想使用Maven,Jasmine和PhantomJS使用Atlassian Bamboo(我的CI服务器)构建和测试我的项目。

当我在本地执行PhantomJS时,如下所示:

$ phantomjs "c:\phantomjs-1.6.1\examples\run-jasmine.js" run-tests.html

我得到以下输出:

'waitFor()' finished in 422ms.
 4 specs, 2 failures in 0.075s

这种情况正在发生,因为PhantomJS无法使用 file:// 协议为EXT JS代理加载本地文件。

我正在关注this示例,我想知道是否可以模拟我的代理响应,以便我可以在本地(在我的Bamboo服务器上)使用带有测试html文件的PhantomJS,而不是必须托管像Apache这样的Web服务器中的项目(我将不得不使用Maven管理外部依赖)。

如果没有,是否有其他机制(内置于Jasmine,PhantomJS或其他方面),我可以使用它来实现这一目标?

3 个答案:

答案 0 :(得分:9)

从文件系统加载时,实际上 可以与PhantomJS进行XHR!

直接来自the PhantomJs wiki

--web-security=[yes|no] disables web security and allows cross-domain XHR (default is yes)

另请参阅this issue report for PhantomJs,这可能会对此主题有所了解。

Sencha的'sencha create jsb'命令使用PhantomJs(Ext.Loader使用XHR),它支持从文件系统加载。

name: 'app-entry',
alias: 'a',
description: 'The file or URL path to your application\'s HTML entry point',

结帐[senchasdktools]/compat/command/src/modules/GenerateJSB.js[senchasdktools]/compat/command/scripts/phantomjs-jsb.js

我没有看到与提到的web-security切换相关的任何内容。也许他们使用自定义的phantomJs构建。

<强>更新 此代码片段允许对文件系统的XHR请求。使用最新版本的phantomJs(1.6.1 / Windows)进行测试:

var page = new WebPage();
page.settings.localToRemoteUrlAccessEnabled = true;

<强> UPDATE2 这是一个有效的例子。

将所有内容放在同一个文件夹中,添加包含某些内容的test.txt文件,然后运行

phantomjs script.js test.html

phantomjs script(script.js):

var fs = require('fs');

var appLocation = phantom.args[0];

var page = new WebPage();

page.settings.localToRemoteUrlAccessEnabled = true;
page.settings.ignoreSslErrors = true;

page.onConsoleMessage = function(message, url, lineNumber) {
    console.log((url ? url + " " : "") + (lineNumber ? lineNumber + ": " : "") + message);
};

page.onError = function (msg, trace) {
    console.log(msg);
    trace.forEach(function(item) {
        console.log('  ', item.file, ':', item.line);
    });
    phantom.exit(1);
};

if (!/^file:\/\/|http(s?):\/\//.test(appLocation)) {
    appLocation = 'file:///' + fs.absolute(appLocation).replace(/\\/g, '/');
}

page.open(appLocation, function(status) {
    if (status !== 'success') {
        error("Failed opening: '" + appLocation + "'. Please verify that the URI is valid");
    }

    page.evaluate(function() {
        window.onerror = function(message, url, lineNumber) {
            console.log((url ? url + " " : "") + (lineNumber ? lineNumber + ": " : "") + message);
        };

    });

    timer = setInterval(function() {
        console.log('Timeout!');
        phantom.exit(1);
    }, 2000);
});

Html文件(test.html):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html class="x-border-box x-strict">
<head>
    <title>Test</title>
    <script type="text/javascript">
    var xhr = new XMLHttpRequest();

    try {
        xhr.open('GET', 'test.txt', false);
        xhr.send(null);
    } catch (e) {
        console.log('cross origin?');
    }

    console.log('status', xhr.status);
    console.log('response', xhr.responseText);

    </script>
</head>
<body class="x-body">
</body>
</html>

Chrome和--disable-web-security和ExtJs

我实际上使用--disable-web-security作为启动参数,谷歌Chrome在开发过程中从文件系统运行我的webapp并在那里工作(启动Chrome时不必运行其他Chrome进程)。 Chrome会显示一条警告消息,指出您使用的是不受支持的选项(顶部的黄色通知栏)。

然而,为了在这样的设置中工作,我需要一个额外的Ext.Connection补丁来解决两个问题: (1)加载文件系统资源时,xhr.status始终为0。 Ext不会将此状态代码视为successful。当Ext在PhantomJs中运行时,有专门用于处理此问题的代码 - 这就是它应该在那里工作的原因。

(2)当网址包含查询字符串时,Chrome无法加载文件系统资源。我重写了Connection类,以便在文件系统模式下删除所有url参数。

答案 1 :(得分:4)

即浏览器和WebKit限制(安全性),除非您运行自己的网络服务器,否则无法绕过。 nodejs有简单的方法。它只需几行代码就可以在本地机器上的某个端口上运行服务器。

在运行phantomjs之前,只需创建如下所示的server.js并使用node server.js运行它

var http = require('http');
var fs=require('fs');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/html'});
  res.end(fs.readFileSync(__dirname + req.url, 'utf8')); 
}).listen(3000, '127.0.0.1');
console.log('Server running at http://127.0.0.1:3000/');

将此文件保留在项目根目录或更新行

res.end(fs.readFileSync(__dirname + req.url, 'utf8')); 

__ dirname是server.js所在的文件夹的路径,由节点进程设置....

现在你可以保存data / * .json甚至在节点中创建模拟数据;)

===更新====

在阅读PhantomJS文档后,我发现你可以在没有nodejs的情况下完成上述操作。显然,PhanotmJS包含以上所有模块

考虑检查:

你会很高兴。

答案 2 :(得分:1)

我使用Karma测试运行器/ Jasmine 1.x和2.0版本以及处理异步问题处理ExtJS 4进行单元测试的2个回购:这里它们是:https://github.com/cgauthier/karma_jasmine_1_extjs4https://github.com/cgauthier/karma_jasmine_2_extjs4。< / p>