Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ACS-6797] search general migrated from Protractor to Playwright #3674

Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions e2e/playwright/search/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"extends": "../../../.eslintrc.json",
"ignorePatterns": [
"!**/*"
],
"overrides": [
{
"files": [
"*.ts"
],
"parserOptions": {
"project": [
"e2e/playwright/search/tsconfig.e2e.json"
],
"createDefaultProgram": true
},
"plugins": [
"rxjs",
"unicorn"
],
"rules": {
"@typescript-eslint/no-floating-promises": "off"
}
}
]
}
1 change: 1 addition & 0 deletions e2e/playwright/search/exclude.tests.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
44 changes: 44 additions & 0 deletions e2e/playwright/search/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*!
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Alfresco Example Content Application
*
* 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
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
*/

import { PlaywrightTestConfig } from '@playwright/test';
import { CustomConfig, getGlobalConfig, getExcludedTestsRegExpArray } from '@alfresco/playwright-shared';
import EXCLUDED_JSON from './exclude.tests.json';

const config: PlaywrightTestConfig<CustomConfig> = {
...getGlobalConfig,

grepInvert: getExcludedTestsRegExpArray(EXCLUDED_JSON, 'Search'),
projects: [
{
name: 'Search',
testDir: './src/tests',
use: {
users: []
}
}
]
};

export default config;
22 changes: 22 additions & 0 deletions e2e/playwright/search/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "search-e2e",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "e2e/playwright/search",
"projectType": "application",
"targets": {
"e2e": {
"executor": "nx:run-commands",
"options": {
"commands": ["npx playwright test --config=e2e/playwright/search/playwright.config.ts"]
},
"configurations": {
"production": {
"devServerTarget": "content-ce:serve:production"
}
}
},
"lint": {
"executor": "@angular-eslint/builder:lint"
}
}
}
155 changes: 155 additions & 0 deletions e2e/playwright/search/src/tests/search-results-general.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/*!
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Alfresco Example Content Application
*
* 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
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
*/

import { expect } from '@playwright/test';
import { ApiClientFactory, Utils, test, TrashcanApi, NodesApi, SitesApi } from '@alfresco/playwright-shared';

test.describe('Search Results - General', () => {
let trashcanApi: TrashcanApi;
let nodesApi: NodesApi;
let sitesApi: SitesApi;

const username = `user1-${Utils.random()}`;
const random = Utils.random();

const file = `test-file-${random}.txt`;
const folder = `test-folder-${random}`;
const site = `test-site-${random}`;

test.beforeEach(async ({ loginPage }) => {
try {
await loginPage.loginUser({ username, password: username }, { withNavigation: true, waitForLoading: true });
} catch (error) {
console.error(`beforeEach failed: ${error}`);
}
});

test.beforeAll(async () => {
try {
const apiClientFactory = new ApiClientFactory();
await apiClientFactory.setUpAcaBackend('admin');
await apiClientFactory.createUser({ username });
trashcanApi = await TrashcanApi.initialize(username, username);
nodesApi = await NodesApi.initialize(username, username);
sitesApi = await SitesApi.initialize(username, username);
await nodesApi.createFolder(folder);
await nodesApi.createFile(file, '-my-');
await sitesApi.createSite(site);
} catch (error) {
console.error(`beforeAll failed: ${error}`);
}
});

test.afterAll(async () => {
try {
await trashcanApi.emptyTrashcan();
await nodesApi.deleteCurrentUserNodes();
} catch (error) {
console.error(`afterAll failed: ${error}`);
}
});

test('[C290005] Only files are returned when Files option is the only one checked', async ({ searchPage }) => {
await searchPage.acaHeader.searchButton.click();
await searchPage.searchInput.searchButton.click();
await searchPage.searchInput.checkOnlyFiles();
await searchPage.searchInput.searchFor(`*${random}`);
await searchPage.dataTable.body.waitFor();

expect(await searchPage.dataTable.isItemPresent(file)).toBeTruthy();
expect(await searchPage.dataTable.isItemPresent(folder)).toBeFalsy();
expect(await searchPage.dataTable.isItemPresent(site)).toBeFalsy();
});

test('[C290006] Only folders are returned when Folders option is the only one checked', async ({ searchPage }) => {
await searchPage.acaHeader.searchButton.click();
await searchPage.searchInput.searchButton.click();
await searchPage.searchInput.checkOnlyFolders();
await searchPage.searchInput.searchFor(`*${random}`);
await searchPage.dataTable.body.waitFor();

expect(await searchPage.dataTable.isItemPresent(file)).toBeFalsy();
expect(await searchPage.dataTable.isItemPresent(folder)).toBeTruthy();
expect(await searchPage.dataTable.isItemPresent(site)).toBeFalsy();
});

test('[C290007] Files and folders are returned when both Files and Folders options are checked', async ({ searchPage }) => {
await searchPage.acaHeader.searchButton.click();
await searchPage.searchInput.searchButton.click();
await searchPage.searchInput.checkFilesAndFolders();
await searchPage.searchInput.searchFor(`*${random}`);
await searchPage.dataTable.body.waitFor();

expect(await searchPage.dataTable.isItemPresent(file)).toBeTruthy();
expect(await searchPage.dataTable.isItemPresent(folder)).toBeTruthy();
expect(await searchPage.dataTable.isItemPresent(site)).toBeFalsy();
});

test('[C290008] Only libraries are returned when Libraries option is checked', async ({ searchPage }) => {
await searchPage.acaHeader.searchButton.click();
await searchPage.searchInput.searchButton.click();
await searchPage.searchInput.checkLibraries();
await searchPage.searchInput.searchFor(`*${random}`);
await searchPage.dataTable.body.waitFor();

expect(await searchPage.dataTable.isItemPresent(file)).toBeFalsy();
expect(await searchPage.dataTable.isItemPresent(folder)).toBeFalsy();
expect(await searchPage.dataTable.isItemPresent(site)).toBeTruthy();
});

test('[C279162] Results are updated automatically when changing the search term', async ({ searchPage }) => {
await searchPage.acaHeader.searchButton.click();
await searchPage.searchInput.searchButton.click();
await searchPage.searchInput.searchFor(file);
await searchPage.dataTable.body.waitFor();

expect(await searchPage.dataTable.isItemPresent(file)).toBeTruthy();
expect(await searchPage.dataTable.isItemPresent(folder)).toBeFalsy();

await searchPage.searchInput.searchButton.click();
await searchPage.searchInput.searchFor(folder);
await searchPage.dataTable.body.waitFor();

expect(await searchPage.dataTable.isItemPresent(file)).toBeFalsy();
expect(await searchPage.dataTable.isItemPresent(folder)).toBeTruthy();
});

test('[C279178] Results are returned when accessing an URL containing a search query', async ({ searchPage, personalFiles }) => {
await searchPage.acaHeader.searchButton.click();
await searchPage.searchInput.searchButton.click();
await searchPage.searchInput.checkLibraries();
await searchPage.searchInput.searchFor(site);
await searchPage.dataTable.body.waitFor();

expect(await searchPage.dataTable.isItemPresent(site)).toBeTruthy();

const url = searchPage.page.url();

await personalFiles.navigate();
await personalFiles.page.goto(url);
await searchPage.dataTable.body.waitFor();

expect(await searchPage.dataTable.isItemPresent(site)).toBeTruthy();
});
});
15 changes: 15 additions & 0 deletions e2e/playwright/search/tsconfig.e2e.adf.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"extends": "../../../tsconfig.adf.json",
"compilerOptions": {
"outDir": "../../out-tsc/e2e",
"baseUrl": "./",
"module": "commonjs",
"target": "es2017",
"types": ["jasmine", "jasminewd2", "node"],
"skipLibCheck": true,
"paths": {
"@alfresco/playwright-shared": ["../../../projects/aca-playwright-shared/src/index.ts"]
}
},
"exclude": ["node_modules"]
}
15 changes: 15 additions & 0 deletions e2e/playwright/search/tsconfig.e2e.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"extends": "../../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/e2e",
"baseUrl": "./",
"module": "commonjs",
"target": "es2017",
"types": ["jasmine", "jasminewd2", "node", "@playwright/test"],
"skipLibCheck": true,
"paths": {
"@alfresco/playwright-shared": ["../../../projects/aca-playwright-shared/src/index.ts"]
}
},
"exclude": ["node_modules"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
}

public pagination = new PaginationComponent(this.page);
body = this.getChild('.adf-datatable-body')
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');
Expand Down Expand Up @@ -182,7 +183,7 @@
* @param name of the data table element with which we want to double click
*/
async performClickFolderOrFileToOpen(name: string): Promise<void> {
await this.getCellLinkByName(name).click();

Check failure on line 186 in projects/aca-playwright-shared/src/page-objects/components/dataTable/data-table.component.ts

View workflow job for this annotation

GitHub Actions / E2e test suites: Playwright (copy-move-actions, 10)

[Copy Move Actions] › src/tests/destination-picker-dialog.test.ts:89:7 › Copy Move actions › [C263877] Contributor user can select the folder as destination

1) [Copy Move Actions] › src/tests/destination-picker-dialog.test.ts:89:7 › Copy Move actions › [C263877] Contributor user can select the folder as destination Error: locator.click: Page closed =========================== logs =========================== waiting for locator('adf-datatable .adf-cell-value span[role="link"]').filter({ hasText: 'site-1roa3' }) ============================================================ at ../../../projects/aca-playwright-shared/src/page-objects/components/dataTable/data-table.component.ts:186 184 | */ 185 | async performClickFolderOrFileToOpen(name: string): Promise<void> { > 186 | await this.getCellLinkByName(name).click(); | ^ 187 | await this.spinnerWaitForReload(); 188 | } 189 | at DataTableComponent.performClickFolderOrFileToOpen (/home/runner/work/alfresco-content-app/alfresco-content-app/projects/aca-playwright-shared/src/page-objects/components/dataTable/data-table.component.ts:186:40) at copyContentInMyLibraries (/home/runner/work/alfresco-content-app/alfresco-content-app/e2e/playwright/copy-move-actions/src/tests/destination-picker-dialog.test.ts:76:37) at /home/runner/work/alfresco-content-app/alfresco-content-app/e2e/playwright/copy-move-actions/src/tests/destination-picker-dialog.test.ts:92:11
await this.spinnerWaitForReload();
}

Expand Down Expand Up @@ -257,7 +258,7 @@
}

async getSortedColumnHeaderText(): Promise<string> {
return this.sortedColumnHeader.innerText();

Check failure on line 261 in projects/aca-playwright-shared/src/page-objects/components/dataTable/data-table.component.ts

View workflow job for this annotation

GitHub Actions / E2e test suites: Playwright (list-views, 8)

[List Views] › src/tests/personal-files.spec.ts:67:9 › Personal Files › Regular user's personal files › [C217143] has default sorted column

1) [List Views] › src/tests/personal-files.spec.ts:67:9 › Personal Files › Regular user's personal files › [C217143] has default sorted column Error: locator.innerText: Page closed =========================== logs =========================== waiting for locator('adf-datatable .adf-datatable__header--sorted-asc .adf-datatable-cell-header-content .adf-datatable-cell-value,\n .adf-datatable__header--sorted-desc .adf-datatable-cell-header-content .adf-datatable-cell-value') ============================================================ at ../../../projects/aca-playwright-shared/src/page-objects/components/dataTable/data-table.component.ts:261 259 | 260 | async getSortedColumnHeaderText(): Promise<string> { > 261 | return this.sortedColumnHeader.innerText(); | ^ 262 | } 263 | 264 | private getItemLocationEl(name: string): Locator { at DataTableComponent.getSortedColumnHeaderText (/home/runner/work/alfresco-content-app/alfresco-content-app/projects/aca-playwright-shared/src/page-objects/components/dataTable/data-table.component.ts:261:36) at /home/runner/work/alfresco-content-app/alfresco-content-app/e2e/playwright/list-views/src/tests/personal-files.spec.ts:68:44
}

private getItemLocationEl(name: string): Locator {
Expand All @@ -276,7 +277,7 @@
}

async clickItemLocation(name: string): Promise<void> {
await this.getItemLocationEl(name).click();

Check failure on line 280 in projects/aca-playwright-shared/src/page-objects/components/dataTable/data-table.component.ts

View workflow job for this annotation

GitHub Actions / E2e test suites: Playwright (list-views, 8)

[List Views] › src/tests/trash.spec.ts:115:9 › Trash › Regular user's personal files › [C280496] Location column redirect - file in folder

2) [List Views] › src/tests/trash.spec.ts:115:9 › Trash › Regular user's personal files › [C280496] Location column redirect - file in folder Error: locator.click: Target closed =========================== logs =========================== waiting for locator('adf-datatable adf-datatable-row').filter({ hasText: 'file-140gs.txt' }).locator('.aca-location-link') locator resolved to <aca-location-link class="aca-location-link adf-location-cell adf-d…>…</aca-location-link> attempting click action waiting for element to be visible, enabled and stable element is not visible - waiting... ============================================================ at ../../../projects/aca-playwright-shared/src/page-objects/components/dataTable/data-table.component.ts:280 278 | 279 | async clickItemLocation(name: string): Promise<void> { > 280 | await this.getItemLocationEl(name).click(); | ^ 281 | } 282 | 283 | async getSortingOrder(): Promise<string> { at DataTableComponent.clickItemLocation (/home/runner/work/alfresco-content-app/alfresco-content-app/projects/aca-playwright-shared/src/page-objects/components/dataTable/data-table.component.ts:280:40) at /home/runner/work/alfresco-content-app/alfresco-content-app/e2e/playwright/list-views/src/tests/trash.spec.ts:116:33
}

async getSortingOrder(): Promise<string> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,18 @@ import { timeouts } from '../../../utils';

export class SearchInputComponent extends BaseComponent {
private static rootElement = 'aca-page-layout';
public searchButton = this.getChild('aca-search-input .app-search-button');
public searchOptionsArea = this.page.locator('mat-checkbox');
public searchInput = this.getChild('input[id="app-control-input"]');
public searchButton = this.getChild('.app-search-button');
public searchButtonWindow = this.page.locator('#app-search-button');
public searchInputWindow = this.page.locator('.app-search-control');
public searchInputWindowInput = this.page.locator('.app-search-control input');
public searchOptions = this.page.locator('#search-options');
public searchFilesOption = this.searchOptionsArea.getByText(' Files ');
public searchLibrariesOption = this.searchOptionsArea.getByText(' Libraries ');
public searchFoldersOption = this.searchOptionsArea.getByText(' Folders ');


getIconByName = (name: string): Locator => this.getChild('.mat-icon', { hasText: name });

/**
Expand All @@ -48,4 +59,71 @@ export class SearchInputComponent extends BaseComponent {
await this.getCellLinkByName(name).dblclick();
await this.spinnerWaitForReload();
}

async clickLibrariesOption() {
await this.searchLibrariesOption.click();
}

async clickFilesOption() {
await this.searchFilesOption.click();
}

async clickFoldersOption() {
await this.searchFoldersOption.click();
}

async isFoldersOptionChecked() {
const optClass = await this.searchFoldersOption.getAttribute('class');
return optClass.includes('mat-checkbox-checked');
}

async isFilesOptionChecked() {
const optClass = await this.searchFilesOption.getAttribute('class');
return optClass.includes('mat-checkbox-checked');
}

async isLibrariesOptionChecked() {
const optClass = await this.searchLibrariesOption.getAttribute('class');
return optClass.includes('mat-checkbox-checked');
}

async clearOptions() {
if (await this.isFilesOptionChecked()) {
await this.clickFilesOption();
}
if (await this.isFoldersOptionChecked()) {
await this.clickFoldersOption();
}
if (await this.isLibrariesOptionChecked()) {
await this.clickLibrariesOption();
}
}

async checkOnlyFolders() {
await this.clearOptions();
await this.clickFoldersOption();
}

async checkOnlyFiles() {
await this.clearOptions();
await this.clickFilesOption();
}

async checkLibraries() {
await this.clearOptions();
await this.clickLibrariesOption();
}

async checkFilesAndFolders() {
await this.clearOptions();
await this.clickFilesOption();
await this.clickFoldersOption();
}

async searchFor(text: string) {
await this.searchInputWindow.click();
await this.searchInputWindowInput.clear();
await this.searchInputWindow.type(text);
await this.searchButtonWindow.click();
}
}
Loading