Feature/3 pilots page and drawer (#17)

* adding pilots page and drawer component

* adding pilot page and pilot drawer
This commit was merged in pull request #17.
This commit is contained in:
2024-05-30 22:15:43 -05:00
committed by GitHub
parent 6782c1906d
commit dd73d48ffd
21 changed files with 878 additions and 14 deletions

View File

@@ -11,7 +11,12 @@
}, },
"dependencies": { "dependencies": {
"@azure/msal-react": "^2.0.15", "@azure/msal-react": "^2.0.15",
"@fortawesome/fontawesome-svg-core": "^6.5.2",
"@fortawesome/free-regular-svg-icons": "^6.5.2",
"@fortawesome/free-solid-svg-icons": "^6.5.2",
"@fortawesome/react-fontawesome": "^0.2.2",
"@nextui-org/react": "^2.3.6", "@nextui-org/react": "^2.3.6",
"@noahspan/noahspan-components": "^0.2.4",
"axios": "^1.7.2", "axios": "^1.7.2",
"framer-motion": "^11.1.7", "framer-motion": "^11.1.7",
"react": "^18.2.0", "react": "^18.2.0",

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -1,12 +1,65 @@
import { useState } from 'react';
import SiteNav from '../siteNav/SiteNav'; import SiteNav from '../siteNav/SiteNav';
import PilotForm from '../pilotForm/PilotForm'; import PilotForm from '../pilotForm/PilotForm';
import { Button } from '@nextui-org/react';
import {
Drawer,
DrawerBody,
DrawerContent,
DrawerFooter,
DrawerHeader
} from '@noahspan/noahspan-components';
import { faPlus } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
const Pilots: React.FC<unknown> = () => { const Pilots: React.FC<unknown> = () => {
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
const onOpenCloseDrawer = () => {
setIsDrawerOpen(!isDrawerOpen);
};
return ( return (
<div> <div className="container mx-auto">
<SiteNav /> <SiteNav />
<div> <div className="px-6">
<h1 role="heading">Pilots</h1>
<Button
color="default"
variant="light"
onClick={onOpenCloseDrawer}
startContent={<FontAwesomeIcon icon={faPlus} />}
data-testid="new-pilot-button"
>
New
</Button>
<Drawer isOpen={isDrawerOpen} data-testid="pilot-drawer">
<DrawerContent>
<DrawerHeader>
<h2>Add Pilot</h2>
</DrawerHeader>
<DrawerBody>
<PilotForm /> <PilotForm />
</DrawerBody>
<DrawerFooter>
<div className="flex gap-4 justify-end justify-self-center">
<div>
<Button
color="default"
onClick={onOpenCloseDrawer}
data-testid="pilot-drawer-cancel-button"
>
Cancel
</Button>
</div>
<div>
<Button color="primary" onClick={onOpenCloseDrawer}>
Save
</Button>
</div>
</div>
</DrawerFooter>
</DrawerContent>
</Drawer>
</div> </div>
</div> </div>
); );

View File

@@ -10,6 +10,7 @@ import {
import { Link as ReactRouterLink } from 'react-router-dom'; import { Link as ReactRouterLink } from 'react-router-dom';
import { useIsAuthenticated, useMsal } from '@azure/msal-react'; import { useIsAuthenticated, useMsal } from '@azure/msal-react';
import { useAppContext } from '../../hooks/appContext/UseAppContext'; import { useAppContext } from '../../hooks/appContext/UseAppContext';
import { Logo, Plane } from '@noahspan/noahspan-components';
const SiteNav: React.FC<unknown> = () => { const SiteNav: React.FC<unknown> = () => {
const isAuthenticated = useIsAuthenticated(); const isAuthenticated = useIsAuthenticated();
@@ -22,8 +23,18 @@ const SiteNav: React.FC<unknown> = () => {
console.log(accounts); console.log(accounts);
return ( return (
<Navbar isBordered> <Navbar
<NavbarBrand>Site Logo Goes Here</NavbarBrand> classNames={{
base: 'bg-transparent z-0'
}}
isBlurred={false}
maxWidth="full"
data-testid="flying-navbar"
>
<NavbarBrand>
<Logo className="pr-3" height={50} width={50} data-testid="logo" />
<Plane size="2xl" />
</NavbarBrand>
<NavbarContent justify="center"> <NavbarContent justify="center">
<NavbarItem> <NavbarItem>
{appContext.state.featureFlags.find( {appContext.state.featureFlags.find(
@@ -37,7 +48,13 @@ const SiteNav: React.FC<unknown> = () => {
</NavbarContent> </NavbarContent>
<NavbarContent justify="end"> <NavbarContent justify="end">
{!isAuthenticated && ( {!isAuthenticated && (
<Button as={Link} color="primary" href="#" onClick={initializeLogin}> <Button
as={Link}
color="primary"
href="#"
onClick={initializeLogin}
data-testid="login-link"
>
Login Login
</Button> </Button>
)} )}

View File

@@ -1,3 +1,12 @@
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
@layer base {
h1 {
@apply text-2xl font-bold leading-7 text-gray-900;
}
h2 {
@apply text-2xl font-bold leading-7 text-gray-900;
}
}

View File

@@ -7,6 +7,7 @@ import App from './App.tsx';
import { BrowserRouter } from 'react-router-dom'; import { BrowserRouter } from 'react-router-dom';
import AppContextProvider from './context/appContext/AppContextProvider.tsx'; import AppContextProvider from './context/appContext/AppContextProvider.tsx';
import './index.css'; import './index.css';
import '@noahspan/noahspan-components/noahspan-components.css';
const configuration: Configuration = { const configuration: Configuration = {
auth: { auth: {

113
package-lock.json generated
View File

@@ -12,9 +12,6 @@
"app", "app",
"tests" "tests"
], ],
"dependencies": {
"@azure/app-configuration": "^1.6.0"
},
"devDependencies": { "devDependencies": {
"@typescript-eslint/eslint-plugin": "^7.2.0", "@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.2.0", "@typescript-eslint/parser": "^7.2.0",
@@ -66,7 +63,12 @@
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@azure/msal-react": "^2.0.15", "@azure/msal-react": "^2.0.15",
"@fortawesome/fontawesome-svg-core": "^6.5.2",
"@fortawesome/free-regular-svg-icons": "^6.5.2",
"@fortawesome/free-solid-svg-icons": "^6.5.2",
"@fortawesome/react-fontawesome": "^0.2.2",
"@nextui-org/react": "^2.3.6", "@nextui-org/react": "^2.3.6",
"@noahspan/noahspan-components": "^0.2.4",
"axios": "^1.7.2", "axios": "^1.7.2",
"framer-motion": "^11.1.7", "framer-motion": "^11.1.7",
"react": "^18.2.0", "react": "^18.2.0",
@@ -2070,6 +2072,75 @@
"tslib": "^2.4.0" "tslib": "^2.4.0"
} }
}, },
"node_modules/@fortawesome/fontawesome-common-types": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz",
"integrity": "sha512-gBxPg3aVO6J0kpfHNILc+NMhXnqHumFxOmjYCFfOiLZfwhnnfhtsdA2hfJlDnj+8PjAs6kKQPenOTKj3Rf7zHw==",
"hasInstallScript": true,
"engines": {
"node": ">=6"
}
},
"node_modules/@fortawesome/fontawesome-svg-core": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.2.tgz",
"integrity": "sha512-5CdaCBGl8Rh9ohNdxeeTMxIj8oc3KNBgIeLMvJosBMdslK/UnEB8rzyDRrbKdL1kDweqBPo4GT9wvnakHWucZw==",
"hasInstallScript": true,
"dependencies": {
"@fortawesome/fontawesome-common-types": "6.5.2"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@fortawesome/free-brands-svg-icons": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.5.2.tgz",
"integrity": "sha512-zi5FNYdmKLnEc0jc0uuHH17kz/hfYTg4Uei0wMGzcoCL/4d3WM3u1VMc0iGGa31HuhV5i7ZK8ZlTCQrHqRHSGQ==",
"hasInstallScript": true,
"dependencies": {
"@fortawesome/fontawesome-common-types": "6.5.2"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@fortawesome/free-regular-svg-icons": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.5.2.tgz",
"integrity": "sha512-iabw/f5f8Uy2nTRtJ13XZTS1O5+t+anvlamJ3zJGLEVE2pKsAWhPv2lq01uQlfgCX7VaveT3EVs515cCN9jRbw==",
"hasInstallScript": true,
"dependencies": {
"@fortawesome/fontawesome-common-types": "6.5.2"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@fortawesome/free-solid-svg-icons": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.2.tgz",
"integrity": "sha512-QWFZYXFE7O1Gr1dTIp+D6UcFUF0qElOnZptpi7PBUMylJh+vFmIedVe1Ir6RM1t2tEQLLSV1k7bR4o92M+uqlw==",
"hasInstallScript": true,
"dependencies": {
"@fortawesome/fontawesome-common-types": "6.5.2"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@fortawesome/react-fontawesome": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.2.tgz",
"integrity": "sha512-EnkrprPNqI6SXJl//m29hpaNzOp1bruISWaOiRtkMi/xSvHJlzc2j2JAYS7egxt/EbjSNV/k6Xy0AQI6vB2+1g==",
"dependencies": {
"prop-types": "^15.8.1"
},
"peerDependencies": {
"@fortawesome/fontawesome-svg-core": "~1 || ~6",
"react": ">=16.3"
}
},
"node_modules/@humanwhocodes/config-array": { "node_modules/@humanwhocodes/config-array": {
"version": "0.11.14", "version": "0.11.14",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
@@ -4402,6 +4473,27 @@
"resolved": "app", "resolved": "app",
"link": true "link": true
}, },
"node_modules/@noahspan/noahspan-components": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/@noahspan/noahspan-components/-/noahspan-components-0.2.4.tgz",
"integrity": "sha512-wj5j83HTIv2fXsGyA2OwO3zBhaiwoPV/rE+4CUxU4Lj/3swzhw2LL+Rzq7SWUzwYux0r+YQjzKXg+Mix+jueYQ==",
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.5.2",
"@fortawesome/free-brands-svg-icons": "^6.5.2",
"@fortawesome/free-regular-svg-icons": "^6.5.2",
"@fortawesome/free-solid-svg-icons": "^6.5.2",
"@fortawesome/react-fontawesome": "^0.2.0",
"@nextui-org/react": "^2.3.6",
"framer-motion": "^11.1.9"
},
"engines": {
"node": ">=18.0.0"
},
"peerDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
},
"node_modules/@noahspan/noahspan-modules": { "node_modules/@noahspan/noahspan-modules": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/@noahspan/noahspan-modules/-/noahspan-modules-0.1.2.tgz", "resolved": "https://registry.npmjs.org/@noahspan/noahspan-modules/-/noahspan-modules-0.1.2.tgz",
@@ -12328,6 +12420,21 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
"dependencies": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
"react-is": "^16.13.1"
}
},
"node_modules/prop-types/node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/property-expr": { "node_modules/property-expr": {
"version": "2.0.6", "version": "2.0.6",
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz",

View File

@@ -24,8 +24,5 @@
}, },
"lint-staged": { "lint-staged": {
"**/*": "prettier --write \"**/src/**/*.ts\" \"**/test/**/*.ts\" --ignore-unknown" "**/*": "prettier --write \"**/src/**/*.ts\" \"**/test/**/*.ts\" --ignore-unknown"
},
"dependencies": {
"@azure/app-configuration": "^1.6.0"
} }
} }

1
tests/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
e2e/results

View File

@@ -0,0 +1,17 @@
import dotenv from 'dotenv';
dotenv.config({ path: '.env' });
const config = {
requireModule: ['ts-node/register'],
require: ['e2e/support/hooks.ts', 'e2e/steps/*.steps.ts'],
format: [
'progress-bar',
'json:e2e/results/report/report.json',
'rerun:e2e/results/@rerun.txt'
],
formatOptions: { snippetInterface: 'async-await' },
parallel: Number(process.env.PARALLEL) ? Number(process.env.PARALLEL) : 1
};
export default config;

View File

@@ -0,0 +1,14 @@
@pilots
Feature: Pilots
Background: Navigate to the Pilots page
Given the user is on the homepage
When the user clicks the "Pilots" navbar link
Then the user is on the "Pilots" page
Scenario: Cancel Add Pilot drawer
Given the user is on the "Pilots" page
When the user clicks the New button
Then the pilot drawer is visible
When the user clicks the pilot drawer cancel button
Then the pilot drawer is no longer visible

View File

@@ -0,0 +1,28 @@
import { Locator, Page } from '@playwright/test';
import { config } from '../support/config';
export class CommonPage {
page: Page;
loginLink: Locator;
navbarLinks: Locator;
pageHeading: Locator;
constructor(page: Page) {
this.page = page;
this.loginLink = page.getByTestId('login-link');
this.navbarLinks = page.getByTestId('flying-navbar').getByRole('link');
this.pageHeading = page.getByRole('heading');
}
public async goto() {
await this.page.goto(config.baseUrl);
}
public async clickLoginLink() {
await this.loginLink.click();
}
public async clickNavbarLink(navbarLinkName: string) {
await this.navbarLinks.filter({ hasText: navbarLinkName });
}
}

View File

@@ -0,0 +1,26 @@
import { Locator, Page } from '@playwright/test';
import { config } from '../support/config';
export class PilotsPage {
page: Page;
newButton: Locator;
pilotDrawer: Locator;
pilotDrawerCancelButton: Locator;
constructor(page: Page) {
this.page = page;
this.newButton = page.getByTestId('new-pilot-button');
this.pilotDrawer = page.getByTestId('pilot-drawer');
this.pilotDrawerCancelButton = page.getByTestId(
'pilot-drawer-cancel-button'
);
}
public async clickNewButton() {
await this.newButton.click();
}
public async clickPilotDrawerCancelButton() {
await this.pilotDrawerCancelButton.click();
}
}

View File

@@ -0,0 +1,31 @@
import { ICustomWorld } from '../support/world';
import { Given, When, Then } from '@cucumber/cucumber';
import { config } from '../support/config';
import { expect } from '@playwright/test';
import { CommonPage } from '../pages/common.page';
Given('the user is on the homepage', async function (this: ICustomWorld) {
const commonPage = new CommonPage(this.page!);
await commonPage.goto();
});
When(
'the user clicks the {string} navbar link',
async function (this: ICustomWorld, navbarLinkName: string) {
const commonPage = new CommonPage(this.page!);
await commonPage.clickNavbarLink(navbarLinkName);
}
);
Then(
'the user is on the {string} page',
async function (this: ICustomWorld, pageHeadingText: string) {
const commonPage = new CommonPage(this.page!);
await expect(
commonPage.pageHeading.filter({ hasText: pageHeadingText })
).toHaveText('Pilots');
}
);

View File

@@ -0,0 +1,35 @@
import { ICustomWorld } from '../support/world';
import { Given, Then, When } from '@cucumber/cucumber';
import { config } from '../support/config';
import { expect } from '@playwright/test';
import { PilotsPage } from '../pages/pilots.page';
When('the user clicks the New button', async function (this: ICustomWorld) {
const pilotsPage = new PilotsPage(this.page!);
await pilotsPage.clickNewButton();
});
When(
'the user clicks the pilot drawer cancel button',
async function (this: ICustomWorld) {
const pilotsPage = new PilotsPage(this.page!);
await pilotsPage.clickPilotDrawerCancelButton();
}
);
Then('the pilot drawer is visible', async function (this: ICustomWorld) {
const pilotsPage = new PilotsPage(this.page!);
await expect(pilotsPage.pilotDrawer).toBeVisible();
});
Then(
'the pilot drawer is no longer visible',
async function (this: ICustomWorld) {
const pilotsPage = new PilotsPage(this.page!);
await expect(pilotsPage.pilotDrawer).not.toBeVisible();
}
);

View File

@@ -0,0 +1,195 @@
{
"cookies": [
{
"name": "esctx-ljf1P4LvjbI",
"value": "AQABCQEAAADnfolhJpSnRYB1SVj-Hgd8TWnAti-t1CIVyn4HTaxc2XQAG6lqgm5UGG9zZ6aTsn3KL3KwVvwPlDyWdHoTqciPQEvzdolOwb7gWVPqdWfUL0VVLPvSrH450zcVBA-UL8YPFdtxw21bwn-SFvQXtTs8uvR6GGJsJfTlqzxx8Kvp6yAA",
"domain": ".login.microsoftonline.com",
"path": "/",
"expires": 1717034520.24429,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "x-ms-gateway-slice",
"value": "estsfd",
"domain": "login.microsoftonline.com",
"path": "/",
"expires": -1,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "stsservicecookie",
"value": "estsfd",
"domain": "login.microsoftonline.com",
"path": "/",
"expires": -1,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "AADSSO",
"value": "NA|NoExtension",
"domain": ".login.microsoftonline.com",
"path": "/",
"expires": -1,
"httpOnly": false,
"secure": true,
"sameSite": "None"
},
{
"name": "SSOCOOKIEPULLED",
"value": "1",
"domain": "login.microsoftonline.com",
"path": "/",
"expires": 1717033079,
"httpOnly": false,
"secure": true,
"sameSite": "None"
},
{
"name": "esctx-WlUBojxe7EE",
"value": "AQABCQEAAADnfolhJpSnRYB1SVj-Hgd8LQYOKD7XbJ28P6Z_MV7kLlohBtx-jqFtxm_SSIng5cJy9uUflVqhkPSmacEheabIyuIGzST_c33rBXi0S8xgC41e-Zu2fhCFEnqcqRL87nj_cBqblMB2kNThZ7M-9uqC8I7WJxdwByo3fVKFr8_OEiAA",
"domain": ".login.microsoftonline.com",
"path": "/",
"expires": 1717034519.611161,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "brcap",
"value": "0",
"domain": ".login.microsoftonline.com",
"path": "/",
"expires": 1750729019,
"httpOnly": false,
"secure": true,
"sameSite": "None"
},
{
"name": "wlidperf",
"value": "FR=L&ST=1717033036323",
"domain": ".microsoftonline.com",
"path": "/",
"expires": 1750729036,
"httpOnly": false,
"secure": true,
"sameSite": "None"
},
{
"name": "ESTSAUTHLIGHT",
"value": "+c9e68190-019f-41a9-bcb2-a342d2ffaca4",
"domain": "login.microsoftonline.com",
"path": "/",
"expires": -1,
"httpOnly": false,
"secure": true,
"sameSite": "None"
},
{
"name": "esctx",
"value": "PAQABBwEAAADnfolhJpSnRYB1SVj-Hgd8UIN4Cdn7PYdlVvq1XBRR5XuuP5PJGrywv6VoauNOofrWVKbZoTGJc07rARSTQOfTgrLsS2bA5gI13qGJeVme3n4_qnUfhU_nGkweMbheT2pwidKT_uXRP6WxWXwpyEjTRN_k2AEmQCKrWnARm0MyO8hqZfMWpjSu6-6HdA3PxGsgAA",
"domain": ".login.microsoftonline.com",
"path": "/",
"expires": -1,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "esctx-pQvAYCeysek",
"value": "AQABCQEAAADnfolhJpSnRYB1SVj-Hgd8H2-WoEzYDEcBbs3HMkOHNUVTpjEcCLiaIoUbGNA3uWRTjdkf1aQUbpLE4ku2AIEtnsRcRChVNFaF5Mfa-iPpFesrUdqaL0V9U-484-1jVy3HwpNH4bwpH-aoB1KI4xAxeJAdujqZqe69goLiNrZt4iAA",
"domain": ".login.microsoftonline.com",
"path": "/",
"expires": 1717034537.496481,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "uaid",
"value": "06fe72e1d1ae4a8bad7e6014202a3913",
"domain": ".login.live.com",
"path": "/",
"expires": -1,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "MSPRequ",
"value": "id=N&lt=1717033036&co=0",
"domain": ".login.live.com",
"path": "/",
"expires": -1,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "ESTSAUTHPERSISTENT",
"value": "0.AXcALmUjDxVLD0KZHj1vx2mjHUUqVtMNBZpPuu0El8cVaSR3AAA.AgABFwQAAADnfolhJpSnRYB1SVj-Hgd8AgDs_wUA9P-YEY-b7d127C-cvQuXU-okGFV6Bl9_A_yxThodV0oCny0S92cxFRr1fkk6N6QxE8_B2DNQZ4U8tyDbYn25M3cKuH2KXqo0M601DBzIDkNvnyQN35xU-G9Yh8U1HkhnjOSeII2fZBk56-1tZrV-ivzjIeQeedOs_04FtjfB9G6pub-JTDlx8NCOK-3T56A39cbO6f3uighR6wItEuul1ArYlhAIhxf1LgjoPKXbsrhrg2whlksnMNgnylWLRvR24QDiqH6i7Pm6K-2Czxnaq4M2mf1za-vtoR1gTEVDI12njnfTSSroDd8IpLB89WY7_O1uhTThswHL81caYLd0B6K-UmawPY0HH9XxjeB3fzUyobTURBDyv8Kl6_WHKuOrH8f2GW9JqwZZr0sXWZKfhmtqy7El19R6vnigFtOo0wUL8e3SSZV3tTB3fis31cjgGQ-VYqiJqPW90cf3pHgTf-iRDGwCOp2sc93T51ZOhrqSxHK2zSK_iX70a3QR-D9YYR7Inqi11LFWuNxnCOq9TgC9WSgRe-4vhWTXfGO2DB7tJlQuplwiNBq9-Md5X579l1FD",
"domain": ".login.microsoftonline.com",
"path": "/",
"expires": 1724809039.632935,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "ESTSAUTH",
"value": "0.AXcALmUjDxVLD0KZHj1vx2mjHUUqVtMNBZpPuu0El8cVaSR3AAA.AgABFwQAAADnfolhJpSnRYB1SVj-Hgd8AgDs_wUA9P9PQzpL9ewclx9R8lP7jVbeAYG8GtIZaMY3fpJb6tViHgrt2i4T2Hw9XKr-tVg68HsAONh9126lpQ",
"domain": ".login.microsoftonline.com",
"path": "/",
"expires": -1,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "buid",
"value": "0.AXcALmUjDxVLD0KZHj1vx2mjHUUqVtMNBZpPuu0El8cVaSR3AAA.AQABGgEAAADnfolhJpSnRYB1SVj-Hgd8nPNt4hKw4Sbl4pz8ODy7iASMy5l3Cp5niRXWyO2N-GFUVcvftqEhy9NqLvt9tsb26JY2wkqr0hQIYf3akDIepL9GuczwHlQN61odPfQJphiCxcy6ZJ_ybgeNCBsKeAlF1zkRYyfuJioWYEFyAXviXSkKJBqxbxbaD-yHhsPLoDIgAA",
"domain": "login.microsoftonline.com",
"path": "/",
"expires": 1719625039.633177,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "CCState",
"value": "RWhJS0VONG0zVXQ4VFU1SnRsMWZra1QySldNPQ==",
"domain": ".login.microsoftonline.com",
"path": "/",
"expires": 1717897039.63325,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "SignInStateCookie",
"value": "CAgABFgIAAADnfolhJpSnRYB1SVj-Hgd8AgDs_wUA9P_6MAoUQd6gAgbrnuM4I6vxj-Uv7XvCG4rE_U1mJU2DFokdMOEJCap5Hq62skJPAvoUS80HVkDr9pmbkWQohDcrv2jfkp2JRcmBs2BoKhDV5Nci-0h9AbnA6micsCMZxWXlnXbfVEnmyF2qiYY0zSJ5PAK9f6rH9OG5XBmJb-QxB8WY3Rdx990nu_ZYgfTtz3H4oRIgvajVUtBwrZwvLCUgpLIWe45HHA7cHcKZfiaRTMjTlmfhYx5T-KCaJLDWqVuVuQ",
"domain": ".login.microsoftonline.com",
"path": "/",
"expires": -1,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "fpc",
"value": "Al_0vK2yLy9BsxW01vSqMjdYBhOdAQAAADvP6d0OAAAAlQhyDwEAAABLz-ndDgAAAGjYt1sBAAAATs_p3Q4AAAA",
"domain": "login.microsoftonline.com",
"path": "/",
"expires": 1719625039.633357,
"httpOnly": true,
"secure": true,
"sameSite": "None"
}
],
"origins": []
}

View File

@@ -0,0 +1,245 @@
{
"cookies": [
{
"name": "esctx-lZpsH7K0xs",
"value": "AQABCQEAAADnfolhJpSnRYB1SVj-Hgd8hZmykvokkKTJopdXhTSHymz1Q-9QXLZPVr3oBddbWQikcfHT9lQCtrCqzwlbDIMo_8YdqnVlLsd4q64cWWA8Ei_asi3Fg6a8RqNpHngAvysdiKxpsZ40BCiBtZbPVBuvMYCr_L29uPTRNdnXqZdWEiAA",
"domain": ".login.microsoftonline.com",
"path": "/",
"expires": 1717034316.401691,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "x-ms-gateway-slice",
"value": "estsfd",
"domain": "login.microsoftonline.com",
"path": "/",
"expires": -1,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "stsservicecookie",
"value": "estsfd",
"domain": "login.microsoftonline.com",
"path": "/",
"expires": -1,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "AADSSO",
"value": "NA|NoExtension",
"domain": ".login.microsoftonline.com",
"path": "/",
"expires": -1,
"httpOnly": false,
"secure": true,
"sameSite": "None"
},
{
"name": "SSOCOOKIEPULLED",
"value": "1",
"domain": "login.microsoftonline.com",
"path": "/",
"expires": 1717032875,
"httpOnly": false,
"secure": true,
"sameSite": "None"
},
{
"name": "esctx-LHb5kGh6RUU",
"value": "AQABCQEAAADnfolhJpSnRYB1SVj-Hgd8o01qTziHeo5QXKa1lRZ8fAdaDGwf_s2N0OA44ej2RxDN4PS35C1XD9BBgnjTYj2m4KEQKStlrarsNx1V_AWWV1rXfLKuKQl53FTUHDkOnTAGps2pEOMqONOK8jkjcZAr4QdL-26MaLHMQqcWxV20tyAA",
"domain": ".login.microsoftonline.com",
"path": "/",
"expires": 1717034316.704943,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "MicrosoftApplicationsTelemetryDeviceId",
"value": "920534cf-892b-4d4e-ba72-c841515afb37",
"domain": "login.microsoftonline.com",
"path": "/",
"expires": 1748568849.524212,
"httpOnly": false,
"secure": true,
"sameSite": "None"
},
{
"name": "brcap",
"value": "0",
"domain": ".login.microsoftonline.com",
"path": "/",
"expires": 1750728816,
"httpOnly": false,
"secure": true,
"sameSite": "None"
},
{
"name": "MC1",
"value": "GUID=dbb77480c2ff41e8a937520a317880e7&HASH=dbb7&LV=202405&V=4&LU=1717032821181",
"domain": ".microsoft.com",
"path": "/",
"expires": 1748568822.161277,
"httpOnly": false,
"secure": true,
"sameSite": "None"
},
{
"name": "MS0",
"value": "31c8801b79e34bb983ebefbfda3ab931",
"domain": ".microsoft.com",
"path": "/",
"expires": 1717034622.161473,
"httpOnly": false,
"secure": true,
"sameSite": "None"
},
{
"name": "MSFPC",
"value": "GUID=dbb77480c2ff41e8a937520a317880e7&HASH=dbb7&LV=202405&V=4&LU=1717032821181",
"domain": "login.microsoftonline.com",
"path": "/",
"expires": 1748568821.164214,
"httpOnly": false,
"secure": true,
"sameSite": "None"
},
{
"name": "wlidperf",
"value": "FR=L&ST=1717032849241",
"domain": ".microsoftonline.com",
"path": "/",
"expires": 1750728849,
"httpOnly": false,
"secure": true,
"sameSite": "None"
},
{
"name": "ESTSAUTHLIGHT",
"value": "+05efde93-b4f6-4ede-8c5c-fe47f4c5d7e5",
"domain": "login.microsoftonline.com",
"path": "/",
"expires": -1,
"httpOnly": false,
"secure": true,
"sameSite": "None"
},
{
"name": "esctx",
"value": "PAQABBwEAAADnfolhJpSnRYB1SVj-Hgd8rrydzYKF9brJW_jQBufFdZx6ZGVeX4jXCGo6RNJS8TJWeO0kToxXJ0zDFWPvF2a2pJ3zN-NNFvr4wY1gTjIk6DrZCEnUrh8k7S7_XOVAibVHnqa-WBQqbzU5SlPiYiwPDSSIiECjEnLPhABvlbOdDU7zufgmJONNA7V4VBVGG5wgAA",
"domain": ".login.microsoftonline.com",
"path": "/",
"expires": -1,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "esctx-60xcpVEzckI",
"value": "AQABCQEAAADnfolhJpSnRYB1SVj-Hgd8DW2ZkuQs5Rjax8TEQwS1kknBdNvzANuWbEd2_Om-37nyCV25djwAyERNOoFMRwJQ9k0NEtpUlFqkt0oeXrTNgHdBp9C-mC5ULKueywLaMjF28yicOKAdugcdKxuv3mgIQbQ2dcEryW1hV1nZARbPlSAA",
"domain": ".login.microsoftonline.com",
"path": "/",
"expires": 1717034350.405847,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "uaid",
"value": "81e53585ebea44eea426512649fd69f0",
"domain": ".login.live.com",
"path": "/",
"expires": -1,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "MSPRequ",
"value": "id=N&lt=1717032849&co=0",
"domain": ".login.live.com",
"path": "/",
"expires": -1,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "ai_session",
"value": "iwsUpdj0G4S8ibK80pbceM|1717032816832|1717032850210",
"domain": "login.microsoftonline.com",
"path": "/",
"expires": 1717034650,
"httpOnly": false,
"secure": true,
"sameSite": "None"
},
{
"name": "ESTSAUTHPERSISTENT",
"value": "0.AXcALmUjDxVLD0KZHj1vx2mjHUUqVtMNBZpPuu0El8cVaSR3AAA.AgABFwQAAADnfolhJpSnRYB1SVj-Hgd8AgDs_wUA9P-6GAHRVAPpbKtWmDljdtGF6pqwyoI9PycjNbG-koB1RMEzGuYciKDsQpI7AsY2aChCTNe3-oFSdDUkE3hPuHFdjDITEaF26D2LQ3zguY-oZWE8UGNGcOTt3mjJlRAxtlc9a8fFSsFYPOB72tDvLeJJs-sNAL6X9uSnelQ5PkTpS3ZGsxkoVBMike8p25Nqg0GG9jfjfHxQVxFWElU5w3kCuG-X-9lE5bh04AyuXuZl4-LEP6h9cXIu62VmpoP4aghvD94KsLk5opBB9G6KWw0S48I472wLTlB9KXlr207_Y1tMd3SDfU5du8FR4V8STEJskVACb0rNQKO_RLkmYEtQy-7b5JMTQBJUK4EpmJlg2ZOrAm29RYqH5OrqlRhSLLA6s-oB8e6bUH7IoM11TB2pqZHtiieevcJp6Nx3hZl8YDimmksgV5JGy4LnkgrvDm0Pug7GxfVYI-1OR8AKPfpuQhtK-DQ36uviuxvvst-tCSJkMS6V53gZEqw2zdKColGy1CZiS0c8UvdYix3rRDSnMF2x-tNxilY5QLPF_Gou629yYeMHl4XXgYOqQEkPX1ZA",
"domain": ".login.microsoftonline.com",
"path": "/",
"expires": 1724808853.484568,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "ESTSAUTH",
"value": "0.AXcALmUjDxVLD0KZHj1vx2mjHUUqVtMNBZpPuu0El8cVaSR3AAA.AgABFwQAAADnfolhJpSnRYB1SVj-Hgd8AgDs_wUA9P9CE_JHzvX38y1LHqrv7IuyLFwZLcv6kZVF9onOFcyuApDDPaDrNRyS08qyKjnvGcjfNK0IJpKYiA",
"domain": ".login.microsoftonline.com",
"path": "/",
"expires": -1,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "buid",
"value": "0.AXcALmUjDxVLD0KZHj1vx2mjHUUqVtMNBZpPuu0El8cVaSR3AAA.AQABGgEAAADnfolhJpSnRYB1SVj-Hgd8IMhpo6W56tEC0yxyzszi2xUdd4MJX_7AgOOuXWmuUZVqXq_i1ievY2R2lCwirhz08eGe82dFwoklNjcUHrPUcMT328XdFAo7oWwwLgvFA-at5ykBxuNOgtKeQtAFgmYypiN_-tDRnfgshJiuZzQF5vAI6Dov48i5vsKT_SGZzlAgAA",
"domain": "login.microsoftonline.com",
"path": "/",
"expires": 1719624853.484812,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "CCState",
"value": "RWhJS0VBV0tQY1luNlZKRG42SUlTcjIvbVNZPQ==",
"domain": ".login.microsoftonline.com",
"path": "/",
"expires": 1717896853.484884,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "SignInStateCookie",
"value": "CAgABFgIAAADnfolhJpSnRYB1SVj-Hgd8AgDs_wUA9P-plMVcqKu73BJxw7BAuaD9ZeURo12GdfU5mL5g21tUEwqex6EFBSy3_ET0yE1YN-0c7XhlDxSAe2ovqN68Vzidj1dXrUZ7MJtXspF7dVRptpXOkR5r0vTQzWqYlRgJmvpeNZqa_vT6SkFD7ywCMfAnxsSIlzxO3JV42jUzBJweIM0ToApGacyIrLgV_zqZnQmIbGvZPA1SVG40mZWC4pSwLIkhChzs8fqW2o6FaPVPOdsFCdaOywKHzVPF1YuIrWu4q64X",
"domain": ".login.microsoftonline.com",
"path": "/",
"expires": -1,
"httpOnly": true,
"secure": true,
"sameSite": "None"
},
{
"name": "fpc",
"value": "AjBuUobXQy9MiI9Zk1zksURYBhOdAQAAAG_O6d0OAAAAm23tYAEAAACQzundDgAAAD8IlT4BAAAAk87p3Q4AAAA",
"domain": "login.microsoftonline.com",
"path": "/",
"expires": 1719624853.485045,
"httpOnly": true,
"secure": true,
"sameSite": "None"
}
],
"origins": []
}

View File

@@ -21,7 +21,7 @@ const desktopChrome = devices['Desktop Chrome'];
export const config = { export const config = {
browser: process.env.BROWSER || 'chromium', browser: process.env.BROWSER || 'chromium',
browserOptions, browserOptions,
baseUrl: process.env.BASE_URL || 'http://localhost:3000', baseUrl: process.env.BASE_URL || 'http://localhost:5173',
username: process.env.TEST_USERNAME, username: process.env.TEST_USERNAME,
password: process.env.TEST_PASSWORD, password: process.env.TEST_PASSWORD,
viewportHeight: process.env.VIEWPORT_HEIGHT || desktopChrome.viewport.height, viewportHeight: process.env.VIEWPORT_HEIGHT || desktopChrome.viewport.height,

View File

@@ -22,6 +22,31 @@ import { ITestCaseHookParameter } from '@cucumber/cucumber/lib/support_code_libr
import { ensureDir } from 'fs-extra'; import { ensureDir } from 'fs-extra';
const tracesDir = './e2e/results/traces'; const tracesDir = './e2e/results/traces';
const getStorageState = (
pickleName: string
):
| string
| {
cookies: {
name: string;
value: string;
domain: string;
path: string;
expires: number;
httpOnly: boolean;
secure: boolean;
sameSite: 'Strict' | 'Lax' | 'None';
}[];
origins: {
origin: string;
localStorage: { name: string; value: string }[];
}[];
}
| undefined => {
if (pickleName.endsWith('admin')) {
return './auth/write.json';
}
};
let browser: ChromiumBrowser | FirefoxBrowser | WebKitBrowser; let browser: ChromiumBrowser | FirefoxBrowser | WebKitBrowser;
declare global { declare global {
@@ -58,6 +83,37 @@ Before({ tags: '@debug' }, async function (this: ICustomWorld) {
this.debug = true; this.debug = true;
}); });
Before(
{ tags: '@noAuth' },
async function (this: ICustomWorld, { pickle }: ITestCaseHookParameter) {
const viewportSize: ViewportSize = {
height: Number(1080),
width: Number(1920)
};
this.startTime = new Date();
this.testName = pickle.name.replace(/\W/g, '-');
this.context = await browser.newContext({
acceptDownloads: true,
viewport: viewportSize,
userAgent: config.userAgent
});
await this.context.tracing.start({
screenshots: true,
snapshots: true
});
this.page = await this.context.newPage();
this.page.on('console', async (msg: ConsoleMessage) => {
if (msg.type() === 'log') {
await this.attach(msg.text());
}
});
this.feature = pickle;
}
);
Before(async function (this: ICustomWorld, { pickle }: ITestCaseHookParameter) { Before(async function (this: ICustomWorld, { pickle }: ITestCaseHookParameter) {
const viewportSize: ViewportSize = { const viewportSize: ViewportSize = {
height: Number(1080), height: Number(1080),
@@ -67,6 +123,7 @@ Before(async function (this: ICustomWorld, { pickle }: ITestCaseHookParameter) {
this.startTime = new Date(); this.startTime = new Date();
this.testName = pickle.name.replace(/\W/g, '-'); this.testName = pickle.name.replace(/\W/g, '-');
this.context = await browser.newContext({ this.context = await browser.newContext({
storageState: getStorageState(pickle.name),
acceptDownloads: true, acceptDownloads: true,
viewport: viewportSize, viewport: viewportSize,
userAgent: config.userAgent userAgent: config.userAgent

View File

@@ -0,0 +1,22 @@
const report = require('multiple-cucumber-html-reporter');
report.generate({
jsonDir: './e2e/results/report',
reportPath: './e2e/results/report',
metadata: {
platform: {
name: 'ubuntu',
version: 'node 16.20.2'
}
},
customData: {
title: 'Run info',
data: [
{ label: 'Project', value: 'Banner CDS' },
{ label: 'Release', value: `${process.env.RELEASE_NUMBER}` },
{ label: 'Run ID', value: `${process.env.RUN_ID}` },
{ label: 'Execution Start Time', value: `${process.env.TEST_START}` },
{ label: 'Execution End Time', value: `${process.env.TEST_END}` }
]
}
});

View File

@@ -4,7 +4,11 @@
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "e2e": "cucumber-js ./e2e/features/**/*.feature",
"e2e:debug": "PWDEBUG=1 cucumber-js",
"e2e:feature": "cucumber-js",
"e2e:report": "node ./e2e/support/support.js",
"e2e:rerun": "cucumber-js ./e2e/results/@rerun.txt"
}, },
"author": "", "author": "",
"license": "ISC", "license": "ISC",