diff --git a/.gitignore b/.gitignore index f52550d9..55a8e719 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,4 @@ rpmbuild /blob-report/ /playwright/.cache/ .env +.auth diff --git a/playwright.config.ts b/playwright.config.ts index fde83958..c6be20e7 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -34,9 +34,14 @@ export default defineConfig({ ignoreHTTPSErrors: true, }, projects: [ + { name: 'setup', testMatch: /.*\.setup\.ts/ }, { name: 'chromium', - use: { ...devices['Desktop Chrome'] }, + use: { + ...devices['Desktop Chrome'], + storageState: '.auth/user.json', + }, + dependencies: ['setup'], }, ], }); diff --git a/playwright/Customizations/Firewall.spec.ts b/playwright/Customizations/Firewall.spec.ts index e2fa5481..ba909e7c 100644 --- a/playwright/Customizations/Firewall.spec.ts +++ b/playwright/Customizations/Firewall.spec.ts @@ -1,10 +1,13 @@ import { expect } from '@playwright/test'; import { v4 as uuidv4 } from 'uuid'; -import { test } from '../fixtures/cleanup'; +import { test } from '../fixtures/customizations'; import { isHosted } from '../helpers/helpers'; -import { login } from '../helpers/login'; -import { navigateToOptionalSteps, ibFrame } from '../helpers/navHelpers'; +import { + navigateToOptionalSteps, + ibFrame, + navigateToLandingPage, +} from '../helpers/navHelpers'; import { registerLater, fillInDetails, @@ -24,8 +27,8 @@ test('Create a blueprint with Firewall customization', async ({ // Delete the blueprint after the run fixture await cleanup.add(() => deleteBlueprint(page, blueprintName)); - // Login, navigate to IB and get the frame - await login(page); + // Navigate to IB landing page and get the frame + await navigateToLandingPage(page); const frame = await ibFrame(page); await test.step('Navigate to optional steps in Wizard', async () => { diff --git a/playwright/Customizations/Hostname.spec.ts b/playwright/Customizations/Hostname.spec.ts index 509635b3..dff4e848 100644 --- a/playwright/Customizations/Hostname.spec.ts +++ b/playwright/Customizations/Hostname.spec.ts @@ -1,10 +1,13 @@ import { expect } from '@playwright/test'; import { v4 as uuidv4 } from 'uuid'; -import { test } from '../fixtures/cleanup'; +import { test } from '../fixtures/customizations'; import { isHosted } from '../helpers/helpers'; -import { login } from '../helpers/login'; -import { navigateToOptionalSteps, ibFrame } from '../helpers/navHelpers'; +import { + navigateToOptionalSteps, + ibFrame, + navigateToLandingPage, +} from '../helpers/navHelpers'; import { registerLater, fillInDetails, @@ -25,8 +28,8 @@ test('Create a blueprint with Hostname customization', async ({ // Delete the blueprint after the run fixture await cleanup.add(() => deleteBlueprint(page, blueprintName)); - // Login, navigate to IB and get the frame - await login(page); + // Navigate to IB landing page and get the frame + await navigateToLandingPage(page); const frame = await ibFrame(page); await test.step('Navigate to optional steps in Wizard', async () => { diff --git a/playwright/Customizations/Kernel.spec.ts b/playwright/Customizations/Kernel.spec.ts index 7a3f28b9..89bbc5dd 100644 --- a/playwright/Customizations/Kernel.spec.ts +++ b/playwright/Customizations/Kernel.spec.ts @@ -1,10 +1,13 @@ import { expect } from '@playwright/test'; import { v4 as uuidv4 } from 'uuid'; -import { test } from '../fixtures/cleanup'; +import { test } from '../fixtures/customizations'; import { isHosted } from '../helpers/helpers'; -import { login } from '../helpers/login'; -import { navigateToOptionalSteps, ibFrame } from '../helpers/navHelpers'; +import { + navigateToOptionalSteps, + ibFrame, + navigateToLandingPage, +} from '../helpers/navHelpers'; import { registerLater, fillInDetails, @@ -24,8 +27,8 @@ test('Create a blueprint with Kernel customization', async ({ // Delete the blueprint after the run fixture await cleanup.add(() => deleteBlueprint(page, blueprintName)); - // Login, navigate to IB and get the frame - await login(page); + // Navigate to IB landing page and get the frame + await navigateToLandingPage(page); const frame = await ibFrame(page); await test.step('Navigate to optional steps in Wizard', async () => { diff --git a/playwright/Customizations/Locale.spec.ts b/playwright/Customizations/Locale.spec.ts index af580176..8f628250 100644 --- a/playwright/Customizations/Locale.spec.ts +++ b/playwright/Customizations/Locale.spec.ts @@ -1,10 +1,13 @@ import { expect } from '@playwright/test'; import { v4 as uuidv4 } from 'uuid'; -import { test } from '../fixtures/cleanup'; +import { test } from '../fixtures/customizations'; import { isHosted } from '../helpers/helpers'; -import { login } from '../helpers/login'; -import { navigateToOptionalSteps, ibFrame } from '../helpers/navHelpers'; +import { + navigateToOptionalSteps, + ibFrame, + navigateToLandingPage, +} from '../helpers/navHelpers'; import { registerLater, fillInDetails, @@ -24,8 +27,8 @@ test('Create a blueprint with Locale customization', async ({ // Delete the blueprint after the run fixture await cleanup.add(() => deleteBlueprint(page, blueprintName)); - // Login, navigate to IB and get the frame - await login(page); + // Navigate to IB landing page and get the frame + await navigateToLandingPage(page); const frame = await ibFrame(page); await test.step('Navigate to optional steps in Wizard', async () => { diff --git a/playwright/Customizations/Systemd.spec.ts b/playwright/Customizations/Systemd.spec.ts index 0586f01c..499703eb 100644 --- a/playwright/Customizations/Systemd.spec.ts +++ b/playwright/Customizations/Systemd.spec.ts @@ -1,10 +1,13 @@ import { expect } from '@playwright/test'; import { v4 as uuidv4 } from 'uuid'; -import { test } from '../fixtures/cleanup'; +import { test } from '../fixtures/customizations'; import { isHosted } from '../helpers/helpers'; -import { login } from '../helpers/login'; -import { navigateToOptionalSteps, ibFrame } from '../helpers/navHelpers'; +import { + navigateToOptionalSteps, + ibFrame, + navigateToLandingPage, +} from '../helpers/navHelpers'; import { registerLater, fillInDetails, @@ -24,8 +27,8 @@ test('Create a blueprint with Systemd customization', async ({ // Delete the blueprint after the run fixture await cleanup.add(() => deleteBlueprint(page, blueprintName)); - // Login, navigate to IB and get the frame - await login(page); + // Navigate to IB landing page and get the frame + await navigateToLandingPage(page); const frame = await ibFrame(page); await test.step('Navigate to optional steps in Wizard', async () => { diff --git a/playwright/Customizations/Timezone.spec.ts b/playwright/Customizations/Timezone.spec.ts index 3c78e2d2..403d6ef9 100644 --- a/playwright/Customizations/Timezone.spec.ts +++ b/playwright/Customizations/Timezone.spec.ts @@ -1,10 +1,13 @@ import { expect } from '@playwright/test'; import { v4 as uuidv4 } from 'uuid'; -import { test } from '../fixtures/cleanup'; +import { test } from '../fixtures/customizations'; import { isHosted } from '../helpers/helpers'; -import { login } from '../helpers/login'; -import { navigateToOptionalSteps, ibFrame } from '../helpers/navHelpers'; +import { + navigateToOptionalSteps, + ibFrame, + navigateToLandingPage, +} from '../helpers/navHelpers'; import { registerLater, fillInDetails, @@ -24,8 +27,8 @@ test('Create a blueprint with Timezone customization', async ({ // Delete the blueprint after the run fixture await cleanup.add(() => deleteBlueprint(page, blueprintName)); - // Login, navigate to IB and get the frame - await login(page); + // Navigate to IB landing page and get the frame + await navigateToLandingPage(page); const frame = await ibFrame(page); await test.step('Navigate to optional steps in Wizard', async () => { diff --git a/playwright/fixtures/customizations.ts b/playwright/fixtures/customizations.ts new file mode 100644 index 00000000..ea926454 --- /dev/null +++ b/playwright/fixtures/customizations.ts @@ -0,0 +1,8 @@ +// This is a common fixture for the customizations tests +import { mergeTests } from '@playwright/test'; + +import { test as cleanupTest } from './cleanup'; +import { test as popupTest } from './popupHandler'; + +// Combine the fixtures into one +export const test = mergeTests(cleanupTest, popupTest); diff --git a/playwright/fixtures/popupHandler.ts b/playwright/fixtures/popupHandler.ts new file mode 100644 index 00000000..dad80348 --- /dev/null +++ b/playwright/fixtures/popupHandler.ts @@ -0,0 +1,19 @@ +import { test as base } from '@playwright/test'; + +import { closePopupsIfExist } from '../helpers/helpers'; + +export interface PopupHandlerFixture { + popupHandler: void; +} + +// This fixture will close any popups that might get opened during the test execution +export const test = base.extend({ + popupHandler: [ + async ({ page }, use) => { + await closePopupsIfExist(page); + // eslint-disable-next-line react-hooks/rules-of-hooks + await use(undefined); + }, + { auto: true }, + ], +}); diff --git a/playwright/global.setup.ts b/playwright/global.setup.ts new file mode 100644 index 00000000..78a8f071 --- /dev/null +++ b/playwright/global.setup.ts @@ -0,0 +1,12 @@ +import { test as setup } from '@playwright/test'; + +import { login, storeStorageStateAndToken } from './helpers/login'; + +setup.describe('Setup', () => { + setup.describe.configure({ retries: 3 }); + + setup('Authenticate', async ({ page }) => { + await login(page); + await storeStorageStateAndToken(page); + }); +}); diff --git a/playwright/helpers/login.ts b/playwright/helpers/login.ts index b283bba3..a52d4ce2 100644 --- a/playwright/helpers/login.ts +++ b/playwright/helpers/login.ts @@ -1,3 +1,5 @@ +import path from 'path'; + import { type Page, expect } from '@playwright/test'; import { closePopupsIfExist, isHosted, togglePreview } from './helpers'; @@ -74,3 +76,14 @@ const loginConsole = async (page: Page, user: string, password: string) => { await togglePreview(page); await expect(page.getByRole('heading', { name: 'All images' })).toBeVisible(); }; + +export const storeStorageStateAndToken = async (page: Page) => { + const { cookies } = await page + .context() + .storageState({ path: path.join(__dirname, '../../.auth/user.json') }); + process.env.TOKEN = `Bearer ${ + cookies.find((cookie) => cookie.name === 'cs_jwt')?.value + }`; + // eslint-disable-next-line playwright/no-wait-for-timeout + await page.waitForTimeout(100); +}; diff --git a/playwright/helpers/wizardHelpers.ts b/playwright/helpers/wizardHelpers.ts index 3d5296c0..9aa537ca 100644 --- a/playwright/helpers/wizardHelpers.ts +++ b/playwright/helpers/wizardHelpers.ts @@ -1,6 +1,6 @@ import { expect, FrameLocator, type Page, test } from '@playwright/test'; -import { isHosted } from './helpers'; +import { closePopupsIfExist, isHosted } from './helpers'; import { ibFrame, navigateToLandingPage } from './navHelpers'; /** @@ -70,6 +70,8 @@ export const fillInImageOutputGuest = async (page: Page | FrameLocator) => { * @param blueprintName - the name of the blueprint to delete */ export const deleteBlueprint = async (page: Page, blueprintName: string) => { + // Since new browser is opened during the BP cleanup, we need to call the popup closer again + await closePopupsIfExist(page); await test.step( 'Delete the blueprint with name: ' + blueprintName, async () => { diff --git a/playwright/test.spec.ts b/playwright/test.spec.ts index a49d09aa..c20fc087 100644 --- a/playwright/test.spec.ts +++ b/playwright/test.spec.ts @@ -1,14 +1,15 @@ import { expect, test } from '@playwright/test'; import { v4 as uuidv4 } from 'uuid'; -import { isHosted } from './helpers/helpers'; -import { login } from './helpers/login'; -import { ibFrame } from './helpers/navHelpers'; +import { closePopupsIfExist, isHosted } from './helpers/helpers'; +import { ibFrame, navigateToLandingPage } from './helpers/navHelpers'; test.describe.serial('test', () => { const blueprintName = uuidv4(); test('create blueprint', async ({ page }) => { - await login(page); + await closePopupsIfExist(page); + // Navigate to IB landing page and get the frame + await navigateToLandingPage(page); const frame = await ibFrame(page); frame.getByRole('heading', { name: 'Images About image builder' }); @@ -84,12 +85,14 @@ test.describe.serial('test', () => { }); test('edit blueprint', async ({ page }) => { + await closePopupsIfExist(page); // package searching is really slow the first time in cockpit if (!isHosted()) { test.setTimeout(300000); } - await login(page); + // Navigate to IB landing page and get the frame + await navigateToLandingPage(page); const frame = await ibFrame(page); await frame .getByRole('textbox', { name: 'Search input' }) @@ -120,7 +123,9 @@ test.describe.serial('test', () => { }); test('build blueprint', async ({ page }) => { - await login(page); + await closePopupsIfExist(page); + // Navigate to IB landing page and get the frame + await navigateToLandingPage(page); const frame = await ibFrame(page); await frame .getByRole('textbox', { name: 'Search input' }) @@ -137,7 +142,9 @@ test.describe.serial('test', () => { }); test('delete blueprint', async ({ page }) => { - await login(page); + await closePopupsIfExist(page); + // Navigate to IB landing page and get the frame + await navigateToLandingPage(page); const frame = await ibFrame(page); await frame .getByRole('textbox', { name: 'Search input' })