mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-07-31 17:38:28 +00:00
[ACS-4586] Implemented Playwright Framework and add it to CI/CD (#2985)
This commit is contained in:
committed by
GitHub
parent
197ef8f0e3
commit
d68deab2bd
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright © 2005 - 2023 Alfresco Software, Ltd. All rights reserved.
|
||||
*
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
|
||||
import { PersonalFilesPage, NodesPage } from '../page-objects';
|
||||
import { test as base } from '@playwright/test';
|
||||
import { ApiClientFactory } from '@alfresco/playwright-shared';
|
||||
|
||||
interface Pages {
|
||||
personalFiles: PersonalFilesPage;
|
||||
nodesPage: NodesPage;
|
||||
}
|
||||
|
||||
interface Api {
|
||||
apiClient: ApiClientFactory;
|
||||
}
|
||||
|
||||
export const test = base.extend<Pages & Api>({
|
||||
personalFiles: async ({ page }, use) => {
|
||||
await use(new PersonalFilesPage(page));
|
||||
},
|
||||
nodesPage: async ({ page }, use) => {
|
||||
await use(new NodesPage(page));
|
||||
},
|
||||
apiClient: async ({}, use) => {
|
||||
const apiClient = new ApiClientFactory();
|
||||
await apiClient.setUpAcaBackend('admin');
|
||||
await use(apiClient);
|
||||
}
|
||||
});
|
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright © 2005 - 2023 Alfresco Software, Ltd. All rights reserved.
|
||||
*
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
|
||||
import { Locator, Page } from '@playwright/test';
|
||||
import { BaseComponent } from '@alfresco/playwright-shared';
|
||||
|
||||
export enum ActionType {
|
||||
Aspect = 'Add aspect',
|
||||
SimpleWorkflow = 'Add simple workflow',
|
||||
IncrementCounter = 'Increment Counter'
|
||||
}
|
||||
|
||||
export class ActionsDropdownComponent extends BaseComponent {
|
||||
private static rootElement = '.mat-select-panel';
|
||||
|
||||
public getOptionLocator = (optionName: string): Locator => this.getChild('.mat-option-text', { hasText: optionName });
|
||||
|
||||
constructor(page: Page) {
|
||||
super(page, ActionsDropdownComponent.rootElement);
|
||||
}
|
||||
|
||||
async selectAction(action: Partial<ActionType>): Promise<void> {
|
||||
await this.page.locator(`aca-edit-rule-dialog [data-automation-id="rule-action-select"]`).click();
|
||||
const option = this.getOptionLocator(action);
|
||||
await option.click();
|
||||
}
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright © 2005 - 2023 Alfresco Software, Ltd. All rights reserved.
|
||||
*
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
|
||||
import { Locator, Page } from '@playwright/test';
|
||||
import { ManageRulesDialogComponent } from './manage-rules-dialog.component';
|
||||
|
||||
export enum Field {
|
||||
Name = 'Name',
|
||||
Size = 'Size',
|
||||
Mimetype = 'Mimetype'
|
||||
}
|
||||
|
||||
export enum Comparator {
|
||||
Equals = '(=) Equals',
|
||||
Contains = 'Contains',
|
||||
StartsWith = 'Starts with',
|
||||
EndsWith = 'Ends with'
|
||||
}
|
||||
|
||||
export class ConditionComponent extends ManageRulesDialogComponent {
|
||||
private getOptionLocator = (optionName: string): Locator => this.page.locator(`.cdk-overlay-pane .mat-option span`, { hasText: optionName });
|
||||
|
||||
constructor(page: Page) {
|
||||
super(page);
|
||||
}
|
||||
|
||||
private async selectField(fields: Partial<Field>): Promise<void> {
|
||||
await this.fieldDropDown.click();
|
||||
const option = this.getOptionLocator(fields);
|
||||
await option.click();
|
||||
}
|
||||
|
||||
private async selectComparator(comparators: Partial<Comparator>): Promise<void> {
|
||||
await this.comparatorDropDown.click();
|
||||
const option = this.getOptionLocator(comparators);
|
||||
await option.click();
|
||||
}
|
||||
|
||||
async addCondition(fields: Partial<Field>, comparators: Partial<Comparator>, value: string): Promise<void> {
|
||||
await this.addConditionButton.click();
|
||||
await this.selectField(fields);
|
||||
await this.selectComparator(comparators);
|
||||
await this.typeConditionValue(value);
|
||||
}
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright © 2005 - 2023 Alfresco Software, Ltd. All rights reserved.
|
||||
*
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
|
||||
import { BaseComponent } from '@alfresco/playwright-shared';
|
||||
import { Page } from '@playwright/test';
|
||||
|
||||
export class ManageRulesDialogComponent extends BaseComponent {
|
||||
private static rootElement = 'aca-edit-rule-dialog';
|
||||
|
||||
public createRuleButton = this.getChild('[data-automation-id="edit-rule-dialog-submit"]');
|
||||
private ruleNameInputLocator = this.getChild('[id="rule-details-name-input"]');
|
||||
public addConditionButton = this.getChild('[data-automation-id="add-condition-button"]');
|
||||
public fieldDropDown = this.getChild('[data-automation-id="field-select"]');
|
||||
public comparatorDropDown = this.getChild('[data-automation-id="comparator-select"]');
|
||||
private valueField = this.getChild('[data-automation-id="value-input"]');
|
||||
|
||||
constructor(page: Page) {
|
||||
super(page, ManageRulesDialogComponent.rootElement);
|
||||
}
|
||||
|
||||
async typeRuleName(ruleName: string): Promise<void> {
|
||||
await this.ruleNameInputLocator.type(ruleName, { delay: 50 });
|
||||
}
|
||||
|
||||
async typeConditionValue(ruleName: string): Promise<void> {
|
||||
await this.valueField.type(ruleName, { delay: 50 });
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright © 2005 - 2023 Alfresco Software, Ltd. All rights reserved.
|
||||
*
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
|
||||
import { Locator, Page } from '@playwright/test';
|
||||
import { BaseComponent } from '@alfresco/playwright-shared';
|
||||
|
||||
export class ManageRules extends BaseComponent {
|
||||
private static rootElement = '.aca-manage-rules';
|
||||
|
||||
public getGroupsList = (optionName: string): Locator => this.getChild('.aca-rule-list-item__header', { hasText: optionName });
|
||||
public disableRuleToggle = this.getChild('.aca-manage-rules__container .mat-slide-toggle-bar').first();
|
||||
|
||||
constructor(page: Page) {
|
||||
super(page, ManageRules.rootElement);
|
||||
}
|
||||
}
|
10
e2e/playwright/tests/folder-rules/page-objects/index.ts
Normal file
10
e2e/playwright/tests/folder-rules/page-objects/index.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright © 2005 - 2023 Alfresco Software, Ltd. All rights reserved.
|
||||
*
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
|
||||
export * from './pages/personal-files.page';
|
||||
export * from './pages/nodes.page';
|
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright © 2005 - 2023 Alfresco Software, Ltd. All rights reserved.
|
||||
*
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
|
||||
import { BasePage, ToolbarComponent } from '@alfresco/playwright-shared';
|
||||
import { Page } from '@playwright/test';
|
||||
import { ManageRulesDialogComponent } from '../components/manage-rules-dialog.component';
|
||||
import { ActionsDropdownComponent } from '../components/actions-dropdown.component';
|
||||
import { ConditionComponent } from '../components/conditions.component';
|
||||
import { ManageRules } from '../components/manage-rules.component';
|
||||
|
||||
export class NodesPage extends BasePage {
|
||||
private static pageUrl = 'nodes';
|
||||
|
||||
constructor(page: Page) {
|
||||
super(page, NodesPage.pageUrl);
|
||||
}
|
||||
|
||||
public toolbar = new ToolbarComponent(this.page);
|
||||
public manageRulesDialog = new ManageRulesDialogComponent(this.page);
|
||||
public actionsDropdown = new ActionsDropdownComponent(this.page);
|
||||
public conditionsDropdown = new ConditionComponent(this.page);
|
||||
public manageRules = new ManageRules(this.page);
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright © 2005 - 2023 Alfresco Software, Ltd. All rights reserved.
|
||||
*
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
|
||||
import { BasePage, DataTableComponent } from '@alfresco/playwright-shared';
|
||||
import { Page } from '@playwright/test';
|
||||
|
||||
export class PersonalFilesPage extends BasePage {
|
||||
private static pageUrl = 'personal-files';
|
||||
|
||||
constructor(page: Page) {
|
||||
super(page, PersonalFilesPage.pageUrl);
|
||||
}
|
||||
|
||||
public dataTable = new DataTableComponent(this.page);
|
||||
}
|
52
e2e/playwright/tests/folder-rules/playwright.config.ts
Normal file
52
e2e/playwright/tests/folder-rules/playwright.config.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { PlaywrightTestConfig, devices } from '@playwright/test';
|
||||
|
||||
require('dotenv').config();
|
||||
|
||||
export const config: PlaywrightTestConfig = {
|
||||
testDir: './',
|
||||
expect: {
|
||||
/**
|
||||
* Maximum time expect() should wait for the condition to be met.
|
||||
* For example in `await expect(locator).toHaveText();`
|
||||
*/
|
||||
timeout: 10000
|
||||
},
|
||||
/* Run tests in files in parallel */
|
||||
fullyParallel: true,
|
||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||
forbidOnly: !!process.env.CI,
|
||||
/* Retry on CI only */
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
/* Opt out of parallel tests on CI. */
|
||||
workers: 5,
|
||||
timeout: 20000,
|
||||
|
||||
globalSetup: require.resolve('../../shared/base-config/global.setup'),
|
||||
use: {
|
||||
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
|
||||
storageState: './storage-state/AdminUserState.json',
|
||||
actionTimeout: 0,
|
||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||
baseURL: process.env.PLAYWRIGHT_E2E_HOST,
|
||||
ignoreHTTPSErrors: true,
|
||||
bypassCSP: true,
|
||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||
trace: 'on-first-retry',
|
||||
launchOptions: {
|
||||
devtools: false,
|
||||
args: ['--disable-web-security', '--no-sandbox', '--disable-site-isolation-trials']
|
||||
}
|
||||
},
|
||||
|
||||
/* Configure projects for major browsers */
|
||||
projects: [
|
||||
{
|
||||
name: 'chromium',
|
||||
use: {
|
||||
...devices['Desktop Chrome']
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export default config;
|
34
e2e/playwright/tests/folder-rules/tests/actions.spec.ts
Normal file
34
e2e/playwright/tests/folder-rules/tests/actions.spec.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { test } from '../fixtures/page-initialization';
|
||||
import { NodeBodyCreate } from '@alfresco/aca-testing-shared';
|
||||
import { ActionType } from '../page-objects/components/actions-dropdown.component';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
test.describe('Folder Rules Actions', () => {
|
||||
const randomFolderName = `playwright-folder-${(Math.random() + 1).toString(36).substring(6)}`;
|
||||
const randomRuleName = `playwright-rule-${(Math.random() + 1).toString(36).substring(6)}`;
|
||||
|
||||
let folderId: string;
|
||||
|
||||
test.beforeAll(async ({ apiClient }) => {
|
||||
folderId = (await apiClient.nodes.createNode('-my-', new NodeBodyCreate(randomFolderName, 'cm:folder'))).entry.id;
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ personalFiles }) => {
|
||||
await personalFiles.navigate({ waitUntil: 'domcontentloaded' });
|
||||
});
|
||||
|
||||
test.afterAll(async ({ apiClient }) => {
|
||||
await apiClient.nodes.deleteNode(folderId);
|
||||
});
|
||||
|
||||
test('Create a rule with actions', async ({ personalFiles, nodesPage }) => {
|
||||
await personalFiles.dataTable.performActionFromExpandableMenu(randomFolderName, 'Manage rules');
|
||||
|
||||
await nodesPage.toolbar.clickCreateRuleButton();
|
||||
await nodesPage.manageRulesDialog.typeRuleName(randomRuleName);
|
||||
await nodesPage.actionsDropdown.selectAction(ActionType.IncrementCounter);
|
||||
await nodesPage.manageRulesDialog.createRuleButton.click();
|
||||
|
||||
await expect.soft(nodesPage.manageRules.getGroupsList(randomRuleName)).toBeVisible();
|
||||
});
|
||||
});
|
37
e2e/playwright/tests/folder-rules/tests/conditions.spec.ts
Normal file
37
e2e/playwright/tests/folder-rules/tests/conditions.spec.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { test } from '../fixtures/page-initialization';
|
||||
import { NodeBodyCreate } from '@alfresco/aca-testing-shared';
|
||||
import { ActionType } from '../page-objects/components/actions-dropdown.component';
|
||||
import { Comparator, Field } from '../page-objects/components/conditions.component';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
test.describe('Folder Rules Conditions', () => {
|
||||
const randomFolderName = `playwright-folder-${(Math.random() + 1).toString(36).substring(6)}`;
|
||||
const randomRuleName = `playwright-rule-${(Math.random() + 1).toString(36).substring(6)}`;
|
||||
const specialChars = '!@£$%^&*()~#/';
|
||||
|
||||
let folderId: string;
|
||||
|
||||
test.beforeAll(async ({ apiClient }) => {
|
||||
folderId = (await apiClient.nodes.createNode('-my-', new NodeBodyCreate(randomFolderName, 'cm:folder'))).entry.id;
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ personalFiles }) => {
|
||||
await personalFiles.navigate();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ apiClient }) => {
|
||||
await apiClient.nodes.deleteNode(folderId);
|
||||
});
|
||||
|
||||
test('Create a rule with condition', async ({ personalFiles, nodesPage }) => {
|
||||
await personalFiles.dataTable.performActionFromExpandableMenu(randomFolderName, 'Manage rules');
|
||||
|
||||
await nodesPage.toolbar.clickCreateRuleButton();
|
||||
await nodesPage.manageRulesDialog.typeRuleName(randomRuleName);
|
||||
await nodesPage.conditionsDropdown.addCondition(Field.Size, Comparator.Equals, specialChars);
|
||||
await nodesPage.actionsDropdown.selectAction(ActionType.IncrementCounter);
|
||||
await nodesPage.manageRulesDialog.createRuleButton.click();
|
||||
|
||||
await expect.soft(nodesPage.manageRules.getGroupsList(randomRuleName)).toBeVisible();
|
||||
});
|
||||
});
|
27
e2e/playwright/tests/folder-rules/tests/manage-rules.spec.ts
Normal file
27
e2e/playwright/tests/folder-rules/tests/manage-rules.spec.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { test } from '../fixtures/page-initialization';
|
||||
import { NodeBodyCreate } from '@alfresco/aca-testing-shared';
|
||||
|
||||
test.describe('Rules - Manage Rules', () => {
|
||||
const randomName = `playwright-folder-${(Math.random() + 1).toString(36).substring(6)}`;
|
||||
const randomRuleName = `playwright-rule-${(Math.random() + 1).toString(36).substring(6)}`;
|
||||
|
||||
let folderId: string;
|
||||
|
||||
test.beforeAll(async ({ apiClient }) => {
|
||||
folderId = (await apiClient.nodes.createNode('-my-', new NodeBodyCreate(randomName, 'cm:folder'))).entry.id;
|
||||
await apiClient.createRandomRule(folderId, randomRuleName);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ personalFiles }) => {
|
||||
await personalFiles.navigate();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ apiClient }) => {
|
||||
await apiClient.nodes.deleteNode(folderId);
|
||||
});
|
||||
|
||||
test('Disable an existing rule', async ({ personalFiles, nodesPage }) => {
|
||||
await personalFiles.dataTable.performActionFromExpandableMenu(randomName, 'Manage rules');
|
||||
await nodesPage.manageRules.disableRuleToggle.click();
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user