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);
}; };
......
This diff is collapsed.
...@@ -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