@salesforce/webapp-experimental 1.21.0 → 1.22.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/dist/api/clients.d.ts +1 -11
- package/dist/api/clients.d.ts.map +1 -1
- package/dist/api/clients.js +20 -53
- package/dist/api/clients.test.js +125 -200
- package/dist/api/graphql-operations-types.d.ts +238 -0
- package/dist/api/graphql-operations-types.d.ts.map +1 -0
- package/dist/api/graphql-operations-types.js +44 -0
- package/dist/api/graphql.d.ts +1 -11
- package/dist/api/graphql.d.ts.map +1 -1
- package/dist/api/graphql.js +6 -9
- package/dist/api/graphql.test.js +9 -23
- package/dist/api/index.d.ts +2 -3
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +1 -3
- package/dist/api/utils/user.d.ts.map +1 -1
- package/dist/api/utils/user.js +19 -7
- package/dist/api/utils/user.test.js +50 -102
- package/package.json +3 -3
- package/dist/api/apex.d.ts +0 -14
- package/dist/api/apex.d.ts.map +0 -1
- package/dist/api/apex.js +0 -23
- package/dist/api/apex.test.d.ts +0 -7
- package/dist/api/apex.test.d.ts.map +0 -1
- package/dist/api/apex.test.js +0 -66
package/dist/api/clients.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export declare const API_VERSION: string;
|
|
|
7
7
|
declare class ApiClient {
|
|
8
8
|
private readonly baseURL;
|
|
9
9
|
private readonly defaultOptions;
|
|
10
|
-
constructor(baseURL: string
|
|
10
|
+
constructor(baseURL: string);
|
|
11
11
|
private isJsonContentType;
|
|
12
12
|
private fetch;
|
|
13
13
|
private processBody;
|
|
@@ -17,16 +17,6 @@ declare class ApiClient {
|
|
|
17
17
|
patch(url: string, body?: unknown, options?: RequestInit): Promise<Response>;
|
|
18
18
|
delete(url: string, options?: RequestInit): Promise<Response>;
|
|
19
19
|
}
|
|
20
|
-
export declare const baseClient: ApiClient;
|
|
21
|
-
export declare const baseDataClient: ApiClient;
|
|
22
20
|
export declare const uiApiClient: ApiClient;
|
|
23
|
-
/**
|
|
24
|
-
* Creates an ApiClient with the provided base URL and default options.
|
|
25
|
-
*
|
|
26
|
-
* @param baseURL - The base URL for the client
|
|
27
|
-
* @param defaultOptions - Default RequestInit options
|
|
28
|
-
* @returns A configured ApiClient
|
|
29
|
-
*/
|
|
30
|
-
export declare function createClient(baseURL: string, defaultOptions?: RequestInit): ApiClient;
|
|
31
21
|
export {};
|
|
32
22
|
//# sourceMappingURL=clients.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../../src/api/clients.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../../src/api/clients.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,eAAO,MAAM,WAAW,QAA+B,CAAC;AAQxD,cAAM,SAAS;IACd,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAK7B;gBAEU,OAAO,EAAE,MAAM;IAI3B,OAAO,CAAC,iBAAiB;YASX,KAAK;IAenB,OAAO,CAAC,WAAW;IAgBb,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAQ/E,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAI9D,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAQ9E,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAQhF,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;CAGvE;AAGD,eAAO,MAAM,WAAW,WAA4B,CAAC"}
|
package/dist/api/clients.js
CHANGED
|
@@ -3,45 +3,31 @@
|
|
|
3
3
|
* All rights reserved.
|
|
4
4
|
* For full license text, see the LICENSE.txt file
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
7
|
-
const BASE_URL = __SF_SERVER_BASE_PATH__ || "";
|
|
6
|
+
import { sdk } from "@salesforce/sdk-data";
|
|
8
7
|
// Project standard API version from environment variable with fallback
|
|
9
8
|
export const API_VERSION = __SF_API_VERSION__ || "65.0";
|
|
10
|
-
const
|
|
11
|
-
const BASE_DATA_URL = `${BASE_SERVICES_URL}/data/v${API_VERSION}`;
|
|
9
|
+
const BASE_DATA_URL = `/services/data/v${API_VERSION}`;
|
|
12
10
|
const UI_API_URL = `${BASE_DATA_URL}/ui-api`;
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const CACHE_NAME = `vibe-coding-starter-${CACHE_VERSION}`;
|
|
16
|
-
ConduitClient.initialize({
|
|
17
|
-
csrf: {
|
|
18
|
-
endpoint: TOKEN_ENDPOINT,
|
|
19
|
-
cacheName: CACHE_NAME,
|
|
20
|
-
protectedUrls: ["/services/data/v", "/lwr/apex/v"],
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
const conduitClient = ConduitClient.instance();
|
|
11
|
+
const MIME_TYPE_JSON = "application/json";
|
|
12
|
+
const HEADER_CONTENT_TYPE = "Content-Type";
|
|
24
13
|
class ApiClient {
|
|
25
14
|
baseURL;
|
|
26
|
-
defaultOptions
|
|
27
|
-
|
|
15
|
+
defaultOptions = {
|
|
16
|
+
headers: {
|
|
17
|
+
[HEADER_CONTENT_TYPE]: MIME_TYPE_JSON,
|
|
18
|
+
Accept: MIME_TYPE_JSON,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
constructor(baseURL) {
|
|
28
22
|
this.baseURL = baseURL;
|
|
29
|
-
this.defaultOptions = {
|
|
30
|
-
...defaultOptions,
|
|
31
|
-
headers: {
|
|
32
|
-
"Content-Type": "application/json",
|
|
33
|
-
Accept: "application/json",
|
|
34
|
-
...(defaultOptions.headers || {}),
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
23
|
}
|
|
38
24
|
isJsonContentType(headers) {
|
|
39
25
|
// default to JSON if no headers specified
|
|
40
26
|
if (!headers)
|
|
41
27
|
return true;
|
|
42
28
|
const headersObj = new Headers(headers);
|
|
43
|
-
const contentType = headersObj.get(
|
|
44
|
-
return !contentType || contentType.includes(
|
|
29
|
+
const contentType = headersObj.get(HEADER_CONTENT_TYPE);
|
|
30
|
+
return !contentType || contentType.includes(MIME_TYPE_JSON);
|
|
45
31
|
}
|
|
46
32
|
async fetch(info, options = {}) {
|
|
47
33
|
const fullURL = info instanceof URL || info.startsWith("http") ? info : `${this.baseURL}${info}`;
|
|
@@ -53,12 +39,7 @@ class ApiClient {
|
|
|
53
39
|
...(options.headers || {}),
|
|
54
40
|
},
|
|
55
41
|
};
|
|
56
|
-
|
|
57
|
-
// handle 401/403 with page reload
|
|
58
|
-
if (response.status === 401 || response.status === 403) {
|
|
59
|
-
window.location.reload();
|
|
60
|
-
}
|
|
61
|
-
return response;
|
|
42
|
+
return await sdk.fetch(fullURL, mergedOptions);
|
|
62
43
|
}
|
|
63
44
|
processBody(body, options) {
|
|
64
45
|
if (body === undefined || body === null) {
|
|
@@ -77,45 +58,31 @@ class ApiClient {
|
|
|
77
58
|
}
|
|
78
59
|
async post(url, body, options = {}) {
|
|
79
60
|
return this.fetch(url, {
|
|
61
|
+
...options,
|
|
80
62
|
method: "POST",
|
|
81
63
|
body: this.processBody(body, options),
|
|
82
|
-
...options,
|
|
83
64
|
});
|
|
84
65
|
}
|
|
85
66
|
async get(url, options = {}) {
|
|
86
|
-
return this.fetch(url, { method: "GET"
|
|
67
|
+
return this.fetch(url, { ...options, method: "GET" });
|
|
87
68
|
}
|
|
88
69
|
async put(url, body, options = {}) {
|
|
89
70
|
return this.fetch(url, {
|
|
71
|
+
...options,
|
|
90
72
|
method: "PUT",
|
|
91
73
|
body: this.processBody(body, options),
|
|
92
|
-
...options,
|
|
93
74
|
});
|
|
94
75
|
}
|
|
95
76
|
async patch(url, body, options = {}) {
|
|
96
77
|
return this.fetch(url, {
|
|
78
|
+
...options,
|
|
97
79
|
method: "PATCH",
|
|
98
80
|
body: this.processBody(body, options),
|
|
99
|
-
...options,
|
|
100
81
|
});
|
|
101
82
|
}
|
|
102
83
|
async delete(url, options = {}) {
|
|
103
|
-
return this.fetch(url, { method: "DELETE"
|
|
84
|
+
return this.fetch(url, { ...options, method: "DELETE" });
|
|
104
85
|
}
|
|
105
86
|
}
|
|
106
|
-
// Base fetch client
|
|
107
|
-
export const baseClient = createClient(BASE_URL);
|
|
108
|
-
// Extension of the base client that by default points to this project's standard version of the Salesforce API
|
|
109
|
-
export const baseDataClient = createClient(BASE_DATA_URL);
|
|
110
87
|
// Client for Salesforce UI API access
|
|
111
|
-
export const uiApiClient =
|
|
112
|
-
/**
|
|
113
|
-
* Creates an ApiClient with the provided base URL and default options.
|
|
114
|
-
*
|
|
115
|
-
* @param baseURL - The base URL for the client
|
|
116
|
-
* @param defaultOptions - Default RequestInit options
|
|
117
|
-
* @returns A configured ApiClient
|
|
118
|
-
*/
|
|
119
|
-
export function createClient(baseURL, defaultOptions = {}) {
|
|
120
|
-
return new ApiClient(baseURL, defaultOptions);
|
|
121
|
-
}
|
|
88
|
+
export const uiApiClient = new ApiClient(UI_API_URL);
|
package/dist/api/clients.test.js
CHANGED
|
@@ -3,18 +3,17 @@
|
|
|
3
3
|
* All rights reserved.
|
|
4
4
|
* For full license text, see the LICENSE.txt file
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
|
-
import { ConduitClient } from "@conduit-client/salesforce-lightning-service-worker";
|
|
6
|
+
import { sdk } from "@salesforce/sdk-data";
|
|
8
7
|
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
9
|
-
import {
|
|
10
|
-
vi.mock("@
|
|
8
|
+
import { uiApiClient } from "./clients.js";
|
|
9
|
+
vi.mock("@salesforce/sdk-data", () => {
|
|
11
10
|
return {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
instance: vi.fn().mockReturnValue({ fetch: vi.fn() }),
|
|
11
|
+
sdk: {
|
|
12
|
+
fetch: vi.fn(),
|
|
15
13
|
},
|
|
16
14
|
};
|
|
17
15
|
});
|
|
16
|
+
vi.stubGlobal("window", {});
|
|
18
17
|
// Mock window.location.reload
|
|
19
18
|
const mockReload = vi.fn();
|
|
20
19
|
Object.defineProperty(window, "location", {
|
|
@@ -24,219 +23,145 @@ Object.defineProperty(window, "location", {
|
|
|
24
23
|
describe("clients", () => {
|
|
25
24
|
let mockFetch;
|
|
26
25
|
beforeEach(() => {
|
|
27
|
-
|
|
28
|
-
mockFetch = mockClient.fetch;
|
|
26
|
+
mockFetch = vi.mocked(sdk.fetch);
|
|
29
27
|
mockFetch.mockClear();
|
|
30
28
|
mockReload.mockClear();
|
|
31
29
|
});
|
|
32
30
|
afterEach(() => {
|
|
33
31
|
vi.clearAllMocks();
|
|
34
32
|
});
|
|
35
|
-
|
|
36
|
-
expect(ConduitClient.initialize).toHaveBeenCalledWith({
|
|
37
|
-
csrf: {
|
|
38
|
-
endpoint: "/services/data/v99.0/ui-api/session/csrf",
|
|
39
|
-
cacheName: "vibe-coding-starter-1",
|
|
40
|
-
protectedUrls: ["/services/data/v", "/lwr/apex/v"],
|
|
41
|
-
},
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
describe("constructor and default options", () => {
|
|
45
|
-
it("should create client with default JSON headers", () => {
|
|
46
|
-
const client = createClient("/api");
|
|
47
|
-
expect(client).toBeDefined();
|
|
48
|
-
});
|
|
33
|
+
describe("uiApiClient", () => {
|
|
49
34
|
it("should merge custom headers with defaults", async () => {
|
|
50
|
-
const client = createClient("/api", {
|
|
51
|
-
headers: { "Custom-Header": "value" },
|
|
52
|
-
});
|
|
53
35
|
mockFetch.mockResolvedValueOnce({
|
|
54
36
|
status: 200,
|
|
55
37
|
json: () => Promise.resolve({ success: true }),
|
|
56
38
|
});
|
|
57
|
-
await
|
|
58
|
-
|
|
59
|
-
method: "GET",
|
|
60
|
-
headers: {
|
|
61
|
-
"Content-Type": "application/json",
|
|
62
|
-
Accept: "application/json",
|
|
63
|
-
"Custom-Header": "value",
|
|
64
|
-
},
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
describe("URL construction", () => {
|
|
69
|
-
it("should combine base URL with relative paths", async () => {
|
|
70
|
-
const client = createClient("/api/v1");
|
|
71
|
-
mockFetch.mockResolvedValueOnce({
|
|
72
|
-
status: 200,
|
|
73
|
-
json: () => Promise.resolve({}),
|
|
74
|
-
});
|
|
75
|
-
await client.get("/users");
|
|
76
|
-
expect(mockFetch).toHaveBeenCalledWith("/api/v1/users", expect.any(Object));
|
|
77
|
-
});
|
|
78
|
-
it("should use absolute URLs as-is", async () => {
|
|
79
|
-
const client = createClient("/api");
|
|
80
|
-
mockFetch.mockResolvedValueOnce({
|
|
81
|
-
status: 200,
|
|
82
|
-
json: () => Promise.resolve({}),
|
|
83
|
-
});
|
|
84
|
-
await client.get("https://external.com/data");
|
|
85
|
-
expect(mockFetch).toHaveBeenCalledWith("https://external.com/data", expect.any(Object));
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
describe("HTTP methods", () => {
|
|
89
|
-
let client;
|
|
90
|
-
beforeEach(() => {
|
|
91
|
-
client = createClient("/api");
|
|
92
|
-
mockFetch.mockResolvedValue({
|
|
93
|
-
status: 200,
|
|
94
|
-
json: () => Promise.resolve({ success: true }),
|
|
39
|
+
await uiApiClient.get("/test", {
|
|
40
|
+
headers: { "Custom-Header": "value" },
|
|
95
41
|
});
|
|
96
|
-
|
|
97
|
-
it("should make GET requests", async () => {
|
|
98
|
-
await client.get("/users");
|
|
99
|
-
expect(mockFetch).toHaveBeenCalledWith("/api/users", {
|
|
42
|
+
expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/ui-api/test", {
|
|
100
43
|
method: "GET",
|
|
101
44
|
headers: {
|
|
102
45
|
"Content-Type": "application/json",
|
|
103
46
|
Accept: "application/json",
|
|
47
|
+
"Custom-Header": "value",
|
|
104
48
|
},
|
|
105
49
|
});
|
|
106
50
|
});
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
it("should export baseClient with correct base URL", () => {
|
|
221
|
-
expect(baseClient).toBeDefined();
|
|
222
|
-
});
|
|
223
|
-
it("should export baseDataClient with correct base URL", () => {
|
|
224
|
-
expect(baseDataClient).toBeDefined();
|
|
225
|
-
});
|
|
226
|
-
it("should export uiApiClient with correct base URL", () => {
|
|
227
|
-
expect(uiApiClient).toBeDefined();
|
|
228
|
-
});
|
|
229
|
-
});
|
|
230
|
-
describe("createClient factory", () => {
|
|
231
|
-
it("should create client with provided base URL", () => {
|
|
232
|
-
const client = createClient("/custom");
|
|
233
|
-
expect(client).toBeDefined();
|
|
234
|
-
});
|
|
235
|
-
it("should create client with default options", () => {
|
|
236
|
-
const client = createClient("/api", {
|
|
237
|
-
headers: { Authorization: "Bearer token" },
|
|
51
|
+
describe("URL construction", () => {
|
|
52
|
+
it("should combine base URL with relative paths", async () => {
|
|
53
|
+
mockFetch.mockResolvedValueOnce({
|
|
54
|
+
status: 200,
|
|
55
|
+
json: () => Promise.resolve({}),
|
|
56
|
+
});
|
|
57
|
+
await uiApiClient.get("/users");
|
|
58
|
+
expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/ui-api/users", expect.any(Object));
|
|
59
|
+
});
|
|
60
|
+
it("should use absolute URLs as-is", async () => {
|
|
61
|
+
mockFetch.mockResolvedValueOnce({
|
|
62
|
+
status: 200,
|
|
63
|
+
json: () => Promise.resolve({}),
|
|
64
|
+
});
|
|
65
|
+
await uiApiClient.get("https://external.com/data");
|
|
66
|
+
expect(mockFetch).toHaveBeenCalledWith("https://external.com/data", expect.any(Object));
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
describe("HTTP methods", () => {
|
|
70
|
+
beforeEach(() => {
|
|
71
|
+
mockFetch.mockResolvedValue({
|
|
72
|
+
status: 200,
|
|
73
|
+
json: () => Promise.resolve({ success: true }),
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
it("should make GET requests", async () => {
|
|
77
|
+
await uiApiClient.get("/users");
|
|
78
|
+
expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/ui-api/users", {
|
|
79
|
+
method: "GET",
|
|
80
|
+
headers: {
|
|
81
|
+
"Content-Type": "application/json",
|
|
82
|
+
Accept: "application/json",
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
it("should make POST requests with JSON body", async () => {
|
|
87
|
+
const data = { name: "John" };
|
|
88
|
+
await uiApiClient.post("/users", data);
|
|
89
|
+
expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/ui-api/users", {
|
|
90
|
+
method: "POST",
|
|
91
|
+
body: JSON.stringify(data),
|
|
92
|
+
headers: {
|
|
93
|
+
"Content-Type": "application/json",
|
|
94
|
+
Accept: "application/json",
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
it("should make PUT requests with JSON body", async () => {
|
|
99
|
+
const data = { name: "John Updated" };
|
|
100
|
+
await uiApiClient.put("/users/1", data);
|
|
101
|
+
expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/ui-api/users/1", {
|
|
102
|
+
method: "PUT",
|
|
103
|
+
body: JSON.stringify(data),
|
|
104
|
+
headers: {
|
|
105
|
+
"Content-Type": "application/json",
|
|
106
|
+
Accept: "application/json",
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
it("should make PATCH requests with JSON body", async () => {
|
|
111
|
+
const data = { name: "John Patched" };
|
|
112
|
+
await uiApiClient.patch("/users/1", data);
|
|
113
|
+
expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/ui-api/users/1", {
|
|
114
|
+
method: "PATCH",
|
|
115
|
+
body: JSON.stringify(data),
|
|
116
|
+
headers: {
|
|
117
|
+
"Content-Type": "application/json",
|
|
118
|
+
Accept: "application/json",
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
it("should make DELETE requests", async () => {
|
|
123
|
+
await uiApiClient.delete("/users/1");
|
|
124
|
+
expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/ui-api/users/1", {
|
|
125
|
+
method: "DELETE",
|
|
126
|
+
headers: {
|
|
127
|
+
"Content-Type": "application/json",
|
|
128
|
+
Accept: "application/json",
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
describe("body processing", () => {
|
|
134
|
+
beforeEach(() => {
|
|
135
|
+
mockFetch.mockResolvedValue({
|
|
136
|
+
status: 200,
|
|
137
|
+
json: () => Promise.resolve({}),
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
it("should stringify object bodies for JSON content-type", async () => {
|
|
141
|
+
const data = { name: "John" };
|
|
142
|
+
await uiApiClient.post("/users", data);
|
|
143
|
+
expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/ui-api/users", expect.objectContaining({
|
|
144
|
+
body: JSON.stringify(data),
|
|
145
|
+
}));
|
|
146
|
+
});
|
|
147
|
+
it("should not stringify non-object bodies", async () => {
|
|
148
|
+
const formData = new FormData();
|
|
149
|
+
await uiApiClient.post("/upload", formData);
|
|
150
|
+
expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/ui-api/upload", expect.objectContaining({
|
|
151
|
+
body: formData,
|
|
152
|
+
}));
|
|
153
|
+
});
|
|
154
|
+
it("should not stringify when content-type is not JSON", async () => {
|
|
155
|
+
const data = { name: "John" };
|
|
156
|
+
await uiApiClient.post("/users", data, {
|
|
157
|
+
headers: { "Content-Type": "multipart/form-data" },
|
|
158
|
+
});
|
|
159
|
+
// When content-type is not JSON and body is a plain object (not FormData/string),
|
|
160
|
+
// processBody returns undefined since it can't serialize non-JSON content
|
|
161
|
+
expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/ui-api/users", expect.objectContaining({
|
|
162
|
+
body: undefined,
|
|
163
|
+
}));
|
|
238
164
|
});
|
|
239
|
-
expect(client).toBeDefined();
|
|
240
165
|
});
|
|
241
166
|
});
|
|
242
167
|
});
|