Skip to content

Commit

Permalink
Changing Playwright locators so the suite can wait for them until the…
Browse files Browse the repository at this point in the history
…y are visible.
  • Loading branch information
victoralfaro-dotcms committed Dec 5, 2024
1 parent cc77a5c commit 1f5c2be
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 41 deletions.
4 changes: 3 additions & 1 deletion e2e/dotcms-e2e-node/frontend/.env
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ CI=false
DEV=false
BASE_URL=http://localhost:8080
HEADLESS=false
RETRIES=0
RETRIES=1
WORKERS=1
REUSE_SERVER=false
INCLUDE_HTML=true
TIMEOUT=30000

USERNAME=[email protected]
PASSWORD=admin
Expand Down
4 changes: 2 additions & 2 deletions e2e/dotcms-e2e-node/frontend/.env.ci
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
CI=true
HEADLESS=true
RETRIES=1
RETRIES=3
INCLUDE_HTML=false
REUSE_SERVER=true
REUSE_SERVER=true
4 changes: 2 additions & 2 deletions e2e/dotcms-e2e-node/frontend/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ export default defineConfig({
/* Retry on CI only */
retries: parseInt(process.env.RETRIES),
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
workers: parseInt(process.env.WORKERS),
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
timeout: 30000,
timeout: parseInt(process.env.TIMEOUT),

reporter,
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {dotCMSUtils} from '../../utils/dotCMSUtils';
import {dotCMSUtils, waitForVisibleAndCallback} from '../../utils/dotCMSUtils';
import {ContentUtils} from '../../utils/contentUtils';
import {addContent, iFramesLocators, richText} from '../../locators/globalLocators';
import {
Expand Down Expand Up @@ -30,6 +30,9 @@ test.beforeEach('Navigate to content portlet', async ({page}) => {
await cmsUtils.navigate(menuLocators.EXPAND, groupsLocators.CONTENT, toolsLocators.SEARCH_ALL);

// Validate the portlet title
const breadcrumbLocator = page.locator('p-breadcrumb');
await waitForVisibleAndCallback(breadcrumbLocator, () => expect(breadcrumbLocator).toContainText('Search All'));

await expect(page.locator('p-breadcrumb')).toContainText('Search All');
});

Expand Down Expand Up @@ -151,16 +154,20 @@ test("Validate the clear button in the search filter", async ({page}) => {
const iframe = page.frameLocator(iFramesLocators.main_iframe);

//expand the search filter
await iframe.getByRole('link', {name: 'Advanced'}).click();
const advancedLinkLocator = iframe.getByRole('link', {name: 'Advanced'});
await waitForVisibleAndCallback(advancedLinkLocator, () => advancedLinkLocator.click());

// Select the workflow in the search filter
await iframe.locator('#widget_scheme_id [data-dojo-attach-point="_buttonNode"]').click();
await iframe.getByRole('option', {name: 'System Workflow'}).click();
//TODO remove this
await page.waitForTimeout(1000);

// Select the step in the search filter
await iframe.locator('div[id=\'widget_step_id\'] div[data-dojo-attach-point=\'_buttonNode\']').click();
await iframe.getByRole('option', {name: 'New'}).click();
const widgetStepIdLocator = iframe.locator('div[id=\'widget_step_id\'] div[data-dojo-attach-point=\'_buttonNode\']');
await waitForVisibleAndCallback(widgetStepIdLocator, () => widgetStepIdLocator.click());
const newOption = iframe.getByRole('option', {name: 'New'});
await waitForVisibleAndCallback(newOption, () => newOption.click());

// Select the Show in the search filter
await iframe.locator('#widget_showingSelect [data-dojo-attach-point="_buttonNode"]').click();
Expand All @@ -183,7 +190,8 @@ test('Validate the hide button collapse the filter', async ({page}) => {
const iframe = page.frameLocator(iFramesLocators.main_iframe);

await expect(iframe.getByRole('button', {name: 'Search'})).toBeVisible();
await iframe.getByRole('link', {name: 'Advanced'}).click();
let advancedLinkLocator = iframe.getByRole('link', {name: 'Advanced'});
await waitForVisibleAndCallback(advancedLinkLocator, () => advancedLinkLocator.click());

await page.waitForTimeout(1000);
await expect(iframe.getByRole('link', {name: 'Advanced'})).not.toBeVisible();
Expand All @@ -195,5 +203,3 @@ test('Validate the hide button collapse the filter', async ({page}) => {
// Validate the filter has been collapsed
await expect(iframe.getByRole('link', {name: 'Advanced'})).toBeVisible();
});


8 changes: 6 additions & 2 deletions e2e/dotcms-e2e-node/frontend/tests/login/translations.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {expect, test} from '@playwright/test';
import {assert} from 'console';
import {waitForVisibleAndCallback} from "../../utils/dotCMSUtils";

const languages = [
{language: 'español (España)', translation: '¡Bienvenido!'},
Expand All @@ -20,8 +21,11 @@ languages.forEach(list => {
const {language, translation} = list;

await page.goto('/dotAdmin');
await page.getByLabel('dropdown trigger').click();
await page.getByText(language).click();
const dropdownTriggerLocator = page.getByLabel('dropdown trigger');
await waitForVisibleAndCallback(dropdownTriggerLocator, () => dropdownTriggerLocator.click());

const pageByTextLocator = page.getByText(language);
await waitForVisibleAndCallback(pageByTextLocator, () => pageByTextLocator.click());

// Assertion of the translation
assert(await expect(page.getByTestId('header')).toContainText(translation));
Expand Down
28 changes: 19 additions & 9 deletions e2e/dotcms-e2e-node/frontend/utils/contentUtils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Page, expect, FrameLocator} from '@playwright/test';
import { iFramesLocators, richText } from '../locators/globalLocators';

import { waitForVisibleAndCallback} from './dotCMSUtils';

export class ContentUtils {
page: Page;
Expand All @@ -17,7 +17,9 @@ export class ContentUtils {
*/
async fillRichTextForm(page: Page, title: string, body: string, action: string) {
const dotIframe = page.frameLocator(iFramesLocators.dot_iframe);
await expect.soft( page.getByRole('heading')).toContainText(richText.label);

const headingLocator = page.getByRole('heading');
await waitForVisibleAndCallback(headingLocator, () => expect.soft(headingLocator).toContainText(richText.label));

//Fill title
await dotIframe.locator('#title').fill(title);
Expand All @@ -29,11 +31,11 @@ export class ContentUtils {
await dotIframe.getByText(action).click();
//Wait for the content to be saved


await expect(dotIframe.getByText('Content saved')).toBeVisible({ timeout: 9000 });
await expect(dotIframe.getByText('Content saved')).toBeHidden();
//Click on close
await page.getByTestId('close-button').getByRole('button').click();
const closeBtnLocator = page.getByTestId('close-button').getByRole('button');
await waitForVisibleAndCallback(closeBtnLocator, () => closeBtnLocator.click());
}

/**
Expand All @@ -44,15 +46,22 @@ export class ContentUtils {
*/
async addNewContentAction(page: Page, typeLocator: string, typeString: string) {
const iframe = page.frameLocator(iFramesLocators.main_iframe);
await expect(iframe.locator('#structure_inode')).toBeVisible();
const structureINodeLocator = iframe.locator('#structure_inode');
await waitForVisibleAndCallback(structureINodeLocator, () => expect(structureINodeLocator).toBeVisible());
//TODO remove this
await page.waitForTimeout(1000);
await iframe.locator('#widget_structure_inode div').first().click();
const structureINodeDivLocator = iframe.locator('#widget_structure_inode div').first();
await waitForVisibleAndCallback(structureINodeDivLocator, () => structureINodeDivLocator.click());
//TODO remove this
await page.waitForTimeout(1000);
await iframe.getByText(typeLocator).click();
const typeLocatorByTextLocator = iframe.getByText(typeLocator);
await waitForVisibleAndCallback(typeLocatorByTextLocator, () => typeLocatorByTextLocator.click());

await iframe.locator('#dijit_form_DropDownButton_0').click();
await expect(iframe.getByLabel('actionPrimaryMenu')).toBeVisible();
await iframe.getByLabel('▼').getByText('Add New Content').click();
await expect(page.getByRole('heading')).toHaveText(typeString);
const headingLocator = page.getByRole('heading');
await waitForVisibleAndCallback(headingLocator, () => expect(headingLocator).toHaveText(typeString));
};

/**
Expand All @@ -74,7 +83,8 @@ export class ContentUtils {
* @param iframe
*/
async showQuery(iframe : FrameLocator) {
await iframe.getByRole('button', { name: 'createOptions' }).click();
const createOptionsBtnLocator = iframe.getByRole('button', { name: 'createOptions' });
await waitForVisibleAndCallback(createOptionsBtnLocator, () => createOptionsBtnLocator.click());

//Validate the search button has a sub-menu
await expect (iframe.getByLabel('Search ▼').getByText('Search')).toBeVisible();
Expand Down
23 changes: 19 additions & 4 deletions e2e/dotcms-e2e-node/frontend/utils/dotCMSUtils.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
import { Page, expect, Locator } from '@playwright/test';
import { loginLocators } from '../locators/globalLocators';

export const waitFor = async (locator: Locator, state: "attached" | "detached" | "visible" | "hidden"): Promise<void> => {
await locator.waitFor({state: state});
}

export const waitForAndCallback = async (locator: Locator, state: "attached" | "detached" | "visible" | "hidden", callback: () => Promise<void>): Promise<void> => {
await waitFor(locator, state);
await callback();
};

export const waitForVisibleAndCallback = async (locator: Locator, callback: () => Promise<void>): Promise<void> => {
await waitForAndCallback(locator, 'visible', callback);
};

export class dotCMSUtils {
page: Page;

/**
* Login to dotCMS
* @param page
Expand All @@ -14,9 +27,11 @@ export class dotCMSUtils {
await page.goto('/dotAdmin');
await page.waitForLoadState()
await page.fill(loginLocators.userNameInput, username);
await page.fill(loginLocators.passwordInput, password);
await page.getByTestId(loginLocators.loginBtn).click();
await expect(page.getByRole('link', { name: 'Getting Started' })).toBeVisible();
await page.fill(loginLocators.passwordInput, password);
const loginBtnLocator = page.getByTestId(loginLocators.loginBtn);
await waitForVisibleAndCallback(loginBtnLocator, () => loginBtnLocator.click());
const gettingStartedLocator = page.getByRole('link', { name: 'Getting Started' });
await waitForVisibleAndCallback(gettingStartedLocator, () => expect(gettingStartedLocator).toBeVisible());
}

/**
Expand Down
15 changes: 1 addition & 14 deletions e2e/dotcms-e2e-node/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@
<skip.npm.install>false</skip.npm.install>
<yarn.install.cmd>install --frozen-lockfile</yarn.install.cmd>
<playwright.add.cmd>global add playwright</playwright.add.cmd>
<playwright.install.cmd>playwright install</playwright.install.cmd>
<playwright.install.deps.cmd>playwright install-deps</playwright.install.deps.cmd>
<playwright.install.cmd>playwright install --with-deps</playwright.install.cmd>
<e2e.test.skip>true</e2e.test.skip>
<e2e.test.env>local</e2e.test.env>
<e2e.frontend.dir>./frontend</e2e.frontend.dir>
Expand Down Expand Up @@ -85,18 +84,6 @@
<arguments>${playwright.install.cmd}</arguments>
</configuration>
</execution>
<execution>
<id>install-playwright-deps</id>
<goals>
<goal>yarn</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<workingDirectory>${e2e.frontend.dir}</workingDirectory>
<skip>${e2e.test.skip}</skip>
<arguments>${playwright.install.deps.cmd}</arguments>
</configuration>
</execution>
<execution>
<id>run node script</id>
<goals>
Expand Down

0 comments on commit 1f5c2be

Please sign in to comment.