This commit is contained in:
Th3NiKo 2019-12-06 12:30:24 +01:00
commit c120a9d1d1
11 changed files with 362 additions and 10 deletions

53
package-lock.json generated
View File

@ -347,6 +347,12 @@
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
},
"assertion-error": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
"dev": true
},
"async": {
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
@ -538,6 +544,20 @@
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
},
"chai": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
"integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==",
"dev": true,
"requires": {
"assertion-error": "^1.1.0",
"check-error": "^1.0.2",
"deep-eql": "^3.0.1",
"get-func-name": "^2.0.0",
"pathval": "^1.1.0",
"type-detect": "^4.0.5"
}
},
"chalk": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
@ -553,6 +573,12 @@
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
"dev": true
},
"check-error": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
"dev": true
},
"chokidar": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz",
@ -803,6 +829,15 @@
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
"dev": true
},
"deep-eql": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
"integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
"dev": true,
"requires": {
"type-detect": "^4.0.0"
}
},
"deep-is": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
@ -1166,6 +1201,12 @@
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true
},
"get-func-name": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
"dev": true
},
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
@ -2276,6 +2317,12 @@
"pinkie-promise": "^2.0.0"
}
},
"pathval": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz",
"integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=",
"dev": true
},
"pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
@ -2778,6 +2825,12 @@
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
},
"type-detect": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
"dev": true
},
"type-fest": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",

View File

@ -23,7 +23,9 @@
"@wdio/mocha-framework": "^5.16.5",
"@wdio/spec-reporter": "^5.16.5",
"@wdio/sync": "^5.16.5",
"chai": "^4.2.0",
"chromedriver": "^78.0.1",
"deepmerge": "^4.2.2",
"wdio-chromedriver-service": "^5.0.2"
},
"dependencies": {

View File

@ -1,6 +1,10 @@
exports.config = {
runner: 'local',
path: '/',
suites: {
login: ['./test/specs/suites/desktop/loginpage.test.js'],
subject: ['./test/specs/suites/desktop/subjectpage.test.js'],
},
specs: [
'./test/specs/**/*.js'
],
@ -11,7 +15,7 @@ exports.config = {
maxInstances: 5,
browserName: 'chrome',
'goog:chromeOptions': {
args: ['--no-sandbox', '--disable-dev-shm-usage','--headless','--start-maximized'],
args: ['--no-sandbox','--headless','--start-maximized'],
},
}],

168
test/specs/base/base.js Normal file
View File

@ -0,0 +1,168 @@
class Base {
click(selector, elementName) {
try {
$(selector).scrollIntoView({ block: 'center' });
$(selector).waitForEnabled();
$(selector).click();
console.log(`${elementName} was clicked`);
} catch (err) {
console.log(`${elementName} was not clicked. Exception: ${err}`);
}
}
clickNth(selector, position, elementName) {
try {
$$(selector)[position].scrollIntoView({ block: 'center' });
$$(selector)[position].waitForEnabled();
$$(selector)[position].click();
console.log(`${elementName} with position: ${position} was clicked`);
} catch (err) {
console.log(`${elementName} with position: ${position} was not clicked. Exception: ${err}`);
}
}
clearInput(selector) {
try {
const valueLength = $(selector).getValue().length;
const backSpaces = new Array(valueLength).fill('Backspace');
$(selector).setValue(backSpaces);
console.log(`${selector} has length: ${valueLength} and was cleared`);
} catch (e) {
console.log(`${selector} was not cleared with exception: ${e}`);
}
}
fillIn(selector, text, elementName) {
console.log(`${elementName} is displayed`);
try {
this.clearInput(selector);
$(selector).setValue(text);
console.log(`${text} was added to ${elementName}`);
} catch (err) {
console.log(`An exception occurred when adding a text to the element: ${err}`);
}
}
fillInNth(selectorList, position, text, elementName) {
try {
$$(selectorList)[position].setValue(text);
console.log(`${text} was added to ${elementName}`);
} catch (err) {
console.log(`An exception occurred when adding a text to the element: ${err}`);
}
}
getAttribute(selector, attribute, elementName) {
let attributeValue = null;
try {
console.log(`${elementName} was displayed`);
attributeValue = $(selector).getAttribute(attribute);
console.log(`${elementName} had value: ${attributeValue}`);
} catch (err) {
console.log(`Could not get ${elementName}. Exception: ${err}`);
}
return attributeValue;
}
getLinkFromElementsArray(selector, position, elementName) {
let href = null;
try {
href = $$(selector)[position].$('a').getAttribute('href').replace('%20', '_');
console.log(`Link for ${elementName} with position ${position} has value: ${href}`);
} catch (err) {
console.log(`Could not get link for ${elementName}. Exception: ${err}`);
}
return href;
}
isEnabled(selector, elementName) {
console.log(`${elementName} is displayed`);
const isEnabled = $(selector).isEnabled();
console.log(`${elementName} is enabled: ${isEnabled}`);
return isEnabled;
}
isDisplayed(selector, elementName, customTimeout) {
let isDisplayed = false;
try {
isDisplayed = $(selector).isDisplayed(customTimeout, true);
console.log(`${elementName} is displayed: ${isDisplayed}`);
} catch (err) {
console.log(`${elementName} is displayed: ${isDisplayed}. Exception: ${err}`);
}
return isDisplayed;
}
isNthDisplayed(selectorsList, position, elementName, customTimeout) {
let isDisplayed = false;
try {
isDisplayed = $$(selectorsList)[position].isDisplayed(customTimeout, true);
console.log(`${elementName} with position ${position} is displayed: ${isDisplayed}`);
} catch (err) {
console.log(`${elementName} with position ${position} is displayed: ${isDisplayed}. Exception: ${err}`);
}
return isDisplayed;
}
waitForDisplayed(selector, elementName) {
browser.waitUntil(() => {
try {
return $(selector).isDisplayed();
} catch (e) {
console.log(`${elementName} is not displayed. Exception: ${e}`);
return false;
}
}, 5000, `Expected ${selector} to be displayed after 5s`);
}
waitForNthElementDisplayed(selectorList, position, elementName) {
browser.waitUntil(() => {
try {
return $$(selectorList)[position].isDisplayed();
} catch (e) {
console.log(`${elementName} with position ${position} is not displayed. Exception: ${e}`);
return false;
}
}, 5000, `Expected ${elementName} with position ${position} to be displayed after 5s`, 500);
}
waitForNotDisplayed(selector, elementName, customTimeout) {
browser.waitUntil(() => {
try {
return !$(selector).isDisplayed(customTimeout, true);
} catch (e) {
console.log(`${elementName} is still displayed. Exception: ${e}`);
return true;
}
}, 5000, `Expected ${elementName} to be displayed after 5s`, 500);
}
waitForEnabled(selector, elementName) {
browser.waitUntil(() => {
try {
return !$(selector).isEnabled();
} catch (e) {
console.log(`${elementName} is not enabled. Exception: ${e}`);
return true;
}
}, 5000, `Expected ${selector} to be enabled after 5s`, 500);
}
isChildDisplayedForParent(parentElementSelector, position, childElementSelector, childElementName) {
const isDisplayed = $$(parentElementSelector)[position].$(childElementSelector).isDisplayed();
console.log(`${childElementName} is displayed: ${isDisplayed}`);
return isDisplayed;
}
wait(timeout) {
setTimeout(() => { console.log(`This is a explicit wait of ${timeout}`); }, timeout);
}
}
module.exports = new Base();

11
test/specs/base/common.js Normal file
View File

@ -0,0 +1,11 @@
class Common {
constructor() {
this.loremIpsum = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.';
this.ecceIpsum = 'Snare hope zarathustra pious society. Ascetic ocean snare chaos endless war ultimate insofar right god spirit. Right free pinnacle philosophy overcome self philosophy. Right passion value dead truth faithful deceptions. Marvelous hatred derive superiority deceptions justice overcome oneself zarathustra gains.';
this.bestNotesLink = 'http://bestnotes.pythonanywhere.com/bestnotes/';
this.errorLoginMessage = 'Nieprawidłowy adres e-mail lub hasło. Spróbuj ponownie!';
}
}
module.exports = new Common();

View File

@ -0,0 +1,14 @@
const base = require('./base');
const Login = require('../components/login');
class Navigation {
constructor() {
this.loginUrl = 'http://bestnotes.pythonanywhere.com/bestnotes/accounts/login/';
}
toLoginPage() {
browser.url(this.loginUrl);
return new Login();
}
}
module.exports = new Navigation();

View File

@ -0,0 +1,35 @@
const path = require('path');
const base = require('../base/base');
class Login {
constructor() {
this.loginForm = '.login-form-2';
this.emailField = '#id_username';
this.passwordField = '#id_password';
this.loginButton = '.btnSubmit';
this.warringMessage = '.text-warning';
}
isLoginFormDisplayed() {
base.waitForDisplayed(this.loginForm);
return base.isDisplayed(this.loginForm);
}
fillCredentials(selector, text) {
base.fillIn(selector, text, 'Fill credentials');
return this;
}
clickLoginButton() {
base.click(this.loginButton, 'Login button');
return this;
}
getErrorMessage() {
base.waitForDisplayed(this.warringMessage);
return base.getAttribute(this.warringMessage, 'textContent', 'Error message text');
}
}
module.exports = Login;

View File

@ -0,0 +1,14 @@
const path = require('path');
const base = require('../base/base');
class Subject {
constructor() {
this.subjectNavbar = '.navbar';
}
isNavbarDisplayed() {
base.waitForDisplayed(this.subjectNavbar);
return base.isDisplayed(this.subjectNavbar);
}
}
module.exports = Subject;

View File

@ -0,0 +1,60 @@
const { addStep } = require('@wdio/allure-reporter').default;
const { expect } = require('chai');
const common = require('../../base/common');
const navigate = require('../../base/navigation');
const Login = require('../../components/login');
const Subject = require('../../components/subject');
const testName = 'test';
const correctName = 'admin';
describe('Login page in BestNotes', () => {
it('should be displayed', () => {
const login = new Login();
addStep('Redirect to Login Page');
navigate.toLoginPage();
addStep('Check if Login Form is displayed and URL ');
expect(browser.getUrl(), 'Post details URL should include post ID').to.equal(common.bestNotesLink + 'accounts/login/');
expect(login.isLoginFormDisplayed(), 'Login form should be displayed').to.be.true;
})
it('shouldnt logged user with incorrect credentials', () => {
const login = new Login();
addStep('Redirect to Login Page');
navigate.toLoginPage();
addStep('Check if Login Form is displayed');
expect(login.isLoginFormDisplayed(), 'Login form should be displayed').to.be.true;
addStep('Fill credentials and try to login');
login.fillCredentials(login.emailField, testName);
login.fillCredentials(login.passwordField, testName);
login.clickLoginButton();
addStep('Check if the error message is displayed');
expect(login.getErrorMessage(), 'Message about wrong credentials should be displayed').to.equal(common.errorLoginMessage);
})
it('should logged user with correct credentials', () => {
const login = new Login();
addStep('Redirect to Login Page');
navigate.toLoginPage();
addStep('Check if Login Form is displayed');
expect(login.isLoginFormDisplayed(), 'Login form should be displayed').to.be.true;
addStep('Fill credentials and try to login');
login.fillCredentials(login.emailField, correctName);
login.fillCredentials(login.passwordField, correctName);
login.clickLoginButton();
addStep('Check if the page is displayed and URL matches');
expect(browser.getUrl(), 'Post details URL should include post ID').to.equal(common.bestNotesLink + 'subject/');
expect(new Subject().isNavbarDisplayed(), 'Subject page should be displayed').to.be.true;
})
});

View File

@ -1,9 +0,0 @@
const assert = require('assert')
describe('webdriver.io page', () => {
it('should have the right title', () => {
browser.url('https://webdriver.io')
const title = browser.getTitle()
assert.strictEqual(title, 'WebdriverIO · Next-gen WebDriver test framework for Node.js')
})
})