Commit 951eb70b authored by Marcel Hoyer's avatar Marcel Hoyer Committed by Colin Eberhardt

Correcting asynchronous testing

removes unnecessary .then() chaining in test.js as selenium-webdriver already queues calls internally

fixed confusing inverted use of idSelector variable

promisified all tests

promisified test.launchBrowser() and global test hooks

promisified test.closeBrowser()

promisified test.createStandardItems()

🛀 streamlined testOps to always return the promise and flattened out the thens

fixed testOps.assertClearCompleteButtonText() to wait for visible clear-complete button before asserting

fixed testOps.assertClearCompleteButtonIsVisible() to lazy wait for visible clear-complete button

renamed testOps.assertFocussedElementId() to .assertFocussedElement() and streamlined code

fixed page.clickMarkAllCompletedCheckBox() to return inner promise

fixed page.enterItem() to return the promise and flattened out the thens

renamed page.getFocussedElementName() with .getFocussedElementIdOrClass()

fixed page.ensureAppIsVisible() to wait for 'new-todo' element instead of 'main' as some frameworks build the contents after DOM-ready

fixed page.clickClearCompleteButton() to wait for actual button to display before clicking

extracted page.waitForVisibleElement() helper function
parent 4de8afb2
'use strict';
var webdriver = require('selenium-webdriver');
var idSelectors = false;
var idSelectors = true;
module.exports = function Page(browser) {
......@@ -16,35 +16,35 @@ module.exports = function Page(browser) {
};
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 () {
return !idSelectors ? '//section[@id="main"]' : '//section[contains(@class, "main")]';
return idSelectors ? '//section[@id="main"]' : '//section[contains(@class, "main")]';
};
this.getFooterSectionXpath = function () {
return !idSelectors ? '//footer[@id="footer"]' : '//footer[contains(@class, "footer")]';
return idSelectors ? '//footer[@id="footer"]' : '//footer[contains(@class, "footer")]';
};
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 () {
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 () {
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 () {
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 () {
return !idSelectors ? '//*[@id="filters"]' : '//*[contains(@class, "filters")]';
return idSelectors ? '//*[@id="filters"]' : '//*[contains(@class, "filters")]';
};
this.getFilterXpathByIndex = function (index) {
......@@ -115,9 +115,9 @@ module.exports = function Page(browser) {
return this.getActiveElement().getTagName();
};
this.getFocussedElementName = function () {
this.getFocussedElementIdOrClass = function () {
return this.getActiveElement()
.getAttribute(!idSelectors ? 'id' : 'class');
.getAttribute(idSelectors ? 'id' : 'class');
};
this.getEditInputForItemAtIndex = function (index) {
......@@ -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 () {
var self = this;
var ret;
return this.getItemLabels()
.then(function (elms) {
return elms.map(function (elm, i) {
......@@ -186,18 +201,8 @@ module.exports = function Page(browser) {
})
.then(function (elms) {
return webdriver.promise.filter(elms, function (elmIndex) {
return browser.wait(function () {
return self.tryGetItemLabelAtIndex(elmIndex).isDisplayed()
.then(function (v) {
ret = v;
return true;
})
.thenCatch(function () {
return false;
});
}, 5000)
.then(function () {
return ret;
return self.waitForVisibleElement(function () {
return self.tryGetItemLabelAtIndex(elmIndex);
});
});
});
......@@ -205,58 +210,63 @@ module.exports = function Page(browser) {
// ----------------- page actions
this.ensureAppIsVisible = function () {
return browser.findElements(webdriver.By.css('#todoapp'))
.then(function (elms) {
if (elms.length > 0) {
return true;
} else {
return browser.findElements(webdriver.By.css('.todoapp'));
}
})
.then(function (elms) {
if (elms === true) {
return true;
}
var self = this;
return browser.wait(function () {
// try to find main element by ID
return browser.isElementPresent(webdriver.By.css('.new-todo'))
.then(function (foundByClass) {
if (foundByClass) {
idSelectors = false;
return true;
}
if (elms.length) {
idSelectors = true;
return true;
// try to find main element by CSS class
return browser.isElementPresent(webdriver.By.css('#new-todo'));
});
}, 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 () {
return this.getMarkAllCompletedCheckBox().then(function (checkbox) {
checkbox.click();
return checkbox.click();
});
};
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) {
var self = this;
browser.wait(function () {
return self.getItemInputField().then(function (textField) {
return textField.sendKeys(itemText, webdriver.Key.ENTER)
.then(function () {
return textField;
});
}).then(function (textField) {
return self.getVisibleLabelText()
.then(function (labels) {
if (labels.indexOf(itemText.trim()) !== -1) {
return true;
}
return textField.clear().then(function () {
return false;
});
});
return browser.wait(function () {
var textField;
return self.getItemInputField().then(function (itemInputField) {
textField = itemInputField;
return textField.sendKeys(itemText, webdriver.Key.ENTER);
})
.then(function () { return self.getVisibleLabelText(); })
.then(function (labels) {
if (labels.indexOf(itemText.trim()) >= 0) {
return true;
}
return textField.clear().then(function () {
return false;
});
});
}, 5000);
};
......
......@@ -15,13 +15,18 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod
var browser, testOps, page;
// a number of tests use this set of ToDo items.
function createStandardItems() {
function createStandardItems(done) {
page.enterItem(TODO_ITEM_ONE);
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();
chromeOptions.addArguments('no-sandbox');
......@@ -30,146 +35,162 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod
}
browser = new webdriver.Builder()
.withCapabilities({
browserName: browserName
})
.setChromeOptions(chromeOptions)
.build();
.withCapabilities({browserName: browserName})
.setChromeOptions(chromeOptions)
.build();
browser.get(baseUrl);
page = laxMode ? new PageLaxMode(browser) : new Page(browser);
testOps = new TestOperations(page);
// for apps that use require, we have to wait a while for the dependencies to
// be loaded. There must be a more elegant solution than this!
browser.sleep(200);
return page.ensureAppIsVisible()
.then(function () {
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() {
browser.quit();
function closeBrowser(done) {
return browser
.quit()
.then(function () {
if (done instanceof Function) {
done();
};
});
}
if (speedMode) {
test.before(function () {
launchBrowser();
});
test.after(function () {
closeBrowser();
});
test.beforeEach(function () {
page.getItemElements().then(function (items) {
if (items.length > 0) {
test.before(launchBrowser);
test.after(closeBrowser);
test.beforeEach(function (done) {
return page.getItemElements()
.then(function (items) {
if (items.length == 0) { return; }
// find any items that are not complete
page.getNonCompletedItemElements().then(function (nonCompleteItems) {
if (nonCompleteItems.length > 0) {
page.clickMarkAllCompletedCheckBox();
}
page.clickClearCompleteButton();
});
}
});
page.getNonCompletedItemElements()
.then(function (nonCompleteItems) {
if (nonCompleteItems.length > 0) {
return page.clickMarkAllCompletedCheckBox();
}
})
return page.clickClearCompleteButton();
})
.then(function () { done(); });
});
} else {
test.beforeEach(function () {
launchBrowser();
page.ensureAppIsVisible();
});
test.afterEach(function () {
(new webdriver.WebDriver.Logs(browser))
.get('browser')
.then(function (v) {
if (v && v.length) {
console.log(v);
}
});
closeBrowser();
test.beforeEach(launchBrowser);
test.afterEach(function (done) {
printCapturedLogs()
.then(function () {
return closeBrowser(done);
})
});
}
test.describe('When page is initially opened', function () {
test.it('should focus on the todo input field', function () {
testOps.assertFocussedElementId('new-todo');
test.it('should focus on the todo input field', function (done) {
testOps.assertFocussedElement('new-todo')
.then(function () { done(); });
});
});
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.assertMainSectionIsHidden();
testOps.assertFooterIsHidden();
testOps.assertFooterIsHidden()
.then(function () { done(); });
});
});
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);
testOps.assertItems([TODO_ITEM_ONE]);
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);
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();
testOps.assertItemCount(3);
testOps.assertItemText(0, TODO_ITEM_ONE);
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 + ' ');
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);
testOps.assertMainSectionIsVisible();
testOps.assertFooterIsVisible();
testOps.assertFooterIsVisible()
.then(function () { done(); });
});
});
test.describe('Mark all as completed', function () {
test.beforeEach(function () {
createStandardItems();
});
test.beforeEach(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();
testOps.assertItemAtIndexIsCompleted(0);
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
page.toggleItemAtIndex(0);
page.toggleItemAtIndex(1);
page.toggleItemAtIndex(2);
// 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();
testOps.assertItemAtIndexIsNotCompleted(0);
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();
testOps.assertCompleteAllIsChecked();
// all items are complete, now mark one as not-complete
......@@ -178,12 +199,13 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod
// now mark as complete, so that once again all items are completed
page.toggleItemAtIndex(0);
testOps.assertCompleteAllIsChecked();
testOps.assertCompleteAllIsChecked()
.then(function () { done(); });
});
});
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_TWO);
......@@ -193,10 +215,11 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod
page.toggleItemAtIndex(1);
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_TWO);
......@@ -206,102 +229,101 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod
page.toggleItemAtIndex(0);
testOps.assertItemAtIndexIsNotCompleted(0);
testOps.assertItemAtIndexIsNotCompleted(1);
testOps.assertItemAtIndexIsNotCompleted(1)
.then(function () { done(); });
});
});
test.describe('Editing', function () {
test.beforeEach(function () {
test.describe('Editing', function (done) {
test.beforeEach(function (done) {
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.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.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);
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');
// click a toggle button so that the blur() event is fired
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);
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);
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);
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.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);
testOps.assertItemCountText('1 item left');
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.beforeEach(function () {
createStandardItems();
});
test.beforeEach(createStandardItems);
test.it('should display the correct text', function () {
test.it('should display the correct text', function (done) {
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.clickClearCompleteButton();
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);
testOps.assertClearCompleteButtonIsVisible();
page.clickClearCompleteButton();
testOps.assertClearCompleteButtonIsHidden();
testOps.assertClearCompleteButtonIsHidden()
.then(function () { done(); });
});
});
test.describe('Persistence', function () {
test.it('should persist its data', function () {
// set up state
page.enterItem(TODO_ITEM_ONE);
page.enterItem(TODO_ITEM_TWO);
page.toggleItemAtIndex(1);
test.it('should persist its data', function (done) {
function stateTest() {
// wait until things are visible
browser.wait(function () {
......@@ -309,13 +331,16 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod
return labels.length > 0;
});
}, 5000);
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO]);
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();
// navigate away and back again
......@@ -323,66 +348,60 @@ module.exports.todoMVCTest = function (frameworkName, baseUrl, speedMode, laxMod
browser.get(baseUrl);
// repeat the state test
stateTest();
stateTest()
.then(function () { done(); });
});
});
test.describe('Routing', function () {
test.beforeEach(function () {
createStandardItems();
});
test.it('should allow me to display active items', function () {
test.beforeEach(createStandardItems);
test.it('should allow me to display active items', function (done) {
page.toggleItemAtIndex(1);
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.filterByActiveItems();
page.filterByCompletedItems();
// should show completed items
testOps.assertItems([TODO_ITEM_TWO]);
// then active items
page.back();
testOps.assertItems([TODO_ITEM_TWO]);// should show completed items
page.back(); // then active items
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_THREE]);
// then all items
page.back();
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO, TODO_ITEM_THREE]);
page.back(); // then all items
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO, TODO_ITEM_THREE])
.then(function () { done(); });
});
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.filterByCompletedItems();
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);
// apply the other filters first, before returning to the 'all' state
page.filterByActiveItems();
page.filterByCompletedItems();
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
testOps.assertFilterAtIndexIsSelected(0);
page.filterByActiveItems();
testOps.assertFilterAtIndexIsSelected(1);
page.filterByCompletedItems();
testOps.assertFilterAtIndexIsSelected(2);
testOps.assertFilterAtIndexIsSelected(2)
.then(function () { done(); });
});
});
});
......
......@@ -16,15 +16,16 @@ function TestOperations(page) {
function testIsVisible(elements, name) {
assert.equal(elements.length, 1);
elements[0].isDisplayed().then(function (isDisplayed) {
assert(isDisplayed, 'the ' + name + ' element should be displayed');
});
return elements[0].isDisplayed()
.then(function (isDisplayed) {
assert(isDisplayed, 'the ' + name + ' element should be displayed');
});
}
this.assertNewInputNotFocused = function () {
return page.getFocussedElementName()
.then(function (name) {
assert.notEqual(name, 'new-todo');
return page.getFocussedElementIdOrClass()
.then(function (focussedElementIdOrClass) {
assert.equal(focussedElementIdOrClass.indexOf('new-todo'), -1);
});
};
......@@ -35,147 +36,177 @@ function TestOperations(page) {
});
};
this.assertFocussedElementId = function (expectedId) {
page.getFocussedElementName().then(function (id) {
assert.notEqual(id.indexOf(expectedId), -1, 'The focused element did not have the expected id ' + expectedId);
});
this.assertFocussedElement = function (expectedIdentifier) {
return page.getFocussedElementIdOrClass()
.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 () {
page.tryGetClearCompleteButton().then(function (element) {
testIsHidden(element, 'clear completed items button');
}, function (_error) {
assert(_error.code === 7, 'error accessing clear completed items button, error: ' + _error.message);
});
return page.tryGetClearCompleteButton()
.then(function (element) {
return testIsHidden(element, 'clear completed items button');
}, function (_error) {
assert(_error.code === 7, 'error accessing clear completed items button, error: ' + _error.message);
});
};
this.assertClearCompleteButtonIsVisible = function () {
page.tryGetClearCompleteButton().then(function (element) {
testIsVisible([element], 'clear completed items button');
});
return page.waitForVisibleElement(function () {
return page.tryGetClearCompleteButton();
})
.then(function (clearCompleteButton) {
assert(clearCompleteButton, 'the clear completed items button element should be displayed');
});
};
this.assertItemCount = function (itemCount) {
page.getItemElements().then(function (toDoItems) {
assert.equal(toDoItems.length, itemCount,
itemCount + ' items expected in the todo list, ' + toDoItems.length + ' items observed');
});
return page.getItemElements()
.then(function (toDoItems) {
assert.equal(toDoItems.length, itemCount,
itemCount + ' items expected in the todo list, ' + toDoItems.length + ' items observed');
});
};
this.assertClearCompleteButtonText = function (buttonText) {
return page.tryGetClearCompleteButton()
.getText().then(function (text) {
assert.equal(text, buttonText);
});
return page.waitForVisibleElement(function () {
return page.tryGetClearCompleteButton();
})
.then(function (clearCompleteButton) {
return clearCompleteButton.getText();
})
.then(function (text) {
return assert.equal(text, buttonText);
});
};
this.assertMainSectionIsHidden = function () {
page.tryGetMainSectionElement().then(function (mainSection) {
testIsHidden(mainSection, 'main');
});
return page.tryGetMainSectionElement()
.then(function (mainSection) {
return testIsHidden(mainSection, 'main');
});
};
this.assertFooterIsHidden = function () {
page.tryGetFooterElement().then(function (footer) {
testIsHidden(footer, 'footer');
});
return page.tryGetFooterElement()
.then(function (footer) {
return testIsHidden(footer, 'footer');
});
};
this.assertMainSectionIsVisible = function () {
page.tryGetMainSectionElement().then(function (mainSection) {
testIsVisible(mainSection, 'main');
});
return page.tryGetMainSectionElement()
.then(function (mainSection) {
return testIsVisible(mainSection, 'main');
});
};
//TODO: fishy!
this.assertItemToggleIsHidden = function (index) {
page.tryGetToggleForItemAtIndex(index).then(function (toggleItem) {
testIsHidden(toggleItem, 'item-toggle');
});
return page.tryGetToggleForItemAtIndex(index)
.then(function (toggleItem) {
return testIsHidden(toggleItem, 'item-toggle');
});
};
this.assertItemLabelIsHidden = function (index) {
page.tryGetItemLabelAtIndex(index).then(function (toggleItem) {
testIsHidden(toggleItem, 'item-label');
});
return page.tryGetItemLabelAtIndex(index)
.then(function (toggleItem) {
return testIsHidden(toggleItem, 'item-label');
});
};
this.assertFooterIsVisible = function () {
page.tryGetFooterElement().then(function (footer) {
testIsVisible(footer, 'footer');
});
return page.tryGetFooterElement()
.then(function (footer) {
return testIsVisible(footer, 'footer');
});
};
this.assertItemInputFieldText = function (text) {
page.getItemInputField().getText().then(function (inputFieldText) {
assert.equal(inputFieldText, text);
});
return page.getItemInputField().getText()
.then(function (inputFieldText) {
assert.equal(inputFieldText, text);
});
};
this.assertItemText = function (itemIndex, textToAssert) {
page.getItemLabelAtIndex(itemIndex).getText().then(function (text) {
assert.equal(text, textToAssert,
'A todo item with text \'' + textToAssert + '\' was expected at index ' +
itemIndex + ', the text \'' + text + '\' was observed');
});
return page.getItemLabelAtIndex(itemIndex).getText()
.then(function (text) {
assert.equal(text, textToAssert,
'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
this.assertItems = function (textArray) {
return page.getVisibleLabelText()
.then(function (visibleText) {
assert.deepEqual(visibleText.sort(), textArray.sort());
});
.then(function (visibleText) {
assert.deepEqual(visibleText.sort(), textArray.sort());
});
};
this.assertItemCountText = function (textToAssert) {
page.getItemsCountElement().getText().then(function (text) {
assert.equal(text.trim(), textToAssert, 'the item count text was incorrect');
});
return page.getItemsCountElement().getText()
.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
this.assertItemAtIndexIsCompleted = function (index) {
page.getItemElements().then(function (toDoItems) {
toDoItems[index].getAttribute('class').then(function (cssClass) {
assert(cssClass.indexOf('completed') !== -1,
'the item at index ' + index + ' should have been marked as completed');
return page.getItemElements()
.then(function (toDoItems) {
return toDoItems[index].getAttribute('class');
})
.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) {
page.getItemElements().then(function (toDoItems) {
toDoItems[index].getAttribute('class').then(function (cssClass) {
return page.getItemElements()
.then(function (toDoItems) {
return toDoItems[index].getAttribute('class');
})
.then(function (cssClass) {
// the maria implementation uses an 'incompleted' CSS class which is redundant
// TODO: this should really be moved into the pageLaxMode
assert(cssClass.indexOf('completed') === -1 || cssClass.indexOf('incompleted') !== -1,
'the item at index ' + index + ' should not have been marked as completed');
var failMsg = '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) {
page.findByXpath(page.getSelectedFilterXPathByIndex(selectedIndex + 1))
.then(function (elm) {
assert.notEqual(elm, undefined, 'the filter / route at index ' + selectedIndex + ' should have been selected');
});
return page.findByXpath(page.getSelectedFilterXPathByIndex(selectedIndex + 1))
.then(function (elm) {
var failMsg = 'the filter / route at index ' + selectedIndex + ' should have been selected';
assert.notEqual(elm, undefined, failMsg);
});
};
this.assertCompleteAllIsClear = function () {
page.getMarkAllCompletedCheckBox().then(function (markAllCompleted) {
markAllCompleted.isSelected().then(function (isSelected) {
return page.getMarkAllCompletedCheckBox()
.then(function (markAllCompleted) {
return markAllCompleted.isSelected();
})
.then(function (isSelected) {
assert(!isSelected, 'the mark-all-completed checkbox should be clear');
});
});
};
this.assertCompleteAllIsChecked = function () {
page.getMarkAllCompletedCheckBox().then(function (markAllCompleted) {
markAllCompleted.isSelected().then(function (isSelected) {
return page.getMarkAllCompletedCheckBox()
.then(function (markAllCompleted) {
return markAllCompleted.isSelected();
})
.then(function (isSelected) {
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