From d68deab2bd0a333d0806362e43afea44e9a3bd30 Mon Sep 17 00:00:00 2001 From: Kristian Dimitrov Date: Thu, 16 Feb 2023 17:23:08 +0000 Subject: [PATCH] [ACS-4586] Implemented Playwright Framework and add it to CI/CD (#2985) --- .gitignore | 3 + .travis.yml | 10 + cspell.json | 9 + .../shared/api/api-client-factory.ts | 122 +++++++++ e2e/playwright/shared/api/index.ts | 10 + e2e/playwright/shared/api/rules-api.ts | 56 +++++ .../shared/base-config/global.setup.ts | 46 ++++ e2e/playwright/shared/base-config/index.ts | 9 + e2e/playwright/shared/index.ts | 29 +++ e2e/playwright/shared/models/index.ts | 9 + e2e/playwright/shared/models/user-model.ts | 44 ++++ e2e/playwright/shared/package.json | 8 + .../page-objects/components/base.component.ts | 48 ++++ .../dataTable/data-table.component.ts | 143 +++++++++++ .../components/dataTable/index.ts | 11 + .../dataTable/mat-menu.component.ts | 22 ++ .../components/dataTable/toolbar.component.ts | 23 ++ .../shared/page-objects/components/index.ts | 11 + .../components/snack-bar.component.ts | 21 ++ .../components/spinner.component.ts | 27 ++ .../shared/page-objects/global-variables.ts | 37 +++ e2e/playwright/shared/page-objects/index.ts | 13 + .../shared/page-objects/pages/base.page.ts | 80 ++++++ .../shared/page-objects/pages/index.ts | 10 + .../shared/page-objects/pages/login.page.ts | 38 +++ .../shared/page-objects/playwright-base.ts | 20 ++ e2e/playwright/shared/tsconfig.lib.json | 24 ++ .../fixtures/page-initialization.ts | 34 +++ .../components/actions-dropdown.component.ts | 32 +++ .../components/conditions.component.ts | 50 ++++ .../manage-rules-dialog.component.ts | 33 +++ .../components/manage-rules.component.ts | 21 ++ .../tests/folder-rules/page-objects/index.ts | 10 + .../page-objects/pages/nodes.page.ts | 28 +++ .../page-objects/pages/personal-files.page.ts | 20 ++ .../tests/folder-rules/playwright.config.ts | 52 ++++ .../tests/folder-rules/tests/actions.spec.ts | 34 +++ .../folder-rules/tests/conditions.spec.ts | 37 +++ .../folder-rules/tests/manage-rules.spec.ts | 27 ++ e2e/tsconfig.e2e.json | 5 +- package-lock.json | 233 ++++++++++-------- package.json | 1 + projects/aca-folder-rules/src/public-api.ts | 2 +- scripts/ci/job_hooks/after_e2e.sh | 3 + scripts/ci/job_hooks/before-playwright.sh | 3 + scripts/ci/jobs/affected-project-with.sh | 20 +- tsconfig.json | 2 + 47 files changed, 1413 insertions(+), 117 deletions(-) create mode 100644 e2e/playwright/shared/api/api-client-factory.ts create mode 100644 e2e/playwright/shared/api/index.ts create mode 100644 e2e/playwright/shared/api/rules-api.ts create mode 100644 e2e/playwright/shared/base-config/global.setup.ts create mode 100644 e2e/playwright/shared/base-config/index.ts create mode 100644 e2e/playwright/shared/index.ts create mode 100644 e2e/playwright/shared/models/index.ts create mode 100644 e2e/playwright/shared/models/user-model.ts create mode 100644 e2e/playwright/shared/package.json create mode 100644 e2e/playwright/shared/page-objects/components/base.component.ts create mode 100644 e2e/playwright/shared/page-objects/components/dataTable/data-table.component.ts create mode 100644 e2e/playwright/shared/page-objects/components/dataTable/index.ts create mode 100644 e2e/playwright/shared/page-objects/components/dataTable/mat-menu.component.ts create mode 100644 e2e/playwright/shared/page-objects/components/dataTable/toolbar.component.ts create mode 100644 e2e/playwright/shared/page-objects/components/index.ts create mode 100644 e2e/playwright/shared/page-objects/components/snack-bar.component.ts create mode 100644 e2e/playwright/shared/page-objects/components/spinner.component.ts create mode 100644 e2e/playwright/shared/page-objects/global-variables.ts create mode 100644 e2e/playwright/shared/page-objects/index.ts create mode 100644 e2e/playwright/shared/page-objects/pages/base.page.ts create mode 100644 e2e/playwright/shared/page-objects/pages/index.ts create mode 100644 e2e/playwright/shared/page-objects/pages/login.page.ts create mode 100644 e2e/playwright/shared/page-objects/playwright-base.ts create mode 100644 e2e/playwright/shared/tsconfig.lib.json create mode 100644 e2e/playwright/tests/folder-rules/fixtures/page-initialization.ts create mode 100644 e2e/playwright/tests/folder-rules/page-objects/components/actions-dropdown.component.ts create mode 100644 e2e/playwright/tests/folder-rules/page-objects/components/conditions.component.ts create mode 100644 e2e/playwright/tests/folder-rules/page-objects/components/manage-rules-dialog.component.ts create mode 100644 e2e/playwright/tests/folder-rules/page-objects/components/manage-rules.component.ts create mode 100644 e2e/playwright/tests/folder-rules/page-objects/index.ts create mode 100644 e2e/playwright/tests/folder-rules/page-objects/pages/nodes.page.ts create mode 100644 e2e/playwright/tests/folder-rules/page-objects/pages/personal-files.page.ts create mode 100644 e2e/playwright/tests/folder-rules/playwright.config.ts create mode 100644 e2e/playwright/tests/folder-rules/tests/actions.spec.ts create mode 100644 e2e/playwright/tests/folder-rules/tests/conditions.spec.ts create mode 100644 e2e/playwright/tests/folder-rules/tests/manage-rules.spec.ts create mode 100755 scripts/ci/job_hooks/before-playwright.sh diff --git a/.gitignore b/.gitignore index 3add0d13c..9d8188862 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,6 @@ testem.log # System Files .DS_Store Thumbs.db +/test-results/ +/playwright-report/ +/playwright/.cache/ diff --git a/.travis.yml b/.travis.yml index 357c39e38..8fe409fd3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,6 +44,7 @@ env: global: - ADMIN_EMAIL=$ADMIN_EMAIL_REMOTE - ADMIN_PASSWORD=$ADMIN_PASSWORD_REMOTE + - PLAYWRIGHT_E2E_HOST="http://localhost:4200" - CONTENT_CE_DIST_PATH="./dist/content-ce" # APP CONFIG DEFAULTS - APP_CONFIG_PROVIDER=ECM @@ -68,6 +69,15 @@ jobs: after_success: ./scripts/ci/utils/artifact-to-s3.sh -a $CONTENT_CE_DIST_PATH -o "$S3_DBP_FOLDER/alfresco-content-app.tar.bz2" || travis_terminate 1 cache: false + - stage: e2e + name: 'Test Suites: Folder Rules - Playwright' + before_script: + - ./scripts/ci/job_hooks/before_e2e.sh "$S3_DBP_FOLDER/alfresco-content-app.tar.bz2" "$CONTENT_CE_DIST_PATH" "-a" || travis_terminate 1 + - ./scripts/ci/job_hooks/before-playwright.sh + script: ./scripts/ci/jobs/affected-project-with.sh -target e2e -options "e2e/playwright/tests/folder-rules/playwright.config.ts" -test-runner playwright + after_script: + - ./scripts/ci/job_hooks/after_e2e.sh + - stage: e2e name: 'Test Suites: authentication,listViews,navigation,application' before_script: diff --git a/cspell.json b/cspell.json index 5b70572bb..980839774 100644 --- a/cspell.json +++ b/cspell.json @@ -11,6 +11,15 @@ "mincount", "QNAME", "PNAME", + "ADDFEATURES", + "CHECKIN", + "thumbnailed", + "superadmin", + "SUPERADMIN", + "hruser", + "salesuser", + "networkidle", + "domcontentloaded", "mimetype", "ngrx", diff --git a/e2e/playwright/shared/api/api-client-factory.ts b/e2e/playwright/shared/api/api-client-factory.ts new file mode 100644 index 000000000..c68f684a0 --- /dev/null +++ b/e2e/playwright/shared/api/api-client-factory.ts @@ -0,0 +1,122 @@ +/* + * 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 { + AdminTenantsApi, + AdminUsersApi, + AlfrescoApi, + ContentClient, + GroupsApi, + NodesApi, + PeopleApi, + QueriesApi, + SearchApi, + SecurityGroupsApi, + SecurityMarksApi, + SitesApi, + UploadApi +} from '@alfresco/js-api'; +import { users } from '../page-objects'; +import { logger } from '@alfresco/adf-cli/scripts/logger'; +import { ActionTypes, Rule } from './rules-api'; + +export interface AcaBackend { + sites: SitesApi; + upload: UploadApi; + nodes: NodesApi; + + tearDown(): Promise; +} + +const config = { + authType: process.env.APP_CONFIG_AUTH_TYPE, + hostBpm: process.env.APP_CONFIG_BPM_HOST, + hostEcm: process.env.APP_CONFIG_ECM_HOST, + provider: process.env.APP_CONFIG_PROVIDER, + contextRoot: 'alfresco' +}; + +export class ApiClientFactory { + public alfrescoApi: AlfrescoApi; + public sites: SitesApi; + public upload: UploadApi; + public nodes: NodesApi; + public people: PeopleApi; + public adminUsers: AdminUsersApi; + public adminTenant: AdminTenantsApi; + public groups: GroupsApi; + public queries: QueriesApi; + public search: SearchApi; + public securityGroupsApi: SecurityGroupsApi; + public securityMarksApi: SecurityMarksApi; + public contentClient: ContentClient; + + constructor() { + this.alfrescoApi = new AlfrescoApi(config); + } + + public async setUpAcaBackend(userProfile: keyof typeof users): Promise { + await this.login(userProfile); + + this.sites = new SitesApi(this.alfrescoApi); + this.upload = new UploadApi(this.alfrescoApi); + this.nodes = new NodesApi(this.alfrescoApi); + this.people = new PeopleApi(this.alfrescoApi); + this.adminUsers = new AdminUsersApi(this.alfrescoApi); + this.adminTenant = new AdminTenantsApi(this.alfrescoApi); + this.groups = new GroupsApi(this.alfrescoApi); + this.queries = new QueriesApi(this.alfrescoApi); + this.search = new SearchApi(this.alfrescoApi); + this.securityGroupsApi = new SecurityGroupsApi(this.alfrescoApi); + this.securityMarksApi = new SecurityMarksApi(this.alfrescoApi); + + return this; + } + + async tearDown(): Promise { + await this.alfrescoApi.logout(); + return this; + } + + private callApi(path: string, httpMethod: string, body: object = {}): Promise { + // APIs used by this service are still private and not yet available for public use + const params = [{}, {}, {}, {}, body, ['application/json'], ['application/json']]; + return this.alfrescoApi.contentPrivateClient.callApi(path, httpMethod, ...params); + } + + async createRule(nodeId: string, rule: Partial, ruleSetId: string = '-default-'): Promise { + const response = await this.callApi(`/nodes/${nodeId}/rule-sets/${ruleSetId}/rules`, 'POST', { ...rule }); + return response.entry; + } + + async createRandomRule(folderId: string, ruleName: string): Promise { + const response = await this.createRule(folderId, { + name: ruleName, + isEnabled: true, + actions: [ActionTypes.ADDFEATURES.value, ActionTypes.CHECKIN.value] + }); + return response; + } + + async login(userProfile: keyof typeof users) { + const userToLog = + users[ + Object.keys(users) + .filter((user) => user.match(new RegExp(`^${userProfile.toString()}$`))) + .toString() + ] || userProfile; + let e: any; + + try { + e = await this.alfrescoApi.login(userToLog.username, userToLog.password); + } catch (error) { + logger.error(`[API Client Factory] Log in user ${userToLog.username} failed ${e}`); + throw error; + } + } +} diff --git a/e2e/playwright/shared/api/index.ts b/e2e/playwright/shared/api/index.ts new file mode 100644 index 000000000..8ee4a04be --- /dev/null +++ b/e2e/playwright/shared/api/index.ts @@ -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 './rules-api'; +export * from './api-client-factory'; diff --git a/e2e/playwright/shared/api/rules-api.ts b/e2e/playwright/shared/api/rules-api.ts new file mode 100644 index 000000000..52c259258 --- /dev/null +++ b/e2e/playwright/shared/api/rules-api.ts @@ -0,0 +1,56 @@ +/* + * 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. + */ + +type RuleTrigger = 'inbound' | 'update' | 'outbound'; + +export interface RuleCompositeCondition { + inverted: boolean; + booleanMode: 'and' | 'or'; + compositeConditions: RuleCompositeCondition[]; + simpleConditions: RuleSimpleCondition[]; +} + +export interface RuleSimpleCondition { + field: string; + comparator: string; + parameter: string; +} + +export interface Rule { + id: string; + name: string; + description: string; + isEnabled: boolean; + isInheritable: boolean; + isAsynchronous: boolean; + errorScript: string; + isShared: boolean; + triggers: RuleTrigger[]; + conditions: RuleCompositeCondition; + actions: RuleAction[]; +} + +export interface RuleAction { + actionDefinitionId: string; + params?: { [key: string]: unknown }; +} + +export class ActionTypes { + static ADDFEATURES = new ActionTypes('ADDFEATURES', { + actionDefinitionId: 'add-features', + params: { 'aspect-name': 'cm:thumbnailed' } + }); + static CHECKIN = new ActionTypes('CHECKIN', { + actionDefinitionId: 'check-in', + params: { + description: 'test', + minorChange: true + } + }); + constructor(public key: string, public value: RuleAction) {} +} diff --git a/e2e/playwright/shared/base-config/global.setup.ts b/e2e/playwright/shared/base-config/global.setup.ts new file mode 100644 index 000000000..6e8260735 --- /dev/null +++ b/e2e/playwright/shared/base-config/global.setup.ts @@ -0,0 +1,46 @@ +/* + * 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 { chromium, FullConfig } from '@playwright/test'; +import { LoginPage } from '../page-objects'; +import fs from 'fs'; + +const E2E_HOST = process.env.PLAYWRIGHT_E2E_HOST; +const E2E_PORT = process.env.PLAYWRIGHT_E2E_PORT; +const acsAdminUser = process.env.ADMIN_EMAIL; +const acsAdminUserPassword = process.env.ADMIN_PASSWORD; + +async function globalSetup(config: FullConfig) { + const { use } = config.projects[0]; + + let baseUrl: string; + + if (use.baseURL) { + baseUrl = use.baseURL; + } else { + if (E2E_HOST?.match(/localhost/)) { + baseUrl = `${E2E_HOST}:${E2E_PORT}`; + } else { + baseUrl = E2E_HOST; + } + } + + const browser = await chromium.launch({ + args: ['--disable-web-security'] + }); + const page = await browser.newPage(); + const loginPage = new LoginPage(page); + + fs.mkdirSync(`./storage-state`, { recursive: true }); + await page.goto(baseUrl); + await loginPage.loginUser({ username: acsAdminUser, password: acsAdminUserPassword }, { withNavigation: false, waitForLoading: true }); + await page.context().storageState({ path: `./storage-state/AdminUserState.json` }); + await browser.close(); +} + +export default globalSetup; diff --git a/e2e/playwright/shared/base-config/index.ts b/e2e/playwright/shared/base-config/index.ts new file mode 100644 index 000000000..cf2f3f177 --- /dev/null +++ b/e2e/playwright/shared/base-config/index.ts @@ -0,0 +1,9 @@ +/* + * 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 './global.setup'; diff --git a/e2e/playwright/shared/index.ts b/e2e/playwright/shared/index.ts new file mode 100644 index 000000000..55bb04d1e --- /dev/null +++ b/e2e/playwright/shared/index.ts @@ -0,0 +1,29 @@ +/*! + * @license + * Alfresco Example Content Application + * + * Copyright (C) 2005 - 2023 Alfresco Software Limited + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +export * from './api'; +export * from './base-config'; +export * from './models'; +export * from './page-objects'; diff --git a/e2e/playwright/shared/models/index.ts b/e2e/playwright/shared/models/index.ts new file mode 100644 index 000000000..007b72f82 --- /dev/null +++ b/e2e/playwright/shared/models/index.ts @@ -0,0 +1,9 @@ +/* + * 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 './user-model'; diff --git a/e2e/playwright/shared/models/user-model.ts b/e2e/playwright/shared/models/user-model.ts new file mode 100644 index 000000000..5b86101b5 --- /dev/null +++ b/e2e/playwright/shared/models/user-model.ts @@ -0,0 +1,44 @@ +/* + * 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 { StringUtil } from '@alfresco/adf-testing'; + +const LOWER_CASE_ALPHA = 'helloworld'; +export class UserModel { + firstName?: string = StringUtil.generateRandomCharset(length, LOWER_CASE_ALPHA)(7); + lastName?: string = StringUtil.generateRandomCharset(length, LOWER_CASE_ALPHA)(7); + password?: string = StringUtil.generateRandomCharset(length, LOWER_CASE_ALPHA)(7); + email?: string; + username?: string; + idIdentityService?: string; + type = 'enterprise'; + tenantId?: number; + company?: string; + id: number; + + constructor(details: any = {}) { + const EMAIL_DOMAIN = 'alfresco'; + this.firstName = details.firstName ?? this.firstName; + this.lastName = details.lastName ?? this.lastName; + + const USER_IDENTIFY = `${this.firstName}${this.lastName}.${StringUtil.generateRandomCharset(length, LOWER_CASE_ALPHA)(7)}`; + + this.password = details.password ?? this.password; + this.email = details.email ?? `${USER_IDENTIFY}@${EMAIL_DOMAIN}.com`; + this.username = details.username ?? USER_IDENTIFY; + this.idIdentityService = details.idIdentityService ?? this.idIdentityService; + this.type = details.type ?? this.type; + this.tenantId = details.tenantId ?? this.tenantId; + this.company = details.company ?? this.company; + this.id = details.id ?? this.id; + } + + get fullName(): string { + return `${this.firstName ?? ''} ${this.lastName ?? ''}`; + } +} diff --git a/e2e/playwright/shared/package.json b/e2e/playwright/shared/package.json new file mode 100644 index 000000000..c7bc52fd2 --- /dev/null +++ b/e2e/playwright/shared/package.json @@ -0,0 +1,8 @@ +{ + "name": "playwright-shared", + "version": "3.0.0", + "main": "index.ts", + "dependencies": { + "tslib": "^2.0.0" + } +} diff --git a/e2e/playwright/shared/page-objects/components/base.component.ts b/e2e/playwright/shared/page-objects/components/base.component.ts new file mode 100644 index 000000000..e7abe19f9 --- /dev/null +++ b/e2e/playwright/shared/page-objects/components/base.component.ts @@ -0,0 +1,48 @@ +/* + * 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 { PlaywrightBase } from '../playwright-base'; + +export abstract class BaseComponent extends PlaywrightBase { + private rootElement: string; + private overlayElement = this.page.locator('.cdk-overlay-backdrop-showing'); + + constructor(page: Page, rootElement: string) { + super(page); + this.rootElement = rootElement; + } + + /** + * Method which should be used across the repository, while creating + * reference to elements, which are in root element of component. + * + * @param cssLocator css selector as String. Need to be in the tree under the root element + * @param options if you want to localize it by text, then provide an optional hasText + * @returns Locator object + */ + getChild(cssLocator: string, options?: { hasText?: string | RegExp; has?: Locator }): Locator { + return this.page.locator(`${this.rootElement} ${cssLocator}`, options); + } + + async closeAdditionalOverlayElementIfVisible(): Promise { + if (await this.overlayElement.isVisible()) { + await this.page.keyboard.press('Escape'); + await this.overlayElement.waitFor({ state: 'detached', timeout: 5000 }); + } + } + + async spinnerWaitForReload(): Promise { + try { + await this.page.locator('mat-progress-spinner').waitFor({ state: 'attached', timeout: 2000 }); + await this.page.locator('mat-progress-spinner').waitFor({ state: 'detached', timeout: 2000 }); + } catch (e) { + this.logger.info('Spinner was not present'); + } + } +} diff --git a/e2e/playwright/shared/page-objects/components/dataTable/data-table.component.ts b/e2e/playwright/shared/page-objects/components/dataTable/data-table.component.ts new file mode 100644 index 000000000..a6ac03e54 --- /dev/null +++ b/e2e/playwright/shared/page-objects/components/dataTable/data-table.component.ts @@ -0,0 +1,143 @@ +/* + * 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 '../base.component'; +import { MatMenuComponent } from './mat-menu.component'; + +export class DataTableComponent extends BaseComponent { + private static rootElement = 'adf-datatable'; + contextMenuActions = new MatMenuComponent(this.page); + + constructor(page: Page, rootElement = DataTableComponent.rootElement) { + super(page, rootElement); + } + + getEmptyFolderLocator = this.getChild('.adf-empty-folder'); + getEmptyContentTitleLocator = this.getChild('adf-empty-content .adf-empty-content__title'); + getEmptyContentSubTitleLocator = this.getChild('adf-empty-content .adf-empty-content__subtitle'); + + /** Locator for row (or rows) */ + getRowLocator = this.getChild(`adf-datatable-row`); + + /** + * Method used in cases where we want to check that some record is visible in the datatable. It will consider whole row + * + * @returns reference to cell element which contains text. + */ + getRowByName = (name: string | number): Locator => this.getChild(`adf-datatable-row`, { hasText: name.toString() }); + + /** + * Method used in cases where we want to check that some record is visible in the datatable. + * But we want to check it by column header title and value of this column. + * + * @returns reference to cell element which contains text. + */ + getRowByColumnTitleAndItsCellValue = (columnTitle: string, cellValue: string | number): Locator => + this.page.locator(`//div[contains(@title, '${columnTitle}')]//span[contains(text(), '${cellValue}')]/ancestor::adf-datatable-row`); + + /** + * Method used in cases where user have possibility to navigate "inside" the element (it's clickable and has link attribute). + * Perform action .click() to navigate inside it + * + * @returns reference to cell element which contains link. + */ + getCellLinkByName = (name: string): Locator => this.getChild('.adf-datatable-cell-value[role="link"]', { hasText: name }); + + /** + * Method used in cases where we want to localize the element by [aria-label] + * + * @returns reference to cell element. + */ + getByAriaLabelTitle = (title: string): Locator => this.getChild(`[aria-label="${title}"]`); + + /** + * Method used in cases where we want to get the button (hamburger menu) for row element + * + * @returns reference to menu placed in row localized by the name + */ + getActionsButtonByName = (name: string): Locator => + this.getRowByName(name).locator('mat-icon', { hasText: new RegExp(`^\\s*more_vert\\s*$`, 'g') }); + + /** + * Method used in cases where we want to get the edit button and there is no hamburger menu + * + * @returns reference to edit button placed in row localized by the name + */ + getEditButtonByName = (name: string): Locator => this.getRowByName(name).locator('button#editButton'); + + /** + * Method used in cases where we want to get the button and there is no hamburger menu + * + * @returns reference to button placed in row localized by the name + */ + getButtonByNameForSpecificRow = (elementTitleInRow: string, buttonTitle: string): Locator => + this.getRowByName(elementTitleInRow).locator('button', { hasText: buttonTitle }); + + /** + * Method used in cases where you want to get some specific cell (by column name) for row which contains some name/title/etc. + * + * @returns reference to cell element + */ + getCellByColumnNameAndRowItem = (item: string | number, columnName: string): Locator => this.getRowByName(item).locator(`[title="${columnName}"]`); + + /** + * Method used in cases where we want to get the checkbox for row element + * + * @returns reference to checkbox placed in row localized by the name + */ + getCheckboxForElement = (item: string): Locator => this.getRowByName(item).locator('mat-checkbox'); + + getColumnHeaderByTitleLocator = (headerTitle: string): Locator => this.getChild('[role="columnheader"]', { hasText: headerTitle }); + + async sortBy(columnTitle: string, order: 'Ascending' | 'Descending'): Promise { + const columnHeaderLocator = this.getColumnHeaderByTitleLocator(columnTitle); + await this.spinnerWaitForReload(); + await columnHeaderLocator.click(); + + const sortAttribute = await columnHeaderLocator.getAttribute('aria-sort'); + if (sortAttribute !== order) { + await columnHeaderLocator.click(); + } + + await this.spinnerWaitForReload(); + } + + /** + * This method is used when we want to perform right mouse click on the dataTable row and perform some action + * + * @param name of the data table element with which we want to click + * @param action provide which action you want to perform + */ + async performActionFromExpandableMenu(name: string | number, action: string): Promise { + const actionButtonLocator = await this.getActionLocatorFromExpandableMenu(name, action); + await actionButtonLocator.click(); + await this.spinnerWaitForReload(); + } + + /** + * Click action from the expandable kebab menu for the element in datatable + * + * @param name title of the record you would like to proceed + * @param action provide button title for the action + * @param subAction if the action is in sub menu, then provide it here + */ + async performActionForElement(name: string, action: string, subAction?: string): Promise { + await this.getActionsButtonByName(name).click(); + await this.contextMenuActions.getButtonByText(action).click(); + + if (subAction) { + await this.contextMenuActions.getButtonByText(subAction).click(); + } + } + + async getActionLocatorFromExpandableMenu(name: string | number, action: string): Promise { + await this.getRowByName(name).click({ button: 'right' }); + return this.contextMenuActions.getButtonByText(action); + } +} diff --git a/e2e/playwright/shared/page-objects/components/dataTable/index.ts b/e2e/playwright/shared/page-objects/components/dataTable/index.ts new file mode 100644 index 000000000..d74c4447d --- /dev/null +++ b/e2e/playwright/shared/page-objects/components/dataTable/index.ts @@ -0,0 +1,11 @@ +/* + * 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 './data-table.component'; +export * from './mat-menu.component'; +export * from './toolbar.component'; diff --git a/e2e/playwright/shared/page-objects/components/dataTable/mat-menu.component.ts b/e2e/playwright/shared/page-objects/components/dataTable/mat-menu.component.ts new file mode 100644 index 000000000..71461aac6 --- /dev/null +++ b/e2e/playwright/shared/page-objects/components/dataTable/mat-menu.component.ts @@ -0,0 +1,22 @@ +/* + * 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 { Page } from '@playwright/test'; +import { BaseComponent } from '../base.component'; + +export class MatMenuComponent extends BaseComponent { + private static rootElement = '.mat-menu-content'; + + constructor(page: Page) { + super(page, MatMenuComponent.rootElement); + } + + public getMenuItemsLocator = this.getChild('button'); + + public getButtonByText = (text: string) => this.getChild('button', { hasText: text }); +} diff --git a/e2e/playwright/shared/page-objects/components/dataTable/toolbar.component.ts b/e2e/playwright/shared/page-objects/components/dataTable/toolbar.component.ts new file mode 100644 index 000000000..3d904be8c --- /dev/null +++ b/e2e/playwright/shared/page-objects/components/dataTable/toolbar.component.ts @@ -0,0 +1,23 @@ +/* + * 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 '../base.component'; +import { Page } from '@playwright/test'; + +export class ToolbarComponent extends BaseComponent { + private static rootElement = 'adf-toolbar'; + private createRuleButton = this.getChild('[data-automation-id="manage-rules-create-button"]'); + + constructor(page: Page) { + super(page, ToolbarComponent.rootElement); + } + + async clickCreateRuleButton(): Promise { + await this.createRuleButton.click(); + } +} diff --git a/e2e/playwright/shared/page-objects/components/index.ts b/e2e/playwright/shared/page-objects/components/index.ts new file mode 100644 index 000000000..ef53b168a --- /dev/null +++ b/e2e/playwright/shared/page-objects/components/index.ts @@ -0,0 +1,11 @@ +/* + * 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 './base.component'; +export * from './snack-bar.component'; +export * from './spinner.component'; diff --git a/e2e/playwright/shared/page-objects/components/snack-bar.component.ts b/e2e/playwright/shared/page-objects/components/snack-bar.component.ts new file mode 100644 index 000000000..a491765ef --- /dev/null +++ b/e2e/playwright/shared/page-objects/components/snack-bar.component.ts @@ -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 { Page } from '@playwright/test'; +import { BaseComponent } from './base.component'; + +export class SnackBarComponent extends BaseComponent { + private static rootElement = 'simple-snack-bar'; + + public message = this.getChild(' > span'); + public getByMessageLocator = (message: string) => this.getChild('span', { hasText: message }); + + constructor(page: Page, rootElement = SnackBarComponent.rootElement) { + super(page, rootElement); + } +} diff --git a/e2e/playwright/shared/page-objects/components/spinner.component.ts b/e2e/playwright/shared/page-objects/components/spinner.component.ts new file mode 100644 index 000000000..67faec726 --- /dev/null +++ b/e2e/playwright/shared/page-objects/components/spinner.component.ts @@ -0,0 +1,27 @@ +/* + * 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 { Page } from '@playwright/test'; +import { BaseComponent } from './base.component'; + +export class SpinnerComponent extends BaseComponent { + private static rootElement = 'mat-progress-spinner'; + + constructor(page: Page, rootElement = SpinnerComponent.rootElement) { + super(page, rootElement); + } + + async waitForReload(): Promise { + try { + await this.getChild('').waitFor({ state: 'attached', timeout: 2000 }); + await this.getChild('').waitFor({ state: 'detached', timeout: 2000 }); + } catch (e) { + this.logger.info('Spinner was not present'); + } + } +} diff --git a/e2e/playwright/shared/page-objects/global-variables.ts b/e2e/playwright/shared/page-objects/global-variables.ts new file mode 100644 index 000000000..31bafb6de --- /dev/null +++ b/e2e/playwright/shared/page-objects/global-variables.ts @@ -0,0 +1,37 @@ +/* + * 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. + */ + +const env = process.env; + +export const testEmailDomain = env.E2E_EMAIL_DOMAIN; +export const users = { + superadmin: { + username: env.SUPERADMIN_EMAIL, + password: env.SUPERADMIN_PASSWORD + }, + identity: { + username: env.IDENTITY_USER_EMAIL, + password: env.IDENTITY_USER_PASSWORD + }, + hruser: { + username: env.HR_USER, + password: env.HR_USER_PASSWORD + }, + salesuser: { + username: env.SALES_USER, + password: env.SALES_USER_PASSWORD + }, + admin: { + username: env.ADMIN_EMAIL, + password: env.ADMIN_PASSWORD + }, + contentIdentity: { + username: env.CONTENT_IDENTITY_USERNAME, + password: env.CONTENT_IDENTITY_PASSWORD + } +}; diff --git a/e2e/playwright/shared/page-objects/index.ts b/e2e/playwright/shared/page-objects/index.ts new file mode 100644 index 000000000..8bdc721ea --- /dev/null +++ b/e2e/playwright/shared/page-objects/index.ts @@ -0,0 +1,13 @@ +/* + * 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 './global-variables'; +export * from './playwright-base'; +export * from './components'; +export * from './components/dataTable'; +export * from './pages'; diff --git a/e2e/playwright/shared/page-objects/pages/base.page.ts b/e2e/playwright/shared/page-objects/pages/base.page.ts new file mode 100644 index 000000000..73f97a423 --- /dev/null +++ b/e2e/playwright/shared/page-objects/pages/base.page.ts @@ -0,0 +1,80 @@ +/* + * 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 { Page } from '@playwright/test'; +import { PlaywrightBase } from '../playwright-base'; +import { SnackBarComponent, SpinnerComponent } from '../components'; + +export interface NavigateOptions { + query?: string; + waitForRequest?: boolean; + waitUntil?: 'networkidle' | 'commit' | 'load' | 'domcontentloaded'; + remoteUrl?: string; +} +export abstract class BasePage extends PlaywrightBase { + private pageUrl: string; + private urlRequest: RegExp; + public snackBar: SnackBarComponent; + public spinner: SpinnerComponent; + + constructor(page: Page, pageUrl: string, urlRequest?: RegExp) { + super(page); + this.pageUrl = pageUrl; + this.urlRequest = urlRequest; + this.snackBar = new SnackBarComponent(this.page); + this.spinner = new SpinnerComponent(this.page); + } + + /** + * Method which navigate to appropriate page or remoteURL + * + * @param options object with configurable options + * @property {string} query if you would like to navigate to page which support query, + * then pass it in this option - e.g. '?appName=content' + * @property {boolean} waitForRequest if you would like to NOT wait for request (which need to be passed + * in the constructor of the page), then pass false. By default it'll wait for request to be fulfilled. + * @property {'networkidle' | 'commit' | 'load' | 'domcontentloaded'} waitUntil by default will wait until 'networkidle' but you can change it if needed + * @property {string} remoteUrl if you need to navigate to third part site, then you need to pass all of the URL in this option + */ + async navigate(options?: Partial): Promise { + const actualOptions: NavigateOptions = { + query: '', + waitForRequest: true, + remoteUrl: '', + ...options + }; + + if (actualOptions.remoteUrl) { + await this.page.goto(actualOptions.remoteUrl, { + waitUntil: actualOptions.waitUntil + }); + } else { + if (this.urlRequest && actualOptions.waitForRequest) { + await Promise.all([ + this.page.goto(`./#/${this.pageUrl}${actualOptions.query}`, { waitUntil: 'load' }), + this.page.waitForResponse(this.urlRequest) + ]); + } else { + await this.page.goto(`./#/${this.pageUrl}${actualOptions.query}`, { + waitUntil: actualOptions.waitUntil, + timeout: 10000 + }); + } + } + + await this.spinner.waitForReload(); + } + + async reload(options?: Pick): Promise { + const actualOptions: Pick = { + waitUntil: 'networkidle', + ...options + }; + await this.page.reload(actualOptions); + } +} diff --git a/e2e/playwright/shared/page-objects/pages/index.ts b/e2e/playwright/shared/page-objects/pages/index.ts new file mode 100644 index 000000000..8b623b8eb --- /dev/null +++ b/e2e/playwright/shared/page-objects/pages/index.ts @@ -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 './base.page'; +export * from './login.page'; diff --git a/e2e/playwright/shared/page-objects/pages/login.page.ts b/e2e/playwright/shared/page-objects/pages/login.page.ts new file mode 100644 index 000000000..c5a9830f5 --- /dev/null +++ b/e2e/playwright/shared/page-objects/pages/login.page.ts @@ -0,0 +1,38 @@ +/* + * 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 { Page } from '@playwright/test'; +import { BasePage } from './base.page'; +import { UserModel } from '../../models'; + +interface LoginOptions { + waitForLoading?: boolean; + withNavigation?: boolean; +} +export class LoginPage extends BasePage { + constructor(page: Page) { + super(page, ''); + } + + private username = this.page.locator('#username'); + private password = this.page.locator('#password'); + private submitButton = this.page.locator('#login-button'); + + async loginUser(userData: { username: string; password: string } | UserModel, options?: LoginOptions): Promise { + if (options?.withNavigation) { + await this.navigate(); + } + await this.username.fill(userData.username); + await this.password.fill(userData.password); + await this.submitButton.click(); + + if (options?.waitForLoading) { + await Promise.all([this.page.waitForLoadState('domcontentloaded'), this.spinner.waitForReload()]); + } + } +} diff --git a/e2e/playwright/shared/page-objects/playwright-base.ts b/e2e/playwright/shared/page-objects/playwright-base.ts new file mode 100644 index 000000000..87c483bcd --- /dev/null +++ b/e2e/playwright/shared/page-objects/playwright-base.ts @@ -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 { GenericLogger, LoggerLike } from '@alfresco/adf-testing'; +import { Page } from '@playwright/test'; + +export abstract class PlaywrightBase { + public page: Page; + public logger: LoggerLike; + + constructor(page: Page) { + this.page = page; + this.logger = new GenericLogger(process.env.PLAYWRIGHT_CUSTOM_LOG_LEVEL); + } +} diff --git a/e2e/playwright/shared/tsconfig.lib.json b/e2e/playwright/shared/tsconfig.lib.json new file mode 100644 index 000000000..281b7ca83 --- /dev/null +++ b/e2e/playwright/shared/tsconfig.lib.json @@ -0,0 +1,24 @@ +{ + "extends": "../../tsconfig.e2e.json", + "compilerOptions": { + "outDir": "../../../out-tsc/playwright-testing", + "target": "es2015", + "module": "es2015", + "moduleResolution": "node", + "declaration": true, + "sourceMap": true, + "inlineSources": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "importHelpers": true, + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "fullTemplateTypeCheck": true, + "strictInjectionParameters": true, + "enableResourceInlining": true + }, + "exclude": ["node_modules"] +} diff --git a/e2e/playwright/tests/folder-rules/fixtures/page-initialization.ts b/e2e/playwright/tests/folder-rules/fixtures/page-initialization.ts new file mode 100644 index 000000000..6bc2f4d35 --- /dev/null +++ b/e2e/playwright/tests/folder-rules/fixtures/page-initialization.ts @@ -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({ + 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); + } +}); diff --git a/e2e/playwright/tests/folder-rules/page-objects/components/actions-dropdown.component.ts b/e2e/playwright/tests/folder-rules/page-objects/components/actions-dropdown.component.ts new file mode 100644 index 000000000..41205992b --- /dev/null +++ b/e2e/playwright/tests/folder-rules/page-objects/components/actions-dropdown.component.ts @@ -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): Promise { + await this.page.locator(`aca-edit-rule-dialog [data-automation-id="rule-action-select"]`).click(); + const option = this.getOptionLocator(action); + await option.click(); + } +} diff --git a/e2e/playwright/tests/folder-rules/page-objects/components/conditions.component.ts b/e2e/playwright/tests/folder-rules/page-objects/components/conditions.component.ts new file mode 100644 index 000000000..16f6e587e --- /dev/null +++ b/e2e/playwright/tests/folder-rules/page-objects/components/conditions.component.ts @@ -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): Promise { + await this.fieldDropDown.click(); + const option = this.getOptionLocator(fields); + await option.click(); + } + + private async selectComparator(comparators: Partial): Promise { + await this.comparatorDropDown.click(); + const option = this.getOptionLocator(comparators); + await option.click(); + } + + async addCondition(fields: Partial, comparators: Partial, value: string): Promise { + await this.addConditionButton.click(); + await this.selectField(fields); + await this.selectComparator(comparators); + await this.typeConditionValue(value); + } +} diff --git a/e2e/playwright/tests/folder-rules/page-objects/components/manage-rules-dialog.component.ts b/e2e/playwright/tests/folder-rules/page-objects/components/manage-rules-dialog.component.ts new file mode 100644 index 000000000..87d86af22 --- /dev/null +++ b/e2e/playwright/tests/folder-rules/page-objects/components/manage-rules-dialog.component.ts @@ -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 { + await this.ruleNameInputLocator.type(ruleName, { delay: 50 }); + } + + async typeConditionValue(ruleName: string): Promise { + await this.valueField.type(ruleName, { delay: 50 }); + } +} diff --git a/e2e/playwright/tests/folder-rules/page-objects/components/manage-rules.component.ts b/e2e/playwright/tests/folder-rules/page-objects/components/manage-rules.component.ts new file mode 100644 index 000000000..a9b290666 --- /dev/null +++ b/e2e/playwright/tests/folder-rules/page-objects/components/manage-rules.component.ts @@ -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); + } +} diff --git a/e2e/playwright/tests/folder-rules/page-objects/index.ts b/e2e/playwright/tests/folder-rules/page-objects/index.ts new file mode 100644 index 000000000..0ab010986 --- /dev/null +++ b/e2e/playwright/tests/folder-rules/page-objects/index.ts @@ -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'; diff --git a/e2e/playwright/tests/folder-rules/page-objects/pages/nodes.page.ts b/e2e/playwright/tests/folder-rules/page-objects/pages/nodes.page.ts new file mode 100644 index 000000000..e1c03f790 --- /dev/null +++ b/e2e/playwright/tests/folder-rules/page-objects/pages/nodes.page.ts @@ -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); +} diff --git a/e2e/playwright/tests/folder-rules/page-objects/pages/personal-files.page.ts b/e2e/playwright/tests/folder-rules/page-objects/pages/personal-files.page.ts new file mode 100644 index 000000000..7578434c8 --- /dev/null +++ b/e2e/playwright/tests/folder-rules/page-objects/pages/personal-files.page.ts @@ -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); +} diff --git a/e2e/playwright/tests/folder-rules/playwright.config.ts b/e2e/playwright/tests/folder-rules/playwright.config.ts new file mode 100644 index 000000000..d6a1c9d27 --- /dev/null +++ b/e2e/playwright/tests/folder-rules/playwright.config.ts @@ -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; diff --git a/e2e/playwright/tests/folder-rules/tests/actions.spec.ts b/e2e/playwright/tests/folder-rules/tests/actions.spec.ts new file mode 100644 index 000000000..744035516 --- /dev/null +++ b/e2e/playwright/tests/folder-rules/tests/actions.spec.ts @@ -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(); + }); +}); diff --git a/e2e/playwright/tests/folder-rules/tests/conditions.spec.ts b/e2e/playwright/tests/folder-rules/tests/conditions.spec.ts new file mode 100644 index 000000000..22fea7d21 --- /dev/null +++ b/e2e/playwright/tests/folder-rules/tests/conditions.spec.ts @@ -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(); + }); +}); diff --git a/e2e/playwright/tests/folder-rules/tests/manage-rules.spec.ts b/e2e/playwright/tests/folder-rules/tests/manage-rules.spec.ts new file mode 100644 index 000000000..d78df7fa6 --- /dev/null +++ b/e2e/playwright/tests/folder-rules/tests/manage-rules.spec.ts @@ -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(); + }); +}); diff --git a/e2e/tsconfig.e2e.json b/e2e/tsconfig.e2e.json index 38350b935..1a23ff5b8 100755 --- a/e2e/tsconfig.e2e.json +++ b/e2e/tsconfig.e2e.json @@ -5,10 +5,11 @@ "baseUrl": "./", "module": "commonjs", "target": "es2017", - "types": ["jasmine", "jasminewd2", "node"], + "types": ["jasmine", "jasminewd2", "node", "@playwright/test"], "skipLibCheck": true, "paths": { - "@alfresco/aca-testing-shared": ["../projects/aca-testing-shared/src/index.ts"] + "@alfresco/aca-testing-shared": ["../projects/aca-testing-shared/src/index.ts"], + "@alfresco/playwright-shared": ["./playwright/shared/index.ts"] } }, "exclude": ["node_modules"] diff --git a/package-lock.json b/package-lock.json index ee964818b..25a8e1014 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4798,6 +4798,22 @@ } } }, + "@playwright/test": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.30.0.tgz", + "integrity": "sha512-SVxkQw1xvn/Wk/EvBnqWIq6NLo1AppwbYOjNLmyU0R1RoQ3rLEBtmjTnElcnz8VEtn11fptj1ECxK0tgURhajw==", + "requires": { + "@types/node": "*", + "playwright-core": "1.30.0" + }, + "dependencies": { + "playwright-core": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.30.0.tgz", + "integrity": "sha512-7AnRmTCf+GVYhHbLJsGUtskWTE33SwMZkybJ0v6rqR1boxq2x36U7p1vDRV7HO2IwTZgmycracLxPEJI49wu4g==" + } + } + }, "@quanzo/change-font-size": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@quanzo/change-font-size/-/change-font-size-1.0.0.tgz", @@ -5054,10 +5070,9 @@ "dev": true }, "@types/node": { - "version": "14.14.25", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.25.tgz", - "integrity": "sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ==", - "dev": true + "version": "14.18.36", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.36.tgz", + "integrity": "sha512-FXKWbsJ6a1hIrRxv+FoukuHnGTgEzKYGi7kilfMae96AL9UNkPFNWJEEYWzdRI9ooIkbr4AKldyuSTLql06vLQ==" }, "@types/normalize-package-data": { "version": "2.4.1", @@ -6174,7 +6189,7 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true }, "ansi-styles": { @@ -6301,13 +6316,13 @@ "array-uniq": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", "dev": true }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", "dev": true }, "array.prototype.flat": { @@ -6337,7 +6352,7 @@ "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", "dev": true }, "asap": { @@ -6358,7 +6373,7 @@ "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", "dev": true }, "assertion-error": { @@ -6391,7 +6406,7 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "at-least-node": { "version": "1.0.0", @@ -6428,7 +6443,7 @@ "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", "dev": true }, "aws4": { @@ -6592,13 +6607,13 @@ "batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", "dev": true }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", "dev": true, "requires": { "tweetnacl": "^0.14.3" @@ -7139,7 +7154,7 @@ "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", "dev": true }, "chai": { @@ -7186,7 +7201,7 @@ "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", "dev": true }, "check-more-types": { @@ -7412,7 +7427,7 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "color-string": { @@ -7567,7 +7582,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "concat-stream": { "version": "1.6.2", @@ -7682,7 +7697,7 @@ "connect-logger": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/connect-logger/-/connect-logger-0.0.1.tgz", - "integrity": "sha1-TZmZeKHSC7RgjnzUNNdBZSJVF0s=", + "integrity": "sha512-kC5FPWpcfgpW5HtICnXbdOAFa4uNilU4ZPmsH6RlXaDVfXLupyUjgI1otpj3kOcsoPpDxknxmcoM0wk0ApsjYQ==", "dev": true, "requires": { "moment": "*" @@ -7876,7 +7891,7 @@ "corser": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", - "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=", + "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", "dev": true }, "cosmiconfig": { @@ -8731,7 +8746,7 @@ "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", "dev": true, "requires": { "assert-plus": "^1.0.0" @@ -8893,7 +8908,7 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, "delegates": { "version": "1.0.0", @@ -9133,7 +9148,7 @@ "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", "dev": true, "requires": { "jsbn": "~0.1.0", @@ -9158,7 +9173,7 @@ "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "dev": true }, "ejs": { @@ -9194,7 +9209,7 @@ "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true }, "encoding": { @@ -9551,7 +9566,7 @@ "es6-promisify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", "dev": true, "requires": { "es6-promise": "^4.0.3" @@ -9721,13 +9736,13 @@ "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "dev": true }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true }, "eslint": { @@ -10656,7 +10671,7 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "dev": true }, "event-emitter": { @@ -10729,7 +10744,7 @@ "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true }, "express": { @@ -11023,7 +11038,7 @@ "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", "dev": true }, "fast-deep-equal": { @@ -11069,7 +11084,7 @@ "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==", "dev": true } } @@ -11166,7 +11181,7 @@ "filename-reserved-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", - "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", "dev": true }, "filenamify": { @@ -11352,7 +11367,7 @@ "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", "dev": true }, "form-data": { @@ -11385,7 +11400,7 @@ "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "dev": true }, "from2": { @@ -11503,7 +11518,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, "fsevents": { @@ -11607,7 +11622,7 @@ "get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", "dev": true }, "get-intrinsic": { @@ -11668,7 +11683,7 @@ "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", "dev": true, "requires": { "assert-plus": "^1.0.0" @@ -11820,7 +11835,7 @@ "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", "dev": true }, "har-validator": { @@ -11844,7 +11859,7 @@ "has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", "dev": true, "requires": { "ansi-regex": "^2.0.0" @@ -11859,7 +11874,7 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true }, "has-own-prop": { @@ -12173,7 +12188,7 @@ "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", "dev": true, "requires": { "assert-plus": "^1.0.0", @@ -12211,7 +12226,7 @@ "humanize-ms": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", "dev": true, "requires": { "ms": "^2.0.0" @@ -12275,7 +12290,7 @@ "immediate": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", "dev": true }, "immutable": { @@ -12320,7 +12335,7 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true }, "indent-string": { @@ -12338,7 +12353,7 @@ "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, "requires": { "once": "^1.3.0", @@ -12590,7 +12605,7 @@ "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, "is-bigint": { @@ -12672,7 +12687,7 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true }, "is-fullwidth-code-point": { @@ -12863,7 +12878,7 @@ "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", "dev": true }, "is-unicode-supported": { @@ -12912,7 +12927,7 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true }, "isbinaryfile": { @@ -12924,7 +12939,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, "isobject": { @@ -12936,7 +12951,7 @@ "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", "dev": true }, "istanbul-lib-coverage": { @@ -13061,7 +13076,7 @@ "jasmine": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", - "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=", + "integrity": "sha512-KbdGQTf5jbZgltoHs31XGiChAPumMSY64OZMWLNYnEnMfG5uwGBhffePwuskexjT+/Jea/gU3qAU8344hNohSw==", "dev": true, "requires": { "exit": "^0.1.2", @@ -13072,7 +13087,7 @@ "jasmine-core": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", - "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=", + "integrity": "sha512-SNkOkS+/jMZvLhuSx1fjhcNWUC/KG6oVyFUGkSBEr9n1axSNduWU8GlI7suaHXr4yxjet6KjrUZxUTE5WzzWwQ==", "dev": true } } @@ -13104,7 +13119,7 @@ "jasminewd2": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz", - "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=", + "integrity": "sha512-Rn0nZe4rfDhzA63Al3ZGh0E+JTmM6ESZYXJGKuqKGZObsAB9fwXPD03GjtIEvJBDOhN94T5MzbwZSqzFHSQPzg==", "dev": true }, "jest-worker": { @@ -13160,7 +13175,7 @@ "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", "dev": true }, "jsdoc-type-pratt-parser": { @@ -13237,7 +13252,7 @@ "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", "dev": true }, "json5": { @@ -13264,7 +13279,7 @@ "jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", "dev": true }, "jsprim": { @@ -13544,7 +13559,7 @@ "karma-mocha-reporter": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/karma-mocha-reporter/-/karma-mocha-reporter-2.2.5.tgz", - "integrity": "sha1-FRIAlejtgZGG5HoLAS8810GJVWA=", + "integrity": "sha512-Hr6nhkIp0GIJJrvzY8JFeHpQZNseuIakGac4bpw8K1+5F0tLb6l7uvXRa8mt2Z+NVwYgCct4QAfp2R2QP6o00w==", "dev": true, "requires": { "chalk": "^2.1.0", @@ -13581,7 +13596,7 @@ "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", "dev": true, "requires": { "ansi-regex": "^3.0.0" @@ -14354,7 +14369,7 @@ "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "dev": true }, "memfs": { @@ -14387,7 +14402,7 @@ "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" }, "micromatch": { "version": "4.0.4", @@ -14635,7 +14650,7 @@ "moment-es6": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/moment-es6/-/moment-es6-1.0.0.tgz", - "integrity": "sha1-VS/PQF1iVlsKH+hObB5peseTMt8=", + "integrity": "sha512-DeFuL4VMEGDSRyuhwPEFrIy0BxlRGk3yaEkJYnHKY50dLg+u5llQwK5Bjk/Rm5iSf8BuatnI0nODjHXhLzcKBw==", "requires": { "moment": "*" } @@ -15809,7 +15824,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true }, "object-inspect": { @@ -15865,7 +15880,7 @@ "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", "dev": true, "requires": { "ee-first": "1.1.1" @@ -15880,7 +15895,7 @@ "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "requires": { "wrappy": "1" @@ -16053,7 +16068,7 @@ "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "dev": true }, "osenv": { @@ -16657,13 +16672,13 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true }, "path-is-inside": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", "dev": true }, "path-key": { @@ -16710,7 +16725,7 @@ "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", "dev": true }, "picocolors": { @@ -16740,13 +16755,13 @@ "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", "dev": true }, "pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", "dev": true, "requires": { "pinkie": "^2.0.0" @@ -17287,7 +17302,7 @@ "promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", "dev": true }, "promise-retry": { @@ -17348,13 +17363,13 @@ "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", "dev": true }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", "dev": true, "requires": { "ansi-styles": "^2.2.1", @@ -17385,7 +17400,7 @@ "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "dev": true }, "source-map-support": { @@ -17400,13 +17415,13 @@ "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", "dev": true }, "tmp": { "version": "0.0.30", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", - "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=", + "integrity": "sha512-HXdTB7lvMwcb55XFfrTM8CPr/IYREk4hVBFaQ4b/6nInrluSL86hfHm7vu0luYKCfyBZp2trCjpc8caC3vVM3w==", "dev": true, "requires": { "os-tmpdir": "~1.0.1" @@ -17533,7 +17548,7 @@ "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, "requires": { "graceful-fs": "^4.1.6" @@ -18021,7 +18036,7 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true }, "require-from-string": { @@ -18045,7 +18060,7 @@ "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, "resolve": { @@ -18462,13 +18477,13 @@ "screenshoter-report-analyzer": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/screenshoter-report-analyzer/-/screenshoter-report-analyzer-0.6.0.tgz", - "integrity": "sha1-Cm+I1fXRrBa2z3Ji7/ujH+5I7RI=", + "integrity": "sha512-T4EbdD57N2fvptFj8GpLlD5lxfwzO3iRv3QEXkSNJWcotLySnrJDaLtzFRo64JBsQ4RomWrSt31XGgBoNOI8KA==", "dev": true }, "secure-compare": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", - "integrity": "sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=", + "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", "dev": true }, "select-hose": { @@ -18611,7 +18626,7 @@ "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", "dev": true, "requires": { "accepts": "~1.3.4", @@ -18635,7 +18650,7 @@ "http-errors": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", "dev": true, "requires": { "depd": "~1.1.2", @@ -18647,13 +18662,13 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", "dev": true }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, "setprototypeof": { @@ -18665,7 +18680,7 @@ "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", "dev": true } } @@ -18691,7 +18706,7 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, "setimmediate": { @@ -19089,7 +19104,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, "sshpk": { @@ -19308,7 +19323,7 @@ "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dev": true, "requires": { "ansi-regex": "^2.0.0" @@ -19535,7 +19550,7 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, "tfunk": { @@ -19584,7 +19599,7 @@ "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, "through2": { @@ -19647,7 +19662,7 @@ "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true }, "to-regex-range": { @@ -19696,7 +19711,7 @@ "trim-repeated": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", - "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", "dev": true, "requires": { "escape-string-regexp": "^1.0.2" @@ -19765,7 +19780,7 @@ "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dev": true, "requires": { "safe-buffer": "^5.0.1" @@ -19774,7 +19789,7 @@ "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", "dev": true }, "type": { @@ -19946,7 +19961,7 @@ "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true }, "untildify": { @@ -19983,7 +19998,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "util-extend": { "version": "1.0.3", @@ -19994,7 +20009,7 @@ "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "dev": true }, "uuid": { @@ -20031,13 +20046,13 @@ "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", "dev": true, "requires": { "assert-plus": "^1.0.0", @@ -20085,7 +20100,7 @@ "wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "dev": true, "requires": { "defaults": "^1.0.3" @@ -20122,7 +20137,7 @@ "tmp": { "version": "0.0.30", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", - "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=", + "integrity": "sha512-HXdTB7lvMwcb55XFfrTM8CPr/IYREk4hVBFaQ4b/6nInrluSL86hfHm7vu0luYKCfyBZp2trCjpc8caC3vVM3w==", "dev": true, "requires": { "os-tmpdir": "~1.0.1" @@ -20152,7 +20167,7 @@ "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", "dev": true }, "array-union": { @@ -20167,7 +20182,7 @@ "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", "dev": true, "requires": { "ansi-styles": "^2.2.1", @@ -20245,7 +20260,7 @@ "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", "dev": true } } @@ -20621,7 +20636,7 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", "dev": true }, "which-typed-array": { @@ -20700,7 +20715,7 @@ "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", "dev": true }, "wrap-ansi": { @@ -20758,7 +20773,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, "write-file-atomic": { diff --git a/package.json b/package.json index cfe256f7f..5e74b3dcb 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "@ngrx/store": "^14.2.0", "@ngrx/store-devtools": "^14.2.0", "@ngx-translate/core": "^14.0.0", + "@playwright/test": "^1.30.0", "minimatch-browser": "^1.0.0", "moment": "^2.29.4", "moment-es6": "1.0.0", diff --git a/projects/aca-folder-rules/src/public-api.ts b/projects/aca-folder-rules/src/public-api.ts index 96c5d3891..31b34ec96 100644 --- a/projects/aca-folder-rules/src/public-api.ts +++ b/projects/aca-folder-rules/src/public-api.ts @@ -2,7 +2,7 @@ * @license * Alfresco Example Content Application * - * Copyright (C) 2005 - 2020 Alfresco Software Limited + * Copyright (C) 2005 - 2023 Alfresco Software Limited * * This file is part of the Alfresco Example Content Application. * If the software was purchased under a paid Alfresco license, the terms of diff --git a/scripts/ci/job_hooks/after_e2e.sh b/scripts/ci/job_hooks/after_e2e.sh index a85f2496d..ce23663a4 100755 --- a/scripts/ci/job_hooks/after_e2e.sh +++ b/scripts/ci/job_hooks/after_e2e.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +storage_dir="./storage-state/AdminUserState.json" +rm -rf $storage_dir + # Upload protractor-smartrunner artifact related to this particular job to S3 ./scripts/ci/utils/artifact-to-s3.sh -a "$SMART_RUNNER_DIRECTORY" -o "$S3_DBP_FOLDER/protractor-smartrunner-$TRAVIS_JOB_ID.tar.bz2" diff --git a/scripts/ci/job_hooks/before-playwright.sh b/scripts/ci/job_hooks/before-playwright.sh new file mode 100755 index 000000000..435aaf670 --- /dev/null +++ b/scripts/ci/job_hooks/before-playwright.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +npx playwright install chromium diff --git a/scripts/ci/jobs/affected-project-with.sh b/scripts/ci/jobs/affected-project-with.sh index 256360aea..77e639540 100755 --- a/scripts/ci/jobs/affected-project-with.sh +++ b/scripts/ci/jobs/affected-project-with.sh @@ -7,6 +7,7 @@ show_help() { echo "-target Project target" echo "-tag Filter project with tag" echo "-name Filter project with name" + echo "-test-runner Test runner to use (playwright or protractor)" } project_target(){ @@ -17,18 +18,27 @@ target_options(){ OPTIONS="$1" } +test_runner(){ + TEST_RUNNER=$1 +} + while [[ $1 == -* ]]; do case "$1" in -target) project_target $2; shift 2;; -options) target_options $2; shift 2;; + -test-runner) test_runner $2; shift 2;; -*) echo "invalid option: $1" 1>&2; show_help; exit 0;; esac done - -echo "Run alfresco-content-e2e protractor with options $OPTIONS" -echo "./node_modules/.bin/protractor \"./protractor.conf.js\" $OPTIONS || exit 1" - ./node_modules/.bin/tsc -p "./e2e/$E2E_TSCONFIG" || exit 1; ./node_modules/.bin/http-server -c-1 $CONTENT_CE_DIST_PATH -p 4200 > /dev/null &\ -./node_modules/.bin/protractor "./protractor.conf.js" $OPTIONS $E2E_PROTRACTOR_OPTS || exit 1 + +if [ "$TEST_RUNNER" == "playwright" ]; then + echo "Running playwright tests with options $OPTIONS" + npx playwright test --config $OPTIONS +else + echo "Running protractor tests with options $OPTIONS" + echo "./node_modules/.bin/protractor \"./protractor.conf.js\" $OPTIONS || exit 1" + ./node_modules/.bin/protractor "./protractor.conf.js" $OPTIONS $E2E_PROTRACTOR_OPTS || exit 1 +fi diff --git a/tsconfig.json b/tsconfig.json index 450c89bba..63f59a60b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,6 +12,7 @@ "emitDecoratorMetadata": true, "experimentalDecorators": true, "noUnusedLocals": true, + "skipLibCheck": true, "noUnusedParameters": true, "noImplicitReturns": true, "target": "es2020", @@ -30,6 +31,7 @@ "@alfresco/aca-content": ["projects/aca-content/src/public-api.ts"], "@alfresco/aca-viewer": ["projects/aca-viewer/src/public-api.ts"], "@alfresco/aca-preview": ["projects/aca-preview/src/public-api.ts"], + "@alfresco/playwright-shared": ["e2e/playwright/shared/index.ts"], "package.json": ["package.json"] } },