diff --git a/playwright.config.ts b/playwright.config.ts index 8c9f182..ee4c2fc 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -12,7 +12,7 @@ export default defineConfig({ fullyParallel: true, forbidOnly: !!process.env.CI, retries: process.env.CI ? 2 : 0, - workers: process.env.CI ? 1 : undefined, + workers: 4, reporter: 'html', use: { baseURL: process.env.WP_BASE_URL, diff --git a/tests/e2e/feature-flags.spec.ts b/tests/e2e/feature-flags.spec.ts index 50626ef..918ebd4 100644 --- a/tests/e2e/feature-flags.spec.ts +++ b/tests/e2e/feature-flags.spec.ts @@ -1,5 +1,14 @@ import { test, expect } from '@wordpress/e2e-test-utils-playwright'; import { ERROR_FLAG_EXISTS, ERROR_FLAG_INVALID } from '../../src/constants'; +import { + AddNewFlag, + AddNewFlagAndFill, + CloseSdkModal, + DisableFlag, + OpenSdkModal, + SaveFlags, + deleteLastFlag, +} from './helper'; // eslint-disable-next-line test.use({ storageState: process.env.WP_AUTH_STORAGE }); @@ -17,22 +26,29 @@ test.describe('Feature flags', () => { ).toBeVisible(); }); - test('Create and delete flags e2e scenarios', async ({ page }) => { - //Create new flag - await page.getByRole('button', { name: 'Add Flag' }).click(); - await page.getByRole('textbox').last().fill('test'); - await page.getByRole('button', { name: 'Save' }).click(); - //Confirm save success + test.afterEach(async ({ page }) => { + await deleteLastFlag(page); + }); + + test('Create and save new flag successfully', async ({ page }) => { + await AddNewFlagAndFill(page, 'hello_test'); + await SaveFlags(page); + expect( await page.getByLabel('Dismiss this notice').innerText() ).toMatch(/Saved successfully!/); + }); + + test('Create new flag and disable it successfully', async ({ page }) => { + await AddNewFlagAndFill(page, 'test123'); + await SaveFlags(page); + + expect( + await page.getByLabel('Dismiss this notice').innerText() + ).toMatch(/Saved successfully!/); + + await DisableFlag(page, true); - //Toggle feature flag - await page - .locator('id=mr-feature-flag-item') - .last() - .getByLabel('Flag enabled') - .click(); expect( await page.getByLabel('Dismiss this notice').innerText() ).toMatch(/Saved successfully!/); @@ -42,34 +58,51 @@ test.describe('Feature flags', () => { .last() .getByLabel('Flag disabled') ).toBeVisible(); + }); + + test('Check duplicate and invalid flag', async ({ page }) => { + //Create new flag + await AddNewFlagAndFill(page, 'testDuplicate'); + await SaveFlags(page); - //Create another flag with same name - await page.getByRole('button', { name: 'Add Flag' }).click(); - await page.getByRole('textbox').last().fill('test'); + //Confirm save success + expect( + await page.getByLabel('Dismiss this notice').innerText() + ).toMatch(/Saved successfully!/); + + //Create another flag with same name should show error + await AddNewFlagAndFill(page, 'testDuplicate'); expect(page.getByText(ERROR_FLAG_EXISTS)).toBeVisible(); expect(page.getByRole('button', { name: 'Save' })).toBeDisabled(); - //update flag name to be unique and check text validation. - await page.getByRole('textbox').last().fill('test 2'); + //update flag name to be unique but still invalid + await AddNewFlag(page, 'test duplicate'); expect(page.getByText(ERROR_FLAG_INVALID)).toBeVisible(); expect(page.getByRole('button', { name: 'Save' })).toBeDisabled(); //Delete the flag - await page - .locator('id=mr-feature-flag-item') - .last() - .getByLabel('Delete Flag') - .click(); - await page.getByRole('button', { name: 'Yes' }).click(); - //Confirm delete success + await deleteLastFlag(page); + + expect( + await page.getByLabel('Dismiss this notice').innerText() + ).toMatch(/Saved successfully!/); + }); + + test('Open SDK modal and test the clipboard', async ({ page }) => { + const flagName = 'testWidget'; + await AddNewFlagAndFill(page, flagName); + await SaveFlags(page); + expect( await page.getByLabel('Dismiss this notice').innerText() ).toMatch(/Saved successfully!/); - //Check SDK modal details. - await page.getByLabel('Click to see SDK setting').last().click(); + await OpenSdkModal(page); + expect( - page.getByRole('heading', { name: 'SDK for feature flag: test' }) + page.getByRole('heading', { + name: `SDK for feature flag: ${flagName}`, + }) ).toBeVisible(); // Check PHP Snippet clipboard details @@ -77,7 +110,7 @@ test.describe('Feature flags', () => { const phpClipboardText = await page.evaluate( 'navigator.clipboard.readText()' ); - expect(phpClipboardText).toContain("Flag::is_enabled( 'test' )"); + expect(phpClipboardText).toContain(`Flag::is_enabled( '${flagName}' )`); // Check JS Snippet clipboard details await page.getByLabel('Copy to clipboard').nth(1).click(); @@ -85,17 +118,10 @@ test.describe('Feature flags', () => { 'navigator.clipboard.readText()' ); expect(jsClipboardText).toContain( - "window.mrFeatureFlags.isEnabled('test')" + `window.mrFeatureFlags.isEnabled('${flagName}')` ); + //Close SDK modal - await page.locator('button[aria-label="Close"]').click(); - - //Delete the created flag - await page - .locator('id=mr-feature-flag-item') - .last() - .getByLabel('Delete Flag') - .click(); - await page.getByRole('button', { name: 'Yes' }).click(); + await CloseSdkModal(page); }); }); diff --git a/tests/e2e/helper/index.ts b/tests/e2e/helper/index.ts new file mode 100644 index 0000000..c81bc1d --- /dev/null +++ b/tests/e2e/helper/index.ts @@ -0,0 +1,83 @@ +import { test } from '@wordpress/e2e-test-utils-playwright'; +import { Page } from '@playwright/test'; + +export async function deleteLastFlag(page: Page) { + await test.step( + 'Delete last flag', + async () => { + await page + .locator('id=mr-feature-flag-item') + .last() + .getByLabel('Delete Flag') + .click(); + await page.getByRole('button', { name: 'Yes' }).click(); + }, + { box: true } + ); +} + +export async function AddNewFlag(page: Page, text: string) { + await test.step( + 'Add new flag', + async () => { + await page.getByRole('textbox').last().fill(text); + }, + { box: true } + ); +} + +export async function AddNewFlagAndFill(page: Page, text: string) { + await test.step( + 'Add new flag and fill text', + async () => { + await page.getByRole('button', { name: 'Add Flag' }).click(); + await page.getByRole('textbox').last().fill(text); + }, + { box: true } + ); +} + +export async function SaveFlags(page: Page) { + await test.step( + 'Save flags', + async () => { + await page.getByRole('button', { name: 'Save' }).click(); + }, + { box: true } + ); +} + +export async function DisableFlag(page: Page, isEnabled: boolean) { + await test.step( + 'Toggle flag', + async () => { + const labelText = isEnabled ? 'Flag enabled' : 'Flag disabled'; + await page + .locator('id=mr-feature-flag-item') + .last() + .getByLabel(labelText) + .click(); + }, + { box: true } + ); +} + +export async function OpenSdkModal(page: Page) { + await test.step( + 'Open sdk modal', + async () => { + await page.getByLabel('Click to see SDK setting').last().click(); + }, + { box: true } + ); +} + +export async function CloseSdkModal(page: Page) { + await test.step( + 'Close sdk modal', + async () => { + await page.locator('button[aria-label="Close"]').click(); + }, + { box: true } + ); +}