parent
34122f4d92
commit
872064e12e
1
.gitignore
vendored
1
.gitignore
vendored
@ -23,3 +23,4 @@ npm-debug.log.*
|
|||||||
plnkr.html
|
plnkr.html
|
||||||
*plnkr.no-link.html
|
*plnkr.no-link.html
|
||||||
public/docs/*/latest/guide/cheatsheet.json
|
public/docs/*/latest/guide/cheatsheet.json
|
||||||
|
protractor-results.txt
|
||||||
|
183
gulpfile.js
183
gulpfile.js
@ -15,8 +15,13 @@ var fsExtra = require('fs-extra');
|
|||||||
var fs = fsExtra;
|
var fs = fsExtra;
|
||||||
var exec = require('child_process').exec;
|
var exec = require('child_process').exec;
|
||||||
var execPromise = Q.denodeify(exec);
|
var execPromise = Q.denodeify(exec);
|
||||||
|
// cross platform version of spawn that also works on windows.
|
||||||
|
var xSpawn = require('cross-spawn');
|
||||||
var prompt = require('prompt');
|
var prompt = require('prompt');
|
||||||
var globby = require("globby");
|
var globby = require("globby");
|
||||||
|
// Ugh... replacement needed to kill processes on any OS
|
||||||
|
// - because childProcess.kill does not work properly on windows
|
||||||
|
var treeKill = require("tree-kill");
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// 1. Think about using runSequence
|
// 1. Think about using runSequence
|
||||||
@ -56,6 +61,120 @@ var _excludeMatchers = _excludePatterns.map(function(excludePattern){
|
|||||||
|
|
||||||
var _exampleBoilerplateFiles = ['package.json', 'tsconfig.json', 'karma.conf.js', 'karma-test-shim.js' ]
|
var _exampleBoilerplateFiles = ['package.json', 'tsconfig.json', 'karma.conf.js', 'karma-test-shim.js' ]
|
||||||
|
|
||||||
|
// --filter may be passed in to filter/select _example app subdir names
|
||||||
|
// i.e. gulp run-e2e-tests --filter=foo ; would select all example apps with
|
||||||
|
// 'foo' in their folder names.
|
||||||
|
gulp.task('run-e2e-tests', function() {
|
||||||
|
var spawnInfo = spawnExt('npm', ['install'], { cwd: EXAMPLES_PATH});
|
||||||
|
return spawnInfo.promise.then(function() {
|
||||||
|
copyExampleBoilerplate();
|
||||||
|
var exePath = path.join(process.cwd(), "./node_modules/.bin/");
|
||||||
|
spawnInfo = spawnExt('webdriver-manager', ['update'], {cwd: exePath});
|
||||||
|
return spawnInfo.promise;
|
||||||
|
}).then(function(x) {
|
||||||
|
return findAndRunE2eTests(argv.filter);
|
||||||
|
}).fail(function(e) {
|
||||||
|
return e;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// finds all of the *e2e-spec.tests under the _examples folder along
|
||||||
|
// with the corresponding apps that they should run under. Then run
|
||||||
|
// each app/spec collection sequentially.
|
||||||
|
function findAndRunE2eTests(filter) {
|
||||||
|
// create an output file with header.
|
||||||
|
var outputFile = path.join(process.cwd(), 'protractor-results.txt');
|
||||||
|
var header = "Protractor example results for: " + (new Date()).toLocaleString() + "\n\n";
|
||||||
|
if (filter) {
|
||||||
|
header += ' Filter: ' + filter.toString() + '\n\n';
|
||||||
|
}
|
||||||
|
fs.writeFileSync(outputFile, header);
|
||||||
|
|
||||||
|
// create an array of combos where each
|
||||||
|
// combo consists of { examplePath: ... , protractorConfigFilename: ... }
|
||||||
|
var exeConfigs = [];
|
||||||
|
var e2eSpecPaths = getE2eSpecPaths(EXAMPLES_PATH);
|
||||||
|
var srcConfig = path.join(EXAMPLES_PATH, 'protractor.config.js');
|
||||||
|
e2eSpecPaths.forEach(function(specPath) {
|
||||||
|
var destConfig = path.join(specPath, 'protractor.config.js');
|
||||||
|
fsExtra.copySync(srcConfig, destConfig);
|
||||||
|
// get all of the examples under each dir where a pcFilename is found
|
||||||
|
examplePaths = getExamplePaths(specPath, true);
|
||||||
|
if (filter) {
|
||||||
|
examplePaths = examplePaths.filter(function (fn) {
|
||||||
|
return fn.match(filter) != null;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
examplePaths.forEach(function(exPath) {
|
||||||
|
exeConfigs.push( { examplePath: exPath, protractorConfigFilename: destConfig });
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
// run the tests sequentially
|
||||||
|
return exeConfigs.reduce(function (promise, combo) {
|
||||||
|
return promise.then(function () {
|
||||||
|
return runE2eTests(combo.examplePath, combo.protractorConfigFilename, outputFile);
|
||||||
|
});
|
||||||
|
}, Q.resolve());
|
||||||
|
}
|
||||||
|
|
||||||
|
// start the example in appDir; then run protractor with the specified
|
||||||
|
// fileName; then shut down the example. All protractor output is appended
|
||||||
|
// to the outputFile.
|
||||||
|
function runE2eTests(appDir, protractorConfigFilename, outputFile ) {
|
||||||
|
// start the app
|
||||||
|
var appRunSpawnInfo = spawnExt('npm',['run','http-server', '--', '-s' ], { cwd: appDir });
|
||||||
|
|
||||||
|
// start protractor
|
||||||
|
var pcFilename = path.resolve(protractorConfigFilename); // need to resolve because we are going to be running from a different dir
|
||||||
|
var exePath = path.join(process.cwd(), "./node_modules/.bin/");
|
||||||
|
var spawnInfo = spawnExt('protractor',
|
||||||
|
[ pcFilename, '--params.appDir=' + appDir, '--params.outputFile=' + outputFile], { cwd: exePath });
|
||||||
|
return spawnInfo.promise.then(function(data) {
|
||||||
|
// kill the app now that protractor has completed.
|
||||||
|
treeKill(appRunSpawnInfo.proc.pid);
|
||||||
|
// Ugh... proc.kill does not work properly on windows with child processes.
|
||||||
|
// appRun.proc.kill();
|
||||||
|
return data;
|
||||||
|
}).fail(function(err) {
|
||||||
|
// Ugh... proc.kill does not work properly on windows with child processes.
|
||||||
|
// appRun.proc.kill();
|
||||||
|
treeKill(appRunSpawnInfo.proc.pid)
|
||||||
|
return err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns both a promise and the spawned process so that it can be killed if needed.
|
||||||
|
function spawnExt(command, args, options) {
|
||||||
|
var deferred = Q.defer();
|
||||||
|
var descr = command + " " + args.join(' ');
|
||||||
|
var proc;
|
||||||
|
gutil.log('running: ' + descr);
|
||||||
|
try {
|
||||||
|
proc = xSpawn.spawn(command, args, options);
|
||||||
|
} catch(e) {
|
||||||
|
gutil.log(e);
|
||||||
|
deferred.reject(e);
|
||||||
|
return { proc: null, promise: deferred.promise };
|
||||||
|
}
|
||||||
|
proc.stdout.on('data', function (data) {
|
||||||
|
gutil.log(data.toString());
|
||||||
|
});
|
||||||
|
proc.stderr.on('data', function (data) {
|
||||||
|
gutil.log(data.toString());
|
||||||
|
});
|
||||||
|
proc.on('close', function (data) {
|
||||||
|
gutil.log('completed: ' + descr);
|
||||||
|
deferred.resolve(data);
|
||||||
|
});
|
||||||
|
proc.on('error', function (data) {
|
||||||
|
gutil.log('completed with error:' + descr);
|
||||||
|
gutil.log(data.toString());
|
||||||
|
deferred.reject(data);
|
||||||
|
});
|
||||||
|
return { proc: proc, promise: deferred.promise };
|
||||||
|
}
|
||||||
|
|
||||||
// Public tasks
|
// Public tasks
|
||||||
|
|
||||||
gulp.task('default', ['help']);
|
gulp.task('default', ['help']);
|
||||||
@ -77,12 +196,25 @@ gulp.task('add-example-boilerplate', function() {
|
|||||||
gutil.log("symlinking " + linkPath + ' -> ' + realPath)
|
gutil.log("symlinking " + linkPath + ' -> ' + realPath)
|
||||||
fsUtils.addSymlink(realPath, linkPath);
|
fsUtils.addSymlink(realPath, linkPath);
|
||||||
});
|
});
|
||||||
|
copyExampleBoilerplate();
|
||||||
|
});
|
||||||
|
|
||||||
|
// copies boilerplate files to locations
|
||||||
|
// where an example app is found
|
||||||
|
// also copies protractor.config.js file
|
||||||
|
function copyExampleBoilerplate() {
|
||||||
var sourceFiles = _exampleBoilerplateFiles.map(function(fn) {
|
var sourceFiles = _exampleBoilerplateFiles.map(function(fn) {
|
||||||
return path.join(EXAMPLES_PATH, fn);
|
return path.join(EXAMPLES_PATH, fn);
|
||||||
});
|
});
|
||||||
var examplePaths = getExamplePaths(EXAMPLES_PATH);
|
var examplePaths = getExamplePaths(EXAMPLES_PATH);
|
||||||
return copyFiles(sourceFiles, examplePaths );
|
// copies protractor.config.js from _examples dir to each subdir that
|
||||||
});
|
// contains a e2e-spec file.
|
||||||
|
return copyFiles(sourceFiles, examplePaths).then(function() {
|
||||||
|
var sourceFiles = [ path.join(EXAMPLES_PATH, 'protractor.config.js') ];
|
||||||
|
var e2eSpecPaths = getE2eSpecPaths(EXAMPLES_PATH);
|
||||||
|
return copyFiles(sourceFiles, e2eSpecPaths);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
gulp.task('remove-example-boilerplate', function() {
|
gulp.task('remove-example-boilerplate', function() {
|
||||||
var nodeModulesPaths = getNodeModulesPaths(EXAMPLES_PATH);
|
var nodeModulesPaths = getNodeModulesPaths(EXAMPLES_PATH);
|
||||||
@ -90,7 +222,10 @@ gulp.task('remove-example-boilerplate', function() {
|
|||||||
fsUtils.removeSymlink(linkPath);
|
fsUtils.removeSymlink(linkPath);
|
||||||
});
|
});
|
||||||
var examplePaths = getExamplePaths(EXAMPLES_PATH);
|
var examplePaths = getExamplePaths(EXAMPLES_PATH);
|
||||||
return deleteFiles(_exampleBoilerplateFiles, examplePaths );
|
return deleteFiles(_exampleBoilerplateFiles, examplePaths).then(function() {
|
||||||
|
var e2eSpecPaths = getE2eSpecPaths(EXAMPLES_PATH);
|
||||||
|
return deleteFiles(['protractor.config.js'], e2eSpecPaths);
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('serve-and-sync', ['build-docs'], function (cb) {
|
gulp.task('serve-and-sync', ['build-docs'], function (cb) {
|
||||||
@ -264,18 +399,11 @@ function deleteFiles(baseFileNames, destPaths) {
|
|||||||
return Q.all(delPromises);
|
return Q.all(delPromises);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getExamplePaths(basePath) {
|
// TODO: filter out all paths that are subdirs of another
|
||||||
var jsonPattern = path.join(basePath, "**/example-config.json");
|
// path in the result.
|
||||||
// ignore (skip) the top level version.
|
function getE2eSpecPaths(basePath) {
|
||||||
var exceptJsonPattern = "!" + path.join(basePath, "/example-config.json");
|
var paths = getPaths(basePath, '*e2e-spec.js', true);
|
||||||
var nmPattern = path.join(basePath, "**/node_modules/**");
|
return _.uniq(paths);
|
||||||
var fileNames = globby.sync( [ jsonPattern, exceptJsonPattern ], { ignore: [nmPattern] } );
|
|
||||||
// same as above but perf can differ.
|
|
||||||
// var fileNames = globby.sync( [jsonPattern, "!" + nmPattern]);
|
|
||||||
var paths = fileNames.map(function(fileName) {
|
|
||||||
return path.dirname(fileName);
|
|
||||||
});
|
|
||||||
return paths;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNodeModulesPaths(basePath) {
|
function getNodeModulesPaths(basePath) {
|
||||||
@ -285,6 +413,31 @@ function getNodeModulesPaths(basePath) {
|
|||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getExamplePaths(basePath, includeBase) {
|
||||||
|
// includeBase defaults to false
|
||||||
|
return getPaths(basePath, "example-config.json", includeBase)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPaths(basePath, filename, includeBase) {
|
||||||
|
var filenames = getFilenames(basePath, filename, includeBase);
|
||||||
|
var paths = filenames.map(function(fileName) {
|
||||||
|
return path.dirname(fileName);
|
||||||
|
});
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFilenames(basePath, filename, includeBase) {
|
||||||
|
// includeBase defaults to false
|
||||||
|
var includePatterns = [path.join(basePath, "**/" + filename)];
|
||||||
|
if (!includeBase) {
|
||||||
|
// ignore (skip) the top level version.
|
||||||
|
includePatterns.push("!" + path.join(basePath, "/" + filename));
|
||||||
|
}
|
||||||
|
var nmPattern = path.join(basePath, "**/node_modules/**");
|
||||||
|
var filenames = globby.sync(includePatterns, {ignore: [nmPattern]});
|
||||||
|
return filenames;
|
||||||
|
}
|
||||||
|
|
||||||
function watchAndSync(options, cb) {
|
function watchAndSync(options, cb) {
|
||||||
|
|
||||||
execCommands(['npm run harp -- server .'], {}, cb);
|
execCommands(['npm run harp -- server .'], {}, cb);
|
||||||
|
@ -8,7 +8,9 @@
|
|||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"harp": "harp",
|
"harp": "harp",
|
||||||
"live-server": "live-server",
|
"live-server": "live-server",
|
||||||
"test-api-builder": "jasmine-node tools/api-builder"
|
"test-api-builder": "jasmine-node tools/api-builder",
|
||||||
|
|
||||||
|
"protractor": "protractor"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -28,6 +30,7 @@
|
|||||||
"assert-plus": "^0.1.5",
|
"assert-plus": "^0.1.5",
|
||||||
"browser-sync": "^2.9.3",
|
"browser-sync": "^2.9.3",
|
||||||
"canonical-path": "0.0.2",
|
"canonical-path": "0.0.2",
|
||||||
|
"cross-spawn": "^2.1.0",
|
||||||
"del": "^1.2.0",
|
"del": "^1.2.0",
|
||||||
"dgeni": "^0.4.0",
|
"dgeni": "^0.4.0",
|
||||||
"dgeni-packages": "^0.11.1",
|
"dgeni-packages": "^0.11.1",
|
||||||
@ -58,7 +61,9 @@
|
|||||||
"nodegit": "0.5.0",
|
"nodegit": "0.5.0",
|
||||||
"path": "^0.11.14",
|
"path": "^0.11.14",
|
||||||
"prompt": "^0.2.14",
|
"prompt": "^0.2.14",
|
||||||
|
"protractor": "^3.0.0",
|
||||||
"q": "^1.4.1",
|
"q": "^1.4.1",
|
||||||
|
"tree-kill": "^1.0.0",
|
||||||
"typescript": "1.7.3",
|
"typescript": "1.7.3",
|
||||||
"yargs": "^3.23.0"
|
"yargs": "^3.23.0"
|
||||||
},
|
},
|
||||||
|
3
public/docs/_examples/.gitignore
vendored
3
public/docs/_examples/.gitignore
vendored
@ -4,4 +4,5 @@ package.json
|
|||||||
karma.conf.js
|
karma.conf.js
|
||||||
karma-test-shim.js
|
karma-test-shim.js
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
npm-debug*.log
|
npm-debug*.
|
||||||
|
**/protractor.config.js
|
||||||
|
60
public/docs/_examples/architecture/e2e-spec.js
Normal file
60
public/docs/_examples/architecture/e2e-spec.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
describe('Architecture', function () {
|
||||||
|
|
||||||
|
var _title = "Hero List";
|
||||||
|
|
||||||
|
beforeAll(function () {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
function itReset(name, func) {
|
||||||
|
it(name, function() {
|
||||||
|
browser.get('').then(func);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should display correct title: ' + _title, function () {
|
||||||
|
expect(element(by.css('h2')).getText()).toEqual(_title);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display correct detail after selection', function() {
|
||||||
|
var detailView = element(by.css('hero-detail'));
|
||||||
|
expect(detailView.isPresent()).toBe(false);
|
||||||
|
// select the 2nd element
|
||||||
|
var selectEle = element.all(by.css('hero-list > div')).get(1);
|
||||||
|
selectEle.click().then(function() {
|
||||||
|
return selectEle.getText();
|
||||||
|
}).then(function(selectedHeroName) {
|
||||||
|
// works but too specific if we change the app
|
||||||
|
// expect(selectedHeroName).toEqual('Mr. Nice');
|
||||||
|
expect(detailView.isDisplayed()).toBe(true);
|
||||||
|
var detailTitleEle = element(by.css('hero-detail > h4'));
|
||||||
|
expect(detailTitleEle.getText()).toContain(selectedHeroName);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
itReset('should display correct detail after modification', function() {
|
||||||
|
var detailView = element(by.css('hero-detail'));
|
||||||
|
expect(detailView.isPresent()).toBe(false);
|
||||||
|
// select the 2nd element
|
||||||
|
var selectEle = element.all(by.css('hero-list > div')).get(1);
|
||||||
|
selectEle.click().then(function () {
|
||||||
|
return selectEle.getText();
|
||||||
|
}).then(function (selectedHeroName) {
|
||||||
|
var detailTitleEle = element(by.css('hero-detail > h4'));
|
||||||
|
expect(detailTitleEle.getText()).toContain(selectedHeroName);
|
||||||
|
var heroNameEle = element.all(by.css('hero-detail input')).get(0);
|
||||||
|
|
||||||
|
// check that both the initial selected item and the detail title reflect changes
|
||||||
|
// made to the input box.
|
||||||
|
heroNameEle.sendKeys('foo');
|
||||||
|
expect(detailTitleEle.getText()).toContain('foo');
|
||||||
|
expect(selectEle.getText()).toContain('foo');
|
||||||
|
|
||||||
|
// getText on an input element always returns null
|
||||||
|
// http://stackoverflow.com/questions/20310442/how-to-gettext-on-an-input-in-protractor
|
||||||
|
// expect(heroNameEle.getText()).toEqual(selectedHeroName);
|
||||||
|
expect(heroNameEle.getAttribute('value')).toEqual(selectedHeroName + 'foo');
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
});
|
26
public/docs/_examples/attribute-directives/e2e-spec.js
Normal file
26
public/docs/_examples/attribute-directives/e2e-spec.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
describe('Attribute directives', function () {
|
||||||
|
|
||||||
|
var _title = "My First Attribute Directive";
|
||||||
|
|
||||||
|
beforeAll(function () {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display correct title: ' + _title, function () {
|
||||||
|
expect(element(by.css('h1')).getText()).toEqual(_title);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to select green highlight', function () {
|
||||||
|
var highlightedEle = element(by.cssContainingText('p', 'Highlight me'));
|
||||||
|
var lightGreen = "rgba(144, 238, 144, 1)";
|
||||||
|
|
||||||
|
expect(highlightedEle.getCssValue('background-color')).not.toEqual(lightGreen);
|
||||||
|
// var greenRb = element(by.cssContainingText('input', 'Green'));
|
||||||
|
var greenRb = element.all(by.css('input')).get(0);
|
||||||
|
greenRb.click().then(function() {
|
||||||
|
browser.actions().mouseMove(highlightedEle).perform();
|
||||||
|
expect(highlightedEle.getCssValue('background-color')).toEqual(lightGreen);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
21
public/docs/_examples/displaying-data/e2e-spec.js
Normal file
21
public/docs/_examples/displaying-data/e2e-spec.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
describe('Displaying Data Tests', function () {
|
||||||
|
|
||||||
|
var _title = "Tour of Heroes";
|
||||||
|
var _defaultHero = 'Windstorm'
|
||||||
|
|
||||||
|
beforeAll(function () {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display correct title: ' + _title, function () {
|
||||||
|
expect(element(by.css('h1')).getText()).toEqual(_title);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have correct default hero: ' + _defaultHero, function () {
|
||||||
|
expect(element(by.css('h2')).getText()).toContain(_defaultHero);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have many heroes', function () {
|
||||||
|
expect(element(by.css('ul ~ p')).getText()).toContain('There are many heroes!');
|
||||||
|
});
|
||||||
|
});
|
61
public/docs/_examples/forms/e2e-spec.js
Normal file
61
public/docs/_examples/forms/e2e-spec.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
describeIf(browser.appIsTs, 'Forms Tests', function () {
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display correct title', function () {
|
||||||
|
expect(element.all(by.css('h1')).get(0).getText()).toEqual('Hero Form');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should not display message before submit', function () {
|
||||||
|
var ele = element(by.css('h2'));
|
||||||
|
expect(ele.isDisplayed()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should hide form after submit', function () {
|
||||||
|
var ele = element.all(by.css('h1')).get(0);
|
||||||
|
expect(ele.isDisplayed()).toBe(true);
|
||||||
|
var b = element.all(by.css('button[type=submit]')).get(0);
|
||||||
|
b.click().then(function() {
|
||||||
|
expect(ele.isDisplayed()).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display message after submit', function () {
|
||||||
|
var b = element.all(by.css('button[type=submit]')).get(0);
|
||||||
|
b.click().then(function() {
|
||||||
|
expect(element(by.css('h2')).getText()).toContain('You submitted the following');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should hide form after submit', function () {
|
||||||
|
var alterEgoEle = element.all(by.css('input[ngcontrol=alterEgo]')).get(0);
|
||||||
|
expect(alterEgoEle.isDisplayed()).toBe(true);
|
||||||
|
var submitButtonEle = element.all(by.css('button[type=submit]')).get(0);
|
||||||
|
submitButtonEle.click().then(function() {
|
||||||
|
expect(alterEgoEle.isDisplayed()).toBe(false);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reflect submitted data after submit', function () {
|
||||||
|
var test = 'testing 1 2 3';
|
||||||
|
var newValue;
|
||||||
|
var alterEgoEle = element.all(by.css('input[ngcontrol=alterEgo]')).get(0);
|
||||||
|
alterEgoEle.getAttribute('value').then(function(value) {
|
||||||
|
alterEgoEle.sendKeys(test);
|
||||||
|
newValue = value + test;
|
||||||
|
expect(alterEgoEle.getAttribute('value')).toEqual(newValue);
|
||||||
|
}).then(function() {
|
||||||
|
var b = element.all(by.css('button[type=submit]')).get(0);
|
||||||
|
return b.click();
|
||||||
|
}).then(function() {
|
||||||
|
var alterEgoTextEle = element(by.cssContainingText('div', 'Alter Ego'));
|
||||||
|
expect(alterEgoTextEle.isPresent()).toBe(true, 'cannot locate "Alter Ego" label');
|
||||||
|
var divEle = element(by.cssContainingText('div', newValue));
|
||||||
|
expect(divEle.isPresent()).toBe(true, 'cannot locate div with this text: ' + newValue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,55 @@
|
|||||||
|
describe('Hierarchical dependency injection', function () {
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should open with a card view', function () {
|
||||||
|
expect(element.all(by.cssContainingText('button','edit')).get(0).isDisplayed()).toBe(true,
|
||||||
|
"edit button should be displayed");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have multiple heros listed', function () {
|
||||||
|
expect(element.all(by.css('heroes-list li')).count()).toBeGreaterThan(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should change to editor view after selection', function () {
|
||||||
|
var editButtonEle = element.all(by.cssContainingText('button','edit')).get(0);
|
||||||
|
editButtonEle.click().then(function() {
|
||||||
|
expect(editButtonEle.isDisplayed()).toBe(false, "edit button should be hidden after selection");
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to save editor change', function () {
|
||||||
|
testEdit(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to cancel editor change', function () {
|
||||||
|
testEdit(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
function testEdit(shouldSave) {
|
||||||
|
var inputEle;
|
||||||
|
// select 2nd ele
|
||||||
|
var heroEle = element.all(by.css('heroes-list li')).get(1);
|
||||||
|
// get the 2nd span which is the name of the hero
|
||||||
|
var heroNameEle = heroEle.all(by.css('hero-card span')).get(1);
|
||||||
|
var editButtonEle = heroEle.element(by.cssContainingText('button','edit'));
|
||||||
|
editButtonEle.click().then(function() {
|
||||||
|
inputEle = heroEle.element(by.css('hero-editor input'));
|
||||||
|
return inputEle.sendKeys("foo");
|
||||||
|
}).then(function() {
|
||||||
|
buttonName = shouldSave ? 'save' : 'cancel';
|
||||||
|
var buttonEle = heroEle.element(by.cssContainingText('button', buttonName));
|
||||||
|
return buttonEle.click();
|
||||||
|
}).then(function() {
|
||||||
|
if (shouldSave) {
|
||||||
|
expect(heroNameEle.getText()).toContain('foo');
|
||||||
|
} else {
|
||||||
|
expect(heroNameEle.getText()).not.toContain('foo');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
});
|
154
public/docs/_examples/lifecycle-hooks/e2e-spec.js
Normal file
154
public/docs/_examples/lifecycle-hooks/e2e-spec.js
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
describe('Lifecycle hooks', function () {
|
||||||
|
|
||||||
|
beforeAll(function () {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should open correctly', function () {
|
||||||
|
expect(element.all(by.css('h2')).get(0).getText()).toEqual('Peek-A-Boo');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to drive peek-a-boo button', function () {
|
||||||
|
var pabComp = element(by.css('peek-a-boo-parent peek-a-boo'));
|
||||||
|
expect(pabComp.isPresent()).toBe(false, "should not be able to find the 'peek-a-boo' component");
|
||||||
|
var pabButton = element.all(by.css('peek-a-boo-parent button')).get(0);
|
||||||
|
var updateHeroButton = element.all(by.css('peek-a-boo-parent button')).get(1);
|
||||||
|
expect(pabButton.getText()).toContain('Create Peek');
|
||||||
|
pabButton.click().then(function () {
|
||||||
|
expect(pabButton.getText()).toContain('Destroy Peek');
|
||||||
|
expect(pabComp.isDisplayed()).toBe(true, "should be able to see the 'peek-a-boo' component");
|
||||||
|
expect(pabComp.getText()).toContain('Windstorm');
|
||||||
|
expect(pabComp.getText()).not.toContain('Windstorm!');
|
||||||
|
expect(updateHeroButton.isPresent()).toBe(true, "should be able to see the update hero button");
|
||||||
|
return updateHeroButton.click();
|
||||||
|
}).then(function () {
|
||||||
|
expect(pabComp.getText()).toContain('Windstorm!');
|
||||||
|
return pabButton.click();
|
||||||
|
}).then(function () {
|
||||||
|
expect(pabComp.isPresent()).toBe(false, "should no longer be able to find the 'peek-a-boo' component");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to trigger onChanges', function () {
|
||||||
|
var onChangesViewEle = element.all(by.css('on-changes-parent my-hero div')).get(0);
|
||||||
|
var inputEles = element.all(by.css('on-changes-parent input'));
|
||||||
|
var heroNameInputEle = inputEles.get(0);
|
||||||
|
var powerInputEle = inputEles.get(1);
|
||||||
|
var titleEle = onChangesViewEle.element(by.css('p'));
|
||||||
|
expect(titleEle.getText()).toContain('Windstorm can sing');
|
||||||
|
var changeLogEles = onChangesViewEle.all(by.css('div'));
|
||||||
|
expect(changeLogEles.count()).toEqual(3, "should start with 3 messages");
|
||||||
|
heroNameInputEle.sendKeys('-foo-').then(function () {
|
||||||
|
expect(titleEle.getText()).toContain('Windstorm-foo- can sing');
|
||||||
|
expect(changeLogEles.count()).toEqual(3, "should still have 3 messages");
|
||||||
|
// protractor bug with sendKeys means that line below does not work.
|
||||||
|
// return powerInputEle.sendKeys('-bar-');
|
||||||
|
return sendKeys(powerInputEle, '-bar-');
|
||||||
|
}).then(function () {
|
||||||
|
expect(titleEle.getText()).toContain('Windstorm-foo- can sing-bar-');
|
||||||
|
// 8 == 3 previously + length of '-bar-'
|
||||||
|
expect(changeLogEles.count()).toEqual(8, "should have 8 messages now");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support after-view hooks', function () {
|
||||||
|
var inputEle = element(by.css('after-view-parent input'));
|
||||||
|
var buttonEle = element(by.css('after-view-parent button'));
|
||||||
|
var logEles = element.all(by.css('after-view-parent h4 ~ div'));
|
||||||
|
var childViewTextEle = element(by.css('after-view-parent my-child .child'));
|
||||||
|
expect(childViewTextEle.getText()).toContain('Magneta is my hero');
|
||||||
|
expect(logEles.count()).toBeGreaterThan(2);
|
||||||
|
var logCount;
|
||||||
|
logEles.count().then(function(count) {
|
||||||
|
logCount = count;
|
||||||
|
return sendKeys(inputEle, "-test-");
|
||||||
|
}).then(function() {
|
||||||
|
expect(childViewTextEle.getText()).toContain('-test-');
|
||||||
|
return logEles.count();
|
||||||
|
}).then(function(count) {
|
||||||
|
expect(logCount + 6).toEqual(count, "6 additional log messages should have been added");
|
||||||
|
logCount = count;
|
||||||
|
return buttonEle.click();
|
||||||
|
}).then(function() {
|
||||||
|
expect(childViewTextEle.isPresent()).toBe(false,"child view should no longer be part of the DOM");
|
||||||
|
sendKeys(inputEle, "-foo-");
|
||||||
|
expect(logEles.count()).toEqual(logCount, "no additional log messages should have been added");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support after-content hooks', function () {
|
||||||
|
var inputEle = element(by.css('after-content-parent input'));
|
||||||
|
var buttonEle = element(by.css('after-content-parent button'));
|
||||||
|
var logEles = element.all(by.css('after-content-parent h4 ~ div'));
|
||||||
|
var childViewTextEle = element(by.css('after-content-parent my-child .child'));
|
||||||
|
expect(childViewTextEle.getText()).toContain('Magneta is my hero');
|
||||||
|
expect(logEles.count()).toBeGreaterThan(2);
|
||||||
|
var logCount;
|
||||||
|
logEles.count().then(function(count) {
|
||||||
|
logCount = count;
|
||||||
|
return sendKeys(inputEle, "-test-");
|
||||||
|
}).then(function() {
|
||||||
|
expect(childViewTextEle.getText()).toContain('-test-');
|
||||||
|
return logEles.count();
|
||||||
|
}).then(function(count) {
|
||||||
|
expect(logCount + 6).toEqual(count, "6 additional log messages should have been added");
|
||||||
|
logCount = count;
|
||||||
|
return buttonEle.click();
|
||||||
|
}).then(function() {
|
||||||
|
expect(childViewTextEle.isPresent()).toBe(false,"child view should no longer be part of the DOM");
|
||||||
|
sendKeys(inputEle, "-foo-");
|
||||||
|
expect(logEles.count()).toEqual(logCount, "no additional log messages should have been added");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support "spy" hooks', function () {
|
||||||
|
var inputEle = element(by.css('spy-parent input'));
|
||||||
|
var addHeroButtonEle = element(by.cssContainingText('spy-parent button','Add Hero'));
|
||||||
|
var resetHeroesButtonEle = element(by.cssContainingText('spy-parent button','Reset Heroes'));
|
||||||
|
var heroEles = element.all(by.css('spy-parent div[my-spy'));
|
||||||
|
var logEles = element.all(by.css('spy-parent h4 ~ div'));
|
||||||
|
expect(heroEles.count()).toBe(2, 'should have two heroes displayed');
|
||||||
|
expect(logEles.count()).toBe(2, 'should have two log entries');
|
||||||
|
sendKeys(inputEle, "-test-").then(function() {
|
||||||
|
return addHeroButtonEle.click();
|
||||||
|
}).then(function() {
|
||||||
|
expect(heroEles.count()).toBe(3, 'should have added one hero');
|
||||||
|
expect(heroEles.get(2).getText()).toContain('-test-');
|
||||||
|
expect(logEles.count()).toBe(3, 'should now have 3 log entries');
|
||||||
|
return resetHeroesButtonEle.click();
|
||||||
|
}).then(function() {
|
||||||
|
expect(heroEles.count()).toBe(0, 'should no longer have any heroes');
|
||||||
|
expect(logEles.count()).toBe(7, 'should now have 7 log entries - 3 orig + 1 reset + 3 removeall');
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support "spy counter" hooks', function () {
|
||||||
|
var updateCounterButtonEle = element(by.cssContainingText('counter-parent button','Update'));
|
||||||
|
var resetCounterButtonEle = element(by.cssContainingText('counter-parent button','Reset'));
|
||||||
|
var textEle = element(by.css('counter-parent my-counter > div'));
|
||||||
|
var logEles = element.all(by.css('counter-parent h4 ~ div'));
|
||||||
|
expect(textEle.getText()).toContain('Counter = 0');
|
||||||
|
expect(logEles.count()).toBe(2, 'should start with two log entries');
|
||||||
|
updateCounterButtonEle.click().then(function() {
|
||||||
|
expect(textEle.getText()).toContain('Counter = 1');
|
||||||
|
expect(logEles.count()).toBe(3, 'should now have 3 log entries');
|
||||||
|
return resetCounterButtonEle.click();
|
||||||
|
}).then(function() {
|
||||||
|
expect(textEle.getText()).toContain('Counter = 0');
|
||||||
|
expect(logEles.count()).toBe(7, 'should now have 7 log entries - 3 prev + 1 reset + 2 destroy + 1 init');
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Hack - because of bug with send keys
|
||||||
|
function sendKeys(element, str) {
|
||||||
|
return str.split('').reduce(function (promise, char) {
|
||||||
|
return promise.then(function () {
|
||||||
|
return element.sendKeys(char);
|
||||||
|
});
|
||||||
|
}, element.getAttribute('value'));
|
||||||
|
// better to create a resolved promise here but ... don't know how with protractor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
});
|
@ -10,7 +10,8 @@
|
|||||||
"live": "live-server",
|
"live": "live-server",
|
||||||
"start": "concurrent \"npm run tsc:w\" \"npm run lite\" ",
|
"start": "concurrent \"npm run tsc:w\" \"npm run lite\" ",
|
||||||
"test": "karma start karma.conf.js",
|
"test": "karma start karma.conf.js",
|
||||||
"build-and-test": "npm run tsc && npm run test"
|
"build-and-test": "npm run tsc && npm run test",
|
||||||
|
"http-server": "tsc && http-server"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
@ -27,15 +28,16 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"concurrently": "^1.0.0",
|
"concurrently": "^1.0.0",
|
||||||
"lite-server": "^1.3.1",
|
"http-server": "^0.8.5",
|
||||||
"live-server": "^0.8.2",
|
"jasmine-core": "~2.1.0",
|
||||||
"typescript": "^1.7.3",
|
|
||||||
"jasmine-core":"~2.1.0",
|
|
||||||
"karma": "^0.12.23",
|
"karma": "^0.12.23",
|
||||||
"karma-chrome-launcher": "^0.1.4",
|
"karma-chrome-launcher": "^0.1.4",
|
||||||
"karma-cli": "^0.0.4",
|
"karma-cli": "^0.0.4",
|
||||||
"karma-jasmine": "^0.3.6",
|
"karma-jasmine": "^0.3.6",
|
||||||
"rimraf": "^2.4.3"
|
"lite-server": "^1.3.1",
|
||||||
}
|
"live-server": "^0.8.2",
|
||||||
|
"rimraf": "^2.4.3",
|
||||||
|
"typescript": "^1.7.3"
|
||||||
|
},
|
||||||
|
"repository": { }
|
||||||
}
|
}
|
||||||
|
78
public/docs/_examples/pipes/e2e-spec.js
Normal file
78
public/docs/_examples/pipes/e2e-spec.js
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
describe('Pipes', function () {
|
||||||
|
|
||||||
|
beforeAll(function () {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should open correctly', function () {
|
||||||
|
expect(element.all(by.css('h4')).get(0).getText()).toEqual('Hero Birthday v.1');
|
||||||
|
expect(element(by.css('body > hero-birthday p')).getText()).toEqual("The hero's birthday is Apr 15, 1988");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show delayed message', function () {
|
||||||
|
expect(element.all(by.css('hero-message')).get(0).getText()).toEqual('Message: You are my Hero!');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show 4 heroes', function () {
|
||||||
|
expect(element.all(by.css('hero-list div')).count()).toEqual(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show 4 heroes in json', function () {
|
||||||
|
expect(element(by.cssContainingText('hero-list p', 'Heroes as JSON')).getText()).toContain('Bombasto');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show alternate birthday formats', function () {
|
||||||
|
expect(element(by.cssContainingText('my-app > p', "The hero's birthday is Apr 15, 1988")).isDisplayed()).toBe(true);
|
||||||
|
expect(element(by.cssContainingText('my-app > p', "The hero's birthday is 04/15/88")).isDisplayed()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to toggle birthday formats', function () {
|
||||||
|
var birthDayEle = element(by.css('my-app > hero-birthday > p'));
|
||||||
|
expect(birthDayEle.getText()).toEqual("The hero's birthday is 4/15/1988");
|
||||||
|
var buttonEle = element(by.cssContainingText('my-app > hero-birthday > button', "Toggle Format"));
|
||||||
|
expect(buttonEle.isDisplayed()).toBe(true);
|
||||||
|
buttonEle.click().then(function() {
|
||||||
|
expect(birthDayEle.getText()).toEqual("The hero's birthday is Friday, April 15, 1988");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to chain and compose pipes', function () {
|
||||||
|
var chainedPipeEles = element.all(by.cssContainingText('my-app p', "The chained hero's"));
|
||||||
|
expect(chainedPipeEles.count()).toBe(3, "should have 3 chained pipe examples");
|
||||||
|
expect(chainedPipeEles.get(0).getText()).toContain('APR 15, 1988');
|
||||||
|
expect(chainedPipeEles.get(1).getText()).toContain('FRIDAY, APRIL 15, 1988');
|
||||||
|
expect(chainedPipeEles.get(2).getText()).toContain('FRIDAY, APRIL 15, 1988');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to use ExponentialStrengthPipe pipe', function () {
|
||||||
|
var ele = element(by.css('power-booster p'));
|
||||||
|
expect(ele.getText()).toContain('Super power boost: 1024');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to use the exponential calculator', function () {
|
||||||
|
var eles = element.all(by.css('power-boost-calculator input'));
|
||||||
|
var baseInputEle = eles.get(0);
|
||||||
|
var factorInputEle = eles.get(1);
|
||||||
|
var outputEle = element(by.css('power-boost-calculator p'));
|
||||||
|
baseInputEle.clear().then(function() {
|
||||||
|
return sendKeys(baseInputEle, "7");
|
||||||
|
}).then(function() {
|
||||||
|
return factorInputEle.clear();
|
||||||
|
}).then(function() {
|
||||||
|
return sendKeys(factorInputEle, "3");
|
||||||
|
}).then(function() {
|
||||||
|
expect(outputEle.getText()).toContain("343");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Hack - because of bug with send keys
|
||||||
|
function sendKeys(element, str) {
|
||||||
|
return str.split('').reduce(function (promise, char) {
|
||||||
|
return promise.then(function () {
|
||||||
|
return element.sendKeys(char);
|
||||||
|
});
|
||||||
|
}, element.getAttribute('value'));
|
||||||
|
// better to create a resolved promise here but ... don't know how with protractor;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
161
public/docs/_examples/protractor.config.js
Normal file
161
public/docs/_examples/protractor.config.js
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
// TO RUN THE TESTS
|
||||||
|
//
|
||||||
|
// The first time, run:
|
||||||
|
// ./node_modules/.bin/webdriver-manager update
|
||||||
|
// Make sure the test server is running. Then do.
|
||||||
|
// ./node_modules/.bin/protractor protractor.config.js
|
||||||
|
|
||||||
|
var fs = require('fs');
|
||||||
|
var path = require('canonical-path');
|
||||||
|
|
||||||
|
|
||||||
|
exports.config = {
|
||||||
|
directConnect: true,
|
||||||
|
|
||||||
|
// Capabilities to be passed to the webdriver instance.
|
||||||
|
capabilities: {
|
||||||
|
'browserName': 'chrome'
|
||||||
|
},
|
||||||
|
|
||||||
|
// Framework to use. Jasmine is recommended.
|
||||||
|
framework: 'jasmine',
|
||||||
|
|
||||||
|
// Spec patterns are relative to this config file
|
||||||
|
specs: ['**/*e2e-spec.js' ],
|
||||||
|
|
||||||
|
|
||||||
|
// For angular2 tests
|
||||||
|
useAllAngular2AppRoots: true,
|
||||||
|
|
||||||
|
baseUrl: 'http://localhost:8080',
|
||||||
|
|
||||||
|
// doesn't seem to work.
|
||||||
|
// resultJsonOutputFile: "foo.json",
|
||||||
|
|
||||||
|
onPrepare: function() {
|
||||||
|
// SpecReporter
|
||||||
|
//var SpecReporter = require('jasmine-spec-reporter');
|
||||||
|
//// add jasmine spec reporter
|
||||||
|
//jasmine.getEnv().addReporter(new SpecReporter({displayStacktrace: 'none'}));
|
||||||
|
// jasmine.getEnv().addReporter(new SpecReporter({displayStacktrace: 'all'}));
|
||||||
|
|
||||||
|
// debugging
|
||||||
|
console.log('browser.params:' + JSON.stringify(browser.params));
|
||||||
|
var appDir = browser.params.appDir;
|
||||||
|
if (appDir) {
|
||||||
|
if (appDir.match('/ts') != null) {
|
||||||
|
browser.appIsTs = true;
|
||||||
|
} else if (appDir.match('/js') != null) {
|
||||||
|
browser.appIsJs = true;
|
||||||
|
} else if (appDir.match('/dart') != null) {
|
||||||
|
browser.appIsDart = true;
|
||||||
|
} else {
|
||||||
|
browser.appIsUnknown = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
browser.appIsUnknown = true;
|
||||||
|
}
|
||||||
|
jasmine.getEnv().addReporter(new Reporter( browser.params )) ;
|
||||||
|
global.describeIf = describeIf;
|
||||||
|
global.itIf = itIf;
|
||||||
|
},
|
||||||
|
|
||||||
|
jasmineNodeOpts: {
|
||||||
|
// defaultTimeoutInterval: 60000,
|
||||||
|
defaultTimeoutInterval: 10000,
|
||||||
|
showTiming: true,
|
||||||
|
print: function() {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function describeIf(cond, name, func) {
|
||||||
|
if (cond) {
|
||||||
|
describe(name, func);
|
||||||
|
} else {
|
||||||
|
xdescribe('*** Skipped *** - ' + name, func);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function itIf(cond, name, func) {
|
||||||
|
if (cond) {
|
||||||
|
it(name, func);
|
||||||
|
} else {
|
||||||
|
xit('*** Skipped *** - ' + name, func);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function Reporter(options) {
|
||||||
|
this.defaultOutputFile = path.resolve(process.cwd(), "../../", 'protractor-results.txt');
|
||||||
|
var _output = [];
|
||||||
|
var _logDepth = 0;
|
||||||
|
var __pad = ' ';
|
||||||
|
var _currentSuite;
|
||||||
|
options.outputFile = options.outputFile || this.defaultOutputFile;
|
||||||
|
log('AppDir: ' + options.appDir);
|
||||||
|
|
||||||
|
this.suiteStarted = function(suite) {
|
||||||
|
_logDepth++;
|
||||||
|
log('Suite: ' + suite.description);
|
||||||
|
// debugging info
|
||||||
|
// log('Suite stringify:' + JSON.stringify(suite));
|
||||||
|
// log('argv stringify:' + JSON.stringify(process.argv));
|
||||||
|
_currentSuite = suite;
|
||||||
|
_currentSuite.ok = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.suiteDone = function(suite) {
|
||||||
|
var status = _currentSuite.ok ? 'Suite passed: ' : 'Suite failed: ';
|
||||||
|
log(status + suite.description);
|
||||||
|
_logDepth--;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.specStarted = function(spec) {
|
||||||
|
_logDepth++;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.specDone = function(spec) {
|
||||||
|
log(spec.status + ": " + spec.description);
|
||||||
|
logFailedSpec(spec);
|
||||||
|
_logDepth--;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.jasmineDone = function() {
|
||||||
|
outputFile = options.outputFile;
|
||||||
|
// console.log('Completed - appending output to: ' + outputFile);
|
||||||
|
fs.appendFileSync(outputFile, _output.join('\n')+ '\n\n');
|
||||||
|
};
|
||||||
|
|
||||||
|
function logFailedSpec(spec) {
|
||||||
|
if (spec.failedExpectations.length == 0) return;
|
||||||
|
_logDepth++;
|
||||||
|
spec.failedExpectations.forEach(function(exp) {
|
||||||
|
log('detail: ' + exp.message);
|
||||||
|
_currentSuite.ok = false;
|
||||||
|
});
|
||||||
|
_logDepth--;
|
||||||
|
}
|
||||||
|
|
||||||
|
function log(msg) {
|
||||||
|
msg = lpad(msg, 3 * _logDepth);
|
||||||
|
console.log(msg);
|
||||||
|
_output.push(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
function lpad(value, length) {
|
||||||
|
return __pad.substr(0,length) + value;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// To be copied into e2e-tests experiencing sendKeys bug.
|
||||||
|
//// Hack - because of bug with send keys
|
||||||
|
//function sendKeys(element, str) {
|
||||||
|
// return str.split('').reduce(function (promise, char) {
|
||||||
|
// return promise.then(function () {
|
||||||
|
// return element.sendKeys(char);
|
||||||
|
// });
|
||||||
|
// }, element.getAttribute('value'));
|
||||||
|
// // better to create a resolved promise here but ... don't know how with protractor;
|
||||||
|
//}
|
@ -1,27 +1,15 @@
|
|||||||
/*global browser, element, by */
|
|
||||||
describe('QuickStart E2E Tests', function () {
|
describe('QuickStart E2E Tests', function () {
|
||||||
|
|
||||||
// #docregion shared
|
|
||||||
var expectedMsg = 'My First Angular 2 App';
|
var expectedMsg = 'My First Angular 2 App';
|
||||||
|
|
||||||
// tests shared across languages
|
|
||||||
function sharedTests(basePath) {
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
browser.get(basePath + 'index.html');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display: ' + expectedMsg, function () {
|
it('should display: ' + expectedMsg, function () {
|
||||||
expect(element(by.css('h1')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('h1')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
// #enddocregion
|
|
||||||
|
|
||||||
describe('QuickStart in JavaScript', function () {
|
|
||||||
sharedTests('quickstart/js/');
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('QuickStart in TypeScript', function () {
|
|
||||||
sharedTests('quickstart/ts/');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
64
public/docs/_examples/structural-directives/e2e-spec.js
Normal file
64
public/docs/_examples/structural-directives/e2e-spec.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
describe('Structural Directives', function () {
|
||||||
|
|
||||||
|
// tests interact - so we need beforeEach instead of beforeAll
|
||||||
|
beforeEach(function () {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to use ngFor, ngIf and ngWhen together', function () {
|
||||||
|
var allDivEles = element.all(by.css('structural-directives > div'));
|
||||||
|
expect(allDivEles.get(0).getText()).toEqual('Mr. Nice');
|
||||||
|
expect(allDivEles.get(1).getText()).toEqual('Mr. Nice');
|
||||||
|
expect(allDivEles.get(4).getText()).toEqual('Ready');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to toggle ngIf with a button', function () {
|
||||||
|
var setConditionButtonEle = element.all(by.css('button')).get(0);
|
||||||
|
var conditionTrueEles = element.all(by.cssContainingText('p', 'condition is true'));
|
||||||
|
var conditionFalseEles = element.all(by.cssContainingText('p', 'condition is false'));
|
||||||
|
expect(conditionTrueEles.count()).toBe(2, 'should be two condition true elements');
|
||||||
|
expect(conditionFalseEles.count()).toBe(0, 'should be no condition false elements');
|
||||||
|
setConditionButtonEle.click().then(function() {
|
||||||
|
expect(conditionTrueEles.count()).toBe(0, 'should be no condition true elements');
|
||||||
|
expect(conditionFalseEles.count()).toBe(2, 'should be two condition false elements');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to compare use of ngIf with changing css visibility', function () {
|
||||||
|
var setConditionButtonEle = element.all(by.css('button')).get(0);
|
||||||
|
var ngIfButtonEle = element(by.cssContainingText('button', 'if | !if'));
|
||||||
|
var ngIfParentEle = ngIfButtonEle.element(by.xpath('..'));
|
||||||
|
var ngIfSiblingEle = ngIfParentEle.element(by.css('heavy-loader'));
|
||||||
|
var cssButtonEle = element(by.cssContainingText('button', 'show | hide'));
|
||||||
|
var cssSiblingEle = cssButtonEle.element(by.xpath('..')).element(by.css('heavy-loader'));
|
||||||
|
var setConditionText;
|
||||||
|
setConditionButtonEle.getText().then(function(text) {
|
||||||
|
setConditionText = text;
|
||||||
|
expect(ngIfButtonEle.isPresent()).toBe(true, 'should be able to find ngIfButton');
|
||||||
|
expect(cssButtonEle.isPresent()).toBe(true, 'should be able to find cssButton');
|
||||||
|
expect(ngIfParentEle.isPresent()).toBe(true, 'should be able to find ngIfButton parent');
|
||||||
|
expect(ngIfSiblingEle.isPresent()).toBe(true, 'should be able to find ngIfButton sibling');
|
||||||
|
expect(cssSiblingEle.isPresent()).toBe(true, 'should be able to find cssButton sibling');
|
||||||
|
return ngIfButtonEle.click();
|
||||||
|
}).then(function() {
|
||||||
|
expect(ngIfSiblingEle.isPresent()).toBe(false, 'now should NOT be able to find ngIfButton sibling');
|
||||||
|
expect(setConditionButtonEle.getText()).not.toEqual(setConditionText);
|
||||||
|
return cssButtonEle.click();
|
||||||
|
}).then(function() {
|
||||||
|
expect(cssSiblingEle.isPresent()).toBe(true, 'now should still be able to find cssButton sibling');
|
||||||
|
expect(cssSiblingEle.isDisplayed()).toBe(false, 'now cssButton sibling should NOT be visible');
|
||||||
|
return ngIfButtonEle.click();
|
||||||
|
}).then(function() {
|
||||||
|
expect(setConditionButtonEle.getText()).toEqual(setConditionText);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to use *ngIf ', function () {
|
||||||
|
var setConditionButtonEle = element.all(by.css('button')).get(0);
|
||||||
|
var displayEles = element.all(by.cssContainingText('p', 'Our heroes are true!'));
|
||||||
|
expect(displayEles.count()).toBe(2, "should be displaying two ngIf elements");
|
||||||
|
setConditionButtonEle.click().then(function() {
|
||||||
|
expect(displayEles.count()).toBe(0, "should nog longer be displaying ngIf elements");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
29
public/docs/_examples/template-syntax/e2e-spec.js
Normal file
29
public/docs/_examples/template-syntax/e2e-spec.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// Not yet complete
|
||||||
|
describe('Template Syntax', function () {
|
||||||
|
|
||||||
|
beforeAll(function () {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to use interpolation with a hero', function () {
|
||||||
|
var heroInterEle = element.all(by.css('h2+p')).get(0);
|
||||||
|
expect(heroInterEle.getText()).toEqual('My current hero is Hercules');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to use interpolation with a calculation', function () {
|
||||||
|
var theSumEles = element.all(by.cssContainingText('h3~p','The sum of'));
|
||||||
|
expect(theSumEles.count()).toBe(2);
|
||||||
|
expect(theSumEles.get(0).getText()).toEqual('The sum of 1 + 1 is 2');
|
||||||
|
expect(theSumEles.get(1).getText()).toEqual('The sum of 1 + 1 is not 4');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to use class binding syntax', function () {
|
||||||
|
var specialEle = element(by.cssContainingText('div','Special'));
|
||||||
|
expect(specialEle.getAttribute('class')).toMatch('special');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to use style binding syntax', function () {
|
||||||
|
var specialButtonEle = element(by.cssContainingText('div.special~button', 'button'));
|
||||||
|
expect(specialButtonEle.getAttribute('style')).toMatch('color: red');
|
||||||
|
});
|
||||||
|
});
|
46
public/docs/_examples/tutorial/e2e-spec.js
Normal file
46
public/docs/_examples/tutorial/e2e-spec.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Not yet complete
|
||||||
|
describe('Tutorial', function () {
|
||||||
|
|
||||||
|
beforeAll(function () {
|
||||||
|
browser.get('');
|
||||||
|
init();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var _hrefEles, _tohDashboardHrefEle, _tohHeroesHrefEle;
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
_hrefEles = element.all(by.css('my-app a'));
|
||||||
|
|
||||||
|
_tohDashboardHrefEle = _hrefEles.get(0);
|
||||||
|
_tohHeroesHrefEle = _hrefEles.get(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should be able to see the start screen', function () {
|
||||||
|
expect(_hrefEles.count()).toEqual(2, 'should be two dashboard choices');
|
||||||
|
expect(_tohDashboardHrefEle.getText()).toEqual("Dashboard");
|
||||||
|
expect(_tohHeroesHrefEle.getText()).toEqual("Heroes");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to see dashboard choices', function () {
|
||||||
|
var dashboardHeroEles = element.all(by.css('my-app my-dashboard .module.hero'));
|
||||||
|
expect(dashboardHeroEles.count()).toBe(4, "should be 4 dashboard hero choices");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to toggle the views', function () {
|
||||||
|
var dashboardEle = element(by.css('my-app my-dashboard'));
|
||||||
|
expect(dashboardEle.element(by.css('h3')).getText()).toEqual('Top Heroes');
|
||||||
|
_tohHeroesHrefEle.click().then(function() {
|
||||||
|
expect(dashboardEle.isPresent()).toBe(false, 'should no longer see dashboard element');
|
||||||
|
var heroEles = element.all(by.css('my-app my-heroes li'));
|
||||||
|
expect(heroEles.count()).toBeGreaterThan(4, "should be more than 4 heroes shown");
|
||||||
|
return _tohDashboardHrefEle.click();
|
||||||
|
}).then(function() {
|
||||||
|
expect(dashboardEle.isPresent()).toBe(true, 'should once again see the dashboard element');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user