Skip to content

Commit

Permalink
Page objects.
Browse files Browse the repository at this point in the history
  • Loading branch information
SebastianStehle committed Sep 5, 2024
1 parent 751e53c commit de2e195
Show file tree
Hide file tree
Showing 22 changed files with 884 additions and 459 deletions.
61 changes: 36 additions & 25 deletions tools/e2e/tests/_fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,45 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/

import { test as base, Page } from '@playwright/test';

type BaseFixture = {
dropdown: Dropdown;
import { test as base } from '@playwright/test';
import { ContentPage, ContentsPage, LoginPage, RulePage, RulesPage, SchemaPage, SchemasPage } from './pages';
import { AppsPage } from './pages/apps';

export type BaseFixture = {
appsPage: AppsPage;
contentPage: ContentPage;
contentsPage: ContentsPage;
loginPage: LoginPage;
rulePage: RulePage;
rulesPage: RulesPage;
schemaPage: SchemaPage;
schemasPage: SchemasPage;
};

class Dropdown {
constructor(
private readonly page: Page,
) {
}

public async delete() {
await this.page.getByText('Delete').click();
await this.page.getByRole('button', { name: /Yes/ }).click();
}

public async action(name: string) {
await this.page.getByText(name).click();
await this.page.locator('sqx-dropdown-menu').waitFor({ state: 'hidden' });
}
}

export const test = base.extend<BaseFixture>({
dropdown: async ({ page }, use) => {
const dropdown = new Dropdown(page);

await use(dropdown);
appsPage: async ({ page }, use) => {
await use(new AppsPage(page));
},
contentPage: async ({ page }, use) => {
await use(new ContentPage(page));
},
contentsPage: async ({ page }, use) => {
await use(new ContentsPage(page));
},
loginPage: async ({ page }, use) => {
await use(new LoginPage(page));
},
rulePage: async ({ page }, use) => {
await use(new RulePage(page));
},
rulesPage: async ({ page }, use) => {
await use(new RulesPage(page));
},
schemaPage: async ({ page }, use) => {
await use(new SchemaPage(page));
},
schemasPage: async ({ page }, use) => {
await use(new SchemasPage(page));
},
});

Expand Down
15 changes: 7 additions & 8 deletions tools/e2e/tests/given-app/_setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,19 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/

import { test as setup } from '@playwright/test';
import { getRandomId, writeJsonAsync } from '../utils';
import { test as setup } from './_fixture';

setup('prepare app', async ({ page }) => {
setup('prepare app', async ({ appsPage }) => {
const appName = `my-app-${getRandomId()}`;

await page.goto('/app');
await appsPage.goto();

await page.getByTestId('new-app').click();
const dialog = await appsPage.openAppDialog();
await dialog.enterName(appName);
await dialog.save();

await page.locator('#name').fill(appName);
await page.getByRole('button', { name: 'Create' }).click();

await page.getByRole('heading', { name: appName }).click();
await appsPage.gotoApp(appName);

await writeJsonAsync('app', { appName });
});
92 changes: 41 additions & 51 deletions tools/e2e/tests/given-app/rules.spec.ts
Original file line number Diff line number Diff line change
@@ -1,90 +1,80 @@
import { expect, Page } from '@playwright/test';
import { escapeRegex, getRandomId } from '../utils';
import { expect } from '@playwright/test';
import { RulePage, RulesPage } from '../pages';
import { getRandomId } from '../utils';
import { test } from './_fixture';

// We have no easy way to identity rules. Therefore run them sequentially.
test.describe.configure({ mode: 'serial' });

test.beforeEach(async ({ page, appName }) => {
await page.goto(`/app/${appName}/rules`);
test.beforeEach(async ({ appName, rulesPage }) => {
await rulesPage.goto(appName);
});

test('create rule', async ({ page }) => {
const ruleName = await createRandomRule(page);
const ruleCard = page.locator('div.card', { hasText: escapeRegex(ruleName) });
test('create rule', async ({ rulesPage, rulePage }) => {
const ruleName = await createRandomRule(rulesPage, rulePage);
const ruleCard = await rulesPage.getRule(ruleName);

await expect(ruleCard).toBeVisible();
await expect(ruleCard.root).toBeVisible();
});

test('delete rule', async ({ dropdown, page }) => {
const ruleName = await createRandomRule(page);
const ruleCard = page.locator('div.card', { hasText: escapeRegex(ruleName) });
test('delete rule', async ({ rulesPage, rulePage }) => {
const ruleName = await createRandomRule(rulesPage, rulePage);
const ruleCard = await rulesPage.getRule(ruleName);

await ruleCard.getByLabel('Options').click();
const dropdown = await ruleCard.openOptionsDropdown();
await dropdown.delete();

await expect(ruleCard).not.toBeVisible();
await expect(ruleCard.root).toBeVisible();
});

test('disable rule', async ({ dropdown, page }) => {
const ruleName = await createRandomRule(page);
const ruleCard = page.locator('div.card', { hasText: escapeRegex(ruleName) });
test('disable rule', async ({ rulePage, rulesPage }) => {
const ruleName = await createRandomRule(rulesPage, rulePage);
const ruleCard = await rulesPage.getRule(ruleName);

await ruleCard.getByLabel('Options').click();
const dropdown = await ruleCard.openOptionsDropdown();
await dropdown.action('Disable');

await expect(ruleCard.locator('sqx-toggle .toggle-container')).toHaveAttribute('data-state', 'unchecked');
await expect(ruleCard.root.locator('sqx-toggle .toggle-container')).toHaveAttribute('data-state', 'unchecked');
});

test('enable rule', async ({ dropdown, page }) => {
const ruleName = await createRandomRule(page);
const ruleCard = page.locator('div.card', { hasText: escapeRegex(ruleName) });
test('enable rule', async ({ rulePage, rulesPage }) => {
const ruleName = await createRandomRule(rulesPage, rulePage);
const ruleCard = await rulesPage.getRule(ruleName);

await ruleCard.getByLabel('Options').click();
await dropdown.action('Disable');
const dropdown1 = await ruleCard.openOptionsDropdown();
await dropdown1.action('Disable');

await expect(ruleCard.locator('sqx-toggle .toggle-container')).toHaveAttribute('data-state', 'unchecked');
await expect(ruleCard.root.locator('sqx-toggle .toggle-container')).toHaveAttribute('data-state', 'unchecked');

await ruleCard.getByLabel('Options').click();
await dropdown.action('Enable');
const dropdown2 = await ruleCard.openOptionsDropdown();
await dropdown2.action('Enable');

await expect(ruleCard.locator('sqx-toggle .toggle-container')).toHaveAttribute('data-state', 'checked');
await expect(ruleCard.root.locator('sqx-toggle .toggle-container')).toHaveAttribute('data-state', 'checked');
});

test('edit rule', async ({ dropdown, page }) => {
const ruleName = await createRandomRule(page);
const ruleCard = page.locator('div.card', { hasText: escapeRegex(ruleName) });
test('edit rule', async ({ page, rulePage, rulesPage }) => {
const ruleName = await createRandomRule(rulesPage, rulePage);
const ruleCard = await rulesPage.getRule(ruleName);

await ruleCard.getByLabel('Options').click();
const dropdown = await ruleCard.openOptionsDropdown();
await dropdown.action('Edit');

await expect(page.getByText('Enabled')).toBeVisible();
});

async function createRandomRule(page: Page) {
async function createRandomRule(rulesPage: RulesPage, rulePage: RulePage) {
const ruleName = `rule-${getRandomId()}`;

await page.getByRole('link', { name: /New Rule/ }).click();

// Define rule action
await page.getByText('Content changed').click();

// Define rule trigger
await page.getByText('Webhook').click();
// This is the only required field, so we have to enter some text.
await page.locator('sqx-formattable-input').first().getByRole('textbox').fill('https:/squidex.io');

await page.getByRole('button', { name: 'Save' }).click();

await page.getByText('Enabled').waitFor({ state: 'visible' });
await rulesPage.addRule();

// Go back
await page.getByLabel('Back').click();
await rulePage.selectContentChangedTrigger();
await rulePage.selectWebhookAction();
await rulePage.save();
await rulePage.back();

// Define rule name.
await page.locator('div.card', { hasText: /Unnamed Rule/ }).getByRole('heading').first().dblclick();
await page.locator('form').getByRole('textbox').fill(ruleName);
await page.locator('form').getByLabel('Save').click();
const rename = await rulesPage.renameRule(/Unnamed Rule/);
await rename.enterName(ruleName);
await rename.save();

return ruleName;
}
Loading

0 comments on commit de2e195

Please sign in to comment.