Skip to content

Commit

Permalink
test(e2e): enforce naming (#1906)
Browse files Browse the repository at this point in the history
* style more like

* add anotation about running on CI

* expanding and grouping developer guidelines

* add paths ignore for e2e docs

* adding Use of External Sources for Validation

* reorganization

* delete innecessari duplications of principles for new PRs

* move e2e contributing file

* delete duplicates

* +readme.md

* improve e2e lint

* enforce naming

* enforce case with lint

* fix broken waitForNextSync

* add prettier and lint check for e2e

* fix missing lint errors

* fix problem caused on github-helper

* rename catalog

* wip

* delete logger

* + logger

* update for catalog path

* rename logs again

* fix lint check on CI

* + POM

* wip on RbacPo

* wip

* wip

wip

wip

replace old references with rbacPo

* amenda

* adjust kubeclient naming and usage

* wip

* fix merge conflicts

* rename typo on KubeClient

* wip

* wip

* fix lint

* fix tests

* minor fixes

* fix main conflicts

* ignore any for lint

---------

Co-authored-by: Joseph Kim <[email protected]>
  • Loading branch information
nilgaar and josephca authored Nov 27, 2024
1 parent e8511c2 commit 7a80e46
Show file tree
Hide file tree
Showing 80 changed files with 1,149 additions and 970 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ jobs:
- name: Run monorepo tools
run: yarn run monorepo:check

- name: Run prettier for e2e
run: cd e2e-tests && yarn prettier:check --concurrency=75% --affected

- name: Run lint for e2e
run: cd e2e-tests && yarn run lint:check

- name: Regenerate dockerfiles
run: |
yarn run build:dockerfile; if [[ $(git diff --name-only | grep Dockerfile || true) != "" ]]; then \
Expand Down
49 changes: 44 additions & 5 deletions e2e-tests/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,48 @@
{
"parser": "@typescript-eslint/parser",

"plugins": ["@typescript-eslint"],
"plugins": ["@typescript-eslint", "filenames"],
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
"ignorePatterns": ["node_modules", "playwright-report", "test-results"],
"rules": {
"@typescript-eslint/no-explicit-any": "off"
},
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"]
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "variable",
"format": ["camelCase"]
},
{
"selector": "variable",
"modifiers": ["const", "exported"],
"format": ["UPPER_CASE"]
},
{
"selector": "function",
"format": ["camelCase"]
},
{
"selector": "parameter",
"format": ["camelCase"],
"leadingUnderscore": "allow"
},
{
"selector": "memberLike",
"modifiers": ["private"],
"format": ["camelCase"],
"leadingUnderscore": "allow"
},
{
"selector": "typeLike",
"format": ["PascalCase"]
},
{
"selector": "enumMember",
"format": ["UPPER_CASE"]
},
{
"selector": "class",
"format": ["PascalCase"]
}
],
"filenames/match-regex": ["error", "^[a-z0-9-.]+$", true]
}
}
1 change: 1 addition & 0 deletions e2e-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"@typescript-eslint/eslint-plugin": "6.21.0",
"@typescript-eslint/parser": "6.21.0",
"eslint": "8.57.1",
"eslint-plugin-filenames": "^1.3.2",
"ioredis": "5.4.1",
"otplib": "12.0.1",
"prettier": "3.3.3",
Expand Down
46 changes: 0 additions & 46 deletions e2e-tests/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
import { defineConfig, devices } from "@playwright/test";

/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/

/**
* See https://playwright.dev/docs/test-configuration.
*/

const useCommonDeviceAndViewportConfig = {
use: {
...devices["Desktop Chrome"],
Expand Down Expand Up @@ -130,42 +121,5 @@ export default defineConfig({
...useCommonDeviceAndViewportConfig,
testMatch: ["**/playwright/e2e/configuration-test/config-map.spec.ts"],
},

// {
// name: 'firefox',
// use: { ...devices['Desktop Firefox'] },
// },
//
// {
// name: 'webkit',
// use: { ...devices['Desktop Safari'] },
// },

/* Test against mobile viewports. */
// {
// name: 'Mobile Chrome',
// use: { ...devices['Pixel 5'] },
// },
// {
// name: 'Mobile Safari',
// use: { ...devices['iPhone 12'] },
// },

/* Test against branded browsers. */
// {
// name: 'Microsoft Edge',
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
// },
// {
// name: 'Google Chrome',
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
// },
],

/* Run your local dev server before starting the tests */
// webServer: {
// command: 'npm run start',
// url: 'http://127.0.0.1:3000',
// reuseExistingServer: !process.env.CI,
// },
});
8 changes: 4 additions & 4 deletions e2e-tests/playwright/e2e/audit-log/catalog.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { test } from "@playwright/test";
import { Common } from "../../utils/Common";
import { UIhelper } from "../../utils/UIhelper";
import { LogUtils } from "./LogUtils";
import { CatalogImport } from "../../support/pages/CatalogImport";
import { Common } from "../../utils/common";
import { UIhelper } from "../../utils/ui-helper";
import { LogUtils } from "./log-utils";
import { CatalogImport } from "../../support/pages/catalog-import";

test.describe("Audit Log check for Catalog Plugin", () => {
let uiHelper: UIhelper;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect } from "@playwright/test";
import { exec } from "child_process";
import { Log } from "./Log";
import { execFile } from "child_process";
import { Log } from "./logs";

export class LogUtils {
/**
Expand All @@ -27,7 +27,7 @@ export class LogUtils {
* @param actual The actual value to compare
* @param expected The expected value
*/
private static compareValues(actual: any, expected: any) {
private static compareValues(actual: unknown, expected: unknown) {
if (typeof expected === "object" && expected !== null) {
Object.keys(expected).forEach((subKey) => {
const expectedSubValue = expected[subKey];
Expand All @@ -42,28 +42,25 @@ export class LogUtils {
}

/**
* Executes a shell command and returns the output as a promise.
* Executes a command and returns the output as a promise.
*
* @param command The shell command to execute
* @param command The command to execute
* @param args An array of arguments for the command
* @returns A promise that resolves with the command output
*/
static executeCommand(command: string): Promise<string> {
static executeCommand(command: string, args: string[] = []): Promise<string> {
return new Promise((resolve, reject) => {
exec(
command,
{ encoding: "utf8", shell: "/bin/bash" },
(error, stdout, stderr) => {
if (error) {
console.error("Error executing command:", error);
reject(`Error: ${error.message}`);
return;
}
if (stderr) {
console.warn("stderr warning:", stderr);
}
resolve(stdout);
},
);
execFile(command, args, { encoding: "utf8" }, (error, stdout, stderr) => {
if (error) {
console.error("Error executing command:", error);
reject(`Error: ${error.message}`);
return;
}
if (stderr) {
console.warn("stderr warning:", stderr);
}
resolve(stdout);
});
});
}

Expand All @@ -74,17 +71,38 @@ export class LogUtils {
* - app.kubernetes.io/instance=redhat-developer-hub
* - app.kubernetes.io/name=developer-hub
*
* @param grepFilter The string to filter the logs using grep
* @param filter The string to filter the logs
* @returns A promise that resolves with the filtered logs
*/
static async getPodLogsWithGrep(grepFilter: string): Promise<string> {
static async getPodLogsWithGrep(filter: string): Promise<string> {
const podSelector =
"app.kubernetes.io/component=backstage,app.kubernetes.io/instance=rhdh,app.kubernetes.io/name=backstage";
const tailNumber = 30;
const command = `oc logs -l ${podSelector} --tail=${tailNumber} -c backstage-backend -n ${process.env.NAME_SPACE} | grep "${grepFilter}" | head -n 1`;
console.log(command);
const namespace = process.env.NAME_SPACE || "default";

const args = [
"logs",
"-l",
podSelector,
`--tail=${tailNumber}`,
"-c",
"backstage-backend",
"-n",
namespace,
];

console.log("Executing command:", "oc", args.join(" "));

try {
return await LogUtils.executeCommand(command);
const output = await LogUtils.executeCommand("oc", args);

const logLines = output.split("\n");

const filteredLines = logLines.filter((line) => line.includes(filter));

const firstMatch = filteredLines[0] || "";

return firstMatch;
} catch (error) {
console.error("Error fetching logs:", error);
throw new Error(`Failed to fetch logs: ${error}`);
Expand All @@ -97,10 +115,21 @@ export class LogUtils {
* @returns A promise that resolves when the login is successful
*/
static async loginToOpenShift(): Promise<void> {
const command = `oc login --token="${process.env.K8S_CLUSTER_TOKEN}" --server="${process.env.K8S_CLUSTER_URL}"`;
const token = process.env.K8S_CLUSTER_TOKEN;
const server = process.env.K8S_CLUSTER_URL;

if (!token || !server) {
throw new Error(
"Environment variables K8S_CLUSTER_TOKEN and K8S_CLUSTER_URL must be set.",
);
}

const command = "oc";
const args = ["login", `--token=${token}`, `--server=${server}`];

try {
const result = await LogUtils.executeCommand(command);
console.log("Login successful:", result);
await LogUtils.executeCommand(command, args);
console.log("Login successful.");
} catch (error) {
console.error("Error during login:", error);
throw new Error(`Failed to login to OpenShift: ${error}`);
Expand Down
File renamed without changes.
8 changes: 4 additions & 4 deletions e2e-tests/playwright/e2e/audit-log/scaffold.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { test } from "@playwright/test";
import { Common } from "../../utils/Common";
import { UIhelper } from "../../utils/UIhelper";
import { LogUtils } from "./LogUtils";
import { CatalogImport } from "../../support/pages/CatalogImport";
import { Common } from "../../utils/common";
import { UIhelper } from "../../utils/ui-helper";
import { LogUtils } from "./log-utils";
import { CatalogImport } from "../../support/pages/catalog-import";

test.describe("Audit Log check for Catalog Plugin", () => {
let uiHelper: UIhelper;
Expand Down
28 changes: 14 additions & 14 deletions e2e-tests/playwright/e2e/authProviders/basic-authentication.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { test, Page, expect } from "@playwright/test";
import { Common, setupBrowser } from "../../utils/Common";
import { UIhelper } from "../../utils/UIhelper";
import { Common, setupBrowser } from "../../utils/common";
import { UIhelper } from "../../utils/ui-helper";
import * as constants from "../../utils/authenticationProviders/constants";
import { logger } from "../../utils/Logger";
import { upgradeHelmChartWithWait } from "../../utils/helper";
import { LOGGER } from "../../utils/logger";
import { HelmActions } from "../../utils/helm";

let page: Page;

Expand All @@ -18,19 +18,19 @@ test.describe("Standard authentication providers: Basic authentication", () => {
common = new Common(page);
uiHelper = new UIhelper(page);
expect(process.env.BASE_URL).not.toBeNull();
logger.info(`Base Url is ${process.env.BASE_URL}`);
logger.info(
LOGGER.info(`Base Url is ${process.env.BASE_URL}`);
LOGGER.info(
`Starting scenario: Standard authentication providers: Basic authentication: attemp #${testInfo.retry}`,
);
});

test("1. Verify guest login can work when no auth provider is configured (dangerouslyAllowSignInWithoutUserInCatalog is enabled by default but it should not conflict with the guest login).", async () => {
test.setTimeout(300 * 1000);
logger.info(
LOGGER.info(
"Executing testcase: Verify guest login can work when no auth provider is configured (dangerouslyAllowSignInWithoutUserInCatalog is enabled by default but it should not conflict with the guest login).",
);

await upgradeHelmChartWithWait(
await HelmActions.upgradeHelmChartWithWait(
constants.AUTH_PROVIDERS_RELEASE,
constants.AUTH_PROVIDERS_CHART,
constants.AUTH_PROVIDERS_NAMESPACE,
Expand Down Expand Up @@ -61,11 +61,11 @@ test.describe("Standard authentication providers: Basic authentication", () => {
// "Login failed; caused by Error: Sign in failed: users/groups have not been ingested into the catalog. Please refer to the authentication provider docs for more information on how to ingest users/groups to the catalog with the appropriate entity provider."

test.setTimeout(300 * 1000);
logger.info(
LOGGER.info(
"Executing testcase: Login should fail when an authProvider is configured without the ingester.",
);

await upgradeHelmChartWithWait(
await HelmActions.upgradeHelmChartWithWait(
constants.AUTH_PROVIDERS_RELEASE,
constants.AUTH_PROVIDERS_CHART,
constants.AUTH_PROVIDERS_NAMESPACE,
Expand Down Expand Up @@ -95,11 +95,11 @@ test.describe("Standard authentication providers: Basic authentication", () => {
// The Microsoft login should now be successful

test.setTimeout(300 * 1000);
logger.info(
LOGGER.info(
"Execute testcase: Set dangerouslyAllowSignInWithoutUserInCatalog to false. Login should now work but no User Entities are in the Catalog",
);

await upgradeHelmChartWithWait(
await HelmActions.upgradeHelmChartWithWait(
constants.AUTH_PROVIDERS_RELEASE,
constants.AUTH_PROVIDERS_CHART,
constants.AUTH_PROVIDERS_NAMESPACE,
Expand Down Expand Up @@ -137,11 +137,11 @@ test.describe("Standard authentication providers: Basic authentication", () => {
// The Microsoft login should now be successful

test.setTimeout(300 * 1000);
logger.info(
LOGGER.info(
"Execute testcase: Ensure Guest login is disabled when setting environment to production",
);

await upgradeHelmChartWithWait(
await HelmActions.upgradeHelmChartWithWait(
constants.AUTH_PROVIDERS_RELEASE,
constants.AUTH_PROVIDERS_CHART,
constants.AUTH_PROVIDERS_NAMESPACE,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { test } from "@playwright/test";
import * as constants from "../../utils/authenticationProviders/constants";
import { k8sClient } from "../../utils/helper";
import { KubeClient } from "../../utils/kube-client";

test.describe("Setup namespace and configure environment for RHDH", () => {
test("Delete namespace", async () => {
await k8sClient.deleteNamespaceAndWait(constants.AUTH_PROVIDERS_NAMESPACE);
await new KubeClient().deleteNamespaceAndWait(
constants.AUTH_PROVIDERS_NAMESPACE,
);
});
});
Loading

0 comments on commit 7a80e46

Please sign in to comment.