Skip to content

Commit

Permalink
Issue 31056 automation ace testing accesability test (#31124)
Browse files Browse the repository at this point in the history
### Proposed Changes
- Add more test cases for content search
- Accessibility Testing

### Checklist
- [x] Tests
  • Loading branch information
bryanboza authored Jan 14, 2025
1 parent 5f8283a commit a935ea5
Show file tree
Hide file tree
Showing 8 changed files with 2,010 additions and 263 deletions.
1,634 changes: 1,617 additions & 17 deletions e2e/dotcms-e2e-node/frontend/package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions e2e/dotcms-e2e-node/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
"main": "index.js",
"license": "MIT",
"devDependencies": {
"@axe-core/playwright": "^4.10.1",
"@eslint/js": "^9.17.0",
"@playwright/test": "^1.48.2",
"@types/node": "^22.5.4",
"@typescript-eslint/eslint-plugin": "^8.19.0",
"axe-html-reporter": "^2.2.11",
"dotenv": "^16.4.5",
"eslint": "^9.17.0",
"eslint-config-prettier": "^9.1.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ export const contentProperties = {
deleteWfAction: "Delete"
}

/**
* Content to create a file asset
*/
export const fileAssetContent = {
title: "File Asset title",
body: "This is a sample file asset content",
Expand All @@ -31,6 +34,9 @@ export const fileAssetContent = {
host:"default"
}

/**
* Content to create a page asset
*/
export const pageAssetContent = {
title: "PageAsset1",
host: "default",
Expand All @@ -41,6 +47,9 @@ export const pageAssetContent = {
cacheTTL: 0,
}

export const accessibilityReport = {
name: 'Content Search'
}



Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@ import {
} from '../../locators/navigation/menuLocators';
import {ContentUtils} from "../../utils/contentUtils";
import {iFramesLocators, contentGeneric, fileAsset, pageAsset} from "../../locators/globalLocators";
import {genericContent1, contentProperties, fileAssetContent, pageAssetContent} from "./contentData";
import {
genericContent1,
contentProperties,
fileAssetContent,
pageAssetContent,
accessibilityReport
} from "./contentData";
import {assert} from "console";


/**
* Test to navigate to the content portlet and login to the dotCMS instance
* @param page
Expand Down Expand Up @@ -44,11 +49,34 @@ test('Add a new Generic content', async ({page}) => {

// Adding new rich text content
await contentUtils.addNewContentAction(page, contentGeneric.locator, contentGeneric.label);
await contentUtils.fillRichTextForm(page, genericContent1.title, genericContent1.body, contentProperties.publishWfAction);
await contentUtils.fillRichTextForm({
page,
title: genericContent1.title,
body: genericContent1.body,
action: contentProperties.publishWfAction,
});
await contentUtils.workflowExecutionValidationAndClose(page, 'Content saved');

await waitForVisibleAndCallback(iframe.locator('#results_table tbody tr').first(), async () => {});
await contentUtils.validateContentExist(page, genericContent1.title).then(assert);
});

/**
* Test to edit an existing piece of content and make sure you can discard the changes
*/
test('Edit a generic content and discard changes', async ({page}) => {
const contentUtils = new ContentUtils(page);
const iframe = page.frameLocator(iFramesLocators.main_iframe);

await contentUtils.selectTypeOnFilter(page, contentGeneric.locator);
await contentUtils.editContent({
page,
title: genericContent1.title,
newTitle: genericContent1.newTitle,
newBody: "genericContent1",
});
await waitForVisibleAndCallback(page.getByTestId ('close-button'), () => page.getByTestId('close-button').click());
await waitForVisibleAndCallback(page.getByRole('button', { name: 'Close' }), () =>page.getByRole('button', { name: 'Close' }).click());
await waitForVisibleAndCallback(iframe.locator('#results_table tbody tr').first(), async () => {});
await contentUtils.validateContentExist(page, genericContent1.title).then(assert);
});

Expand All @@ -59,9 +87,14 @@ test('Edit a generic content', async ({page}) => {
const contentUtils = new ContentUtils(page);
const iframe = page.frameLocator(iFramesLocators.main_iframe);

// Edit the content
await contentUtils.selectTypeOnFilter(page, contentGeneric.locator);
await contentUtils.editContent(page, genericContent1.title, genericContent1.newTitle, genericContent1.newBody, contentProperties.publishWfAction);
await contentUtils.editContent({
page,
title: genericContent1.title,
newTitle: genericContent1.newTitle,
newBody: genericContent1.newBody,
action: contentProperties.publishWfAction,
});
await waitForVisibleAndCallback(iframe.locator('#results_table tbody tr').first(), async () => {});
await contentUtils.validateContentExist(page, genericContent1.newTitle).then(assert);
});
Expand All @@ -83,7 +116,12 @@ test('Validate required on text fields', async ({page}) => {
const iframe = page.frameLocator(iFramesLocators.dot_iframe);

await contentUtils.addNewContentAction(page, contentGeneric.locator, contentGeneric.label);
await contentUtils.fillRichTextForm(page, '', genericContent1.body, contentProperties.publishWfAction);
await contentUtils.fillRichTextForm({
page,
title: '',
body: genericContent1.body,
action: contentProperties.publishWfAction,
});
await expect(iframe.getByText('Error x')).toBeVisible();
await expect(iframe.getByText('The field Title is required.')).toBeVisible();
});
Expand Down Expand Up @@ -346,6 +384,30 @@ test('Add a new page', async ({page}) => {
await expect(page.locator('ol')).toContainText('Pages' + pageAssetContent.title);
});

/**
* Test to validate the URL is unique on pages
*/
test('Validate URL is unique on pages', async ({page}) => {
const contentUtils = new ContentUtils(page);

await contentUtils.addNewContentAction(page, pageAsset.locator, pageAsset.label);
await contentUtils.fillPageAssetForm({
page: page,
title: pageAssetContent.title,
host: pageAssetContent.host,
template: pageAssetContent.template,
friendlyName: pageAssetContent.friendlyName,
showOnMenu: pageAssetContent.showOnMenu,
sortOrder: pageAssetContent.sortOrder,
cacheTTL: pageAssetContent.cacheTTL,
action: contentProperties.publishWfAction,
});
await page.frameLocator('dot-iframe-dialog iframe[name="detailFrame"]').getByText('Another Page with the same').click();

const iframe = page.frameLocator(iFramesLocators.dot_iframe);
await expect(iframe.getByText('Another Page with the same')).toBeVisible();
});

/**
* Test to validate the required fields on the page form
*/
Expand Down Expand Up @@ -406,4 +468,15 @@ test('Validate you are able to delete pages', async ({page}) => {
const contentUtils = new ContentUtils(page);
await contentUtils.selectTypeOnFilter(page, pageAsset.locator);
await contentUtils.deleteContent(page, pageAssetContent.title);
});
});

/**
* Test to do a regression according the axe-standards on accessibility
*/
/**
test('accessibility test', async ({page}) => {
const accessibility = new accessibilityUtils(page);
const accessibilityScanResults = await accessibility.generateReport(page, accessibilityReport.name);
expect(accessibilityScanResults.violations).toEqual([]); // 5
});
*/
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ test("Search filter", async ({ page }) => {
contentGeneric.locator,
contentGeneric.label,
);
await contentUtils.fillRichTextForm(
await contentUtils.fillRichTextForm({
page,
genericContent1.title,
genericContent1.body,
contentProperties.publishWfAction,
);
title: genericContent1.title,
body: genericContent1.body,
action: contentProperties.publishWfAction,
});
await contentUtils.workflowExecutionValidationAndClose(page, "Content saved");

// Validate the content has been created
Expand Down
30 changes: 30 additions & 0 deletions e2e/dotcms-e2e-node/frontend/utils/accessibilityUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import * as fs from 'node:fs';
import { Page } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
import { createHtmlReport } from 'axe-html-reporter';

export class accessibilityUtils {
page: Page;

constructor(page: Page) {
this.page = page;
}

async generateReport(page: Page, description: string) {
const accessibilityScanResults = await new AxeBuilder({page}).analyze();
const reportHTML = createHtmlReport({
results: accessibilityScanResults,
options: {
projectKey: description,
},
});

if (!fs.existsSync('build/reports')) {
fs.mkdirSync('build/reports', {
recursive: true,
});
}
fs.writeFileSync('build/reports/accessibility-report.html', reportHTML);
return accessibilityScanResults;
}
}
73 changes: 44 additions & 29 deletions e2e/dotcms-e2e-node/frontend/utils/contentUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,31 @@ export class ContentUtils {

/**
* Fill the rich text form
* @param page
* @param title
* @param body
* @param action
* @param params
*/
async fillRichTextForm(page: Page, title: string, body: string, action: string) {
async fillRichTextForm(params: RichTextFormParams) {
const {page, title, body, action, newBody, newTitle} = params;
const dotIframe = page.frameLocator(iFramesLocators.dot_iframe);

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

//Fill title
await dotIframe.locator('#title').fill(title);
//Fill body
await dotIframe.locator('#block-editor-body div').nth(1).fill(body);
//Click on action
await dotIframe.getByText(action).first().click();
await waitForVisibleAndCallback(page.getByRole('heading'), () =>
expect.soft(page.getByRole('heading')).toContainText(contentGeneric.label)
);

if (newTitle) {
await dotIframe.locator('#title').clear();
await dotIframe.locator('#title').fill(newTitle);
}
if (newBody) {
await dotIframe.locator('#block-editor-body div').nth(1).clear()
await dotIframe.locator('#block-editor-body div').nth(1).fill(newBody);
}
if (!newTitle && !newBody) {
await dotIframe.locator('#title').fill(title);
await dotIframe.locator('#block-editor-body div').nth(1).fill(body);
}
if (action) {
await dotIframe.getByText(action).first().click();
}
}

/**
Expand All @@ -54,7 +62,7 @@ export class ContentUtils {
await editFrame.getByRole('button', {name: 'Save'}).click();
} else {
await waitForVisibleAndCallback(page.getByRole('heading'), async () => {
expect.soft(page.getByRole('heading')).toContainText(fileAsset.label);
await expect.soft(page.getByRole('heading')).toContainText(fileAsset.label);
});
await dotIframe.locator('#HostSelector-hostFolderSelect').fill(host);
await dotIframe.getByRole('button', {name: ' Create New File'}).click();
Expand Down Expand Up @@ -128,9 +136,11 @@ export class ContentUtils {

const structureINodeDivLocator = iframe.locator('#widget_structure_inode div').first();
await waitForVisibleAndCallback(structureINodeDivLocator, () => structureINodeDivLocator.click());
const typeLocatorByTextLocator = iframe.getByText(typeLocator);
await waitForVisibleAndCallback(typeLocatorByTextLocator, () => typeLocatorByTextLocator.click());
await page.waitForLoadState();

await waitForVisibleAndCallback(iframe.getByLabel('structure_inode_popup'), async () => {});

const typeLocatorByText = iframe.getByText(typeLocator);
await waitForVisibleAndCallback(typeLocatorByText, () => typeLocatorByText.click());
}

/**
Expand Down Expand Up @@ -205,22 +215,20 @@ export class ContentUtils {

/**
* Edit content on the content portlet
* @param page
* @param title
* @param newTitle
* @param newBody
* @param action
* @param params
*/
async editContent(page: Page, title: string, newTitle: string, newBody: string, action: string) {
async editContent(params: RichTextFormParams) {
const {page, title, action} = params;
const contentElement = await this.getContentElement(page, title);
if (contentElement) {
await contentElement.click();
} else {
if (!contentElement) {
console.log('Content not found');
return;
}
await this.fillRichTextForm(page, newTitle, newBody, action);
await this.workflowExecutionValidationAndClose(page, 'Content saved');
await contentElement.click();
await this.fillRichTextForm(params);
if(action) {
await this.workflowExecutionValidationAndClose(page, 'Content saved');
}
}

/**
Expand Down Expand Up @@ -362,6 +370,13 @@ interface BaseFormParams {
action?: string;
}


interface RichTextFormParams extends BaseFormParams {
body?: string,
action?: string
newTitle?: string,
newBody?: string,
}
/**
* Parameter to fill the file asset form params
*/
Expand Down
Loading

0 comments on commit a935ea5

Please sign in to comment.