diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml new file mode 100644 index 0000000..b4401f3 --- /dev/null +++ b/.github/workflows/e2e-tests.yml @@ -0,0 +1,31 @@ +name: E2E tests + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: "1.21.7" + - uses: oven-sh/setup-bun@v2 + - run: go mod tidy + - run: cd reporters/golang && go mod tidy && cd ../.. + - run: cd reporters/javascript && bun install && bun run build && cd ../.. + - run: cd frontend && bun install && cd ../.. + - run: cd e2e-tests && bun install && bunx playwright install --with-deps chromium && cd ../.. + - run: cd e2e-tests && bun run test && cd ../.. + - uses: actions/upload-artifact@v4 + if: ${{ !cancelled() }} + with: + name: playwright-report + path: e2e-tests/playwright-report/ + retention-days: 3 diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml deleted file mode 100644 index 0b443f3..0000000 --- a/.github/workflows/go.yml +++ /dev/null @@ -1,28 +0,0 @@ -# This workflow will build a golang project -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go - -name: Go - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -jobs: - - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: '1.20' - - - name: Build - run: go build -v ./... - - - name: Test - run: go test -v ./... diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml deleted file mode 100644 index 57ccc13..0000000 --- a/.github/workflows/node.js.yml +++ /dev/null @@ -1,31 +0,0 @@ -# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs - -name: Node.js CI - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -jobs: - build: - - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [16.x, 18.x, 20.x, 22.x] - # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ - - steps: - - uses: actions/checkout@v4 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - cache: 'npm' - - run: npm ci - - run: npm run build --if-present - - run: npm test diff --git a/README.md b/README.md index 5d31b48..758b50a 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ In `e2e-tests` directory: ```bash bun install # install dependencies -bunx playwright install +bunx playwright install --with-deps chromium bun run test # run tests ``` diff --git a/e2e-tests/playwright.config.ts b/e2e-tests/playwright.config.ts index fa96668..65a17dc 100644 --- a/e2e-tests/playwright.config.ts +++ b/e2e-tests/playwright.config.ts @@ -1,4 +1,4 @@ -import { defineConfig, devices } from '@playwright/test'; +import { defineConfig, devices } from "@playwright/test"; /** * Read environment variables from file. @@ -10,31 +10,31 @@ import { defineConfig, devices } from '@playwright/test'; * See https://playwright.dev/docs/test-configuration. */ export default defineConfig({ - testDir: './tests', + testDir: "./tests", /* Run tests in files in parallel */ fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ forbidOnly: !!process.env.CI, /* Retry on CI only */ - retries: process.env.CI ? 2 : 0, + retries: process.env.CI ? 0 : 0, /* Opt out of parallel tests on CI. */ workers: process.env.CI ? 1 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'html', + reporter: "html", /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ // baseURL: 'http://127.0.0.1:3000', /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', + trace: "on-first-retry", }, /* Configure projects for major browsers */ projects: [ { - name: 'chromium', - use: { ...devices['Desktop Chrome'] }, + name: "chromium", + use: { ...devices["Desktop Chrome"] }, }, // { diff --git a/e2e-tests/tests/javascript-server/javascript-server-bulk.spec.ts b/e2e-tests/tests/javascript-server/javascript-server-bulk.spec.ts index 164bbcc..7214782 100644 --- a/e2e-tests/tests/javascript-server/javascript-server-bulk.spec.ts +++ b/e2e-tests/tests/javascript-server/javascript-server-bulk.spec.ts @@ -21,7 +21,7 @@ test("send 100 events from JS server", async ({ page }) => { const COUNT = 100; - await exec(`node count.js ${TEST_NAME} ${COUNT}`, { + await exec(`bun count.js ${TEST_NAME} ${COUNT}`, { env: { ...process.env, TT_TOKEN: TOKEN, TT_SERVER_URL: `ws://localhost:${serverPort}` }, cwd: path.join(__dirname, "reporter"), }); diff --git a/e2e-tests/tests/javascript-server/javascript-server.spec.ts b/e2e-tests/tests/javascript-server/javascript-server.spec.ts index 9efd552..27085e8 100644 --- a/e2e-tests/tests/javascript-server/javascript-server.spec.ts +++ b/e2e-tests/tests/javascript-server/javascript-server.spec.ts @@ -1,5 +1,5 @@ import { expect, test } from "@playwright/test"; -import { runServer } from "../utils"; +import { runServer, sleep } from "../utils"; import child_process from "child_process"; import util from "util"; import path from "path"; @@ -20,11 +20,17 @@ test("send hello from JS server", async ({ page }) => { await page.getByPlaceholder("Enter session ID").fill(TOKEN); await page.getByRole("button", { name: "Go" }).click(); - await exec(`node hello.js ${TEST_NAME}`, { + const result = await exec(`bun hello.js ${TEST_NAME}`, { env: { ...process.env, TT_TOKEN: TOKEN, TT_SERVER_URL: `ws://localhost:${serverPort}` }, cwd: path.join(__dirname, "reporter"), }); + if (process.env["DEBUG"]) { + console.log("Reporter output: "); + console.log(result.stdout); + console.error(result.stderr); + } + await expect(page.getByText(`hello ${TEST_NAME}`)).toBeVisible(); }); diff --git a/e2e-tests/tests/utils.ts b/e2e-tests/tests/utils.ts index 4a01be8..ba65390 100644 --- a/e2e-tests/tests/utils.ts +++ b/e2e-tests/tests/utils.ts @@ -1,5 +1,5 @@ import path from "path"; -import { Readable } from "stream"; +import { PassThrough, Readable } from "stream"; import freeports from "find-free-ports"; import { ChildProcess, exec } from "child_process"; @@ -36,9 +36,17 @@ export async function runServer(startPort: number): Promise<[ChildProcess, numbe env: { ...process.env, PORT: serverPort.toString(), LOCAL: "true", DISABLE_METRICS: "true" }, cwd: rootDir, }); + + const out = new PassThrough(); + serverProcess.stdout?.pipe(out); + serverProcess.stdout?.pipe(process.stdout); serverProcess.stderr?.pipe(process.stderr); - await waitForString("Listening", serverProcess.stdout!); + await waitForString("Listening", out); + + if (process.env["DEBUG"]) { + console.log(`Server started on port ${serverPort}`); + } return [serverProcess, serverPort]; } diff --git a/reporters/javascript/src/crypto.ts b/reporters/javascript/src/crypto.ts index 8137b62..2269709 100644 --- a/reporters/javascript/src/crypto.ts +++ b/reporters/javascript/src/crypto.ts @@ -1,3 +1,14 @@ +let cachedNodeCrypto: Crypto | undefined; + +const loadCrypto = async () => { + if (globalThis?.crypto) return globalThis.crypto; + try { + return (cachedNodeCrypto ||= (await import("node:crypto")).webcrypto as Crypto); + } catch (error) { + throw new Error("Failed to load crypto"); + } +}; + /** * Encrypts plaintext using AES-GCM with supplied password, for decryption with aes_gcm_decrypt() * @@ -6,6 +17,7 @@ * @returns {Promise} encrypted cipher text */ export async function encrypt(plaintext: string, password: string): Promise { + const crypto = await loadCrypto(); // encode password as UTF-8 const pwUtf8 = new TextEncoder().encode(password); // hash the password @@ -68,6 +80,8 @@ export async function decrypt(ciphertext: string, password: string): Promise { + const crypto = await loadCrypto(); + // encode as UTF-8 const msgBuffer = new TextEncoder().encode(message);