diff --git a/package.json b/package.json index 67f24dd541a..496c34e7387 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "nightwatch-api": "^3.0.1" }, "scripts": { - "test:e2e": "node_modules/cucumber/bin/cucumber-js --require test/acceptance/index.js --require test/acceptance/stepDefinitions -f node_modules/cucumber-pretty" + "test:e2e": "node_modules/cucumber/bin/cucumber-js --require test/acceptance/index.js --require test/acceptance/setup.js --require test/acceptance/stepDefinitions -f node_modules/cucumber-pretty" }, "dependencies": { "cucumber-pretty": "^6.0.0", diff --git a/test/acceptance/features/Api/apiAddUsers.feature b/test/acceptance/features/Api/apiAddUsers.feature new file mode 100644 index 00000000000..32d94a7b3cf --- /dev/null +++ b/test/acceptance/features/Api/apiAddUsers.feature @@ -0,0 +1,67 @@ +Feature: Add user + As an admin + I want to add users + So that the authorized access is possible + + Scenario: Admin adds user without permission + Given the user with login "harrypotter@gmail.com" does not exist + When the admin creates user with following details using API + | last name | Potter | + | login | harrypotter@gmail.com | + | password | password | + Then the response status code should be "200" + And user with login "harrypotter@gmail.com" should exist + + Scenario: Admin creates already existing user + Given the admin has created the following users + | login | last name | password | + | Harry | Potter | hello123 | + When the admin creates user with following details using API + | last name | Potter | + | login | Harry | + | password | hello123 | + Then the response status code should be "500" + And the response message should be "ErrorLoginAlreadyExists" + + Scenario Outline: Admin adds user with incomplete essential credentials + Given the user with login "Harry" does not exist + When the admin creates user with following details using API + | last name | | + | login | Harry | + | password | | + Then the response status code should be "200" + And user with login "Harry" should exist + Examples: + | last name | password | + | | | + | Manson | | + | | 123 | + + Scenario Outline: Admin adds user without login + Given the user with login "harrypotter@gmail.com" does not exist + When the admin creates user with following details using API + | last name | | + | login | | + | password | | + Then the response status code should be "500" + And the response message should be "Field 'Login' is required" + Examples: + | last name | password | + | Potter | Hello123 | + | Potter | | + | | hello123 | + + Scenario Outline: Admin adds user with last name as special characters + Given the user with login "" does not exist + When the admin creates user with following details using API + | last name | | + | login | | + | password | password | + Then the response status code should be "200" + And user with login "" should exist + Examples: + | last name | login | + | swi@ | s$5^2 | + | g!!@%ui | नेपाली | + | swikriti@h | सिमप्ले $%#?&@name.txt | + | !@#$%^&*()-_+ | España§àôœ€ | \ No newline at end of file diff --git a/test/acceptance/features/addUsers.feature b/test/acceptance/features/WebUI/addUsers.feature similarity index 100% rename from test/acceptance/features/addUsers.feature rename to test/acceptance/features/WebUI/addUsers.feature diff --git a/test/acceptance/features/listUsers.feature b/test/acceptance/features/WebUI/listUsers.feature similarity index 100% rename from test/acceptance/features/listUsers.feature rename to test/acceptance/features/WebUI/listUsers.feature diff --git a/test/acceptance/features/login.feature b/test/acceptance/features/WebUI/login.feature similarity index 100% rename from test/acceptance/features/login.feature rename to test/acceptance/features/WebUI/login.feature diff --git a/test/acceptance/features/logout.feature b/test/acceptance/features/WebUI/logout.feature similarity index 100% rename from test/acceptance/features/logout.feature rename to test/acceptance/features/WebUI/logout.feature diff --git a/test/acceptance/pageObjects/listUsersPage.js b/test/acceptance/pageObjects/listUsersPage.js index 6f9df509d5f..3567bb576ab 100644 --- a/test/acceptance/pageObjects/listUsersPage.js +++ b/test/acceptance/pageObjects/listUsersPage.js @@ -30,7 +30,7 @@ module.exports = { elements: { userRow: { - selector: '//table[contains(@class,"tagtable liste")]/tbody/tr[position()>2]', + selector: '//table[contains(@class,"tagtable")]/tbody/tr[position()>2]', locateStrategy: 'xpath' }, @@ -40,7 +40,7 @@ module.exports = { }, userList: { - selector: '//table[contains(@class,"tagtable liste")]/tbody/tr[position()>2]/td/a//span[normalize-space(@class="nopadding usertext")][.="%s"]/../../following-sibling::td[.="%s"]', + selector: '//table[contains(@class,"tagtable")]/tbody/tr[position()>2]/td/a//span[normalize-space(@class="nopadding usertext")][.="%s"]/../../following-sibling::td[.="%s"]', locateStrategy: 'xpath' } } diff --git a/test/acceptance/setup.js b/test/acceptance/setup.js new file mode 100644 index 00000000000..eeed97b3466 --- /dev/null +++ b/test/acceptance/setup.js @@ -0,0 +1,77 @@ +const { Before, After } = require('cucumber'); +const { client } = require('nightwatch-api'); +const fetch = require('node-fetch'); +let initialUsers = {}; +let dolApiKey = ''; + +const getUsers = async function () { + const header = {}; + const url = client.globals.backend_url + 'api/index.php/users'; + const users = {}; + header['Accept'] = 'application/json'; + header['DOLAPIKEY'] = 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; +}; + +Before(async function getDolApiKey() { + const header = {} + const adminUsername = client.globals.adminUsername; + const adminPassword = client.globals.adminPassword; + const params = new URLSearchParams() + params.set('login', adminUsername) + params.set('password', adminPassword) + const apiKey = `http://localhost/dolibarr/htdocs/api/index.php/login?${params.toString()}`; + header['Accept'] = 'application/json' + await fetch(apiKey, { + method: 'GET', + headers: header + }) + .then(async (response) => { + const jsonResponse = await response.json() + dolApiKey = jsonResponse['success']['token'] + client.globals.dolApiKey = dolApiKey + }) +}) + +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'] = 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); + } + }); + } + } +}); \ No newline at end of file diff --git a/test/acceptance/stepDefinitions/addUsersContext.js b/test/acceptance/stepDefinitions/addUsersContext.js index 22dc218d04a..385f731b8f7 100644 --- a/test/acceptance/stepDefinitions/addUsersContext.js +++ b/test/acceptance/stepDefinitions/addUsersContext.js @@ -1,142 +1,156 @@ -const { Before, Given, When, Then, After } = require('cucumber'); -const { client } = require('nightwatch-api'); +const {Given, When, Then} = require('cucumber'); +const {client} = require('nightwatch-api'); const fetch = require('node-fetch'); -let initialUsers = {}; -let dolApiKey = ''; +const assert = require('assert'); +let response; +let Login = {}; 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); + 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(); + return client.page.homePage().browsedToNewUserPage(); }); When('the admin creates user with following details', function (datatable) { - return client.page.addUsersPage().adminCreatesUser(datatable); + return client.page.addUsersPage().adminCreatesUser(datatable); }); Then('new user {string} should be created', function (lastname) { - return client.page.addUsersPage().newUserShouldBeCreated(lastname); + return client.page.addUsersPage().newUserShouldBeCreated(lastname); }); Then('message {string} should be displayed in the webUI', function (message) { - return client.page.addUsersPage().noPermissionMessage(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); + return client.page.addUsersPage().noPermissionDefinedMessageNotShown(message); }); Then('new user {string} should not be created', function (lastname) { - return client.page.addUsersPage().userNotCreated(lastname); + return client.page.addUsersPage().userNotCreated(lastname); }); Given('a user has been created with following details', function (dataTable) { - return adminHasCreatedUser(dataTable); + return adminHasCreatedUser(dataTable); }); Given('the admin has created the following users', function (dataTable) { - return adminHasCreatedUser(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'] = 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; +When('the admin creates user with following details using API', function (dataTable) { + return adminCreatesUserWithAPI(dataTable); +}); + +Given('the user with login {string} does not exist', async function (login) { + await userDoesNotExist(login); +}); + +Then('the response status code should be {string}', function (expectedStatusCode) { + return getStatusCode(expectedStatusCode); +}); + +Then('user with login {string} should exist', function (login) { + return userShouldExist(login); +}); + +Then('the response message should be {string}', function (expectedResponseMessage) { + return getResponseMessage(expectedResponseMessage); +}); + +const createUserRequest = function (login, lastname, password) { + 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'; + return fetch(url, { + method: 'POST', + headers: header, + body: JSON.stringify( + { + login: login, + lastname: lastname, + pass: password + } + ) + }); +}; + +const adminCreatesUserWithAPI = function (dataTable) { + const userDetails = dataTable.rowsHash(); + return createUserRequest(userDetails['login'], userDetails['last name'], userDetails['password']) + .then((res) => { + response = res; + }); }; const adminHasCreatedUser = async function (dataTable) { - const header = {}; - const url = client.globals.backend_url + 'api/index.php/users'; - header['Accept'] = 'application/json'; - header['DOLAPIKEY'] = 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(); - }); - } + const userDetails = dataTable.hashes(); + for (const user of userDetails) { + await createUserRequest(user['login'], user['last name'], user['password']) + .then((response) => { + if (response.status < 200 || response.status >= 400) { + throw new Error('Failed to create user: ' + user['login'] + + ' ' + response.statusText); + } + }); + } }; -Before(async () => { - const header = {} - const adminUsername = client.globals.adminUsername; - const adminPassword = client.globals.adminPassword; - const params = new URLSearchParams() - params.set('login', adminUsername) - params.set('password', adminPassword) - const apiKey = `http://localhost/dolibarr/htdocs/api/index.php/login?${params.toString()}`; - header['Accept'] = 'application/json' - await fetch(apiKey, { - method: 'GET', - headers: header - }) - .then(async (response) => { - const jsonResponse = await response.json() - dolApiKey = jsonResponse['success']['token'] - }) -}) -Before(async () => { - initialUsers = await getUsers(); -}); +const getUsersLogin = async function () { + 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'; + await fetch(url, { + method: 'GET', + headers: header + }) + .then(async (response) => { + const json_response = await response.json(); + for (const user of json_response) { + Login[user.login] = user.login; + } + }); +}; -After(async () => { - const finalUsers = await getUsers(); - const header = {}; - const url = client.globals.backend_url + 'api/index.php/users/'; - header['Accept'] = 'application/json'; - header['DOLAPIKEY'] = 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); - } - }); - } - } -}); +const userDoesNotExist = async function (login) { + await getUsersLogin(); + if (login in Login) { + Login = {}; + throw new Error(`user ${login} exists`); + } + Login = {}; + return; +}; + +const userShouldExist = async function (login) { + await getUsersLogin(); + if (login in Login) { + Login = {}; + return; + } else { + Login = {}; + throw new Error(`User ${login} does not Exist`); + } +}; + +const getStatusCode = async function (expectedStatusCode) { + const actualStatusCode = response.status.toString(); + return assert.strictEqual(actualStatusCode, expectedStatusCode, + `The expected status code was ${expectedStatusCode} but got ${actualStatusCode}`); +}; + +const getResponseMessage = async function (expectedResponseMessage) { + const json_response = await response.json(); + const actualResponseMessage = json_response['error']['0']; + return assert.strictEqual(actualResponseMessage, expectedResponseMessage, + `the expected response message was ${expectedResponseMessage} but got ${actualResponseMessage}`); +}; \ No newline at end of file