mirror of
https://github.com/zhigang1992/angular.js.git
synced 2026-04-24 12:05:46 +08:00
chore(tests): implement e2e test harness outside of docs app
Included: - A sample test fixture - A sample test - Server middleware to serve the E2E harness - Convenient test helpers to simplify loading the right fixture Closes #9557 Closes #9527
This commit is contained in:
8
test/e2e/fixtures/.jshintrc
Normal file
8
test/e2e/fixtures/.jshintrc
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"browser": true,
|
||||
"globals": {
|
||||
"angular": false,
|
||||
"jQuery": false,
|
||||
"$": false
|
||||
}
|
||||
}
|
||||
9
test/e2e/fixtures/sample/index.html
Normal file
9
test/e2e/fixtures/sample/index.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html ng-app="test">
|
||||
<div ng-controller="TestCtrl">
|
||||
<p>{{text}}</p>
|
||||
</div>
|
||||
|
||||
<script src="angular.js"></script>
|
||||
<script src="script.js"></script>
|
||||
</html>
|
||||
4
test/e2e/fixtures/sample/script.js
Normal file
4
test/e2e/fixtures/sample/script.js
Normal file
@@ -0,0 +1,4 @@
|
||||
angular.module("test", []).
|
||||
controller("TestCtrl", function($scope) {
|
||||
$scope.text = "Hello, world!";
|
||||
});
|
||||
23
test/e2e/templates/test.html
Normal file
23
test/e2e/templates/test.html
Normal file
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
{% if eq(test.ngAppTag, "html") %}
|
||||
<html ng-app="{{ test.ngApp }}">
|
||||
{% else %}
|
||||
<html>
|
||||
{% endif %}
|
||||
<head>
|
||||
{% if scripts.jQuery %}
|
||||
<script src="{{ scripts.jQuery }}"></script>
|
||||
{% endif %}
|
||||
{% for script in test.scripts %}
|
||||
<script src="{{ test.scripts[script] }}"></script>
|
||||
{% endfor %}
|
||||
{{ test.head }}
|
||||
</head>
|
||||
{% if test.ngAppTag === "body" %}
|
||||
<body ng-app="{{ test.ngApp }}">
|
||||
{% else %}
|
||||
<body>
|
||||
{% endif %}
|
||||
{% test.body %}
|
||||
</body>
|
||||
</html>
|
||||
11
test/e2e/tests/.jshintrc
Normal file
11
test/e2e/tests/.jshintrc
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"node": true,
|
||||
"globals": {
|
||||
"describe": false,
|
||||
"ddescribe": false,
|
||||
"xdescribe": false,
|
||||
"it": false,
|
||||
"xit": false,
|
||||
"iit": false
|
||||
}
|
||||
}
|
||||
23
test/e2e/tests/helpers/main.js
Normal file
23
test/e2e/tests/helpers/main.js
Normal file
@@ -0,0 +1,23 @@
|
||||
var helper = {
|
||||
andWaitForAngular: function() {
|
||||
browser.waitForAngular();
|
||||
},
|
||||
loadFixture: function(fixture) {
|
||||
var i = 0;
|
||||
while (fixture[i] === '/') ++i;
|
||||
fixture = fixture.slice(i);
|
||||
if (!/\/(index\.html)?$/.test(fixture)) {
|
||||
fixture += '/';
|
||||
}
|
||||
|
||||
if (process.env.USE_JQUERY) {
|
||||
fixture += '?jquery';
|
||||
}
|
||||
|
||||
browser.get('/e2e/fixtures/' + fixture);
|
||||
return helper;
|
||||
}
|
||||
};
|
||||
|
||||
global.test = helper;
|
||||
global.loadFixture = helper.loadFixture;
|
||||
12
test/e2e/tests/sampleSpec.js
Normal file
12
test/e2e/tests/sampleSpec.js
Normal file
@@ -0,0 +1,12 @@
|
||||
// Sample E2E test:
|
||||
//
|
||||
describe('Sample', function() {
|
||||
beforeEach(function() {
|
||||
loadFixture("sample").andWaitForAngular();
|
||||
});
|
||||
|
||||
it('should have the interpolated text', function() {
|
||||
expect(element(by.binding('text')).getText())
|
||||
.toBe('Hello, world!');
|
||||
});
|
||||
});
|
||||
3
test/e2e/tools/.jshintrc
Normal file
3
test/e2e/tools/.jshintrc
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"node": true
|
||||
}
|
||||
83
test/e2e/tools/fixture.js
Normal file
83
test/e2e/tools/fixture.js
Normal file
@@ -0,0 +1,83 @@
|
||||
'use strict';
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var $ = require('cheerio');
|
||||
var util = require('./util');
|
||||
|
||||
var root = path.resolve(__dirname, '..');
|
||||
var fixtures = path.resolve(root, 'fixtures');
|
||||
|
||||
var projectRoot = path.resolve(__dirname, '../../..');
|
||||
var build = path.resolve(projectRoot, 'build');
|
||||
|
||||
function rewriteAngularSrc(src, query) {
|
||||
if (query) {
|
||||
if (query.build) {
|
||||
return query.build + '/' + src;
|
||||
} else if (query.cdn) {
|
||||
return '//ajax.googleapis.com/ajax/libs/angularjs/' + query.cdn + '/' + src;
|
||||
}
|
||||
}
|
||||
return '/build/' + src;
|
||||
}
|
||||
|
||||
function generateFixture(test, query) {
|
||||
var indexFile = path.resolve(fixtures, test, 'index.html');
|
||||
var text = fs.readFileSync(indexFile, 'utf8');
|
||||
|
||||
var $$ = $.load(text);
|
||||
|
||||
var firstScript = null;
|
||||
var jquery = null;
|
||||
var angular = null;
|
||||
$$('script').each(function(i, script) {
|
||||
var src = $(script).attr('src');
|
||||
if (src === 'jquery.js' && jquery === null) jquery = script;
|
||||
else if (src === 'angular.js' && angular === null) angular = script;
|
||||
if (firstScript === null) firstScript = script;
|
||||
if (src) {
|
||||
var s = util.stat(path.resolve(build, src));
|
||||
if (s && s.isFile()) {
|
||||
$(script).attr('src', rewriteAngularSrc(src, query));
|
||||
} else {
|
||||
$(script).attr('src', util.rewriteTestFile(test, src));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (jquery && (!('jquery' in query) || (/^(0|no|false|off|n)$/i).test(query.jquery))) {
|
||||
$(jquery).remove();
|
||||
} else if ('jquery' in query) {
|
||||
if ((/^(0|no|false|off|n)$/i).test(query.jquery)) {
|
||||
if (jquery) {
|
||||
$(jquery).remove();
|
||||
}
|
||||
} else {
|
||||
if (!jquery) {
|
||||
jquery = $.load('<script></script>')('script')[0];
|
||||
if (firstScript) {
|
||||
$(firstScript).before(jquery);
|
||||
} else {
|
||||
var head = $$('head');
|
||||
if (head.length) {
|
||||
head.prepend(jquery);
|
||||
} else {
|
||||
$$.root().first().before(jquery);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!/^\d+\.\d+.*$/.test(query.jquery)) {
|
||||
$(jquery).attr('src', '/bower_components/jquery/dist/jquery.js');
|
||||
} else {
|
||||
$(jquery).attr('src', '//ajax.googleapis.com/ajax/libs/jquery/' + query.jquery + '/jquery.js');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $$.html();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
generate: generateFixture
|
||||
};
|
||||
5
test/e2e/tools/index.js
Normal file
5
test/e2e/tools/index.js
Normal file
@@ -0,0 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
middleware: require('./middleware')
|
||||
};
|
||||
44
test/e2e/tools/middleware.js
Normal file
44
test/e2e/tools/middleware.js
Normal file
@@ -0,0 +1,44 @@
|
||||
'use strict';
|
||||
|
||||
var url = require('url');
|
||||
var util = require('./util');
|
||||
var fixture = require('./fixture');
|
||||
|
||||
module.exports = middlewareFactory;
|
||||
|
||||
function middlewareFactory(base) {
|
||||
base = base || '/e2e';
|
||||
while (base.length && base[base.length-1] === '/') base = base.slice(0, base.length-1);
|
||||
var fixture_regexp = new RegExp('^' + base + '/fixtures/([a-zA-Z0-9_-]+)(/(index.html)?)?$');
|
||||
var static_regexp = new RegExp('^' + base + '/fixtures/([a-zA-Z0-9_-]+)(/.*)$');
|
||||
|
||||
return function(req, res, next) {
|
||||
var match;
|
||||
var basicUrl = req.url;
|
||||
var idx = basicUrl.indexOf('?');
|
||||
if (idx >= 0) {
|
||||
basicUrl = basicUrl.slice(0, idx);
|
||||
}
|
||||
if ((match = fixture_regexp.exec(basicUrl))) {
|
||||
if (util.testExists(match[1])) {
|
||||
try {
|
||||
var query = url.parse(req.url, true).query;
|
||||
res.write(fixture.generate(match[1], query));
|
||||
res.end();
|
||||
} catch (e) {
|
||||
return next(e);
|
||||
}
|
||||
} else {
|
||||
return next('Fixture ' + match[1] + ' not found.');
|
||||
}
|
||||
} else if ((match = static_regexp.exec(basicUrl))) {
|
||||
var rewritten = util.rewriteTestFile(match[1], match[2]);
|
||||
if (rewritten !== false) {
|
||||
req.url = rewritten;
|
||||
}
|
||||
next();
|
||||
} else {
|
||||
return next();
|
||||
}
|
||||
};
|
||||
}
|
||||
41
test/e2e/tools/util.js
Normal file
41
test/e2e/tools/util.js
Normal file
@@ -0,0 +1,41 @@
|
||||
'use strict';
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var url = require('url');
|
||||
|
||||
var root = path.resolve(__dirname, '..');
|
||||
var tests = path.resolve(root, 'fixtures');
|
||||
|
||||
function stat(path) {
|
||||
try {
|
||||
return fs.statSync(path);
|
||||
} catch (e) {
|
||||
// Ignore ENOENT.
|
||||
if (e.code !== 'ENOENT') {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function testExists(testname) {
|
||||
var s = stat(path.resolve(tests, testname));
|
||||
return s && s.isDirectory();
|
||||
}
|
||||
|
||||
function rewriteTestFile(testname, testfile) {
|
||||
var i = 0;
|
||||
while (testfile[i] === '/') ++i;
|
||||
testfile = testfile.slice(i);
|
||||
var s = stat(path.resolve(tests, testname, testfile));
|
||||
if (s && (s.isFile() || s.isDirectory())) {
|
||||
return ['/test/e2e/fixtures', testname, testfile].join('/');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
stat: stat,
|
||||
testExists: testExists,
|
||||
rewriteTestFile: rewriteTestFile
|
||||
};
|
||||
Reference in New Issue
Block a user