This commit is contained in:
@@ -101,6 +101,16 @@ npm run seed:demo
|
|||||||
|
|
||||||
The seed is non-destructive and exits without changes when the demo catalog already exists.
|
The seed is non-destructive and exits without changes when the demo catalog already exists.
|
||||||
|
|
||||||
|
## Browser Workflow Tests
|
||||||
|
|
||||||
|
With `npm run dev` running, configured local admin credentials, and demo lookup data available, run the authenticated browser workflow with:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run test:e2e
|
||||||
|
```
|
||||||
|
|
||||||
|
The workflow covers login, admin overview loading, product creation, physical inventory creation, and navigation to image management. It skips when `INITIAL_ADMIN_EMAIL` or `INITIAL_ADMIN_PASSWORD` is not configured.
|
||||||
|
|
||||||
## Initial Administrator
|
## Initial Administrator
|
||||||
|
|
||||||
After the development database is migrated, set `INITIAL_ADMIN_EMAIL`, `INITIAL_ADMIN_PASSWORD`, and `INITIAL_SELLER_NAME` in your local `.env`, then run `npm run provision:admin` once. The command creates the only initial administrator and linked Seller; it refuses to run after any User exists.
|
After the development database is migrated, set `INITIAL_ADMIN_EMAIL`, `INITIAL_ADMIN_PASSWORD`, and `INITIAL_SELLER_NAME` in your local `.env`, then run `npm run provision:admin` once. The command creates the only initial administrator and linked Seller; it refuses to run after any User exists.
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
|
||||||
|
test('signs in and creates a product and physical copy from the admin workspace', async ({ page }) => {
|
||||||
|
const email = process.env.INITIAL_ADMIN_EMAIL;
|
||||||
|
const password = process.env.INITIAL_ADMIN_PASSWORD;
|
||||||
|
|
||||||
|
test.skip(!email || !password, 'Set INITIAL_ADMIN_EMAIL and INITIAL_ADMIN_PASSWORD for the local authenticated workflow.');
|
||||||
|
|
||||||
|
await page.goto('/login');
|
||||||
|
await page.getByLabel('Email').fill(email);
|
||||||
|
await page.getByLabel('Password').fill(password);
|
||||||
|
await page.getByRole('button', { name: 'Sign in' }).click();
|
||||||
|
await expect(page).toHaveURL(/\/admin$/);
|
||||||
|
await expect(page.getByRole('heading', { name: 'Collector workspace' })).toBeVisible();
|
||||||
|
|
||||||
|
const category = page.locator('#product-category option').nth(1);
|
||||||
|
await expect(category).toBeAttached();
|
||||||
|
await page.getByLabel('Name').fill(`Browser test collectible ${Date.now()}`);
|
||||||
|
await page.getByLabel('Category').selectOption({ index: 1 });
|
||||||
|
await page.getByRole('button', { name: 'Create product' }).click();
|
||||||
|
|
||||||
|
await expect(page.locator('#inventory-product option').nth(1)).toBeAttached();
|
||||||
|
await page.getByLabel('Product').selectOption({ index: 1 });
|
||||||
|
await page.getByLabel('Condition').selectOption({ index: 1 });
|
||||||
|
await page.getByRole('button', { name: 'Create copy' }).click();
|
||||||
|
|
||||||
|
await expect(page.getByText('Manage images')).toBeVisible();
|
||||||
|
await page.getByText('Manage images').last().click();
|
||||||
|
await expect(page).toHaveURL(/\/admin\/inventory\/[^/]+\/images$/);
|
||||||
|
await expect(page.getByRole('heading', { name: 'Manage images' })).toBeVisible();
|
||||||
|
});
|
||||||
Generated
+24
@@ -10,6 +10,7 @@
|
|||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@playwright/test": "^1.63.0",
|
||||||
"@storybook/addon-a11y": "^8.6.14",
|
"@storybook/addon-a11y": "^8.6.14",
|
||||||
"@storybook/addon-essentials": "^8.6.14",
|
"@storybook/addon-essentials": "^8.6.14",
|
||||||
"@storybook/test": "^8.6.14",
|
"@storybook/test": "^8.6.14",
|
||||||
@@ -610,6 +611,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"apps/worker": {
|
||||||
|
"name": "@pokemon-inventory/worker"
|
||||||
|
},
|
||||||
"node_modules/@adobe/css-tools": {
|
"node_modules/@adobe/css-tools": {
|
||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.5.0.tgz",
|
||||||
@@ -4014,6 +4018,22 @@
|
|||||||
"integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==",
|
"integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@playwright/test": {
|
||||||
|
"version": "1.63.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.63.0.tgz",
|
||||||
|
"integrity": "sha512-oxMK4vllB9RK5NQ2l1pq1IfOf2AvnEuj/vYGDj0H2nMtmtZpKtCwt/l00GEO6xjGfpBNAvjovvYdCm50dRQkpQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"playwright": "1.63.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"playwright": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@pokemon-inventory/api": {
|
"node_modules/@pokemon-inventory/api": {
|
||||||
"resolved": "apps/api",
|
"resolved": "apps/api",
|
||||||
"link": true
|
"link": true
|
||||||
@@ -4030,6 +4050,10 @@
|
|||||||
"resolved": "apps/web",
|
"resolved": "apps/web",
|
||||||
"link": true
|
"link": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@pokemon-inventory/worker": {
|
||||||
|
"resolved": "apps/worker",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
"node_modules/@redis/bloom": {
|
"node_modules/@redis/bloom": {
|
||||||
"version": "5.12.1",
|
"version": "5.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-5.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-5.12.1.tgz",
|
||||||
|
|||||||
+4
-2
@@ -19,6 +19,7 @@
|
|||||||
"storybook": "npm run storybook --workspace=@pokemon-inventory/web",
|
"storybook": "npm run storybook --workspace=@pokemon-inventory/web",
|
||||||
"build-storybook": "npm run build-storybook --workspace=@pokemon-inventory/web",
|
"build-storybook": "npm run build-storybook --workspace=@pokemon-inventory/web",
|
||||||
"test-storybook": "concurrently --kill-others --success first \"npm run storybook\" \"wait-on http://127.0.0.1:6006 && npm run test-storybook --workspace=@pokemon-inventory/web\"",
|
"test-storybook": "concurrently --kill-others --success first \"npm run storybook\" \"wait-on http://127.0.0.1:6006 && npm run test-storybook --workspace=@pokemon-inventory/web\"",
|
||||||
|
"test:e2e": "playwright test",
|
||||||
"provision:admin": "npm run provision:admin --workspace=@pokemon-inventory/api",
|
"provision:admin": "npm run provision:admin --workspace=@pokemon-inventory/api",
|
||||||
"seed:demo": "npm run seed:demo --workspace=@pokemon-inventory/api",
|
"seed:demo": "npm run seed:demo --workspace=@pokemon-inventory/api",
|
||||||
"test:application": "npm run test:application --workspace=@pokemon-inventory/api",
|
"test:application": "npm run test:application --workspace=@pokemon-inventory/api",
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
"test": "npm run test:domain && npm run test:application && npm run test:http"
|
"test": "npm run test:domain && npm run test:application && npm run test:http"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@playwright/test": "^1.63.0",
|
||||||
"@storybook/addon-a11y": "^8.6.14",
|
"@storybook/addon-a11y": "^8.6.14",
|
||||||
"@storybook/addon-essentials": "^8.6.14",
|
"@storybook/addon-essentials": "^8.6.14",
|
||||||
"@storybook/test": "^8.6.14",
|
"@storybook/test": "^8.6.14",
|
||||||
@@ -36,7 +38,7 @@
|
|||||||
"concurrently": "^10.0.5",
|
"concurrently": "^10.0.5",
|
||||||
"dotenv": "^16.6.1",
|
"dotenv": "^16.6.1",
|
||||||
"drizzle-kit": "^0.31.8",
|
"drizzle-kit": "^0.31.8",
|
||||||
"storybook": "^8.6.14"
|
"storybook": "^8.6.14",
|
||||||
,"wait-on": "^8.0.3"
|
"wait-on": "^8.0.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { defineConfig } from '@playwright/test';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
testDir: './apps/web/tests/e2e',
|
||||||
|
timeout: 30_000,
|
||||||
|
use: {
|
||||||
|
baseURL: process.env.E2E_BASE_URL ?? 'http://127.0.0.1:5173',
|
||||||
|
trace: 'on-first-retry',
|
||||||
|
screenshot: 'only-on-failure',
|
||||||
|
},
|
||||||
|
reporter: [['list']],
|
||||||
|
});
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"status": "passed",
|
||||||
|
"failedTests": []
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user