Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add required env variables for e2e telemetry tests to README #8341

Merged
merged 16 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
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
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ CHROME_EXTENSION_ID=mpjjildhmpddojocokjkgmlkkkfjnepo
# Shadow DOM mode for all components. Default is SHADOW_DOM=closed in regular webpack builds, open elsewhere
# SHADOW_DOM=open

# Enable telemetry in development. Default is false
# DEV_EVENT_TELEMETRY=true

# This makes all optional permissions required in the manifest.json to avoid permission popups. Only required for Playwright tests.
# REQUIRE_OPTIONAL_PERMISSIONS_IN_MANIFEST=1

Expand Down
4 changes: 3 additions & 1 deletion end-to-end-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ One-time setup:
- The test user password `E2E_TEST_USER_PASSWORD_UNAFFILIATED`
- Uncomment `REQUIRE_OPTIONAL_PERMISSIONS_IN_MANIFEST=1`
- Uncomment `SHADOW_DOM=open`
- Uncomment `DATADOG_CLIENT_TOKEN` (used for telemetry tests, can be set to a fake token, e.g. `secret123`)
mnholtz marked this conversation as resolved.
Show resolved Hide resolved
- Uncomment `DEV_EVENT_TELEMETRY` (used for telemetry tests, actual telemetry requests should be mocked during testing)
- `MV` will determine the manifest version for the both the extension and the tests (defaulted to 3 if not defined.)
- Install browsers: Execute `npx playwright install chromium chrome msedge`.

1. Install dependencies: Run `npm install`
2. Build the extension: Run: `npm run build:webpack` (or `npm run watch`)
2. Build the extension: Run: `npm run watch`
3. Run the tests: Use the command `npm run test:e2e`.

- To run tests in interactive UI mode, use `npm run test:e2e -- --ui`. This view shows you the entire test suite and
Expand Down
2 changes: 1 addition & 1 deletion end-to-end-tests/auth.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/

import { expect, type Page } from "@playwright/test";
import { test } from "./fixtures/authSetupFixture";
import { test } from "./fixtures/authSetup";
import {
E2E_TEST_USER_EMAIL_UNAFFILIATED,
E2E_TEST_USER_PASSWORD_UNAFFILIATED,
Expand Down
29 changes: 17 additions & 12 deletions end-to-end-tests/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const requiredEnvVariables = [
"SERVICE_URL",
"E2E_TEST_USER_EMAIL_UNAFFILIATED",
"E2E_TEST_USER_PASSWORD_UNAFFILIATED",
"SHADOW_DOM",
] as const;

// It's not strictly required for the test run itself, but the extension manifest.json must have been built with
Expand All @@ -45,20 +46,24 @@ type OptionalEnvVariables = Record<
string | undefined
>;

for (const key of requiredEnvVariables) {
// eslint-disable-next-line security/detect-object-injection -- key is a constant
if (process.env[key] === undefined) {
throw new Error(`Required environment variable is not configured: ${key}`);
}
export const assertRequiredEnvVariables = () => {
for (const key of requiredEnvVariables) {
// eslint-disable-next-line security/detect-object-injection -- key is a constant
if (process.env[key] === undefined) {
throw new Error(
`Required environment variable is not configured: ${key}`,
);
}

// eslint-disable-next-line security/detect-object-injection -- key is a constant
if (typeof process.env[key] !== "string") {
// For the time being we expect all of our requiredEnvVariables to be strings
throw new TypeError(
`Required environment variable is not configured: ${key}`,
);
// eslint-disable-next-line security/detect-object-injection -- key is a constant
if (typeof process.env[key] !== "string") {
// For the time being we expect all of our requiredEnvVariables to be strings
throw new TypeError(
`Required environment variable is not configured: ${key}`,
);
}
}
}
};

export const {
SERVICE_URL,
Expand Down
91 changes: 91 additions & 0 deletions end-to-end-tests/fixtures/authSetup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright (C) 2024 PixieBrix, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import {
test as base,
mergeTests,
type BrowserContext,
type Page,
} from "@playwright/test";
import {
getAuthProfilePathFile,
launchPersistentContextWithExtension,
} from "./utils";
import fs from "node:fs/promises";
import path from "node:path";
import * as os from "node:os";
import { test as envSetup } from "./envSetup";

// Create a local auth directory to store the profile paths
const createAuthProfilePathDirectory = async () => {
const authPath = path.join(__dirname, "../.auth");
try {
await fs.mkdir(authPath);
} catch (error) {
if (
!(error instanceof Error && "code" in error && error.code === "EEXIST")
) {
throw error;
}
}
};

export const test = mergeTests(
envSetup,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is unchanged except for wrapping this extend in mergeTests and adding the additionalRequiredEnvVariables override below.

base.extend<{
contextAndPage: { context: BrowserContext; page: Page };
chromiumChannel: "chrome" | "msedge";
additionalRequiredEnvVariables: string[];
}>({
chromiumChannel: ["chrome", { option: true }],
additionalRequiredEnvVariables: [
"REQUIRE_OPTIONAL_PERMISSIONS_IN_MANIFEST",
],
// Provides the context and the initial page together in the same fixture
async contextAndPage({ chromiumChannel }, use, testInfo) {
// Create a temp directory to store the test profile
const authSetupProfileDirectory = await fs.mkdtemp(
path.join(os.tmpdir(), "authSetup-"),
);

// Create a local auth directory to store the profile paths
await createAuthProfilePathDirectory();

const context = await launchPersistentContextWithExtension(
chromiumChannel,
authSetupProfileDirectory,
);

// The admin console automatically opens a new tab to log in and link the newly installed extension to the user's account.
const page = await context.waitForEvent("page", { timeout: 10_000 });

await use({ context, page });

// Store the profile path for future use if the auth setup test passes
if (testInfo.status === "passed") {
const authProfilePathFile = getAuthProfilePathFile(chromiumChannel);
await fs.writeFile(
authProfilePathFile,
authSetupProfileDirectory,
"utf8",
);
}

await context.close();
},
}),
);
85 changes: 0 additions & 85 deletions end-to-end-tests/fixtures/authSetupFixture.ts

This file was deleted.

41 changes: 41 additions & 0 deletions end-to-end-tests/fixtures/envSetup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2024 PixieBrix, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import { test as base } from "@playwright/test";
import { assertRequiredEnvVariables } from "../env";

export const test = base.extend<{
additionalRequiredEnvVariables: string[];
expectRequiredEnvVariables: () => void;
}>({
additionalRequiredEnvVariables: [],
expectRequiredEnvVariables: [
async ({ additionalRequiredEnvVariables }, use) => {
assertRequiredEnvVariables();

for (const key of additionalRequiredEnvVariables) {
if (process.env[key] === undefined) {
throw new Error(
`This test requires additional environment variable ${key} to be configured. Configure it in your .env.development file and re-build the extension.`,
);
}
}
await use(undefined);

Check failure on line 37 in end-to-end-tests/fixtures/envSetup.ts

View workflow job for this annotation

GitHub Actions / lint

Expected blank line before this statement

Check failure on line 37 in end-to-end-tests/fixtures/envSetup.ts

View workflow job for this annotation

GitHub Actions / lint

Do not use useless `undefined`
},
{ auto: true },
],
});
Loading
Loading