From 617e1a597a22cb1edbe842d30373b76c0c420c14 Mon Sep 17 00:00:00 2001 From: barbmarcio Date: Thu, 18 Jul 2024 13:40:44 +0100 Subject: [PATCH 01/10] feat: initial revision for e2e tests --- .gitignore | 2 ++ bun.lockb | Bin 83432 -> 107822 bytes e2e/auctions.test.ts | 54 +++++++++++++++++++++++++++++++++++++++++++ e2e/index.html | 46 ++++++++++++++++++++++++++++++++++++ package.json | 3 +++ playwright.config.ts | 31 +++++++++++++++++++++++++ tsup.config.ts | 3 ++- 7 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 e2e/auctions.test.ts create mode 100644 e2e/index.html create mode 100644 playwright.config.ts diff --git a/.gitignore b/.gitignore index ef229ed..aace4f7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ coverage/ dist/ node_modules/ +test-results/ +test-results.json diff --git a/bun.lockb b/bun.lockb index 72143bcb09d786ddeb7c40249b8cbf49aa6030c9..70f493ae65a05a11cd764fbc7a95e4bfb7b70b8f 100755 GIT binary patch delta 30868 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 V{nD7u{{dNzoxlJ9 delta 16440 zcmeHOd3a69w%@hokP{*!LPjD)$VpBT8RZZ&C#KdMF@%VNLnaxJ7?PN0qO?t$+dQ

TB~aBv$JdK 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 { + test('should create auction successfully', async ({ page }) => { + const mockAPIResponse = { + results: [ + { + resultType: "listings", + winners: [], + error: false, + }, + { + resultType: "banners", + winners: [], + error: false, + }, + ], + } + + await page.route(`${baseURL}/${apis.auctions}`, async route => { + await route.fulfill({ json: mockAPIResponse }); + }); + + await page.goto('http://localhost:8080/e2e/index.html'); + + await page.fill('input[name="apiKey"]', 'your-api-key'); + await page.fill('input[name="auctionDetails"]', JSON.stringify({ + auctions: [ + { + type: "listings", + slots: 3, + category: { id: "cat123" }, + geoTargeting: { location: "US" }, + }, + { + type: "banners", + slots: 1, + device: "desktop", + slotId: "slot123", + category: { ids: ["cat1", "cat2"] }, + geoTargeting: { location: "UK" }, + }, + ], + })); + + await page.click('button[type="submit"]'); + + const response = await page.locator('#response').textContent(); + const jsonResponse = JSON.parse(response || '{}'); + expect(jsonResponse).toEqual(mockAPIResponse) + expect(jsonResponse).toEqual(mockAPIResponse); + }); +}); \ No newline at end of file diff --git a/e2e/index.html b/e2e/index.html new file mode 100644 index 0000000..55a09d8 --- /dev/null +++ b/e2e/index.html @@ -0,0 +1,46 @@ + + + + + + Topsort SDK Test Application + + + +

Test Topsort.js Integration

+
+ + + +
+

+    
+  
+
diff --git a/package.json b/package.json
index bf04689..a3dfb3d 100644
--- a/package.json
+++ b/package.json
@@ -32,13 +32,16 @@
   ],
   "scripts": {
     "build": "tsup",
+    "test:e2e": "playwright test",
     "format": "biome check",
     "format:fix": "biome check --write",
     "prepare": "lefthook install"
   },
   "devDependencies": {
     "@biomejs/biome": "1.8.3",
+    "@playwright/test": "^1.45.2",
     "@types/bun": "1.1.6",
+    "http-server": "^14.1.1",
     "lefthook": "1.7.2",
     "msw": "2.3.1",
     "tsup": "8.1.0",
diff --git a/playwright.config.ts b/playwright.config.ts
new file mode 100644
index 0000000..0ed5b16
--- /dev/null
+++ b/playwright.config.ts
@@ -0,0 +1,31 @@
+import { defineConfig, devices } from '@playwright/test';
+
+export default defineConfig({
+    testDir: './e2e',
+    timeout: 30000,
+    retries: 1,
+    reporter: [['list'], ['json', { outputFile: 'test-results.json' }]],
+    use: {
+        trace: 'on-first-retry',
+    },
+    projects: [
+        {
+            name: 'chromium',
+            use: { ...devices['Desktop Chrome'] },
+        },
+        {
+            name: 'firefox',
+            use: { ...devices['Desktop Firefox'] },
+        },
+        {
+            name: 'webkit',
+            use: { ...devices['Desktop Safari'] },
+        },
+    ],
+    webServer: {
+        command: 'http-server ./ -p 8080',
+        reuseExistingServer: !process.env.CI,
+        stdout: 'ignore',
+        stderr: 'pipe',
+    }
+})
\ No newline at end of file
diff --git a/tsup.config.ts b/tsup.config.ts
index 0e3f406..d8f1bb2 100644
--- a/tsup.config.ts
+++ b/tsup.config.ts
@@ -2,11 +2,12 @@ import { defineConfig } from "tsup";
 
 export default defineConfig({
   entry: ["src/index.ts"],
-  format: ["cjs", "esm"],
+  format: ["cjs", "esm", "iife"],
   dts: true,
   clean: true,
   minify: true,
   esbuildOptions(options) {
     options.keepNames = true;
+    options.globalName = "Topsort"
   },
 });

From 3ad5a554a380d2e99720a645a1a17d73d3c66b60 Mon Sep 17 00:00:00 2001
From: barbmarcio 
Date: Thu, 18 Jul 2024 13:44:11 +0100
Subject: [PATCH 02/10] feat: adding e2e tests to contributing docs

---
 CONTRIBUTING.md | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d920b47..59ab0b9 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -17,6 +17,7 @@ We'd love to accept your patches and contributions to this project. Bellow, you
 - [Building the SDK](#building-the-sdk)
 - [Tests](#tests)
   - [Unit Tests](#unit-tests)
+  - [E2E Tests](#e2e-tests)
 - [Code Standards](#code-standards)
 - [Submitting contributions](#submitting-contributions)
   - [Commit Messages](#commit-messages)
@@ -94,6 +95,14 @@ To run the unit tests, use the following command:
 bun run test
 ```
 
+### E2E Tests
+
+To run the end-to-end tests, use the following command:
+
+```bash
+bun run test:e2e
+```
+
 ## Code Standards
 
 We follow the coding standards set by Biome. Ensure your code follows these guidelines before submitting a pull request. You can run the formatter with the following command:
@@ -125,6 +134,7 @@ We do conventional commits, so it will fail on checker with capital case after c
 The SDK uses following configuration files:
 - `tsconfig.json`: TypeScript configuration.
 - `tsup.config.ts`: Configuration for the TSUP bundler.
+- `playwright.config.ts`: Configuration for E2E tests runner
 
 ## License
 This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.

From 9cf52ab5ea6d92fdec904d7d296189e884e0d8fe Mon Sep 17 00:00:00 2001
From: barbmarcio 
Date: Thu, 18 Jul 2024 14:13:53 +0100
Subject: [PATCH 03/10] feat: adding root for bun tests and e2e tests

---
 bunfig.toml          | 1 +
 playwright.config.ts | 1 +
 2 files changed, 2 insertions(+)

diff --git a/bunfig.toml b/bunfig.toml
index 0c9079a..101803d 100644
--- a/bunfig.toml
+++ b/bunfig.toml
@@ -1,2 +1,3 @@
 [test]
 coverage = true
+root = "./test"
\ No newline at end of file
diff --git a/playwright.config.ts b/playwright.config.ts
index 0ed5b16..dd57aa1 100644
--- a/playwright.config.ts
+++ b/playwright.config.ts
@@ -4,6 +4,7 @@ export default defineConfig({
     testDir: './e2e',
     timeout: 30000,
     retries: 1,
+    testMatch: '**/*.spec.ts',
     reporter: [['list'], ['json', { outputFile: 'test-results.json' }]],
     use: {
         trace: 'on-first-retry',

From 1abb2887d65e356495f7309287865fba0a8c57fb Mon Sep 17 00:00:00 2001
From: barbmarcio 
Date: Thu, 18 Jul 2024 14:16:21 +0100
Subject: [PATCH 04/10] fix: biome formatting

---
 e2e/auctions.test.ts | 63 +++++++++++++++++++++++---------------------
 playwright.config.ts | 58 ++++++++++++++++++++--------------------
 tsup.config.ts       |  2 +-
 3 files changed, 63 insertions(+), 60 deletions(-)

diff --git a/e2e/auctions.test.ts b/e2e/auctions.test.ts
index aba3152..1340a3c 100644
--- a/e2e/auctions.test.ts
+++ b/e2e/auctions.test.ts
@@ -1,8 +1,8 @@
-import { apis, baseURL } from '../src/constants/apis.constant';
-import { test, expect } from '@playwright/test'
+import { expect, test } from "@playwright/test";
+import { apis, baseURL } from "../src/constants/apis.constant";
 
-test.describe('Create Auction via Topsort.js', () => {
-  test('should create auction successfully', async ({ page }) => {
+test.describe("Create Auction via Topsort.js", () => {
+  test("should create auction successfully", async ({ page }) => {
     const mockAPIResponse = {
       results: [
         {
@@ -16,39 +16,42 @@ test.describe('Create Auction via Topsort.js', () => {
           error: false,
         },
       ],
-    }
+    };
 
-    await page.route(`${baseURL}/${apis.auctions}`, async route => {
+    await page.route(`${baseURL}/${apis.auctions}`, async (route) => {
       await route.fulfill({ json: mockAPIResponse });
     });
 
-    await page.goto('http://localhost:8080/e2e/index.html');
+    await page.goto("http://localhost:8080/e2e/index.html");
 
-    await page.fill('input[name="apiKey"]', 'your-api-key');
-    await page.fill('input[name="auctionDetails"]', JSON.stringify({
-      auctions: [
-        {
-          type: "listings",
-          slots: 3,
-          category: { id: "cat123" },
-          geoTargeting: { location: "US" },
-        },
-        {
-          type: "banners",
-          slots: 1,
-          device: "desktop",
-          slotId: "slot123",
-          category: { ids: ["cat1", "cat2"] },
-          geoTargeting: { location: "UK" },
-        },
-      ],
-    }));
+    await page.fill('input[name="apiKey"]', "your-api-key");
+    await page.fill(
+      'input[name="auctionDetails"]',
+      JSON.stringify({
+        auctions: [
+          {
+            type: "listings",
+            slots: 3,
+            category: { id: "cat123" },
+            geoTargeting: { location: "US" },
+          },
+          {
+            type: "banners",
+            slots: 1,
+            device: "desktop",
+            slotId: "slot123",
+            category: { ids: ["cat1", "cat2"] },
+            geoTargeting: { location: "UK" },
+          },
+        ],
+      }),
+    );
 
     await page.click('button[type="submit"]');
 
-    const response = await page.locator('#response').textContent();
-    const jsonResponse = JSON.parse(response || '{}');
-    expect(jsonResponse).toEqual(mockAPIResponse)
+    const response = await page.locator("#response").textContent();
+    const jsonResponse = JSON.parse(response || "{}");
+    expect(jsonResponse).toEqual(mockAPIResponse);
     expect(jsonResponse).toEqual(mockAPIResponse);
   });
-});
\ No newline at end of file
+});
diff --git a/playwright.config.ts b/playwright.config.ts
index dd57aa1..817ed77 100644
--- a/playwright.config.ts
+++ b/playwright.config.ts
@@ -1,32 +1,32 @@
-import { defineConfig, devices } from '@playwright/test';
+import { defineConfig, devices } from "@playwright/test";
 
 export default defineConfig({
-    testDir: './e2e',
-    timeout: 30000,
-    retries: 1,
-    testMatch: '**/*.spec.ts',
-    reporter: [['list'], ['json', { outputFile: 'test-results.json' }]],
-    use: {
-        trace: 'on-first-retry',
+  testDir: "./e2e",
+  timeout: 30000,
+  retries: 1,
+  testMatch: "**/*.spec.ts",
+  reporter: [["list"], ["json", { outputFile: "test-results.json" }]],
+  use: {
+    trace: "on-first-retry",
+  },
+  projects: [
+    {
+      name: "chromium",
+      use: { ...devices["Desktop Chrome"] },
     },
-    projects: [
-        {
-            name: 'chromium',
-            use: { ...devices['Desktop Chrome'] },
-        },
-        {
-            name: 'firefox',
-            use: { ...devices['Desktop Firefox'] },
-        },
-        {
-            name: 'webkit',
-            use: { ...devices['Desktop Safari'] },
-        },
-    ],
-    webServer: {
-        command: 'http-server ./ -p 8080',
-        reuseExistingServer: !process.env.CI,
-        stdout: 'ignore',
-        stderr: 'pipe',
-    }
-})
\ No newline at end of file
+    {
+      name: "firefox",
+      use: { ...devices["Desktop Firefox"] },
+    },
+    {
+      name: "webkit",
+      use: { ...devices["Desktop Safari"] },
+    },
+  ],
+  webServer: {
+    command: "http-server ./ -p 8080",
+    reuseExistingServer: !process.env.CI,
+    stdout: "ignore",
+    stderr: "pipe",
+  },
+});
diff --git a/tsup.config.ts b/tsup.config.ts
index d8f1bb2..a51cc34 100644
--- a/tsup.config.ts
+++ b/tsup.config.ts
@@ -8,6 +8,6 @@ export default defineConfig({
   minify: true,
   esbuildOptions(options) {
     options.keepNames = true;
-    options.globalName = "Topsort"
+    options.globalName = "Topsort";
   },
 });

From c5c03fe083721ce0956c4143bafc3610eeb44769 Mon Sep 17 00:00:00 2001
From: barbmarcio 
Date: Fri, 19 Jul 2024 18:59:32 +0100
Subject: [PATCH 05/10] fix: adding new skel using only function in script

---
 e2e/auctions.test.ts | 29 +++++++++++++++--------------
 e2e/index.html       | 41 +++++++++--------------------------------
 global.d.ts          |  5 +++++
 package.json         |  1 +
 playwright.config.ts |  1 -
 5 files changed, 30 insertions(+), 47 deletions(-)
 create mode 100644 global.d.ts

diff --git a/e2e/auctions.test.ts b/e2e/auctions.test.ts
index 1340a3c..fe605ec 100644
--- a/e2e/auctions.test.ts
+++ b/e2e/auctions.test.ts
@@ -1,8 +1,8 @@
 import { expect, test } from "@playwright/test";
 import { apis, baseURL } from "../src/constants/apis.constant";
 
-test.describe("Create Auction via Topsort.js", () => {
-  test("should create auction successfully", async ({ page }) => {
+test.describe("Create Auction via Topsort SDK", () => {
+  test("should create an auction successfully", async ({ page }) => {
     const mockAPIResponse = {
       results: [
         {
@@ -22,12 +22,13 @@ test.describe("Create Auction via Topsort.js", () => {
       await route.fulfill({ json: mockAPIResponse });
     });
 
-    await page.goto("http://localhost:8080/e2e/index.html");
+    await page.goto("http://localhost:8080/e2e");
+    const result = await page.evaluate(() => {
+      const config = {
+        apiKey: "rando-api-key",
+      };
 
-    await page.fill('input[name="apiKey"]', "your-api-key");
-    await page.fill(
-      'input[name="auctionDetails"]',
-      JSON.stringify({
+      const auctionDetails = {
         auctions: [
           {
             type: "listings",
@@ -44,14 +45,14 @@ test.describe("Create Auction via Topsort.js", () => {
             geoTargeting: { location: "UK" },
           },
         ],
-      }),
-    );
+      };
+      if (typeof window.sdk.createAuction === "undefined") {
+        throw new Error("Global function `createAuctions` is not available.");
+      }
 
-    await page.click('button[type="submit"]');
+      return window.sdk.createAuction(config, auctionDetails);
+    });
 
-    const response = await page.locator("#response").textContent();
-    const jsonResponse = JSON.parse(response || "{}");
-    expect(jsonResponse).toEqual(mockAPIResponse);
-    expect(jsonResponse).toEqual(mockAPIResponse);
+    expect(result).toEqual(mockAPIResponse);
   });
 });
diff --git a/e2e/index.html b/e2e/index.html
index 55a09d8..52f40ad 100644
--- a/e2e/index.html
+++ b/e2e/index.html
@@ -8,39 +8,16 @@
   
   
     

Test Topsort.js Integration

-
- - - -
-

     
   
 
diff --git a/global.d.ts b/global.d.ts
new file mode 100644
index 0000000..41758e2
--- /dev/null
+++ b/global.d.ts
@@ -0,0 +1,5 @@
+interface Window {
+  sdk: {
+    createAuction: (a, b) => void;
+  };
+}
diff --git a/package.json b/package.json
index a3dfb3d..926bd26 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
     "CHANGELOG.md",
     "LICENSE",
     "README.md",
+    "dist/index.global.js",
     "dist/index.d.mts",
     "dist/index.d.ts",
     "dist/index.js",
diff --git a/playwright.config.ts b/playwright.config.ts
index 817ed77..352e5e8 100644
--- a/playwright.config.ts
+++ b/playwright.config.ts
@@ -4,7 +4,6 @@ export default defineConfig({
   testDir: "./e2e",
   timeout: 30000,
   retries: 1,
-  testMatch: "**/*.spec.ts",
   reporter: [["list"], ["json", { outputFile: "test-results.json" }]],
   use: {
     trace: "on-first-retry",

From cc9fb3395bf291f03e57c0bb7d37ec9fc5280776 Mon Sep 17 00:00:00 2001
From: barbmarcio 
Date: Fri, 19 Jul 2024 19:55:40 +0100
Subject: [PATCH 06/10] feat: adding reportevent tests and negative tests

---
 CONTRIBUTING.md      |  3 +-
 README.md            |  2 +-
 e2e/auctions.test.ts | 38 +++++++++++++++++++++-
 e2e/events.test.ts   | 76 ++++++++++++++++++++++++++++++++++++++++++++
 e2e/index.html       |  7 ++++
 global.d.ts          |  3 +-
 6 files changed, 125 insertions(+), 4 deletions(-)
 create mode 100644 e2e/events.test.ts

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 59ab0b9..3925749 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -97,9 +97,10 @@ bun run test
 
 ### E2E Tests
 
-To run the end-to-end tests, use the following command:
+To run the end-to-end tests, make sure you have latest bundled file before running it. Use the following commands:
 
 ```bash
+bun run build
 bun run test:e2e
 ```
 
diff --git a/README.md b/README.md
index 175d5f4..a3c108c 100644
--- a/README.md
+++ b/README.md
@@ -157,7 +157,7 @@ reportEvent(config, event)
 400:
 ```json
 {
-  "status": 204,
+  "status": 400,
   "statusText": "No Content",
   "body": {
     "errCode": "bad_request",
diff --git a/e2e/auctions.test.ts b/e2e/auctions.test.ts
index fe605ec..73d6c60 100644
--- a/e2e/auctions.test.ts
+++ b/e2e/auctions.test.ts
@@ -47,7 +47,7 @@ test.describe("Create Auction via Topsort SDK", () => {
         ],
       };
       if (typeof window.sdk.createAuction === "undefined") {
-        throw new Error("Global function `createAuctions` is not available.");
+        throw new Error("Global function `createAuction` is not available.");
       }
 
       return window.sdk.createAuction(config, auctionDetails);
@@ -55,4 +55,40 @@ test.describe("Create Auction via Topsort SDK", () => {
 
     expect(result).toEqual(mockAPIResponse);
   });
+
+  test("should fail to call with missing apiKey", async ({ page }) => {
+    const expectedError = { status: 401, statusText: 'API Key is required.', body: {} }
+    await page.goto("http://localhost:8080/e2e");
+    const result = await page.evaluate(() => {
+      const config = {
+        apiKey: null
+      };
+
+      const auctionDetails = {
+        auctions: [
+          {
+            type: "listings",
+            slots: 3,
+            category: { id: "cat123" },
+            geoTargeting: { location: "US" },
+          },
+          {
+            type: "banners",
+            slots: 1,
+            device: "desktop",
+            slotId: "slot123",
+            category: { ids: ["cat1", "cat2"] },
+            geoTargeting: { location: "UK" },
+          },
+        ],
+      };
+      if (typeof window.sdk.createAuction === "undefined") {
+        throw new Error("Global function `createAuction` is not available.");
+      }
+
+      return window.sdk.createAuction(config, auctionDetails);
+    });
+
+    expect(result).toEqual(expectedError);
+  });
 });
diff --git a/e2e/events.test.ts b/e2e/events.test.ts
new file mode 100644
index 0000000..38b18b1
--- /dev/null
+++ b/e2e/events.test.ts
@@ -0,0 +1,76 @@
+import { expect, test } from "@playwright/test";
+import { apis, baseURL } from "../src/constants/apis.constant";
+
+test.describe("Report Events via Topsort SDK", () => {
+  test("should report an successfully", async ({ page }) => {
+    const mockAPIResponse = {
+      ok: true
+    }
+
+    await page.route(`${baseURL}/${apis.events}`, async (route) => {
+      await route.fulfill({ json: mockAPIResponse });
+    });
+
+    await page.goto("http://localhost:8080/e2e");
+    const result = await page.evaluate(() => {
+      const config = {
+        apiKey: "rando-api-key",
+      };
+
+      const event = {
+        impressions: [
+          {
+            resolvedBidId:
+              "ChAGaP5D2ex-UKEEBCOHwvDjEhABkF4FDAx0S5mMD2cOG0w9GhABkEnL2CB6qKIoqeItVgA_InsKd2h0dHBzOi8vd3d3LndlYmEuYmUvZnIvcHJvbW8uaHRtbD91dG1fc291cmNlPW15c2hvcGkmdXRtX21lZGl1bT1iYW5uZXJfMTI4MHg0MDAmdXRtX2NvbnRlbnQ9ZGlzcGxheSZ1dG1fY2FtcGFpZ249c29sZGVuEAU",
+            id: "1720706109.713344-53B92988-7A49-4679-B18E-465943B46149",
+            occurredAt: "2024-07-11T13:55:09Z",
+            opaqueUserId: "38e0a5ff-9f8a-4e80-8969-e5e3f01348e8",
+            placement: {
+              path: "/categories/sports",
+            },
+          },
+        ],
+      };
+
+      if (typeof window.sdk.reportEvent === "undefined") {
+        throw new Error("Global function `reportEvent` is not available.");
+      }
+
+      return window.sdk.reportEvent(config, event);
+    });
+
+    expect(result).toEqual(mockAPIResponse);
+  });
+
+  test("should fail to call with missing apiKey", async ({ page }) => {
+    const expectedError = { status: 401, statusText: 'API Key is required.', body: {} }
+    await page.goto("http://localhost:8080/e2e");
+    const result = await page.evaluate(() => {
+      const config = {
+        apiKey: null
+      };
+
+      const event = {
+        impressions: [
+          {
+            resolvedBidId:
+              "ChAGaP5D2ex-UKEEBCOHwvDjEhABkF4FDAx0S5mMD2cOG0w9GhABkEnL2CB6qKIoqeItVgA_InsKd2h0dHBzOi8vd3d3LndlYmEuYmUvZnIvcHJvbW8uaHRtbD91dG1fc291cmNlPW15c2hvcGkmdXRtX21lZGl1bT1iYW5uZXJfMTI4MHg0MDAmdXRtX2NvbnRlbnQ9ZGlzcGxheSZ1dG1fY2FtcGFpZ249c29sZGVuEAU",
+            id: "1720706109.713344-53B92988-7A49-4679-B18E-465943B46149",
+            occurredAt: "2024-07-11T13:55:09Z",
+            opaqueUserId: "38e0a5ff-9f8a-4e80-8969-e5e3f01348e8",
+            placement: {
+              path: "/categories/sports",
+            },
+          },
+        ],
+      };
+      if (typeof window.sdk.reportEvent === "undefined") {
+        throw new Error("Global function `reportEvent` is not available.");
+      }
+
+      return window.sdk.reportEvent(config, event);
+    });
+
+    expect(result).toEqual(expectedError);
+  });
+});
diff --git a/e2e/index.html b/e2e/index.html
index 52f40ad..9b1cedd 100644
--- a/e2e/index.html
+++ b/e2e/index.html
@@ -17,6 +17,13 @@ 

Test Topsort.js Integration

).catch((error) => error); return result; }, + reportEvent: async (config, eventDetails) => { + const result = await Topsort.reportEvent( + config, + eventDetails + ).catch((error) => error); + return result; + }, }; diff --git a/global.d.ts b/global.d.ts index 41758e2..8aa34ae 100644 --- a/global.d.ts +++ b/global.d.ts @@ -1,5 +1,6 @@ interface Window { sdk: { - createAuction: (a, b) => void; + createAuction: (a, b) => unknown, + reportEvent: (a, b) => unknown, }; } From c5d63eb232de74ce70fa00d67c7843b446ac7382 Mon Sep 17 00:00:00 2001 From: barbmarcio Date: Fri, 19 Jul 2024 19:58:26 +0100 Subject: [PATCH 07/10] fix: biome formatting --- bunfig.toml | 2 +- e2e/auctions.test.ts | 4 ++-- e2e/events.test.ts | 8 ++++---- global.d.ts | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/bunfig.toml b/bunfig.toml index 101803d..61328de 100644 --- a/bunfig.toml +++ b/bunfig.toml @@ -1,3 +1,3 @@ [test] coverage = true -root = "./test" \ No newline at end of file +root = "./test" diff --git a/e2e/auctions.test.ts b/e2e/auctions.test.ts index 73d6c60..63b963f 100644 --- a/e2e/auctions.test.ts +++ b/e2e/auctions.test.ts @@ -57,11 +57,11 @@ test.describe("Create Auction via Topsort SDK", () => { }); test("should fail to call with missing apiKey", async ({ page }) => { - const expectedError = { status: 401, statusText: 'API Key is required.', body: {} } + const expectedError = { status: 401, statusText: "API Key is required.", body: {} }; await page.goto("http://localhost:8080/e2e"); const result = await page.evaluate(() => { const config = { - apiKey: null + apiKey: null, }; const auctionDetails = { diff --git a/e2e/events.test.ts b/e2e/events.test.ts index 38b18b1..400223c 100644 --- a/e2e/events.test.ts +++ b/e2e/events.test.ts @@ -4,8 +4,8 @@ import { apis, baseURL } from "../src/constants/apis.constant"; test.describe("Report Events via Topsort SDK", () => { test("should report an successfully", async ({ page }) => { const mockAPIResponse = { - ok: true - } + ok: true, + }; await page.route(`${baseURL}/${apis.events}`, async (route) => { await route.fulfill({ json: mockAPIResponse }); @@ -43,11 +43,11 @@ test.describe("Report Events via Topsort SDK", () => { }); test("should fail to call with missing apiKey", async ({ page }) => { - const expectedError = { status: 401, statusText: 'API Key is required.', body: {} } + const expectedError = { status: 401, statusText: "API Key is required.", body: {} }; await page.goto("http://localhost:8080/e2e"); const result = await page.evaluate(() => { const config = { - apiKey: null + apiKey: null, }; const event = { diff --git a/global.d.ts b/global.d.ts index 8aa34ae..f9bc02d 100644 --- a/global.d.ts +++ b/global.d.ts @@ -1,6 +1,6 @@ interface Window { sdk: { - createAuction: (a, b) => unknown, - reportEvent: (a, b) => unknown, + createAuction: (a, b) => unknown; + reportEvent: (a, b) => unknown; }; } From ce16f32cc5c70c78917b141667d4f6deabc258ba Mon Sep 17 00:00:00 2001 From: barbmarcio Date: Fri, 19 Jul 2024 20:20:23 +0100 Subject: [PATCH 08/10] feat: adding playwright port to env file --- .env.example | 1 + .gitignore | 2 ++ CONTRIBUTING.md | 4 ++++ e2e/auctions.test.ts | 5 +++-- e2e/constants.ts | 3 +++ e2e/events.test.ts | 5 +++-- playwright.config.ts | 2 +- 7 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 .env.example create mode 100644 e2e/constants.ts diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..f7baccf --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +PLAYWRIGHT_PORT= diff --git a/.gitignore b/.gitignore index aace4f7..64b0d86 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.env + coverage/ dist/ node_modules/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3925749..8b5b61d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -97,6 +97,7 @@ bun run test ### E2E Tests +By default, the application is set to serve a web browser in the port `8080` for Playwright. If this port is already being used on your local machine, make sure you change the port in your `.env`.`PLAYWRIGHT_PORT`. To run the end-to-end tests, make sure you have latest bundled file before running it. Use the following commands: ```bash @@ -137,5 +138,8 @@ The SDK uses following configuration files: - `tsup.config.ts`: Configuration for the TSUP bundler. - `playwright.config.ts`: Configuration for E2E tests runner +We also have the following variables as part of the `.env` file: +- `PLAYWRIGHT_PORT`: Port used to run the local web browser to run Playwright E2E tests. + ## License This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details. diff --git a/e2e/auctions.test.ts b/e2e/auctions.test.ts index 63b963f..07cb2c7 100644 --- a/e2e/auctions.test.ts +++ b/e2e/auctions.test.ts @@ -1,5 +1,6 @@ import { expect, test } from "@playwright/test"; import { apis, baseURL } from "../src/constants/apis.constant"; +import { playwrightConstants } from "./constants"; test.describe("Create Auction via Topsort SDK", () => { test("should create an auction successfully", async ({ page }) => { @@ -22,7 +23,7 @@ test.describe("Create Auction via Topsort SDK", () => { await route.fulfill({ json: mockAPIResponse }); }); - await page.goto("http://localhost:8080/e2e"); + await page.goto(playwrightConstants.url); const result = await page.evaluate(() => { const config = { apiKey: "rando-api-key", @@ -58,7 +59,7 @@ test.describe("Create Auction via Topsort SDK", () => { test("should fail to call with missing apiKey", async ({ page }) => { const expectedError = { status: 401, statusText: "API Key is required.", body: {} }; - await page.goto("http://localhost:8080/e2e"); + await page.goto(playwrightConstants.url); const result = await page.evaluate(() => { const config = { apiKey: null, diff --git a/e2e/constants.ts b/e2e/constants.ts new file mode 100644 index 0000000..2864308 --- /dev/null +++ b/e2e/constants.ts @@ -0,0 +1,3 @@ +export const playwrightConstants = { + url: `http://localhost:${process.env.PLAYWRIGHT_PORT || 8080}/e2e`, +} \ No newline at end of file diff --git a/e2e/events.test.ts b/e2e/events.test.ts index 400223c..9b92682 100644 --- a/e2e/events.test.ts +++ b/e2e/events.test.ts @@ -1,5 +1,6 @@ import { expect, test } from "@playwright/test"; import { apis, baseURL } from "../src/constants/apis.constant"; +import { playwrightConstants } from "./constants"; test.describe("Report Events via Topsort SDK", () => { test("should report an successfully", async ({ page }) => { @@ -11,7 +12,7 @@ test.describe("Report Events via Topsort SDK", () => { await route.fulfill({ json: mockAPIResponse }); }); - await page.goto("http://localhost:8080/e2e"); + await page.goto(playwrightConstants.url); const result = await page.evaluate(() => { const config = { apiKey: "rando-api-key", @@ -44,7 +45,7 @@ test.describe("Report Events via Topsort SDK", () => { test("should fail to call with missing apiKey", async ({ page }) => { const expectedError = { status: 401, statusText: "API Key is required.", body: {} }; - await page.goto("http://localhost:8080/e2e"); + await page.goto(playwrightConstants.url); const result = await page.evaluate(() => { const config = { apiKey: null, diff --git a/playwright.config.ts b/playwright.config.ts index 352e5e8..94b2487 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -23,7 +23,7 @@ export default defineConfig({ }, ], webServer: { - command: "http-server ./ -p 8080", + command: `http-server ./ -p ${process.env.PLAYWRIGHT_PORT || 8080}`, reuseExistingServer: !process.env.CI, stdout: "ignore", stderr: "pipe", From 1be8541838396bd8902d81125af6ccd4c6e54567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rcio=20Barbosa?= <52362496+barbmarcio@users.noreply.github.com> Date: Wed, 24 Jul 2024 17:52:33 +0100 Subject: [PATCH 09/10] feat: use `bun serve` in http tests Drops a dependency and simplifies serving assets related to e2e tests. --- .env.example | 2 +- bun.lockb | Bin 107822 -> 93319 bytes e2e/auctions.test.ts | 6 +++--- e2e/config.ts | 3 +++ e2e/constants.ts | 3 --- e2e/events.test.ts | 6 +++--- e2e/{ => public}/index.html | 2 +- e2e/server.ts | 22 ++++++++++++++++++++++ package.json | 5 ++--- playwright.config.ts | 4 ++-- tsconfig.json | 2 +- tsup.config.ts | 1 + 12 files changed, 39 insertions(+), 17 deletions(-) create mode 100644 e2e/config.ts delete mode 100644 e2e/constants.ts rename e2e/{ => public}/index.html (93%) create mode 100644 e2e/server.ts diff --git a/.env.example b/.env.example index f7baccf..9b47526 100644 --- a/.env.example +++ b/.env.example @@ -1 +1 @@ -PLAYWRIGHT_PORT= +SERVER_PORT= diff --git a/bun.lockb b/bun.lockb index 70f493ae65a05a11cd764fbc7a95e4bfb7b70b8f..500b13a69b0e7d58eabb5f3e3b0456bbda350dc3 100755 GIT binary patch delta 12911 zcmeHOdtB93w*T!T2l!#A2m*)0OHD;ZGDI$`hASkAR3TSz&>EUBn z+tMqAke_uUU3cGUkVmrq%WVO?YO-J>?|s3Uz<*Yk_s(%7W4olH0+z0$)@y z;hy4>iCT?^rnLoM0!;dOzyZKnraa!{LxBS!*Ma?OKwNHNbUX%39rgf|LY>J!4;%#k z5mR0XOal~|?Zbg-V3)~v1*ZOiz@*23+X0`o81@eVQ~TS%J!rs1DF{}z9pr~Ajh@w$k(PL6c*#yne+URr6l-GmzL;ErC zErBP@C@3td(6qmjJ_u+RRAEDJw@pKv|>GTVIK z<-nA(%EGc~nnp=Fp;FU^#~MqV4XmU6QmnamN{ePpDvH;%Z}>24P}lWw#&#};gi_^A zU?|oeM7K7;6N_iat@j{bVvUGfo@i)4226u40H$8EOssZ733$q0)8#l&l1nB*5=fF^yyG}OUm=p6u0j=Td*12YUv zddEzM4gk~s++pI^fhjzOT^{Jw*6(tr(e)%S&EW`ldUau|d4X3@4ZF>l|LK0lxpD}Y z;!$t%>w#(b<)-{WV2V=(Fl{DyBcpw|zcCHve)s@`N9IU(p8!v*a(6}1tfFZ%D{KR$ zFMVsV7}Ecx*+w$Y2BzG~2Mz`v2uufFEHEXt4LAsxneC?sZknNIc=3~dAF@1N*Ve_h z@dkX39*}B104hsTcB`fhkW?WkqjgP_ z>^!I(*_!I9ddvr9=)DWd=3B=ZlmuWFtTs zMeFW{7__2KpK@Fci9rLFm?$=*nR zBsIAk08`*-7!R7B{)x#Us4(n8{>G!t!ZXn}y@|sj=)VV-CEJL*1dd#g;nS0m=h$E1 z$f0uX?Bqh=Dm%G!U+fHO@!|*^yNx$=a#vU=EU_j zIS*cs89xk;=3$Y`b%p2r0SX|YX>D8)~r4 zY1$}BRf95QpMn}LWzpR=Z7iRckmdoRSc)!yDv;E0Y^$-7+5l>jq=I^AT9KsYg36cF zXH8T}jOrmk8LgK<84e8Tsc9prhyEfc+?=#HogMm7aK=f1#Mj%!YFZN7TFR|84jd(e zagMCu&SV$UcqKm5cpW~=c>_MTbEnf~xfsW*oEfY;uXDQex!8h~SvUx~IrQD&jBLn^ za_D{unuhz9jAHnq;AnTXkUL=sI3vR-&v%0(*KmX)7aPIR&NlXI92$tT(tg#~fx8_X zY@*+FaD5C8XFvw#L%v|QV6Ro1oT2#^IGP|fY%=M%L6Sw-LPSiv%VJ`wIM#R_(zkIr!YIi z>-xI%Xc#hLotf-lCEVH1rLTbuFGI$<;Vh`@=VCFu0WD=ngWJ%e@%c`N{wHuo&aiNY z^+#~n=V7UO8iekAnFFq$^nuQ&t>EAWe5Wk94vrEV(Fk=g2XDx7u^HUi-^E_$mHk~- z?>_P>4^P$a07bDuw2_0$z>$aT$cpt-aLMu%^XqG@D~|5;WZp2qrB|2|taN&^HyCoo zONQezI9g7G17S=>194c2{tmr8W;wKpn+}ea&}e)2Z`#_yD|cHlxSS@<*TA{0So<3( zZ&(=)?hd7CS>2ys9g$%<)}N>3W>~rm;8j2c1NiGeD+lnaKu09fqXw!Z#DZDJgX_<4 zv_6tm&Fxi_(-$2M<5jF6!chRo`nszsU)F%^z=VnaW#Q?%n z0Q3+h{SspE5T@a00BD$d0Hi+)Ko4P(R}zEgCR`&Gt01HfbEp*$Vd_u~Ai0qw1}6Ce z06qT-liot9Wngmn0h4!QSPp{lS+n8)9IKiAnt^G@ZZIeCOL5IF?eI(VDJTAHI!4$E zcmqI7u?2vqmn2BA6+mmf4M5K}0LixlNd7i}9*KEaegu!6>}}H_*(2qDiy0rAAH+-Y zy#c{|MSdF_DSZf_XnhSJo5uhe-!j?Q2FJmW%iod|4`K4)3^90`!_0psUjQtBRog%ua|F1Claf_)(nEY=AOd|Y5 zEXOB8qr)tSq`wlAiC}!tKq0`y)35A=Lrok8OzjcO7#{>UDKH%AV)Fl6OtvUO1oRMY z_MS7xmlvM&2#Wuqi;l+qw-;v3ueeEn)&Mu#r=b4bJ(nRbJZfm}f};^g{@X=|Aka?w z?V|hH_mvzg=`jOm4pLe!J+Jzxe*2Uvxu^mHdxgben7?_YdLLorCzv zH+=cnor5f=H2%uYT)ym0U+%kWkma<-NAJqz1Gf0`Env@T+-G+#zXG;&_aMu8jlaG- z*Ycgl+rFP``Cj8wfG%i!JJ1gr580Dz`BCFDfG%o$7tke*ci5Y2xvcT3z2C61O$8r3 zY+>JRI=k;0vrG)&x9`v88`^s4odS)&dGy>gc>f0$srNCHE$T0LeAA6jwzgoUo31FU)lJmK5DRb29!$h424g`Lmz#X>EsZTet9G`-jsAHud+G!jj^cDHX;W zhLrK|_eGFKxcL{D+M6{d6ql9Kx1%)!H$8SdJhtUm7mbzr@RBBCLRki#V?Q+-549Ww z(0vK7<)e6-L2FZX2$*yzC+S^?o=*TodH~dm<)@%Yhu)LF2hei_Kzj6I`XfM|qo12X zdXE_kpyvw!DbnSvzNmc(nhergatVOiz6Ow<4`3RAWXAv`YY8X^kc{4jNv2(<4^4ag zszhQ=7;7(|qpyvw#zTQvmXbeEk6Mj<7|rj%h1)K*^ z{C@yY%qayf0VopJ0DA!ifC+#?z}tX712zL*2P^>G2e=fUSU1Kp9{< zpcs%1*iJ*v2eA^+7eH^}7l5w-t^yeNM&R)PN)}2EN`_iMHGsa9ZzDxKcQtBaHWI;; zLUmf(Z0W#qJ+e=N`4&LSw+pZnK+Ad#Kub&Uqc~DLDXtV>@_=If9bhpHkLSO_M0FQ- zuV@p+ZfAWq=SQ&?YzQgn@TS|->lVLIRWirI#>K_N$HZg1z;Pe696$4V$hOEE`z)*h zy0<{0ieAoKnechOzjq?~B*nzW#A5PdV^?NlUB&LMEP2%~_+slbYvZ>#Jy>i^d;(dgdWQfQde3X9 z$U0fN-Q99XgmuSAsxTt>>eaYAcJ(T9D=;w(3M^1eB|TM$;TzQN)U)em?QrY4#7a_7 zg%QPdX)h&umVV<_C=wfcu>eo$Po+3ZMjsLL9ZK}PXdewxok#_;s{)Xc@y|CNTvC_m zHgimrK_N*MVw`w#=7m+ROK-RpR4K=U9x z(6_4!rt}}SZQRu+X|fzeD(n|MdLka3{mg9aIpF%0F##9cZm6QExt?Q}r$4fK8d~5u zWkr>kgRXW}rL(-<=5Iq5zBv^Nu`vmh$bn*gPs|`f9P5cJixqLP%x1aVR^-I8V7n@Z zy5pgP>%#N0eb6ltcHwhtQ4`C$`{el>NpE%#@5izbyQ*2*7ShS{jr{RnNpG-kG;N(= zaR|_6VF$8rN4mB_#@gDpExEH}>;0x4y#7cGAq7=kHMF|q%_AE(y$S_0?u*2Iaqv1& zY>tE1r-U`0bx&U(WE7dG+N$r~nODBz(EA^wTO4)?!lA0GMr}Q3UGc@)D6~LK^Vu&- z<1ylRn^DH`>?=!82e$iYArz9K0M|>!DkxYQY~sy$L?$%E@cqiwIg_{NJ-*t)tdPKg z+GueeibDp0Z3TAXsJFL2+xj`Hh4q4@9VDtWWyHs4ZmlY7GfIvTM~gKJ8otno^ZEXC zx2ymU3!4B5ZR#yzOeWk@)m=AA*oN{B{SKpRB60{_qs1apP-S4F*^1AyF0U+y0v$e> zV6@npfE-d~TxTYZ9`SkFwtnUWVZo>v(`sKWi~Cc_xx#1BV&+h_@J)nmRWY_N@0AY+ z{&NS9M}Xf7-JyD$#ct z#;3Cuu9pbEBp6yK@{?FlSge*AX+(Pbz`~Xt9vVSWNHC%xRcyVQJtX5|l5jb2v3LKez8Ew?>K>mJF+TVk(ebRlg;FH)lwzHV^D`>pdw} zLZO!`m%B3Vsp`ZPyBggJs-W(h%ue1H`}TXs-O>;x&XE(S!ILF;OXr7n#ywr1uB$kdw`4*`j3%)K#V3-s4-!mpyjzOJpFO z<=90Bg^Luv0oexoc5C$V!>J>Jv(02qz$>PxNWtZBDOS9c!s2l`dHk<#u1zKo6nB@hr2VL!|FfU_4@!1sx(H7Gw zjOr)wJ;25~2vkzp?5fhRVU_=muxTyor4R8=IFTiWKp{z$C>E_7dfUvDtsTvg;G`;M zy!K3Lm#Bn{FtlK;DcAdmXEJdA$e9L+#tddj9D88@5%!;F6xBAMN~Fx)WXFF{Q*9=LInx3d|xNCOuU*`ND`7UU_Qw=t9zq z!NHB2R%|6b!xeio$)WPY%+Fc68y?|;jzgYy z5H|+G&BO?s+q)cWU1(-Y^6Tk6(hq7e#~ z!~MmEfh;&l)r0%>^}(M_hy~xON?1oM>b+oH z_SYTV8XwZve>{uBMcyD*&T_=gK`f&E;}H4djNJ8uNUyH1Jii7!otc*%i(l;eqAg*A z&~sQs|5biQZSiL#=DaX+ZKUm0@bm?5e$a?kjRA>Y`~`d)@b5bFhr4E_9NI=dG~hXJ s{=X2Pw0n{>BICs3E-Y9)ki+_JK9Iu-`-|&KnO%fE!o1eRtYn`50}o+if&c&j delta 21967 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 diff --git a/e2e/auctions.test.ts b/e2e/auctions.test.ts index 07cb2c7..4c55b7d 100644 --- a/e2e/auctions.test.ts +++ b/e2e/auctions.test.ts @@ -1,6 +1,6 @@ import { expect, test } from "@playwright/test"; import { apis, baseURL } from "../src/constants/apis.constant"; -import { playwrightConstants } from "./constants"; +import { playwrightConstants } from "./config"; test.describe("Create Auction via Topsort SDK", () => { test("should create an auction successfully", async ({ page }) => { @@ -23,7 +23,7 @@ test.describe("Create Auction via Topsort SDK", () => { await route.fulfill({ json: mockAPIResponse }); }); - await page.goto(playwrightConstants.url); + await page.goto(playwrightConstants.host); const result = await page.evaluate(() => { const config = { apiKey: "rando-api-key", @@ -59,7 +59,7 @@ test.describe("Create Auction via Topsort SDK", () => { test("should fail to call with missing apiKey", async ({ page }) => { const expectedError = { status: 401, statusText: "API Key is required.", body: {} }; - await page.goto(playwrightConstants.url); + await page.goto(playwrightConstants.host); const result = await page.evaluate(() => { const config = { apiKey: null, diff --git a/e2e/config.ts b/e2e/config.ts new file mode 100644 index 0000000..008e530 --- /dev/null +++ b/e2e/config.ts @@ -0,0 +1,3 @@ +export const playwrightConstants = { + host: `http://localhost:${process.env.SERVER_PORT || 8080}/index.html`, +}; diff --git a/e2e/constants.ts b/e2e/constants.ts deleted file mode 100644 index 2864308..0000000 --- a/e2e/constants.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const playwrightConstants = { - url: `http://localhost:${process.env.PLAYWRIGHT_PORT || 8080}/e2e`, -} \ No newline at end of file diff --git a/e2e/events.test.ts b/e2e/events.test.ts index 9b92682..57408e5 100644 --- a/e2e/events.test.ts +++ b/e2e/events.test.ts @@ -1,6 +1,6 @@ import { expect, test } from "@playwright/test"; import { apis, baseURL } from "../src/constants/apis.constant"; -import { playwrightConstants } from "./constants"; +import { playwrightConstants } from "./config"; test.describe("Report Events via Topsort SDK", () => { test("should report an successfully", async ({ page }) => { @@ -12,7 +12,7 @@ test.describe("Report Events via Topsort SDK", () => { await route.fulfill({ json: mockAPIResponse }); }); - await page.goto(playwrightConstants.url); + await page.goto(playwrightConstants.host); const result = await page.evaluate(() => { const config = { apiKey: "rando-api-key", @@ -45,7 +45,7 @@ test.describe("Report Events via Topsort SDK", () => { test("should fail to call with missing apiKey", async ({ page }) => { const expectedError = { status: 401, statusText: "API Key is required.", body: {} }; - await page.goto(playwrightConstants.url); + await page.goto(playwrightConstants.host); const result = await page.evaluate(() => { const config = { apiKey: null, diff --git a/e2e/index.html b/e2e/public/index.html similarity index 93% rename from e2e/index.html rename to e2e/public/index.html index 9b1cedd..0165b8e 100644 --- a/e2e/index.html +++ b/e2e/public/index.html @@ -4,7 +4,7 @@ Topsort SDK Test Application - +

Test Topsort.js Integration

diff --git a/e2e/server.ts b/e2e/server.ts new file mode 100644 index 0000000..d9a8a45 --- /dev/null +++ b/e2e/server.ts @@ -0,0 +1,22 @@ +import { file } from "bun"; + +const PORT = process.env.SERVER_PORT || 8080; + +Bun.serve({ + fetch(req) { + const url = new URL(req.url); + const pathname = url.pathname === "/" ? "/index.html" : url.pathname; + const filePath = `./dist${pathname}`; + + try { + if (filePath.endsWith(".ico")) { + return new Response("", { status: 204 }); + } + + return new Response(file(filePath)); + } catch (e) { + return new Response("Not Found", { status: 404 }); + } + }, + port: PORT, +}); diff --git a/package.json b/package.json index 926bd26..214358f 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,6 @@ "CHANGELOG.md", "LICENSE", "README.md", - "dist/index.global.js", "dist/index.d.mts", "dist/index.d.ts", "dist/index.js", @@ -36,13 +35,13 @@ "test:e2e": "playwright test", "format": "biome check", "format:fix": "biome check --write", - "prepare": "lefthook install" + "prepare": "lefthook install", + "serve:e2e": "bun run ./e2e/server.ts" }, "devDependencies": { "@biomejs/biome": "1.8.3", "@playwright/test": "^1.45.2", "@types/bun": "1.1.6", - "http-server": "^14.1.1", "lefthook": "1.7.2", "msw": "2.3.1", "tsup": "8.1.0", diff --git a/playwright.config.ts b/playwright.config.ts index 94b2487..b7af23b 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -3,7 +3,7 @@ import { defineConfig, devices } from "@playwright/test"; export default defineConfig({ testDir: "./e2e", timeout: 30000, - retries: 1, + retries: 0, reporter: [["list"], ["json", { outputFile: "test-results.json" }]], use: { trace: "on-first-retry", @@ -23,7 +23,7 @@ export default defineConfig({ }, ], webServer: { - command: `http-server ./ -p ${process.env.PLAYWRIGHT_PORT || 8080}`, + command: "bun run serve:e2e", reuseExistingServer: !process.env.CI, stdout: "ignore", stderr: "pipe", diff --git a/tsconfig.json b/tsconfig.json index 4eb4110..531c5f2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,6 +17,6 @@ "allowJs": true, "types": ["node"] }, - "include": ["src/*.ts", "src/**/*.ts"], + "include": ["src/*.ts", "src/**/*.ts", "e2e/server.ts"], "exclude": ["node_modules"] } diff --git a/tsup.config.ts b/tsup.config.ts index a51cc34..49225ea 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -10,4 +10,5 @@ export default defineConfig({ options.keepNames = true; options.globalName = "Topsort"; }, + onSuccess: "cp -r ./e2e/public/* dist", }); From 472353d8e5ce400e1ce085ea282156ca0e75e879 Mon Sep 17 00:00:00 2001 From: barbmarcio Date: Thu, 25 Jul 2024 02:45:58 +0100 Subject: [PATCH 10/10] feat: adding browser installation on contribution docs --- CONTRIBUTING.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8b5b61d..d805965 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -97,8 +97,16 @@ bun run test ### E2E Tests -By default, the application is set to serve a web browser in the port `8080` for Playwright. If this port is already being used on your local machine, make sure you change the port in your `.env`.`PLAYWRIGHT_PORT`. -To run the end-to-end tests, make sure you have latest bundled file before running it. Use the following commands: +By default, the application is set to serve a web browser in the port `8080` for Playwright. If this port is already being used on your local machine, make sure you change the port in your `.env`.`SERVER_PORT`. +To run the end-to-end tests, make sure you have installed the browsers supported by playwright by running this command: + +```bash +npx playwright install +``` + +Please refer to [Playwright Documentation](https://playwright.dev/docs/browsers) for details. + +Then, also make sure you have the latest bundled files before running it. Use the following commands: ```bash bun run build