@red-hat-developer-hub/e2e-test-utils 1.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +6 -0
- package/dist/deployment/keycloak/config/keycloak-values.yaml +96 -0
- package/dist/deployment/keycloak/constants.d.ts +29 -0
- package/dist/deployment/keycloak/constants.d.ts.map +1 -0
- package/dist/deployment/keycloak/constants.js +75 -0
- package/dist/deployment/keycloak/deployment.d.ts +89 -0
- package/dist/deployment/keycloak/deployment.d.ts.map +1 -0
- package/dist/deployment/keycloak/deployment.js +435 -0
- package/dist/deployment/keycloak/index.d.ts +2 -0
- package/dist/deployment/keycloak/index.d.ts.map +1 -0
- package/dist/deployment/keycloak/index.js +1 -0
- package/dist/deployment/keycloak/types.d.ts +59 -0
- package/dist/deployment/keycloak/types.d.ts.map +1 -0
- package/dist/deployment/keycloak/types.js +1 -0
- package/dist/deployment/rhdh/config/auth/guest/app-config.yaml +5 -0
- package/dist/deployment/rhdh/config/auth/keycloak/app-config.yaml +19 -0
- package/dist/deployment/rhdh/config/auth/keycloak/dynamic-plugins.yaml +3 -0
- package/dist/deployment/rhdh/config/auth/keycloak/secrets.yaml +12 -0
- package/dist/deployment/rhdh/config/common/app-config-rhdh.yaml +6 -0
- package/dist/deployment/rhdh/config/common/dynamic-plugins.yaml +3 -0
- package/dist/deployment/rhdh/config/common/rhdh-secrets.yaml +7 -0
- package/dist/deployment/rhdh/config/helm/value_file.yaml +7 -0
- package/dist/deployment/rhdh/config/operator/subscription.yaml +21 -0
- package/dist/deployment/rhdh/constants.d.ts +19 -0
- package/dist/deployment/rhdh/constants.d.ts.map +1 -0
- package/dist/deployment/rhdh/constants.js +27 -0
- package/dist/deployment/rhdh/deployment.d.ts +40 -0
- package/dist/deployment/rhdh/deployment.d.ts.map +1 -0
- package/dist/deployment/rhdh/deployment.js +303 -0
- package/dist/deployment/rhdh/index.d.ts +2 -0
- package/dist/deployment/rhdh/index.d.ts.map +1 -0
- package/dist/deployment/rhdh/index.js +1 -0
- package/dist/deployment/rhdh/types.d.ts +31 -0
- package/dist/deployment/rhdh/types.d.ts.map +1 -0
- package/dist/deployment/rhdh/types.js +1 -0
- package/dist/eslint/base.config.d.ts +10 -0
- package/dist/eslint/base.config.d.ts.map +1 -0
- package/dist/eslint/base.config.js +213 -0
- package/dist/playwright/base-config.d.ts +14 -0
- package/dist/playwright/base-config.d.ts.map +1 -0
- package/dist/playwright/base-config.js +47 -0
- package/dist/playwright/fixtures/test.d.ts +13 -0
- package/dist/playwright/fixtures/test.d.ts.map +1 -0
- package/dist/playwright/fixtures/test.js +48 -0
- package/dist/playwright/global-setup.d.ts +6 -0
- package/dist/playwright/global-setup.d.ts.map +1 -0
- package/dist/playwright/global-setup.js +67 -0
- package/dist/playwright/helpers/accessibility.d.ts +13 -0
- package/dist/playwright/helpers/accessibility.d.ts.map +1 -0
- package/dist/playwright/helpers/accessibility.js +24 -0
- package/dist/playwright/helpers/api-endpoints.d.ts +11 -0
- package/dist/playwright/helpers/api-endpoints.d.ts.map +1 -0
- package/dist/playwright/helpers/api-endpoints.js +15 -0
- package/dist/playwright/helpers/api-helper.d.ts +77 -0
- package/dist/playwright/helpers/api-helper.d.ts.map +1 -0
- package/dist/playwright/helpers/api-helper.js +285 -0
- package/dist/playwright/helpers/common.d.ts +31 -0
- package/dist/playwright/helpers/common.d.ts.map +1 -0
- package/dist/playwright/helpers/common.js +342 -0
- package/dist/playwright/helpers/index.d.ts +5 -0
- package/dist/playwright/helpers/index.d.ts.map +1 -0
- package/dist/playwright/helpers/index.js +4 -0
- package/dist/playwright/helpers/navbar.d.ts +2 -0
- package/dist/playwright/helpers/navbar.d.ts.map +1 -0
- package/dist/playwright/helpers/navbar.js +1 -0
- package/dist/playwright/helpers/ui-helper.d.ts +106 -0
- package/dist/playwright/helpers/ui-helper.d.ts.map +1 -0
- package/dist/playwright/helpers/ui-helper.js +439 -0
- package/dist/playwright/page-objects/global-obj.d.ts +25 -0
- package/dist/playwright/page-objects/global-obj.d.ts.map +1 -0
- package/dist/playwright/page-objects/global-obj.js +24 -0
- package/dist/playwright/page-objects/page-obj.d.ts +41 -0
- package/dist/playwright/page-objects/page-obj.d.ts.map +1 -0
- package/dist/playwright/page-objects/page-obj.js +40 -0
- package/dist/playwright/pages/catalog-import.d.ts +31 -0
- package/dist/playwright/pages/catalog-import.d.ts.map +1 -0
- package/dist/playwright/pages/catalog-import.js +65 -0
- package/dist/playwright/pages/catalog.d.ts +14 -0
- package/dist/playwright/pages/catalog.d.ts.map +1 -0
- package/dist/playwright/pages/catalog.js +37 -0
- package/dist/playwright/pages/extensions.d.ts +38 -0
- package/dist/playwright/pages/extensions.d.ts.map +1 -0
- package/dist/playwright/pages/extensions.js +110 -0
- package/dist/playwright/pages/home-page.d.ts +10 -0
- package/dist/playwright/pages/home-page.d.ts.map +1 -0
- package/dist/playwright/pages/home-page.js +46 -0
- package/dist/playwright/pages/index.d.ts +6 -0
- package/dist/playwright/pages/index.d.ts.map +1 -0
- package/dist/playwright/pages/index.js +5 -0
- package/dist/playwright/pages/notifications.d.ts +24 -0
- package/dist/playwright/pages/notifications.d.ts.map +1 -0
- package/dist/playwright/pages/notifications.js +112 -0
- package/dist/utils/bash.d.ts +3 -0
- package/dist/utils/bash.d.ts.map +1 -0
- package/dist/utils/bash.js +4 -0
- package/dist/utils/common.d.ts +3 -0
- package/dist/utils/common.d.ts.map +1 -0
- package/dist/utils/common.js +8 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/kubernetes-client.d.ts +97 -0
- package/dist/utils/kubernetes-client.d.ts.map +1 -0
- package/dist/utils/kubernetes-client.js +558 -0
- package/dist/utils/merge-yamls.d.ts +50 -0
- package/dist/utils/merge-yamls.d.ts.map +1 -0
- package/dist/utils/merge-yamls.js +96 -0
- package/dist/utils/plugin-metadata.d.ts +116 -0
- package/dist/utils/plugin-metadata.d.ts.map +1 -0
- package/dist/utils/plugin-metadata.js +330 -0
- package/package.json +108 -0
- package/tsconfig.base.json +16 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Locator, Page } from "@playwright/test";
|
|
2
|
+
export declare class CatalogPage {
|
|
3
|
+
private page;
|
|
4
|
+
private uiHelper;
|
|
5
|
+
private searchField;
|
|
6
|
+
constructor(page: Page);
|
|
7
|
+
go(): Promise<void>;
|
|
8
|
+
goToByName(name: string): Promise<void>;
|
|
9
|
+
goToBackstageJanusProjectCITab(): Promise<void>;
|
|
10
|
+
goToBackstageJanusProject(): Promise<void>;
|
|
11
|
+
search(s: string): Promise<void>;
|
|
12
|
+
tableRow(content: string): Promise<Locator>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../../src/playwright/pages/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAItD,qBAAa,WAAW;IACtB,OAAO,CAAC,IAAI,CAAO;IACnB,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,WAAW,CAAU;gBAEjB,IAAI,EAAE,IAAI;IAMhB,EAAE;IAIF,UAAU,CAAC,IAAI,EAAE,MAAM;IAKvB,8BAA8B;IAO9B,yBAAyB;IAIzB,MAAM,CAAC,CAAC,EAAE,MAAM;IAShB,QAAQ,CAAC,OAAO,EAAE,MAAM;CAG/B"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { UIhelper } from "../helpers/ui-helper.js";
|
|
2
|
+
//${BASE_URL}/catalog page
|
|
3
|
+
export class CatalogPage {
|
|
4
|
+
page;
|
|
5
|
+
uiHelper;
|
|
6
|
+
searchField;
|
|
7
|
+
constructor(page) {
|
|
8
|
+
this.page = page;
|
|
9
|
+
this.uiHelper = new UIhelper(page);
|
|
10
|
+
this.searchField = page.locator("#input-with-icon-adornment");
|
|
11
|
+
}
|
|
12
|
+
async go() {
|
|
13
|
+
await this.uiHelper.openSidebar("Catalog");
|
|
14
|
+
}
|
|
15
|
+
async goToByName(name) {
|
|
16
|
+
await this.uiHelper.openCatalogSidebar("Component");
|
|
17
|
+
await this.uiHelper.clickLink(name);
|
|
18
|
+
}
|
|
19
|
+
async goToBackstageJanusProjectCITab() {
|
|
20
|
+
await this.goToBackstageJanusProject();
|
|
21
|
+
await this.uiHelper.clickTab("CI");
|
|
22
|
+
await this.page.waitForSelector('h2:text("Pipeline Runs")');
|
|
23
|
+
await this.uiHelper.verifyHeading("Pipeline Runs");
|
|
24
|
+
}
|
|
25
|
+
async goToBackstageJanusProject() {
|
|
26
|
+
await this.goToByName("backstage-janus");
|
|
27
|
+
}
|
|
28
|
+
async search(s) {
|
|
29
|
+
await this.searchField.clear();
|
|
30
|
+
const searchResponse = this.page.waitForResponse(new RegExp(`${process.env.BASE_URL}/api/catalog/entities/by-query/*`));
|
|
31
|
+
await this.searchField.fill(s);
|
|
32
|
+
await searchResponse;
|
|
33
|
+
}
|
|
34
|
+
async tableRow(content) {
|
|
35
|
+
return this.page.locator(`tr >> a >> text="${content}"`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Page, Locator } from "@playwright/test";
|
|
2
|
+
export declare class ExtensionsPage {
|
|
3
|
+
private page;
|
|
4
|
+
badge: Locator;
|
|
5
|
+
private uiHelper;
|
|
6
|
+
private commonHeadings;
|
|
7
|
+
private tableHeaders;
|
|
8
|
+
constructor(page: Page);
|
|
9
|
+
clickReadMoreByPluginTitle(pluginTitle: string): Promise<void>;
|
|
10
|
+
selectDropdown(name: string): Promise<void>;
|
|
11
|
+
toggleOption(name: string): Promise<void>;
|
|
12
|
+
clickAway(): Promise<void>;
|
|
13
|
+
selectSupportTypeFilter(supportType: string): Promise<void>;
|
|
14
|
+
resetSupportTypeFilter(supportType: string): Promise<void>;
|
|
15
|
+
verifyMultipleHeadings(headings?: string[]): Promise<void>;
|
|
16
|
+
waitForSearchResults(searchText: string): Promise<void>;
|
|
17
|
+
verifyPluginDetails({ pluginName, badgeLabel, badgeText, headings, includeTable, includeAbout, }: {
|
|
18
|
+
pluginName: string;
|
|
19
|
+
badgeLabel: string;
|
|
20
|
+
badgeText: string;
|
|
21
|
+
headings?: string[];
|
|
22
|
+
includeTable?: boolean;
|
|
23
|
+
includeAbout?: boolean;
|
|
24
|
+
}): Promise<void>;
|
|
25
|
+
verifySupportTypeBadge({ supportType, pluginName, badgeLabel, badgeText, tooltipText, searchTerm, headings, includeTable, includeAbout, }: {
|
|
26
|
+
supportType: string;
|
|
27
|
+
pluginName?: string;
|
|
28
|
+
badgeLabel: string;
|
|
29
|
+
badgeText: string;
|
|
30
|
+
tooltipText: string;
|
|
31
|
+
searchTerm?: string;
|
|
32
|
+
headings?: string[];
|
|
33
|
+
includeTable?: boolean;
|
|
34
|
+
includeAbout?: boolean;
|
|
35
|
+
}): Promise<void>;
|
|
36
|
+
verifyKeyValueRowElements(rowTitle: string, rowValue: string): Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=extensions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../../../src/playwright/pages/extensions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAItD,qBAAa,cAAc;IACzB,OAAO,CAAC,IAAI,CAAO;IACZ,KAAK,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,QAAQ,CAAW;IAE3B,OAAO,CAAC,cAAc,CAOpB;IACF,OAAO,CAAC,YAAY,CAMlB;gBAEU,IAAI,EAAE,IAAI;IAMhB,0BAA0B,CAAC,WAAW,EAAE,MAAM;IAM9C,cAAc,CAAC,IAAI,EAAE,MAAM;IAO3B,YAAY,CAAC,IAAI,EAAE,MAAM;IAOzB,SAAS;IAIT,uBAAuB,CAAC,WAAW,EAAE,MAAM;IAM3C,sBAAsB,CAAC,WAAW,EAAE,MAAM;IAM1C,sBAAsB,CAAC,QAAQ,GAAE,MAAM,EAAwB;IAO/D,oBAAoB,CAAC,UAAU,EAAE,MAAM;IAMvC,mBAAmB,CAAC,EACxB,UAAU,EACV,UAAU,EACV,SAAS,EACT,QAA8B,EAC9B,YAAmB,EACnB,YAAoB,GACrB,EAAE;QACD,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB;IAuBK,sBAAsB,CAAC,EAC3B,WAAW,EACX,UAAU,EACV,UAAU,EACV,SAAS,EACT,WAAW,EACX,UAAU,EACV,QAA8B,EAC9B,YAAmB,EACnB,YAAoB,GACrB,EAAE;QACD,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB;IA2BK,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAMnE"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { expect } from "@playwright/test";
|
|
2
|
+
import { UIhelper } from "../helpers/ui-helper.js";
|
|
3
|
+
export class ExtensionsPage {
|
|
4
|
+
page;
|
|
5
|
+
badge;
|
|
6
|
+
uiHelper;
|
|
7
|
+
commonHeadings = [
|
|
8
|
+
"Versions",
|
|
9
|
+
"Author",
|
|
10
|
+
"Tags",
|
|
11
|
+
"Category",
|
|
12
|
+
"Publisher",
|
|
13
|
+
"Support Provider",
|
|
14
|
+
];
|
|
15
|
+
tableHeaders = [
|
|
16
|
+
"Package name",
|
|
17
|
+
"Version",
|
|
18
|
+
"Role",
|
|
19
|
+
"Backstage compatibility version",
|
|
20
|
+
"Status",
|
|
21
|
+
];
|
|
22
|
+
constructor(page) {
|
|
23
|
+
this.page = page;
|
|
24
|
+
this.badge = this.page.getByTestId("TaskAltIcon");
|
|
25
|
+
this.uiHelper = new UIhelper(page);
|
|
26
|
+
}
|
|
27
|
+
async clickReadMoreByPluginTitle(pluginTitle) {
|
|
28
|
+
const allCards = this.page.locator(".v5-MuiPaper-outlined");
|
|
29
|
+
const targetCard = allCards.filter({ hasText: pluginTitle });
|
|
30
|
+
await targetCard.getByRole("link", { name: "Read more" }).click();
|
|
31
|
+
}
|
|
32
|
+
async selectDropdown(name) {
|
|
33
|
+
await this.page
|
|
34
|
+
.getByLabel(name)
|
|
35
|
+
.getByRole("button", { name: "Open" })
|
|
36
|
+
.click();
|
|
37
|
+
}
|
|
38
|
+
async toggleOption(name) {
|
|
39
|
+
await this.page
|
|
40
|
+
.getByRole("option", { name: name })
|
|
41
|
+
.getByRole("checkbox")
|
|
42
|
+
.click();
|
|
43
|
+
}
|
|
44
|
+
async clickAway() {
|
|
45
|
+
await this.page.locator("#menu- div").first().click();
|
|
46
|
+
}
|
|
47
|
+
async selectSupportTypeFilter(supportType) {
|
|
48
|
+
await this.selectDropdown("Support type");
|
|
49
|
+
await this.toggleOption(supportType);
|
|
50
|
+
await this.page.keyboard.press("Escape");
|
|
51
|
+
}
|
|
52
|
+
async resetSupportTypeFilter(supportType) {
|
|
53
|
+
await this.selectDropdown("Support type");
|
|
54
|
+
await this.toggleOption(supportType);
|
|
55
|
+
await this.page.keyboard.press("Escape");
|
|
56
|
+
}
|
|
57
|
+
async verifyMultipleHeadings(headings = this.commonHeadings) {
|
|
58
|
+
for (const heading of headings) {
|
|
59
|
+
console.log(`Verifying heading: ${heading}`);
|
|
60
|
+
await this.uiHelper.verifyHeading(heading);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async waitForSearchResults(searchText) {
|
|
64
|
+
await expect(this.page.locator(".v5-MuiPaper-outlined").first()).toContainText(searchText, { timeout: 10000 });
|
|
65
|
+
}
|
|
66
|
+
async verifyPluginDetails({ pluginName, badgeLabel, badgeText, headings = this.commonHeadings, includeTable = true, includeAbout = false, }) {
|
|
67
|
+
await this.clickReadMoreByPluginTitle(pluginName);
|
|
68
|
+
await expect(this.page.getByLabel(badgeLabel).getByText(badgeText)).toBeVisible();
|
|
69
|
+
if (includeAbout) {
|
|
70
|
+
await this.uiHelper.verifyText("About");
|
|
71
|
+
}
|
|
72
|
+
await this.verifyMultipleHeadings(headings);
|
|
73
|
+
if (includeTable) {
|
|
74
|
+
await this.uiHelper.verifyTableHeadingAndRows(this.tableHeaders);
|
|
75
|
+
}
|
|
76
|
+
await this.page
|
|
77
|
+
.getByRole("button", {
|
|
78
|
+
name: "close",
|
|
79
|
+
})
|
|
80
|
+
.click();
|
|
81
|
+
}
|
|
82
|
+
async verifySupportTypeBadge({ supportType, pluginName, badgeLabel, badgeText, tooltipText, searchTerm, headings = this.commonHeadings, includeTable = true, includeAbout = false, }) {
|
|
83
|
+
await this.selectSupportTypeFilter(supportType);
|
|
84
|
+
if (searchTerm) {
|
|
85
|
+
await this.uiHelper.searchInputPlaceholder(searchTerm);
|
|
86
|
+
await this.waitForSearchResults(searchTerm);
|
|
87
|
+
}
|
|
88
|
+
if (pluginName) {
|
|
89
|
+
await this.verifyPluginDetails({
|
|
90
|
+
pluginName,
|
|
91
|
+
badgeLabel,
|
|
92
|
+
badgeText,
|
|
93
|
+
headings,
|
|
94
|
+
includeTable,
|
|
95
|
+
includeAbout,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
await expect(this.page.getByLabel(badgeLabel).first()).toBeVisible();
|
|
100
|
+
await expect(this.badge.first()).toBeVisible();
|
|
101
|
+
await this.badge.first().hover();
|
|
102
|
+
await this.uiHelper.verifyTextInTooltip(tooltipText);
|
|
103
|
+
}
|
|
104
|
+
await this.resetSupportTypeFilter(supportType);
|
|
105
|
+
}
|
|
106
|
+
async verifyKeyValueRowElements(rowTitle, rowValue) {
|
|
107
|
+
const rowLocator = this.page.locator(".v5-MuiTableRow-root");
|
|
108
|
+
await expect(rowLocator.filter({ hasText: rowTitle })).toContainText(rowValue);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Page } from "@playwright/test";
|
|
2
|
+
export declare class HomePage {
|
|
3
|
+
private page;
|
|
4
|
+
private uiHelper;
|
|
5
|
+
constructor(page: Page);
|
|
6
|
+
verifyQuickSearchBar(text: string): Promise<void>;
|
|
7
|
+
verifyQuickAccess(section: string, quickAccessItem: string, expand?: boolean): Promise<void>;
|
|
8
|
+
verifyVisitedCardContent(section: string): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=home-page.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"home-page.d.ts","sourceRoot":"","sources":["../../../src/playwright/pages/home-page.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAG7C,qBAAa,QAAQ;IACnB,OAAO,CAAC,IAAI,CAAO;IACnB,OAAO,CAAC,QAAQ,CAAW;gBAEf,IAAI,EAAE,IAAI;IAIhB,oBAAoB,CAAC,IAAI,EAAE,MAAM;IAUjC,iBAAiB,CACrB,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,EACvB,MAAM,UAAQ;IAyBV,wBAAwB,CAAC,OAAO,EAAE,MAAM;CAY/C"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { HOME_PAGE_COMPONENTS, SEARCH_OBJECTS_COMPONENTS, } from "../page-objects/page-obj.js";
|
|
2
|
+
import { UIhelper } from "../helpers/ui-helper.js";
|
|
3
|
+
import { expect } from "@playwright/test";
|
|
4
|
+
export class HomePage {
|
|
5
|
+
page;
|
|
6
|
+
uiHelper;
|
|
7
|
+
constructor(page) {
|
|
8
|
+
this.page = page;
|
|
9
|
+
this.uiHelper = new UIhelper(page);
|
|
10
|
+
}
|
|
11
|
+
async verifyQuickSearchBar(text) {
|
|
12
|
+
const searchBar = this.page.locator(SEARCH_OBJECTS_COMPONENTS.ariaLabelSearch);
|
|
13
|
+
await searchBar.waitFor();
|
|
14
|
+
await searchBar.fill("");
|
|
15
|
+
await searchBar.type(text + "\n"); // '\n' simulates pressing the Enter key
|
|
16
|
+
await this.uiHelper.verifyLink(text);
|
|
17
|
+
}
|
|
18
|
+
async verifyQuickAccess(section, quickAccessItem, expand = false) {
|
|
19
|
+
await this.page.waitForSelector(HOME_PAGE_COMPONENTS.MuiAccordion, {
|
|
20
|
+
state: "visible",
|
|
21
|
+
});
|
|
22
|
+
const sectionLocator = this.page
|
|
23
|
+
.locator(HOME_PAGE_COMPONENTS.MuiAccordion)
|
|
24
|
+
.filter({ hasText: section });
|
|
25
|
+
if (expand) {
|
|
26
|
+
await sectionLocator.click();
|
|
27
|
+
await this.page.waitForTimeout(500);
|
|
28
|
+
}
|
|
29
|
+
const itemLocator = sectionLocator
|
|
30
|
+
.locator(`a div[class*="MuiListItemText-root"]`)
|
|
31
|
+
.filter({ hasText: quickAccessItem });
|
|
32
|
+
await itemLocator.waitFor({ state: "visible" });
|
|
33
|
+
const isVisible = itemLocator;
|
|
34
|
+
await expect(isVisible).toBeVisible();
|
|
35
|
+
}
|
|
36
|
+
async verifyVisitedCardContent(section) {
|
|
37
|
+
await this.page.waitForSelector(HOME_PAGE_COMPONENTS.MuiCard, {
|
|
38
|
+
state: "visible",
|
|
39
|
+
});
|
|
40
|
+
const sectionLocator = this.page
|
|
41
|
+
.locator(HOME_PAGE_COMPONENTS.MuiCard)
|
|
42
|
+
.filter({ hasText: section });
|
|
43
|
+
const itemLocator = sectionLocator.locator(`li[class*="MuiListItem-root"]`);
|
|
44
|
+
expect(await itemLocator.count()).toBeGreaterThanOrEqual(0);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { CatalogImportPage } from "./catalog-import.js";
|
|
2
|
+
export { CatalogPage } from "./catalog.js";
|
|
3
|
+
export { ExtensionsPage } from "./extensions.js";
|
|
4
|
+
export { HomePage } from "./home-page.js";
|
|
5
|
+
export { NotificationPage } from "./notifications.js";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/playwright/pages/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type Page } from "@playwright/test";
|
|
2
|
+
export declare class NotificationPage {
|
|
3
|
+
private readonly page;
|
|
4
|
+
private readonly uiHelper;
|
|
5
|
+
constructor(page: Page);
|
|
6
|
+
clickNotificationsNavBarItem(): Promise<void>;
|
|
7
|
+
notificationContains(text: string | RegExp): Promise<void>;
|
|
8
|
+
clickNotificationHeadingLink(text: string | RegExp): Promise<void>;
|
|
9
|
+
markAllNotificationsAsRead(): Promise<void>;
|
|
10
|
+
selectAllNotifications(): Promise<void>;
|
|
11
|
+
selectNotification(nth?: number): Promise<void>;
|
|
12
|
+
selectSeverity(severity?: string): Promise<void>;
|
|
13
|
+
saveSelected(): Promise<void>;
|
|
14
|
+
saveAllSelected(): Promise<void>;
|
|
15
|
+
viewSaved(): Promise<void>;
|
|
16
|
+
markLastNotificationAsRead(): Promise<void>;
|
|
17
|
+
markNotificationAsRead(text: string): Promise<void>;
|
|
18
|
+
markLastNotificationAsUnRead(): Promise<void>;
|
|
19
|
+
viewRead(): Promise<void>;
|
|
20
|
+
viewUnRead(): Promise<void>;
|
|
21
|
+
sortByOldestOnTop(): Promise<void>;
|
|
22
|
+
sortByNewestOnTop(): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=notifications.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../../src/playwright/pages/notifications.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAGrD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAO;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;gBAExB,IAAI,EAAE,IAAI;IAKhB,4BAA4B;IAO5B,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAW1C,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAOlD,0BAA0B;IAiB1B,sBAAsB;IAItB,kBAAkB,CAAC,GAAG,SAAI;IAI1B,cAAc,CAAC,QAAQ,SAAK;IAW5B,YAAY;IAWZ,eAAe;IAWf,SAAS;IAQT,0BAA0B;IAK1B,sBAAsB,CAAC,IAAI,EAAE,MAAM;IAKnC,4BAA4B;IAK5B,QAAQ;IAUR,UAAU;IAUV,iBAAiB;IAQjB,iBAAiB;CAOxB"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { expect } from "@playwright/test";
|
|
2
|
+
import { UIhelper } from "../helpers/ui-helper.js";
|
|
3
|
+
export class NotificationPage {
|
|
4
|
+
page;
|
|
5
|
+
uiHelper;
|
|
6
|
+
constructor(page) {
|
|
7
|
+
this.page = page;
|
|
8
|
+
this.uiHelper = new UIhelper(page);
|
|
9
|
+
}
|
|
10
|
+
async clickNotificationsNavBarItem() {
|
|
11
|
+
await this.uiHelper.openSidebar("Notifications");
|
|
12
|
+
await expect(this.page.getByTestId("loading-indicator").getByRole("img")).toHaveCount(0);
|
|
13
|
+
}
|
|
14
|
+
async notificationContains(text) {
|
|
15
|
+
await this.page.getByLabel(/.*rows/).click();
|
|
16
|
+
// always expand the notifications table to show as many notifications as possible
|
|
17
|
+
await this.page.getByRole("option", { name: "20" }).click();
|
|
18
|
+
await expect(this.page.getByTestId("loading-indicator").getByRole("img")).toHaveCount(0);
|
|
19
|
+
const row = this.page.locator(`tr`, { hasText: text }).first();
|
|
20
|
+
await expect(row).toHaveCount(1);
|
|
21
|
+
}
|
|
22
|
+
async clickNotificationHeadingLink(text) {
|
|
23
|
+
await this.page
|
|
24
|
+
.getByRole("cell", { name: text, exact: true })
|
|
25
|
+
.first()
|
|
26
|
+
.getByRole("heading")
|
|
27
|
+
.click();
|
|
28
|
+
}
|
|
29
|
+
async markAllNotificationsAsRead() {
|
|
30
|
+
const markAllNotificationsAsReadIsVisible = await this.page
|
|
31
|
+
.getByTitle("Mark all read")
|
|
32
|
+
.getByRole("button")
|
|
33
|
+
.isVisible();
|
|
34
|
+
console.log(markAllNotificationsAsReadIsVisible);
|
|
35
|
+
// If button isn't visible there are no records in the notification table
|
|
36
|
+
if (markAllNotificationsAsReadIsVisible.toString() != "false") {
|
|
37
|
+
await this.page.getByTitle("Mark all read").getByRole("button").click();
|
|
38
|
+
await this.page.getByRole("button", { name: "MARK ALL" }).click();
|
|
39
|
+
await expect(this.page.getByTestId("loading-indicator").getByRole("img")).toHaveCount(0);
|
|
40
|
+
await expect(this.page.getByText("No records to display")).toBeVisible();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async selectAllNotifications() {
|
|
44
|
+
await this.page.getByRole("checkbox").first().click();
|
|
45
|
+
}
|
|
46
|
+
async selectNotification(nth = 1) {
|
|
47
|
+
await this.page.getByRole("checkbox").nth(nth).click();
|
|
48
|
+
}
|
|
49
|
+
async selectSeverity(severity = "") {
|
|
50
|
+
await this.page.getByLabel("Severity").click();
|
|
51
|
+
await this.page.getByRole("option", { name: severity }).click();
|
|
52
|
+
await expect(this.page.getByRole("table").filter({ hasText: "Rows per page" })).toBeVisible();
|
|
53
|
+
await expect(this.page.getByTestId("loading-indicator").getByRole("img")).toHaveCount(0);
|
|
54
|
+
}
|
|
55
|
+
async saveSelected() {
|
|
56
|
+
await this.page
|
|
57
|
+
.locator("thead")
|
|
58
|
+
.getByTitle("Save selected for later")
|
|
59
|
+
.getByRole("button")
|
|
60
|
+
.click();
|
|
61
|
+
await expect(this.page.getByTestId("loading-indicator").getByRole("img")).toHaveCount(0);
|
|
62
|
+
}
|
|
63
|
+
async saveAllSelected() {
|
|
64
|
+
await this.page
|
|
65
|
+
.locator("thead")
|
|
66
|
+
.getByTitle("Save selected for later")
|
|
67
|
+
.getByRole("button")
|
|
68
|
+
.click();
|
|
69
|
+
await expect(this.page.getByTestId("loading-indicator").getByRole("img")).toHaveCount(0);
|
|
70
|
+
}
|
|
71
|
+
async viewSaved() {
|
|
72
|
+
await this.page.getByLabel("View").click();
|
|
73
|
+
await this.page.getByRole("option", { name: "Saved" }).click();
|
|
74
|
+
await expect(this.page.getByTestId("loading-indicator").getByRole("img")).toHaveCount(0);
|
|
75
|
+
}
|
|
76
|
+
async markLastNotificationAsRead() {
|
|
77
|
+
const row = this.page.locator("td:nth-child(3) > div").first();
|
|
78
|
+
await row.getByRole("button").nth(1).click();
|
|
79
|
+
}
|
|
80
|
+
async markNotificationAsRead(text) {
|
|
81
|
+
const row = this.page.locator(`tr:has-text("${text}")`);
|
|
82
|
+
await row.getByRole("button").nth(1).click();
|
|
83
|
+
}
|
|
84
|
+
async markLastNotificationAsUnRead() {
|
|
85
|
+
const row = this.page.locator("td:nth-child(3) > div").first();
|
|
86
|
+
await row.getByRole("button").nth(1).click();
|
|
87
|
+
}
|
|
88
|
+
async viewRead() {
|
|
89
|
+
await this.page.getByLabel("View").click();
|
|
90
|
+
await this.page
|
|
91
|
+
.getByRole("option", { name: "Read notifications", exact: true })
|
|
92
|
+
.click();
|
|
93
|
+
await expect(this.page.getByTestId("loading-indicator").getByRole("img")).toHaveCount(0);
|
|
94
|
+
}
|
|
95
|
+
async viewUnRead() {
|
|
96
|
+
await this.page.getByLabel("View").click();
|
|
97
|
+
await this.page
|
|
98
|
+
.getByRole("option", { name: "Unread notifications", exact: true })
|
|
99
|
+
.click();
|
|
100
|
+
await expect(this.page.getByTestId("loading-indicator").getByRole("img")).toHaveCount(0);
|
|
101
|
+
}
|
|
102
|
+
async sortByOldestOnTop() {
|
|
103
|
+
await this.page.getByLabel("Sort by").click();
|
|
104
|
+
await this.page.getByRole("option", { name: "Oldest on top" }).click();
|
|
105
|
+
await expect(this.page.getByTestId("loading-indicator").getByRole("img")).toHaveCount(0);
|
|
106
|
+
}
|
|
107
|
+
async sortByNewestOnTop() {
|
|
108
|
+
await this.page.getByLabel("Sort by").click();
|
|
109
|
+
await this.page.getByRole("option", { name: "Newest on top" }).click();
|
|
110
|
+
await expect(this.page.getByTestId("loading-indicator").getByRole("img")).toHaveCount(0);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../src/utils/bash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,IAAI,CAAC;AAKvB,OAAO,EAAE,CAAC,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/utils/common.ts"],"names":[],"mappings":"AAAA,iBAAS,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,oBAAc,UAS/C;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { envsubst } from "./common.js";
|
|
2
|
+
export { $ } from "./bash.js";
|
|
3
|
+
export { mergeYamlFiles, mergeYamlFilesIfExists, mergeYamlFilesToFile, } from "./merge-yamls.js";
|
|
4
|
+
export { KubernetesClientHelper } from "./kubernetes-client.js";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,CAAC,EAAE,MAAM,WAAW,CAAC;AAC9B,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import * as k8s from "@kubernetes/client-node";
|
|
2
|
+
/**
|
|
3
|
+
* Kubernetes client wrapper with proper abstraction
|
|
4
|
+
*/
|
|
5
|
+
declare class KubernetesClientHelper {
|
|
6
|
+
private _kc;
|
|
7
|
+
private _k8sApi;
|
|
8
|
+
private _appsApi;
|
|
9
|
+
private _customObjectsApi;
|
|
10
|
+
constructor();
|
|
11
|
+
/**
|
|
12
|
+
* Create or update a ConfigMap from a file
|
|
13
|
+
*/
|
|
14
|
+
createOrUpdateConfigMap(name: string, namespace: string, configFilePath: string, dataKey?: string): Promise<k8s.V1ConfigMap>;
|
|
15
|
+
/**
|
|
16
|
+
* Create a namespace if it doesn't exist
|
|
17
|
+
*/
|
|
18
|
+
createNamespaceIfNotExists(namespace: string): Promise<k8s.V1Namespace>;
|
|
19
|
+
/**
|
|
20
|
+
* Apply a Kubernetes manifest from a YAML file
|
|
21
|
+
// */
|
|
22
|
+
/**
|
|
23
|
+
* Apply a Kubernetes resource dynamically
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* Create or update a Secret
|
|
27
|
+
*/
|
|
28
|
+
private _applySecret;
|
|
29
|
+
/**
|
|
30
|
+
* Create or update a ConfigMap from a plain object
|
|
31
|
+
*/
|
|
32
|
+
applyConfigMapFromObject(name: string, data: Record<string, unknown>, namespace: string): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Create or update a Secret from a plain object
|
|
35
|
+
*/
|
|
36
|
+
applySecretFromObject(name: string, data: {
|
|
37
|
+
stringData?: Record<string, string>;
|
|
38
|
+
}, namespace: string): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Delete a namespace and wait for it to be fully terminated
|
|
41
|
+
*/
|
|
42
|
+
deleteNamespace(namespace: string, waitForDeletion?: boolean, timeoutSeconds?: number): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Wait for a namespace to be fully deleted
|
|
45
|
+
*/
|
|
46
|
+
private _waitForNamespaceDeletion;
|
|
47
|
+
/**
|
|
48
|
+
* Check if an error is a "not found" (404) error.
|
|
49
|
+
* Handles different error formats from various k8s client versions.
|
|
50
|
+
*/
|
|
51
|
+
private _isNotFoundError;
|
|
52
|
+
/**
|
|
53
|
+
* Check if a StatefulSet is ready (all replicas are available)
|
|
54
|
+
*/
|
|
55
|
+
isStatefulSetReady(namespace: string, name: string): Promise<boolean>;
|
|
56
|
+
/**
|
|
57
|
+
* Wait for a StatefulSet to be ready (all replicas available)
|
|
58
|
+
*/
|
|
59
|
+
waitForStatefulSetReady(namespace: string, name: string, timeoutSeconds?: number, pollIntervalMs?: number): Promise<boolean>;
|
|
60
|
+
/**
|
|
61
|
+
* Get the cluster's ingress domain from OpenShift config
|
|
62
|
+
* Equivalent to: oc get ingresses.config.openshift.io cluster -o jsonpath='{.spec.domain}'
|
|
63
|
+
*/
|
|
64
|
+
getClusterIngressDomain(): Promise<string>;
|
|
65
|
+
/**
|
|
66
|
+
* Get the URL/location of an OpenShift Route by name
|
|
67
|
+
*
|
|
68
|
+
* @param namespace - The namespace to search in
|
|
69
|
+
* @param name - The route name
|
|
70
|
+
* @returns The route URL (e.g., https://myapp.apps.cluster.example.com)
|
|
71
|
+
*/
|
|
72
|
+
getRouteLocation(namespace: string, name: string): Promise<string>;
|
|
73
|
+
/**
|
|
74
|
+
* Extract the URL from a route object
|
|
75
|
+
*/
|
|
76
|
+
private _extractRouteUrl;
|
|
77
|
+
/**
|
|
78
|
+
* Failure states that indicate a pod will not recover without intervention
|
|
79
|
+
*/
|
|
80
|
+
private static readonly failureReasons;
|
|
81
|
+
/**
|
|
82
|
+
* Wait for pods matching a label selector to be ready, with early failure detection.
|
|
83
|
+
* Fails fast when it detects unrecoverable states like CrashLoopBackOff.
|
|
84
|
+
*
|
|
85
|
+
* @param namespace - Namespace to watch
|
|
86
|
+
* @param labelSelector - Label selector (e.g., "app=myapp")
|
|
87
|
+
* @param timeoutSeconds - Maximum time to wait (default: 300)
|
|
88
|
+
* @param pollIntervalMs - How often to check pod status (default: 5000)
|
|
89
|
+
*/
|
|
90
|
+
waitForPodsWithFailureDetection(namespace: string, labelSelector: string, timeoutSeconds?: number, pollIntervalMs?: number): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Check if a pod is in a failure state. Returns failure info or null if healthy.
|
|
93
|
+
*/
|
|
94
|
+
private _checkPodFailure;
|
|
95
|
+
}
|
|
96
|
+
export { KubernetesClientHelper };
|
|
97
|
+
//# sourceMappingURL=kubernetes-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kubernetes-client.d.ts","sourceRoot":"","sources":["../../src/utils/kubernetes-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,GAAG,MAAM,yBAAyB,CAAC;AAO/C;;GAEG;AACH,cAAM,sBAAsB;IAC1B,OAAO,CAAC,GAAG,CAAiB;IAC5B,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,iBAAiB,CAAuB;;IAoChD;;OAEG;IACG,uBAAuB,CAC3B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;IA8C3B;;OAEG;IACG,0BAA0B,CAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;IA+B3B;;UAEM;IAmBN;;OAEG;IAsBH;;OAEG;YACW,YAAY;IA8B1B;;OAEG;IACG,wBAAwB,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC;IA0ChB;;OAEG;IACG,qBAAqB,CACzB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,EAC7C,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC;IAqChB;;OAEG;IACG,eAAe,CACnB,SAAS,EAAE,MAAM,EACjB,eAAe,GAAE,OAAc,EAC/B,cAAc,GAAE,MAAY,GAC3B,OAAO,CAAC,IAAI,CAAC;IAyBhB;;OAEG;YACW,yBAAyB;IAsCvC;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IA2BxB;;OAEG;IACG,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAc3E;;OAEG;IACG,uBAAuB,CAC3B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,cAAc,GAAE,MAAY,EAC5B,cAAc,GAAE,MAAa,GAC5B,OAAO,CAAC,OAAO,CAAC;IAiBnB;;;OAGG;IACG,uBAAuB,IAAI,OAAO,CAAC,MAAM,CAAC;IAsBhD;;;;;;OAMG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAkBxE;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAmBxB;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAQnC;IAEH;;;;;;;;OAQG;IACG,+BAA+B,CACnC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,cAAc,GAAE,MAAY,EAC5B,cAAc,GAAE,MAAa,GAC5B,OAAO,CAAC,IAAI,CAAC;IA8FhB;;OAEG;IACH,OAAO,CAAC,gBAAgB;CA8BzB;AAED,OAAO,EAAE,sBAAsB,EAAE,CAAC"}
|