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';
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,51 +210,57 @@ 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) {
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()
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()) !== -1) {
if (labels.indexOf(itemText.trim()) >= 0) {
return true;
}
......@@ -257,7 +268,6 @@ module.exports = function Page(browser) {
return false;
});
});
});
}, 5000);
};
......
This diff is collapsed.
......@@ -16,15 +16,16 @@ function TestOperations(page) {
function testIsVisible(elements, name) {
assert.equal(elements.length, 1);
elements[0].isDisplayed().then(function (isDisplayed) {
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,85 +36,105 @@ 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');
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) {
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) {
return page.getItemInputField().getText()
.then(function (inputFieldText) {
assert.equal(inputFieldText, text);
});
};
this.assertItemText = function (itemIndex, textToAssert) {
page.getItemLabelAtIndex(itemIndex).getText().then(function (text) {
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');
......@@ -129,53 +150,63 @@ function TestOperations(page) {
};
this.assertItemCountText = function (textToAssert) {
page.getItemsCountElement().getText().then(function (text) {
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))
return page.findByXpath(page.getSelectedFilterXPathByIndex(selectedIndex + 1))
.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 () {
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