diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6074379..611049c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -5,12 +5,6 @@ on: release: types: [published] -env: - LOCAL-NOTARY: true - LOCAL-WS: false - HEADLESS: true - PUPPETEER_SKIP_DOWNLOAD: true - jobs: build-and-test: name: Build and test @@ -37,7 +31,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 cache: 'npm' - name: Install stable nightly toolchain @@ -61,27 +55,18 @@ jobs: - name: Build run: npm run build - + - name: Lint run: npm run lint - - - name: Install Chrome - uses: browser-actions/setup-chrome@v1 - id: setup-chrome - with: - chrome-version: 121.0.6167.85 - - name: Set CHROME_PATH environment variable - run: echo "CHROME_PATH=${{ steps.setup-chrome.outputs['chrome-path'] }}" >> $GITHUB_ENV + - name: install wstcp + run: cargo install wstcp + + - name: Install Chromium (Playwright) + run: npx playwright install --with-deps chromium - name: Test - run: | - # Install wstcp and use it in the background - cargo install wstcp - wstcp --bind-addr 127.0.0.1:55688 raw.githubusercontent.com:443 & - WSTCP_PID=$! - trap "kill $WSTCP_PID" EXIT - npm run test + run: npm run test - name: Determine release type (dry-run or publish) run: | diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 0000000..24353ee --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,54 @@ +name: Tests demos +on: + pull_request: +jobs: + test: + timeout-minutes: 60 + name: Tests demos + runs-on: ubuntu-latest + services: + notary-server: + image: ghcr.io/tlsnotary/tlsn/notary-server:v0.1.0-alpha.10 + env: + NOTARY_SERVER__TLS__ENABLED: false + ports: + - 7047:7047 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: lts/* + - name: build tlsn-js + run: npm ci; npm run build + - name: install wstcp + run: cargo install wstcp + - name: Install Chromium (Playwright) + run: npx playwright install --with-deps chromium + - name: Test react demo + working-directory: demo/react-ts-webpack + continue-on-error: true + run: | + set -e + npm i + npm run test + - name: Test interactive verifier demo + continue-on-error: true + run: | + set -e + cd demo/interactive-demo/verifier-rs + cargo build --release + cd ../prover-ts + npm i + npm run test + - name: Test web-to-web p2p demo + working-directory: demo/react-ts-webpack + continue-on-error: true + run: | + set -e + npm run test + - uses: actions/upload-artifact@v4 + if: ${{ !cancelled() }} + with: + name: playwright-report + path: '**/playwright-report/' + retention-days: 30 diff --git a/.gitignore b/.gitignore index 287d1b4..7760288 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,10 @@ dev-build/ test-build/ ./demo/node_modules utils/tlsn -.vscode \ No newline at end of file +.vscode + +# Playwright +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/demo/interactive-demo/README.md b/demo/interactive-demo/README.md index 18ebfac..491de45 100644 --- a/demo/interactive-demo/README.md +++ b/demo/interactive-demo/README.md @@ -1,38 +1,59 @@ -# Test Rust Prover - -1. Start the verifier: -```bash -cd verifier-rs; cargo run --release -``` -2. Run the prover: -```bash -cd prover-rs; cargo run --release -``` - -# Test Browser Prover -1. Start the verifier: -```bash -cd verifier-rs; cargo run --release -``` -2. Since a web browser doesn't have the ability to make TCP connection, we need to use a websocket proxy server to access . -```bash -cargo install wstcp - -wstcp --bind-addr 127.0.0.1:55688 raw.githubusercontent.com:443 -``` -3. Run the prover - 1. Build tlsn-js +# Interactive Verifier Demo + +This demo shows how to use TLSNotary **without a notary**: a direct proof between a prover and a verifier, where the verifier checks both the TLS session and the revealed data. + +There are two prover implementations: +- **Rust** +- **TypeScript** (browser) +The verifier is implemented in Rust. + +--- + +## Interactive Verifier Demo with Rust Prover + +1. **Start the verifier:** + ```bash + cd verifier-rs + cargo run --release + ``` +2. **Run the prover:** + ```bash + cd prover-rs + cargo run --release + ``` + +--- + +## Interactive Verifier Demo with TypeScript Prover (Browser) + +1. **Start the verifier:** + ```bash + cd verifier-rs + cargo run --release + ``` +2. **Set up a websocket proxy for raw.githubusercontent.com** + Browsers cannot make raw TCP connections, so a websocket proxy is required: + ```bash + cargo install wstcp + wstcp --bind-addr 127.0.0.1:55688 raw.githubusercontent.com:443 + ``` +3. **Run the prover in the browser:** + 1. **Build tlsn-js** ```bash cd .. - npm i + npm install npm run build - npm link ``` - 2. Build demo prover-ts + 2. **Build and start the TypeScript prover demo** ```bash cd prover-ts - npm i - npm link + npm install npm run dev ``` - 3. Open and click **Start Prover** + 3. **Open the demo in your browser:** + Go to [http://localhost:8080/](http://localhost:8080/) and click **Start Prover**. + +--- + +**Tip:** +If you encounter issues, make sure all dependencies are installed and the websocket proxy is running before starting the browser demo. diff --git a/demo/interactive-demo/prover-ts/.gitignore b/demo/interactive-demo/prover-ts/.gitignore index d8b83df..d23165c 100644 --- a/demo/interactive-demo/prover-ts/.gitignore +++ b/demo/interactive-demo/prover-ts/.gitignore @@ -1 +1,8 @@ package-lock.json + +# Playwright +node_modules/ +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/demo/interactive-demo/prover-ts/index.ejs b/demo/interactive-demo/prover-ts/index.ejs index c39083c..6335dff 100644 --- a/demo/interactive-demo/prover-ts/index.ejs +++ b/demo/interactive-demo/prover-ts/index.ejs @@ -4,7 +4,7 @@ - React/Typescript Example + TLSNotary React TypeScript Demo diff --git a/demo/interactive-demo/prover-ts/package.json b/demo/interactive-demo/prover-ts/package.json index 96eac21..f4b3879 100644 --- a/demo/interactive-demo/prover-ts/package.json +++ b/demo/interactive-demo/prover-ts/package.json @@ -4,7 +4,9 @@ "description": "", "main": "webpack.js", "scripts": { - "dev": "webpack-dev-server --config webpack.js" + "dev": "webpack-dev-server --config webpack.js", + "start": "webpack serve --config webpack.js", + "test": "npx playwright test" }, "author": "", "license": "ISC", diff --git a/demo/interactive-demo/prover-ts/playwright.config.ts b/demo/interactive-demo/prover-ts/playwright.config.ts new file mode 100644 index 0000000..def8f9c --- /dev/null +++ b/demo/interactive-demo/prover-ts/playwright.config.ts @@ -0,0 +1,90 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// import dotenv from 'dotenv'; +// import path from 'path'; +// dotenv.config({ path: path.resolve(__dirname, '.env') }); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + 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, + /* 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', + /* 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://localhost:8080', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + // { + // 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://localhost:8080', + reuseExistingServer: !process.env.CI, + }, + { + command: 'wstcp --bind-addr 127.0.0.1:55688 raw.githubusercontent.com:443', + reuseExistingServer: true, + }, + { + command: 'cargo run --release', + cwd: '../verifier-rs', + reuseExistingServer: true, + } + ] +}); diff --git a/demo/interactive-demo/prover-ts/src/app.tsx b/demo/interactive-demo/prover-ts/src/app.tsx index db22bb8..329d3bd 100644 --- a/demo/interactive-demo/prover-ts/src/app.tsx +++ b/demo/interactive-demo/prover-ts/src/app.tsx @@ -224,7 +224,7 @@ function App(): ReactElement { ) : (
-
+            
               {JSON.stringify(result, null, 2)}
             
diff --git a/demo/interactive-demo/prover-ts/tests/demo-flow.spec.ts b/demo/interactive-demo/prover-ts/tests/demo-flow.spec.ts new file mode 100644 index 0000000..9970648 --- /dev/null +++ b/demo/interactive-demo/prover-ts/tests/demo-flow.spec.ts @@ -0,0 +1,16 @@ +import { test, expect } from '@playwright/test'; + +test('has title', async ({ page }) => { + await page.goto('/'); + await expect(page).toHaveTitle(/TLSNotary/) +}); + +test('run demo', async ({ page }) => { + await page.goto('/'); + + // Click the get started link. + await page.getByRole('button', { name: 'Start Prover' }).click(); + + await expect(page.getByTestId('proof-data')).toContainText('Unredacted data successfully revealed to Verifier', { timeout: 60000 }); + +}); \ No newline at end of file diff --git a/demo/react-ts-webpack/.gitignore b/demo/react-ts-webpack/.gitignore index d8b83df..d23165c 100644 --- a/demo/react-ts-webpack/.gitignore +++ b/demo/react-ts-webpack/.gitignore @@ -1 +1,8 @@ package-lock.json + +# Playwright +node_modules/ +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/demo/react-ts-webpack/README.md b/demo/react-ts-webpack/README.md new file mode 100644 index 0000000..b1616db --- /dev/null +++ b/demo/react-ts-webpack/README.md @@ -0,0 +1,79 @@ +# TLSNotary in React/TypeScript with `tlsn-js` + +This demo shows how to use TLSNotary with a delegated verifier, also known as a **notary**. +In this demo, we request JSON data from a GitHub page, use `tlsn-js` to notarize the TLS request with TLSNotary, and display the attestation and revealed data. + +> **Note:** +> This demo uses TLSNotary to notarize **public** data for simplicity. In real-world applications, TLSNotary is especially valuable for notarizing private and sensitive data. + +--- + +## Setup + +Before running the demo, you need to start a local notary server and a websocket proxy. If you prefer to use the hosted test servers from PSE, see the section below. + +### Websocket Proxy + +Browsers cannot make raw TCP connections, so a websocket proxy server is required. + +1. **Install [wstcp](https://github.com/sile/wstcp):** + ```sh + cargo install wstcp + ``` +2. **Run a websocket proxy for `https://raw.githubusercontent.com`:** + ```sh + wstcp --bind-addr 127.0.0.1:55688 raw.githubusercontent.com:443 + ``` + > Note: The `raw.githubusercontent.com:443` argument specifies the server used in this quick start. + +### Run a Local Notary Server + +You also need to run a local notary server for this demo. + +- **Using Git and Rust Cargo:** + ```sh + git clone https://github.com/tlsnotary/tlsn.git + cargo run --release --bin notary-server + ``` +- **Using Docker (from the root of the tlsn-js repo):** + ```sh + npm run notary + ``` + +The notary server will now be running in the background, waiting for connections. + +--- + +### Use the PSE Web Proxy and Notary + +If you want to use the hosted PSE notary and proxy: + +1. Open `app.tsx` in your editor. +2. Replace the notary URL: + ```ts + notaryUrl: 'https://notary.pse.dev/v0.1.0-alpha.10', + ``` + This uses the [PSE](https://pse.dev) notary server to notarize the API request. You can use a different or [local notary](#run-a-local-notary-server); a local server will be faster due to the high bandwidth and low network latency. +3. Replace the websocket proxy URL: + ```ts + websocketProxyUrl: 'wss://notary.pse.dev/proxy?token=raw.githubusercontent.com', + ``` + This uses a proxy hosted by [PSE](https://pse.dev). You can use a different or local proxy if you prefer. + +--- + +## Run the Demo + +1. **Install dependencies:** + ```sh + npm i + ``` +2. **Start the Webpack Dev Server:** + ```sh + npm run dev + ``` +3. **Open the demo in your browser:** + Go to [http://localhost:8080](http://localhost:8080) +4. **Click the "Start demo" button** +5. **Open Developer Tools** and monitor the console logs +œœ \ No newline at end of file diff --git a/demo/react-ts-webpack/index.ejs b/demo/react-ts-webpack/index.ejs index 7bd6dac..6335dff 100644 --- a/demo/react-ts-webpack/index.ejs +++ b/demo/react-ts-webpack/index.ejs @@ -4,13 +4,13 @@ - React/Typescrip Example + TLSNotary React TypeScript Demo - -
+ +
\ No newline at end of file diff --git a/demo/react-ts-webpack/package.json b/demo/react-ts-webpack/package.json index 6061910..1c6a8f2 100644 --- a/demo/react-ts-webpack/package.json +++ b/demo/react-ts-webpack/package.json @@ -5,16 +5,18 @@ "main": "webpack.js", "scripts": { "dev": "webpack-dev-server --config webpack.js", - "build": "webpack --config webpack.js" + "build": "webpack --config webpack.js", + "start": "webpack serve --config webpack.js", + "test": "npx playwright test" }, "author": "", "license": "ISC", "dependencies": { "comlink": "^4.4.1", "css-loader": "^7.1.2", + "http-parser-js": "^0.5.9", "postcss": "^8.4.49", "postcss-loader": "^8.1.1", - "http-parser-js": "^0.5.9", "react": "^18.2.0", "react-dom": "^18.2.0", "react-loader-spinner": "^6.1.6", @@ -25,6 +27,8 @@ "tlsn-js": "../../" }, "devDependencies": { + "@playwright/test": "^1.52.0", + "@types/node": "^22.15.18", "@types/react": "^18.0.26", "@types/react-dom": "^18.0.10", "babel-loader": "^9.1.3", @@ -41,4 +45,4 @@ "webpack-cli": "^4.10.0", "webpack-dev-server": "^4.11.1" } -} +} \ No newline at end of file diff --git a/demo/react-ts-webpack/playwright.config.ts b/demo/react-ts-webpack/playwright.config.ts new file mode 100644 index 0000000..4fd339c --- /dev/null +++ b/demo/react-ts-webpack/playwright.config.ts @@ -0,0 +1,85 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// import dotenv from 'dotenv'; +// import path from 'path'; +// dotenv.config({ path: path.resolve(__dirname, '.env') }); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + 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, + /* 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', + /* 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://localhost:8080', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + // { + // 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://localhost:8080', + reuseExistingServer: !process.env.CI, + }, + { + command: 'wstcp --bind-addr 127.0.0.1:55688 raw.githubusercontent.com:443', + reuseExistingServer: true, + } + ] +}); diff --git a/demo/react-ts-webpack/src/app.tsx b/demo/react-ts-webpack/src/app.tsx index 0debe0c..3abfdab 100644 --- a/demo/react-ts-webpack/src/app.tsx +++ b/demo/react-ts-webpack/src/app.tsx @@ -140,6 +140,7 @@ function App(): ReactElement { const proof = await (Prover.notarize as typeof TProver.notarize)({ notaryUrl: notaryUrl, websocketProxyUrl: websocketProxyUrl, + maxRecvData: 2048, url: serverUrl, method: 'GET', headers: { @@ -285,7 +286,7 @@ function App(): ReactElement { View Proof -
@@ -301,7 +302,7 @@ function App(): ReactElement {
           ) : !result ? (
             verifying
           ) : (
-            
diff --git a/demo/react-ts-webpack/tests/demo-flow.spec.ts b/demo/react-ts-webpack/tests/demo-flow.spec.ts
new file mode 100644
index 0000000..6892be5
--- /dev/null
+++ b/demo/react-ts-webpack/tests/demo-flow.spec.ts
@@ -0,0 +1,36 @@
+import { test, expect } from '@playwright/test';
+
+test('has title', async ({ page }) => {
+  await page.goto('/');
+  await expect(page).toHaveTitle(/TLSNotary React TypeScript Demo/)
+});
+
+test('run demo (normal)', async ({ page }) => {
+  test.setTimeout(60000);
+  await page.goto('/');
+
+  // Click the get started link.
+  await page.getByRole('button', { name: 'Start Demo (Normal config)' }).click();
+
+  await expect(page.getByTestId('proof-data')).toContainText('"data":', { timeout: 60000 });
+
+  let verify_data = await page.getByTestId('verify-data').innerText();
+  expect(verify_data).toContain('"serverName": "raw.githubusercontent.com"');
+  expect(verify_data).toContain('John Doe');
+});
+
+test('run demo (helper)', async ({ page }) => {
+  test.setTimeout(60000);
+  await page.goto('/');
+
+  // Click the get started link.
+  await page.getByRole('button', { name: 'Start Demo 2 (With helper method)' }).click();
+
+  await expect(page.getByTestId('proof-data')).toContainText('"data":', { timeout: 60000 });
+
+  // await page.screenshot({ path: 'screenshot.png', fullPage: true });
+
+  let verify_data = await page.getByTestId('verify-data').innerText();
+  expect(verify_data).toContain('"serverName": "raw.githubusercontent.com"');
+  expect(verify_data).toContain('"recv"');
+});
\ No newline at end of file
diff --git a/demo/web-to-web-p2p/.gitignore b/demo/web-to-web-p2p/.gitignore
index d8b83df..d23165c 100644
--- a/demo/web-to-web-p2p/.gitignore
+++ b/demo/web-to-web-p2p/.gitignore
@@ -1 +1,8 @@
 package-lock.json
+
+# Playwright
+node_modules/
+/test-results/
+/playwright-report/
+/blob-report/
+/playwright/.cache/
diff --git a/demo/web-to-web-p2p/README.md b/demo/web-to-web-p2p/README.md
index f414d33..a41d253 100644
--- a/demo/web-to-web-p2p/README.md
+++ b/demo/web-to-web-p2p/README.md
@@ -12,7 +12,7 @@ In this demo, the two web clients run in the same browser page (`./src/app.tsx`)
     npm i
     npm run dev
 ```
-2. Open 
+2. Open 
 3. Click the **Start Demo** button
 
 The Prover window logs the Prover's output, the Verifier logs the Verifier's output. In the console view you can see the websocket log.
diff --git a/demo/web-to-web-p2p/index.ejs b/demo/web-to-web-p2p/index.ejs
index 7bd6dac..02bc4eb 100644
--- a/demo/web-to-web-p2p/index.ejs
+++ b/demo/web-to-web-p2p/index.ejs
@@ -4,13 +4,13 @@
 
     
     
-    React/Typescrip Example
+    Web-to-Web P2P Demo
 
 
 
-
-
+ +
\ No newline at end of file diff --git a/demo/web-to-web-p2p/package.json b/demo/web-to-web-p2p/package.json index 0b6c7a9..7e06daf 100644 --- a/demo/web-to-web-p2p/package.json +++ b/demo/web-to-web-p2p/package.json @@ -7,7 +7,9 @@ "dev:server": "node ./server/index.js", "dev:ui": "webpack-dev-server --config webpack.js", "dev": "concurrently npm:dev:ui npm:dev:server", - "build": "webpack --config webpack.js" + "build": "webpack --config webpack.js", + "start:ui": "webpack serve --config webpack.js", + "test": "npm run build && npx playwright test" }, "author": "", "license": "ISC", @@ -45,4 +47,4 @@ "webpack-cli": "^4.10.0", "webpack-dev-server": "^4.11.1" } -} +} \ No newline at end of file diff --git a/demo/web-to-web-p2p/playwright.config.ts b/demo/web-to-web-p2p/playwright.config.ts new file mode 100644 index 0000000..05841f9 --- /dev/null +++ b/demo/web-to-web-p2p/playwright.config.ts @@ -0,0 +1,90 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// import dotenv from 'dotenv'; +// import path from 'path'; +// dotenv.config({ path: path.resolve(__dirname, '.env') }); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + 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, + /* 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', + /* 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://localhost:8080', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + // { + // 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:ui', + url: 'http://localhost:8080', + reuseExistingServer: !process.env.CI, + }, + { + command: 'wstcp --bind-addr 127.0.0.1:55688 raw.githubusercontent.com:443', + reuseExistingServer: true, + }, + { + command: 'node ./server/index.js', + port: 3001, + reuseExistingServer: !process.env.CI, + } + ] +}); diff --git a/demo/web-to-web-p2p/src/app.tsx b/demo/web-to-web-p2p/src/app.tsx index d9746db..a265dd4 100644 --- a/demo/web-to-web-p2p/src/app.tsx +++ b/demo/web-to-web-p2p/src/app.tsx @@ -243,6 +243,7 @@ function App(): ReactElement { {proverMessages.map((m, index) => ( {m} @@ -257,6 +258,7 @@ function App(): ReactElement { {verifierMessages.map((m, index) => ( {m} @@ -271,7 +273,7 @@ function App(): ReactElement { disabled={!ready || started} onClick={start} > -
+
{ready && !started ? ( <>Start Demo ) : ( diff --git a/demo/web-to-web-p2p/tests/demo-flow.spec.ts b/demo/web-to-web-p2p/tests/demo-flow.spec.ts new file mode 100644 index 0000000..b35b744 --- /dev/null +++ b/demo/web-to-web-p2p/tests/demo-flow.spec.ts @@ -0,0 +1,24 @@ +import { test, expect } from '@playwright/test'; + +test('has title', async ({ page }) => { + await page.goto('/'); + await expect(page).toHaveTitle(/Web-to-Web P2P Demo/) +}); + +test('run web-to-web p2p demo', async ({ page }) => { + await page.goto('/'); + + await page.getByTestId('start').click(); + + await expect(page.getByTestId('start')).toContainText('Start Demo', { timeout: 60000 }); + + const proverMessages = await page.getByTestId('prover-data').allTextContents(); + expect(proverMessages.some(text => text.includes('Transcript received'))).toBe(true); + // console.log('Verifier Messages:', proverMessages); + expect(proverMessages.some(text => text.includes('"name": "John Doe",'))).toBe(true); + expect(proverMessages.some(text => text.includes('"address": {'))).toBe(true); + + const verifierMessages = await page.getByTestId('verifier-data').allTextContents(); + expect(verifierMessages.some(text => text.includes('Verification completed'))).toBe(true); + expect(verifierMessages.some(text => text.includes('***"name": "John Doe"*************************"street": "123 Elm Street"***'))).toBe(true); +}); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 5a12c88..2696b51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,8 @@ "tlsn-wasm": "0.1.0-alpha.10" }, "devDependencies": { - "@types/mocha": "^10.0.6", + "@playwright/test": "^1.52.0", + "@types/node": "^22.15.18", "@types/serve-handler": "^6.1.4", "browserify": "^17.0.0", "buffer": "^6.0.3", @@ -30,16 +31,13 @@ "https-browserify": "^1.0.0", "image-webpack-loader": "^6.0.0", "js-yaml": "^4.1.0", - "mocha": "^10.2.0", "node-loader": "^0.6.0", "prettier": "^3.0.2", "process": "^0.11.10", - "puppeteer": "^24.1.0", "serve": "14.2.1", "serve-handler": "^6.1.5", "stream-browserify": "^3.0.0", "ts-loader": "^6.2.1", - "ts-mocha": "^10.0.0", "ts-node": "^10.9.2", "typescript": "^4.9.5", "typescript-eslint": "^7.4.0", @@ -52,27 +50,6 @@ "node": ">= 16.20.2" } }, - "node_modules/@babel/code-frame": { - "version": "7.26.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/runtime": { "version": "7.26.9", "dev": true, @@ -306,147 +283,22 @@ "url": "https://opencollective.com/unts" } }, - "node_modules/@puppeteer/browsers": { - "version": "2.8.0", + "node_modules/@playwright/test": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.52.0.tgz", + "integrity": "sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==", "dev": true, "license": "Apache-2.0", "dependencies": { - "debug": "^4.4.0", - "extract-zip": "^2.0.1", - "progress": "^2.0.3", - "proxy-agent": "^6.5.0", - "semver": "^7.7.1", - "tar-fs": "^3.0.8", - "yargs": "^17.7.2" + "playwright": "1.52.0" }, "bin": { - "browsers": "lib/cjs/main-cli.js" + "playwright": "cli.js" }, "engines": { "node": ">=18" } }, - "node_modules/@puppeteer/browsers/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@puppeteer/browsers/node_modules/cliui": { - "version": "8.0.1", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@puppeteer/browsers/node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@puppeteer/browsers/node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/@puppeteer/browsers/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@puppeteer/browsers/node_modules/semver": { - "version": "7.7.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@puppeteer/browsers/node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@puppeteer/browsers/node_modules/wrap-ansi": { - "version": "7.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@puppeteer/browsers/node_modules/y18n": { - "version": "5.0.8", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/@puppeteer/browsers/node_modules/yargs": { - "version": "17.7.2", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@puppeteer/browsers/node_modules/yargs-parser": { - "version": "21.1.1", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/@sindresorhus/is": { "version": "0.7.0", "dev": true, @@ -456,11 +308,6 @@ "node": ">=4" } }, - "node_modules/@tootallnate/quickjs-emscripten": { - "version": "0.23.0", - "dev": true, - "license": "MIT" - }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "dev": true, @@ -603,12 +450,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/json5": { - "version": "0.0.29", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/@types/mime": { "version": "1.3.5", "dev": true, @@ -619,17 +460,14 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/mocha": { - "version": "10.0.10", - "dev": true, - "license": "MIT" - }, "node_modules/@types/node": { - "version": "22.13.10", + "version": "22.15.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.18.tgz", + "integrity": "sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "undici-types": "~6.21.0" } }, "node_modules/@types/node-forge": { @@ -712,15 +550,6 @@ "@types/node": "*" } }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "7.18.0", "dev": true, @@ -1218,14 +1047,6 @@ "node": ">=0.4.0" } }, - "node_modules/agent-base": { - "version": "7.1.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, "node_modules/ajv": { "version": "6.12.6", "dev": true, @@ -1311,14 +1132,6 @@ "node": ">=8" } }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/ansi-html-community": { "version": "0.0.8", "dev": true, @@ -1483,14 +1296,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/arrify": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/asn1.js": { "version": "4.10.1", "dev": true, @@ -1528,17 +1333,6 @@ "inherits": "2.0.3" } }, - "node_modules/ast-types": { - "version": "0.13.4", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/async-function": { "version": "1.0.0", "dev": true, @@ -1562,75 +1356,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/b4a": { - "version": "1.6.7", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/balanced-match": { "version": "1.0.2", "dev": true, "license": "MIT" }, - "node_modules/bare-events": { - "version": "2.5.4", - "dev": true, - "license": "Apache-2.0", - "optional": true - }, - "node_modules/bare-fs": { - "version": "4.0.1", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "bare-events": "^2.0.0", - "bare-path": "^3.0.0", - "bare-stream": "^2.0.0" - }, - "engines": { - "bare": ">=1.7.0" - } - }, - "node_modules/bare-os": { - "version": "3.6.0", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "engines": { - "bare": ">=1.14.0" - } - }, - "node_modules/bare-path": { - "version": "3.0.0", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "bare-os": "^3.0.1" - } - }, - "node_modules/bare-stream": { - "version": "2.6.5", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "streamx": "^2.21.0" - }, - "peerDependencies": { - "bare-buffer": "*", - "bare-events": "*" - }, - "peerDependenciesMeta": { - "bare-buffer": { - "optional": true - }, - "bare-events": { - "optional": true - } - } - }, "node_modules/base64-js": { "version": "1.5.1", "dev": true, @@ -1650,14 +1380,6 @@ ], "license": "MIT" }, - "node_modules/basic-ftp": { - "version": "5.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/batch": { "version": "0.6.1", "dev": true, @@ -2184,11 +1906,6 @@ "resolve": "^1.17.0" } }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "dev": true, - "license": "ISC" - }, "node_modules/browserify": { "version": "17.0.1", "dev": true, @@ -2408,6 +2125,7 @@ "version": "0.2.13", "dev": true, "license": "MIT", + "optional": true, "engines": { "node": "*" } @@ -2757,18 +2475,6 @@ "node": ">=6.0" } }, - "node_modules/chromium-bidi": { - "version": "2.1.2", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "mitt": "^3.0.1", - "zod": "^3.24.1" - }, - "peerDependencies": { - "devtools-protocol": "*" - } - }, "node_modules/cipher-base": { "version": "1.0.6", "dev": true, @@ -3212,31 +2918,6 @@ "dev": true, "license": "MIT" }, - "node_modules/cosmiconfig": { - "version": "9.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/create-ecdh": { "version": "4.0.4", "dev": true, @@ -3448,14 +3129,6 @@ "dev": true, "license": "Apache-2.0" }, - "node_modules/data-uri-to-buffer": { - "version": "6.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, "node_modules/data-view-buffer": { "version": "1.0.2", "dev": true, @@ -3860,19 +3533,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/degenerator": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ast-types": "^0.13.4", - "escodegen": "^2.1.0", - "esprima": "^4.0.1" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/depd": { "version": "2.0.0", "dev": true, @@ -3934,21 +3594,8 @@ "node": ">=0.8.0" } }, - "node_modules/devtools-protocol": { - "version": "0.0.1413902", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/diff": { - "version": "5.2.0", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/diffie-hellman": { - "version": "5.0.3", + "node_modules/diffie-hellman": { + "version": "5.0.3", "dev": true, "license": "MIT", "dependencies": { @@ -4201,6 +3848,7 @@ "version": "1.4.4", "dev": true, "license": "MIT", + "optional": true, "dependencies": { "once": "^1.4.0" } @@ -4233,14 +3881,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/env-paths": { - "version": "2.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/envinfo": { "version": "7.14.0", "dev": true, @@ -4427,35 +4067,6 @@ "node": ">=0.8.0" } }, - "node_modules/escodegen": { - "version": "2.1.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/escodegen/node_modules/source-map": { - "version": "0.6.1", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/eslint": { "version": "8.57.1", "dev": true, @@ -4671,6 +4282,7 @@ "version": "4.0.1", "dev": true, "license": "BSD-2-Clause", + "optional": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -4972,39 +4584,6 @@ "node": ">=4" } }, - "node_modules/extract-zip": { - "version": "2.0.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/extract-zip/node_modules/get-stream": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "dev": true, @@ -5015,11 +4594,6 @@ "dev": true, "license": "Apache-2.0" }, - "node_modules/fast-fifo": { - "version": "1.3.2", - "dev": true, - "license": "MIT" - }, "node_modules/fast-glob": { "version": "3.3.3", "dev": true, @@ -5133,6 +4707,7 @@ "version": "1.1.0", "dev": true, "license": "MIT", + "optional": true, "dependencies": { "pend": "~1.2.0" } @@ -5555,19 +5130,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-uri": { - "version": "6.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "basic-ftp": "^5.0.2", - "data-uri-to-buffer": "^6.0.2", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/gifsicle": { "version": "4.0.1", "dev": true, @@ -6115,18 +5677,6 @@ "node": ">=8.0.0" } }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/http-proxy-middleware": { "version": "2.0.7", "dev": true, @@ -6166,18 +5716,6 @@ "dev": true, "license": "MIT" }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/human-signals": { "version": "2.1.0", "dev": true, @@ -6789,18 +6327,6 @@ "node": ">=4" } }, - "node_modules/ip-address": { - "version": "9.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, - "engines": { - "node": ">= 12" - } - }, "node_modules/ipaddr.js": { "version": "2.2.0", "dev": true, @@ -7326,17 +6852,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-utf8": { "version": "0.2.1", "dev": true, @@ -7463,11 +6978,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "dev": true, - "license": "MIT" - }, "node_modules/js-yaml": { "version": "4.1.0", "dev": true, @@ -7479,11 +6989,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbn": { - "version": "1.1.0", - "dev": true, - "license": "MIT" - }, "node_modules/json-buffer": { "version": "3.0.1", "dev": true, @@ -7597,11 +7102,6 @@ "node": ">= 0.8.0" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "dev": true, - "license": "MIT" - }, "node_modules/load-json-file": { "version": "1.1.0", "dev": true, @@ -7701,85 +7201,6 @@ "dev": true, "license": "MIT" }, - "node_modules/log-symbols": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/logalot": { "version": "2.1.0", "dev": true, @@ -8082,15 +7503,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mitt": { - "version": "3.0.1", - "dev": true, - "license": "MIT" - }, "node_modules/mkdirp": { "version": "0.5.6", "dev": true, "license": "MIT", + "optional": true, "dependencies": { "minimist": "^1.2.6" }, @@ -8103,209 +7520,6 @@ "dev": true, "license": "MIT" }, - "node_modules/mocha": { - "version": "10.8.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-colors": "^4.1.3", - "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", - "debug": "^4.3.5", - "diff": "^5.2.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^8.1.0", - "he": "^1.2.0", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", - "ms": "^2.1.3", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", - "yargs-unparser": "^2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/mocha/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/cliui": { - "version": "7.0.4", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/mocha/node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/mocha/node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/mocha/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/glob": { - "version": "8.1.0", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.1.6", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/mocha/node_modules/wrap-ansi": { - "version": "7.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/mocha/node_modules/y18n": { - "version": "5.0.8", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/module-deps": { "version": "6.2.3", "dev": true, @@ -8387,14 +7601,6 @@ "dev": true, "license": "MIT" }, - "node_modules/netmask": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/nice-try": { "version": "1.0.5", "dev": true, @@ -8902,39 +8108,9 @@ "node_modules/p-try": { "version": "2.2.0", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/pac-proxy-agent": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@tootallnate/quickjs-emscripten": "^0.23.0", - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "get-uri": "^6.0.1", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.6", - "pac-resolver": "^7.0.1", - "socks-proxy-agent": "^8.0.5" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-resolver": { - "version": "7.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "degenerator": "^5.0.0", - "netmask": "^2.0.2" - }, + "license": "MIT", "engines": { - "node": ">= 14" + "node": ">=6" } }, "node_modules/pako": { @@ -8986,23 +8162,6 @@ "node": ">= 0.10" } }, - "node_modules/parse-json": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/parseurl": { "version": "1.3.3", "dev": true, @@ -9098,7 +8257,8 @@ "node_modules/pend": { "version": "1.2.0", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/picocolors": { "version": "1.1.1", @@ -9145,6 +8305,53 @@ "node": ">=0.10.0" } }, + "node_modules/playwright": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.52.0.tgz", + "integrity": "sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.52.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.52.0.tgz", + "integrity": "sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/pngquant-bin": { "version": "5.0.2", "dev": true, @@ -9312,14 +8519,6 @@ "dev": true, "license": "MIT" }, - "node_modules/progress": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/proto-list": { "version": "1.2.4", "dev": true, @@ -9346,37 +8545,6 @@ "node": ">= 0.10" } }, - "node_modules/proxy-agent": { - "version": "6.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.1", - "https-proxy-agent": "^7.0.6", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.1.0", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.5" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/lru-cache": { - "version": "7.18.3", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "dev": true, - "license": "MIT" - }, "node_modules/prr": { "version": "1.0.1", "dev": true, @@ -9410,6 +8578,7 @@ "version": "3.0.2", "dev": true, "license": "MIT", + "optional": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -9420,42 +8589,6 @@ "dev": true, "license": "MIT" }, - "node_modules/puppeteer": { - "version": "24.4.0", - "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@puppeteer/browsers": "2.8.0", - "chromium-bidi": "2.1.2", - "cosmiconfig": "^9.0.0", - "devtools-protocol": "0.0.1413902", - "puppeteer-core": "24.4.0", - "typed-query-selector": "^2.12.0" - }, - "bin": { - "puppeteer": "lib/cjs/puppeteer/node/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/puppeteer-core": { - "version": "24.4.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@puppeteer/browsers": "2.8.0", - "chromium-bidi": "2.1.2", - "debug": "^4.4.0", - "devtools-protocol": "0.0.1413902", - "typed-query-selector": "^2.12.0", - "ws": "^8.18.1" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/q": { "version": "1.5.1", "dev": true, @@ -10755,15 +9888,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, "node_modules/sockjs": { "version": "0.3.24", "dev": true, @@ -10782,32 +9906,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/socks": { - "version": "2.8.4", - "dev": true, - "license": "MIT", - "dependencies": { - "ip-address": "^9.0.5", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "8.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/sort-keys": { "version": "1.1.2", "dev": true, @@ -10930,11 +10028,6 @@ "node": ">= 6" } }, - "node_modules/sprintf-js": { - "version": "1.1.3", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/squeak": { "version": "1.3.0", "dev": true, @@ -11082,18 +10175,6 @@ "readable-stream": "^2.0.2" } }, - "node_modules/streamx": { - "version": "2.22.0", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-fifo": "^1.3.2", - "text-decoder": "^1.1.0" - }, - "optionalDependencies": { - "bare-events": "^2.2.0" - } - }, "node_modules/strict-uri-encode": { "version": "1.1.0", "dev": true, @@ -11219,15 +10300,6 @@ "node": ">=8" } }, - "node_modules/strip-bom": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } - }, "node_modules/strip-dirs": { "version": "2.1.0", "dev": true, @@ -11479,29 +10551,6 @@ "node": ">=6" } }, - "node_modules/tar-fs": { - "version": "3.0.8", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0", - "tar-stream": "^3.1.5" - }, - "optionalDependencies": { - "bare-fs": "^4.0.1", - "bare-path": "^3.0.0" - } - }, - "node_modules/tar-fs/node_modules/tar-stream": { - "version": "3.1.7", - "dev": true, - "license": "MIT", - "dependencies": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" - } - }, "node_modules/tar-stream": { "version": "1.6.2", "dev": true, @@ -11635,14 +10684,6 @@ "node": ">=0.10.0" } }, - "node_modules/text-decoder": { - "version": "1.2.3", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "b4a": "^1.6.4" - } - }, "node_modules/text-table": { "version": "0.2.0", "dev": true, @@ -11783,63 +10824,6 @@ "semver": "bin/semver.js" } }, - "node_modules/ts-mocha": { - "version": "10.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ts-node": "7.0.1" - }, - "bin": { - "ts-mocha": "bin/ts-mocha" - }, - "engines": { - "node": ">= 6.X.X" - }, - "optionalDependencies": { - "tsconfig-paths": "^3.5.0" - }, - "peerDependencies": { - "mocha": "^3.X.X || ^4.X.X || ^5.X.X || ^6.X.X || ^7.X.X || ^8.X.X || ^9.X.X || ^10.X.X || ^11.X.X" - } - }, - "node_modules/ts-mocha/node_modules/diff": { - "version": "3.5.0", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/ts-mocha/node_modules/ts-node": { - "version": "7.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "arrify": "^1.0.0", - "buffer-from": "^1.1.0", - "diff": "^3.1.0", - "make-error": "^1.1.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "source-map-support": "^0.5.6", - "yn": "^2.0.0" - }, - "bin": { - "ts-node": "dist/bin.js" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/ts-mocha/node_modules/yn": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/ts-node": { "version": "10.9.2", "dev": true, @@ -11906,18 +10890,6 @@ "node": ">=0.3.1" } }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, "node_modules/tslib": { "version": "2.8.1", "dev": true, @@ -12048,11 +11020,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typed-query-selector": { - "version": "2.12.0", - "dev": true, - "license": "MIT" - }, "node_modules/typedarray": { "version": "0.0.6", "dev": true, @@ -12171,7 +11138,9 @@ } }, "node_modules/undici-types": { - "version": "6.20.0", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -12794,11 +11763,6 @@ "node": ">=0.10.0" } }, - "node_modules/workerpool": { - "version": "6.5.1", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/wrap-ansi": { "version": "8.1.0", "dev": true, @@ -12906,58 +11870,6 @@ "yargs-parser": "^13.1.2" } }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/is-plain-obj": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/yargs/node_modules/ansi-regex": { "version": "4.1.1", "dev": true, @@ -13066,6 +11978,7 @@ "version": "2.10.0", "dev": true, "license": "MIT", + "optional": true, "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" @@ -13089,14 +12002,6 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } - }, - "node_modules/zod": { - "version": "3.24.2", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } } } } diff --git a/package.json b/package.json index 7479e52..461fe3e 100644 --- a/package.json +++ b/package.json @@ -23,13 +23,12 @@ "lint:eslint": "eslint . --fix", "lint:tsc": "tsc --noEmit", "lint": "concurrently npm:lint:tsc npm:lint:eslint", - "run:spec": "TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\"}' mocha -r ts-node/register 'test/specs/*.ts'", - "run:e2e": "TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\"}' mocha -r ts-node/register 'test/testRunner.ts'", - "test": "npm run build:test && npm run run:e2e", + "test": "playwright test", "notary": "docker run --platform=linux/amd64 -p 7047:7047 --rm ghcr.io/tlsnotary/tlsn/notary-server:v0.1.0-alpha.10 notary-server --tls-enabled=false" }, "devDependencies": { - "@types/mocha": "^10.0.6", + "@playwright/test": "^1.52.0", + "@types/node": "^22.15.18", "@types/serve-handler": "^6.1.4", "browserify": "^17.0.0", "buffer": "^6.0.3", @@ -43,20 +42,17 @@ "eslint-plugin-prettier": "^5.0.0", "file-loader": "^5.0.2", "html-webpack-plugin": "~5.3.2", - "https-browserify": "^1.0.0", "http-parser-js": "^0.5.9", + "https-browserify": "^1.0.0", "image-webpack-loader": "^6.0.0", "js-yaml": "^4.1.0", - "mocha": "^10.2.0", "node-loader": "^0.6.0", "prettier": "^3.0.2", "process": "^0.11.10", - "puppeteer": "^24.1.0", "serve": "14.2.1", "serve-handler": "^6.1.5", "stream-browserify": "^3.0.0", "ts-loader": "^6.2.1", - "ts-mocha": "^10.0.0", "ts-node": "^10.9.2", "typescript": "^4.9.5", "typescript-eslint": "^7.4.0", diff --git a/playwright-test/full-integration.spec.ts b/playwright-test/full-integration.spec.ts new file mode 100644 index 0000000..efd9908 --- /dev/null +++ b/playwright-test/full-integration.spec.ts @@ -0,0 +1,26 @@ +import { test, expect } from '@playwright/test'; + +test('full-integration', async ({ page }) => { + // log browser console messages + page.on('console', (msg) => { + console.log(`[BROWSER ${msg.type().toUpperCase()}] ${msg.text()}`); + }); + + await page.goto('/full-integration'); + + await expect(page.getByTestId('full-integration')).toHaveText(/\{.*\}/s, { timeout: 60000 }); + + const json = await page.getByTestId('full-integration').innerText(); + const { sent, recv, server_name, version, meta } = JSON.parse(json); + + expect(version).toBe('0.1.0-alpha.10'); + expect(new URL(meta.notaryUrl!).protocol === 'http:'); + expect(server_name).toBe('raw.githubusercontent.com'); + + expect(sent).toContain('host: raw.githubusercontent.com'); + expect(sent).not.toContain('secret: test_secret'); + expect(recv).toContain('"id": 1234567890'); + expect(recv).toContain('"city": "Anytown"'); + expect(recv).toContain('"postalCode": "12345"'); + +}); diff --git a/playwright-test/simple-verify.spec.ts b/playwright-test/simple-verify.spec.ts new file mode 100644 index 0000000..f9343c4 --- /dev/null +++ b/playwright-test/simple-verify.spec.ts @@ -0,0 +1,20 @@ +import { test, expect } from '@playwright/test'; + +test('simple verify', async ({ page }) => { + // log browser console messages + page.on('console', (msg) => { + console.log(`[BROWSER ${msg.type().toUpperCase()}] ${msg.text()}`); + }); + + await page.goto('/simple-verify'); + + await expect(page.getByTestId('simple-verify')).toHaveText(/\{.*\}/s); + + const json = await page.getByTestId('simple-verify').innerText(); + const { sent, recv } = JSON.parse(json); + + expect(sent).toContain('host: raw.githubusercontent.com'); + expect(recv).toContain('"name": "John Doe"'); + expect(recv).toContain('"city": "Anytown"'); + expect(recv).toContain('"id": **********,'); +}); diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..ba58b2e --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,85 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// import dotenv from 'dotenv'; +// import path from 'path'; +// dotenv.config({ path: path.resolve(__dirname, '.env') }); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './playwright-test', + /* 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, + /* 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', + /* 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://localhost:3001', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + // { + // 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 build:test && npm run serve:test', + url: 'http://localhost:3001', + reuseExistingServer: !process.env.CI, + }, + { + command: 'wstcp --bind-addr 127.0.0.1:55688 raw.githubusercontent.com:443', + reuseExistingServer: true, + }, + ] +}); diff --git a/readme.md b/readme.md index b0bb720..636194f 100644 --- a/readme.md +++ b/readme.md @@ -1,43 +1,42 @@ -![MIT licensed][mit-badge] +![MIT licensed][mit-badge] ![Apache licensed][apache-badge] -[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg +[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg [apache-badge]: https://img.shields.io/github/license/saltstack/salt # tlsn-js -NPM Modules for proving and verifying using TLSNotary in the browser. - -The prover requires a [notary-server](https://github.com/tlsnotary/notary-server) and a websocket proxy. +NPM modules for proving and verifying using TLSNotary in the browser. > [!IMPORTANT] -> The primary purpose of `tlsn-js` is to support the development of the [TLSNotary browser extension](https://github.com/tlsnotary/tlsn-extension/). -> **Please do not treat this as a public API (yet).** +> `tlsn-js` is developed specifically for **browser environments** and does **not** work in Node.js. > [!IMPORTANT] -> `tlsn-js` is developed for the usage of TLSNotary **in the Browser**. This module does not work in `nodejs`. +> The primary goal of `tlsn-js` is to support the development of the [TLSNotary browser extension](https://github.com/tlsnotary/tlsn-extension/). +> **Please do not treat this as a public API (yet).** ## License -This repository is licensed under either of + +This repository is licensed under either: - [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) -- [MIT license](http://opensource.org/licenses/MIT) +- [MIT License](http://opensource.org/licenses/MIT) -at your option. +...at your option. ## Examples -`tlsn-js` can be used in many different modes, depending on your use case. +`tlsn-js` can be used in several modes depending on your use case. -The `./demo` folder contains three demos of `tlsn-js`: +The `./demo` folder contains three demos: -* `react-ts-webpack`: create an attestation with a Notary and render the result. -* `interactive-demo`: prove data interactively to a Verifier. -* `web-to-web-p2p`: prove data between two peers, in the browser. +- `react-ts-webpack`: Create an attestation with a Notary and render the result. +- `interactive-demo`: Prove data interactively to a Verifier. +- `web-to-web-p2p`: Prove data between two browser peers. -## Running a local websocket proxy +## Running a Local WebSocket Proxy -In the demos, we attest data from `https://raw.githubusercontent.com`. Because the browser does not allow for TCP connections, you need to set up a websocket proxy: +In the demos, we attest data from `https://raw.githubusercontent.com`. Since browsers do not support raw TCP connections, a WebSocket proxy is required: 1. Install [wstcp](https://github.com/sile/wstcp): @@ -47,33 +46,42 @@ In the demos, we attest data from `https://raw.githubusercontent.com`. Because t | brew | `brew install wstcp` | | source | https://github.com/sile/wstcp | -2. Run a websocket proxy for `https://raw.githubusercontent.com`: -```sh -wstcp --bind-addr 127.0.0.1:55688 raw.githubusercontent.com:443 -``` +2. Run a WebSocket proxy for `https://raw.githubusercontent.com`: + + ```sh + wstcp --bind-addr 127.0.0.1:55688 raw.githubusercontent.com:443 + ``` + ## Install as NPM Package ```sh npm install tlsn-js ``` -# Development +## Development -This library is a JS wrapper for `tlsn-wasm`. +This library wraps the `tlsn-wasm` module. -To work on `tlsn-wasm` and `tlsn-js` at the same time, replace the "tlsn-wasm" dependency in `package.json` with: +To work on both `tlsn-wasm` and `tlsn-js` locally, update `package.json`: + +```json +"tlsn-wasm": "./tlsn-wasm/pkg" ``` - "tlsn-wasm": "./tlsn-wasm/pkg" + +Then build `tlsn-wasm`: + +```sh +npm run build:wasm ``` -and run `npm run build:wasm` to build `tlsn-wasm` locally. -Next, run: +Next: + ```sh npm install npm run test ``` -Note: if you want to switch back to a build with the version from npm, make sure to reset/remove `package-lock.json`, or it will keep using the local link. +> ℹ️ To switch back to the npm-published version of `tlsn-wasm`, delete or reset `package-lock.json` to remove the local path reference. ## Build for NPM @@ -82,9 +90,42 @@ npm install npm run build ``` -## Adding a new test -1. Create a new `new-test.spec.ts` file in the `test/` directory. -2. Add your spec file to the entry object in `webpack.web.dev.config.js`. -3. Add a new `div` block to `test/test.ejs` like this: `
Testing "new-test":
`. The `div` id must be the same as the filename. +## Testing + +Testing is slightly complex due to the need for browser-based workers. + +- Tests live in the `test/` directory. +- The `tests/` directory contains a Playwright test runner that opens a Chromium browser and runs the actual test page. + +Some tests require a running Notary. You can start one via Docker: + +```sh +npm run notary +``` + +### Adding a New `tlsn-js` Test + +1. Create a `new-test.spec.ts` file in the `test/` directory. +2. Add your spec file to the `entry` object in `webpack.web.dev.config.js`. +3. Create a corresponding `new-test.spec.ts` file in the `playwright-test/` directory. + +4. Add an `expect()` call for it in `tests/test.spec.ts`. + +### Testing the Demos + +Playwright is also used to test the demos. + +```sh +npm install +npm run test +``` +- View tests in the browser: + ```sh + npx playwright test --ui + ``` +- Debug tests: + ```sh + npx playwright test --debug + ``` diff --git a/test/e2e/full-integration.spec.ts b/test/e2e/full-integration.spec.ts index c265602..5d75e9b 100644 --- a/test/e2e/full-integration.spec.ts +++ b/test/e2e/full-integration.spec.ts @@ -8,7 +8,6 @@ import { Transcript, } from '../../src/lib'; import * as Comlink from 'comlink'; -import { assert } from '../utils'; import { HTTPParser } from 'http-parser-js'; const { init, Prover, Presentation }: any = Comlink.wrap( @@ -89,8 +88,7 @@ const { init, Prover, Presentation }: any = Comlink.wrap( console.log('presentation:', await presentation.serialize()); console.timeEnd('prove'); const json = await presentation.json(); - assert(json.version === '0.1.0-alpha.10'); - assert(new URL(json.meta.notaryUrl!).protocol === 'http:'); + console.time('verify'); const { transcript: partialTranscript, server_name } = @@ -109,19 +107,17 @@ const { init, Prover, Presentation }: any = Comlink.wrap( console.log("Sent:", sentStr); console.log("Received:", recvStr); - assert(sentStr.includes('host: raw.githubusercontent.com')); - assert(!sentStr.includes('secret: test_secret')); - assert(recvStr.includes('"id": 1234567890')); - assert(recvStr.includes('"city": "Anytown"')); - assert(recvStr.includes('"postalCode": "12345"')); - assert(server_name === 'raw.githubusercontent.com'); - // @ts-ignore - document.getElementById('full-integration').textContent = 'OK'; + document.getElementById('full-integration').textContent = JSON.stringify({ + sent: sentStr, + recv: recvStr, + version: json.version, + meta: json.meta, + server_name + }, null, 2); } catch (err) { console.log('caught error from wasm'); console.error(err); - // @ts-ignore document.getElementById('full-integration').textContent = err.message; } diff --git a/test/e2e/simple-verify.spec.ts b/test/e2e/simple-verify.spec.ts index b1b54e2..561d435 100644 --- a/test/e2e/simple-verify.spec.ts +++ b/test/e2e/simple-verify.spec.ts @@ -2,7 +2,6 @@ import { Presentation as _Presentation } from '../../src/lib'; // import { assert } from '../utils'; import * as Comlink from 'comlink'; import { Transcript } from '../../src/lib'; -import { assert } from '../utils'; const { init, Presentation }: any = Comlink.wrap( // @ts-ignore @@ -26,16 +25,11 @@ const { init, Presentation }: any = Comlink.wrap( const sent = transcript.sent(); const recv = transcript.recv(); - console.log('sent', sent); - console.log('recv', recv); - - assert(sent.includes('host: raw.githubusercontent.com')); - - assert(recv.includes('"name": "John Doe"')); - assert(recv.includes('"city": "Anytown"')); - // @ts-ignore - document.getElementById('simple-verify').textContent = 'OK'; + document.getElementById('simple-verify').textContent = JSON.stringify({ + sent, + recv + }, null, 2); } catch (err) { console.log('caught error from wasm'); console.error(err); diff --git a/test/specs/transcript.ts b/test/specs/transcript.ts deleted file mode 100644 index b43a437..0000000 --- a/test/specs/transcript.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { describe, it } from 'mocha'; -import * as assert from 'assert'; -import { Transcript } from '../../src/transcript'; - -describe('Transcript parsing', () => { - it('should parse transcript correctly', async () => { - const transcript = new Transcript({ sent: swapiSent, recv: swapiRecv }); - assert.strictEqual( - Buffer.from(transcript.raw.sent).toString('utf-8'), - 'GET https://swapi.dev/api/people/1 HTTP/1.1\r\nconnection: close\r\ncontent-length: 25\r\ncontent-type: application/json\r\nhost: swapi.dev\r\n\r\n{"hello":"world","one":1}', - ); - assert.strictEqual( - Buffer.from(transcript.raw.recv).toString('utf-8'), - 'HTTP/1.1 200 OK\r\nServer: nginx/1.16.1\r\nDate: Fri, 07 Feb 2025 07:37:11 GMT\r\nContent-Type: application/json\r\nTransfer-Encoding: chunked\r\nConnection: close\r\nVary: Accept, Cookie\r\nX-Frame-Options: SAMEORIGIN\r\nETag: \"ee398610435c328f4d0a4e1b0d2f7bbc\"\r\nAllow: GET, HEAD, OPTIONS\r\nStrict-Transport-Security: max-age=15768000\r\n\r\n287\r\n{\"name\":\"Luke Skywalker\",\"height\":\"172\",\"mass\":\"77\",\"hair_color\":\"blond\",\"skin_color\":\"fair\",\"eye_color\":\"blue\",\"birth_year\":\"19BBY\",\"gender\":\"male\",\"homeworld\":\"https://swapi.dev/api/planets/1/\",\"films\":[\"https://swapi.dev/api/films/1/\",\"https://swapi.dev/api/films/2/\",\"https://swapi.dev/api/films/3/\",\"https://swapi.dev/api/films/6/\"],\"species\":[],\"vehicles\":[\"https://swapi.dev/api/vehicles/14/\",\"https://swapi.dev/api/vehicles/30/\"],\"starships\":[\"https://swapi.dev/api/starships/12/\",\"https://swapi.dev/api/starships/22/\"],\"created\":\"2014-12-09T13:50:51.644000Z\",\"edited\":\"2014-12-20T21:17:56.891000Z\",\"url\":\"https://swapi.dev/api/people/1/\"}\r\n0\r\n\r\n', - ); - }); -}); - -const swapiRecv = [ - 72, 84, 84, 80, 47, 49, 46, 49, 32, 50, 48, 48, 32, 79, 75, 13, 10, 83, 101, - 114, 118, 101, 114, 58, 32, 110, 103, 105, 110, 120, 47, 49, 46, 49, 54, 46, - 49, 13, 10, 68, 97, 116, 101, 58, 32, 70, 114, 105, 44, 32, 48, 55, 32, 70, - 101, 98, 32, 50, 48, 50, 53, 32, 48, 55, 58, 51, 55, 58, 49, 49, 32, 71, 77, - 84, 13, 10, 67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 32, - 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47, 106, 115, 111, 110, - 13, 10, 84, 114, 97, 110, 115, 102, 101, 114, 45, 69, 110, 99, 111, 100, 105, - 110, 103, 58, 32, 99, 104, 117, 110, 107, 101, 100, 13, 10, 67, 111, 110, 110, - 101, 99, 116, 105, 111, 110, 58, 32, 99, 108, 111, 115, 101, 13, 10, 86, 97, - 114, 121, 58, 32, 65, 99, 99, 101, 112, 116, 44, 32, 67, 111, 111, 107, 105, - 101, 13, 10, 88, 45, 70, 114, 97, 109, 101, 45, 79, 112, 116, 105, 111, 110, - 115, 58, 32, 83, 65, 77, 69, 79, 82, 73, 71, 73, 78, 13, 10, 69, 84, 97, 103, - 58, 32, 34, 101, 101, 51, 57, 56, 54, 49, 48, 52, 51, 53, 99, 51, 50, 56, 102, - 52, 100, 48, 97, 52, 101, 49, 98, 48, 100, 50, 102, 55, 98, 98, 99, 34, 13, - 10, 65, 108, 108, 111, 119, 58, 32, 71, 69, 84, 44, 32, 72, 69, 65, 68, 44, - 32, 79, 80, 84, 73, 79, 78, 83, 13, 10, 83, 116, 114, 105, 99, 116, 45, 84, - 114, 97, 110, 115, 112, 111, 114, 116, 45, 83, 101, 99, 117, 114, 105, 116, - 121, 58, 32, 109, 97, 120, 45, 97, 103, 101, 61, 49, 53, 55, 54, 56, 48, 48, - 48, 13, 10, 13, 10, 50, 56, 55, 13, 10, 123, 34, 110, 97, 109, 101, 34, 58, - 34, 76, 117, 107, 101, 32, 83, 107, 121, 119, 97, 108, 107, 101, 114, 34, 44, - 34, 104, 101, 105, 103, 104, 116, 34, 58, 34, 49, 55, 50, 34, 44, 34, 109, 97, - 115, 115, 34, 58, 34, 55, 55, 34, 44, 34, 104, 97, 105, 114, 95, 99, 111, 108, - 111, 114, 34, 58, 34, 98, 108, 111, 110, 100, 34, 44, 34, 115, 107, 105, 110, - 95, 99, 111, 108, 111, 114, 34, 58, 34, 102, 97, 105, 114, 34, 44, 34, 101, - 121, 101, 95, 99, 111, 108, 111, 114, 34, 58, 34, 98, 108, 117, 101, 34, 44, - 34, 98, 105, 114, 116, 104, 95, 121, 101, 97, 114, 34, 58, 34, 49, 57, 66, 66, - 89, 34, 44, 34, 103, 101, 110, 100, 101, 114, 34, 58, 34, 109, 97, 108, 101, - 34, 44, 34, 104, 111, 109, 101, 119, 111, 114, 108, 100, 34, 58, 34, 104, 116, - 116, 112, 115, 58, 47, 47, 115, 119, 97, 112, 105, 46, 100, 101, 118, 47, 97, - 112, 105, 47, 112, 108, 97, 110, 101, 116, 115, 47, 49, 47, 34, 44, 34, 102, - 105, 108, 109, 115, 34, 58, 91, 34, 104, 116, 116, 112, 115, 58, 47, 47, 115, - 119, 97, 112, 105, 46, 100, 101, 118, 47, 97, 112, 105, 47, 102, 105, 108, - 109, 115, 47, 49, 47, 34, 44, 34, 104, 116, 116, 112, 115, 58, 47, 47, 115, - 119, 97, 112, 105, 46, 100, 101, 118, 47, 97, 112, 105, 47, 102, 105, 108, - 109, 115, 47, 50, 47, 34, 44, 34, 104, 116, 116, 112, 115, 58, 47, 47, 115, - 119, 97, 112, 105, 46, 100, 101, 118, 47, 97, 112, 105, 47, 102, 105, 108, - 109, 115, 47, 51, 47, 34, 44, 34, 104, 116, 116, 112, 115, 58, 47, 47, 115, - 119, 97, 112, 105, 46, 100, 101, 118, 47, 97, 112, 105, 47, 102, 105, 108, - 109, 115, 47, 54, 47, 34, 93, 44, 34, 115, 112, 101, 99, 105, 101, 115, 34, - 58, 91, 93, 44, 34, 118, 101, 104, 105, 99, 108, 101, 115, 34, 58, 91, 34, - 104, 116, 116, 112, 115, 58, 47, 47, 115, 119, 97, 112, 105, 46, 100, 101, - 118, 47, 97, 112, 105, 47, 118, 101, 104, 105, 99, 108, 101, 115, 47, 49, 52, - 47, 34, 44, 34, 104, 116, 116, 112, 115, 58, 47, 47, 115, 119, 97, 112, 105, - 46, 100, 101, 118, 47, 97, 112, 105, 47, 118, 101, 104, 105, 99, 108, 101, - 115, 47, 51, 48, 47, 34, 93, 44, 34, 115, 116, 97, 114, 115, 104, 105, 112, - 115, 34, 58, 91, 34, 104, 116, 116, 112, 115, 58, 47, 47, 115, 119, 97, 112, - 105, 46, 100, 101, 118, 47, 97, 112, 105, 47, 115, 116, 97, 114, 115, 104, - 105, 112, 115, 47, 49, 50, 47, 34, 44, 34, 104, 116, 116, 112, 115, 58, 47, - 47, 115, 119, 97, 112, 105, 46, 100, 101, 118, 47, 97, 112, 105, 47, 115, 116, - 97, 114, 115, 104, 105, 112, 115, 47, 50, 50, 47, 34, 93, 44, 34, 99, 114, - 101, 97, 116, 101, 100, 34, 58, 34, 50, 48, 49, 52, 45, 49, 50, 45, 48, 57, - 84, 49, 51, 58, 53, 48, 58, 53, 49, 46, 54, 52, 52, 48, 48, 48, 90, 34, 44, - 34, 101, 100, 105, 116, 101, 100, 34, 58, 34, 50, 48, 49, 52, 45, 49, 50, 45, - 50, 48, 84, 50, 49, 58, 49, 55, 58, 53, 54, 46, 56, 57, 49, 48, 48, 48, 90, - 34, 44, 34, 117, 114, 108, 34, 58, 34, 104, 116, 116, 112, 115, 58, 47, 47, - 115, 119, 97, 112, 105, 46, 100, 101, 118, 47, 97, 112, 105, 47, 112, 101, - 111, 112, 108, 101, 47, 49, 47, 34, 125, 13, 10, 48, 13, 10, 13, 10, -]; - -const swapiSent = [ - 71, 69, 84, 32, 104, 116, 116, 112, 115, 58, 47, 47, 115, 119, 97, 112, 105, - 46, 100, 101, 118, 47, 97, 112, 105, 47, 112, 101, 111, 112, 108, 101, 47, 49, - 32, 72, 84, 84, 80, 47, 49, 46, 49, 13, 10, 99, 111, 110, 110, 101, 99, 116, - 105, 111, 110, 58, 32, 99, 108, 111, 115, 101, 13, 10, 99, 111, 110, 116, 101, - 110, 116, 45, 108, 101, 110, 103, 116, 104, 58, 32, 50, 53, 13, 10, 99, 111, - 110, 116, 101, 110, 116, 45, 116, 121, 112, 101, 58, 32, 97, 112, 112, 108, - 105, 99, 97, 116, 105, 111, 110, 47, 106, 115, 111, 110, 13, 10, 104, 111, - 115, 116, 58, 32, 115, 119, 97, 112, 105, 46, 100, 101, 118, 13, 10, 13, 10, - 123, 34, 104, 101, 108, 108, 111, 34, 58, 34, 119, 111, 114, 108, 100, 34, 44, - 34, 111, 110, 101, 34, 58, 49, 125, -]; diff --git a/test/test.ejs b/test/test.ejs index 18413bc..d3f02e8 100644 --- a/test/test.ejs +++ b/test/test.ejs @@ -5,19 +5,21 @@ - tlsn-js development + + Testing <%= htmlWebpackPlugin.options.testName || 'test' %> + -
Testing "full-integration": -
-
-
Testing "simple-verify": -
-
+

Testing "<%= htmlWebpackPlugin.options.testName || 'unknown' %>":

+
+        
+
+
\ No newline at end of file diff --git a/test/testRunner.ts b/test/testRunner.ts deleted file mode 100644 index 2832362..0000000 --- a/test/testRunner.ts +++ /dev/null @@ -1,125 +0,0 @@ -import puppeteer, { Browser, LaunchOptions, Page } from 'puppeteer'; -import { describe, it, before, after } from 'mocha'; -const assert = require('assert'); -import { exec, ChildProcess } from 'node:child_process'; -import * as fs from 'fs'; -import path from 'path'; - -const timeout = 300000; - -// puppeteer options -let opts: LaunchOptions = { - headless: !!process.env.HEADLESS ? true : false, - slowMo: 100, - timeout: timeout, - args: ['--no-sandbox', '--disable-setuid-sandbox'], -}; - -if (process.env.CHROME_PATH) { - opts = { - ...opts, - executablePath: process.env.CHROME_PATH, - }; -} - -let browser: Browser; -let page: Page; -let server: ChildProcess; - -const waitForNotaryServer = async () => { - // wait for the notary server to be ready - while (true) { - try { - const response = await fetch('http://127.0.0.1:7047/info'); - if (response.ok) { - return; - } - } catch (error) { - console.error('Waiting for local notary server...', error); - } - await new Promise((resolve) => setTimeout(resolve, 1000)); - } -}; - -// expose variables -before(async function () { - server = exec('serve --config ../serve.json ./test-build -l 3001'); - - await waitForNotaryServer(); - browser = await puppeteer.launch(opts); - page = await browser.newPage(); - - // log browser console messages - page.on('console', (msg) => { - console.log(`[BROWSER ${msg.type().toUpperCase()}] ${msg.text()}`); - }); - - await page.goto('http://127.0.0.1:3001'); -}); - -// close browser and reset global variables -after(async function () { - console.log('Cleaning up:'); - - try { - server.kill(); - console.log('* Stopped Test Web Server ✅'); - - if (page) { - await page.close(); - } - if (browser) { - await browser.close(); - const childProcess = browser.process(); - if (childProcess) { - childProcess.kill(9); - } - console.log('* Closed browser ✅'); - - const tests = this.test?.parent?.suites.flatMap((suite) => suite.tests); - const failed = tests!.some((test) => test.state === 'failed'); - - console.log('tests', tests); - console.log('failed', failed); - process.exit(failed ? 1 : 0); - } - process.exit(1); - } catch (e) { - console.error(e); - process.exit(1); - } -}); - -describe('tlsn-js test suite', function () { - fs.readdirSync(path.join(__dirname, 'e2e')).forEach((file) => { - const [id] = file.split('.'); - it(`Test ID: ${id}`, async function () { - const content = await check(id); - assert.strictEqual( - content, - 'OK', - `Test ID: ${id} - Expected 'OK' but got '${content}'`, - ); - }); - }); -}); - -async function check(testId: string): Promise { - const startTime = Date.now(); - const attemptFetchContent = async (): Promise => { - const content = await page.$eval( - `#${testId}`, - (el: any) => el.textContent || '', - ); - if (content) return content; - const elapsedTime = Date.now() - startTime; - if (elapsedTime >= timeout) { - throw new Error( - `Timeout: Failed to retrieve content for '#${testId}' within ${timeout} ms.`, - ); - } - await new Promise((resolve) => setTimeout(resolve, 1000)); - return attemptFetchContent(); - }; - return attemptFetchContent(); -} diff --git a/test/utils.ts b/test/utils.ts deleted file mode 100644 index 3ddb6a6..0000000 --- a/test/utils.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function assert(expr: any, msg = 'unknown assertion error') { - if (!Boolean(expr)) throw new Error(msg); -} diff --git a/webpack.web.dev.config.js b/webpack.web.dev.config.js index e0c6c12..85c276e 100644 --- a/webpack.web.dev.config.js +++ b/webpack.web.dev.config.js @@ -33,14 +33,17 @@ const rules = [ const rendererRules = []; +const entry = { + 'full-integration': path.join(__dirname, 'test', 'e2e', 'full-integration.spec.ts'), + 'simple-verify': path.join(__dirname, 'test', 'e2e', 'simple-verify.spec.ts'), + // add more entries as needed +}; + module.exports = [ { target: 'web', mode: isProd ? 'production' : 'development', - entry: { - 'full-integration.spec': path.join(__dirname, 'test', 'e2e', 'full-integration.spec.ts'), - 'simple-verify': path.join(__dirname, 'test', 'e2e', 'simple-verify.spec.ts'), - }, + entry, output: { path: __dirname + '/test-build', publicPath: '/', @@ -49,25 +52,6 @@ module.exports = [ devtool: 'source-map', resolve: { extensions: ['.ts', '.tsx', '.js', '.jsx', '.png', '.svg'], - // modules: [ - // path.resolve('./node_modules'), - // path.resolve(__dirname, compilerOptions.baseUrl), - // ], - // fallback: { - // browserify: require.resolve('browserify'), - // stream: require.resolve('stream-browserify'), - // path: require.resolve('path-browserify'), - // crypto: require.resolve('crypto-browserify'), - // os: require.resolve('os-browserify/browser'), - // http: require.resolve('stream-http'), - // https: require.resolve('https-browserify'), - // assert: require.resolve('assert/'), - // events: require.resolve('events/'), - // 'ansi-html-community': require.resolve('ansi-html-community'), - // 'html-entities': require.resolve('html-entities'), - // constants: false, - // fs: false, - // }, }, module: { rules: [...rules, ...rendererRules], @@ -89,10 +73,41 @@ module.exports = [ }, ], }), + // Generate an HTML file for each entry + ...Object.keys(entry).map( + (name) => + new HtmlWebpackPlugin({ + template: './test/test.ejs', + filename: `${name}.html`, + chunks: [name], + inject: true, + testName: name, + }) + ), + // Add an index page listing all test pages new HtmlWebpackPlugin({ - template: './test/test.ejs', - filename: `index.html`, - inject: true, + templateContent: () => ` + + + + + tlsn-js test index + + +

tlsn-js test index

+
    + ${Object.keys(entry) + .map( + (name) => + `
  • ${name}
  • ` + ) + .join('\n')} +
+ + + `, + filename: 'index.html', + inject: false, }), ], stats: 'minimal',