Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
f747f6d
test: unskip annotator test to see CI output
djanickova Jan 9, 2026
b06f19b
fix: create catalogGraphApiFactory
djanickova Jan 9, 2026
a169ddd
test: refactor tests for the annotator plugin
djanickova Jan 16, 2026
cd4b9fa
Merge branch 'main' into scaffolder-annotator-test
djanickova Jan 16, 2026
0791f7e
chore: fix prettier
djanickova Jan 16, 2026
5c35ffd
chore: run prettier against tests
djanickova Jan 16, 2026
71da3e7
Merge branch 'main' into scaffolder-annotator-test
djanickova Jan 20, 2026
aef753e
fix: use verifyPartialTextInSelector
djanickova Jan 20, 2026
b4d5277
Merge branch 'main' into scaffolder-annotator-test
djanickova Jan 20, 2026
da6c791
Merge branch 'main' into scaffolder-annotator-test
djanickova Jan 20, 2026
38caaa5
Merge branch 'main' into scaffolder-annotator-test
djanickova Jan 20, 2026
427312e
ref: use a more precise selector
djanickova Jan 21, 2026
487e023
Merge branch 'main' into scaffolder-annotator-test
djanickova Jan 21, 2026
3c1f855
fix: run prettier
djanickova Jan 21, 2026
586c1e7
Merge branch 'main' into scaffolder-annotator-test
djanickova Jan 21, 2026
3fe447e
Merge branch 'main' into scaffolder-annotator-test
djanickova Jan 21, 2026
5e7dd96
Merge branch 'main' into scaffolder-annotator-test
djanickova Jan 22, 2026
832767c
Merge branch 'main' into scaffolder-annotator-test
djanickova Jan 23, 2026
8cbfaef
Merge branch 'main' into scaffolder-annotator-test
djanickova Jan 26, 2026
ca3d302
Merge branch 'main' into scaffolder-annotator-test
djanickova Jan 27, 2026
399a304
Merge branch 'main' into scaffolder-annotator-test
djanickova Jan 27, 2026
6b793db
Merge branch 'main' into scaffolder-annotator-test
djanickova Jan 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions e2e-tests/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ export default defineConfig({
"**/playwright/e2e/auth-providers/**/*.spec.ts",
"**/playwright/e2e/plugins/bulk-import.spec.ts",
"**/playwright/e2e/plugins/tekton/tekton.spec.ts",
"**/playwright/e2e/scaffolder-backend-module-annotator.spec.ts",
"**/playwright/e2e/plugins/scaffolder-backend-module-annotator/**/*.spec.ts",
"**/playwright/e2e/plugins/scaffolder-relation-processor/**/*.spec.ts",
"**/playwright/e2e/plugins/ocm.spec.ts",
"**/playwright/e2e/audit-log/**/*.spec.ts",
"**/playwright/e2e/external-database/verify-tls-config-with-external-rds.spec.ts",
Expand Down Expand Up @@ -149,7 +150,8 @@ export default defineConfig({
"**/playwright/e2e/auth-providers/**/*.spec.ts",
"**/playwright/e2e/plugins/bulk-import.spec.ts",
"**/playwright/e2e/plugins/tekton/tekton.spec.ts",
"**/playwright/e2e/scaffolder-backend-module-annotator.spec.ts",
"**/playwright/e2e/plugins/scaffolder-backend-module-annotator/**/*.spec.ts",
"**/playwright/e2e/plugins/scaffolder-relation-processor/**/*.spec.ts",
"**/playwright/e2e/audit-log/**/*.spec.ts",
"**/playwright/e2e/external-database/verify-tls-config-with-external-rds.spec.ts",
"**/playwright/e2e/external-database/verify-tls-config-with-external-azure-db.spec.ts",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { expect, Page, test } from "@playwright/test";
import { UIhelper } from "../utils/ui-helper";
import { Common, setupBrowser } from "../utils/common";
import { CatalogImport } from "../support/pages/catalog-import";
import { APIHelper } from "../utils/api-helper";
import { GITHUB_API_ENDPOINTS } from "../utils/api-endpoints";
import { runAccessibilityTests } from "../utils/accessibility";
import { Page, test } from "@playwright/test";
import { UIhelper } from "../../../utils/ui-helper";
import { Common, setupBrowser } from "../../../utils/common";
import { CatalogImport } from "../../../support/pages/catalog-import";
import { APIHelper } from "../../../utils/api-helper";
import { GITHUB_API_ENDPOINTS } from "../../../utils/api-endpoints";
import { runAccessibilityTests } from "../../../utils/accessibility";

let page: Page;

test.describe.serial("Test Scaffolder Backend Module Annotator Actions", () => {
test.skip(true, "Disabled on Backstage 1.45 update");
test.describe.serial("Test Scaffolder Backend Module Annotator", () => {
test.skip(() => process.env.JOB_NAME.includes("osd-gcp")); // skipping due to RHIDP-5704 on OSD Env

let uiHelper: UIhelper;
let common: Common;
let catalogImport: CatalogImport;
Expand All @@ -20,12 +20,11 @@ test.describe.serial("Test Scaffolder Backend Module Annotator Actions", () => {

const reactAppDetails = {
owner: "janus-qe/maintainers",
componentName: `test-scaffoldedfromlink-${Date.now()}`,
componentPartialName: `test-scaffoldedfromlink-`,
description: "react app using template",
componentName: `test-annotator-${Date.now()}`,
description: "react app for annotator test",
label: "some-label",
annotation: "some-annotation",
repo: `test-scaffolded-${Date.now()}`,
repo: `test-annotator-${Date.now()}`,
repoOwner: Buffer.from(
process.env.GITHUB_ORG || "amFudXMtcWU=",
"base64",
Expand All @@ -35,7 +34,7 @@ test.describe.serial("Test Scaffolder Backend Module Annotator Actions", () => {
test.beforeAll(async ({ browser }, testInfo) => {
test.info().annotations.push({
type: "component",
description: "core",
description: "plugins",
});

page = (await setupBrowser(browser, testInfo)).page;
Expand All @@ -47,7 +46,7 @@ test.describe.serial("Test Scaffolder Backend Module Annotator Actions", () => {
await common.loginAsGuest();
});

test("Register a Template", async ({}, testInfo) => {
test("Register the annotator template", async ({}, testInfo) => {
await uiHelper.openSidebar("Catalog");
await uiHelper.verifyText("Name");

Expand All @@ -58,7 +57,7 @@ test.describe.serial("Test Scaffolder Backend Module Annotator Actions", () => {
await catalogImport.registerExistingComponent(template, false);
});

test("Create a React App using the newly registered Template", async () => {
test("Scaffold a component using the annotator template", async () => {
test.setTimeout(130000);
await uiHelper.openSidebar("Catalog");
await uiHelper.clickButton("Self-service");
Expand Down Expand Up @@ -109,68 +108,7 @@ test.describe.serial("Test Scaffolder Backend Module Annotator Actions", () => {
await uiHelper.clickLink("Open in catalog");
});

test("Verify Scaffolded link in components Dependencies and scaffoldedFrom relation in entity Raw Yaml ", async () => {
await uiHelper.openCatalogSidebar("Component");

await uiHelper.searchInputPlaceholder("scaffoldedfromlink-\n");
await clickOnScaffoldedFromLink();

await uiHelper.clickTab("Dependencies");

// Define selectors for labels and nodes
const labelSelector = 'g[data-testid="label"]'; // Selector for labels
const nodeSelector = 'g[data-testid="node"]'; // Selector for nodes

// Verify text inside the 'label' selector
await uiHelper.verifyTextInSelector(labelSelector, "ownerOf");
await uiHelper.verifyTextInSelector(labelSelector, "/ ownedBy");
await uiHelper.verifyTextInSelector(labelSelector, "scaffoldedFrom");

// Verify text inside the 'node' selector
await uiHelper.verifyPartialTextInSelector(
nodeSelector,
reactAppDetails.componentPartialName,
);

await uiHelper.verifyTextInSelector(
nodeSelector,
"Create React App Template",
);

// Verify the scaffoldedFrom relation in the YAML view of the entity
await catalogImport.inspectEntityAndVerifyYaml(
`relations:
- type: ownedBy
targetRef: group:janus-qe/maintainers
- type: scaffoldedFrom
targetRef: template:default/create-react-app-template-with-timestamp-entityref
spec:
type: website
lifecycle: experimental
owner: group:janus-qe/maintainers
scaffoldedFrom: template:default/create-react-app-template-with-timestamp-entityref`,
);
});

test("Verify Registered Template and scaffolderOf relation in entity Raw Yaml", async () => {
await uiHelper.openSidebar("Catalog");
await uiHelper.selectMuiBox("Kind", "Template");

await uiHelper.searchInputPlaceholder("Create React App Template\n");
await uiHelper.verifyRowInTableByUniqueText("Create React App Template", [
"website",
]);
await uiHelper.clickLink("Create React App Template");

await catalogImport.inspectEntityAndVerifyYaml(
`- type: scaffolderOf\n targetRef: component:default/${reactAppDetails.componentName}\n`,
);

await uiHelper.clickLink("Launch Template");
await uiHelper.verifyText("Provide some simple information");
});

test("Verify Registered Component has templated label in entity Raw Yaml", async () => {
test("Verify custom label is added to scaffolded component", async () => {
await uiHelper.openCatalogSidebar("Component");
await uiHelper.searchInputPlaceholder(reactAppDetails.componentName);

Expand All @@ -185,7 +123,7 @@ test.describe.serial("Test Scaffolder Backend Module Annotator Actions", () => {
);
});

test("Verify Registered Component has templated annotation in entity Raw Yaml", async () => {
test("Verify custom annotation is added to scaffolded component", async () => {
await uiHelper.openCatalogSidebar("Component");
await uiHelper.searchInputPlaceholder(reactAppDetails.componentName);

Expand All @@ -200,7 +138,7 @@ test.describe.serial("Test Scaffolder Backend Module Annotator Actions", () => {
);
});

test("Verify Registered Component has templated version in entity Raw Yaml", async () => {
test("Verify template version annotation is added to scaffolded component", async () => {
await uiHelper.openCatalogSidebar("Component");
await uiHelper.searchInputPlaceholder(reactAppDetails.componentName);

Expand All @@ -215,7 +153,7 @@ test.describe.serial("Test Scaffolder Backend Module Annotator Actions", () => {
);
});

test("Verify Registered Template has templated version in entity Raw Yaml", async () => {
test("Verify template version annotation is present on the template", async () => {
await uiHelper.openSidebar("Catalog");
await uiHelper.selectMuiBox("Kind", "Template");

Expand All @@ -240,13 +178,4 @@ test.describe.serial("Test Scaffolder Backend Module Annotator Actions", () => {
);
await page.close();
});

async function clickOnScaffoldedFromLink() {
const selector =
'a[href*="/catalog/default/component/test-scaffoldedfromlink-"]';
await page.locator(selector).first().waitFor({ state: "visible" });
const link = page.locator(selector).first();
await expect(link).toBeVisible();
await link.click();
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import { expect, Page, test } from "@playwright/test";
import { UIhelper } from "../../../utils/ui-helper";
import { Common, setupBrowser } from "../../../utils/common";
import { CatalogImport } from "../../../support/pages/catalog-import";
import { APIHelper } from "../../../utils/api-helper";
import { GITHUB_API_ENDPOINTS } from "../../../utils/api-endpoints";

let page: Page;

test.describe.serial("Test Scaffolder Relation Processor Plugin", () => {
test.skip(() => process.env.JOB_NAME.includes("osd-gcp")); // skipping due to RHIDP-5704 on OSD Env

let uiHelper: UIhelper;
let common: Common;
let catalogImport: CatalogImport;

const template =
"https://github.com/backstage/community-plugins/blob/main/workspaces/scaffolder-backend-module-annotator/plugins/scaffolder-backend-module-annotator/examples/templates/01-scaffolder-template.yaml";

const reactAppDetails = {
owner: "janus-qe/maintainers",
componentName: `test-relation-${Date.now()}`,
componentPartialName: `test-relation-`,
description: "react app for relation processor test",
label: "test-label",
annotation: "test-annotation",
repo: `test-relation-${Date.now()}`,
repoOwner: Buffer.from(
process.env.GITHUB_ORG || "amFudXMtcWU=",
"base64",
).toString("utf8"), // Default repoOwner janus-qe
};

test.beforeAll(async ({ browser }, testInfo) => {
test.info().annotations.push({
type: "component",
description: "plugins",
});

page = (await setupBrowser(browser, testInfo)).page;

common = new Common(page);
uiHelper = new UIhelper(page);
catalogImport = new CatalogImport(page);

await common.loginAsGuest();
});

test("Register the template for scaffolder relation processor", async () => {
await uiHelper.openSidebar("Catalog");
await uiHelper.verifyText("Name");

await uiHelper.clickButton("Self-service");
await uiHelper.clickButton("Import an existing Git repository");
await catalogImport.registerExistingComponent(template, false);
});

test("Scaffold a component to test relation processing", async () => {
test.setTimeout(130000);
await uiHelper.openSidebar("Catalog");
await uiHelper.clickButton("Self-service");
await uiHelper.searchInputPlaceholder("Create React App Template");
await uiHelper.verifyText("Create React App Template");
await uiHelper.waitForTextDisappear("Add ArgoCD to an existing project");
await uiHelper.clickButton("Choose");

await uiHelper.fillTextInputByLabel("Name", reactAppDetails.componentName);
await uiHelper.fillTextInputByLabel(
"Description",
reactAppDetails.description,
);
await uiHelper.fillTextInputByLabel("Owner", reactAppDetails.owner);
await uiHelper.fillTextInputByLabel("Label", reactAppDetails.label);
await uiHelper.fillTextInputByLabel(
"Annotation",
reactAppDetails.annotation,
);
await uiHelper.clickButton("Next");

await uiHelper.fillTextInputByLabel("Owner", reactAppDetails.repoOwner);
await uiHelper.fillTextInputByLabel("Repository", reactAppDetails.repo);
await uiHelper.pressTab();
await uiHelper.clickButton("Review");

await uiHelper.clickButton("Create");
await page.waitForTimeout(5000);
await uiHelper.clickLink("Open in catalog");
});

test("Verify scaffoldedFrom relation in dependency graph and raw YAML", async () => {
// Verify the scaffoldedFrom relation in the YAML view of the entity
await catalogImport.inspectEntityAndVerifyYaml(
`relations:
- type: ownedBy
targetRef: group:janus-qe/maintainers
- type: scaffoldedFrom
targetRef: template:default/create-react-app-template-with-timestamp-entityref
spec:
type: website
lifecycle: experimental
owner: group:janus-qe/maintainers
scaffoldedFrom: template:default/create-react-app-template-with-timestamp-entityref`,
);

await uiHelper.openCatalogSidebar("Component");
await uiHelper.searchInputPlaceholder("test-relation-\n");
await clickOnRelationTestComponent();

await uiHelper.clickTab("Dependencies");

const labelSelector = 'g[data-testid="label"]';
const nodeSelector = 'g[data-testid="node"]';

await uiHelper.verifyTextInSelector(
labelSelector,
"scaffolderOf / scaffoldedFrom",
);

await uiHelper.verifyPartialTextInSelector(
nodeSelector,
reactAppDetails.componentPartialName,
);
});

test("Verify scaffolderOf relation on the template", async () => {
await uiHelper.openSidebar("Catalog");
await uiHelper.selectMuiBox("Kind", "Template");

await uiHelper.searchInputPlaceholder("Create React App Template\n");
await uiHelper.verifyRowInTableByUniqueText("Create React App Template", [
"website",
]);
await uiHelper.clickLink("Create React App Template");

// Verify the scaffolderOf relation in the YAML view
await catalogImport.inspectEntityAndVerifyYaml(
`- type: scaffolderOf\n targetRef: component:default/${reactAppDetails.componentName}\n`,
);

// Verify the template is still functional
await uiHelper.clickLink("Launch Template");
await uiHelper.verifyText("Provide some simple information");
});

test.afterAll(async () => {
await APIHelper.githubRequest(
"DELETE",
GITHUB_API_ENDPOINTS.deleteRepo(
reactAppDetails.repoOwner,
reactAppDetails.repo,
),
);
await page.close();
});

async function clickOnRelationTestComponent() {
const selector = 'a[href*="/catalog/default/component/test-relation-"]';
await page.locator(selector).first().waitFor({ state: "visible" });
const link = page.locator(selector).first();
await expect(link).toBeVisible();
await link.click();
}
});
Loading
Loading