Skip to content

Commit

Permalink
RHIDP-744 [Test Automation] Automate RHDH theme customization - E2E
Browse files Browse the repository at this point in the history
Refactor custom theme E2E test and update uihelper functions

Signed-off-by: Gustavo Lira <guga.java@gmail.com>
  • Loading branch information
gustavolira committed Jul 4, 2024
1 parent e38c2e7 commit 76e5a2a
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ data:
headerColor1: "rgb(248, 248, 248)"
headerColor2: "rgb(248, 248, 248)"
navigationIndicatorColor: "rgb(255,95,21)"
dark:
primaryColor: '#ab75cf'
headerColor1: 'rgb(0, 0, 208)'
headerColor2: 'rgb(255, 246, 140)'
navigationIndicatorColor: 'rgb(244, 238, 169)'
backend:
auth:
keys:
Expand Down Expand Up @@ -44,6 +49,8 @@ data:
# see https://backstage.io/docs/auth/ to learn about auth providers
environment: development
providers:
guest:
dangerouslyAllowOutsideDevelopment: true
# Plugin: GitHub
github:
development:
Expand All @@ -53,8 +60,6 @@ data:
development:
clientId: ${GOOGLE_CLIENT_ID}
clientSecret: ${GOOGLE_CLIENT_SECRET}
guest:
dangerouslyAllowOutsideDevelopment: true
proxy:
skipInvalidProxies: true
Expand Down Expand Up @@ -99,7 +104,6 @@ data:
rules:
- allow: [User, Group]
dynatrace:
baseUrl: temp
argocd:
Expand Down
50 changes: 0 additions & 50 deletions e2e-tests/playwright/e2e/custom-theme.spec.ts

This file was deleted.

52 changes: 52 additions & 0 deletions e2e-tests/playwright/e2e/plugins/custom-theme/custom-theme.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { test, Page, TestInfo } from '@playwright/test';
import { Common, setupBrowser } from '../../../utils/Common';
import { ThemeVerifier } from './theme-verifier';

let page: Page;

test.describe('CustomTheme should be applied', () => {
let common: Common;
let themeVerifier: ThemeVerifier;

test.beforeAll(async ({ browser }, testInfo) => {
page = (await setupBrowser(browser, testInfo)).page;
common = new Common(page);
themeVerifier = new ThemeVerifier(page);

await common.loginAsGuest();
});

// eslint-disable-next-line no-empty-pattern
test('Verify that theme light colors are applied and make screenshots', async ({}, testInfo: TestInfo) => {
await themeVerifier
.setTheme('Light')
.verifyHeaderGradient(
'none, linear-gradient(90deg, rgb(248, 248, 248), rgb(248, 248, 248))',
)
.verifyBorderLeftColor('rgb(255, 95, 21)')
.takeScreenshotAndAttach(
'screenshots/custom-theme-light-inspection.png',
testInfo,
'custom-theme-light-inspection',
)
// .verifyPrimaryColors('rgb(255, 95, 21)') //TODO: comment out when the primary color issue is fixed (RHIDP-3107)
.execute();
});

// eslint-disable-next-line no-empty-pattern
test('Verify that theme dark colors are applied and make screenshots', async ({}, testInfo: TestInfo) => {
await themeVerifier
.setTheme('Dark')
.verifyHeaderGradient(
'none, linear-gradient(90deg, rgb(0, 0, 208), rgb(255, 246, 140))',
)
.verifyBorderLeftColor('rgb(244, 238, 169)')
.takeScreenshotAndAttach(
'screenshots/custom-theme-dark-inspection.png',
testInfo,
'custom-theme-dark-inspection',
)
// .verifyPrimaryColors('#ab75cf') //TODO: comment out when the primary color issue is fixed (RHIDP-3107)
.execute();
});
});
83 changes: 83 additions & 0 deletions e2e-tests/playwright/e2e/plugins/custom-theme/theme-verifier.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { Page, expect, TestInfo } from '@playwright/test';
import { UIhelper } from '../../../utils/UIhelper';
import { UIhelperPO } from '../../../support/pageObjects/global-obj';

export class ThemeVerifier {
private readonly page: Page;
private uiHelper: UIhelper;
private readonly tasks: Array<() => Promise<void>>;

constructor(page: Page) {
this.page = page;
this.uiHelper = new UIhelper(page);
this.tasks = [];
}

setTheme(theme: 'Light' | 'Dark'): this {
this.tasks.push(async () => {
await this.uiHelper.openSidebar('Settings');
await this.uiHelper.clickBtnByTitleIfNotPressed(`Select theme ${theme}`);
});
return this;
}

verifyHeaderGradient(expectedGradient: string): this {
this.tasks.push(async () => {
const header = await this.page.locator('main header');
await expect(header).toHaveCSS('background-image', expectedGradient);
});
return this;
}

verifyBorderLeftColor(expectedColor: string): this {
this.tasks.push(async () => {
const locator = await this.page.locator("a[aria-label='Settings']");
await expect(locator).toHaveCSS(
'border-left',
`3px solid ${expectedColor}`,
);
});
return this;
}

verifyPrimaryColors(colorPrimary: string): this {
this.tasks.push(async () => {
await this.uiHelper.checkCssColor(
this.page,
UIhelperPO.MuiTypographyColorPrimary,
colorPrimary,
);
await this.uiHelper.checkCssColor(
this.page,
UIhelperPO.MuiSwitchColorPrimary,
colorPrimary,
);
await this.uiHelper.openSidebar('Catalog');
await this.uiHelper.checkCssColor(
this.page,
UIhelperPO.MuiButtonTextPrimary,
colorPrimary,
);
await this.uiHelper.openSidebar('Settings');
});
return this;
}

takeScreenshotAndAttach(
screenshotPath: string,
testInfo: TestInfo,
description: string,
): this {
this.tasks.push(async () => {
await this.page.screenshot({ path: screenshotPath, fullPage: true });
await testInfo.attach(description, { path: screenshotPath });
});
return this;
}

async execute(): Promise<void> {
for (const task of this.tasks) {
await task();
}
}
}
4 changes: 4 additions & 0 deletions e2e-tests/playwright/support/pageObjects/global-obj.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ export const waitsObjs = {

export const UIhelperPO = {
MuiButtonLabel: 'span[class^="MuiButton-label"]',
MuiToggleButtonLabel: 'span[class^="MuiToggleButton-label"]',
MuiBoxLabel: 'div[class*="MuiBox-root"] label',
MuiTableHead: 'th[class*="MuiTableCell-root"]',
MuiTableCell: 'td[class*="MuiTableCell-root"]',
MuiTableRow: 'tr[class*="MuiTableRow-root"]',
MuiTypographyColorPrimary: '.MuiTypography-colorPrimary',
MuiSwitchColorPrimary: '.MuiSwitch-colorPrimary',
MuiButtonTextPrimary: '.MuiButton-textPrimary',
MuiCard: cardHeading =>
`//div[contains(@class,'MuiCardHeader-root') and descendant::*[text()='${cardHeading}']]/..`,
MuiTable: 'table.MuiTable-root',
Expand Down
36 changes: 35 additions & 1 deletion e2e-tests/playwright/utils/UIhelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { UIhelperPO } from '../support/pageObjects/global-obj';

export class UIhelper {
private page: Page;
private selectors: { [key: string]: string };

constructor(page: Page) {
this.page = page;
Expand Down Expand Up @@ -46,6 +45,15 @@ export class UIhelper {
return button;
}

async clickBtnByTitleIfNotPressed(title: string) {
const button = this.page.locator(`button[title="${title}"]`);
const isPressed = await button.getAttribute('aria-pressed');

if (isPressed === 'false') {
await button.click();
}
}

async verifyDivHasText(divText: string) {
await expect(
this.page.locator(`div`).filter({ hasText: divText }),
Expand Down Expand Up @@ -247,4 +255,30 @@ export class UIhelper {
const rowCount = await this.page.locator(rowSelector).count();
expect(rowCount).toBeGreaterThan(0);
}

// Function to convert hexadecimal to RGB or return RGB if it's already in RGB
toRgb(color: string): string {
if (color.startsWith('rgb')) {
return color;
}

const bigint = parseInt(color.slice(1), 16);
const r = (bigint >> 16) & 255;
const g = (bigint >> 8) & 255;
const b = bigint & 255;
return `rgb(${r}, ${g}, ${b})`;
}

async checkCssColor(page: Page, selector: string, expectedColor: string) {
const elements = await page.locator(selector);
const count = await elements.count();
const expectedRgbColor = this.toRgb(expectedColor);

for (let i = 0; i < count; i++) {
const color = await elements
.nth(i)
.evaluate(el => window.getComputedStyle(el).color);
expect(color).toBe(expectedRgbColor);
}
}
}

0 comments on commit 76e5a2a

Please sign in to comment.