forked from Wavyzz/dolibarr
Feature files created to login, add users and logout
Co-authored-by: Yamuna Adhikari <adhikariamuna4444@gmail.com>
This commit is contained in:
11
.gitignore
vendored
11
.gitignore
vendored
@@ -41,3 +41,14 @@ htdocs/includes/sebastian/
|
|||||||
htdocs/includes/squizlabs/
|
htdocs/includes/squizlabs/
|
||||||
htdocs/includes/webmozart/
|
htdocs/includes/webmozart/
|
||||||
htdocs/.well-known/apple-developer-merchantid-domain-association
|
htdocs/.well-known/apple-developer-merchantid-domain-association
|
||||||
|
|
||||||
|
# Node Modules
|
||||||
|
build/yarn-error.log
|
||||||
|
build/node_modules/
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
#yarn
|
||||||
|
yarn.lock
|
||||||
|
|
||||||
|
#package-lock
|
||||||
|
package-lock.json
|
||||||
|
|||||||
29
nightwatch.conf.js
Normal file
29
nightwatch.conf.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
const admin_username = process.env.ADMIN_USERNAME || 'dolibarr';
|
||||||
|
const admin_password = process.env.ADMIN_PASSWORD || 'password';
|
||||||
|
const launch_url = process.env.LAUNCH_URL || 'http://localhost/dolibarr/htdocs/';
|
||||||
|
const dol_api_key = process.env.DOLAPIKEY || 'superadminuser';
|
||||||
|
module.exports = {
|
||||||
|
page_objects_path : './test/acceptance/pageObjects/', // jshint ignore:line
|
||||||
|
src_folders : ['test'],
|
||||||
|
|
||||||
|
test_settings : {
|
||||||
|
default : {
|
||||||
|
selenium_host : '127.0.0.1',
|
||||||
|
launchUrl : launch_url,
|
||||||
|
globals : {
|
||||||
|
backend_url : launch_url,
|
||||||
|
adminUsername : admin_username,
|
||||||
|
adminPassword : admin_password,
|
||||||
|
dolApiKey : dol_api_key
|
||||||
|
},
|
||||||
|
desiredCapabilities : {
|
||||||
|
browserName : 'chrome',
|
||||||
|
javascriptEnabled : true,
|
||||||
|
chromeOptions : {
|
||||||
|
args : ['disable-gpu'],
|
||||||
|
w3c : false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
13
package.json
Normal file
13
package.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"devDependencies": {
|
||||||
|
"cucumber": "^6.0.5",
|
||||||
|
"nightwatch": "^1.4.1",
|
||||||
|
"nightwatch-api": "^3.0.1"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test:e2e": "node_modules/cucumber/bin/cucumber-js --require test/acceptance/index.js --require test/acceptance/stepDefinitions"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"node-fetch": "^2.6.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
86
test/acceptance/features/addUsers.feature
Normal file
86
test/acceptance/features/addUsers.feature
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
Feature: Add user
|
||||||
|
As an admin
|
||||||
|
I want to add users
|
||||||
|
So that the authorized access is possible
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the administrator has logged in using the webUI
|
||||||
|
And the administrator has browsed to the new users page
|
||||||
|
|
||||||
|
Scenario: Admin adds user without permission
|
||||||
|
When the admin creates user with following details
|
||||||
|
| last name | Potter |
|
||||||
|
| login | harrypotter@gmail.com |
|
||||||
|
| password | password |
|
||||||
|
Then new user "Potter" should be created
|
||||||
|
And message "This user has no permissions defined" should be displayed in the webUI
|
||||||
|
|
||||||
|
Scenario Outline: Admin adds user with permission
|
||||||
|
When the admin creates user with following details
|
||||||
|
| last name | Potter |
|
||||||
|
| login | harrypotter@gmail.com |
|
||||||
|
| password | password |
|
||||||
|
| administrator | <administrator> |
|
||||||
|
| gender | <gender> |
|
||||||
|
Then message "This user has no permissions defined" <shouldOrShouldNot> be displayed in the webUI
|
||||||
|
And new user "Potter" should be created
|
||||||
|
Examples:
|
||||||
|
| administrator | gender | shouldOrShouldNot |
|
||||||
|
| No | | should |
|
||||||
|
| No | Man | should |
|
||||||
|
| No | Woman | should |
|
||||||
|
| Yes | | should not |
|
||||||
|
| Yes | Man | should not |
|
||||||
|
| Yes | Woman | should not |
|
||||||
|
|
||||||
|
Scenario Outline: Admin adds user with last name as special characters
|
||||||
|
When the admin creates user with following details
|
||||||
|
| last name | <last name> |
|
||||||
|
| login | harry |
|
||||||
|
| password | password |
|
||||||
|
Then message "This user has no permissions defined" should be displayed in the webUI
|
||||||
|
And new user "<last name>" should be created
|
||||||
|
Examples:
|
||||||
|
| last name |
|
||||||
|
| swi@ |
|
||||||
|
| g!!@%ui |
|
||||||
|
| swikriti@h |
|
||||||
|
| !@#$%^&*()-_+=[]{}:;,.<>?~ |
|
||||||
|
| $w!kr!t! |
|
||||||
|
| España§àôœ€ |
|
||||||
|
| नेपाली |
|
||||||
|
| सिमप्ले $%#?&@name.txt |
|
||||||
|
|
||||||
|
Scenario Outline: Admin adds user with incomplete essential credentials
|
||||||
|
When the admin creates user with following details
|
||||||
|
| last name | <last name> |
|
||||||
|
| login | <login> |
|
||||||
|
| password | <password> |
|
||||||
|
Then message "<message>" should be displayed in the webUI
|
||||||
|
And new user "<last name>" should not be created
|
||||||
|
Examples:
|
||||||
|
| last name | login | password | message |
|
||||||
|
| | | | Name is not defined.\nLogin is not defined. |
|
||||||
|
| Joseph | | | Login is not defined. |
|
||||||
|
| | john@gmail.com | | Name is not defined. |
|
||||||
|
| Joseph | | hihi | Login is not defined. |
|
||||||
|
|
||||||
|
Scenario: Admin adds user with incomplete essential credentials
|
||||||
|
When the admin creates user with following details
|
||||||
|
| last name | Doe |
|
||||||
|
| login | John |
|
||||||
|
| password | |
|
||||||
|
Then message "This user has no permissions defined" should be displayed in the webUI
|
||||||
|
And new user "Doe" should be created
|
||||||
|
|
||||||
|
Scenario: Admin tries to add user with pre-existing login credential
|
||||||
|
Given a user has been created with following details
|
||||||
|
| login | last name | password |
|
||||||
|
| Tyler | Joseph | pass1234 |
|
||||||
|
And the administrator has browsed to the new users page
|
||||||
|
When the admin creates user with following details
|
||||||
|
| last name | Dun |
|
||||||
|
| login | Tyler |
|
||||||
|
| password | pass1234 |
|
||||||
|
Then message "Login already exists." should be displayed in the webUI
|
||||||
|
And new user "Dun" should not be created
|
||||||
29
test/acceptance/features/listUsers.feature
Normal file
29
test/acceptance/features/listUsers.feature
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
Feature: list users
|
||||||
|
As an admin user
|
||||||
|
I want to view the list of users
|
||||||
|
So that I can manage users
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the administrator has logged in using the webUI
|
||||||
|
|
||||||
|
Scenario: Admin user should be able to see list of created users when no new users are created
|
||||||
|
When the administrator browses to the list of users page using the webUI
|
||||||
|
Then following users should be displayed in the users list
|
||||||
|
| login | last name |
|
||||||
|
| dolibarr | SuperAdmin |
|
||||||
|
And the number of created users should be 1
|
||||||
|
|
||||||
|
Scenario: Admin user should be able to see number of created users
|
||||||
|
Given the admin has created the following users
|
||||||
|
| login | last name | password |
|
||||||
|
| Harry | Potter | hello123 |
|
||||||
|
| Hermoine | Granger | hello123 |
|
||||||
|
| Ron | Weasley | hello123 |
|
||||||
|
When the administrator browses to the list of users page using the webUI
|
||||||
|
Then following users should be displayed in the users list
|
||||||
|
| login | last name |
|
||||||
|
| dolibarr | SuperAdmin |
|
||||||
|
| Harry | Potter |
|
||||||
|
| Hermoine | Granger |
|
||||||
|
| Ron | Weasley |
|
||||||
|
And the number of created users should be 4
|
||||||
27
test/acceptance/features/login.feature
Normal file
27
test/acceptance/features/login.feature
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
Feature: user login
|
||||||
|
As a user/admin
|
||||||
|
I want to login to my account
|
||||||
|
So that I can have access to my functionality
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the user has browsed to the login page
|
||||||
|
|
||||||
|
Scenario: Admin user should be able to login successfully
|
||||||
|
When user logs in with username "dolibarr" and password "password"
|
||||||
|
Then the user should be directed to the homepage
|
||||||
|
|
||||||
|
Scenario: Admin user with empty credentials should not be able to login
|
||||||
|
When user logs in with username "" and password ""
|
||||||
|
Then the user should not be able to login
|
||||||
|
|
||||||
|
Scenario Outline: user logs in with invalid credentials
|
||||||
|
When user logs in with username "<username>" and password "<password>"
|
||||||
|
Then the user should not be able to login
|
||||||
|
And error message "Bad value for login or password" should be displayed in the webUI
|
||||||
|
Examples:
|
||||||
|
| username | password |
|
||||||
|
| dolibar | pass |
|
||||||
|
| dolibarr | passw |
|
||||||
|
| dolibar | |
|
||||||
|
| dolibarr | |
|
||||||
|
| dolibar | password |
|
||||||
10
test/acceptance/features/logout.feature
Normal file
10
test/acceptance/features/logout.feature
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Feature: user logs out
|
||||||
|
As a user
|
||||||
|
I want to log out of my account
|
||||||
|
So that I can protect my work, identity and be assured of my privacy
|
||||||
|
|
||||||
|
Scenario: User can logout
|
||||||
|
Given the administrator has logged in using the webUI
|
||||||
|
When the user opens the user profile using the webUI
|
||||||
|
And the user logs out using the webUI
|
||||||
|
Then the user should be logged out successfully
|
||||||
14
test/acceptance/index.js
Normal file
14
test/acceptance/index.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
const { setDefaultTimeout, After, Before } = require('cucumber')
|
||||||
|
const { createSession, closeSession, startWebDriver, stopWebDriver } = require('nightwatch-api')
|
||||||
|
|
||||||
|
setDefaultTimeout(60000)
|
||||||
|
|
||||||
|
Before(async () => {
|
||||||
|
await startWebDriver();
|
||||||
|
await createSession();
|
||||||
|
})
|
||||||
|
|
||||||
|
After(async () => {
|
||||||
|
await closeSession();
|
||||||
|
await stopWebDriver();
|
||||||
|
})
|
||||||
128
test/acceptance/pageObjects/addUsersPage.js
Normal file
128
test/acceptance/pageObjects/addUsersPage.js
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
const util = require('util');
|
||||||
|
module.exports = {
|
||||||
|
url: function () {
|
||||||
|
return this.api.launchUrl + 'user/card.php?leftmenu=users&action=create';
|
||||||
|
},
|
||||||
|
|
||||||
|
commands: [
|
||||||
|
{
|
||||||
|
adminCreatesUser: async function (dataTable) {
|
||||||
|
const userDetails = dataTable.rowsHash();
|
||||||
|
let administrator = userDetails['administrator'];
|
||||||
|
let gender = userDetails['gender'];
|
||||||
|
await this.waitForElementVisible('@newUserAddOption')
|
||||||
|
.useXpath()
|
||||||
|
.waitForElementVisible('@lastnameField')
|
||||||
|
.clearValue('@lastnameField')
|
||||||
|
.setValue('@lastnameField', userDetails['last name'])
|
||||||
|
.waitForElementVisible('@loginField')
|
||||||
|
.clearValue('@loginField')
|
||||||
|
.setValue('@loginField', userDetails['login'])
|
||||||
|
.waitForElementVisible('@newUserPasswordField')
|
||||||
|
.clearValue('@newUserPasswordField')
|
||||||
|
.setValue('@newUserPasswordField', userDetails['password']);
|
||||||
|
|
||||||
|
if (userDetails['administrator']) {
|
||||||
|
const admin = util.format(this.elements.administratorSelectOption.selector, administrator);
|
||||||
|
await this.waitForElementVisible('@administratorField')
|
||||||
|
.click('@administratorField')
|
||||||
|
.waitForElementVisible(admin)
|
||||||
|
.click(admin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userDetails['gender']) {
|
||||||
|
const genderValue = util.format(this.elements.genderSelectOption.selector, gender)
|
||||||
|
await this.waitForElementVisible('@genderField')
|
||||||
|
.click('@genderField')
|
||||||
|
.waitForElementVisible(genderValue)
|
||||||
|
.click(genderValue);
|
||||||
|
}
|
||||||
|
return this.waitForElementVisible('@submitButton')
|
||||||
|
.click('@submitButton')
|
||||||
|
.useCss();
|
||||||
|
},
|
||||||
|
|
||||||
|
noPermissionMessage: async function (message) {
|
||||||
|
await this.useXpath()
|
||||||
|
.waitForElementVisible('@noPermissionDefinedMessage')
|
||||||
|
.expect.element('@noPermissionDefinedMessage')
|
||||||
|
.text.to.equal(message);
|
||||||
|
return this.useCss();
|
||||||
|
},
|
||||||
|
|
||||||
|
newUserShouldBeCreated: async function (lastname) {
|
||||||
|
await this.useXpath()
|
||||||
|
.waitForElementVisible('@newUserCreated')
|
||||||
|
.expect.element('@newUserCreated')
|
||||||
|
.text.to.equal(lastname);
|
||||||
|
return this.useCss();
|
||||||
|
},
|
||||||
|
|
||||||
|
noPermissionDefinedMessageNotShown: function (message) {
|
||||||
|
return this.useXpath()
|
||||||
|
.waitForElementNotPresent('@noPermissionDefinedMessage')
|
||||||
|
.useCss();
|
||||||
|
},
|
||||||
|
|
||||||
|
userNotCreated: function (lastname) {
|
||||||
|
return this.waitForElementVisible('@newUserAddOption');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
elements: {
|
||||||
|
newUserAddOption: {
|
||||||
|
selector: '.fiche'
|
||||||
|
},
|
||||||
|
|
||||||
|
lastnameField: {
|
||||||
|
selector: '//table[@class="border centpercent"]/tbody/tr/td//input[@id="lastname"]',
|
||||||
|
locateStrategy: 'xpath'
|
||||||
|
},
|
||||||
|
|
||||||
|
loginField: {
|
||||||
|
selector: '//table[@class="border centpercent"]/tbody/tr/td//input[@name="login"]',
|
||||||
|
locateStrategy: 'xpath'
|
||||||
|
},
|
||||||
|
|
||||||
|
newUserPasswordField: {
|
||||||
|
selector: '//table[@class="border centpercent"]/tbody/tr/td//input[@name="password"]',
|
||||||
|
locateStrategy: 'xpath'
|
||||||
|
},
|
||||||
|
|
||||||
|
submitButton: {
|
||||||
|
selector: '//div[@class="center"]/input[@class="button"]',
|
||||||
|
locateStrategy: 'xpath'
|
||||||
|
},
|
||||||
|
|
||||||
|
administratorField: {
|
||||||
|
selector: '//table[@class="border centpercent"]/tbody/tr/td//select[@id="admin"]',
|
||||||
|
locateStrategy: 'xpath'
|
||||||
|
},
|
||||||
|
|
||||||
|
administratorSelectOption: {
|
||||||
|
selector: '//select[@id="admin"]/option[.="%s"]',
|
||||||
|
locateStrategy: 'xpath'
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
genderField: {
|
||||||
|
selector: '//table[@class="border centpercent"]/tbody/tr/td//select[@id="gender"]',
|
||||||
|
locateStrategy: 'xpath'
|
||||||
|
},
|
||||||
|
genderSelectOption: {
|
||||||
|
selector: '//select[@id="gender"]/option[.="%s"]',
|
||||||
|
locateStrategy: 'xpath'
|
||||||
|
},
|
||||||
|
|
||||||
|
noPermissionDefinedMessage: {
|
||||||
|
selector: '//div[@class="jnotify-message"]',
|
||||||
|
locateStrategy: 'xpath'
|
||||||
|
},
|
||||||
|
|
||||||
|
newUserCreated: {
|
||||||
|
selector: '//div[contains(@class,"valignmiddle")]//div[contains(@class,"inline-block floatleft valignmiddle")]',
|
||||||
|
locateStrategy: 'xpath'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
44
test/acceptance/pageObjects/homePage.js
Normal file
44
test/acceptance/pageObjects/homePage.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
module.exports = {
|
||||||
|
url: function () {
|
||||||
|
return this.api.launchUrl + 'admin/index.php?mainmenu=home&leftmenu=setup&mesg=setupnotcomplete';
|
||||||
|
},
|
||||||
|
|
||||||
|
commands: [
|
||||||
|
{
|
||||||
|
browsedToNewUserPage: function () {
|
||||||
|
return this.useXpath()
|
||||||
|
.waitForElementVisible('@usersAndGroups')
|
||||||
|
.click('@usersAndGroups')
|
||||||
|
.waitForElementVisible('@newUser')
|
||||||
|
.click('@newUser')
|
||||||
|
.useCss();
|
||||||
|
},
|
||||||
|
|
||||||
|
browsedToListOfUsers: function () {
|
||||||
|
return this.useXpath()
|
||||||
|
.waitForElementVisible('@usersAndGroups')
|
||||||
|
.click('@usersAndGroups')
|
||||||
|
.waitForElementVisible('@listOfUsers')
|
||||||
|
.click('@listOfUsers')
|
||||||
|
.useCss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
elements: {
|
||||||
|
usersAndGroups: {
|
||||||
|
selector: '//div[@class="menu_titre"]/a[@title="Users & Groups"]',
|
||||||
|
locateStrategy: 'xpath'
|
||||||
|
},
|
||||||
|
|
||||||
|
newUser: {
|
||||||
|
selector: '//div[@class="menu_contenu menu_contenu_user_card"]/a[@title="New user"]',
|
||||||
|
locateStrategy: 'xpath'
|
||||||
|
},
|
||||||
|
|
||||||
|
listOfUsers: {
|
||||||
|
selector: '//a[@class="vsmenu"][@title="List of users"]',
|
||||||
|
locateStrategy: 'xpath'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
47
test/acceptance/pageObjects/listUsersPage.js
Normal file
47
test/acceptance/pageObjects/listUsersPage.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
const util = require('util');
|
||||||
|
module.exports = {
|
||||||
|
url: function () {
|
||||||
|
return this.api.launchUrl + 'user/list.php?leftmenu=users';
|
||||||
|
},
|
||||||
|
|
||||||
|
commands: [
|
||||||
|
{
|
||||||
|
listOfUsersDisplayed: async function (dataTable) {
|
||||||
|
const usersList = dataTable.hashes();
|
||||||
|
this.useXpath();
|
||||||
|
for (const row of usersList) {
|
||||||
|
let login = row['login'];
|
||||||
|
let lastName = row['last name'];
|
||||||
|
const userDetail = util.format(this.elements.userList.selector, login, lastName);
|
||||||
|
await this.waitForElementVisible('@userRow')
|
||||||
|
.waitForElementVisible(userDetail);
|
||||||
|
}
|
||||||
|
return this.useCss();
|
||||||
|
},
|
||||||
|
|
||||||
|
numberOfUsersDisplayed: async function (number) {
|
||||||
|
const userCount = util.format(this.elements.numberOfUsers.selector, number);
|
||||||
|
await this.useXpath()
|
||||||
|
.waitForElementVisible(userCount);
|
||||||
|
return this.useCss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
elements: {
|
||||||
|
userRow: {
|
||||||
|
selector: '//table[contains(@class,"tagtable liste")]/tbody/tr[position()>2]',
|
||||||
|
locateStrategy: 'xpath'
|
||||||
|
},
|
||||||
|
|
||||||
|
numberOfUsers: {
|
||||||
|
selector: '//div[contains(@class, "titre inline-block") and contains(., "List of users")]/span[.="(%d)"]',
|
||||||
|
locateStrategy: 'xpath'
|
||||||
|
},
|
||||||
|
|
||||||
|
userList: {
|
||||||
|
selector: '//table[contains(@class,"tagtable liste")]/tbody/tr[position()>2]/td/a//span[normalize-space(@class="nopadding usertext")][.="%s"]/../../following-sibling::td[.="%s"]',
|
||||||
|
locateStrategy: 'xpath'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
83
test/acceptance/pageObjects/loginPage.js
Normal file
83
test/acceptance/pageObjects/loginPage.js
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
module.exports = {
|
||||||
|
url: function () {
|
||||||
|
return this.api.launchUrl;
|
||||||
|
},
|
||||||
|
|
||||||
|
commands: [
|
||||||
|
{
|
||||||
|
waitForLoginPage: function () {
|
||||||
|
return this.waitForElementVisible('@loginTable');
|
||||||
|
},
|
||||||
|
|
||||||
|
userLogsInWithUsernameAndPassword: function (username, password) {
|
||||||
|
return this.waitForElementVisible('@userNameField')
|
||||||
|
.setValue('@userNameField', username)
|
||||||
|
.waitForElementVisible('@passwordField')
|
||||||
|
.setValue('@passwordField', password)
|
||||||
|
.useXpath()
|
||||||
|
.waitForElementVisible('@loginButton')
|
||||||
|
.click('@loginButton')
|
||||||
|
.useCss();
|
||||||
|
},
|
||||||
|
|
||||||
|
successfulLogin: function () {
|
||||||
|
return this.waitForElementNotPresent('@loginTable')
|
||||||
|
.waitForElementVisible('@userProfileDropdown');
|
||||||
|
},
|
||||||
|
|
||||||
|
userIsLoggedIn: async function (login) {
|
||||||
|
await this.useXpath()
|
||||||
|
.waitForElementVisible('@userLogin')
|
||||||
|
.expect.element('@userLogin')
|
||||||
|
.text.to.equal(login);
|
||||||
|
return this.useCss();
|
||||||
|
},
|
||||||
|
|
||||||
|
unsuccessfulLogin: function () {
|
||||||
|
return this.waitForElementVisible('@loginTable')
|
||||||
|
.waitForElementNotPresent('@userProfileDropdown');
|
||||||
|
},
|
||||||
|
|
||||||
|
loginErrorDisplayed: async function (errorMessage) {
|
||||||
|
await this.useXpath()
|
||||||
|
.waitForElementVisible('@loginError')
|
||||||
|
.expect.element('@loginError')
|
||||||
|
.text.to.equal(errorMessage);
|
||||||
|
return this.useCss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
elements: {
|
||||||
|
loginButton: {
|
||||||
|
selector: '//div[@id="login-submit-wrapper"]/input[@type="submit"]',
|
||||||
|
locateStrategy: 'xpath'
|
||||||
|
},
|
||||||
|
|
||||||
|
userNameField: {
|
||||||
|
selector: '#username'
|
||||||
|
},
|
||||||
|
|
||||||
|
passwordField: {
|
||||||
|
selector: '#password'
|
||||||
|
},
|
||||||
|
|
||||||
|
loginTable: {
|
||||||
|
selector: '.login_table'
|
||||||
|
},
|
||||||
|
|
||||||
|
userProfileDropdown: {
|
||||||
|
selector: '#topmenu-login-dropdown'
|
||||||
|
},
|
||||||
|
|
||||||
|
userLogin: {
|
||||||
|
selector: '//div[@id="topmenu-login-dropdown"]/a//span[contains(@class,"atoploginusername")]',
|
||||||
|
locateStrategy: 'xpath'
|
||||||
|
},
|
||||||
|
|
||||||
|
loginError: {
|
||||||
|
selector: '//div[@class="center login_main_message"]/div[@class="error"]',
|
||||||
|
locateStrategy: 'xpath'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
34
test/acceptance/pageObjects/logoutPage.js
Normal file
34
test/acceptance/pageObjects/logoutPage.js
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
module.exports = {
|
||||||
|
url: function () {
|
||||||
|
return this.api.launchUrl + 'admin/index.php?mainmenu=home&leftmenu=setup&mesg=setupnotcomplete';
|
||||||
|
},
|
||||||
|
|
||||||
|
commands:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
userOpensProfile: async function () {
|
||||||
|
await this.useXpath()
|
||||||
|
.waitForElementVisible('@userProfileDropdown')
|
||||||
|
.click('@userProfileDropdown')
|
||||||
|
return this.useCss();
|
||||||
|
},
|
||||||
|
|
||||||
|
userLogsOut: function () {
|
||||||
|
return this.waitForElementVisible('@logoutButton')
|
||||||
|
.click('@logoutButton');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
elements: {
|
||||||
|
|
||||||
|
logoutButton: {
|
||||||
|
selector: '.pull-right'
|
||||||
|
},
|
||||||
|
|
||||||
|
userProfileDropdown: {
|
||||||
|
selector: '//div[@id="topmenu-login-dropdown"]',
|
||||||
|
locateStrategy: 'xpath'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
123
test/acceptance/stepDefinitions/addUsersContext.js
Normal file
123
test/acceptance/stepDefinitions/addUsersContext.js
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
const { Before, Given, When, Then, After } = require('cucumber');
|
||||||
|
const { client } = require('nightwatch-api');
|
||||||
|
const fetch = require('node-fetch');
|
||||||
|
let initialUsers = {};
|
||||||
|
|
||||||
|
Given('the administrator has logged in using the webUI', async function () {
|
||||||
|
await client.page.loginPage().navigate().waitForLoginPage();
|
||||||
|
await client.page.loginPage().userLogsInWithUsernameAndPassword(client.globals.adminUsername, client.globals.adminPassword);
|
||||||
|
return client.page.loginPage().userIsLoggedIn(client.globals.adminUsername);
|
||||||
|
});
|
||||||
|
|
||||||
|
Given('the administrator has browsed to the new users page', function () {
|
||||||
|
return client.page.homePage().browsedToNewUserPage();
|
||||||
|
});
|
||||||
|
|
||||||
|
When('the admin creates user with following details', function (datatable) {
|
||||||
|
return client.page.addUsersPage().adminCreatesUser(datatable);
|
||||||
|
});
|
||||||
|
|
||||||
|
Then('new user {string} should be created', function (lastname) {
|
||||||
|
return client.page.addUsersPage().newUserShouldBeCreated(lastname);
|
||||||
|
});
|
||||||
|
|
||||||
|
Then('message {string} should be displayed in the webUI', function (message) {
|
||||||
|
return client.page.addUsersPage().noPermissionMessage(message);
|
||||||
|
});
|
||||||
|
|
||||||
|
Then('message {string} should not be displayed in the webUI', function (message) {
|
||||||
|
return client.page.addUsersPage().noPermissionDefinedMessageNotShown(message);
|
||||||
|
});
|
||||||
|
|
||||||
|
Then('new user {string} should not be created', function (lastname) {
|
||||||
|
return client.page.addUsersPage().userNotCreated(lastname);
|
||||||
|
});
|
||||||
|
|
||||||
|
Given('a user has been created with following details', function (dataTable) {
|
||||||
|
return adminHasCreatedUser(dataTable);
|
||||||
|
});
|
||||||
|
|
||||||
|
Given('the admin has created the following users', function (dataTable) {
|
||||||
|
return adminHasCreatedUser(dataTable);
|
||||||
|
});
|
||||||
|
|
||||||
|
const getUsers = async function () {
|
||||||
|
const header = {};
|
||||||
|
const url = client.globals.backend_url + 'api/index.php/users';
|
||||||
|
const users = {};
|
||||||
|
header['Accept'] = 'application/json';
|
||||||
|
header['DOLAPIKEY'] = client.globals.dolApiKey;
|
||||||
|
await fetch(url, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: header
|
||||||
|
})
|
||||||
|
.then(async (response) => {
|
||||||
|
const json_response = await response.json();
|
||||||
|
for (const user of json_response) {
|
||||||
|
users[user.id] = user.id;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return users;
|
||||||
|
};
|
||||||
|
|
||||||
|
const adminHasCreatedUser = async function (dataTable) {
|
||||||
|
const header = {};
|
||||||
|
const url = client.globals.backend_url + 'api/index.php/users';
|
||||||
|
header['Accept'] = 'application/json';
|
||||||
|
header['DOLAPIKEY'] = client.globals.dolApiKey;
|
||||||
|
header['Content-Type'] = 'application/json';
|
||||||
|
const userDetails = dataTable.hashes();
|
||||||
|
for (const user of userDetails) {
|
||||||
|
await fetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: header,
|
||||||
|
body: JSON.stringify(
|
||||||
|
{
|
||||||
|
login: user['login'],
|
||||||
|
lastname: user['last name'],
|
||||||
|
pass: user['password']
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status < 200 || response.status >= 400) {
|
||||||
|
throw new Error('Failed to create user: ' + user['login'] +
|
||||||
|
' ' + response.statusText);
|
||||||
|
}
|
||||||
|
return response.text();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Before(async () => {
|
||||||
|
initialUsers = await getUsers();
|
||||||
|
});
|
||||||
|
|
||||||
|
After(async () => {
|
||||||
|
const finalUsers = await getUsers();
|
||||||
|
const header = {};
|
||||||
|
const url = client.globals.backend_url + 'api/index.php/users/';
|
||||||
|
header['Accept'] = 'application/json';
|
||||||
|
header['DOLAPIKEY'] = client.globals.dolApiKey;
|
||||||
|
let found;
|
||||||
|
for (const finaluser in finalUsers) {
|
||||||
|
for (const initialuser in initialUsers) {
|
||||||
|
found = false;
|
||||||
|
if (initialuser === finaluser) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
await fetch(url + finaluser, {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: header
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
if (res.status < 200 || res.status >= 400) {
|
||||||
|
throw new Error("Failed to delete user: " + res.statusText);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
14
test/acceptance/stepDefinitions/listUsersContext.js
Normal file
14
test/acceptance/stepDefinitions/listUsersContext.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
const { When, Then } = require('cucumber');
|
||||||
|
const { client } = require('nightwatch-api');
|
||||||
|
|
||||||
|
When('the administrator browses to the list of users page using the webUI', function () {
|
||||||
|
return client.page.homePage().browsedToListOfUsers();
|
||||||
|
});
|
||||||
|
|
||||||
|
Then('following users should be displayed in the users list', function (dataTable) {
|
||||||
|
return client.page.listUsersPage().listOfUsersDisplayed(dataTable);
|
||||||
|
});
|
||||||
|
|
||||||
|
Then('the number of created users should be {int}', function (number) {
|
||||||
|
return client.page.listUsersPage().numberOfUsersDisplayed(number);
|
||||||
|
});
|
||||||
22
test/acceptance/stepDefinitions/loginContext.js
Normal file
22
test/acceptance/stepDefinitions/loginContext.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
const { Given, When, Then } = require('cucumber')
|
||||||
|
const { client } = require('nightwatch-api')
|
||||||
|
|
||||||
|
Given('the user has browsed to the login page', function () {
|
||||||
|
return client.page.loginPage().navigate();
|
||||||
|
});
|
||||||
|
|
||||||
|
When('user logs in with username {string} and password {string}', function (username, password) {
|
||||||
|
return client.page.loginPage().userLogsInWithUsernameAndPassword(username, password);
|
||||||
|
});
|
||||||
|
|
||||||
|
Then('the user should be directed to the homepage', function () {
|
||||||
|
return client.page.loginPage().successfulLogin();
|
||||||
|
});
|
||||||
|
|
||||||
|
Then('the user should not be able to login', function () {
|
||||||
|
return client.page.loginPage().unsuccessfulLogin();
|
||||||
|
});
|
||||||
|
|
||||||
|
Then('error message {string} should be displayed in the webUI', function (errormessage) {
|
||||||
|
return client.page.loginPage().loginErrorDisplayed(errormessage);
|
||||||
|
});
|
||||||
14
test/acceptance/stepDefinitions/logoutContext.js
Normal file
14
test/acceptance/stepDefinitions/logoutContext.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
const { When, Then } = require('cucumber');
|
||||||
|
const { client } = require('nightwatch-api');
|
||||||
|
|
||||||
|
When('the user opens the user profile using the webUI', function () {
|
||||||
|
return client.page.logoutPage().userOpensProfile();
|
||||||
|
});
|
||||||
|
|
||||||
|
When('the user logs out using the webUI', function () {
|
||||||
|
return client.page.logoutPage().userLogsOut();
|
||||||
|
});
|
||||||
|
|
||||||
|
Then('the user should be logged out successfully', function () {
|
||||||
|
return client.page.loginPage().waitForLoginPage();
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user