Skip to content
49 changes: 49 additions & 0 deletions e2e-tests/oxlint.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export default defineConfig({
categories: {
correctness: "error",
suspicious: "error",
pedantic: "error",
},
options: {
typeAware: true,
Expand All @@ -17,6 +18,7 @@ export default defineConfig({
"test-results/**",
"coverage/**",
".local-test/**",
"scripts/**",
],
rules: {
"typescript/no-floating-promises": "error",
Expand All @@ -26,6 +28,7 @@ export default defineConfig({
"typescript/no-unsafe-call": "error",
"typescript/no-unsafe-return": "error",
"typescript/strict-void-return": "error",
"typescript/prefer-readonly-parameter-types": "off",
"check-file/filename-naming-convention": [
"error",
{
Expand Down Expand Up @@ -61,12 +64,57 @@ export default defineConfig({
},
overrides: [
{
// Auth-provider specs deploy RHDH in beforeAll and use async Playwright hooks.
// strict-void-return and no-misused-promises produce false positives on those
// describe/beforeAll callbacks without improving test safety.
files: ["playwright/e2e/auth-providers/**/*.spec.ts"],
rules: {
"typescript/strict-void-return": "off",
"typescript/no-misused-promises": "off",
},
},
{
// Spec files orchestrate multi-step E2E flows; length limits target production
// code readability, not test scenarios that must stay in one file for clarity.
files: ["**/*.spec.ts", "**/*.test.ts"],
rules: {
"eslint/max-lines": "off",
"eslint/max-lines-per-function": "off",
},
},
{
// Shared infrastructure (utils, support, data, e2e helpers) is split into
// modules but still contains cohesive orchestration (kube waits, deployment
// setup, log parsing). Complexity limits would force artificial fragmentation.
files: [
"playwright/utils/**/*.ts",
"playwright/support/**/*.ts",
"playwright/data/**/*.ts",
"playwright/e2e/**/*.ts",
],
rules: {
"eslint/max-lines": "off",
"eslint/max-lines-per-function": "off",
"eslint/max-depth": "off",
},
},
{
// Facade modules aggregate many submodules by design (e.g. KubeClient re-exports,
// rhdh-deployment orchestration, locale translation maps). A flat import count
// does not reflect coupling when each import is a focused submodule.
files: ["playwright/utils/**/*.ts", "playwright/e2e/localization/**/*.ts"],
rules: {
"import/max-dependencies": "off",
},
},
{
// valid-title / valid-describe-callback: existing suite uses legacy naming
// patterns that do not match the plugin's strict conventions.
// no-wait-for-selector: replaced with expect() and locator.waitFor() per
// hardening guidelines; rule would flag intentional migration patterns.
// expect-expect + assertFunctionNames: POM verify* helpers and loginAsGuest
// perform assertions on behalf of the spec; register them so specs are not
// forced to duplicate expect() calls after every helper invocation.
files: ["**/*.spec.ts", "**/*.test.ts", "playwright/**/*.ts"],
rules: {
// Playwright requires object destructuring for hook/test callbacks that take
Expand Down Expand Up @@ -107,6 +155,7 @@ export default defineConfig({
"verifyTextInSelector",
"verifyPartialTextInSelector",
"loginAsGuest",
"restartDeployment",
"waitForTitle",
],
},
Expand Down
23 changes: 13 additions & 10 deletions e2e-tests/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import type { ReporterDescription } from "@playwright/test";

import { PW_PROJECT } from "./playwright/projects";

process.env.JOB_NAME = process.env.JOB_NAME || "";
process.env.IS_OPENSHIFT = process.env.IS_OPENSHIFT || "";
process.env.JOB_NAME = process.env.JOB_NAME ?? "";
process.env.IS_OPENSHIFT = process.env.IS_OPENSHIFT ?? "";

// Set LOCALE based on which project is being run
const args = process.argv;
Expand All @@ -19,26 +19,27 @@ if (args.some((arg) => arg.includes(PW_PROJECT.SHOWCASE_LOCALIZATION_DE))) {
process.env.LOCALE = "it";
} else if (args.some((arg) => arg.includes(PW_PROJECT.SHOWCASE_LOCALIZATION_JA))) {
process.env.LOCALE = "ja";
} else if (!process.env.LOCALE) {
} else if (process.env.LOCALE === undefined || process.env.LOCALE === "") {
process.env.LOCALE = "en";
}

const k8sSpecificConfig = {
use: {
actionTimeout: 15 * 1000,
},
// Global expect timeout
expect: {
timeout: 15 * 1000, // Global expect timeout
timeout: 15 * 1000,
},
};

export default defineConfig({
timeout: 90 * 1000,
testDir: "./playwright",
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
forbidOnly: process.env.CI !== undefined && process.env.CI !== "",
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
retries: process.env.CI !== undefined && process.env.CI !== "" ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: 3,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
Expand All @@ -47,14 +48,14 @@ export default defineConfig({
reporter: [
["html"],
["list"],
["junit", { outputFile: process.env.JUNIT_RESULTS || "junit-results.xml" }],
["junit", { outputFile: process.env.JUNIT_RESULTS ?? "junit-results.xml" }],
...(process.env.COLLECT_COVERAGE === "true"
? ([["./playwright/support/coverage/reporter.ts"]] satisfies ReporterDescription[])
: []),
],
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
locale: process.env.LOCALE || "en",
locale: process.env.LOCALE ?? "en",
baseURL: process.env.BASE_URL,
ignoreHTTPSErrors: true,
trace: "on",
Expand All @@ -72,8 +73,9 @@ export default defineConfig({
actionTimeout: 10 * 1000,
navigationTimeout: 50 * 1000,
},
// Global expect timeout
expect: {
timeout: 10 * 1000, // Global expect timeout
timeout: 10 * 1000,
},

/* Configure projects for major browsers */
Expand Down Expand Up @@ -110,7 +112,8 @@ export default defineConfig({
name: PW_PROJECT.SHOWCASE_AUTH_PROVIDERS,
testMatch: ["**/playwright/e2e/auth-providers/*.spec.ts"],
testIgnore: [
"**/playwright/e2e/auth-providers/github-happy-path.spec.ts", // temporarily disable
// temporarily disable github-happy-path
"**/playwright/e2e/auth-providers/github-happy-path.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
148 changes: 148 additions & 0 deletions e2e-tests/playwright/data/rbac-constants-policies.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import { Policy } from "../support/api/rbac-api-structures";

export const EXPECTED_POLICIES: Policy[] = [
{
entityReference: "role:default/rbac_admin",
permission: "policy-entity",
policy: "read",
effect: "allow",
},
{
entityReference: "role:default/rbac_admin",
permission: "policy.entity.create",
policy: "create",
effect: "allow",
},
{
entityReference: "role:default/rbac_admin",
permission: "policy-entity",
policy: "delete",
effect: "allow",
},
{
entityReference: "role:default/rbac_admin",
permission: "policy-entity",
policy: "update",
effect: "allow",
},
{
entityReference: "role:default/rbac_admin",
permission: "catalog-entity",
policy: "read",
effect: "allow",
},
{
entityReference: "role:default/guests",
permission: "catalog.entity.create",
policy: "create",
effect: "allow",
},
{
entityReference: "role:default/team_a",
permission: "catalog-entity",
policy: "read",
effect: "allow",
},
{
entityReference: "role:xyz/team_a",
permission: "catalog-entity",
policy: "read",
effect: "allow",
},
{
entityReference: "role:xyz/team_a",
permission: "catalog.entity.create",
policy: "create",
effect: "allow",
},
{
entityReference: "role:xyz/team_a",
permission: "catalog.location.create",
policy: "create",
effect: "allow",
},
{
entityReference: "role:xyz/team_a",
permission: "catalog.location.read",
policy: "read",
effect: "allow",
},
{
entityReference: "role:default/qe_rbac_admin",
permission: "kubernetes.proxy",
policy: "use",
effect: "allow",
},
{
entityReference: "role:default/qe_rbac_admin",
permission: "kubernetes.resources.read",
policy: "read",
effect: "allow",
},
{
entityReference: "role:default/qe_rbac_admin",
permission: "kubernetes.clusters.read",
policy: "read",
effect: "allow",
},
{
entityReference: "role:default/qe_rbac_admin",
permission: "catalog.entity.create",
policy: "create",
effect: "allow",
},
{
entityReference: "role:default/qe_rbac_admin",
permission: "catalog.location.create",
policy: "create",
effect: "allow",
},
{
entityReference: "role:default/qe_rbac_admin",
permission: "catalog.location.read",
policy: "read",
effect: "allow",
},
{
entityReference: "role:default/kubernetes_reader",
permission: "kubernetes.resources.read",
policy: "read",
effect: "allow",
},
{
entityReference: "role:default/kubernetes_reader",
permission: "kubernetes.clusters.read",
policy: "read",
effect: "allow",
},
{
entityReference: "role:default/catalog_reader",
permission: "catalog.entity.read",
policy: "read",
effect: "allow",
},
{
entityReference: "role:default/all_resource_reader",
permission: "catalog-entity",
policy: "read",
effect: "allow",
},
{
entityReference: "role:default/all_resource_reader",
permission: "catalog-entity",
policy: "create",
effect: "allow",
},
{
entityReference: "role:default/all_resource_denier",
permission: "catalog-entity",
policy: "read",
effect: "deny",
},
{
entityReference: "role:default/all_resource_denier",
permission: "catalog-entity",
policy: "create",
effect: "allow",
},
];
56 changes: 56 additions & 0 deletions e2e-tests/playwright/data/rbac-constants-roles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Role } from "../support/api/rbac-api-structures";

export const EXPECTED_ROLES: Role[] = [
{
memberReferences: ["user:default/rhdh-qe"],
name: "role:default/rbac_admin",
},
{
memberReferences: ["user:default/guest"],
name: "role:default/guests",
},
{
memberReferences: ["user:default/user_team_a", "user:default/rhdh-qe"],
name: "role:default/team_a",
},
{
memberReferences: ["user:xyz/user"],
name: "role:xyz/team_a",
},
{
memberReferences: ["group:default/rhdh-qe-2-team"],
name: "role:default/test2-role",
},
{
memberReferences: ["user:default/rhdh-qe"],
name: "role:default/qe_rbac_admin",
},
{
memberReferences: ["group:default/rhdh-qe-parent-team", "group:default/rhdh-qe-child-team"],
name: "role:default/transitive-owner",
},
{
memberReferences: ["user:default/rhdh-qe-5"],
name: "role:default/kubernetes_reader",
},
{
memberReferences: ["user:default/rhdh-qe-5", "user:default/rhdh-qe-6"],
name: "role:default/catalog_reader",
},
{
memberReferences: ["user:default/rhdh-qe-7", "user:default/rhdh-qe-9"],
name: "role:default/all_resource_reader",
},
{
memberReferences: ["user:default/rhdh-qe-8"],
name: "role:default/all_resource_denier",
},
{
memberReferences: ["user:default/rhdh-qe-7", "user:default/rhdh-qe-8"],
name: "role:default/owned_resource_reader",
},
{
memberReferences: ["user:default/rhdh-qe-9"],
name: "role:default/conditional_denier",
},
];
Loading
Loading