diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..1faf1bb0 --- /dev/null +++ b/.envrc @@ -0,0 +1,5 @@ +# shellcheck shell=bash +if ! has nix_direnv_version || ! nix_direnv_version 3.0.5; then + source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.5/direnvrc" "sha256-RuwIS+QKFj/T9M2TFXScjBsLR6V3A17YVoEW/Q6AZ1w=" +fi +use flake diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b31e1392..0f22b196 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -138,6 +138,43 @@ jobs: - name: Test run: pnpm run test + test-e2e: + name: E2E test + runs-on: ubuntu-latest + timeout-minutes: 25 + needs: build + env: + NODE_VERSION: 22 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Cache turbo build setup + uses: actions/cache@v4 + with: + path: .turbo + key: ${{ runner.os }}-${{ env.NODE_VERSION }}-turbo-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-${{ env.NODE_VERSION }}-turbo- + + - name: Setup PNPM + uses: pnpm/action-setup@v2 + + - name: Setup node@${{ env.NODE_VERSION }} + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: "pnpm" + + - name: Install dependencies + run: pnpm install + + - name: Install Playwright browsers + run: pnpm dlx playwright@latest install --with-deps + + - name: Test + run: pnpm test:e2e + duplicated-packages: name: Check for duplicated dependencies runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index ae4d3254..40f2b3d2 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ node_modules/ /turbo/cache-key.json .pnpm-store .parcel-cache +.direnv # dotenv environment variable files .env @@ -56,3 +57,10 @@ dist/ build/ .inox-tools/ *.js.map + +# Test results +test-results/ +test-results/ +playwright-report/ +blob-report/ +playwright/.cache/ diff --git a/docs/turbo.json b/docs/turbo.json index 65df999a..f468ebef 100644 --- a/docs/turbo.json +++ b/docs/turbo.json @@ -1,9 +1,20 @@ { "$schema": "https://turbo.build/schema.json", - "extends": ["//"], + "extends": [ + "//" + ], "tasks": { "build": { - "inputs": ["*", "src/**", "public/**", "../packages/*/package.json"] + "inputs": [ + "*", + "src/**", + "public/**", + "../packages/*/package.json" + ], + "outputs": [ + ".vercel", + ".astro" + ] } } } diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..657ad2e7 --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1726203198, + "narHash": "sha256-2W3/zcYtZXdLtSyuC8vtAaCU7LCW727q2hxWOd+yC7U=", + "owner": "Fryuni", + "repo": "nixpkgs", + "rev": "aaaf317d6bc5936da1713e06544c2523d007b191", + "type": "github" + }, + "original": { + "owner": "Fryuni", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..caf628d8 --- /dev/null +++ b/flake.nix @@ -0,0 +1,62 @@ +{ + description = "A collection of oxygen-free tools for astronauts."; + inputs = { + nixpkgs.url = "github:Fryuni/nixpkgs/master"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { + nixpkgs, + flake-utils, + ... + }: + flake-utils.lib.eachDefaultSystem ( + system: let + throwSystem = throw "Unsupported system: ${system}"; + pkgs = nixpkgs.legacyPackages.${system}; + + browsersInfo = builtins.fromJSON (builtins.readFile "${pkgs.playwright-driver}/browsers.json"); + in { + devShells.default = pkgs.mkShell { + packages = [ + pkgs.nodejs_20 + pkgs.corepack_20 + pkgs.playwright + ]; + + PLAYWRIGHT_NODEJS_PATH = "${pkgs.nodejs_20}/bin/node"; + PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS = true; + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD = 1; + PLAYWRIGHT_BROWSERS_PATH = "${pkgs.playwright-driver.browsers}"; + + PLAYWRIGHT_CHROME_BIN = let + chromeInfo = pkgs.lib.lists.findFirst (b: b.name == "chromium") (throw "value not found") browsersInfo.browsers; + chromePath = + { + x86_64-linux = "chrome-linux/chrome"; + aarch64-linux = "chrome-linux/chrome"; + x86_64-darwin = "chrome-mac/Chromium.app/Contents/MacOS/Chromium"; + arm64-darwin = "chrome-mac/Chromium.app/Contents/MacOS/Chromium"; + } + .${system} + or throwSystem; + in "${pkgs.playwright-driver.browsers}/chromium-${chromeInfo.revision}/${chromePath}"; + + PLAYWRIGHT_FIREFOX_BIN = let + firefoxInfo = pkgs.lib.lists.findFirst (b: b.name == "firefox") (throw "value not found") browsersInfo.browsers; + firefoxPath = + { + x86_64-linux = "firefox-linux/firefox"; + aarch64-linux = "firefox-linux/firefox"; + x86_64-darwin = "firefox/Nightly.app/Contents/MacOS/firefox"; + arm64-darwin = "firefox/Nightly.app/Contents/MacOS/firefox"; + } + .${system} + or throwSystem; + in "${pkgs.playwright-driver.browsers}/firefox-${firefoxInfo.revision}/${firefoxPath}"; + }; + + formatter = pkgs.alejandra; + } + ); +} diff --git a/package.json b/package.json index 7192bf76..a1aa105c 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "postinstall": "node ./turbo/cache-key.mjs", "release": "pnpm run build && changeset publish", "test": "turbo run --concurrency=1 --filter '@inox-tools/*' test", + "test:e2e": "turbo run --concurrency=1 --filter '@inox-tools/*' test:e2e", "version": "changeset version && pnpm install && pnpm format" }, "lint-staged": { diff --git a/packages/request-state/e2e/basic.spec.ts b/packages/request-state/e2e/basic.spec.ts new file mode 100644 index 00000000..2e69aa5d --- /dev/null +++ b/packages/request-state/e2e/basic.spec.ts @@ -0,0 +1,29 @@ +import { setTimeout } from 'node:timers/promises'; +import { loadFixture, type PreviewServer } from '@inox-tools/astro-tests/astroFixture'; +import { test, expect } from '@playwright/test'; + +const fixture = await loadFixture({ + root: './fixture/basic', +}); + +let server: PreviewServer; + +test.beforeAll(async () => { + await fixture.build({}); + server = await fixture.preview({}); +}); + +test.afterAll(async () => { + await server?.stop(); + await server?.closed(); +}); + +test('share state ', async ({ page }) => { + const pageUrl = fixture.resolveUrl('/?name=John+Doe'); + + await page.goto(pageUrl); + + await setTimeout(15000); + + await expect(page.locator('span#name')).toHaveText('John Doe'); +}); diff --git a/packages/request-state/e2e/fixture/basic/astro.config.ts b/packages/request-state/e2e/fixture/basic/astro.config.ts new file mode 100644 index 00000000..8be37952 --- /dev/null +++ b/packages/request-state/e2e/fixture/basic/astro.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'astro/config'; +import node from '@astrojs/node'; +import requestState from '@inox-tools/request-state'; + +export default defineConfig({ + output: 'server', + adapter: node({ mode: 'standalone' }), + integrations: [requestState()], +}); diff --git a/packages/request-state/e2e/fixture/basic/package.json b/packages/request-state/e2e/fixture/basic/package.json new file mode 100644 index 00000000..a3e9f541 --- /dev/null +++ b/packages/request-state/e2e/fixture/basic/package.json @@ -0,0 +1,10 @@ +{ + "name": "@request-state/basic", + "private": true, + "type": "module", + "dependencies": { + "@astrojs/node": "catalog:", + "@inox-tools/request-state": "workspace:", + "astro": "catalog:" + } +} diff --git a/packages/request-state/e2e/fixture/basic/src/pages/index.astro b/packages/request-state/e2e/fixture/basic/src/pages/index.astro new file mode 100644 index 00000000..a72b0c37 --- /dev/null +++ b/packages/request-state/e2e/fixture/basic/src/pages/index.astro @@ -0,0 +1,20 @@ +--- +import { setState } from '@it-astro:state'; + +const name = Astro.url.searchParams.get('name'); +setState('name', name ?? 'World'); +--- + + +
+