From df7746f896b12b5a49ead8648f2edf625b514bc6 Mon Sep 17 00:00:00 2001 From: Amrita <54478846+amrita-shrestha@users.noreply.github.com> Date: Fri, 18 Oct 2024 00:03:31 +0545 Subject: [PATCH] test: Setup UI test using BDD approach (#152) --- client/nightwatch.conf.js | 19 ++++++++++++++ client/package.json | 7 ++++- client/tests/acceptance/cucumber.conf.js | 25 ++++++++++++++++++ .../features/webUILogin/login.feature | 9 +++++++ .../acceptance/pageObjects/dashboardPage.js | 20 ++++++++++++++ .../tests/acceptance/pageObjects/loginPage.js | 26 +++++++++++++++++++ .../stepDefinitions/loginContext.js | 26 +++++++++++++++++++ 7 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 client/nightwatch.conf.js create mode 100644 client/tests/acceptance/cucumber.conf.js create mode 100644 client/tests/acceptance/features/webUILogin/login.feature create mode 100644 client/tests/acceptance/pageObjects/dashboardPage.js create mode 100644 client/tests/acceptance/pageObjects/loginPage.js create mode 100644 client/tests/acceptance/stepDefinitions/loginContext.js diff --git a/client/nightwatch.conf.js b/client/nightwatch.conf.js new file mode 100644 index 00000000..93569f17 --- /dev/null +++ b/client/nightwatch.conf.js @@ -0,0 +1,19 @@ +const path = require('path'); +const LAUNCH_URL = process.env.LAUNCH_URL || 'http://localhost:3000'; + +module.exports = { + page_objects_path: path.join(__dirname, 'tests' , 'acceptance', 'pageObjects'), + test_settings: { + default: { + launch_url: LAUNCH_URL, + selenium: { + start_process: false, + host: 'localhost', + port: 4444, + }, + desiredCapabilities: { + browserName: 'chrome', + }, + }, + }, +}; \ No newline at end of file diff --git a/client/package.json b/client/package.json index 6360eea5..02f47539 100755 --- a/client/package.json +++ b/client/package.json @@ -6,7 +6,8 @@ "eject": "react-scripts eject", "lint": "eslint --ext js,jsx src config-overrides.js", "start": "react-app-rewired start", - "test": "react-app-rewired test" + "test": "react-app-rewired test", + "test:webui": "cucumber-js --require tests/acceptance/cucumber.conf.js --require tests/acceptance/stepDefinitions -f @cucumber/pretty-formatter" }, "browserslist": { "production": [ @@ -108,6 +109,8 @@ }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", + "@cucumber/cucumber": "^7.3.1", + "@cucumber/pretty-formatter": "^1.0.0-alpha.1", "@testing-library/jest-dom": "^6.5.0", "@testing-library/react": "^15.0.7", "@testing-library/user-event": "^14.5.2", @@ -119,6 +122,8 @@ "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-react": "^7.36.1", "eslint-plugin-react-hooks": "^4.6.2", + "nightwatch": "^1.7.8", + "nightwatch-api": "^3.0.2", "react-test-renderer": "18.2.0" } } diff --git a/client/tests/acceptance/cucumber.conf.js b/client/tests/acceptance/cucumber.conf.js new file mode 100644 index 00000000..66e58ad8 --- /dev/null +++ b/client/tests/acceptance/cucumber.conf.js @@ -0,0 +1,25 @@ +const { + After, + Before, + AfterAll, + BeforeAll, + setDefaultTimeout, +} = require("@cucumber/cucumber"); +const { createSession, closeSession } = require("nightwatch-api"); + +setDefaultTimeout(60000); +// runs before all scenarios +BeforeAll(async function () {}); + +// runs before each scenario +Before(async function () { + await createSession(); +}); + +// runs after each scenario +After(async function () { + await closeSession(); +}); + +// runs after all scenarios +AfterAll(async function () {}); diff --git a/client/tests/acceptance/features/webUILogin/login.feature b/client/tests/acceptance/features/webUILogin/login.feature new file mode 100644 index 00000000..97b7fe8f --- /dev/null +++ b/client/tests/acceptance/features/webUILogin/login.feature @@ -0,0 +1,9 @@ +Feature: login + As a user + I want to log in + So that I can manage project + + Scenario: User logs in with valid credentials + Given user has browsed to the login page + When user logs in with email "demo@demo.demo" and password "demo" using the webUI + Then the user should be in the dashboard page \ No newline at end of file diff --git a/client/tests/acceptance/pageObjects/dashboardPage.js b/client/tests/acceptance/pageObjects/dashboardPage.js new file mode 100644 index 00000000..3303d398 --- /dev/null +++ b/client/tests/acceptance/pageObjects/dashboardPage.js @@ -0,0 +1,20 @@ +module.exports = { + url: function () { + return this.api.launchUrl + "/dashboard"; + }, + commands: { + isDashboardPage: async function () { + let result = false; + await this.waitForElementVisible("@dashboardHeader"); + await this.isVisible("@dashboardHeader", (res) => { + result = res.value; + }); + return result; + }, + }, + elements: { + dashboardHeader: { + selector: "a.Header_title__3SEjb", + }, + }, +}; diff --git a/client/tests/acceptance/pageObjects/loginPage.js b/client/tests/acceptance/pageObjects/loginPage.js new file mode 100644 index 00000000..7b54d963 --- /dev/null +++ b/client/tests/acceptance/pageObjects/loginPage.js @@ -0,0 +1,26 @@ +module.exports = { + url: function () { + return this.api.launchUrl + "/login"; + }, + commands: { + logIn: function (email, password) { + return this.waitForElementVisible("@emailInput") + .setValue("@emailInput", email) + .waitForElementVisible("@passwordInput") + .setValue("@passwordInput", password) + .waitForElementVisible("@loginBtn") + .click("@loginBtn"); + }, + }, + elements: { + emailInput: { + selector: "input[name=emailOrUsername]", + }, + passwordInput: { + selector: "input[name=password]", + }, + loginBtn: { + selector: "form button", + }, + }, +}; diff --git a/client/tests/acceptance/stepDefinitions/loginContext.js b/client/tests/acceptance/stepDefinitions/loginContext.js new file mode 100644 index 00000000..ade4873f --- /dev/null +++ b/client/tests/acceptance/stepDefinitions/loginContext.js @@ -0,0 +1,26 @@ +const { Given, When, Then } = require("@cucumber/cucumber"); +const { client } = require("nightwatch-api"); +const assert = require("assert"); + +const loginPage = client.page.loginPage(); +const dashboardPage = client.page.dashboardPage(); + +Given("user has browsed to the login page", function () { + return loginPage.navigate(); +}); + +When( + "user logs in with username/email {string} and password {string} using the webUI", + function (username, password) { + return loginPage.logIn(username, password); + } +); + +Then("the user should be in the dashboard page", async function () { + const isDashboard = await dashboardPage.isDashboardPage(); + assert.strictEqual( + isDashboard, + true, + "Expected to see dashboard page but not visible" + ); +});