@amalaika/form-sdk-package 1.0.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.
Files changed (75) hide show
  1. package/README.md +342 -0
  2. package/dist/cjs/client/__tests__/client.spec.d.ts +2 -0
  3. package/dist/cjs/client/__tests__/client.spec.d.ts.map +1 -0
  4. package/dist/cjs/client/__tests__/client.spec.js +300 -0
  5. package/dist/cjs/client/__tests__/client.spec.js.map +1 -0
  6. package/dist/cjs/client/index.d.ts +26 -0
  7. package/dist/cjs/client/index.d.ts.map +1 -0
  8. package/dist/cjs/client/index.js +179 -0
  9. package/dist/cjs/client/index.js.map +1 -0
  10. package/dist/cjs/client.d.ts +22 -0
  11. package/dist/cjs/client.d.ts.map +1 -0
  12. package/dist/cjs/client.js +111 -0
  13. package/dist/cjs/client.js.map +1 -0
  14. package/dist/cjs/index.d.ts +4 -0
  15. package/dist/cjs/index.d.ts.map +1 -0
  16. package/dist/cjs/index.js +10 -0
  17. package/dist/cjs/index.js.map +1 -0
  18. package/dist/cjs/package.json +1 -0
  19. package/dist/cjs/types/index.d.ts +91 -0
  20. package/dist/cjs/types/index.d.ts.map +1 -0
  21. package/dist/cjs/types/index.js +3 -0
  22. package/dist/cjs/types/index.js.map +1 -0
  23. package/dist/cjs/types.d.ts +78 -0
  24. package/dist/cjs/types.d.ts.map +1 -0
  25. package/dist/cjs/types.js +3 -0
  26. package/dist/cjs/types.js.map +1 -0
  27. package/dist/cjs/utils/__tests__/utils.spec.d.ts +2 -0
  28. package/dist/cjs/utils/__tests__/utils.spec.d.ts.map +1 -0
  29. package/dist/cjs/utils/__tests__/utils.spec.js +172 -0
  30. package/dist/cjs/utils/__tests__/utils.spec.js.map +1 -0
  31. package/dist/cjs/utils/index.d.ts +5 -0
  32. package/dist/cjs/utils/index.d.ts.map +1 -0
  33. package/dist/cjs/utils/index.js +45 -0
  34. package/dist/cjs/utils/index.js.map +1 -0
  35. package/dist/cjs/utils.d.ts +5 -0
  36. package/dist/cjs/utils.d.ts.map +1 -0
  37. package/dist/cjs/utils.js +45 -0
  38. package/dist/cjs/utils.js.map +1 -0
  39. package/dist/esm/client/__tests__/client.spec.d.ts +2 -0
  40. package/dist/esm/client/__tests__/client.spec.d.ts.map +1 -0
  41. package/dist/esm/client/__tests__/client.spec.js +355 -0
  42. package/dist/esm/client/__tests__/client.spec.js.map +1 -0
  43. package/dist/esm/client/index.d.ts +26 -0
  44. package/dist/esm/client/index.d.ts.map +1 -0
  45. package/dist/esm/client/index.js +175 -0
  46. package/dist/esm/client/index.js.map +1 -0
  47. package/dist/esm/client.d.ts +22 -0
  48. package/dist/esm/client.d.ts.map +1 -0
  49. package/dist/esm/client.js +107 -0
  50. package/dist/esm/client.js.map +1 -0
  51. package/dist/esm/index.d.ts +4 -0
  52. package/dist/esm/index.d.ts.map +1 -0
  53. package/dist/esm/index.js +3 -0
  54. package/dist/esm/index.js.map +1 -0
  55. package/dist/esm/types/index.d.ts +91 -0
  56. package/dist/esm/types/index.d.ts.map +1 -0
  57. package/dist/esm/types/index.js +2 -0
  58. package/dist/esm/types/index.js.map +1 -0
  59. package/dist/esm/types.d.ts +78 -0
  60. package/dist/esm/types.d.ts.map +1 -0
  61. package/dist/esm/types.js +2 -0
  62. package/dist/esm/types.js.map +1 -0
  63. package/dist/esm/utils/__tests__/utils.spec.d.ts +2 -0
  64. package/dist/esm/utils/__tests__/utils.spec.d.ts.map +1 -0
  65. package/dist/esm/utils/__tests__/utils.spec.js +182 -0
  66. package/dist/esm/utils/__tests__/utils.spec.js.map +1 -0
  67. package/dist/esm/utils/index.d.ts +5 -0
  68. package/dist/esm/utils/index.d.ts.map +1 -0
  69. package/dist/esm/utils/index.js +40 -0
  70. package/dist/esm/utils/index.js.map +1 -0
  71. package/dist/esm/utils.d.ts +5 -0
  72. package/dist/esm/utils.d.ts.map +1 -0
  73. package/dist/esm/utils.js +40 -0
  74. package/dist/esm/utils.js.map +1 -0
  75. package/package.json +54 -0
package/README.md ADDED
@@ -0,0 +1,342 @@
1
+ # @amalaika/form-sdk-package
2
+
3
+ Framework-agnostic SDK for integrating the event registration form system. Handles data fetching, conditional visibility, file uploads, and form submission — no UI rendering included.
4
+
5
+ Works with React, Vue, Angular, Svelte, vanilla JS, or any environment with the Fetch API.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @amalaika/form-sdk-package
11
+ ```
12
+
13
+ For local development (monorepo):
14
+
15
+ ```json
16
+ {
17
+ "dependencies": {
18
+ "@amalaika/form-sdk-package": "file:../form-sdk-package"
19
+ }
20
+ }
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ```ts
26
+ import { EventFormClient, getAllFields, isFieldVisible } from "@amalaika/form-sdk-package";
27
+
28
+ const client = new EventFormClient({
29
+ apiKey: "Am_550e8400-e29b-41d4-a716-446655440000",
30
+ resourceType: "ticketing",
31
+ locale: "en", // default locale for all requests
32
+ });
33
+
34
+ // All calls automatically use "en" — no locale param needed
35
+ const tickets = await client.fetchTickets();
36
+ const form = await client.fetchForm(tickets[0].id);
37
+ const fields = getAllFields(form.schema);
38
+
39
+ // Switch language without reinstantiating
40
+ client.setLocale("fr");
41
+ const ticketsFr = await client.fetchTickets(); // now uses "fr"
42
+ ```
43
+
44
+ ## API Reference
45
+
46
+ ### Constructor
47
+
48
+ ```ts
49
+ const client = new EventFormClient(config: EventFormConfig);
50
+ ```
51
+
52
+ | Parameter | Type | Required | Description |
53
+ |-----------|------|----------|-------------|
54
+ | `apiKey` | `string` | Yes | Event API key (e.g. `"Am_550e8400-..."`) |
55
+ | `resourceType` | `"ticketing" \| "accommodation" \| "exhibition"` | Yes | Resource type for submissions |
56
+ | `apiBaseUrl` | `string` | No | API base URL. Defaults to `"https://api.eventsfactory.rw/api"` |
57
+ | `locale` | `string` | No | Default locale for all requests. Can be changed later via `setLocale()` |
58
+ | `errorMessages` | `Partial<ErrorMessages>` | No | Custom error messages — override any or all defaults |
59
+
60
+ ### Locale Management
61
+
62
+ Set a default locale on the constructor so you don't have to pass it on every method call:
63
+
64
+ ```ts
65
+ const client = new EventFormClient({
66
+ apiKey: "Am_550e8400-...",
67
+ resourceType: "ticketing",
68
+ locale: "fr",
69
+ });
70
+
71
+ // All calls automatically use "fr" — no need to pass locale
72
+ const tickets = await client.fetchTickets();
73
+ const form = await client.fetchForm(tickets[0].id);
74
+ ```
75
+
76
+ Switch locale at any time without reinstantiating:
77
+
78
+ ```ts
79
+ client.setLocale("en");
80
+ // All subsequent calls now use "en"
81
+ ```
82
+
83
+ Read the current locale:
84
+
85
+ ```ts
86
+ client.getLocale(); // "en"
87
+ ```
88
+
89
+ Per-call locale still overrides the default when needed:
90
+
91
+ ```ts
92
+ // Uses "de" for this call only, default remains "en"
93
+ const tickets = await client.fetchTickets({ locale: "de" });
94
+ ```
95
+
96
+ ### Methods
97
+
98
+ #### `client.fetchTickets(options?)`
99
+
100
+ Fetch all published tickets for the event.
101
+
102
+ ```ts
103
+ const tickets = await client.fetchTickets({ locale: "fr", name: "VIP" });
104
+ ```
105
+
106
+ | Option | Type | Description |
107
+ |--------|------|-------------|
108
+ | `locale` | `string` | Locale code for translations (also sent as `Accept-Language`) |
109
+ | `name` | `string` | Filter tickets by name |
110
+
111
+ Returns `Promise<Ticket[]>`.
112
+
113
+ ---
114
+
115
+ #### `client.fetchTicketById(id, locale?)`
116
+
117
+ Fetch a single ticket by ID.
118
+
119
+ ```ts
120
+ const ticket = await client.fetchTicketById(42, "en");
121
+ ```
122
+
123
+ Returns `Promise<Ticket>`.
124
+
125
+ ---
126
+
127
+ #### `client.fetchLanguages()`
128
+
129
+ Fetch available languages for the event. Returns codes sorted with the default language first.
130
+
131
+ ```ts
132
+ const languages = await client.fetchLanguages();
133
+ // ["en", "fr", "ar"]
134
+ ```
135
+
136
+ Returns `Promise<string[]>`.
137
+
138
+ ---
139
+
140
+ #### `client.fetchForm(ticketId, locale?)`
141
+
142
+ Fetch the form linked to a ticket.
143
+
144
+ ```ts
145
+ const form = await client.fetchForm(1, "fr");
146
+ ```
147
+
148
+ Returns `Promise<FormData>`. The `form.schema` contains the field definitions used to render the form.
149
+
150
+ ---
151
+
152
+ #### `client.authorizeUpload(formId, fieldId, file, locale?)`
153
+
154
+ Step 1 of file upload — request an upload token.
155
+
156
+ ```ts
157
+ const token = await client.authorizeUpload(form.id, "resume", file);
158
+ ```
159
+
160
+ Returns `Promise<string>` (the upload token).
161
+
162
+ ---
163
+
164
+ #### `client.uploadFile(formId, token, file, locale?)`
165
+
166
+ Step 2 of file upload — upload the file using the token.
167
+
168
+ ```ts
169
+ const fileUrl = await client.uploadFile(form.id, token, file);
170
+ ```
171
+
172
+ Returns `Promise<string>` (the uploaded file URL to include in submission data).
173
+
174
+ ---
175
+
176
+ #### `client.submitForm(formId, data, context)`
177
+
178
+ Submit form data.
179
+
180
+ ```ts
181
+ await client.submitForm(form.id, submissionData, {
182
+ eventId: form.eventId,
183
+ ticketId: 1,
184
+ locale: "en",
185
+ });
186
+ ```
187
+
188
+ | Context Field | Type | Required | Description |
189
+ |---------------|------|----------|-------------|
190
+ | `eventId` | `number` | Yes | Event ID (from `form.eventId`) |
191
+ | `ticketId` | `number` | Yes | Ticket ID used to fetch the form |
192
+ | `locale` | `string` | No | Locale for `Accept-Language` header |
193
+
194
+ The `resourceType` is automatically sent from the constructor config.
195
+
196
+ Returns `Promise<void>`.
197
+
198
+ ### Utility Functions
199
+
200
+ Pure functions for working with form schemas and conditional visibility. Import directly:
201
+
202
+ ```ts
203
+ import { getAllFields, isFieldVisible, getVisibleFieldIds } from "@amalaika/form-sdk-package";
204
+ ```
205
+
206
+ #### `getAllFields(schema)`
207
+
208
+ Extracts all fields from a `FormSchema`, whether flat or stepped.
209
+
210
+ ```ts
211
+ const fields = getAllFields(form.schema);
212
+ ```
213
+
214
+ Returns `FieldDefinition[]`.
215
+
216
+ ---
217
+
218
+ #### `isFieldVisible(field, formValues, allFields)`
219
+
220
+ Checks whether a field should be visible based on the current form values. Supports cascading visibility (if a parent field is hidden, its dependents are too).
221
+
222
+ ```ts
223
+ if (isFieldVisible(field, currentValues, allFields)) {
224
+ // render this field
225
+ }
226
+ ```
227
+
228
+ Returns `boolean`.
229
+
230
+ **Supported operators:**
231
+
232
+ | Operator | Visible when |
233
+ |----------|-------------|
234
+ | `equals` | `formValues[dependsOn] === value` |
235
+ | `not_equals` | `formValues[dependsOn] !== value` |
236
+ | `in` | Any overlap between selected values and target values |
237
+
238
+ ---
239
+
240
+ #### `getVisibleFieldIds(allFields, formValues)`
241
+
242
+ Returns the set of field IDs that are currently visible. Use this to filter submission data — only submit visible fields.
243
+
244
+ ```ts
245
+ const visibleIds = getVisibleFieldIds(allFields, formValues);
246
+
247
+ const submissionData = {};
248
+ for (const [key, val] of Object.entries(formValues)) {
249
+ if (visibleIds.has(key)) submissionData[key] = val;
250
+ }
251
+ ```
252
+
253
+ Returns `Set<string>`.
254
+
255
+ ## Full Example
256
+
257
+ ```ts
258
+ import {
259
+ EventFormClient,
260
+ getAllFields,
261
+ getVisibleFieldIds,
262
+ } from "@amalaika/form-sdk-package";
263
+
264
+ const client = new EventFormClient({
265
+ apiKey: "Am_550e8400-e29b-41d4-a716-446655440000",
266
+ resourceType: "ticketing",
267
+ locale: "en",
268
+ });
269
+
270
+ // 1. Fetch tickets and pick one (uses default locale "en")
271
+ const tickets = await client.fetchTickets();
272
+ const ticket = tickets[0];
273
+
274
+ // 2. Fetch the form (uses default locale "en")
275
+ const form = await client.fetchForm(ticket.id);
276
+ const allFields = getAllFields(form.schema);
277
+
278
+ // 3. Collect user input into formValues (your UI handles this)
279
+ const formValues: Record<string, unknown> = {
280
+ first_name: "Jane",
281
+ last_name: "Doe",
282
+ email: "jane@example.com",
283
+ role: "speaker",
284
+ talk_title: "Building Dynamic Forms",
285
+ };
286
+
287
+ // 4. Filter to visible fields only
288
+ const visibleIds = getVisibleFieldIds(allFields, formValues);
289
+ const submissionData: Record<string, unknown> = {};
290
+ for (const [key, val] of Object.entries(formValues)) {
291
+ if (visibleIds.has(key)) submissionData[key] = val;
292
+ }
293
+
294
+ // 5. Handle file uploads (if any)
295
+ const resumeFile = new File(["..."], "resume.pdf", { type: "application/pdf" });
296
+ const token = await client.authorizeUpload(form.id, "resume", resumeFile);
297
+ const fileUrl = await client.uploadFile(form.id, token, resumeFile);
298
+ submissionData["resume"] = fileUrl;
299
+
300
+ // 6. Submit (locale comes from constructor default)
301
+ await client.submitForm(form.id, submissionData, {
302
+ eventId: form.eventId!,
303
+ ticketId: ticket.id,
304
+ });
305
+ ```
306
+
307
+ ## Exported Types
308
+
309
+ ```ts
310
+ import type {
311
+ ErrorMessages,
312
+ EventFormConfig,
313
+ FieldOption,
314
+ FieldDefinition,
315
+ StepDefinition,
316
+ FormSchema,
317
+ FormData,
318
+ ApiResponse,
319
+ TicketTranslation,
320
+ Ticket,
321
+ } from "@amalaika/form-sdk-package";
322
+ ```
323
+
324
+ ## Development
325
+
326
+ ```bash
327
+ # Install dependencies
328
+ npm install
329
+
330
+ # Build (ESM + CJS)
331
+ npm run build
332
+
333
+ # Run tests
334
+ npm test
335
+
336
+ # Lint
337
+ npm run lint
338
+ ```
339
+
340
+ ## License
341
+
342
+ MIT
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=client.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.spec.d.ts","sourceRoot":"","sources":["../../../../src/client/__tests__/client.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,300 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const __1 = require("..");
4
+ // ---------------------------------------------------------------------------
5
+ // Fetch mock helpers
6
+ // ---------------------------------------------------------------------------
7
+ const mockFetch = jest.fn();
8
+ global.fetch = mockFetch;
9
+ function jsonResponse(data, status = 200) {
10
+ const body = { statusCode: status, message: "OK", data };
11
+ return {
12
+ ok: status >= 200 && status < 300,
13
+ status,
14
+ json: () => Promise.resolve(body),
15
+ };
16
+ }
17
+ function errorResponse(message, status = 400) {
18
+ return {
19
+ ok: false,
20
+ status,
21
+ json: () => Promise.resolve({ statusCode: status, message }),
22
+ };
23
+ }
24
+ // ---------------------------------------------------------------------------
25
+ // Fixtures
26
+ // ---------------------------------------------------------------------------
27
+ const API_BASE = "https://test.api/api";
28
+ const API_KEY = "Am_test-key";
29
+ function createClient() {
30
+ return new __1.EventFormClient({
31
+ apiKey: API_KEY,
32
+ resourceType: "ticketing",
33
+ apiBaseUrl: API_BASE,
34
+ });
35
+ }
36
+ const sampleTicket = {
37
+ id: 1,
38
+ eventId: 10,
39
+ price: "50.00",
40
+ currency: "USD",
41
+ attendanceType: "PHYSICAL",
42
+ virtualPrice: null,
43
+ physicalPrice: null,
44
+ quantityTotal: 200,
45
+ salesStartAt: null,
46
+ salesEndAt: null,
47
+ discountPercentage: null,
48
+ discountEndAt: null,
49
+ isActive: true,
50
+ createdBy: 1,
51
+ name: "General Admission",
52
+ };
53
+ const sampleForm = {
54
+ id: 6,
55
+ title: "Registration",
56
+ description: null,
57
+ eventId: 10,
58
+ schema: {
59
+ fields: [
60
+ { id: "first_name", type: "text", required: true },
61
+ { id: "email", type: "email", required: true },
62
+ ],
63
+ },
64
+ };
65
+ // ---------------------------------------------------------------------------
66
+ // Tests
67
+ // ---------------------------------------------------------------------------
68
+ beforeEach(() => {
69
+ mockFetch.mockReset();
70
+ });
71
+ describe("EventFormClient", () => {
72
+ describe("constructor", () => {
73
+ it("uses default API base when none provided", () => {
74
+ const client = new __1.EventFormClient({
75
+ apiKey: API_KEY,
76
+ resourceType: "ticketing",
77
+ });
78
+ mockFetch.mockResolvedValueOnce(jsonResponse([sampleTicket]));
79
+ client.fetchTickets();
80
+ expect(mockFetch).toHaveBeenCalledWith(expect.stringContaining("https://api.eventsfactory.rw/api/"), expect.anything());
81
+ });
82
+ it("strips trailing slash from custom API base", () => {
83
+ const client = new __1.EventFormClient({
84
+ apiKey: API_KEY,
85
+ resourceType: "ticketing",
86
+ apiBaseUrl: "https://custom.api/api/",
87
+ });
88
+ mockFetch.mockResolvedValueOnce(jsonResponse([sampleTicket]));
89
+ client.fetchTickets();
90
+ expect(mockFetch).toHaveBeenCalledWith(expect.stringContaining("https://custom.api/api/events/"), expect.anything());
91
+ });
92
+ });
93
+ // -------------------------------------------------------------------------
94
+ // fetchTickets
95
+ // -------------------------------------------------------------------------
96
+ describe("fetchTickets", () => {
97
+ it("calls the correct endpoint with API key", async () => {
98
+ mockFetch.mockResolvedValueOnce(jsonResponse([sampleTicket]));
99
+ const client = createClient();
100
+ const tickets = await client.fetchTickets();
101
+ expect(mockFetch).toHaveBeenCalledWith(expect.stringContaining(`/events/tickets/event/${API_KEY}/public`), expect.objectContaining({ headers: {} }));
102
+ expect(tickets).toEqual([sampleTicket]);
103
+ });
104
+ it("passes locale as query param and Accept-Language header", async () => {
105
+ mockFetch.mockResolvedValueOnce(jsonResponse([sampleTicket]));
106
+ const client = createClient();
107
+ await client.fetchTickets({ locale: "fr" });
108
+ const [url, opts] = mockFetch.mock.calls[0];
109
+ expect(url).toContain("locale=fr");
110
+ expect(opts.headers).toEqual({ "Accept-Language": "fr" });
111
+ });
112
+ it("passes name as query param", async () => {
113
+ mockFetch.mockResolvedValueOnce(jsonResponse([sampleTicket]));
114
+ const client = createClient();
115
+ await client.fetchTickets({ name: "VIP" });
116
+ const [url] = mockFetch.mock.calls[0];
117
+ expect(url).toContain("name=VIP");
118
+ });
119
+ it("throws on non-OK response", async () => {
120
+ mockFetch.mockResolvedValueOnce(errorResponse("Not found", 404));
121
+ const client = createClient();
122
+ await expect(client.fetchTickets()).rejects.toThrow("Failed to fetch tickets (404)");
123
+ });
124
+ });
125
+ // -------------------------------------------------------------------------
126
+ // fetchTicketById
127
+ // -------------------------------------------------------------------------
128
+ describe("fetchTicketById", () => {
129
+ it("calls the correct endpoint", async () => {
130
+ mockFetch.mockResolvedValueOnce(jsonResponse(sampleTicket));
131
+ const client = createClient();
132
+ const ticket = await client.fetchTicketById(1);
133
+ expect(mockFetch).toHaveBeenCalledWith(`${API_BASE}/events/tickets/1`, expect.objectContaining({ headers: {} }));
134
+ expect(ticket).toEqual(sampleTicket);
135
+ });
136
+ it("sends Accept-Language header when locale is provided", async () => {
137
+ mockFetch.mockResolvedValueOnce(jsonResponse(sampleTicket));
138
+ const client = createClient();
139
+ await client.fetchTicketById(1, "en");
140
+ const [, opts] = mockFetch.mock.calls[0];
141
+ expect(opts.headers).toEqual({ "Accept-Language": "en" });
142
+ });
143
+ it("throws on non-OK response", async () => {
144
+ mockFetch.mockResolvedValueOnce(errorResponse("Not found", 404));
145
+ const client = createClient();
146
+ await expect(client.fetchTicketById(999)).rejects.toThrow("Ticket not found (404)");
147
+ });
148
+ });
149
+ // -------------------------------------------------------------------------
150
+ // fetchLanguages
151
+ // -------------------------------------------------------------------------
152
+ describe("fetchLanguages", () => {
153
+ it("returns sorted language codes with default first", async () => {
154
+ mockFetch.mockResolvedValueOnce(jsonResponse([
155
+ { id: 2, languageCode: "fr", isDefault: false },
156
+ { id: 1, languageCode: "en", isDefault: true },
157
+ ]));
158
+ const client = createClient();
159
+ const langs = await client.fetchLanguages();
160
+ expect(langs).toEqual(["en", "fr"]);
161
+ expect(mockFetch).toHaveBeenCalledWith(`${API_BASE}/events/onboarding/main-info/${API_KEY}/languages`);
162
+ });
163
+ it("throws on non-OK response", async () => {
164
+ mockFetch.mockResolvedValueOnce(errorResponse("Not found", 404));
165
+ const client = createClient();
166
+ await expect(client.fetchLanguages()).rejects.toThrow("Failed to fetch languages (404)");
167
+ });
168
+ });
169
+ // -------------------------------------------------------------------------
170
+ // fetchForm
171
+ // -------------------------------------------------------------------------
172
+ describe("fetchForm", () => {
173
+ it("calls the correct endpoint and returns form data", async () => {
174
+ mockFetch.mockResolvedValueOnce(jsonResponse(sampleForm));
175
+ const client = createClient();
176
+ const form = await client.fetchForm(1);
177
+ expect(mockFetch).toHaveBeenCalledWith(`${API_BASE}/application/forms/ticketing/1/public`, expect.objectContaining({ headers: {} }));
178
+ expect(form).toEqual(sampleForm);
179
+ });
180
+ it("sends Accept-Language when locale provided", async () => {
181
+ mockFetch.mockResolvedValueOnce(jsonResponse(sampleForm));
182
+ const client = createClient();
183
+ await client.fetchForm(1, "fr");
184
+ const [, opts] = mockFetch.mock.calls[0];
185
+ expect(opts.headers).toEqual({ "Accept-Language": "fr" });
186
+ });
187
+ it("throws on non-OK response", async () => {
188
+ mockFetch.mockResolvedValueOnce(errorResponse("Not found", 404));
189
+ const client = createClient();
190
+ await expect(client.fetchForm(999)).rejects.toThrow("Form not found (404)");
191
+ });
192
+ });
193
+ // -------------------------------------------------------------------------
194
+ // authorizeUpload
195
+ // -------------------------------------------------------------------------
196
+ describe("authorizeUpload", () => {
197
+ const file = new File(["content"], "resume.pdf", { type: "application/pdf" });
198
+ it("sends correct payload and returns upload token", async () => {
199
+ mockFetch.mockResolvedValueOnce(jsonResponse({ uploadToken: "tok-123" }));
200
+ const client = createClient();
201
+ const token = await client.authorizeUpload(6, "resume", file);
202
+ expect(token).toBe("tok-123");
203
+ const [url, opts] = mockFetch.mock.calls[0];
204
+ expect(url).toBe(`${API_BASE}/application/forms/6/submissions/authorize-upload`);
205
+ expect(opts.method).toBe("POST");
206
+ const body = JSON.parse(opts.body);
207
+ expect(body).toEqual({
208
+ fieldId: "resume",
209
+ mimeType: "application/pdf",
210
+ fileSize: file.size,
211
+ fileName: "resume.pdf",
212
+ });
213
+ });
214
+ it("throws with server error message on failure", async () => {
215
+ mockFetch.mockResolvedValueOnce(errorResponse("File type not allowed", 400));
216
+ const client = createClient();
217
+ await expect(client.authorizeUpload(6, "resume", file)).rejects.toThrow("File type not allowed");
218
+ });
219
+ });
220
+ // -------------------------------------------------------------------------
221
+ // uploadFile
222
+ // -------------------------------------------------------------------------
223
+ describe("uploadFile", () => {
224
+ const file = new File(["content"], "resume.pdf", { type: "application/pdf" });
225
+ it("sends multipart form data and returns URL", async () => {
226
+ mockFetch.mockResolvedValueOnce(jsonResponse({ url: "https://files.example.com/resume.pdf" }));
227
+ const client = createClient();
228
+ const url = await client.uploadFile(6, "tok-123", file);
229
+ expect(url).toBe("https://files.example.com/resume.pdf");
230
+ const [fetchUrl, opts] = mockFetch.mock.calls[0];
231
+ expect(fetchUrl).toBe(`${API_BASE}/application/forms/6/submissions/upload`);
232
+ expect(opts.method).toBe("POST");
233
+ expect(opts.body).toBeInstanceOf(FormData);
234
+ });
235
+ it("throws on non-OK response", async () => {
236
+ mockFetch.mockResolvedValueOnce(errorResponse("Token expired", 401));
237
+ const client = createClient();
238
+ await expect(client.uploadFile(6, "bad-tok", file)).rejects.toThrow("File upload failed");
239
+ });
240
+ });
241
+ // -------------------------------------------------------------------------
242
+ // submitForm
243
+ // -------------------------------------------------------------------------
244
+ describe("submitForm", () => {
245
+ it("sends correct payload with resourceType from constructor", async () => {
246
+ mockFetch.mockResolvedValueOnce({
247
+ ok: true,
248
+ status: 201,
249
+ json: () => Promise.resolve({ statusCode: 201, message: "Created" }),
250
+ });
251
+ const client = createClient();
252
+ await client.submitForm(6, { first_name: "Jane", email: "jane@test.com" }, {
253
+ eventId: 10,
254
+ ticketId: 1,
255
+ });
256
+ const [url, opts] = mockFetch.mock.calls[0];
257
+ expect(url).toBe(`${API_BASE}/application/forms/6/submissions`);
258
+ expect(opts.method).toBe("POST");
259
+ const body = JSON.parse(opts.body);
260
+ expect(body).toEqual({
261
+ data: { first_name: "Jane", email: "jane@test.com" },
262
+ eventId: 10,
263
+ resourceType: "ticketing",
264
+ resourceId: 1,
265
+ });
266
+ });
267
+ it("sends Accept-Language header when locale is in context", async () => {
268
+ mockFetch.mockResolvedValueOnce({
269
+ ok: true,
270
+ status: 201,
271
+ json: () => Promise.resolve({ statusCode: 201, message: "Created" }),
272
+ });
273
+ const client = createClient();
274
+ await client.submitForm(6, {}, { eventId: 10, ticketId: 1, locale: "fr" });
275
+ const [, opts] = mockFetch.mock.calls[0];
276
+ expect(opts.headers).toEqual(expect.objectContaining({ "Accept-Language": "fr" }));
277
+ });
278
+ it("throws with server error message on failure", async () => {
279
+ mockFetch.mockResolvedValueOnce(errorResponse("Duplicate email", 400));
280
+ const client = createClient();
281
+ await expect(client.submitForm(6, {}, { eventId: 10, ticketId: 1 })).rejects.toThrow("Duplicate email");
282
+ });
283
+ it("uses different resourceType when configured", async () => {
284
+ mockFetch.mockResolvedValueOnce({
285
+ ok: true,
286
+ status: 201,
287
+ json: () => Promise.resolve({ statusCode: 201, message: "Created" }),
288
+ });
289
+ const client = new __1.EventFormClient({
290
+ apiKey: API_KEY,
291
+ resourceType: "accommodation",
292
+ apiBaseUrl: API_BASE,
293
+ });
294
+ await client.submitForm(6, {}, { eventId: 10, ticketId: 1 });
295
+ const body = JSON.parse(mockFetch.mock.calls[0][1].body);
296
+ expect(body.resourceType).toBe("accommodation");
297
+ });
298
+ });
299
+ });
300
+ //# sourceMappingURL=client.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.spec.js","sourceRoot":"","sources":["../../../../src/client/__tests__/client.spec.ts"],"names":[],"mappings":"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"}