Skip to content

Commit 0fe3914

Browse files
Pedro-S-AbreuPedro Abreu
andauthored
MTV-3247 - Add Tips and Tricks functionality testing (#2080)
* Add Tips and Tricks functionality testing Resolves: MTV-3247 Signed-off-by: Pedro Abreu <[email protected]> * Add Tips and Tricks functionality testing part 2 Resolves: MTV-3247 Signed-off-by: Pedro Abreu <[email protected]> * Update ESLint configuration to include testing directories in TypeScript settings Resolves: MTV-3247 Signed-off-by: Pedro Abreu <[email protected]> * Add data-testid to topic card and update button name formatting Resolves: MTV-3247 Signed-off-by: Pedro Abreu <[email protected]> * Refactor OverviewPage Resolves: MTV-3247 Signed-off-by: Pedro Abreu <[email protected]> * Remove unnecessary timeout in OverviewPage i Resolves: MTV-3247 Signed-off-by: Pedro Abreu <[email protected]> * Simplify Tips and Tricks test Resolves: MTV-3247 Signed-off-by: Pedro Abreu <[email protected]> * Refactor Overview Page test setup Resolves: MTV-3247 Signed-off-by: Pedro Abreu <[email protected]> * Update ESLint configuration to simplify testing directory rules Resolves: None Signed-off-by: Pedro Abreu <[email protected]> * Refactor NavigationHelper Resolves: MTV-3247 Signed-off-by: Pedro Abreu <[email protected]> * Add unique key to Alert component in PlanPreserveIPWarningsAlerts Resolves: MTV-3247 Signed-off-by: Pedro Abreu <[email protected]> * fix conflicts Resolves: none Signed-off-by: Pedro Abreu <[email protected]> * Fix old tests Resolves: None Signed-off-by: Pedro Abreu <[email protected]> --------- Signed-off-by: Pedro Abreu <[email protected]> Co-authored-by: Pedro Abreu <[email protected]>
1 parent f5c4f44 commit 0fe3914

File tree

10 files changed

+262
-5
lines changed

10 files changed

+262
-5
lines changed

src/onlineHelp/learningExperience/LearningTopicsCards.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const LearningTopicsCards: FC<LearningTopicsCardsProps> = ({ onSelect, topics })
2020
<FlexItem key={learningExperienceTopic.id}>
2121
<Card
2222
id={learningExperienceTopic.id}
23+
data-testid="topic-card"
2324
isClickable
2425
onClick={() => {
2526
trackEvent(TELEMETRY_EVENTS.TIPS_AND_TRICKS_VISITED, {

src/plans/details/components/PlanPageHeader/components/PlanPreserveIPWarningsAlerts.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const PlanPreserveIPWarningsAlerts: FC<PlanPreserveIPWarningsAlertsProps> = ({
3333
<>
3434
{conditions?.map((condition, index) => (
3535
<Alert
36-
key={condition?.type ?? `condition-${index}`}
36+
key={`${condition?.type}-${condition?.message}`}
3737
title={t('The plan migration might not work as expected')}
3838
variant={AlertVariant.warning}
3939
>

src/providers/create/components/ProvidersCreatePageHeader.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const ProvidersCreatePageHeader: FC<ProvidersCreatePageHeaderProps> = ({ apiErro
1414
return (
1515
<>
1616
<SectionHeading
17+
testId="create-provider-heading"
1718
text={
1819
<>
1920
{t('Create provider')}

src/providers/details/tabs/Credentials/components/CertificateEditSection.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ const CertificateEditSection: FC<CertificateEditSectionProps> = ({
4444
fieldId="insecureSkipVerify"
4545
>
4646
<Switch
47+
data-testid="skip-certificate-validation-switch"
4748
className="forklift-section-secret-edit-switch"
4849
id="insecureSkipVerify"
4950
name="insecureSkipVerify"
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { expect, test } from '@playwright/test';
2+
3+
import { TIPS_AND_TRICKS_TOPICS } from '../../fixtures/overview-page-topics';
4+
import { OverviewPage } from '../../page-objects/OverviewPage';
5+
6+
test.describe(
7+
'Overview Page - Tips and Tricks',
8+
{
9+
tag: '@downstream',
10+
},
11+
() => {
12+
test('should verify complete Tips and tricks functionality with all expandable content', async ({
13+
page,
14+
}) => {
15+
const overviewPage = new OverviewPage(page);
16+
17+
// SETUP: Navigate to Overview page
18+
await overviewPage.navigateDirectly();
19+
20+
// STEP 1: Navigate to Tips and Tricks and Verify All Topics Present
21+
const { drawerTitle, closeDrawerButton } = await overviewPage.openTipsAndTricksDrawer();
22+
await overviewPage.verifyTopicCards(TIPS_AND_TRICKS_TOPICS);
23+
await overviewPage.verifyPicklist(TIPS_AND_TRICKS_TOPICS);
24+
25+
// STEP 2: Test All Topics and Expandable Sections
26+
for (let i = 0; i < TIPS_AND_TRICKS_TOPICS.length; i += 1) {
27+
const topic = TIPS_AND_TRICKS_TOPICS[i];
28+
29+
// Select topic (first via card, remaining via dropdown)
30+
if (i === 0) {
31+
await overviewPage.selectTopicByCard(topic);
32+
} else {
33+
const previousTopic = TIPS_AND_TRICKS_TOPICS[i - 1];
34+
await overviewPage.navigateToNextTopic(previousTopic.name, topic.name);
35+
await overviewPage.verifyTopicHeading(topic.name);
36+
}
37+
38+
// Test expandable sections structure
39+
if (topic.minimumAccordions) {
40+
await overviewPage.testAccordionsStructure(topic.minimumAccordions);
41+
}
42+
}
43+
44+
// STEP 3: Verify Drawer Close Functionality
45+
await closeDrawerButton.click();
46+
await expect(drawerTitle).not.toBeVisible();
47+
});
48+
},
49+
);
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import type { TopicConfig } from '../page-objects/OverviewPage';
2+
3+
export const TIPS_AND_TRICKS_TOPICS: TopicConfig[] = [
4+
{
5+
name: 'Migrating your virtual machines',
6+
description: 'Learn the best practices for seamlessly migrating your VMs.',
7+
minimumAccordions: 9,
8+
},
9+
{
10+
name: 'Choosing the right migration type',
11+
description: 'Compare migration types to find the best fit for your needs.',
12+
minimumAccordions: 2,
13+
},
14+
{
15+
name: 'Troubleshooting',
16+
description: 'Get quick answers to common problems.',
17+
minimumAccordions: 5,
18+
},
19+
{
20+
name: 'Key terminology',
21+
description: 'Understand OpenShift more with definitions to essential vocabulary.',
22+
minimumAccordions: 10,
23+
},
24+
];

testing/playwright/page-objects/CreateProviderPage.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ export class CreateProviderPage {
4747
if (testData.password) {
4848
await this.page.getByTestId('provider-password-input').fill(testData.password);
4949
}
50-
await this.page.locator('#insecureSkipVerify-off').click();
50+
51+
await this.page.getByTestId('skip-certificate-validation-switch').check({ force: true });
5152

5253
await this.page.getByTestId('create-provider-button').click();
5354

@@ -82,6 +83,6 @@ export class CreateProviderPage {
8283
}
8384

8485
async waitForWizardLoad() {
85-
await expect(this.page.getByText('Create new provider')).toBeVisible();
86+
await expect(this.page.getByTestId('create-provider-heading')).toBeVisible();
8687
}
8788
}
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
import { expect, type Locator, type Page } from '@playwright/test';
2+
3+
import { NavigationHelper } from '../utils/NavigationHelper';
4+
5+
export interface TopicConfig {
6+
name: string;
7+
description: string;
8+
minimumAccordions?: number;
9+
}
10+
11+
export class OverviewPage {
12+
private readonly navigation: NavigationHelper;
13+
private readonly page: Page;
14+
15+
constructor(page: Page) {
16+
this.page = page;
17+
this.navigation = new NavigationHelper(page);
18+
}
19+
20+
get choosingMigrationTypeOption() {
21+
return this.page.getByText('Choosing the right migration type', { exact: true }).first();
22+
}
23+
24+
get closeDrawerButton() {
25+
return this.page.getByRole('button', { name: 'Close drawer panel' });
26+
}
27+
28+
async closeTipsAndTricks() {
29+
await expect(this.closeDrawerButton).toBeVisible();
30+
await this.closeDrawerButton.click();
31+
await expect(this.tipsAndTricksDrawerTitle).not.toBeVisible();
32+
}
33+
34+
get keyTerminologyOption() {
35+
return this.page.getByText('Key terminology', { exact: true }).first();
36+
}
37+
38+
get migratingVMsOption() {
39+
return this.page.getByText('Migrating your virtual machines', { exact: true }).first();
40+
}
41+
42+
async navigateDirectly() {
43+
await this.navigation.navigateToOverview();
44+
await this.waitForPageLoad();
45+
}
46+
47+
async navigateFromMainMenu() {
48+
await this.navigation.navigateToOverview();
49+
await this.waitForPageLoad();
50+
}
51+
52+
async navigateToNextTopic(currentTopicName: string, nextTopicName: string): Promise<void> {
53+
await this.page.getByRole('button', { name: currentTopicName }).first().click();
54+
await this.page.getByRole('option', { name: nextTopicName }).click();
55+
}
56+
57+
async openTipsAndTricks() {
58+
await expect(this.tipsAndTricksButton).toBeVisible({ timeout: 10000 });
59+
await this.tipsAndTricksButton.click();
60+
await expect(this.tipsAndTricksDrawerTitle).toBeVisible({ timeout: 10000 });
61+
}
62+
63+
async openTipsAndTricksDrawer(): Promise<{
64+
drawerTitle: Locator;
65+
selectTopicButton: Locator;
66+
closeDrawerButton: Locator;
67+
}> {
68+
await this.openTipsAndTricks();
69+
70+
await expect(this.selectTopicButton).toBeVisible();
71+
await expect(this.closeDrawerButton).toBeVisible();
72+
73+
return {
74+
drawerTitle: this.tipsAndTricksDrawerTitle,
75+
selectTopicButton: this.selectTopicButton,
76+
closeDrawerButton: this.closeDrawerButton,
77+
};
78+
}
79+
80+
get pageTitle() {
81+
return this.page.getByRole('heading', { name: 'Migration Toolkit for Virtualization' });
82+
}
83+
84+
async selectTopic(
85+
topicName: 'migrating-vms' | 'migration-type' | 'troubleshooting' | 'terminology',
86+
) {
87+
const topicMap = {
88+
'migrating-vms': this.migratingVMsOption,
89+
'migration-type': this.choosingMigrationTypeOption,
90+
troubleshooting: this.troubleshootingOption,
91+
terminology: this.keyTerminologyOption,
92+
};
93+
94+
const topic = topicMap[topicName];
95+
await expect(topic).toBeVisible();
96+
await topic.click();
97+
}
98+
99+
get selectTopicButton() {
100+
return this.page.getByRole('button', { name: 'Select a topic' });
101+
}
102+
103+
async selectTopicByCard(topicConfig: TopicConfig): Promise<void> {
104+
await this.page.getByTestId('topic-card').filter({ hasText: topicConfig.name }).click();
105+
await expect(
106+
this.page.getByRole('heading', { name: topicConfig.name, level: 3 }),
107+
).toBeVisible();
108+
}
109+
110+
async selectTopicByName(topicName: string): Promise<void> {
111+
await this.page.getByTestId('topic-card').filter({ hasText: topicName }).click();
112+
await this.verifyTopicHeading(topicName);
113+
}
114+
115+
async testAccordionsStructure(minimumCount: number): Promise<void> {
116+
const accordions = this.page.locator('.pf-v5-c-expandable-section');
117+
await expect(accordions.first()).toBeVisible({ timeout: 10000 });
118+
119+
const count = await accordions.count();
120+
expect(count).toBeGreaterThanOrEqual(minimumCount);
121+
122+
const testCount = Math.min(3, count);
123+
for (let i = 0; i < testCount; i += 1) {
124+
const accordion = accordions.nth(i);
125+
const toggleButton = accordion.locator('button').first();
126+
127+
await toggleButton.scrollIntoViewIfNeeded();
128+
await expect(toggleButton).toBeVisible();
129+
130+
// Expand then collapse (mimicking old behavior without state assertions)
131+
await toggleButton.click();
132+
await toggleButton.click();
133+
}
134+
}
135+
136+
get tipsAndTricksButton() {
137+
return this.page.getByRole('button', { name: 'Tips and tricks' });
138+
}
139+
140+
get tipsAndTricksDrawerTitle() {
141+
return this.page.getByRole('heading', { name: 'Tips and tricks', level: 2 });
142+
}
143+
144+
get troubleshootingOption() {
145+
return this.page.getByText('Troubleshooting', { exact: true }).first();
146+
}
147+
148+
async verifyPicklist(topics: TopicConfig[]): Promise<void> {
149+
await this.selectTopicButton.click();
150+
151+
for (const topic of topics) {
152+
await expect(this.page.getByRole('option', { name: topic.name })).toBeVisible();
153+
}
154+
155+
await this.selectTopicButton.click();
156+
}
157+
158+
async verifyTopicCards(topics: TopicConfig[]): Promise<void> {
159+
for (const topic of topics) {
160+
await expect(this.page.getByText(topic.name)).toBeVisible();
161+
await expect(this.page.getByText(topic.description)).toBeVisible();
162+
}
163+
}
164+
165+
async verifyTopicHeading(topicName: string): Promise<void> {
166+
await expect(this.page.getByRole('heading', { name: topicName, level: 3 })).toBeVisible();
167+
}
168+
169+
async waitForPageLoad() {
170+
await expect(this.pageTitle).toBeVisible({ timeout: 30000 });
171+
}
172+
}

testing/playwright/utils/NavigationHelper.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ export class NavigationHelper {
5757
allNamespaces?: boolean;
5858
}): Promise<void> {
5959
const url = this.buildK8sUrl(options);
60-
6160
await this.page.goto(url);
61+
await this.page.waitForLoadState('networkidle');
6262
await disableGuidedTour(this.page);
6363
}
6464

@@ -67,6 +67,14 @@ export class NavigationHelper {
6767
await this.page.getByTestId('migration-nav-item').click({ timeout: 20000 });
6868
}
6969

70+
async navigateToOverview(): Promise<void> {
71+
await disableGuidedTour(this.page);
72+
await this.page.goto('/mtv/overview');
73+
await this.page.waitForLoadState('networkidle');
74+
75+
await disableGuidedTour(this.page);
76+
}
77+
7078
async navigateToPlans(): Promise<void> {
7179
await this.navigateToMigrationMenu();
7280
await this.page.getByTestId('plans-nav-item').click();

tsconfig.eslint.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"extends": "./tsconfig.json",
3-
"include": ["src/**/*", "*.ts", "testing/**/*"],
3+
"include": ["src/**/*", "*.ts", "testing/**/*", "**/__tests__/**/*", "**/__mocks__/**/*"],
44
"exclude": ["node_modules", "dist", "locales", "docs", "ci"]
55
}

0 commit comments

Comments
 (0)