diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 0000000..b5dee97 --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,36 @@ +name: Playwright Tests +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] +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 pnpm + run: npm install -g pnpm + - name: Install dependencies + run: pnpm install + - name: Install Playwright Browsers + run: pnpm exec playwright install --with-deps + - name: Build + run: pnpm run build + - name: Run app and e2e tests + env: + USE_MOCK_DATA: true + run: | + pnpm run preview & + npx wait-on http://localhost:4173 --timeout 60000 + pnpm exec 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 7f4b39a..fd7075d 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,10 @@ vite.config.ts.timestamp-* # Coolify coolify.config.json -deploy.config.json \ No newline at end of file +deploy.config.json + +# Playwright +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/package.json b/package.json index 9bc5c7c..068f54d 100644 --- a/package.json +++ b/package.json @@ -1,82 +1,84 @@ { - "name": "slimstarter", - "version": "0.0.1", - "private": true, - "scripts": { - "dev": "vite dev", - "build": "vite build", - "preview": "vite preview", - "test": "npm run test:integration && npm run test:unit", - "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", - "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", - "lint": "prettier --check . && eslint .", - "format": "prettier --write .", - "test:integration": "playwright test", - "test:unit": "vitest", - "db:studio": "npx drizzle-kit studio", - "db:generate": "npx drizzle-kit generate", - "db:migrate": "npx drizzle-kit migrate", - "prod": "pnpm db:migrate && PORT=5173 node build" - }, - "devDependencies": { - "@iconify/svelte": "^4.2.0", - "@inlang/paraglide-js": "1.11.3", - "@playwright/test": "^1.49.1", - "@sveltejs/adapter-auto": "^3.3.1", - "@sveltejs/adapter-node": "^5.2.12", - "@sveltejs/kit": "^2.16.0", - "@sveltejs/vite-plugin-svelte": "^4.0.4", - "@types/eslint": "^9.6.1", - "autoprefixer": "^10.4.20", - "bits-ui": "1.0.0-next.78", - "clsx": "^2.1.1", - "drizzle-kit": "^0.25.0", - "eslint": "^9.18.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-svelte": "^2.46.1", - "formsnap": "^2.0.0", - "globals": "^15.14.0", - "lucide-svelte": "^0.454.0", - "mdsvex": "^0.12.3", - "mode-watcher": "^0.5.0", - "postcss": "^8.5.1", - "prettier": "^3.4.2", - "prettier-plugin-svelte": "^3.3.3", - "svelte": "^5.19.0", - "svelte-check": "^4.1.4", - "svelte-meta-tags": "^4.1.0", - "svelte-radix": "^1.1.1", - "svelte-sonner": "^0.3.28", - "sveltekit-superforms": "^2.22.1", - "tailwind-merge": "^2.6.0", - "tailwind-variants": "^0.2.1", - "tailwindcss": "^3.4.17", - "tailwindcss-animate": "^1.0.7", - "typescript": "^5.7.3", - "typescript-eslint": "^8.20.0", - "vite": "^5.4.12", - "vitest": "^2.1.8", - "zod": "^3.24.1" - }, - "type": "module", - "dependencies": { - "@inlang/paraglide-sveltekit": "0.11.5", - "@node-rs/argon2": "^1.8.3", - "@oslojs/binary": "^1.0.0", - "@oslojs/crypto": "^1.0.1", - "@oslojs/encoding": "^1.1.0", - "@oslojs/otp": "^1.1.0", - "@oslojs/webauthn": "^1.0.0", - "@paddle/paddle-js": "^1.3.3", - "@paddle/paddle-node-sdk": "^1.10.0", - "@pilcrowjs/object-parser": "^0.0.4", - "arctic": "^2.3.3", - "dotenv": "^16.4.7", - "drizzle-orm": "^0.34.1", - "pg": "^8.13.1", - "postgres": "^3.4.5", - "svelte-inview": "^4.0.4", - "svelte-motion": "^0.12.2", - "uqr": "^0.1.2" - } + "name": "slimstarter", + "version": "0.0.1", + "private": true, + "scripts": { + "dev": "vite dev", + "build": "vite build", + "preview": "vite preview", + "test": "npm run test:integration && npm run test:unit", + "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "lint": "prettier --check . && eslint .", + "format": "prettier --write .", + "test:integration": "playwright test", + "test:unit": "vitest", + "db:studio": "npx drizzle-kit studio", + "db:generate": "npx drizzle-kit generate", + "db:migrate": "npx drizzle-kit migrate", + "prod": "pnpm db:migrate && PORT=5173 node build", + "test:e2e": "pnpm exec playwright test" + }, + "devDependencies": { + "@iconify/svelte": "^4.2.0", + "@inlang/paraglide-js": "1.11.3", + "@playwright/test": "^1.49.1", + "@sveltejs/adapter-auto": "^3.3.1", + "@sveltejs/adapter-node": "^5.2.12", + "@sveltejs/kit": "^2.16.0", + "@sveltejs/vite-plugin-svelte": "^4.0.4", + "@types/eslint": "^9.6.1", + "@types/node": "^22.13.0", + "autoprefixer": "^10.4.20", + "bits-ui": "1.0.0-next.78", + "clsx": "^2.1.1", + "drizzle-kit": "^0.25.0", + "eslint": "^9.18.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-svelte": "^2.46.1", + "formsnap": "^2.0.0", + "globals": "^15.14.0", + "lucide-svelte": "^0.454.0", + "mdsvex": "^0.12.3", + "mode-watcher": "^0.5.0", + "postcss": "^8.5.1", + "prettier": "^3.4.2", + "prettier-plugin-svelte": "^3.3.3", + "svelte": "^5.19.0", + "svelte-check": "^4.1.4", + "svelte-meta-tags": "^4.1.0", + "svelte-radix": "^1.1.1", + "svelte-sonner": "^0.3.28", + "sveltekit-superforms": "^2.22.1", + "tailwind-merge": "^2.6.0", + "tailwind-variants": "^0.2.1", + "tailwindcss": "^3.4.17", + "tailwindcss-animate": "^1.0.7", + "typescript": "^5.7.3", + "typescript-eslint": "^8.20.0", + "vite": "^5.4.12", + "vitest": "^2.1.8", + "zod": "^3.24.1" + }, + "type": "module", + "dependencies": { + "@inlang/paraglide-sveltekit": "0.11.5", + "@node-rs/argon2": "^1.8.3", + "@oslojs/binary": "^1.0.0", + "@oslojs/crypto": "^1.0.1", + "@oslojs/encoding": "^1.1.0", + "@oslojs/otp": "^1.1.0", + "@oslojs/webauthn": "^1.0.0", + "@paddle/paddle-js": "^1.3.3", + "@paddle/paddle-node-sdk": "^1.10.0", + "@pilcrowjs/object-parser": "^0.0.4", + "arctic": "^2.3.3", + "dotenv": "^16.4.7", + "drizzle-orm": "^0.34.1", + "pg": "^8.13.1", + "postgres": "^3.4.5", + "svelte-inview": "^4.0.4", + "svelte-motion": "^0.12.2", + "uqr": "^0.1.2" + } } diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..a05d8b5 --- /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:3000', + + /* 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/pnpm-lock.yaml b/pnpm-lock.yaml index 838761a..03a6528 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,7 +10,7 @@ importers: dependencies: '@inlang/paraglide-sveltekit': specifier: 0.11.5 - version: 0.11.5(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0))) + version: 0.11.5(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0))) '@node-rs/argon2': specifier: ^1.8.3 version: 1.8.3 @@ -74,19 +74,22 @@ importers: version: 1.49.1 '@sveltejs/adapter-auto': specifier: ^3.3.1 - version: 3.3.1(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0))) + version: 3.3.1(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0))) '@sveltejs/adapter-node': specifier: ^5.2.12 - version: 5.2.12(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0))) + version: 5.2.12(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0))) '@sveltejs/kit': specifier: ^2.16.0 - version: 2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)) + version: 2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)) '@sveltejs/vite-plugin-svelte': specifier: ^4.0.4 - version: 4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)) + version: 4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)) '@types/eslint': specifier: ^9.6.1 version: 9.6.1 + '@types/node': + specifier: ^22.13.0 + version: 22.13.0 autoprefixer: specifier: ^10.4.20 version: 10.4.20(postcss@8.5.1) @@ -110,7 +113,7 @@ importers: version: 2.46.1(eslint@9.18.0(jiti@1.21.7))(svelte@5.19.0) formsnap: specifier: ^2.0.0 - version: 2.0.0(svelte@5.19.0)(sveltekit-superforms@2.22.1(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(@types/json-schema@7.0.15)(svelte@5.19.0)(typescript@5.7.3)) + version: 2.0.0(svelte@5.19.0)(sveltekit-superforms@2.22.1(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(@types/json-schema@7.0.15)(svelte@5.19.0)(typescript@5.7.3)) globals: specifier: ^15.14.0 version: 15.14.0 @@ -149,7 +152,7 @@ importers: version: 0.3.28(svelte@5.19.0) sveltekit-superforms: specifier: ^2.22.1 - version: 2.22.1(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(@types/json-schema@7.0.15)(svelte@5.19.0)(typescript@5.7.3) + version: 2.22.1(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(@types/json-schema@7.0.15)(svelte@5.19.0)(typescript@5.7.3) tailwind-merge: specifier: ^2.6.0 version: 2.6.0 @@ -170,10 +173,10 @@ importers: version: 8.20.0(eslint@9.18.0(jiti@1.21.7))(typescript@5.7.3) vite: specifier: ^5.4.12 - version: 5.4.12(@types/node@22.10.7)(terser@5.37.0) + version: 5.4.12(@types/node@22.13.0)(terser@5.37.0) vitest: specifier: ^2.1.8 - version: 2.1.8(@types/node@22.10.7)(terser@5.37.0) + version: 2.1.8(@types/node@22.13.0)(terser@5.37.0) zod: specifier: ^3.24.1 version: 3.24.1 @@ -1436,8 +1439,8 @@ packages: '@types/jsonwebtoken@9.0.7': resolution: {integrity: sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==} - '@types/node@22.10.7': - resolution: {integrity: sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==} + '@types/node@22.13.0': + resolution: {integrity: sha512-ClIbNe36lawluuvq3+YYhnIN2CELi+6q8NpnM7PYp4hBn/TatfboPgVSm2rwKRfnV2M+Ty9GWDFI64KEe+kysA==} '@types/prop-types@15.7.14': resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} @@ -3754,12 +3757,12 @@ snapshots: - babel-plugin-macros - debug - '@inlang/paraglide-sveltekit@0.11.5(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))': + '@inlang/paraglide-sveltekit@0.11.5(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))': dependencies: '@inlang/paraglide-js': 1.11.3 '@inlang/paraglide-vite': 1.2.76 '@lix-js/client': 2.2.1 - '@sveltejs/kit': 2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)) + '@sveltejs/kit': 2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)) commander: 12.1.0 dedent: 1.5.1 devalue: 4.3.3 @@ -4303,22 +4306,22 @@ snapshots: '@sinclair/typebox@0.34.14': optional: true - '@sveltejs/adapter-auto@3.3.1(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))': + '@sveltejs/adapter-auto@3.3.1(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))': dependencies: - '@sveltejs/kit': 2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)) + '@sveltejs/kit': 2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)) import-meta-resolve: 4.1.0 - '@sveltejs/adapter-node@5.2.12(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))': + '@sveltejs/adapter-node@5.2.12(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))': dependencies: '@rollup/plugin-commonjs': 28.0.2(rollup@4.31.0) '@rollup/plugin-json': 6.1.0(rollup@4.31.0) '@rollup/plugin-node-resolve': 16.0.0(rollup@4.31.0) - '@sveltejs/kit': 2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)) + '@sveltejs/kit': 2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)) rollup: 4.31.0 - '@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0))': + '@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0))': dependencies: - '@sveltejs/vite-plugin-svelte': 4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)) + '@sveltejs/vite-plugin-svelte': 4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)) '@types/cookie': 0.6.0 cookie: 0.6.0 devalue: 5.1.1 @@ -4331,27 +4334,27 @@ snapshots: set-cookie-parser: 2.7.1 sirv: 3.0.0 svelte: 5.19.0 - vite: 5.4.12(@types/node@22.10.7)(terser@5.37.0) + vite: 5.4.12(@types/node@22.13.0)(terser@5.37.0) - '@sveltejs/vite-plugin-svelte-inspector@3.0.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0))': + '@sveltejs/vite-plugin-svelte-inspector@3.0.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0))': dependencies: - '@sveltejs/vite-plugin-svelte': 4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)) + '@sveltejs/vite-plugin-svelte': 4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)) debug: 4.4.0 svelte: 5.19.0 - vite: 5.4.12(@types/node@22.10.7)(terser@5.37.0) + vite: 5.4.12(@types/node@22.13.0)(terser@5.37.0) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0))': + '@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 3.0.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)) + '@sveltejs/vite-plugin-svelte-inspector': 3.0.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)) debug: 4.4.0 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.17 svelte: 5.19.0 - vite: 5.4.12(@types/node@22.10.7)(terser@5.37.0) - vitefu: 1.0.5(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)) + vite: 5.4.12(@types/node@22.13.0)(terser@5.37.0) + vitefu: 1.0.5(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)) transitivePeerDependencies: - supports-color @@ -4381,9 +4384,9 @@ snapshots: '@types/jsonwebtoken@9.0.7': dependencies: - '@types/node': 22.10.7 + '@types/node': 22.13.0 - '@types/node@22.10.7': + '@types/node@22.13.0': dependencies: undici-types: 6.20.0 @@ -4514,13 +4517,13 @@ snapshots: chai: 5.1.2 tinyrainbow: 1.2.0 - '@vitest/mocker@2.1.8(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0))': + '@vitest/mocker@2.1.8(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0))': dependencies: '@vitest/spy': 2.1.8 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 5.4.12(@types/node@22.10.7)(terser@5.37.0) + vite: 5.4.12(@types/node@22.13.0)(terser@5.37.0) '@vitest/pretty-format@2.1.8': dependencies: @@ -5141,11 +5144,11 @@ snapshots: combined-stream: 1.0.8 mime-types: 2.1.35 - formsnap@2.0.0(svelte@5.19.0)(sveltekit-superforms@2.22.1(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(@types/json-schema@7.0.15)(svelte@5.19.0)(typescript@5.7.3)): + formsnap@2.0.0(svelte@5.19.0)(sveltekit-superforms@2.22.1(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(@types/json-schema@7.0.15)(svelte@5.19.0)(typescript@5.7.3)): dependencies: svelte: 5.19.0 svelte-toolbelt: 0.5.0(svelte@5.19.0) - sveltekit-superforms: 2.22.1(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(@types/json-schema@7.0.15)(svelte@5.19.0)(typescript@5.7.3) + sveltekit-superforms: 2.22.1(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(@types/json-schema@7.0.15)(svelte@5.19.0)(typescript@5.7.3) fraction.js@4.3.7: {} @@ -5911,9 +5914,9 @@ snapshots: magic-string: 0.30.17 zimmerframe: 1.1.2 - sveltekit-superforms@2.22.1(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(@types/json-schema@7.0.15)(svelte@5.19.0)(typescript@5.7.3): + sveltekit-superforms@2.22.1(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(@types/json-schema@7.0.15)(svelte@5.19.0)(typescript@5.7.3): dependencies: - '@sveltejs/kit': 2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)) + '@sveltejs/kit': 2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)))(svelte@5.19.0)(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)) devalue: 5.1.1 memoize-weak: 1.0.2 svelte: 5.19.0 @@ -6102,13 +6105,13 @@ snapshots: '@types/unist': 2.0.11 unist-util-stringify-position: 2.0.3 - vite-node@2.1.8(@types/node@22.10.7)(terser@5.37.0): + vite-node@2.1.8(@types/node@22.13.0)(terser@5.37.0): dependencies: cac: 6.7.14 debug: 4.4.0 es-module-lexer: 1.6.0 pathe: 1.1.2 - vite: 5.4.12(@types/node@22.10.7)(terser@5.37.0) + vite: 5.4.12(@types/node@22.13.0)(terser@5.37.0) transitivePeerDependencies: - '@types/node' - less @@ -6120,24 +6123,24 @@ snapshots: - supports-color - terser - vite@5.4.12(@types/node@22.10.7)(terser@5.37.0): + vite@5.4.12(@types/node@22.13.0)(terser@5.37.0): dependencies: esbuild: 0.21.5 postcss: 8.5.1 rollup: 4.31.0 optionalDependencies: - '@types/node': 22.10.7 + '@types/node': 22.13.0 fsevents: 2.3.3 terser: 5.37.0 - vitefu@1.0.5(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)): + vitefu@1.0.5(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)): optionalDependencies: - vite: 5.4.12(@types/node@22.10.7)(terser@5.37.0) + vite: 5.4.12(@types/node@22.13.0)(terser@5.37.0) - vitest@2.1.8(@types/node@22.10.7)(terser@5.37.0): + vitest@2.1.8(@types/node@22.13.0)(terser@5.37.0): dependencies: '@vitest/expect': 2.1.8 - '@vitest/mocker': 2.1.8(vite@5.4.12(@types/node@22.10.7)(terser@5.37.0)) + '@vitest/mocker': 2.1.8(vite@5.4.12(@types/node@22.13.0)(terser@5.37.0)) '@vitest/pretty-format': 2.1.8 '@vitest/runner': 2.1.8 '@vitest/snapshot': 2.1.8 @@ -6153,11 +6156,11 @@ snapshots: tinyexec: 0.3.2 tinypool: 1.0.2 tinyrainbow: 1.2.0 - vite: 5.4.12(@types/node@22.10.7)(terser@5.37.0) - vite-node: 2.1.8(@types/node@22.10.7)(terser@5.37.0) + vite: 5.4.12(@types/node@22.13.0)(terser@5.37.0) + vite-node: 2.1.8(@types/node@22.13.0)(terser@5.37.0) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 22.10.7 + '@types/node': 22.13.0 transitivePeerDependencies: - less - lightningcss diff --git a/src/lib/components/forms/contactForm.svelte b/src/lib/components/forms/contactForm.svelte index ddd687e..3822331 100644 --- a/src/lib/components/forms/contactForm.svelte +++ b/src/lib/components/forms/contactForm.svelte @@ -13,6 +13,7 @@ const contactForm = superForm(form, { validators: zodClient(contactSchema), onUpdated({ form }) { + console.log("form : ", form.data, form.valid); if (form.valid) { toast.success('Email successfully send!'); } @@ -22,7 +23,7 @@ const { form: formData, enhance } = contactForm; -
+ {#snippet children({ props })} diff --git a/src/lib/server/database/mockData/mockProductWithVariants.ts b/src/lib/server/database/mockData/mockProductWithVariants.ts new file mode 100644 index 0000000..f2480ff --- /dev/null +++ b/src/lib/server/database/mockData/mockProductWithVariants.ts @@ -0,0 +1,22 @@ +export const mockProductWithVariants = [ + { + id: 1, + name: 'Test Product', + description: 'Test Product', + iconUrl: '', + details: '', + status: 'active', + variants: [ + { + id: 1, + name: 'Test Variant', + price: 10, + currency: 'USD', + billingPeriod: 'monthly', + status: 'active' + } + ] + } +]; + +export default mockProductWithVariants; \ No newline at end of file diff --git a/src/lib/server/database/productService.ts b/src/lib/server/database/productService.ts index 1c99ce3..afdae9b 100644 --- a/src/lib/server/database/productService.ts +++ b/src/lib/server/database/productService.ts @@ -1,14 +1,25 @@ -import { db } from "./client"; +import { db } from './client'; +import { env } from '$env/dynamic/private'; +import mockProductWithVariants from './mockData/mockProductWithVariants'; export type ProductWithVariants = Awaited>; export async function getActiveProductsWithVariants() { - return await db.query.productsTable.findMany({ - where: (productsTable, { eq }) => (eq(productsTable.status, "active")), - with: { - variants: { - where: (productVariantTable, { eq }) => eq(productVariantTable.status, "active") - } - } - }) -} \ No newline at end of file + if (env.USE_MOCK_DATA) { + return mockProductWithVariants; + } + + try { + return await db.query.productsTable.findMany({ + where: (productsTable, { eq }) => eq(productsTable.status, 'active'), + with: { + variants: { + where: (productVariantTable, { eq }) => eq(productVariantTable.status, 'active') + } + } + }); + } catch (error) { + console.error(error); + return []; + } +} diff --git a/src/routes/contact/+page.server.ts b/src/routes/contact/+page.server.ts index d68dbf1..9d92619 100644 --- a/src/routes/contact/+page.server.ts +++ b/src/routes/contact/+page.server.ts @@ -16,7 +16,7 @@ export async function load() { } export const actions: Actions = { - default: async (event: RequestEvent) => { + send: async (event: RequestEvent) => { const form = await superValidate(event, zod(contactSchema)); if (!form.valid) { return fail(400, { diff --git a/src/routes/contact/+page.svelte b/src/routes/contact/+page.svelte index b295a85..fb3a8f9 100644 --- a/src/routes/contact/+page.svelte +++ b/src/routes/contact/+page.svelte @@ -5,6 +5,7 @@ import type { SuperValidated, Infer } from 'sveltekit-superforms'; let { data }: { data: { form: SuperValidated> } } = $props(); + $inspect(data.form)
diff --git a/tests/e2e.spec.ts b/tests/e2e.spec.ts new file mode 100644 index 0000000..877c302 --- /dev/null +++ b/tests/e2e.spec.ts @@ -0,0 +1,21 @@ +import { test, expect } from '@playwright/test'; + +test('if user not logged in, when click on pricing button then redirect to authentication page', async ({ page }) => { + await page.goto('http://localhost:4173/payment'); + + await page.getByRole('button', { name: 'Get Mysaas' }).click(); + await page.waitForURL('http://localhost:4173/auth/login'); + + await expect(page).toHaveURL('http://localhost:4173/auth/login'); +}); + +test('if error occurs when submit contact form, then show error message', async ({ page }) => { + await page.goto('http://localhost:4173/contact'); + + await page.getByLabel('Email').fill('test@test.test'); + await page.getByLabel('Subject').fill('Test'); + await page.getByLabel('Message').fill('test'); + await page.getByRole('button', { name: 'Send Message' }).click(); + + await expect(page.getByText('An error occurred when')).toBeVisible(); +}); \ No newline at end of file