@websolutespa/test 3.1.2 → 4.0.0-next.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/README.md +35 -35
- package/dist/exports/payload.d.ts.map +1 -1
- package/dist/exports/payload.js.map +1 -1
- package/dist/exports/vitest-setup-dom.js.map +1 -1
- package/dist/exports/vitest.d.ts.map +1 -1
- package/dist/exports/vitest.js +3 -1
- package/dist/exports/vitest.js.map +1 -1
- package/package.json +15 -13
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @websolutespa/test
|
|
2
2
|
|
|
3
|
+
## 4.0.0-next.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- d0f1be7: Generated projects build and run again: externals, peer dependencies and exports.
|
|
8
|
+
|
|
9
|
+
- `bom-mixer-image` is loaded by Node, not bundled: the web apps list it in `serverExternalPackages` and leave it out of `transpilePackages`. Turbopack bundled `sharp`'s native addon through it (`non-ecmascript placeable asset`, the image route answered 500). The package has no runtime import of `next` any more (`Response.redirect`, type-only imports), so it loads in plain Node.
|
|
10
|
+
Projects: in `src/mixer/web/next.config.ts` add `serverExternalPackages: ['@websolutespa/bom-mixer-image']` and filter it out of `transpilePackages`, as the samples do.
|
|
11
|
+
- The other mixer packages import `next/server` again (no `.js`): they are transpiled by Next. `@websolutespa/test/vitest` inlines `@websolutespa/*` (`server.deps.inline`), so project tests compile them like Next does.
|
|
12
|
+
- `schema-dts` is a peer dependency (`^2.1.0`) of `bom-mixer-models`, `bom-mixer-ui` and `bom-mixer-hooks`: their published `.d.ts` imported an inlined copy of it, and generated projects failed to type check (`TS2321: Excessive stack depth` in `test-pagination.tsx`).
|
|
13
|
+
- `bom-mixer-checkout` publishes `./server` again under pnpm: a stray `publishConfig.exports` with a Windows separator replaced the exports map.
|
|
14
|
+
- `payload-plugin-search` no longer requires `@payloadcms/richtext-slate`: it was a peer used only by its own tests, auto-installed at the newest Payload version, and Payload refused to start on the version mismatch.
|
|
15
|
+
- `bom create` downloads the samples of its own release tag (falls back to `main` when the tag does not exist) and writes `^<cli version>` for every `@websolutespa` dependency, local packages included, instead of `latest`.
|
|
16
|
+
- `react-error-boundary ^6.1.6`, `@ariakit/react ^0.4.17`, `rollup-plugin-postcss ^4.0.2` everywhere.
|
|
17
|
+
|
|
18
|
+
- aa3870b: Fixes found by the pnpm strict layout and TypeScript 7:
|
|
19
|
+
|
|
20
|
+
- `@websolutespa/test`: each project keeps its own vitest module cache (no EBUSY between parallel runs on Windows).
|
|
21
|
+
- `@websolutespa/bom-mixer-ui`: `Flex`, `Grid` and `Checkbox` have explicit types, so their declarations are portable.
|
|
22
|
+
- `@websolutespa/bom-mixer-llm`: the swiper module augmentation is valid TypeScript 7.
|
|
23
|
+
- @websolutespa/payload-db-memory@4.0.0-next.6
|
|
24
|
+
|
|
25
|
+
## 4.0.0-next.0
|
|
26
|
+
|
|
27
|
+
### Major Changes
|
|
28
|
+
|
|
29
|
+
- Next: support of the bom-next app package
|
|
30
|
+
- Updated dependencies
|
|
31
|
+
- @websolutespa/bom-core@4.0.0-next.0
|
|
32
|
+
|
|
3
33
|
## 3.1.2
|
|
4
34
|
|
|
5
35
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
# @websolutespa/test
|
|
2
|
-
|
|
3
|
-
[](https://badge.fury.io/js/%40websolutespa%2Ftest)
|
|
4
|
-
|
|
5
|
-
[](https://shields.io/)
|
|
6
|
-
|
|
7
|
-
Test shared config of the [BOM Repository](https://github.com/websolutespa/bom) by [websolute](https://www.websolute.com/).
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
#####
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
### Vitest configurations
|
|
16
|
-
|
|
17
|
-
```ts
|
|
18
|
-
// vitest.config.ts
|
|
19
|
-
import { definePayloadConfig } from '@websolutespa/test/vitest';
|
|
20
|
-
|
|
21
|
-
export default definePayloadConfig();
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
| factory
|
|
25
|
-
|
|
|
26
|
-
| `defineNodeConfig`
|
|
27
|
-
| `defineDomConfig`
|
|
28
|
-
| `definePayloadConfig` | node, `BOM_TEST_DB=memory` by default
|
|
29
|
-
|
|
30
|
-
Each factory accepts a vitest config, deep merged over the defaults.
|
|
31
|
-
|
|
32
|
-
### Payload test context
|
|
33
|
-
|
|
34
|
-
`getContext(config, { db })` builds a Payload instance on `@websolutespa/payload-db-memory` (`db: 'memory'`, the default with `definePayloadConfig`)
|
|
35
|
-
or on a mongo memory replica set (`db: 'mongo'`, or `BOM_TEST_DB=mongo`).
|
|
1
|
+
# @websolutespa/test
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/js/%40websolutespa%2Ftest)
|
|
4
|
+
|
|
5
|
+
[](https://shields.io/)
|
|
6
|
+
|
|
7
|
+
Test shared config of the [BOM Repository](https://github.com/websolutespa/bom) by [websolute](https://www.websolute.com/).
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
##### _this library is for internal usage and not production ready_
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
### Vitest configurations
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
// vitest.config.ts
|
|
19
|
+
import { definePayloadConfig } from '@websolutespa/test/vitest';
|
|
20
|
+
|
|
21
|
+
export default definePayloadConfig();
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
| factory | environment | use |
|
|
25
|
+
| --------------------- | -------------------------------------------- | ------------------------------------------------------ |
|
|
26
|
+
| `defineNodeConfig` | node | libraries, server code |
|
|
27
|
+
| `defineDomConfig` | jsdom + `@testing-library/jest-dom` matchers | react components and hooks |
|
|
28
|
+
| `definePayloadConfig` | node, `BOM_TEST_DB=memory` by default | Payload suites built with `@websolutespa/test/payload` |
|
|
29
|
+
|
|
30
|
+
Each factory accepts a vitest config, deep merged over the defaults.
|
|
31
|
+
|
|
32
|
+
### Payload test context
|
|
33
|
+
|
|
34
|
+
`getContext(config, { db })` builds a Payload instance on `@websolutespa/payload-db-memory` (`db: 'memory'`, the default with `definePayloadConfig`)
|
|
35
|
+
or on a mongo memory replica set (`db: 'mongo'`, or `BOM_TEST_DB=mongo`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payload.d.ts","names":[],"sources":["../../src/payload/client.ts","../../src/payload/config.ts","../../src/payload/context.ts","../../src/payload/seed.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"payload.d.ts","names":[],"sources":["../../src/payload/client.ts","../../src/payload/config.ts","../../src/payload/context.ts","../../src/payload/seed.ts"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payload.js","names":[],"sources":["../../src/payload/seed.ts","../../src/payload/client.ts","../../src/payload/email.adapter.ts","../../src/payload/config.ts","../../src/payload/context.ts"],"sourcesContent":["import { uuidv4 } from '@websolutespa/bom-core';\r\nimport type { TestPayload } from './context';\r\n\r\n/**\r\n * Defaults user roles and endUser roles available on the bowl plugin configuration:\r\n *\r\n * admin: user role with super powers.\r\n * contributor: user role with minor powers.\r\n * editor: user role with content editing powers.\r\n * guest: endUser role with application reading capabilities.\r\n * user: endUser authenticated role with reserved data.\r\n *\r\n */\r\nexport const roles = {\r\n Admin: 'admin',\r\n Contributor: 'contributor',\r\n Editor: 'editor',\r\n Guest: 'guest', // api requests (from Oven) will be made with this role if the user didn't authenticate\r\n User: 'user',\r\n} as const;\r\n\r\nexport const users = {\r\n admin: {\r\n email: 'admin@payload.com',\r\n password: 'admin@payload.com',\r\n roles: [roles.Admin],\r\n },\r\n editor: {\r\n email: 'editor@payload.com',\r\n password: 'editor@payload.com',\r\n roles: [roles.Editor],\r\n },\r\n api: {\r\n email: 'api@payload.com',\r\n password: 'api@payload.com',\r\n roles: [roles.Guest],\r\n enableAPIKey: true,\r\n apiKey: uuidv4(),\r\n },\r\n};\r\n\r\nexport const endUsers = {\r\n user: {\r\n email: 'user@payload.com',\r\n password: 'user@payload.com',\r\n roles: [roles.Guest, roles.User],\r\n },\r\n};\r\n\r\nexport const seedUsers = async (payload: TestPayload) => {\r\n const { totalDocs } = await payload.count({\r\n collection: 'users',\r\n });\r\n if (totalDocs === 0) {\r\n for (const entry of Object.entries(users)) {\r\n const user = entry[1];\r\n await payload.create({\r\n collection: 'users',\r\n data: user,\r\n });\r\n }\r\n }\r\n};\r\n\r\nexport const seedEndUsers = async (payload: TestPayload) => {\r\n const { totalDocs } = await payload.count({\r\n collection: 'end_users',\r\n });\r\n if (totalDocs === 0) {\r\n for (const entry of Object.entries(endUsers)) {\r\n const user = entry[1];\r\n await payload.create({\r\n collection: 'end_users',\r\n data: user,\r\n draft: false,\r\n });\r\n }\r\n }\r\n};\r\n\r\nexport const seed = async (payload: TestPayload) => {\r\n if (payload.collections['users'] !== undefined) {\r\n await seedUsers(payload);\r\n }\r\n if (payload.collections['end_users'] !== undefined) {\r\n await seedEndUsers(payload);\r\n }\r\n};\r\n","import { GRAPHQL_POST, REST_DELETE, REST_GET, REST_PATCH, REST_POST, REST_PUT } from '@payloadcms/next/routes';\r\nimport type { CollectionSlug, JoinQuery, PopulateType, SanitizedConfig, SelectType, Where } from 'payload';\r\nimport type { ParsedQs } from 'qs-esm';\r\nimport * as qs from 'qs-esm';\r\nimport { users } from './seed';\r\n\r\nexport type ValidPath = `/${string}`;\r\n\r\nexport type FileArg = {\r\n file?: Omit<File, 'webkitRelativePath'>;\r\n};\r\n\r\nexport type RequestQuery = {\r\n [key: string]: unknown;\r\n} & {\r\n depth?: number;\r\n fallbackLocale?: string;\r\n joins?: JoinQuery;\r\n limit?: number;\r\n locale?: string;\r\n page?: number;\r\n populate?: PopulateType;\r\n select?: SelectType;\r\n sort?: string;\r\n where?: Where;\r\n};\r\n\r\nexport type RequestOptions = {\r\n auth?: boolean;\r\n query?: RequestQuery;\r\n};\r\n\r\nexport type ClientRequestOptions = FileArg & RequestInit & RequestOptions;\r\n\r\nexport type NextRoute = (request: Request, args: { params: Promise<{ slug: string[] }> }) => Promise<Response>;\r\n\r\nfunction asValidPath(path: string): ValidPath {\r\n if (!path.match(/^\\//)) {\r\n path = `/${path}`;\r\n }\r\n return path as ValidPath;\r\n}\r\n\r\nfunction getQueryString(query?: RequestQuery, params?: ParsedQs): string {\r\n return qs.stringify(\r\n {\r\n ...(params || {}),\r\n ...(query || {}),\r\n },\r\n {\r\n addQueryPrefix: true,\r\n },\r\n )\r\n}\r\n\r\nexport class RestClient {\r\n\r\n private readonly config: SanitizedConfig;\r\n serverURL: string = 'http://localhost:3000';\r\n private token: string = '';\r\n\r\n private getRest_: NextRoute;\r\n private postRest_: NextRoute;\r\n private putRest_: NextRoute;\r\n private patchRest_: NextRoute;\r\n private deleteRest_: NextRoute;\r\n private postGraphql_: (request: Request) => Promise<Response>;\r\n\r\n constructor(config: SanitizedConfig) {\r\n this.config = config;\r\n if (config?.serverURL) {\r\n this.serverURL = config.serverURL;\r\n }\r\n this.getRest_ = REST_GET(config);\r\n this.postRest_ = REST_POST(config);\r\n this.putRest_ = REST_PUT(config);\r\n this.patchRest_ = REST_PATCH(config);\r\n this.deleteRest_ = REST_DELETE(config);\r\n this.postGraphql_ = GRAPHQL_POST(config);\r\n }\r\n\r\n private getHeaders(options: ClientRequestOptions): Headers {\r\n const defaultHeaders = {\r\n 'Content-Type': 'application/json',\r\n };\r\n const headers = new Headers({\r\n ...(options?.file ? {\r\n 'Content-Length': options.file.size.toString(),\r\n } : defaultHeaders),\r\n ...(options?.headers || {}),\r\n });\r\n if (options.auth !== false && this.token) {\r\n headers.set('Authorization', `JWT ${this.token}`);\r\n }\r\n if (options.auth === false) {\r\n headers.set('DisableAutologin', 'true');\r\n }\r\n return headers;\r\n }\r\n\r\n private getPathParts(path: ValidPath): {\r\n params?: ParsedQs;\r\n slug: string[];\r\n url: string;\r\n } {\r\n const [slugs, params] = path.slice(1).split('?');\r\n const url = `${this.serverURL}${this.config.routes.api}/${slugs}`;\r\n return {\r\n slug: slugs.split('/'),\r\n params: params ? qs.parse(params) : undefined,\r\n url,\r\n }\r\n }\r\n\r\n async GET(path: ValidPath, options: Omit<ClientRequestOptions, 'body' | 'file'> = {}): Promise<Response> {\r\n const { slug, params, url } = this.getPathParts(path);\r\n const { query, ...rest } = options || {};\r\n const queryParams = getQueryString(query, params);\r\n const request = new Request(`${url}${queryParams}`, {\r\n ...rest,\r\n headers: this.getHeaders(options),\r\n method: 'GET',\r\n });\r\n return this.getRest_(request, { params: Promise.resolve({ slug }) });\r\n }\r\n\r\n async POST(path: ValidPath, options: ClientRequestOptions = {}): Promise<Response> {\r\n const { slug, params, url } = this.getPathParts(path);\r\n const queryParams = getQueryString({}, params);\r\n const request = new Request(`${url}${queryParams}`, {\r\n ...options,\r\n headers: this.getHeaders(options),\r\n method: 'POST',\r\n });\r\n return this.postRest_(request, { params: Promise.resolve({ slug }) });\r\n }\r\n\r\n async PUT(path: ValidPath, options: ClientRequestOptions = {}): Promise<Response> {\r\n const { slug, params, url } = this.getPathParts(path);\r\n const { query, ...rest } = options;\r\n const queryParams = getQueryString(query, params);\r\n const request = new Request(`${url}${queryParams}`, {\r\n ...rest,\r\n headers: this.getHeaders(options),\r\n method: 'PUT',\r\n });\r\n return this.putRest_(request, { params: Promise.resolve({ slug }) });\r\n }\r\n\r\n async PATCH(path: ValidPath, options: ClientRequestOptions = {}): Promise<Response> {\r\n const { slug, params, url } = this.getPathParts(path);\r\n const { query, ...rest } = options;\r\n const queryParams = getQueryString(query, params);\r\n const request = new Request(`${url}${queryParams}`, {\r\n ...rest,\r\n headers: this.getHeaders(options),\r\n method: 'PATCH',\r\n });\r\n return this.patchRest_(request, { params: Promise.resolve({ slug }) });\r\n }\r\n\r\n async DELETE(path: ValidPath, options: Omit<ClientRequestOptions, 'file'> = {}): Promise<Response> {\r\n const { slug, params, url } = this.getPathParts(path);\r\n const { query, ...rest } = options || {};\r\n const queryParams = getQueryString(query, params);\r\n const request = new Request(`${url}${queryParams}`, {\r\n ...rest,\r\n headers: this.getHeaders(options),\r\n method: 'DELETE',\r\n });\r\n return this.deleteRest_(request, { params: Promise.resolve({ slug }) });\r\n }\r\n\r\n async GRAPHQL_POST(options: Omit<ClientRequestOptions, 'file'> = {}): Promise<Response> {\r\n const { query, ...rest } = options;\r\n const queryParams = getQueryString(query, {});\r\n const request = new Request(`${this.serverURL}${this.config.routes.api}${this.config.routes.graphQL}${queryParams}`, {\r\n ...rest,\r\n headers: this.getHeaders(options),\r\n method: 'POST',\r\n });\r\n return this.postGraphql_(request);\r\n }\r\n\r\n async get(path: string, options: Omit<ClientRequestOptions, 'body' | 'file'> = {}): Promise<{ [key: string]: any }> {\r\n try {\r\n const response = await this.GET(asValidPath(path), options);\r\n if (!response.ok) {\r\n throw response;\r\n }\r\n const data = await response.json();\r\n return data;\r\n } catch (error: any) {\r\n console.log('RestClient.get.error', path, 'json' in error ? await error.json() : error);\r\n throw (error);\r\n }\r\n }\r\n\r\n async post(path: string, body: any, options: ClientRequestOptions = {}): Promise<{ [key: string]: any }> {\r\n try {\r\n options = {\r\n ...options,\r\n body: JSON.stringify(body),\r\n };\r\n const response = await this.POST(asValidPath(path), options);\r\n if (!response.ok) {\r\n throw response;\r\n }\r\n const data = await response.json();\r\n return data;\r\n } catch (error: any) {\r\n console.log('RestClient.post.error', path, error);\r\n throw (error);\r\n }\r\n }\r\n\r\n async patch(path: string, body: any, options: ClientRequestOptions = {}): Promise<{ [key: string]: any }> {\r\n try {\r\n options = {\r\n ...options,\r\n body: JSON.stringify(body),\r\n };\r\n const response = await this.PATCH(asValidPath(path), options);\r\n if (!response.ok) {\r\n throw response;\r\n }\r\n const data = await response.json();\r\n return data;\r\n } catch (error: any) {\r\n console.log('RestClient.patch.error', path, error);\r\n throw (error);\r\n }\r\n }\r\n\r\n async delete(path: string, options: Omit<ClientRequestOptions, 'body' | 'file'> = {}): Promise<{ [key: string]: any }> {\r\n try {\r\n const response = await this.DELETE(asValidPath(path), options);\r\n if (!response.ok) {\r\n throw response;\r\n }\r\n const data = await response.json();\r\n return data;\r\n } catch (error: any) {\r\n console.log('RestClient.delete.error', path, error);\r\n throw (error);\r\n }\r\n }\r\n\r\n async getToken(slug: CollectionSlug = 'users', credentials: { email: string, password: string } = users.admin): Promise<string> {\r\n const result = await this.post(`/${slug}/login`, {\r\n email: credentials.email,\r\n password: credentials.password,\r\n });\r\n return result.token as string;\r\n }\r\n\r\n async login({\r\n slug,\r\n credentials,\r\n }: {\r\n slug: string;\r\n credentials?: {\r\n email: string;\r\n password: string;\r\n };\r\n }): Promise<{ [key: string]: any }> {\r\n const response = await this.POST(`/${slug}/login`, {\r\n body: JSON.stringify(\r\n credentials ? {\r\n ...credentials\r\n } : {\r\n email: users.admin.email,\r\n password: users.admin.password\r\n },\r\n ),\r\n });\r\n const result = await response.json();\r\n this.token = result.token;\r\n if (!result.token) {\r\n // If the token is not in the response body, then we can extract it from the cookies\r\n const setCookie = response.headers.get('Set-Cookie');\r\n const tokenMatchResult = setCookie?.match(/payload-token=(?<token>.+?);/);\r\n this.token = tokenMatchResult?.groups?.token || '';\r\n }\r\n return result;\r\n }\r\n\r\n}\r\n","import type { EmailAdapter, SendEmailOptions } from 'payload';\r\n\r\nexport const testEmailAdapter: EmailAdapter<void> = ({ payload }) => ({\r\n name: 'test-email-adapter',\r\n defaultFromAddress: 'dev@payloadcms.com',\r\n defaultFromName: 'Payload Test',\r\n sendEmail: async (message) => {\r\n const stringifiedTo = getStringifiedToAddress(message)\r\n const res = `Test email to: '${stringifiedTo}', Subject: '${message.subject}'`\r\n payload.logger.info({ content: message, msg: res })\r\n return Promise.resolve()\r\n },\r\n})\r\n\r\nfunction getAddress(to: unknown): string {\r\n if (typeof to === 'string') {\r\n return to;\r\n }\r\n if (to && typeof to === 'object' && 'address' in to && typeof to.address === 'string') {\r\n return to.address;\r\n }\r\n return '';\r\n}\r\n\r\nfunction getStringifiedToAddress(message: SendEmailOptions): string | undefined {\r\n if (!message.to) {\r\n return undefined;\r\n }\r\n return Array.isArray(message.to) ?\r\n message.to.map(getAddress).join(', ') :\r\n getAddress(message.to) || undefined;\r\n}\r\n","import { mongooseAdapter } from '@payloadcms/db-mongodb';\r\nimport { lexicalEditor } from '@payloadcms/richtext-lexical';\r\nimport { slateEditor } from '@payloadcms/richtext-slate';\r\nimport { memoryAdapter } from '@websolutespa/payload-db-memory';\r\nimport { MongoMemoryReplSet } from 'mongodb-memory-server';\r\nimport path from 'path';\r\nimport { buildConfig, Config, SanitizedConfig } from 'payload';\r\nimport sharp from 'sharp';\r\nimport { fileURLToPath } from 'url';\r\nimport { testEmailAdapter } from './email.adapter';\r\nimport type { TestPayload } from './context';\r\nimport { seed } from './seed';\r\n\r\nconst SLATE = true;\r\n\r\nexport type TestDatabase = 'mongo' | 'memory';\r\n\r\nexport type TestConfigOptions = {\r\n /**\r\n * Database backing the test payload.\r\n * - 'mongo' (default): MongoMemoryReplSet + mongooseAdapter, Slate editor.\r\n * - 'memory': @websolutespa/payload-db-memory, Lexical editor (no replica set, no DATABASE_URL).\r\n * Defaults to the BOM_TEST_DB environment variable when set.\r\n */\r\n db?: TestDatabase;\r\n};\r\n\r\nfunction resolveDatabase(options?: TestConfigOptions): TestDatabase {\r\n return options?.db || (process.env.BOM_TEST_DB === 'memory' ? 'memory' : 'mongo');\r\n}\r\n\r\nconst filename = fileURLToPath(import.meta.url);\r\nconst dirname = path.dirname(filename);\r\n\r\nif (!process.env.ROOT_DIR) {\r\n process.env.ROOT_DIR = dirname;\r\n}\r\n\r\nconst buildConfigWithMemoryDB = async (config: Partial<Config>, options?: TestConfigOptions) => {\r\n const memory = resolveDatabase(options) === 'memory';\r\n if (!memory && process.env.NODE_ENV === 'test') {\r\n const memoryDB = await MongoMemoryReplSet.create({\r\n replSet: {\r\n count: 3,\r\n dbName: 'payloadmemory',\r\n },\r\n });\r\n process.env.DATABASE_URL = `${memoryDB.getUri()}&retryWrites=true`;\r\n }\r\n // console.log('NODE_ENV', process.env.NODE_ENV, process.env.DATABASE_URL);\r\n return buildConfig({\r\n ...config,\r\n admin: {\r\n ...config.admin,\r\n importMap: {\r\n baseDir: path.resolve(dirname),\r\n },\r\n },\r\n db: memory ?\r\n memoryAdapter() :\r\n mongooseAdapter({\r\n ensureIndexes: true,\r\n url: process.env.DATABASE_URL || '',\r\n }),\r\n editor: memory ?\r\n (config.editor || lexicalEditor()) :\r\n SLATE ? slateEditor({}) : lexicalEditor(),\r\n email: testEmailAdapter,\r\n i18n: {\r\n ...config.i18n,\r\n fallbackLanguage: 'en',\r\n },\r\n // indexSortableFields: true\r\n localization: {\r\n locales: ['en', 'it'],\r\n defaultLocale: 'en',\r\n fallback: true,\r\n },\r\n maxDepth: 10,\r\n onInit: async (payload) => {\r\n await seed(payload as TestPayload);\r\n },\r\n serverURL: 'http://localhost:3000',\r\n secret: process.env.PAYLOAD_SECRET || 'test-secret_key',\r\n sharp,\r\n typescript: {\r\n declare: false,\r\n outputFile: path.resolve(dirname, 'payload-types.ts'),\r\n },\r\n });\r\n};\r\n\r\nexport async function getConfig(config: Partial<Config>, options?: TestConfigOptions): Promise<SanitizedConfig> {\r\n return await buildConfigWithMemoryDB(config, options);\r\n}\r\n","\r\nimport type { Config, Payload } from 'payload';\r\nimport { getPayload } from 'payload';\r\nimport { RestClient } from './client';\r\nimport { getConfig, type TestConfigOptions } from './config';\r\n\r\n/**\r\n * Local Payload API surface for integration suites that register collections\r\n * at runtime and therefore cannot use an application's generated schema.\r\n * It is an intersection with Payload, so it stays assignable to Payload.\r\n */\r\nexport type TestPayload = Payload & {\r\n create: (options: unknown) => Promise<any>;\r\n find: (options: unknown) => Promise<any>;\r\n findByID: (options: unknown) => Promise<any>;\r\n update: (options: unknown) => Promise<any>;\r\n};\r\n\r\nexport type TestContext = {\r\n payload: TestPayload;\r\n client: RestClient;\r\n}\r\n\r\nlet CONTEXT: TestContext | undefined = undefined;\r\n\r\nexport async function getContext(userConfig: Partial<Config>, options?: TestConfigOptions): Promise<TestContext> {\r\n if (CONTEXT) {\r\n return CONTEXT;\r\n }\r\n const config = await getConfig(userConfig, options);\r\n const payload = await getPayload({ config });\r\n const client = new RestClient(payload.config);\r\n const context: TestContext = {\r\n payload: payload as TestPayload,\r\n client,\r\n };\r\n CONTEXT = context;\r\n // onTestFinished(async () => await clearContext(context));\r\n return context;\r\n}\r\n\r\nexport async function clearContext(context?: TestContext) {\r\n /*\r\n if (context?.payload) {\r\n await context.payload.destroy();\r\n }\r\n */\r\n}\r\n\r\n/*\r\nexport default function setup(project: TestProject) {\r\n project.onTestsRerun(async () => {\r\n const context = await getContext();\r\n });\r\n}\r\n*/\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"payload.js","names":[],"sources":["../../src/payload/seed.ts","../../src/payload/client.ts","../../src/payload/email.adapter.ts","../../src/payload/config.ts","../../src/payload/context.ts"],"sourcesContent":["import { uuidv4 } from '@websolutespa/bom-core';\nimport type { TestPayload } from './context';\n\n/**\n * Defaults user roles and endUser roles available on the bowl plugin configuration:\n *\n * admin: user role with super powers.\n * contributor: user role with minor powers.\n * editor: user role with content editing powers.\n * guest: endUser role with application reading capabilities.\n * user: endUser authenticated role with reserved data.\n *\n */\nexport const roles = {\n Admin: 'admin',\n Contributor: 'contributor',\n Editor: 'editor',\n Guest: 'guest', // api requests (from Oven) will be made with this role if the user didn't authenticate\n User: 'user',\n} as const;\n\nexport const users = {\n admin: {\n email: 'admin@payload.com',\n password: 'admin@payload.com',\n roles: [roles.Admin],\n },\n editor: {\n email: 'editor@payload.com',\n password: 'editor@payload.com',\n roles: [roles.Editor],\n },\n api: {\n email: 'api@payload.com',\n password: 'api@payload.com',\n roles: [roles.Guest],\n enableAPIKey: true,\n apiKey: uuidv4(),\n },\n};\n\nexport const endUsers = {\n user: {\n email: 'user@payload.com',\n password: 'user@payload.com',\n roles: [roles.Guest, roles.User],\n },\n};\n\nexport const seedUsers = async (payload: TestPayload) => {\n const { totalDocs } = await payload.count({\n collection: 'users',\n });\n if (totalDocs === 0) {\n for (const entry of Object.entries(users)) {\n const user = entry[1];\n await payload.create({\n collection: 'users',\n data: user,\n });\n }\n }\n};\n\nexport const seedEndUsers = async (payload: TestPayload) => {\n const { totalDocs } = await payload.count({\n collection: 'end_users',\n });\n if (totalDocs === 0) {\n for (const entry of Object.entries(endUsers)) {\n const user = entry[1];\n await payload.create({\n collection: 'end_users',\n data: user,\n draft: false,\n });\n }\n }\n};\n\nexport const seed = async (payload: TestPayload) => {\n if (payload.collections['users'] !== undefined) {\n await seedUsers(payload);\n }\n if (payload.collections['end_users'] !== undefined) {\n await seedEndUsers(payload);\n }\n};\n","import {\n GRAPHQL_POST,\n REST_DELETE,\n REST_GET,\n REST_PATCH,\n REST_POST,\n REST_PUT,\n} from '@payloadcms/next/routes';\nimport type {\n CollectionSlug,\n JoinQuery,\n PopulateType,\n SanitizedConfig,\n SelectType,\n Where,\n} from 'payload';\nimport type { ParsedQs } from 'qs-esm';\nimport * as qs from 'qs-esm';\nimport { users } from './seed';\n\nexport type ValidPath = `/${string}`;\n\nexport type FileArg = {\n file?: Omit<File, 'webkitRelativePath'>;\n};\n\nexport type RequestQuery = {\n [key: string]: unknown;\n} & {\n depth?: number;\n fallbackLocale?: string;\n joins?: JoinQuery;\n limit?: number;\n locale?: string;\n page?: number;\n populate?: PopulateType;\n select?: SelectType;\n sort?: string;\n where?: Where;\n};\n\nexport type RequestOptions = {\n auth?: boolean;\n query?: RequestQuery;\n};\n\nexport type ClientRequestOptions = FileArg & RequestInit & RequestOptions;\n\nexport type NextRoute = (\n request: Request,\n args: { params: Promise<{ slug: string[] }> }\n) => Promise<Response>;\n\nfunction asValidPath(path: string): ValidPath {\n if (!path.match(/^\\//)) {\n path = `/${path}`;\n }\n return path as ValidPath;\n}\n\nfunction getQueryString(query?: RequestQuery, params?: ParsedQs): string {\n return qs.stringify(\n {\n ...(params || {}),\n ...(query || {}),\n },\n {\n addQueryPrefix: true,\n }\n );\n}\n\nexport class RestClient {\n private readonly config: SanitizedConfig;\n serverURL: string = 'http://localhost:3000';\n private token: string = '';\n\n private getRest_: NextRoute;\n private postRest_: NextRoute;\n private putRest_: NextRoute;\n private patchRest_: NextRoute;\n private deleteRest_: NextRoute;\n private postGraphql_: (request: Request) => Promise<Response>;\n\n constructor(config: SanitizedConfig) {\n this.config = config;\n if (config?.serverURL) {\n this.serverURL = config.serverURL;\n }\n this.getRest_ = REST_GET(config);\n this.postRest_ = REST_POST(config);\n this.putRest_ = REST_PUT(config);\n this.patchRest_ = REST_PATCH(config);\n this.deleteRest_ = REST_DELETE(config);\n this.postGraphql_ = GRAPHQL_POST(config);\n }\n\n private getHeaders(options: ClientRequestOptions): Headers {\n const defaultHeaders = {\n 'Content-Type': 'application/json',\n };\n const headers = new Headers({\n ...(options?.file\n ? {\n 'Content-Length': options.file.size.toString(),\n }\n : defaultHeaders),\n ...(options?.headers || {}),\n });\n if (options.auth !== false && this.token) {\n headers.set('Authorization', `JWT ${this.token}`);\n }\n if (options.auth === false) {\n headers.set('DisableAutologin', 'true');\n }\n return headers;\n }\n\n private getPathParts(path: ValidPath): {\n params?: ParsedQs;\n slug: string[];\n url: string;\n } {\n const [slugs, params] = path.slice(1).split('?');\n const url = `${this.serverURL}${this.config.routes.api}/${slugs}`;\n return {\n slug: slugs.split('/'),\n params: params ? qs.parse(params) : undefined,\n url,\n };\n }\n\n async GET(\n path: ValidPath,\n options: Omit<ClientRequestOptions, 'body' | 'file'> = {}\n ): Promise<Response> {\n const { slug, params, url } = this.getPathParts(path);\n const { query, ...rest } = options || {};\n const queryParams = getQueryString(query, params);\n const request = new Request(`${url}${queryParams}`, {\n ...rest,\n headers: this.getHeaders(options),\n method: 'GET',\n });\n return this.getRest_(request, { params: Promise.resolve({ slug }) });\n }\n\n async POST(path: ValidPath, options: ClientRequestOptions = {}): Promise<Response> {\n const { slug, params, url } = this.getPathParts(path);\n const queryParams = getQueryString({}, params);\n const request = new Request(`${url}${queryParams}`, {\n ...options,\n headers: this.getHeaders(options),\n method: 'POST',\n });\n return this.postRest_(request, { params: Promise.resolve({ slug }) });\n }\n\n async PUT(path: ValidPath, options: ClientRequestOptions = {}): Promise<Response> {\n const { slug, params, url } = this.getPathParts(path);\n const { query, ...rest } = options;\n const queryParams = getQueryString(query, params);\n const request = new Request(`${url}${queryParams}`, {\n ...rest,\n headers: this.getHeaders(options),\n method: 'PUT',\n });\n return this.putRest_(request, { params: Promise.resolve({ slug }) });\n }\n\n async PATCH(path: ValidPath, options: ClientRequestOptions = {}): Promise<Response> {\n const { slug, params, url } = this.getPathParts(path);\n const { query, ...rest } = options;\n const queryParams = getQueryString(query, params);\n const request = new Request(`${url}${queryParams}`, {\n ...rest,\n headers: this.getHeaders(options),\n method: 'PATCH',\n });\n return this.patchRest_(request, { params: Promise.resolve({ slug }) });\n }\n\n async DELETE(\n path: ValidPath,\n options: Omit<ClientRequestOptions, 'file'> = {}\n ): Promise<Response> {\n const { slug, params, url } = this.getPathParts(path);\n const { query, ...rest } = options || {};\n const queryParams = getQueryString(query, params);\n const request = new Request(`${url}${queryParams}`, {\n ...rest,\n headers: this.getHeaders(options),\n method: 'DELETE',\n });\n return this.deleteRest_(request, { params: Promise.resolve({ slug }) });\n }\n\n async GRAPHQL_POST(options: Omit<ClientRequestOptions, 'file'> = {}): Promise<Response> {\n const { query, ...rest } = options;\n const queryParams = getQueryString(query, {});\n const request = new Request(\n `${this.serverURL}${this.config.routes.api}${this.config.routes.graphQL}${queryParams}`,\n {\n ...rest,\n headers: this.getHeaders(options),\n method: 'POST',\n }\n );\n return this.postGraphql_(request);\n }\n\n async get(\n path: string,\n options: Omit<ClientRequestOptions, 'body' | 'file'> = {}\n ): Promise<{ [key: string]: any }> {\n try {\n const response = await this.GET(asValidPath(path), options);\n if (!response.ok) {\n throw response;\n }\n const data = await response.json();\n return data;\n } catch (error: any) {\n console.log('RestClient.get.error', path, 'json' in error ? await error.json() : error);\n throw error;\n }\n }\n\n async post(\n path: string,\n body: any,\n options: ClientRequestOptions = {}\n ): Promise<{ [key: string]: any }> {\n try {\n options = {\n ...options,\n body: JSON.stringify(body),\n };\n const response = await this.POST(asValidPath(path), options);\n if (!response.ok) {\n throw response;\n }\n const data = await response.json();\n return data;\n } catch (error: any) {\n console.log('RestClient.post.error', path, error);\n throw error;\n }\n }\n\n async patch(\n path: string,\n body: any,\n options: ClientRequestOptions = {}\n ): Promise<{ [key: string]: any }> {\n try {\n options = {\n ...options,\n body: JSON.stringify(body),\n };\n const response = await this.PATCH(asValidPath(path), options);\n if (!response.ok) {\n throw response;\n }\n const data = await response.json();\n return data;\n } catch (error: any) {\n console.log('RestClient.patch.error', path, error);\n throw error;\n }\n }\n\n async delete(\n path: string,\n options: Omit<ClientRequestOptions, 'body' | 'file'> = {}\n ): Promise<{ [key: string]: any }> {\n try {\n const response = await this.DELETE(asValidPath(path), options);\n if (!response.ok) {\n throw response;\n }\n const data = await response.json();\n return data;\n } catch (error: any) {\n console.log('RestClient.delete.error', path, error);\n throw error;\n }\n }\n\n async getToken(\n slug: CollectionSlug = 'users',\n credentials: { email: string; password: string } = users.admin\n ): Promise<string> {\n const result = await this.post(`/${slug}/login`, {\n email: credentials.email,\n password: credentials.password,\n });\n return result.token as string;\n }\n\n async login({\n slug,\n credentials,\n }: {\n slug: string;\n credentials?: {\n email: string;\n password: string;\n };\n }): Promise<{ [key: string]: any }> {\n const response = await this.POST(`/${slug}/login`, {\n body: JSON.stringify(\n credentials\n ? {\n ...credentials,\n }\n : {\n email: users.admin.email,\n password: users.admin.password,\n }\n ),\n });\n const result = await response.json();\n this.token = result.token;\n if (!result.token) {\n // If the token is not in the response body, then we can extract it from the cookies\n const setCookie = response.headers.get('Set-Cookie');\n const tokenMatchResult = setCookie?.match(/payload-token=(?<token>.+?);/);\n this.token = tokenMatchResult?.groups?.token || '';\n }\n return result;\n }\n}\n","import type { EmailAdapter, SendEmailOptions } from 'payload';\n\nexport const testEmailAdapter: EmailAdapter<void> = ({ payload }) => ({\n name: 'test-email-adapter',\n defaultFromAddress: 'dev@payloadcms.com',\n defaultFromName: 'Payload Test',\n sendEmail: async (message) => {\n const stringifiedTo = getStringifiedToAddress(message);\n const res = `Test email to: '${stringifiedTo}', Subject: '${message.subject}'`;\n payload.logger.info({ content: message, msg: res });\n return Promise.resolve();\n },\n});\n\nfunction getAddress(to: unknown): string {\n if (typeof to === 'string') {\n return to;\n }\n if (to && typeof to === 'object' && 'address' in to && typeof to.address === 'string') {\n return to.address;\n }\n return '';\n}\n\nfunction getStringifiedToAddress(message: SendEmailOptions): string | undefined {\n if (!message.to) {\n return undefined;\n }\n return Array.isArray(message.to)\n ? message.to.map(getAddress).join(', ')\n : getAddress(message.to) || undefined;\n}\n","import { mongooseAdapter } from '@payloadcms/db-mongodb';\nimport { lexicalEditor } from '@payloadcms/richtext-lexical';\nimport { slateEditor } from '@payloadcms/richtext-slate';\nimport { memoryAdapter } from '@websolutespa/payload-db-memory';\nimport { MongoMemoryReplSet } from 'mongodb-memory-server';\nimport path from 'path';\nimport { buildConfig, Config, SanitizedConfig } from 'payload';\nimport sharp from 'sharp';\nimport { fileURLToPath } from 'url';\nimport { testEmailAdapter } from './email.adapter';\nimport type { TestPayload } from './context';\nimport { seed } from './seed';\n\nconst SLATE = true;\n\nexport type TestDatabase = 'mongo' | 'memory';\n\nexport type TestConfigOptions = {\n /**\n * Database backing the test payload.\n * - 'mongo' (default): MongoMemoryReplSet + mongooseAdapter, Slate editor.\n * - 'memory': @websolutespa/payload-db-memory, Lexical editor (no replica set, no DATABASE_URL).\n * Defaults to the BOM_TEST_DB environment variable when set.\n */\n db?: TestDatabase;\n};\n\nfunction resolveDatabase(options?: TestConfigOptions): TestDatabase {\n return options?.db || (process.env.BOM_TEST_DB === 'memory' ? 'memory' : 'mongo');\n}\n\nconst filename = fileURLToPath(import.meta.url);\nconst dirname = path.dirname(filename);\n\nif (!process.env.ROOT_DIR) {\n process.env.ROOT_DIR = dirname;\n}\n\nconst buildConfigWithMemoryDB = async (config: Partial<Config>, options?: TestConfigOptions) => {\n const memory = resolveDatabase(options) === 'memory';\n if (!memory && process.env.NODE_ENV === 'test') {\n const memoryDB = await MongoMemoryReplSet.create({\n replSet: {\n count: 3,\n dbName: 'payloadmemory',\n },\n });\n process.env.DATABASE_URL = `${memoryDB.getUri()}&retryWrites=true`;\n }\n // console.log('NODE_ENV', process.env.NODE_ENV, process.env.DATABASE_URL);\n return buildConfig({\n ...config,\n admin: {\n ...config.admin,\n importMap: {\n baseDir: path.resolve(dirname),\n },\n },\n db: memory\n ? memoryAdapter()\n : mongooseAdapter({\n ensureIndexes: true,\n url: process.env.DATABASE_URL || '',\n }),\n editor: memory ? config.editor || lexicalEditor() : SLATE ? slateEditor({}) : lexicalEditor(),\n email: testEmailAdapter,\n i18n: {\n ...config.i18n,\n fallbackLanguage: 'en',\n },\n // indexSortableFields: true\n localization: {\n locales: ['en', 'it'],\n defaultLocale: 'en',\n fallback: true,\n },\n maxDepth: 10,\n onInit: async (payload) => {\n await seed(payload as TestPayload);\n },\n serverURL: 'http://localhost:3000',\n secret: process.env.PAYLOAD_SECRET || 'test-secret_key',\n sharp,\n typescript: {\n declare: false,\n outputFile: path.resolve(dirname, 'payload-types.ts'),\n },\n });\n};\n\nexport async function getConfig(\n config: Partial<Config>,\n options?: TestConfigOptions\n): Promise<SanitizedConfig> {\n return await buildConfigWithMemoryDB(config, options);\n}\n","import type { Config, Payload } from 'payload';\nimport { getPayload } from 'payload';\nimport { RestClient } from './client';\nimport { getConfig, type TestConfigOptions } from './config';\n\n/**\n * Local Payload API surface for integration suites that register collections\n * at runtime and therefore cannot use an application's generated schema.\n * It is an intersection with Payload, so it stays assignable to Payload.\n */\nexport type TestPayload = Payload & {\n create: (options: unknown) => Promise<any>;\n find: (options: unknown) => Promise<any>;\n findByID: (options: unknown) => Promise<any>;\n update: (options: unknown) => Promise<any>;\n};\n\nexport type TestContext = {\n payload: TestPayload;\n client: RestClient;\n};\n\nlet CONTEXT: TestContext | undefined = undefined;\n\nexport async function getContext(\n userConfig: Partial<Config>,\n options?: TestConfigOptions\n): Promise<TestContext> {\n if (CONTEXT) {\n return CONTEXT;\n }\n const config = await getConfig(userConfig, options);\n const payload = await getPayload({ config });\n const client = new RestClient(payload.config);\n const context: TestContext = {\n payload: payload as TestPayload,\n client,\n };\n CONTEXT = context;\n // onTestFinished(async () => await clearContext(context));\n return context;\n}\n\nexport async function clearContext(context?: TestContext) {\n /*\n if (context?.payload) {\n await context.payload.destroy();\n }\n */\n}\n\n/*\nexport default function setup(project: TestProject) {\n project.onTestsRerun(async () => {\n const context = await getContext();\n });\n}\n*/\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest-setup-dom.js","names":[],"sources":["../../src/exports/vitest-setup-dom.ts"],"sourcesContent":["// vitest setup of `defineDomConfig`: `@testing-library/jest-dom` matchers and dom cleanup between tests\
|
|
1
|
+
{"version":3,"file":"vitest-setup-dom.js","names":[],"sources":["../../src/exports/vitest-setup-dom.ts"],"sourcesContent":["// vitest setup of `defineDomConfig`: `@testing-library/jest-dom` matchers and dom cleanup between tests\nimport '@testing-library/jest-dom/vitest';\nimport { cleanup } from '@testing-library/react';\nimport { afterEach } from 'vitest';\n\nafterEach(() => {\n cleanup();\n});\n"],"mappings":";;;;AAKA,gBAAgB;AACd,UAAS;EACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest.d.ts","names":[],"sources":["../../src/exports/vitest.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"vitest.d.ts","names":[],"sources":["../../src/exports/vitest.ts"],"mappings":";;;;;AA0CA;iBAAgB,gBAAA,CAAiB,MAAA,GAAQ,cAAA,GAAmB,cAAA;;;;iBAO5C,eAAA,CAAgB,MAAA,GAAQ,cAAA,GAAmB,cAAA;;;;AAA3D;;iBAmBgB,mBAAA,CAAoB,MAAA,GAAQ,cAAA,GAAmB,cAAA"}
|
package/dist/exports/vitest.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest.js","names":[],"sources":["../../src/exports/vitest.ts"],"sourcesContent":["import react from '@vitejs/plugin-react';\
|
|
1
|
+
{"version":3,"file":"vitest.js","names":[],"sources":["../../src/exports/vitest.ts"],"sourcesContent":["import react from '@vitejs/plugin-react';\nimport { configDefaults, defineConfig, mergeConfig, type ViteUserConfig } from 'vitest/config';\n\n/**\n * Shared vitest configurations of the BOM Repository.\n * Each factory takes an optional config, deep merged over the defaults.\n *\n * @example\n * ```ts\n * // vitest.config.ts\n * import { definePayloadConfig } from '@websolutespa/test/vitest';\n * export default definePayloadConfig();\n * ```\n */\n\nconst baseConfig: ViteUserConfig = {\n plugins: [react()],\n resolve: {\n tsconfigPaths: true,\n },\n test: {\n environment: 'node',\n // build outputs may contain compiled test files\n exclude: [...configDefaults.exclude, '**/dist/**', '**/.next/**'],\n hookTimeout: 30_000,\n testTimeout: 30_000,\n // one module cache per project: the default one at the workspace root is shared\n // by the parallel turbo test tasks, and clearing it fails with EBUSY on windows\n fsModuleCachePath: 'node_modules/.vitest-cache',\n server: {\n deps: {\n // compiled by vite like Next compiles them (transpilePackages): plain Node ESM cannot resolve\n // their extensionless imports of packages without an exports map (e.g. `next/server`)\n inline: [/@websolutespa\\//],\n },\n },\n },\n};\n\n/**\n * Node environment, for libraries and server code.\n */\nexport function defineNodeConfig(config: ViteUserConfig = {}) {\n return defineConfig(mergeConfig(baseConfig, config));\n}\n\n/**\n * jsdom environment with the `@testing-library/jest-dom` matchers, for react components and hooks.\n */\nexport function defineDomConfig(config: ViteUserConfig = {}) {\n return defineConfig(\n mergeConfig(\n mergeConfig(baseConfig, {\n test: {\n environment: 'jsdom',\n setupFiles: ['@websolutespa/test/vitest-setup-dom'],\n },\n }),\n config\n )\n );\n}\n\n/**\n * Node environment for Payload integration suites built with `@websolutespa/test/payload`.\n * Uses the in-memory database by default, `BOM_TEST_DB=mongo` switches to a mongo replica set.\n * Node, not jsdom: jsdom breaks the Payload REST api.\n */\nexport function definePayloadConfig(config: ViteUserConfig = {}) {\n return defineConfig(\n mergeConfig(\n mergeConfig(baseConfig, {\n test: {\n // payload init seeds the database\n hookTimeout: 5 * 60_000,\n env: {\n BOM_TEST_DB: process.env.BOM_TEST_DB || 'memory',\n },\n },\n }),\n config\n )\n );\n}\n"],"mappings":";;;;;;;;;;;;;;AAeA,MAAM,aAA6B;CACjC,SAAS,CAAC,OAAO,CAAC;CAClB,SAAS,EACP,eAAe,MAChB;CACD,MAAM;EACJ,aAAa;EAEb,SAAS;GAAC,GAAG,eAAe;GAAS;GAAc;GAAc;EACjE,aAAa;EACb,aAAa;EAGb,mBAAmB;EACnB,QAAQ,EACN,MAAM,EAGJ,QAAQ,CAAC,kBAAkB,EAC5B,EACF;EACF;CACF;;;;AAKD,SAAgB,iBAAiB,SAAyB,EAAE,EAAE;AAC5D,QAAO,aAAa,YAAY,YAAY,OAAO,CAAC;;;;;AAMtD,SAAgB,gBAAgB,SAAyB,EAAE,EAAE;AAC3D,QAAO,aACL,YACE,YAAY,YAAY,EACtB,MAAM;EACJ,aAAa;EACb,YAAY,CAAC,sCAAsC;EACpD,EACF,CAAC,EACF,OACD,CACF;;;;;;;AAQH,SAAgB,oBAAoB,SAAyB,EAAE,EAAE;AAC/D,QAAO,aACL,YACE,YAAY,YAAY,EACtB,MAAM;EAEJ,aAAa,IAAI;EACjB,KAAK,EACH,aAAa,QAAQ,IAAI,eAAe,UACzC;EACF,EACF,CAAC,EACF,OACD,CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@websolutespa/test",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0-next.6",
|
|
4
4
|
"description": "Test shared config of the BOM Repository",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bom",
|
|
@@ -11,31 +11,25 @@
|
|
|
11
11
|
"type": "git",
|
|
12
12
|
"url": "git://github.com/websolutespa/bom.git"
|
|
13
13
|
},
|
|
14
|
-
"scripts": {
|
|
15
|
-
"lint": "eslint .",
|
|
16
|
-
"compile": "tsdown",
|
|
17
|
-
"prepack": "bom prepack",
|
|
18
|
-
"postpack": "bom postpack",
|
|
19
|
-
"types": "tsc --noemit"
|
|
20
|
-
},
|
|
21
14
|
"peerDependencies": {
|
|
22
15
|
"@payloadcms/db-mongodb": "^3.91.0",
|
|
23
16
|
"@payloadcms/next": "^3.91.0",
|
|
24
17
|
"@payloadcms/richtext-lexical": "^3.91.0",
|
|
25
18
|
"@payloadcms/richtext-slate": "^3.91.0",
|
|
26
|
-
"@websolutespa/bom-core": "^
|
|
19
|
+
"@websolutespa/bom-core": "^4.0.0-next.1",
|
|
27
20
|
"next": "^16.3.3",
|
|
28
21
|
"payload": "^3.91.0",
|
|
29
22
|
"react": "^19.2.1",
|
|
30
23
|
"react-dom": "^19.2.1",
|
|
31
|
-
"vitest": "^5.0.5"
|
|
24
|
+
"vitest": "^5.0.5",
|
|
25
|
+
"@websolutespa/payload-db-memory": "^4.0.0-next.6"
|
|
32
26
|
},
|
|
33
27
|
"dependencies": {
|
|
34
28
|
"@testing-library/dom": "10.4.2",
|
|
35
29
|
"@testing-library/jest-dom": "7.0.1",
|
|
36
30
|
"@testing-library/react": "16.3.3",
|
|
37
31
|
"@vitejs/plugin-react": "6.1.2",
|
|
38
|
-
"@websolutespa/payload-db-memory": "^
|
|
32
|
+
"@websolutespa/payload-db-memory": "^4.0.0-next.6",
|
|
39
33
|
"jsdom": "30.1.3",
|
|
40
34
|
"mongodb-memory-server": "11.3.0",
|
|
41
35
|
"qs-esm": "7.0.2",
|
|
@@ -43,9 +37,12 @@
|
|
|
43
37
|
"vite": "8.3.5"
|
|
44
38
|
},
|
|
45
39
|
"devDependencies": {
|
|
46
|
-
"@
|
|
47
|
-
"eslint": "
|
|
40
|
+
"@types/node": "24.19.2",
|
|
41
|
+
"@websolutespa/eslint-config": "^4.0.0-next.6",
|
|
42
|
+
"@websolutespa/tsconfig": "^4.0.0-next.6",
|
|
48
43
|
"next": "16.4.2",
|
|
44
|
+
"oxlint": "1.89.0",
|
|
45
|
+
"oxlint-tsgolint": "7.0.2005",
|
|
49
46
|
"tsdown": "0.21.0",
|
|
50
47
|
"typescript": "6.0.3"
|
|
51
48
|
},
|
|
@@ -158,5 +155,10 @@
|
|
|
158
155
|
"types": "./dist/exports/vitest-setup-dom.d.ts",
|
|
159
156
|
"default": "./dist/exports/vitest-setup-dom.js"
|
|
160
157
|
}
|
|
158
|
+
},
|
|
159
|
+
"scripts": {
|
|
160
|
+
"lint": "oxlint --type-aware",
|
|
161
|
+
"compile": "tsdown",
|
|
162
|
+
"types": "tsc --noemit"
|
|
161
163
|
}
|
|
162
164
|
}
|