Replace UI module with Next.js
This commit is contained in:
parent
8aeff18162
commit
616205fe73
91 changed files with 3570 additions and 722 deletions
83
source/selenium/.eslintrc
Normal file
83
source/selenium/.eslintrc
Normal file
|
@ -0,0 +1,83 @@
|
|||
{
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"prettier"
|
||||
],
|
||||
"plugins": [
|
||||
"typescript",
|
||||
"@typescript-eslint",
|
||||
"typescript-sort-keys",
|
||||
"simple-import-sort",
|
||||
"import"
|
||||
],
|
||||
"settings": {
|
||||
"import/parsers": {
|
||||
"@typescript-eslint/parser": [
|
||||
".ts",
|
||||
".tsx"
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"*.js"
|
||||
],
|
||||
"parser": "esprima",
|
||||
"rules": {
|
||||
"@typescript-eslint/no-var-requires": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"ignorePatterns": [],
|
||||
"rules": {
|
||||
"max-len": "off",
|
||||
"no-useless-escape": "off",
|
||||
"object-curly-spacing": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"no-multi-spaces": "error",
|
||||
"no-console": [
|
||||
"error",
|
||||
{
|
||||
"allow": [
|
||||
"info",
|
||||
"warn",
|
||||
"error"
|
||||
]
|
||||
}
|
||||
],
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"@typescript-eslint/no-unused-vars": 2,
|
||||
"@typescript-eslint/interface-name-prefix": 0,
|
||||
"@typescript-eslint/no-empty-interface:": 0,
|
||||
"@typescript-eslint/explicit-function-return-type": 0,
|
||||
"@typescript-eslint/explicit-member-accessibility": 2,
|
||||
"@typescript-eslint/no-explicit-any": 0,
|
||||
"@typescript-eslint/no-empty-function": 0,
|
||||
"typescript-sort-keys/interface": "error",
|
||||
"typescript-sort-keys/string-enum": "error",
|
||||
"sort-imports": "off",
|
||||
"import/no-duplicates": "error",
|
||||
"import/order": "off",
|
||||
"simple-import-sort/imports": [
|
||||
"error",
|
||||
{
|
||||
"groups": [
|
||||
[
|
||||
"^\\u0000"
|
||||
],
|
||||
[
|
||||
"^[^.]"
|
||||
],
|
||||
[
|
||||
"^\\."
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
14
source/selenium/.tsconfig.json
Normal file
14
source/selenium/.tsconfig.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"module": "commonjs",
|
||||
"types": [
|
||||
"./global.d.ts"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts"
|
||||
]
|
||||
}
|
6
source/selenium/config/.ci.env
Normal file
6
source/selenium/config/.ci.env
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Cucumber
|
||||
SELENIUM_SERVER_URL="http://10.0.1.22:4444"
|
||||
|
||||
# Application
|
||||
# HOST_IP="" - defined in Jenkins node
|
||||
APP_PORT="9092"
|
6
source/selenium/config/.local.env
Normal file
6
source/selenium/config/.local.env
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Cucumber
|
||||
SELENIUM_SERVER_URL="http://10.2.1.4:4444"
|
||||
|
||||
# Application
|
||||
HOST_IP="http://10.2.1.2"
|
||||
APP_PORT="3000"
|
24
source/selenium/cucumber.js
Normal file
24
source/selenium/cucumber.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
const argv = require('minimist')(process.argv);
|
||||
|
||||
const common = [
|
||||
'src/features/home.feature',
|
||||
'src/features/*.feature',
|
||||
'--require-module ts-node/register',
|
||||
'--require src/steps/**/*.ts',
|
||||
'-f summary',
|
||||
'-f json:report/report.json',
|
||||
'-f @qavajs/html-formatter:report/report.html',
|
||||
].join(' ');
|
||||
|
||||
module.exports = (async function () {
|
||||
if (argv['p'] === 'ci') {
|
||||
require('dotenv').config({ path: './config/.ci.env' });
|
||||
} else {
|
||||
require('dotenv').config({ path: './config/.local.env' });
|
||||
}
|
||||
|
||||
return {
|
||||
default: common,
|
||||
ci: common,
|
||||
};
|
||||
})();
|
11
source/selenium/global.d.ts
vendored
Normal file
11
source/selenium/global.d.ts
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
declare global {
|
||||
namespace NodeJS {
|
||||
interface ProcessEnv {
|
||||
APP_PORT: string;
|
||||
HOST_IP: string;
|
||||
SELENIUM_SERVER_URL: string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default global;
|
38
source/selenium/package.json
Normal file
38
source/selenium/package.json
Normal file
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"name": "$(appName)-selenium",
|
||||
"version": "0.1.0",
|
||||
"author": "Roman Jaroš",
|
||||
"license": "ISC",
|
||||
"scripts": {
|
||||
"selenium:smoke": "cucumber-js"
|
||||
},
|
||||
"dependencies": {
|
||||
"typescript": "5.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@qavajs/html-formatter": "0.15.3",
|
||||
"@types/chai": "4.3.11",
|
||||
"@types/selenium-webdriver": "4.1.21",
|
||||
"@typescript-eslint/eslint-plugin": "6.15.0",
|
||||
"@typescript-eslint/parser": "6.15.0",
|
||||
"@cucumber/cucumber": "10.0.1",
|
||||
"dotenv": "16.3.1",
|
||||
"eslint": "8.56.0",
|
||||
"eslint-config-prettier": "9.1.0",
|
||||
"eslint-plugin-import": "2.29.1",
|
||||
"eslint-config-next": "14.0.4",
|
||||
"eslint-plugin-react": "7.33.2",
|
||||
"eslint-plugin-react-hooks": "4.6.0",
|
||||
"eslint-plugin-simple-import-sort": "10.0.0",
|
||||
"eslint-plugin-typescript": "0.14.0",
|
||||
"eslint-plugin-typescript-sort-keys": "3.1.0",
|
||||
"chai": "4.3.10",
|
||||
"cucumber-tsflow": "4.3.1",
|
||||
"minimist": "1.2.8",
|
||||
"prettier": "3.1.1",
|
||||
"selenium-webdriver": "4.16.0",
|
||||
"ts-loader": "9.5.1",
|
||||
"ts-node": "10.9.2"
|
||||
},
|
||||
"peerDependencies": {}
|
||||
}
|
13
source/selenium/src/.tsconfig.json
Normal file
13
source/selenium/src/.tsconfig.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"emitDecoratorMetadata": false,
|
||||
"typeRoots": [
|
||||
"../"
|
||||
]
|
||||
},
|
||||
"ts-node": {
|
||||
"transpileOnly": true
|
||||
}
|
||||
}
|
17
source/selenium/src/common/BasePage.ts
Normal file
17
source/selenium/src/common/BasePage.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { By } from 'selenium-webdriver';
|
||||
|
||||
export class BasePage {
|
||||
protected url: string;
|
||||
|
||||
public title?: string;
|
||||
public root: By;
|
||||
|
||||
public buttons?: Record<string, By>;
|
||||
public fields?: Record<string, By>;
|
||||
public forms?: Record<string, By>;
|
||||
public messages?: Record<string, By>;
|
||||
|
||||
public getPageUrl() {
|
||||
return `${process.env.HOST_IP}:${process.env.APP_PORT}` + this.url;
|
||||
}
|
||||
}
|
13
source/selenium/src/common/BaseStep.ts
Normal file
13
source/selenium/src/common/BaseStep.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { setDefaultTimeout } from '@cucumber/cucumber';
|
||||
import { ThenableWebDriver } from 'selenium-webdriver';
|
||||
|
||||
import { WebDriver } from './WebDriver';
|
||||
|
||||
export class BaseStep {
|
||||
protected driver: ThenableWebDriver;
|
||||
|
||||
public constructor() {
|
||||
this.driver = new WebDriver().getDriver();
|
||||
setDefaultTimeout(10 * 60 * 1000);
|
||||
}
|
||||
}
|
25
source/selenium/src/common/WebDriver.ts
Normal file
25
source/selenium/src/common/WebDriver.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { binding } from 'cucumber-tsflow';
|
||||
import { Builder, Capabilities, ThenableWebDriver } from 'selenium-webdriver';
|
||||
|
||||
const capabilities = Capabilities.chrome();
|
||||
capabilities.set('chromeOptions', { w3c: false });
|
||||
|
||||
@binding()
|
||||
export class WebDriver {
|
||||
protected readonly driver: ThenableWebDriver;
|
||||
private static instance: WebDriver;
|
||||
|
||||
public constructor() {
|
||||
if (WebDriver.instance) {
|
||||
return WebDriver.instance;
|
||||
}
|
||||
|
||||
this.driver = new Builder().usingServer(process.env.SELENIUM_SERVER_URL).withCapabilities(capabilities).build();
|
||||
this.driver.manage().setTimeouts({ implicit: 100 });
|
||||
WebDriver.instance = this;
|
||||
}
|
||||
|
||||
public getDriver() {
|
||||
return this.driver;
|
||||
}
|
||||
}
|
5
source/selenium/src/features/home.feature
Normal file
5
source/selenium/src/features/home.feature
Normal file
|
@ -0,0 +1,5 @@
|
|||
Feature: Home page
|
||||
|
||||
Scenario: Verify home page title
|
||||
Given i visit home page
|
||||
Then page title is $(AppName)
|
15
source/selenium/src/pages/HomePage.ts
Normal file
15
source/selenium/src/pages/HomePage.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { binding } from 'cucumber-tsflow';
|
||||
import { By } from 'selenium-webdriver';
|
||||
|
||||
import { BasePage } from '../common/BasePage';
|
||||
|
||||
@binding()
|
||||
export class HomePage extends BasePage {
|
||||
protected url = '/';
|
||||
|
||||
// initial div
|
||||
public root = By.xpath('//body');
|
||||
|
||||
// page buttons
|
||||
public buttons = {};
|
||||
}
|
6
source/selenium/src/pages/components/Navigation.ts
Normal file
6
source/selenium/src/pages/components/Navigation.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
import { By } from 'selenium-webdriver';
|
||||
|
||||
export class Navigation {
|
||||
public root = By.xpath('//div[@class="page-top"]');
|
||||
public logoutLink = By.xpath(`${this.root.value}//div[contains(text(), "Odhlásit se")]`);
|
||||
}
|
20
source/selenium/src/steps/common/page.steps.ts
Normal file
20
source/selenium/src/steps/common/page.steps.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { expect } from 'chai';
|
||||
import { binding, given } from 'cucumber-tsflow';
|
||||
import { ThenableWebDriver } from 'selenium-webdriver';
|
||||
|
||||
import { WebDriver } from '../../common/WebDriver';
|
||||
|
||||
@binding([])
|
||||
export class PageSteps {
|
||||
protected driver: ThenableWebDriver;
|
||||
|
||||
public constructor() {
|
||||
this.driver = new WebDriver().getDriver();
|
||||
}
|
||||
|
||||
@given(/page title is (.*)/)
|
||||
public async thenPageTitleIs(title: string) {
|
||||
const pageTitle = await this.driver.getTitle();
|
||||
expect(pageTitle).to.equal(title);
|
||||
}
|
||||
}
|
24
source/selenium/src/steps/common/session.steps.ts
Normal file
24
source/selenium/src/steps/common/session.steps.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { afterAll, binding } from 'cucumber-tsflow';
|
||||
import { until } from 'selenium-webdriver';
|
||||
|
||||
import { WebDriver } from '../../common/WebDriver';
|
||||
import { Navigation } from '../../pages/components/Navigation';
|
||||
|
||||
@binding([])
|
||||
export class SessionSteps {
|
||||
@afterAll()
|
||||
protected async closeBrowser() {
|
||||
const driver = new WebDriver().getDriver();
|
||||
await driver.quit();
|
||||
}
|
||||
|
||||
@afterAll()
|
||||
protected async logout() {
|
||||
const driver = new WebDriver().getDriver();
|
||||
const webElements = await driver.findElements(new Navigation().logoutLink);
|
||||
if (webElements.length > 0) {
|
||||
await webElements[0]?.click?.();
|
||||
await driver.wait(until.urlContains(`${process.env.HOST_IP}:${process.env.APP_PORT}`));
|
||||
}
|
||||
}
|
||||
}
|
16
source/selenium/src/steps/home.steps.ts
Normal file
16
source/selenium/src/steps/home.steps.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { binding, given } from 'cucumber-tsflow';
|
||||
|
||||
import { BaseStep } from '../common/BaseStep';
|
||||
import { HomePage } from '../pages/HomePage';
|
||||
|
||||
@binding([HomePage])
|
||||
export class HomePageSteps extends BaseStep {
|
||||
public constructor(public readonly homePage: HomePage) {
|
||||
super();
|
||||
}
|
||||
|
||||
@given(/i visit home page/)
|
||||
public async givenIamOnHomePage() {
|
||||
await this.driver.get(this.homePage.getPageUrl());
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue