Skip to content

Commit 3cad71c

Browse files
committed
feat: Changed file structure for a clean and better navigation
1 parent 74bca69 commit 3cad71c

26 files changed

+176
-82
lines changed

page-objects/service-spec-config-page.ts

Lines changed: 97 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,12 @@ export class ServiceSpecConfigPage extends BasePage {
4242

4343
constructor(page: Page, testInfo: TestInfo, eyes: any, specName: string) {
4444
super(page, testInfo, eyes, specName);
45+
const specFileName = specName.includes("/")
46+
? specName.split("/").pop()!
47+
: specName;
4548
this.specTree = page.locator("#spec-tree");
4649
this.specSection = page.locator(
47-
`xpath=//div[contains(@id,"${specName}") and @data-mode="spec"]`,
50+
`xpath=//div[contains(@id,"${specFileName}") and @data-mode="spec"]`,
4851
);
4952
this.specBtn = page.locator('li.tab[data-type="spec"]').first();
5053
this.editBtn = this.specSection.getByText(/Edit specmatic.yaml/i);
@@ -57,10 +60,10 @@ export class ServiceSpecConfigPage extends BasePage {
5760
this.contractTestTab = page.locator('li.tab[data-type="test"]').first();
5861
this.alertMsg = page.locator(".alert-msg p");
5962
this.validationErrorBtn = page
60-
.locator(`[id*="${this.specName}"]`)
63+
.locator(`[id*="${specFileName}"]`)
6164
.locator("button.bcc-errors-btn");
6265
this.errorContent = page
63-
.locator(`[id*="${this.specName}"]`)
66+
.locator(`[id*="${specFileName}"]`)
6467
.locator(".bcc-errors-content");
6568

6669
this.bccTestButton = this.specSection.locator("#bcc-test-btn");
@@ -384,14 +387,23 @@ export class ServiceSpecConfigPage extends BasePage {
384387
}
385388

386389
async toggleBccErrorSection(shouldExpand: boolean) {
387-
const isExpanded = await this.bccErrorToggle.getAttribute("aria-expanded");
390+
// Use the content element's CSS class as the source of truth for the
391+
// current expanded state. aria-expanded on the toggle button can drift
392+
// out of sync with the actual visual state when scenarios run back-to-back
393+
// without a page reload.
394+
const classes = (await this.bccErrorContent.getAttribute("class")) ?? "";
395+
const isCurrentlyExpanded = classes.includes("show");
388396

389397
if (
390-
(shouldExpand && isExpanded === "false") ||
391-
(!shouldExpand && isExpanded === "true")
398+
(shouldExpand && !isCurrentlyExpanded) ||
399+
(!shouldExpand && isCurrentlyExpanded)
392400
) {
393401
await this.bccErrorToggle.click();
394-
await takeAndAttachScreenshot(this.page, "expanding-error-setion");
402+
await takeAndAttachScreenshot(
403+
this.page,
404+
"expanding-error-section",
405+
this.eyes,
406+
);
395407
}
396408

397409
if (shouldExpand) {
@@ -510,4 +522,82 @@ export class ServiceSpecConfigPage extends BasePage {
510522
await expect(saveAlert).toBeHidden({ timeout: 5000 });
511523
});
512524
}
525+
526+
async verifyCompatibilityScenario(
527+
scenario: {
528+
oldText: string;
529+
newText: string;
530+
expectedMessage: string | RegExp;
531+
},
532+
reload: boolean = true,
533+
) {
534+
await test.step(`Scenario: ${scenario.oldText} -> ${scenario.newText}`, async () => {
535+
if (scenario.newText === "") {
536+
await this.deleteSpecLinesInEditor(scenario.oldText, 1);
537+
} else {
538+
await this.editSpecInEditor(scenario.oldText, scenario.newText);
539+
}
540+
541+
await this.runBackwardCompatibilityTest();
542+
543+
const actualMessage = await this.getAlertMessageText();
544+
expect(actualMessage).toContain(scenario.expectedMessage);
545+
546+
await this.dismissAlert();
547+
548+
if (reload) {
549+
await this.page.reload();
550+
await this.openSpecTab();
551+
}
552+
});
553+
}
554+
555+
async verifyIncompatibilityScenario(
556+
scenario: {
557+
oldText: string;
558+
newText: string;
559+
lineCount: number;
560+
expectedErrorCount: number;
561+
expectedDetail: string;
562+
},
563+
reload: boolean = true,
564+
) {
565+
// 1. Preconditions: Get back to a clean state (skipped when batching without reload)
566+
if (reload) {
567+
await test.step("Preconditions for the test", async () => {
568+
await this.page.reload();
569+
await this.navigateToSpec(this.specName!);
570+
});
571+
}
572+
573+
await test.step(`Incompatibility Check for: ${scenario.oldText}`, async () => {
574+
if (scenario.lineCount > 0) {
575+
await this.deleteSpecLinesInEditor(
576+
scenario.oldText,
577+
scenario.lineCount,
578+
);
579+
} else if (scenario.newText !== "") {
580+
await this.editSpecInEditor(scenario.oldText, scenario.newText);
581+
}
582+
583+
await this.runBackwardCompatibilityTest();
584+
585+
const toastText = await this.getAlertMessageText();
586+
expect.soft(toastText).toContain("Backward compatibility test failed");
587+
await this.dismissAlert();
588+
589+
await this.toggleBccErrorSection(true);
590+
const { summary, details } = await this.getBccErrorDetails();
591+
592+
// Check for error count and details
593+
expect.soft(summary).toContain(`${scenario.expectedErrorCount} error`);
594+
const hasMatch = details.some((d) => d.includes(scenario.expectedDetail));
595+
expect
596+
.soft(
597+
hasMatch,
598+
`Expected error detail not found: ${scenario.expectedDetail}`,
599+
)
600+
.toBe(true);
601+
});
602+
}
513603
}

page-objects/side-bar-page.ts

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@ export class SideBarPage {
1414
this.eyes = eyes;
1515
}
1616

17-
/**
18-
* Ensures the left sidebar is expanded. If closed, expands it and verifies the state.
19-
* Takes a screenshot after opening if testInfo is provided.
20-
*/
2117
async ensureSidebarOpen(): Promise<void> {
2218
console.log("\tEnsuring sidebar is open");
2319
await expect(this.leftSidebar).toBeAttached();
@@ -33,15 +29,43 @@ export class SideBarPage {
3329
}
3430

3531
async selectSpec(specName: string): Promise<Locator> {
32+
const parts = specName.split("/");
33+
const fileName = parts[parts.length - 1];
34+
const folderPath = parts.slice(0, -1);
3635
const specLocator = this.page
3736
.locator("#spec-tree")
38-
.locator(`span.wb-title:has-text("${specName}")`);
37+
.locator(`span.wb-title[title="${fileName}"]`);
3938

4039
await test.step(`Maps to Service Spec: '${specName}'`, async () => {
4140
await this.ensureSidebarOpen();
42-
4341
await this.page.waitForTimeout(500);
4442

43+
for (let i = 0; i < folderPath.length; i++) {
44+
const folder = folderPath[i];
45+
const folderRow = this.page
46+
.locator("#spec-tree")
47+
.locator(`div.wb-row:has(span.wb-title[title="${folder}"])`);
48+
49+
await folderRow.waitFor({ state: "visible", timeout: 5000 });
50+
51+
const classes = (await folderRow.getAttribute("class")) ?? "";
52+
if (!classes.includes("wb-expanded")) {
53+
const expander = folderRow.locator("i.wb-expander");
54+
if ((await expander.count()) > 0) {
55+
await expander.click();
56+
} else {
57+
await folderRow.click();
58+
}
59+
60+
const nextLabel =
61+
i + 1 < folderPath.length ? folderPath[i + 1] : fileName;
62+
await this.page
63+
.locator("#spec-tree")
64+
.locator(`span.wb-title[title="${nextLabel}"]`)
65+
.waitFor({ state: "visible", timeout: 5000 });
66+
}
67+
}
68+
4569
await expect(specLocator).toBeVisible({ timeout: 5000 });
4670

4771
await specLocator.evaluate((node) =>

specmatic-studio-demo/specs/examples/dynamic.json

Lines changed: 0 additions & 44 deletions
This file was deleted.

specmatic-studio-demo/specs/product_search_bff_v5_backward_compatibility.yaml renamed to specmatic-studio-demo/specs/test-openapi/bcc/product_search_bff_v5_backward_compatibility.yaml

File renamed without changes.

specmatic-studio-demo/specs/product_search_bff_v5_backward_incompatibility.yaml renamed to specmatic-studio-demo/specs/test-openapi/bcc/product_search_bff_v5_backward_incompatibility.yaml

File renamed without changes.

specmatic-studio-demo/specs/product_search_bff_v5_contract_tests_default.yaml renamed to specmatic-studio-demo/specs/test-openapi/contract-tests/product_search_bff_v5_contract_tests_default.yaml

File renamed without changes.

specmatic-studio-demo/specs/product_search_bff_v5_contract_tests_excluded.yaml renamed to specmatic-studio-demo/specs/test-openapi/contract-tests/product_search_bff_v5_contract_tests_excluded.yaml

File renamed without changes.

specmatic-studio-demo/specs/product_search_bff_v5_contract_tests_filter.yaml renamed to specmatic-studio-demo/specs/test-openapi/contract-tests/product_search_bff_v5_contract_tests_filter.yaml

File renamed without changes.

specmatic-studio-demo/specs/product_search_bff_v5_contract_tests_generative.yaml renamed to specmatic-studio-demo/specs/test-openapi/contract-tests/product_search_bff_v5_contract_tests_generative.yaml

File renamed without changes.

specmatic-studio-demo/specs/product_search_bff_v5_contract_tests_negative.yaml renamed to specmatic-studio-demo/specs/test-openapi/contract-tests/product_search_bff_v5_contract_tests_negative.yaml

File renamed without changes.

0 commit comments

Comments
 (0)