diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 0000000..84a9976 --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,42 @@ +name: Playwright Tests +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] +jobs: + test: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: lts/* + - name: Install dependencies + run: npm ci + - name: Install Playwright Browsers + run: npx playwright install --with-deps + - name: Build Next.js app + run: npm run build + - name: Start Next.js app + run: npm run start & + - name: Wait for Next.js to start + run: | + timeout=30 + while ! nc -z localhost 3000; do + if [ $timeout -le 0 ]; then + echo "Timed out waiting for Next.js to start" + exit 1 + fi + sleep 1 + ((timeout--)) + done + - name: Run Playwright tests + run: npx playwright 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 d879e86..ed3da21 100644 --- a/.gitignore +++ b/.gitignore @@ -36,4 +36,8 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts -node_modules \ No newline at end of file +node_modules +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/package-lock.json b/package-lock.json index 7d3feed..b4ffee7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@next/third-parties": "^14.2.9", "@novu/framework": "^2.1.0", "@novu/node": "^2.0.1", - "@novu/react": "^2.3.0", + "@novu/react": "^2.5.0", "@paralleldrive/cuid2": "^2.2.2", "@react-email/components": "0.0.22", "axios": "^1.7.4", @@ -35,6 +35,7 @@ "zod-to-json-schema": "^3.23.2" }, "devDependencies": { + "@playwright/test": "^1.48.1", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", @@ -2263,9 +2264,9 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/@novu/js": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@novu/js/-/js-2.3.0.tgz", - "integrity": "sha512-HkLeWa1L/adizBManmQETsWifJCgRydUiEd4AKVp7ACiKLGhabTfU7VyzMKOC1+WQ+266e39mYcWkSdm/lkrEw==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@novu/js/-/js-2.5.0.tgz", + "integrity": "sha512-pAlTIYD2YVd0es2I8UJ9eT0laYHhGkHiehBq0R3NZfDS30RVttpjiZBMpA0uk+/+uxI1jMk1VEl1EQiefuhGyQ==", "dependencies": { "@floating-ui/dom": "^1.6.7", "@novu/client": "^2.0.0", @@ -2297,11 +2298,11 @@ } }, "node_modules/@novu/react": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@novu/react/-/react-2.3.0.tgz", - "integrity": "sha512-UQLD1nm2KX2n0p6iztAQwOJwqInbKcV23gF6ESaEhMG0TcyiLCNfhcpBmL5QXK/0xEzwsvMJmtXcYdU0NQWmLg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@novu/react/-/react-2.5.0.tgz", + "integrity": "sha512-Q8BKjmkws3zgz8fZNRMDSNmmE/lmPPGO+0Z/zejGuD9bbKEYN2Z6eXphrA4QZy1iHgy5SmmmP8ksPNxC5AAk1Q==", "dependencies": { - "@novu/js": "^2.3.0" + "@novu/js": "^2.5.0" }, "peerDependencies": { "react": ">=17", @@ -2363,6 +2364,21 @@ "node": ">=14" } }, + "node_modules/@playwright/test": { + "version": "1.48.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.1.tgz", + "integrity": "sha512-s9RtWoxkOLmRJdw3oFvhFbs9OJS0BzrLUc8Hf6l2UdCNd1rqeEyD4BhCJkvzeEoD1FsK4mirsWwGerhVmYKtZg==", + "devOptional": true, + "dependencies": { + "playwright": "1.48.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@popperjs/core": { "version": "2.11.8", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", @@ -7160,6 +7176,50 @@ "node": ">= 6" } }, + "node_modules/playwright": { + "version": "1.48.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.1.tgz", + "integrity": "sha512-j8CiHW/V6HxmbntOfyB4+T/uk08tBy6ph0MpBXwuoofkSnLmlfdYNNkFTYD6ofzzlSqLA1fwH4vwvVFvJgLN0w==", + "devOptional": true, + "dependencies": { + "playwright-core": "1.48.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.48.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.1.tgz", + "integrity": "sha512-Yw/t4VAFX/bBr1OzwCuOMZkY1Cnb4z/doAFSwf4huqAGWmf9eMNjmK7NiOljCdLmxeRYcGPPmcDgU0zOlzP0YA==", + "devOptional": true, + "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, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -8177,9 +8237,9 @@ } }, "node_modules/solid-js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.1.tgz", - "integrity": "sha512-Gd6QWRFfO2XKKZqVK4YwbhWZkr0jWw1dYHOt+VYebomeyikGP0SuMflf42XcDuU9HAEYDArFJIYsBNjlE7iZsw==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.2.tgz", + "integrity": "sha512-fe/K03nV+kMFJYhAOE8AIQHcGxB4rMIEoEyrulbtmf217NffbbwBqJnJI4ovt16e+kaIt0czE2WA7mP/pYN9yg==", "dependencies": { "csstype": "^3.1.0", "seroval": "^1.1.0", @@ -8571,9 +8631,9 @@ "integrity": "sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==" }, "node_modules/tailwind-merge": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.2.tgz", - "integrity": "sha512-kjEBm+pvD+6eAwzJL2Bi+02/9LFLal1Gs61+QB7HvTfQQ0aXwC5LGT8PEt1gS0CWKktKe6ysPTAy3cBC5MeiIg==", + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.4.tgz", + "integrity": "sha512-0q8cfZHMu9nuYP/b5Shb7Y7Sh1B7Nnl5GqNr1U+n2p6+mybvRtayrQ+0042Z5byvTA8ihjlP8Odo8/VnHbZu4Q==", "funding": { "type": "github", "url": "https://github.com/sponsors/dcastil" diff --git a/package.json b/package.json index 3bca07b..7a09e41 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,9 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "next dev", + "dev": "next dev --port 3005", "build": "next build", - "start": "next start", + "start": "next start --port 3005", "lint": "next lint", "format": "prettier --write \"**/*.{css,js,jsx,ts,tsx,json}\"" }, @@ -37,6 +37,7 @@ "zod-to-json-schema": "^3.23.2" }, "devDependencies": { + "@playwright/test": "^1.48.1", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..311fddd --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,79 @@ +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://127.0.0.1:3005", + + /* 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://127.0.0.1:3000', + // reuseExistingServer: !process.env.CI, + // }, +}); diff --git a/tests/inbox.spec.ts b/tests/inbox.spec.ts new file mode 100644 index 0000000..247b73a --- /dev/null +++ b/tests/inbox.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from "@playwright/test"; + +test("loads inbox playground", async ({ page }) => { + await page.goto("/"); + + await expect(page.locator(".nv-notificationList")).toBeVisible(); + await expect(page.locator(".nv-inboxStatus__title")).toBeVisible(); +});