parent
34122f4d92
commit
872064e12e
|
@ -23,3 +23,4 @@ npm-debug.log.*
|
|||
plnkr.html
|
||||
*plnkr.no-link.html
|
||||
public/docs/*/latest/guide/cheatsheet.json
|
||||
protractor-results.txt
|
||||
|
|
185
gulpfile.js
185
gulpfile.js
|
@ -15,8 +15,13 @@ var fsExtra = require('fs-extra');
|
|||
var fs = fsExtra;
|
||||
var exec = require('child_process').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 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:
|
||||
// 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' ]
|
||||
|
||||
// --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
|
||||
|
||||
gulp.task('default', ['help']);
|
||||
|
@ -69,7 +188,7 @@ gulp.task('help', taskListing.withFilters(function(taskName) {
|
|||
}));
|
||||
|
||||
// requires admin access
|
||||
gulp.task('add-example-boilerplate', function() {
|
||||
gulp.task('add-example-boilerplate', function() {
|
||||
var realPath = path.join(EXAMPLES_PATH, '/node_modules');
|
||||
var nodeModulesPaths = getNodeModulesPaths(EXAMPLES_PATH);
|
||||
|
||||
|
@ -77,12 +196,25 @@ gulp.task('add-example-boilerplate', function() {
|
|||
gutil.log("symlinking " + linkPath + ' -> ' + realPath)
|
||||
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) {
|
||||
return path.join(EXAMPLES_PATH, fn);
|
||||
});
|
||||
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() {
|
||||
var nodeModulesPaths = getNodeModulesPaths(EXAMPLES_PATH);
|
||||
|
@ -90,7 +222,10 @@ gulp.task('remove-example-boilerplate', function() {
|
|||
fsUtils.removeSymlink(linkPath);
|
||||
});
|
||||
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) {
|
||||
|
@ -264,18 +399,11 @@ function deleteFiles(baseFileNames, destPaths) {
|
|||
return Q.all(delPromises);
|
||||
}
|
||||
|
||||
function getExamplePaths(basePath) {
|
||||
var jsonPattern = path.join(basePath, "**/example-config.json");
|
||||
// ignore (skip) the top level version.
|
||||
var exceptJsonPattern = "!" + path.join(basePath, "/example-config.json");
|
||||
var nmPattern = path.join(basePath, "**/node_modules/**");
|
||||
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;
|
||||
// TODO: filter out all paths that are subdirs of another
|
||||
// path in the result.
|
||||
function getE2eSpecPaths(basePath) {
|
||||
var paths = getPaths(basePath, '*e2e-spec.js', true);
|
||||
return _.uniq(paths);
|
||||
}
|
||||
|
||||
function getNodeModulesPaths(basePath) {
|
||||
|
@ -285,6 +413,31 @@ function getNodeModulesPaths(basePath) {
|
|||
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) {
|
||||
|
||||
execCommands(['npm run harp -- server .'], {}, cb);
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"harp": "harp",
|
||||
"live-server": "live-server",
|
||||
"test-api-builder": "jasmine-node tools/api-builder"
|
||||
"test-api-builder": "jasmine-node tools/api-builder",
|
||||
|
||||
"protractor": "protractor"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -28,6 +30,7 @@
|
|||
"assert-plus": "^0.1.5",
|
||||
"browser-sync": "^2.9.3",
|
||||
"canonical-path": "0.0.2",
|
||||
"cross-spawn": "^2.1.0",
|
||||
"del": "^1.2.0",
|
||||
"dgeni": "^0.4.0",
|
||||
"dgeni-packages": "^0.11.1",
|
||||
|
@ -58,7 +61,9 @@
|
|||
"nodegit": "0.5.0",
|
||||
"path": "^0.11.14",
|
||||
"prompt": "^0.2.14",
|
||||
"protractor": "^3.0.0",
|
||||
"q": "^1.4.1",
|
||||
"tree-kill": "^1.0.0",
|
||||
"typescript": "1.7.3",
|
||||
"yargs": "^3.23.0"
|
||||
},
|
||||
|
|
|
@ -4,4 +4,5 @@ package.json
|
|||
karma.conf.js
|
||||
karma-test-shim.js
|
||||
tsconfig.json
|
||||
npm-debug*.log
|
||||
npm-debug*.
|
||||
**/protractor.config.js
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
})
|
||||
|
||||
});
|
|
@ -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);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
|
@ -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!');
|
||||
});
|
||||
});
|
|
@ -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');
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
});
|
|
@ -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",
|
||||
"start": "concurrent \"npm run tsc:w\" \"npm run lite\" ",
|
||||
"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": [],
|
||||
"author": "",
|
||||
|
@ -27,15 +28,16 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"concurrently": "^1.0.0",
|
||||
"lite-server": "^1.3.1",
|
||||
"live-server": "^0.8.2",
|
||||
"typescript": "^1.7.3",
|
||||
"jasmine-core":"~2.1.0",
|
||||
"http-server": "^0.8.5",
|
||||
"jasmine-core": "~2.1.0",
|
||||
"karma": "^0.12.23",
|
||||
"karma-chrome-launcher": "^0.1.4",
|
||||
"karma-cli": "^0.0.4",
|
||||
"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": { }
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
});
|
|
@ -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 () {
|
||||
|
||||
// #docregion shared
|
||||
var expectedMsg = 'My First Angular 2 App';
|
||||
|
||||
// tests shared across languages
|
||||
function sharedTests(basePath) {
|
||||
beforeEach(function () {
|
||||
browser.get(basePath + 'index.html');
|
||||
});
|
||||
|
||||
it('should display: ' + expectedMsg, function () {
|
||||
expect(element(by.css('h1')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
}
|
||||
// #enddocregion
|
||||
beforeEach(function () {
|
||||
browser.get('');
|
||||
});
|
||||
|
||||
describe('QuickStart in JavaScript', function () {
|
||||
sharedTests('quickstart/js/');
|
||||
});
|
||||
|
||||
describe('QuickStart in TypeScript', function () {
|
||||
sharedTests('quickstart/ts/');
|
||||
});
|
||||
it('should display: ' + expectedMsg, function () {
|
||||
expect(element(by.css('h1')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -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");
|
||||
});
|
||||
});
|
||||
});
|
|
@ -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');
|
||||
});
|
||||
});
|
|
@ -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…
Reference in New Issue