Commit 537c4122 authored by Colin Eberhardt's avatar Colin Eberhardt

Merge pull request #1573 from ColinEberhardt/mhoyer-async-tests

Correcting asynchronous testing
parents 4de8afb2 951eb70b
'use strict'; 'use strict';
var webdriver = require('selenium-webdriver'); var webdriver = require('selenium-webdriver');
var idSelectors = false; var idSelectors = true;
module.exports = function Page(browser) { module.exports = function Page(browser) {
...@@ -16,35 +16,35 @@ module.exports = function Page(browser) { ...@@ -16,35 +16,35 @@ module.exports = function Page(browser) {
}; };
this.getTodoListXpath = function () { this.getTodoListXpath = function () {
return !idSelectors ? '//ul[@id="todo-list"]' : '//ul[contains(@class, "todo-list")]'; return idSelectors ? '//ul[@id="todo-list"]' : '//ul[contains(@class, "todo-list")]';
}; };
this.getMainSectionXpath = function () { this.getMainSectionXpath = function () {
return !idSelectors ? '//section[@id="main"]' : '//section[contains(@class, "main")]'; return idSelectors ? '//section[@id="main"]' : '//section[contains(@class, "main")]';
}; };
this.getFooterSectionXpath = function () { this.getFooterSectionXpath = function () {
return !idSelectors ? '//footer[@id="footer"]' : '//footer[contains(@class, "footer")]'; return idSelectors ? '//footer[@id="footer"]' : '//footer[contains(@class, "footer")]';
}; };
this.getCompletedButtonXpath = function () { this.getCompletedButtonXpath = function () {
return !idSelectors ? '//button[@id="clear-completed"]' : '//button[contains(@class, "clear-completed")]'; return idSelectors ? '//button[@id="clear-completed"]' : '//button[contains(@class, "clear-completed")]';
}; };
this.getNewInputXpath = function () { this.getNewInputXpath = function () {
return !idSelectors ? '//input[@id="new-todo"]' : '//input[contains(@class,"new-todo")]'; return idSelectors ? '//input[@id="new-todo"]' : '//input[contains(@class,"new-todo")]';
}; };
this.getToggleAllXpath = function () { this.getToggleAllXpath = function () {
return !idSelectors ? '//input[@id="toggle-all"]' : '//input[contains(@class,"toggle-all")]'; return idSelectors ? '//input[@id="toggle-all"]' : '//input[contains(@class,"toggle-all")]';
}; };
this.getCountXpath = function () { this.getCountXpath = function () {
return !idSelectors ? '//span[@id="todo-count"]' : '//span[contains(@class, "todo-count")]'; return idSelectors ? '//span[@id="todo-count"]' : '//span[contains(@class, "todo-count")]';
}; };
this.getFiltersElementXpath = function () { this.getFiltersElementXpath = function () {
return !idSelectors ? '//*[@id="filters"]' : '//*[contains(@class, "filters")]'; return idSelectors ? '//*[@id="filters"]' : '//*[contains(@class, "filters")]';
}; };
this.getFilterXpathByIndex = function (index) { this.getFilterXpathByIndex = function (index) {
...@@ -115,9 +115,9 @@ module.exports = function Page(browser) { ...@@ -115,9 +115,9 @@ module.exports = function Page(browser) {
return this.getActiveElement().getTagName(); return this.getActiveElement().getTagName();
}; };
this.getFocussedElementName = function () { this.getFocussedElementIdOrClass = function () {
return this.getActiveElement() return this.getActiveElement()
.getAttribute(!idSelectors ? 'id' : 'class'); .getAttribute(idSelectors ? 'id' : 'class');
}; };
this.getEditInputForItemAtIndex = function (index) { this.getEditInputForItemAtIndex = function (index) {
...@@ -175,9 +175,24 @@ module.exports = function Page(browser) { ...@@ -175,9 +175,24 @@ module.exports = function Page(browser) {
}); });
}; };
this.waitForVisibleElement = function (getElementFn, timeout) {
var foundVisibleElement;
timeout = timeout || 500;
return browser.wait(function () {
foundVisibleElement = getElementFn();
return foundVisibleElement.isDisplayed();
}, timeout)
.then(function () {
return foundVisibleElement;
})
.thenCatch(function (err) {
return false;
});
}
this.getVisibileLabelIndicies = function () { this.getVisibileLabelIndicies = function () {
var self = this; var self = this;
var ret;
return this.getItemLabels() return this.getItemLabels()
.then(function (elms) { .then(function (elms) {
return elms.map(function (elm, i) { return elms.map(function (elm, i) {
...@@ -186,18 +201,8 @@ module.exports = function Page(browser) { ...@@ -186,18 +201,8 @@ module.exports = function Page(browser) {
}) })
.then(function (elms) { .then(function (elms) {
return webdriver.promise.filter(elms, function (elmIndex) { return webdriver.promise.filter(elms, function (elmIndex) {
return browser.wait(function () { return self.waitForVisibleElement(function () {
return self.tryGetItemLabelAtIndex(elmIndex).isDisplayed() return self.tryGetItemLabelAtIndex(elmIndex);
.then(function (v) {
ret = v;
return true;
})
.thenCatch(function () {
return false;
});
}, 5000)
.then(function () {
return ret;
}); });
}); });
}); });
...@@ -205,58 +210,63 @@ module.exports = function Page(browser) { ...@@ -205,58 +210,63 @@ module.exports = function Page(browser) {
// ----------------- page actions // ----------------- page actions
this.ensureAppIsVisible = function () { this.ensureAppIsVisible = function () {
return browser.findElements(webdriver.By.css('#todoapp')) var self = this;
.then(function (elms) { return browser.wait(function () {
if (elms.length > 0) { // try to find main element by ID
return true; return browser.isElementPresent(webdriver.By.css('.new-todo'))
} else { .then(function (foundByClass) {
return browser.findElements(webdriver.By.css('.todoapp')); if (foundByClass) {
} idSelectors = false;
}) return true;
.then(function (elms) { }
if (elms === true) {
return true;
}
if (elms.length) { // try to find main element by CSS class
idSelectors = true; return browser.isElementPresent(webdriver.By.css('#new-todo'));
return true; });
}, 5000)
.then(function (hasFoundNewTodoElement) {
if (!hasFoundNewTodoElement) {
throw new Error('Unable to find application, did you start your local server?');
} }
throw new Error('Unable to find application root, did you start your local server?');
}); });
}; };
this.clickMarkAllCompletedCheckBox = function () { this.clickMarkAllCompletedCheckBox = function () {
return this.getMarkAllCompletedCheckBox().then(function (checkbox) { return this.getMarkAllCompletedCheckBox().then(function (checkbox) {
checkbox.click(); return checkbox.click();
}); });
}; };
this.clickClearCompleteButton = function () { this.clickClearCompleteButton = function () {
return this.tryGetClearCompleteButton().click(); var self = this;
return self.waitForVisibleElement(function () {
return self.tryGetClearCompleteButton();
})
.then(function (clearCompleteButton) {
return clearCompleteButton.click();
});
}; };
this.enterItem = function (itemText) { this.enterItem = function (itemText) {
var self = this; var self = this;
browser.wait(function () { return browser.wait(function () {
return self.getItemInputField().then(function (textField) { var textField;
return textField.sendKeys(itemText, webdriver.Key.ENTER)
.then(function () { return self.getItemInputField().then(function (itemInputField) {
return textField; textField = itemInputField;
}); return textField.sendKeys(itemText, webdriver.Key.ENTER);
}).then(function (textField) { })
return self.getVisibleLabelText() .then(function () { return self.getVisibleLabelText(); })
.then(function (labels) { .then(function (labels) {
if (labels.indexOf(itemText.trim()) !== -1) { if (labels.indexOf(itemText.trim()) >= 0) {
return true; return true;
} }
return textField.clear().then(function () { return textField.clear().then(function () {
return false; return false;
}); });
});
}); });
}, 5000); }, 5000);
}; };
......
...@@ -15,13 +15,18 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod ...@@ -15,13 +15,18 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod
var browser, testOps, page; var browser, testOps, page;
// a number of tests use this set of ToDo items. // a number of tests use this set of ToDo items.
function createStandardItems() { function createStandardItems(done) {
page.enterItem(TODO_ITEM_ONE); page.enterItem(TODO_ITEM_ONE);
page.enterItem(TODO_ITEM_TWO); page.enterItem(TODO_ITEM_TWO);
page.enterItem(TODO_ITEM_THREE); return page.enterItem(TODO_ITEM_THREE)
.then(function () {
if (done instanceof Function) {
done();
};
});
} }
function launchBrowser() { function launchBrowser(done) {
var chromeOptions = new chrome.Options(); var chromeOptions = new chrome.Options();
chromeOptions.addArguments('no-sandbox'); chromeOptions.addArguments('no-sandbox');
...@@ -30,146 +35,162 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod ...@@ -30,146 +35,162 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod
} }
browser = new webdriver.Builder() browser = new webdriver.Builder()
.withCapabilities({ .withCapabilities({browserName: browserName})
browserName: browserName .setChromeOptions(chromeOptions)
}) .build();
.setChromeOptions(chromeOptions)
.build();
browser.get(baseUrl); browser.get(baseUrl);
page = laxMode ? new PageLaxMode(browser) : new Page(browser); page = laxMode ? new PageLaxMode(browser) : new Page(browser);
testOps = new TestOperations(page); testOps = new TestOperations(page);
// for apps that use require, we have to wait a while for the dependencies to return page.ensureAppIsVisible()
// be loaded. There must be a more elegant solution than this! .then(function () {
browser.sleep(200); if (done instanceof Function) {
done();
};
});
}
function printCapturedLogs() {
var logs = new webdriver.WebDriver.Logs(browser);
return logs.get('browser')
.then(function (entries) {
if (entries && entries.length) {
console.log(entries);
}
});
} }
function closeBrowser() { function closeBrowser(done) {
browser.quit(); return browser
.quit()
.then(function () {
if (done instanceof Function) {
done();
};
});
} }
if (speedMode) { if (speedMode) {
test.before(function () { test.before(launchBrowser);
launchBrowser(); test.after(closeBrowser);
}); test.beforeEach(function (done) {
test.after(function () { return page.getItemElements()
closeBrowser(); .then(function (items) {
}); if (items.length == 0) { return; }
test.beforeEach(function () {
page.getItemElements().then(function (items) {
if (items.length > 0) {
// find any items that are not complete // find any items that are not complete
page.getNonCompletedItemElements().then(function (nonCompleteItems) { page.getNonCompletedItemElements()
if (nonCompleteItems.length > 0) { .then(function (nonCompleteItems) {
page.clickMarkAllCompletedCheckBox(); if (nonCompleteItems.length > 0) {
} return page.clickMarkAllCompletedCheckBox();
page.clickClearCompleteButton(); }
}); })
}
}); return page.clickClearCompleteButton();
})
.then(function () { done(); });
}); });
} else { } else {
test.beforeEach(function () { test.beforeEach(launchBrowser);
launchBrowser(); test.afterEach(function (done) {
page.ensureAppIsVisible(); printCapturedLogs()
}); .then(function () {
test.afterEach(function () { return closeBrowser(done);
(new webdriver.WebDriver.Logs(browser)) })
.get('browser')
.then(function (v) {
if (v && v.length) {
console.log(v);
}
});
closeBrowser();
}); });
} }
test.describe('When page is initially opened', function () { test.describe('When page is initially opened', function () {
test.it('should focus on the todo input field', function () { test.it('should focus on the todo input field', function (done) {
testOps.assertFocussedElementId('new-todo'); testOps.assertFocussedElement('new-todo')
.then(function () { done(); });
}); });
}); });
test.describe('No Todos', function () { test.describe('No Todos', function () {
test.it('should hide #main and #footer', function () { test.it('should hide #main and #footer', function (done) {
testOps.assertItemCount(0); testOps.assertItemCount(0);
testOps.assertMainSectionIsHidden(); testOps.assertMainSectionIsHidden();
testOps.assertFooterIsHidden(); testOps.assertFooterIsHidden()
.then(function () { done(); });
}); });
}); });
test.describe('New Todo', function () { test.describe('New Todo', function () {
test.it('should allow me to add todo items', function () { test.it('should allow me to add todo items', function (done) {
page.enterItem(TODO_ITEM_ONE); page.enterItem(TODO_ITEM_ONE);
testOps.assertItems([TODO_ITEM_ONE]); testOps.assertItems([TODO_ITEM_ONE]);
page.enterItem(TODO_ITEM_TWO); page.enterItem(TODO_ITEM_TWO);
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO]); testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO])
.then(function () { done(); });
}); });
test.it('should clear text input field when an item is added', function () { test.it('should clear text input field when an item is added', function (done) {
page.enterItem(TODO_ITEM_ONE); page.enterItem(TODO_ITEM_ONE);
testOps.assertItemInputFieldText(''); testOps.assertItemInputFieldText('')
.then(function () { done(); });
}); });
test.it('should append new items to the bottom of the list', function () { test.it('should append new items to the bottom of the list', function (done) {
createStandardItems(); createStandardItems();
testOps.assertItemCount(3); testOps.assertItemCount(3);
testOps.assertItemText(0, TODO_ITEM_ONE); testOps.assertItemText(0, TODO_ITEM_ONE);
testOps.assertItemText(1, TODO_ITEM_TWO); testOps.assertItemText(1, TODO_ITEM_TWO);
testOps.assertItemText(2, TODO_ITEM_THREE); testOps.assertItemText(2, TODO_ITEM_THREE)
.then(function () { done(); });
}); });
test.it('should trim text input', function () { test.it('should trim text input', function (done) {
page.enterItem(' ' + TODO_ITEM_ONE + ' '); page.enterItem(' ' + TODO_ITEM_ONE + ' ');
testOps.assertItemText(0, TODO_ITEM_ONE); testOps.assertItemText(0, TODO_ITEM_ONE)
.then(function () { done(); });
}); });
test.it('should show #main and #footer when items added', function () { test.it('should show #main and #footer when items added', function (done) {
page.enterItem(TODO_ITEM_ONE); page.enterItem(TODO_ITEM_ONE);
testOps.assertMainSectionIsVisible(); testOps.assertMainSectionIsVisible();
testOps.assertFooterIsVisible(); testOps.assertFooterIsVisible()
.then(function () { done(); });
}); });
}); });
test.describe('Mark all as completed', function () { test.describe('Mark all as completed', function () {
test.beforeEach(function () { test.beforeEach(createStandardItems);
createStandardItems();
});
test.it('should allow me to mark all items as completed', function () { test.it('should allow me to mark all items as completed', function (done) {
page.clickMarkAllCompletedCheckBox(); page.clickMarkAllCompletedCheckBox();
testOps.assertItemAtIndexIsCompleted(0); testOps.assertItemAtIndexIsCompleted(0);
testOps.assertItemAtIndexIsCompleted(1); testOps.assertItemAtIndexIsCompleted(1);
testOps.assertItemAtIndexIsCompleted(2); testOps.assertItemAtIndexIsCompleted(2)
.then(function () { done(); });
}); });
test.it('should correctly update the complete all checked state', function () { test.it('should correctly update the complete all checked state', function (done) {
// manually check all items // manually check all items
page.toggleItemAtIndex(0); page.toggleItemAtIndex(0);
page.toggleItemAtIndex(1); page.toggleItemAtIndex(1);
page.toggleItemAtIndex(2); page.toggleItemAtIndex(2);
// ensure checkall is in the correct state // ensure checkall is in the correct state
testOps.assertCompleteAllIsChecked(); testOps.assertCompleteAllIsChecked()
.then(function () { done(); });
}); });
test.it('should allow me to clear the completion state of all items', function () { test.it('should allow me to clear the completion state of all items', function (done) {
page.clickMarkAllCompletedCheckBox(); page.clickMarkAllCompletedCheckBox();
page.clickMarkAllCompletedCheckBox(); page.clickMarkAllCompletedCheckBox();
testOps.assertItemAtIndexIsNotCompleted(0); testOps.assertItemAtIndexIsNotCompleted(0);
testOps.assertItemAtIndexIsNotCompleted(1); testOps.assertItemAtIndexIsNotCompleted(1);
testOps.assertItemAtIndexIsNotCompleted(2); testOps.assertItemAtIndexIsNotCompleted(2)
.then(function () { done(); });
}); });
test.it('complete all checkbox should update state when items are completed / cleared', function () { test.it('complete all checkbox should update state when items are completed / cleared', function (done) {
page.clickMarkAllCompletedCheckBox(); page.clickMarkAllCompletedCheckBox();
testOps.assertCompleteAllIsChecked(); testOps.assertCompleteAllIsChecked();
// all items are complete, now mark one as not-complete // all items are complete, now mark one as not-complete
...@@ -178,12 +199,13 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod ...@@ -178,12 +199,13 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod
// now mark as complete, so that once again all items are completed // now mark as complete, so that once again all items are completed
page.toggleItemAtIndex(0); page.toggleItemAtIndex(0);
testOps.assertCompleteAllIsChecked(); testOps.assertCompleteAllIsChecked()
.then(function () { done(); });
}); });
}); });
test.describe('Item', function () { test.describe('Item', function () {
test.it('should allow me to mark items as complete', function () { test.it('should allow me to mark items as complete', function (done) {
page.enterItem(TODO_ITEM_ONE); page.enterItem(TODO_ITEM_ONE);
page.enterItem(TODO_ITEM_TWO); page.enterItem(TODO_ITEM_TWO);
...@@ -193,10 +215,11 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod ...@@ -193,10 +215,11 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod
page.toggleItemAtIndex(1); page.toggleItemAtIndex(1);
testOps.assertItemAtIndexIsCompleted(0); testOps.assertItemAtIndexIsCompleted(0);
testOps.assertItemAtIndexIsCompleted(1); testOps.assertItemAtIndexIsCompleted(1)
.then(function () { done(); });
}); });
test.it('should allow me to un-mark items as complete', function () { test.it('should allow me to un-mark items as complete', function (done) {
page.enterItem(TODO_ITEM_ONE); page.enterItem(TODO_ITEM_ONE);
page.enterItem(TODO_ITEM_TWO); page.enterItem(TODO_ITEM_TWO);
...@@ -206,102 +229,101 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod ...@@ -206,102 +229,101 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod
page.toggleItemAtIndex(0); page.toggleItemAtIndex(0);
testOps.assertItemAtIndexIsNotCompleted(0); testOps.assertItemAtIndexIsNotCompleted(0);
testOps.assertItemAtIndexIsNotCompleted(1); testOps.assertItemAtIndexIsNotCompleted(1)
.then(function () { done(); });
}); });
}); });
test.describe('Editing', function () { test.describe('Editing', function (done) {
test.beforeEach(function () { test.beforeEach(function (done) {
createStandardItems(); createStandardItems();
page.doubleClickItemAtIndex(1); page.doubleClickItemAtIndex(1)
.then(function () { done(); });
}); });
test.it('should focus the input', function () { test.it('should focus the input', function (done) {
testOps.assertInputFocused(); testOps.assertInputFocused();
testOps.assertNewInputNotFocused(); testOps.assertNewInputNotFocused()
.then(function () { done(); });
}); });
test.it('should hide other controls when editing', function () { test.it('should hide other controls when editing', function (done) {
testOps.assertItemToggleIsHidden(1); testOps.assertItemToggleIsHidden(1);
testOps.assertItemLabelIsHidden(1); testOps.assertItemLabelIsHidden(1)
.then(function () { done(); });
}); });
test.it('should save edits on enter', function () { test.it('should save edits on enter', function (done) {
page.editItemAtIndex(1, 'buy some sausages' + webdriver.Key.ENTER); page.editItemAtIndex(1, 'buy some sausages' + webdriver.Key.ENTER);
testOps.assertItems([TODO_ITEM_ONE, 'buy some sausages', TODO_ITEM_THREE])
testOps.assertItems([TODO_ITEM_ONE, 'buy some sausages', TODO_ITEM_THREE]); .then(function () { done(); });
}); });
test.it('should save edits on blur', function () { test.it('should save edits on blur', function (done) {
page.editItemAtIndex(1, 'buy some sausages'); page.editItemAtIndex(1, 'buy some sausages');
// click a toggle button so that the blur() event is fired // click a toggle button so that the blur() event is fired
page.toggleItemAtIndex(0); page.toggleItemAtIndex(0);
testOps.assertItems([TODO_ITEM_ONE, 'buy some sausages', TODO_ITEM_THREE])
testOps.assertItems([TODO_ITEM_ONE, 'buy some sausages', TODO_ITEM_THREE]); .then(function () { done(); });
}); });
test.it('should trim entered text', function () { test.it('should trim entered text', function (done) {
page.editItemAtIndex(1, ' buy some sausages ' + webdriver.Key.ENTER); page.editItemAtIndex(1, ' buy some sausages ' + webdriver.Key.ENTER);
testOps.assertItems([TODO_ITEM_ONE, 'buy some sausages', TODO_ITEM_THREE])
testOps.assertItems([TODO_ITEM_ONE, 'buy some sausages', TODO_ITEM_THREE]); .then(function () { done(); });
}); });
test.it('should remove the item if an empty text string was entered', function () { test.it('should remove the item if an empty text string was entered', function (done) {
page.editItemAtIndex(1, webdriver.Key.ENTER); page.editItemAtIndex(1, webdriver.Key.ENTER);
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_THREE])
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_THREE]); .then(function () { done(); });
}); });
test.it('should cancel edits on escape', function () { test.it('should cancel edits on escape', function (done) {
page.editItemAtIndex(1, 'foo' + webdriver.Key.ESCAPE); page.editItemAtIndex(1, 'foo' + webdriver.Key.ESCAPE);
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO, TODO_ITEM_THREE])
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO, TODO_ITEM_THREE]); .then(function () { done(); });
}); });
}); });
test.describe('Counter', function () { test.describe('Counter', function () {
test.it('should display the current number of todo items', function () { test.it('should display the current number of todo items', function (done) {
page.enterItem(TODO_ITEM_ONE); page.enterItem(TODO_ITEM_ONE);
testOps.assertItemCountText('1 item left'); testOps.assertItemCountText('1 item left');
page.enterItem(TODO_ITEM_TWO); page.enterItem(TODO_ITEM_TWO);
testOps.assertItemCountText('2 items left'); testOps.assertItemCountText('2 items left')
.then(function () { done(); });
}); });
}); });
test.describe('Clear completed button', function () { test.describe('Clear completed button', function () {
test.beforeEach(function () { test.beforeEach(createStandardItems);
createStandardItems();
});
test.it('should display the correct text', function () { test.it('should display the correct text', function (done) {
page.toggleItemAtIndex(1); page.toggleItemAtIndex(1);
testOps.assertClearCompleteButtonText('Clear completed'); testOps.assertClearCompleteButtonText('Clear completed')
.then(function () { done(); });
}); });
test.it('should remove completed items when clicked', function () { test.it('should remove completed items when clicked', function (done) {
page.toggleItemAtIndex(1); page.toggleItemAtIndex(1);
page.clickClearCompleteButton(); page.clickClearCompleteButton();
testOps.assertItemCount(2); testOps.assertItemCount(2);
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_THREE]); testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_THREE])
.then(function () { done(); });
}); });
test.it('should be hidden when there are no items that are completed', function () { test.it('should be hidden when there are no items that are completed', function (done) {
page.toggleItemAtIndex(1); page.toggleItemAtIndex(1);
testOps.assertClearCompleteButtonIsVisible(); testOps.assertClearCompleteButtonIsVisible();
page.clickClearCompleteButton(); page.clickClearCompleteButton();
testOps.assertClearCompleteButtonIsHidden(); testOps.assertClearCompleteButtonIsHidden()
.then(function () { done(); });
}); });
}); });
test.describe('Persistence', function () { test.describe('Persistence', function () {
test.it('should persist its data', function () { test.it('should persist its data', function (done) {
// set up state
page.enterItem(TODO_ITEM_ONE);
page.enterItem(TODO_ITEM_TWO);
page.toggleItemAtIndex(1);
function stateTest() { function stateTest() {
// wait until things are visible // wait until things are visible
browser.wait(function () { browser.wait(function () {
...@@ -309,13 +331,16 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod ...@@ -309,13 +331,16 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod
return labels.length > 0; return labels.length > 0;
}); });
}, 5000); }, 5000);
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO]); testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO]);
testOps.assertItemAtIndexIsCompleted(1); testOps.assertItemAtIndexIsCompleted(1);
testOps.assertItemAtIndexIsNotCompleted(0);
return testOps.assertItemAtIndexIsNotCompleted(0);
} }
// test it // set up state
page.enterItem(TODO_ITEM_ONE);
page.enterItem(TODO_ITEM_TWO);
page.toggleItemAtIndex(1);
stateTest(); stateTest();
// navigate away and back again // navigate away and back again
...@@ -323,66 +348,60 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod ...@@ -323,66 +348,60 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod
browser.get(baseUrl); browser.get(baseUrl);
// repeat the state test // repeat the state test
stateTest(); stateTest()
.then(function () { done(); });
}); });
}); });
test.describe('Routing', function () { test.describe('Routing', function () {
test.beforeEach(function () { test.beforeEach(createStandardItems);
createStandardItems();
}); test.it('should allow me to display active items', function (done) {
test.it('should allow me to display active items', function () {
page.toggleItemAtIndex(1); page.toggleItemAtIndex(1);
page.filterByActiveItems(); page.filterByActiveItems();
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_THREE])
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_THREE]); .then(function () { return done(); });
}); });
test.it('should respect the back button', function () { test.it('should respect the back button', function (done) {
page.toggleItemAtIndex(1); page.toggleItemAtIndex(1);
page.filterByActiveItems(); page.filterByActiveItems();
page.filterByCompletedItems(); page.filterByCompletedItems();
testOps.assertItems([TODO_ITEM_TWO]);// should show completed items
// should show completed items page.back(); // then active items
testOps.assertItems([TODO_ITEM_TWO]);
// then active items
page.back();
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_THREE]); testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_THREE]);
page.back(); // then all items
// then all items testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO, TODO_ITEM_THREE])
page.back(); .then(function () { done(); });
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO, TODO_ITEM_THREE]);
}); });
test.it('should allow me to display completed items', function () { test.it('should allow me to display completed items', function (done) {
page.toggleItemAtIndex(1); page.toggleItemAtIndex(1);
page.filterByCompletedItems(); page.filterByCompletedItems();
testOps.assertItems([TODO_ITEM_TWO]); testOps.assertItems([TODO_ITEM_TWO]);
page.filterByAllItems() // TODO: why
.then(function () { done(); });
}); });
test.it('should allow me to display all items', function () { test.it('should allow me to display all items', function (done) {
page.toggleItemAtIndex(1); page.toggleItemAtIndex(1);
// apply the other filters first, before returning to the 'all' state // apply the other filters first, before returning to the 'all' state
page.filterByActiveItems(); page.filterByActiveItems();
page.filterByCompletedItems(); page.filterByCompletedItems();
page.filterByAllItems(); page.filterByAllItems();
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO, TODO_ITEM_THREE])
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO, TODO_ITEM_THREE]); .then(function () { done(); });
}); });
test.it('should highlight the currently applied filter', function () { test.it('should highlight the currently applied filter', function (done) {
// initially 'all' should be selected // initially 'all' should be selected
testOps.assertFilterAtIndexIsSelected(0); testOps.assertFilterAtIndexIsSelected(0);
page.filterByActiveItems(); page.filterByActiveItems();
testOps.assertFilterAtIndexIsSelected(1); testOps.assertFilterAtIndexIsSelected(1);
page.filterByCompletedItems(); page.filterByCompletedItems();
testOps.assertFilterAtIndexIsSelected(2); testOps.assertFilterAtIndexIsSelected(2)
.then(function () { done(); });
}); });
}); });
}); });
......
...@@ -16,15 +16,16 @@ function TestOperations(page) { ...@@ -16,15 +16,16 @@ function TestOperations(page) {
function testIsVisible(elements, name) { function testIsVisible(elements, name) {
assert.equal(elements.length, 1); assert.equal(elements.length, 1);
elements[0].isDisplayed().then(function (isDisplayed) { return elements[0].isDisplayed()
assert(isDisplayed, 'the ' + name + ' element should be displayed'); .then(function (isDisplayed) {
}); assert(isDisplayed, 'the ' + name + ' element should be displayed');
});
} }
this.assertNewInputNotFocused = function () { this.assertNewInputNotFocused = function () {
return page.getFocussedElementName() return page.getFocussedElementIdOrClass()
.then(function (name) { .then(function (focussedElementIdOrClass) {
assert.notEqual(name, 'new-todo'); assert.equal(focussedElementIdOrClass.indexOf('new-todo'), -1);
}); });
}; };
...@@ -35,147 +36,177 @@ function TestOperations(page) { ...@@ -35,147 +36,177 @@ function TestOperations(page) {
}); });
}; };
this.assertFocussedElementId = function (expectedId) { this.assertFocussedElement = function (expectedIdentifier) {
page.getFocussedElementName().then(function (id) { return page.getFocussedElementIdOrClass()
assert.notEqual(id.indexOf(expectedId), -1, 'The focused element did not have the expected id ' + expectedId); .then(function (focusedElementIdentifier) {
}); var failMsg = 'The focused element did not have the expected class or id "' + expectedIdentifier + '"';
assert.notEqual(focusedElementIdentifier.indexOf(expectedIdentifier), -1, failMsg);
});
}; };
this.assertClearCompleteButtonIsHidden = function () { this.assertClearCompleteButtonIsHidden = function () {
page.tryGetClearCompleteButton().then(function (element) { return page.tryGetClearCompleteButton()
testIsHidden(element, 'clear completed items button'); .then(function (element) {
}, function (_error) { return testIsHidden(element, 'clear completed items button');
assert(_error.code === 7, 'error accessing clear completed items button, error: ' + _error.message); }, function (_error) {
}); assert(_error.code === 7, 'error accessing clear completed items button, error: ' + _error.message);
});
}; };
this.assertClearCompleteButtonIsVisible = function () { this.assertClearCompleteButtonIsVisible = function () {
page.tryGetClearCompleteButton().then(function (element) { return page.waitForVisibleElement(function () {
testIsVisible([element], 'clear completed items button'); return page.tryGetClearCompleteButton();
}); })
.then(function (clearCompleteButton) {
assert(clearCompleteButton, 'the clear completed items button element should be displayed');
});
}; };
this.assertItemCount = function (itemCount) { this.assertItemCount = function (itemCount) {
page.getItemElements().then(function (toDoItems) { return page.getItemElements()
assert.equal(toDoItems.length, itemCount, .then(function (toDoItems) {
itemCount + ' items expected in the todo list, ' + toDoItems.length + ' items observed'); assert.equal(toDoItems.length, itemCount,
}); itemCount + ' items expected in the todo list, ' + toDoItems.length + ' items observed');
});
}; };
this.assertClearCompleteButtonText = function (buttonText) { this.assertClearCompleteButtonText = function (buttonText) {
return page.tryGetClearCompleteButton() return page.waitForVisibleElement(function () {
.getText().then(function (text) { return page.tryGetClearCompleteButton();
assert.equal(text, buttonText); })
}); .then(function (clearCompleteButton) {
return clearCompleteButton.getText();
})
.then(function (text) {
return assert.equal(text, buttonText);
});
}; };
this.assertMainSectionIsHidden = function () { this.assertMainSectionIsHidden = function () {
page.tryGetMainSectionElement().then(function (mainSection) { return page.tryGetMainSectionElement()
testIsHidden(mainSection, 'main'); .then(function (mainSection) {
}); return testIsHidden(mainSection, 'main');
});
}; };
this.assertFooterIsHidden = function () { this.assertFooterIsHidden = function () {
page.tryGetFooterElement().then(function (footer) { return page.tryGetFooterElement()
testIsHidden(footer, 'footer'); .then(function (footer) {
}); return testIsHidden(footer, 'footer');
});
}; };
this.assertMainSectionIsVisible = function () { this.assertMainSectionIsVisible = function () {
page.tryGetMainSectionElement().then(function (mainSection) { return page.tryGetMainSectionElement()
testIsVisible(mainSection, 'main'); .then(function (mainSection) {
}); return testIsVisible(mainSection, 'main');
});
}; };
//TODO: fishy! //TODO: fishy!
this.assertItemToggleIsHidden = function (index) { this.assertItemToggleIsHidden = function (index) {
page.tryGetToggleForItemAtIndex(index).then(function (toggleItem) { return page.tryGetToggleForItemAtIndex(index)
testIsHidden(toggleItem, 'item-toggle'); .then(function (toggleItem) {
}); return testIsHidden(toggleItem, 'item-toggle');
});
}; };
this.assertItemLabelIsHidden = function (index) { this.assertItemLabelIsHidden = function (index) {
page.tryGetItemLabelAtIndex(index).then(function (toggleItem) { return page.tryGetItemLabelAtIndex(index)
testIsHidden(toggleItem, 'item-label'); .then(function (toggleItem) {
}); return testIsHidden(toggleItem, 'item-label');
});
}; };
this.assertFooterIsVisible = function () { this.assertFooterIsVisible = function () {
page.tryGetFooterElement().then(function (footer) { return page.tryGetFooterElement()
testIsVisible(footer, 'footer'); .then(function (footer) {
}); return testIsVisible(footer, 'footer');
});
}; };
this.assertItemInputFieldText = function (text) { this.assertItemInputFieldText = function (text) {
page.getItemInputField().getText().then(function (inputFieldText) { return page.getItemInputField().getText()
assert.equal(inputFieldText, text); .then(function (inputFieldText) {
}); assert.equal(inputFieldText, text);
});
}; };
this.assertItemText = function (itemIndex, textToAssert) { this.assertItemText = function (itemIndex, textToAssert) {
page.getItemLabelAtIndex(itemIndex).getText().then(function (text) { return page.getItemLabelAtIndex(itemIndex).getText()
assert.equal(text, textToAssert, .then(function (text) {
'A todo item with text \'' + textToAssert + '\' was expected at index ' + assert.equal(text, textToAssert,
itemIndex + ', the text \'' + text + '\' was observed'); 'A todo item with text \'' + textToAssert + '\' was expected at index ' +
}); itemIndex + ', the text \'' + text + '\' was observed');
});
}; };
// tests that the list contains the following items, independant of order // tests that the list contains the following items, independant of order
this.assertItems = function (textArray) { this.assertItems = function (textArray) {
return page.getVisibleLabelText() return page.getVisibleLabelText()
.then(function (visibleText) { .then(function (visibleText) {
assert.deepEqual(visibleText.sort(), textArray.sort()); assert.deepEqual(visibleText.sort(), textArray.sort());
}); });
}; };
this.assertItemCountText = function (textToAssert) { this.assertItemCountText = function (textToAssert) {
page.getItemsCountElement().getText().then(function (text) { return page.getItemsCountElement().getText()
assert.equal(text.trim(), textToAssert, 'the item count text was incorrect'); .then(function (text) {
}); assert.equal(text.trim(), textToAssert, 'the item count text was incorrect');
});
}; };
// tests for the presence of the 'completed' CSS class for the item at the given index // tests for the presence of the 'completed' CSS class for the item at the given index
this.assertItemAtIndexIsCompleted = function (index) { this.assertItemAtIndexIsCompleted = function (index) {
page.getItemElements().then(function (toDoItems) { return page.getItemElements()
toDoItems[index].getAttribute('class').then(function (cssClass) { .then(function (toDoItems) {
assert(cssClass.indexOf('completed') !== -1, return toDoItems[index].getAttribute('class');
'the item at index ' + index + ' should have been marked as completed'); })
.then(function (cssClass) {
var failMsg = 'the item at index ' + index + ' should have been marked as completed';
assert(cssClass.indexOf('completed') !== -1, failMsg);
}); });
});
}; };
this.assertItemAtIndexIsNotCompleted = function (index) { this.assertItemAtIndexIsNotCompleted = function (index) {
page.getItemElements().then(function (toDoItems) { return page.getItemElements()
toDoItems[index].getAttribute('class').then(function (cssClass) { .then(function (toDoItems) {
return toDoItems[index].getAttribute('class');
})
.then(function (cssClass) {
// the maria implementation uses an 'incompleted' CSS class which is redundant // the maria implementation uses an 'incompleted' CSS class which is redundant
// TODO: this should really be moved into the pageLaxMode // TODO: this should really be moved into the pageLaxMode
assert(cssClass.indexOf('completed') === -1 || cssClass.indexOf('incompleted') !== -1, var failMsg = 'the item at index ' + index + ' should not have been marked as completed';
'the item at index ' + index + ' should not have been marked as completed'); assert(cssClass.indexOf('completed') === -1 || cssClass.indexOf('incompleted') !== -1, failMsg);
}); });
});
}; };
this.assertFilterAtIndexIsSelected = function (selectedIndex) { this.assertFilterAtIndexIsSelected = function (selectedIndex) {
page.findByXpath(page.getSelectedFilterXPathByIndex(selectedIndex + 1)) return page.findByXpath(page.getSelectedFilterXPathByIndex(selectedIndex + 1))
.then(function (elm) { .then(function (elm) {
assert.notEqual(elm, undefined, 'the filter / route at index ' + selectedIndex + ' should have been selected'); var failMsg = 'the filter / route at index ' + selectedIndex + ' should have been selected';
}); assert.notEqual(elm, undefined, failMsg);
});
}; };
this.assertCompleteAllIsClear = function () { this.assertCompleteAllIsClear = function () {
page.getMarkAllCompletedCheckBox().then(function (markAllCompleted) { return page.getMarkAllCompletedCheckBox()
markAllCompleted.isSelected().then(function (isSelected) { .then(function (markAllCompleted) {
return markAllCompleted.isSelected();
})
.then(function (isSelected) {
assert(!isSelected, 'the mark-all-completed checkbox should be clear'); assert(!isSelected, 'the mark-all-completed checkbox should be clear');
}); });
});
}; };
this.assertCompleteAllIsChecked = function () { this.assertCompleteAllIsChecked = function () {
page.getMarkAllCompletedCheckBox().then(function (markAllCompleted) { return page.getMarkAllCompletedCheckBox()
markAllCompleted.isSelected().then(function (isSelected) { .then(function (markAllCompleted) {
return markAllCompleted.isSelected();
})
.then(function (isSelected) {
assert(isSelected, 'the mark-all-completed checkbox should be checked'); assert(isSelected, 'the mark-all-completed checkbox should be checked');
}); });
});
}; };
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment