@websolutespa/test 3.0.1 → 3.1.0
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 +35 -0
- package/README.md +24 -0
- package/dist/exports/payload.d.ts +162 -0
- package/dist/exports/payload.d.ts.map +1 -0
- package/dist/exports/payload.js +354 -0
- package/dist/exports/payload.js.map +1 -0
- package/dist/exports/vitest-setup-dom.d.ts +1 -0
- package/dist/exports/vitest-setup-dom.js +11 -0
- package/dist/exports/vitest-setup-dom.js.map +1 -0
- package/dist/exports/vitest.d.ts +20 -0
- package/dist/exports/vitest.d.ts.map +1 -0
- package/dist/exports/vitest.js +58 -0
- package/dist/exports/vitest.js.map +1 -0
- package/dist/index.d.ts +2 -9
- package/dist/index.js +2 -214
- package/package.json +87 -26
- package/dist/index.cjs +0 -246
- package/dist/index.d.cts +0 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# @websolutespa/test
|
|
2
2
|
|
|
3
|
+
## 3.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 3f7c21b: - Payload 3.91.0 and Next.js 16.4.2 (React 19.2.9): peer dependencies are now ranges, `payload` / `@payloadcms/*` `^3.91.0`, `next` `^16.3.3`, `react` / `react-dom` `^19.2.1`
|
|
8
|
+
- payload-plugin-bowl: the mixer context is built only for reads by an authenticated user (payload 3.90+ resolves the jwt user with the request query, populating tenants before `req.user` is set); email options typed with payload `SendEmailOptions`, no direct nodemailer dependency
|
|
9
|
+
- payload-plugin-storage: `AZURE_STORAGE_CONTAINER_ACCESS` (`private` default since payload 3.90, `blob`, `container`) for containers created by the plugin
|
|
10
|
+
- mixer web: `images.qualities` includes `IMAGE_QUALITY` (next 16 defaults to `[75]`)
|
|
11
|
+
- e96a9d6: - tsconfig: TypeScript 6, `types: ["node"]` (no longer implicit) and `noUncheckedSideEffectImports: false` in the base config; drop `baseUrl` in consumers (deprecated)
|
|
12
|
+
- test: vitest 5 / vite 8 (native tsconfig paths, `vite-tsconfig-paths` removed), build outputs excluded from the test run, jsdom 30, testing-library jest-dom 7
|
|
13
|
+
- bom-mixer-llm: `isChunkType` guard, narrowing of unknown chunk items under typescript 6
|
|
14
|
+
- node 24 (engines >= 22.13)
|
|
15
|
+
- 12b6e2f: - test: replace the jest presets with shared vitest configurations, `@websolutespa/test/vitest` (`defineNodeConfig`, `defineDomConfig`, `definePayloadConfig`); drop jest dependencies
|
|
16
|
+
- declare every imported package and script binary in the package that uses it (no more reliance on hoisting), drop unused dependencies
|
|
17
|
+
- bom-mixer-checkout: `useCart.add` no longer mutates the previous cart state
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- b320a0f: - payload-db-memory: keep versions when Payload enforces `maxPerDoc`, query drafts on `version.*`, apply static field defaults and `$push` on jobs (queued jobs now run), store `Date` values as ISO strings
|
|
22
|
+
- payload-plugin-bowl: support inline array `src` for static collections, decorate rich text with mixer context (`beforeOperationHook`), create redirects on slug updates, honour `getTranslation` default text, keep the app `config.custom`
|
|
23
|
+
- payload-plugin-bowl-llm: merge `config.custom` instead of replacing it
|
|
24
|
+
- payload-plugin-cron-job: mark failing handlers as failed, log unknown jobs correctly
|
|
25
|
+
- payload-plugin-search: match tab fields, trim slate trailing new lines, return 400 when the query is missing
|
|
26
|
+
- test: `getConfig` / `getContext` accept `{ db: 'memory' | 'mongo' }` (default from `BOM_TEST_DB`)
|
|
27
|
+
- Updated dependencies [b320a0f]
|
|
28
|
+
- Updated dependencies [3f7c21b]
|
|
29
|
+
- Updated dependencies [12b6e2f]
|
|
30
|
+
- @websolutespa/payload-db-memory@3.1.0
|
|
31
|
+
|
|
32
|
+
## 3.0.2
|
|
33
|
+
|
|
34
|
+
### Patch Changes
|
|
35
|
+
|
|
36
|
+
- Fixing: payload exports
|
|
37
|
+
|
|
3
38
|
## 3.0.1
|
|
4
39
|
|
|
5
40
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -9,3 +9,27 @@ Test shared config of the [BOM Repository](https://github.com/websolutespa/bom)
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
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`).
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { CollectionSlug, Config, JoinQuery, Payload, PopulateType, SanitizedConfig, SelectType, Where } from "payload";
|
|
2
|
+
|
|
3
|
+
//#region src/payload/client.d.ts
|
|
4
|
+
type ValidPath = `/${string}`;
|
|
5
|
+
type FileArg = {
|
|
6
|
+
file?: Omit<File, 'webkitRelativePath'>;
|
|
7
|
+
};
|
|
8
|
+
type RequestQuery = {
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
} & {
|
|
11
|
+
depth?: number;
|
|
12
|
+
fallbackLocale?: string;
|
|
13
|
+
joins?: JoinQuery;
|
|
14
|
+
limit?: number;
|
|
15
|
+
locale?: string;
|
|
16
|
+
page?: number;
|
|
17
|
+
populate?: PopulateType;
|
|
18
|
+
select?: SelectType;
|
|
19
|
+
sort?: string;
|
|
20
|
+
where?: Where;
|
|
21
|
+
};
|
|
22
|
+
type RequestOptions = {
|
|
23
|
+
auth?: boolean;
|
|
24
|
+
query?: RequestQuery;
|
|
25
|
+
};
|
|
26
|
+
type ClientRequestOptions = FileArg & RequestInit & RequestOptions;
|
|
27
|
+
type NextRoute = (request: Request, args: {
|
|
28
|
+
params: Promise<{
|
|
29
|
+
slug: string[];
|
|
30
|
+
}>;
|
|
31
|
+
}) => Promise<Response>;
|
|
32
|
+
declare class RestClient {
|
|
33
|
+
private readonly config;
|
|
34
|
+
serverURL: string;
|
|
35
|
+
private token;
|
|
36
|
+
private getRest_;
|
|
37
|
+
private postRest_;
|
|
38
|
+
private putRest_;
|
|
39
|
+
private patchRest_;
|
|
40
|
+
private deleteRest_;
|
|
41
|
+
private postGraphql_;
|
|
42
|
+
constructor(config: SanitizedConfig);
|
|
43
|
+
private getHeaders;
|
|
44
|
+
private getPathParts;
|
|
45
|
+
GET(path: ValidPath, options?: Omit<ClientRequestOptions, 'body' | 'file'>): Promise<Response>;
|
|
46
|
+
POST(path: ValidPath, options?: ClientRequestOptions): Promise<Response>;
|
|
47
|
+
PUT(path: ValidPath, options?: ClientRequestOptions): Promise<Response>;
|
|
48
|
+
PATCH(path: ValidPath, options?: ClientRequestOptions): Promise<Response>;
|
|
49
|
+
DELETE(path: ValidPath, options?: Omit<ClientRequestOptions, 'file'>): Promise<Response>;
|
|
50
|
+
GRAPHQL_POST(options?: Omit<ClientRequestOptions, 'file'>): Promise<Response>;
|
|
51
|
+
get(path: string, options?: Omit<ClientRequestOptions, 'body' | 'file'>): Promise<{
|
|
52
|
+
[key: string]: any;
|
|
53
|
+
}>;
|
|
54
|
+
post(path: string, body: any, options?: ClientRequestOptions): Promise<{
|
|
55
|
+
[key: string]: any;
|
|
56
|
+
}>;
|
|
57
|
+
patch(path: string, body: any, options?: ClientRequestOptions): Promise<{
|
|
58
|
+
[key: string]: any;
|
|
59
|
+
}>;
|
|
60
|
+
delete(path: string, options?: Omit<ClientRequestOptions, 'body' | 'file'>): Promise<{
|
|
61
|
+
[key: string]: any;
|
|
62
|
+
}>;
|
|
63
|
+
getToken(slug?: CollectionSlug, credentials?: {
|
|
64
|
+
email: string;
|
|
65
|
+
password: string;
|
|
66
|
+
}): Promise<string>;
|
|
67
|
+
login({
|
|
68
|
+
slug,
|
|
69
|
+
credentials
|
|
70
|
+
}: {
|
|
71
|
+
slug: string;
|
|
72
|
+
credentials?: {
|
|
73
|
+
email: string;
|
|
74
|
+
password: string;
|
|
75
|
+
};
|
|
76
|
+
}): Promise<{
|
|
77
|
+
[key: string]: any;
|
|
78
|
+
}>;
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
//#region src/payload/config.d.ts
|
|
82
|
+
type TestDatabase = 'mongo' | 'memory';
|
|
83
|
+
type TestConfigOptions = {
|
|
84
|
+
/**
|
|
85
|
+
* Database backing the test payload.
|
|
86
|
+
* - 'mongo' (default): MongoMemoryReplSet + mongooseAdapter, Slate editor.
|
|
87
|
+
* - 'memory': @websolutespa/payload-db-memory, Lexical editor (no replica set, no DATABASE_URL).
|
|
88
|
+
* Defaults to the BOM_TEST_DB environment variable when set.
|
|
89
|
+
*/
|
|
90
|
+
db?: TestDatabase;
|
|
91
|
+
};
|
|
92
|
+
declare function getConfig(config: Partial<Config>, options?: TestConfigOptions): Promise<SanitizedConfig>;
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/payload/context.d.ts
|
|
95
|
+
/**
|
|
96
|
+
* Local Payload API surface for integration suites that register collections
|
|
97
|
+
* at runtime and therefore cannot use an application's generated schema.
|
|
98
|
+
* It is an intersection with Payload, so it stays assignable to Payload.
|
|
99
|
+
*/
|
|
100
|
+
type TestPayload = Payload & {
|
|
101
|
+
create: (options: unknown) => Promise<any>;
|
|
102
|
+
find: (options: unknown) => Promise<any>;
|
|
103
|
+
findByID: (options: unknown) => Promise<any>;
|
|
104
|
+
update: (options: unknown) => Promise<any>;
|
|
105
|
+
};
|
|
106
|
+
type TestContext = {
|
|
107
|
+
payload: TestPayload;
|
|
108
|
+
client: RestClient;
|
|
109
|
+
};
|
|
110
|
+
declare function getContext(userConfig: Partial<Config>, options?: TestConfigOptions): Promise<TestContext>;
|
|
111
|
+
declare function clearContext(context?: TestContext): Promise<void>;
|
|
112
|
+
//#endregion
|
|
113
|
+
//#region src/payload/seed.d.ts
|
|
114
|
+
/**
|
|
115
|
+
* Defaults user roles and endUser roles available on the bowl plugin configuration:
|
|
116
|
+
*
|
|
117
|
+
* admin: user role with super powers.
|
|
118
|
+
* contributor: user role with minor powers.
|
|
119
|
+
* editor: user role with content editing powers.
|
|
120
|
+
* guest: endUser role with application reading capabilities.
|
|
121
|
+
* user: endUser authenticated role with reserved data.
|
|
122
|
+
*
|
|
123
|
+
*/
|
|
124
|
+
declare const roles: {
|
|
125
|
+
readonly Admin: "admin";
|
|
126
|
+
readonly Contributor: "contributor";
|
|
127
|
+
readonly Editor: "editor";
|
|
128
|
+
readonly Guest: "guest";
|
|
129
|
+
readonly User: "user";
|
|
130
|
+
};
|
|
131
|
+
declare const users: {
|
|
132
|
+
admin: {
|
|
133
|
+
email: string;
|
|
134
|
+
password: string;
|
|
135
|
+
roles: "admin"[];
|
|
136
|
+
};
|
|
137
|
+
editor: {
|
|
138
|
+
email: string;
|
|
139
|
+
password: string;
|
|
140
|
+
roles: "editor"[];
|
|
141
|
+
};
|
|
142
|
+
api: {
|
|
143
|
+
email: string;
|
|
144
|
+
password: string;
|
|
145
|
+
roles: "guest"[];
|
|
146
|
+
enableAPIKey: boolean;
|
|
147
|
+
apiKey: string;
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
declare const endUsers: {
|
|
151
|
+
user: {
|
|
152
|
+
email: string;
|
|
153
|
+
password: string;
|
|
154
|
+
roles: ("guest" | "user")[];
|
|
155
|
+
};
|
|
156
|
+
};
|
|
157
|
+
declare const seedUsers: (payload: TestPayload) => Promise<void>;
|
|
158
|
+
declare const seedEndUsers: (payload: TestPayload) => Promise<void>;
|
|
159
|
+
declare const seed: (payload: TestPayload) => Promise<void>;
|
|
160
|
+
//#endregion
|
|
161
|
+
export { ClientRequestOptions, FileArg, NextRoute, RequestOptions, RequestQuery, RestClient, TestConfigOptions, TestContext, TestDatabase, TestPayload, ValidPath, clearContext, endUsers, getConfig, getContext, roles, seed, seedEndUsers, seedUsers, users };
|
|
162
|
+
//# sourceMappingURL=payload.d.ts.map
|
|
@@ -0,0 +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":"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"}
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
import { GRAPHQL_POST, REST_DELETE, REST_GET, REST_PATCH, REST_POST, REST_PUT } from "@payloadcms/next/routes";
|
|
2
|
+
import * as qs from "qs-esm";
|
|
3
|
+
import { uuidv4 } from "@websolutespa/bom-core";
|
|
4
|
+
import { mongooseAdapter } from "@payloadcms/db-mongodb";
|
|
5
|
+
import { lexicalEditor } from "@payloadcms/richtext-lexical";
|
|
6
|
+
import { slateEditor } from "@payloadcms/richtext-slate";
|
|
7
|
+
import { memoryAdapter } from "@websolutespa/payload-db-memory";
|
|
8
|
+
import { MongoMemoryReplSet } from "mongodb-memory-server";
|
|
9
|
+
import path from "path";
|
|
10
|
+
import { buildConfig, getPayload } from "payload";
|
|
11
|
+
import sharp from "sharp";
|
|
12
|
+
import { fileURLToPath } from "url";
|
|
13
|
+
//#region src/payload/seed.ts
|
|
14
|
+
/**
|
|
15
|
+
* Defaults user roles and endUser roles available on the bowl plugin configuration:
|
|
16
|
+
*
|
|
17
|
+
* admin: user role with super powers.
|
|
18
|
+
* contributor: user role with minor powers.
|
|
19
|
+
* editor: user role with content editing powers.
|
|
20
|
+
* guest: endUser role with application reading capabilities.
|
|
21
|
+
* user: endUser authenticated role with reserved data.
|
|
22
|
+
*
|
|
23
|
+
*/
|
|
24
|
+
const roles = {
|
|
25
|
+
Admin: "admin",
|
|
26
|
+
Contributor: "contributor",
|
|
27
|
+
Editor: "editor",
|
|
28
|
+
Guest: "guest",
|
|
29
|
+
User: "user"
|
|
30
|
+
};
|
|
31
|
+
const users = {
|
|
32
|
+
admin: {
|
|
33
|
+
email: "admin@payload.com",
|
|
34
|
+
password: "admin@payload.com",
|
|
35
|
+
roles: [roles.Admin]
|
|
36
|
+
},
|
|
37
|
+
editor: {
|
|
38
|
+
email: "editor@payload.com",
|
|
39
|
+
password: "editor@payload.com",
|
|
40
|
+
roles: [roles.Editor]
|
|
41
|
+
},
|
|
42
|
+
api: {
|
|
43
|
+
email: "api@payload.com",
|
|
44
|
+
password: "api@payload.com",
|
|
45
|
+
roles: [roles.Guest],
|
|
46
|
+
enableAPIKey: true,
|
|
47
|
+
apiKey: uuidv4()
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const endUsers = { user: {
|
|
51
|
+
email: "user@payload.com",
|
|
52
|
+
password: "user@payload.com",
|
|
53
|
+
roles: [roles.Guest, roles.User]
|
|
54
|
+
} };
|
|
55
|
+
const seedUsers = async (payload) => {
|
|
56
|
+
const { totalDocs } = await payload.count({ collection: "users" });
|
|
57
|
+
if (totalDocs === 0) for (const entry of Object.entries(users)) {
|
|
58
|
+
const user = entry[1];
|
|
59
|
+
await payload.create({
|
|
60
|
+
collection: "users",
|
|
61
|
+
data: user
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const seedEndUsers = async (payload) => {
|
|
66
|
+
const { totalDocs } = await payload.count({ collection: "end_users" });
|
|
67
|
+
if (totalDocs === 0) for (const entry of Object.entries(endUsers)) {
|
|
68
|
+
const user = entry[1];
|
|
69
|
+
await payload.create({
|
|
70
|
+
collection: "end_users",
|
|
71
|
+
data: user,
|
|
72
|
+
draft: false
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const seed = async (payload) => {
|
|
77
|
+
if (payload.collections["users"] !== void 0) await seedUsers(payload);
|
|
78
|
+
if (payload.collections["end_users"] !== void 0) await seedEndUsers(payload);
|
|
79
|
+
};
|
|
80
|
+
//#endregion
|
|
81
|
+
//#region src/payload/client.ts
|
|
82
|
+
function asValidPath(path) {
|
|
83
|
+
if (!path.match(/^\//)) path = `/${path}`;
|
|
84
|
+
return path;
|
|
85
|
+
}
|
|
86
|
+
function getQueryString(query, params) {
|
|
87
|
+
return qs.stringify({
|
|
88
|
+
...params || {},
|
|
89
|
+
...query || {}
|
|
90
|
+
}, { addQueryPrefix: true });
|
|
91
|
+
}
|
|
92
|
+
var RestClient = class {
|
|
93
|
+
config;
|
|
94
|
+
serverURL = "http://localhost:3000";
|
|
95
|
+
token = "";
|
|
96
|
+
getRest_;
|
|
97
|
+
postRest_;
|
|
98
|
+
putRest_;
|
|
99
|
+
patchRest_;
|
|
100
|
+
deleteRest_;
|
|
101
|
+
postGraphql_;
|
|
102
|
+
constructor(config) {
|
|
103
|
+
this.config = config;
|
|
104
|
+
if (config?.serverURL) this.serverURL = config.serverURL;
|
|
105
|
+
this.getRest_ = REST_GET(config);
|
|
106
|
+
this.postRest_ = REST_POST(config);
|
|
107
|
+
this.putRest_ = REST_PUT(config);
|
|
108
|
+
this.patchRest_ = REST_PATCH(config);
|
|
109
|
+
this.deleteRest_ = REST_DELETE(config);
|
|
110
|
+
this.postGraphql_ = GRAPHQL_POST(config);
|
|
111
|
+
}
|
|
112
|
+
getHeaders(options) {
|
|
113
|
+
const headers = new Headers({
|
|
114
|
+
...options?.file ? { "Content-Length": options.file.size.toString() } : { "Content-Type": "application/json" },
|
|
115
|
+
...options?.headers || {}
|
|
116
|
+
});
|
|
117
|
+
if (options.auth !== false && this.token) headers.set("Authorization", `JWT ${this.token}`);
|
|
118
|
+
if (options.auth === false) headers.set("DisableAutologin", "true");
|
|
119
|
+
return headers;
|
|
120
|
+
}
|
|
121
|
+
getPathParts(path) {
|
|
122
|
+
const [slugs, params] = path.slice(1).split("?");
|
|
123
|
+
const url = `${this.serverURL}${this.config.routes.api}/${slugs}`;
|
|
124
|
+
return {
|
|
125
|
+
slug: slugs.split("/"),
|
|
126
|
+
params: params ? qs.parse(params) : void 0,
|
|
127
|
+
url
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
async GET(path, options = {}) {
|
|
131
|
+
const { slug, params, url } = this.getPathParts(path);
|
|
132
|
+
const { query, ...rest } = options || {};
|
|
133
|
+
const queryParams = getQueryString(query, params);
|
|
134
|
+
const request = new Request(`${url}${queryParams}`, {
|
|
135
|
+
...rest,
|
|
136
|
+
headers: this.getHeaders(options),
|
|
137
|
+
method: "GET"
|
|
138
|
+
});
|
|
139
|
+
return this.getRest_(request, { params: Promise.resolve({ slug }) });
|
|
140
|
+
}
|
|
141
|
+
async POST(path, options = {}) {
|
|
142
|
+
const { slug, params, url } = this.getPathParts(path);
|
|
143
|
+
const queryParams = getQueryString({}, params);
|
|
144
|
+
const request = new Request(`${url}${queryParams}`, {
|
|
145
|
+
...options,
|
|
146
|
+
headers: this.getHeaders(options),
|
|
147
|
+
method: "POST"
|
|
148
|
+
});
|
|
149
|
+
return this.postRest_(request, { params: Promise.resolve({ slug }) });
|
|
150
|
+
}
|
|
151
|
+
async PUT(path, options = {}) {
|
|
152
|
+
const { slug, params, url } = this.getPathParts(path);
|
|
153
|
+
const { query, ...rest } = options;
|
|
154
|
+
const queryParams = getQueryString(query, params);
|
|
155
|
+
const request = new Request(`${url}${queryParams}`, {
|
|
156
|
+
...rest,
|
|
157
|
+
headers: this.getHeaders(options),
|
|
158
|
+
method: "PUT"
|
|
159
|
+
});
|
|
160
|
+
return this.putRest_(request, { params: Promise.resolve({ slug }) });
|
|
161
|
+
}
|
|
162
|
+
async PATCH(path, options = {}) {
|
|
163
|
+
const { slug, params, url } = this.getPathParts(path);
|
|
164
|
+
const { query, ...rest } = options;
|
|
165
|
+
const queryParams = getQueryString(query, params);
|
|
166
|
+
const request = new Request(`${url}${queryParams}`, {
|
|
167
|
+
...rest,
|
|
168
|
+
headers: this.getHeaders(options),
|
|
169
|
+
method: "PATCH"
|
|
170
|
+
});
|
|
171
|
+
return this.patchRest_(request, { params: Promise.resolve({ slug }) });
|
|
172
|
+
}
|
|
173
|
+
async DELETE(path, options = {}) {
|
|
174
|
+
const { slug, params, url } = this.getPathParts(path);
|
|
175
|
+
const { query, ...rest } = options || {};
|
|
176
|
+
const queryParams = getQueryString(query, params);
|
|
177
|
+
const request = new Request(`${url}${queryParams}`, {
|
|
178
|
+
...rest,
|
|
179
|
+
headers: this.getHeaders(options),
|
|
180
|
+
method: "DELETE"
|
|
181
|
+
});
|
|
182
|
+
return this.deleteRest_(request, { params: Promise.resolve({ slug }) });
|
|
183
|
+
}
|
|
184
|
+
async GRAPHQL_POST(options = {}) {
|
|
185
|
+
const { query, ...rest } = options;
|
|
186
|
+
const queryParams = getQueryString(query, {});
|
|
187
|
+
const request = new Request(`${this.serverURL}${this.config.routes.api}${this.config.routes.graphQL}${queryParams}`, {
|
|
188
|
+
...rest,
|
|
189
|
+
headers: this.getHeaders(options),
|
|
190
|
+
method: "POST"
|
|
191
|
+
});
|
|
192
|
+
return this.postGraphql_(request);
|
|
193
|
+
}
|
|
194
|
+
async get(path, options = {}) {
|
|
195
|
+
try {
|
|
196
|
+
const response = await this.GET(asValidPath(path), options);
|
|
197
|
+
if (!response.ok) throw response;
|
|
198
|
+
return await response.json();
|
|
199
|
+
} catch (error) {
|
|
200
|
+
console.log("RestClient.get.error", path, "json" in error ? await error.json() : error);
|
|
201
|
+
throw error;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
async post(path, body, options = {}) {
|
|
205
|
+
try {
|
|
206
|
+
options = {
|
|
207
|
+
...options,
|
|
208
|
+
body: JSON.stringify(body)
|
|
209
|
+
};
|
|
210
|
+
const response = await this.POST(asValidPath(path), options);
|
|
211
|
+
if (!response.ok) throw response;
|
|
212
|
+
return await response.json();
|
|
213
|
+
} catch (error) {
|
|
214
|
+
console.log("RestClient.post.error", path, error);
|
|
215
|
+
throw error;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
async patch(path, body, options = {}) {
|
|
219
|
+
try {
|
|
220
|
+
options = {
|
|
221
|
+
...options,
|
|
222
|
+
body: JSON.stringify(body)
|
|
223
|
+
};
|
|
224
|
+
const response = await this.PATCH(asValidPath(path), options);
|
|
225
|
+
if (!response.ok) throw response;
|
|
226
|
+
return await response.json();
|
|
227
|
+
} catch (error) {
|
|
228
|
+
console.log("RestClient.patch.error", path, error);
|
|
229
|
+
throw error;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
async delete(path, options = {}) {
|
|
233
|
+
try {
|
|
234
|
+
const response = await this.DELETE(asValidPath(path), options);
|
|
235
|
+
if (!response.ok) throw response;
|
|
236
|
+
return await response.json();
|
|
237
|
+
} catch (error) {
|
|
238
|
+
console.log("RestClient.delete.error", path, error);
|
|
239
|
+
throw error;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
async getToken(slug = "users", credentials = users.admin) {
|
|
243
|
+
return (await this.post(`/${slug}/login`, {
|
|
244
|
+
email: credentials.email,
|
|
245
|
+
password: credentials.password
|
|
246
|
+
})).token;
|
|
247
|
+
}
|
|
248
|
+
async login({ slug, credentials }) {
|
|
249
|
+
const response = await this.POST(`/${slug}/login`, { body: JSON.stringify(credentials ? { ...credentials } : {
|
|
250
|
+
email: users.admin.email,
|
|
251
|
+
password: users.admin.password
|
|
252
|
+
}) });
|
|
253
|
+
const result = await response.json();
|
|
254
|
+
this.token = result.token;
|
|
255
|
+
if (!result.token) this.token = (response.headers.get("Set-Cookie")?.match(/payload-token=(?<token>.+?);/))?.groups?.token || "";
|
|
256
|
+
return result;
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
//#endregion
|
|
260
|
+
//#region src/payload/email.adapter.ts
|
|
261
|
+
const testEmailAdapter = ({ payload }) => ({
|
|
262
|
+
name: "test-email-adapter",
|
|
263
|
+
defaultFromAddress: "dev@payloadcms.com",
|
|
264
|
+
defaultFromName: "Payload Test",
|
|
265
|
+
sendEmail: async (message) => {
|
|
266
|
+
const res = `Test email to: '${getStringifiedToAddress(message)}', Subject: '${message.subject}'`;
|
|
267
|
+
payload.logger.info({
|
|
268
|
+
content: message,
|
|
269
|
+
msg: res
|
|
270
|
+
});
|
|
271
|
+
return Promise.resolve();
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
function getAddress(to) {
|
|
275
|
+
if (typeof to === "string") return to;
|
|
276
|
+
if (to && typeof to === "object" && "address" in to && typeof to.address === "string") return to.address;
|
|
277
|
+
return "";
|
|
278
|
+
}
|
|
279
|
+
function getStringifiedToAddress(message) {
|
|
280
|
+
if (!message.to) return;
|
|
281
|
+
return Array.isArray(message.to) ? message.to.map(getAddress).join(", ") : getAddress(message.to) || void 0;
|
|
282
|
+
}
|
|
283
|
+
//#endregion
|
|
284
|
+
//#region src/payload/config.ts
|
|
285
|
+
function resolveDatabase(options) {
|
|
286
|
+
return options?.db || (process.env.BOM_TEST_DB === "memory" ? "memory" : "mongo");
|
|
287
|
+
}
|
|
288
|
+
const filename = fileURLToPath(import.meta.url);
|
|
289
|
+
const dirname = path.dirname(filename);
|
|
290
|
+
if (!process.env.ROOT_DIR) process.env.ROOT_DIR = dirname;
|
|
291
|
+
const buildConfigWithMemoryDB = async (config, options) => {
|
|
292
|
+
const memory = resolveDatabase(options) === "memory";
|
|
293
|
+
if (!memory && process.env.NODE_ENV === "test") {
|
|
294
|
+
const memoryDB = await MongoMemoryReplSet.create({ replSet: {
|
|
295
|
+
count: 3,
|
|
296
|
+
dbName: "payloadmemory"
|
|
297
|
+
} });
|
|
298
|
+
process.env.DATABASE_URL = `${memoryDB.getUri()}&retryWrites=true`;
|
|
299
|
+
}
|
|
300
|
+
return buildConfig({
|
|
301
|
+
...config,
|
|
302
|
+
admin: {
|
|
303
|
+
...config.admin,
|
|
304
|
+
importMap: { baseDir: path.resolve(dirname) }
|
|
305
|
+
},
|
|
306
|
+
db: memory ? memoryAdapter() : mongooseAdapter({
|
|
307
|
+
ensureIndexes: true,
|
|
308
|
+
url: process.env.DATABASE_URL || ""
|
|
309
|
+
}),
|
|
310
|
+
editor: memory ? config.editor || lexicalEditor() : slateEditor({}),
|
|
311
|
+
email: testEmailAdapter,
|
|
312
|
+
i18n: {
|
|
313
|
+
...config.i18n,
|
|
314
|
+
fallbackLanguage: "en"
|
|
315
|
+
},
|
|
316
|
+
localization: {
|
|
317
|
+
locales: ["en", "it"],
|
|
318
|
+
defaultLocale: "en",
|
|
319
|
+
fallback: true
|
|
320
|
+
},
|
|
321
|
+
maxDepth: 10,
|
|
322
|
+
onInit: async (payload) => {
|
|
323
|
+
await seed(payload);
|
|
324
|
+
},
|
|
325
|
+
serverURL: "http://localhost:3000",
|
|
326
|
+
secret: process.env.PAYLOAD_SECRET || "test-secret_key",
|
|
327
|
+
sharp,
|
|
328
|
+
typescript: {
|
|
329
|
+
declare: false,
|
|
330
|
+
outputFile: path.resolve(dirname, "payload-types.ts")
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
};
|
|
334
|
+
async function getConfig(config, options) {
|
|
335
|
+
return await buildConfigWithMemoryDB(config, options);
|
|
336
|
+
}
|
|
337
|
+
//#endregion
|
|
338
|
+
//#region src/payload/context.ts
|
|
339
|
+
let CONTEXT = void 0;
|
|
340
|
+
async function getContext(userConfig, options) {
|
|
341
|
+
if (CONTEXT) return CONTEXT;
|
|
342
|
+
const payload = await getPayload({ config: await getConfig(userConfig, options) });
|
|
343
|
+
const context = {
|
|
344
|
+
payload,
|
|
345
|
+
client: new RestClient(payload.config)
|
|
346
|
+
};
|
|
347
|
+
CONTEXT = context;
|
|
348
|
+
return context;
|
|
349
|
+
}
|
|
350
|
+
async function clearContext(context) {}
|
|
351
|
+
//#endregion
|
|
352
|
+
export { RestClient, clearContext, endUsers, getConfig, getContext, roles, seed, seedEndUsers, seedUsers, users };
|
|
353
|
+
|
|
354
|
+
//# sourceMappingURL=payload.js.map
|
|
@@ -0,0 +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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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import "@testing-library/jest-dom/vitest";
|
|
2
|
+
import { cleanup } from "@testing-library/react";
|
|
3
|
+
import { afterEach } from "vitest";
|
|
4
|
+
//#region src/exports/vitest-setup-dom.ts
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
cleanup();
|
|
7
|
+
});
|
|
8
|
+
//#endregion
|
|
9
|
+
export {};
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=vitest-setup-dom.js.map
|
|
@@ -0,0 +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\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"}
|