Fetch_test.res.mjs

  1// Generated by ReScript, PLEASE EDIT WITH CARE
  2
  3import * as Fetch from "../src/ffi/Fetch.res.mjs";
  4import * as Vitest from "vitest";
  5import * as Core__JSON from "@rescript/core/lib/es6/src/Core__JSON.res.mjs";
  6
  7let mockFetchJson = (function(json, status, statusText) {
  8    globalThis.fetch = vi.fn(() => Promise.resolve({
  9      ok: status >= 200 && status < 300,
 10      status: status,
 11      statusText: statusText,
 12      json: () => Promise.resolve(json)
 13    }));
 14  });
 15
 16let setupMockWithCapture = (function() {
 17    const calls = [];
 18    globalThis.fetch = vi.fn((url, init) => {
 19      calls.push({url, init});
 20      return Promise.resolve({
 21        ok: true,
 22        status: 200,
 23        statusText: 'OK',
 24        json: () => Promise.resolve(null)
 25      });
 26    });
 27    return calls;
 28  });
 29
 30let getContentType = (function(calls) {
 31    const headers = calls[0].init.headers;
 32    if (Array.isArray(headers)) {
 33      const found = headers.find(h => h[0] === 'Content-Type');
 34      return found ? found[1] : undefined;
 35    }
 36    return headers['Content-Type'];
 37  });
 38
 39let getCredentials = (function(calls) {
 40    return calls[0].init.credentials;
 41  });
 42
 43Vitest.describe("Fetch", () => {
 44  Vitest.test("GET request returns user-defined response variant", async t => {
 45    let json = Object.fromEntries([[
 46        "name",
 47        "test"
 48      ]]);
 49    mockFetchJson(json, 200, "OK");
 50    let result = await Fetch.send(Fetch.onResponse(Fetch.get("http://example.com/api"), json => {
 51      let dict = Core__JSON.Decode.object(json);
 52      if (dict === undefined) {
 53        return {
 54          NAME: "DecodeError",
 55          VAL: "not an object"
 56        };
 57      }
 58      let name = dict["name"];
 59      if (name === undefined) {
 60        return {
 61          NAME: "DecodeError",
 62          VAL: "name missing"
 63        };
 64      }
 65      let s = Core__JSON.Decode.string(name);
 66      if (s !== undefined) {
 67        return {
 68          NAME: "Success",
 69          VAL: s
 70        };
 71      } else {
 72        return {
 73          NAME: "DecodeError",
 74          VAL: "name not string"
 75        };
 76      }
 77    }, (status, message) => ({
 78      NAME: "APIError",
 79      VAL: [
 80        status,
 81        message
 82      ]
 83    })));
 84    t.expect(result).toEqual({
 85      NAME: "Success",
 86      VAL: "test"
 87    });
 88  });
 89  Vitest.test("POST request sends body and auto-sets content-type", async t => {
 90    let body = Object.fromEntries([[
 91        "data",
 92        "value"
 93      ]]);
 94    let responseJson = Object.fromEntries([[
 95        "id",
 96        123
 97      ]]);
 98    mockFetchJson(responseJson, 201, "Created");
 99    let result = await Fetch.send(Fetch.onResponse(Fetch.setBody(Fetch.post("http://example.com/api"), body), json => {
100      let dict = Core__JSON.Decode.object(json);
101      if (dict === undefined) {
102        return {
103          NAME: "DecodeError",
104          VAL: "not an object"
105        };
106      }
107      let id = dict["id"];
108      if (id === undefined) {
109        return {
110          NAME: "DecodeError",
111          VAL: "id missing"
112        };
113      }
114      let f = Core__JSON.Decode.float(id);
115      if (f !== undefined) {
116        return {
117          NAME: "Created",
118          VAL: f | 0
119        };
120      } else {
121        return {
122          NAME: "DecodeError",
123          VAL: "id not number"
124        };
125      }
126    }, (status, message) => ({
127      NAME: "APIError",
128      VAL: [
129        status,
130        message
131      ]
132    })));
133    t.expect(result).toEqual({
134      NAME: "Created",
135      VAL: 123
136    });
137  });
138  Vitest.test("POST auto-sets content-type header", async t => {
139    let _calls = setupMockWithCapture();
140    await Fetch.send(Fetch.onResponse(Fetch.setBody(Fetch.post("http://example.com/api"), "test body"), _json => ({
141      NAME: "Success",
142      VAL: true
143    }), (_status, _message) => ({
144      NAME: "Success",
145      VAL: false
146    })));
147    let ct = getContentType(_calls);
148    t.expect(ct).toEqual("application/json");
149  });
150  Vitest.test("POST does not override custom content-type", async t => {
151    let _calls = setupMockWithCapture();
152    await Fetch.send(Fetch.onResponse(Fetch.setBody(Fetch.setHeader(Fetch.post("http://example.com/api"), "Content-Type", "text/plain"), "test body"), _json => ({
153      NAME: "Success",
154      VAL: true
155    }), (_status, _message) => ({
156      NAME: "Success",
157      VAL: false
158    })));
159    let ct = getContentType(_calls);
160    t.expect(ct).toEqual("text/plain");
161  });
162  Vitest.test("error response triggers onError", async t => {
163    let errorJson = Object.fromEntries([[
164        "error",
165        "not found"
166      ]]);
167    mockFetchJson(errorJson, 404, "Not Found");
168    let result = await Fetch.send(Fetch.onResponse(Fetch.get("http://example.com/api"), _json => ({
169      NAME: "Success",
170      VAL: 0
171    }), (status, message) => {
172      if (status === 404 && message === "not found") {
173        return "NotFound";
174      } else {
175        return "OtherError";
176      }
177    }));
178    t.expect(result).toEqual("NotFound");
179  });
180  Vitest.test("promise returns a rescript promise", async t => {
181    let json = Object.fromEntries([[
182        "value",
183        42
184      ]]);
185    mockFetchJson(json, 200, "OK");
186    let p = Fetch.promise(Fetch.onResponse(Fetch.get("http://example.com/api"), json => {
187      let dict = Core__JSON.Decode.object(json);
188      if (dict === undefined) {
189        return {
190          NAME: "DecodeError",
191          VAL: "not an object"
192        };
193      }
194      let v = dict["value"];
195      if (v === undefined) {
196        return {
197          NAME: "DecodeError",
198          VAL: "value missing"
199        };
200      }
201      let f = Core__JSON.Decode.float(v);
202      if (f !== undefined) {
203        return {
204          NAME: "Success",
205          VAL: f | 0
206        };
207      } else {
208        return {
209          NAME: "DecodeError",
210          VAL: "value not number"
211        };
212      }
213    }, (status, message) => ({
214      NAME: "APIError",
215      VAL: [
216        status,
217        message
218      ]
219    })));
220    let result = await p;
221    t.expect(result).toEqual({
222      NAME: "Success",
223      VAL: 42
224    });
225  });
226  Vitest.test("DELETE request works", async t => {
227    mockFetchJson(null, 204, "No Content");
228    let result = await Fetch.send(Fetch.onResponse(Fetch.$$delete("http://example.com/api/1"), _json => "Deleted", (_status, _message) => "Failed"));
229    t.expect(result).toEqual("Deleted");
230  });
231  Vitest.test("default credentials is same-origin", async t => {
232    let _calls = setupMockWithCapture();
233    await Fetch.send(Fetch.onResponse(Fetch.get("http://example.com/api"), _json => ({
234      NAME: "Success",
235      VAL: true
236    }), (_status, _message) => ({
237      NAME: "Success",
238      VAL: false
239    })));
240    let creds = getCredentials(_calls);
241    t.expect(creds).toEqual("same-origin");
242  });
243  Vitest.test("credentials omit sets omit", async t => {
244    let _calls = setupMockWithCapture();
245    await Fetch.send(Fetch.onResponse(Fetch.credentials(Fetch.get("http://example.com/api"), "omit"), _json => ({
246      NAME: "Success",
247      VAL: true
248    }), (_status, _message) => ({
249      NAME: "Success",
250      VAL: false
251    })));
252    let creds = getCredentials(_calls);
253    t.expect(creds).toEqual("omit");
254  });
255  Vitest.test("credentials include sets include", async t => {
256    let _calls = setupMockWithCapture();
257    await Fetch.send(Fetch.onResponse(Fetch.credentials(Fetch.post("http://example.com/api"), "include"), _json => ({
258      NAME: "Success",
259      VAL: true
260    }), (_status, _message) => ({
261      NAME: "Success",
262      VAL: false
263    })));
264    let creds = getCredentials(_calls);
265    t.expect(creds).toEqual("include");
266  });
267  Vitest.test("abort triggers onAbort handler", async t => {
268    let controller = new AbortController();
269    (((() => {
270        globalThis.fetch = vi.fn((url, init) => {
271          return new Promise((resolve, reject) => {
272            // Listen for abort
273            if (init.signal) {
274              init.signal.addEventListener('abort', () => {
275                reject(new DOMException('The operation was aborted', 'AbortError'));
276              });
277            }
278            // Never resolve - wait for abort
279          });
280        });
281      })()));
282    let p = Fetch.promise(Fetch.onResponse(Fetch.withAbortController(Fetch.get("http://example.com/api"), controller, () => "Aborted"), _json => ({
283      NAME: "Success",
284      VAL: true
285    }), (_status, _message) => "Error"));
286    await (new Promise(r => setTimeout(r, 10)));
287    controller.abort();
288    let result = await p;
289    t.expect(result).toEqual("Aborted");
290  });
291  Vitest.test("abort after completion is no-op", async t => {
292    let controller = new AbortController();
293    let json = Object.fromEntries([[
294        "data",
295        "value"
296      ]]);
297    mockFetchJson(json, 200, "OK");
298    let p = Fetch.promise(Fetch.onResponse(Fetch.withAbortController(Fetch.get("http://example.com/api"), controller, () => "Aborted"), _json => ({
299      NAME: "Success",
300      VAL: true
301    }), (_status, _message) => "Error"));
302    let result = await p;
303    controller.abort();
304    t.expect(result).toEqual({
305      NAME: "Success",
306      VAL: true
307    });
308  });
309  Vitest.test("request with abort controller completes normally", async t => {
310    let controller = new AbortController();
311    let json = Object.fromEntries([[
312        "name",
313        "test"
314      ]]);
315    mockFetchJson(json, 200, "OK");
316    let result = await Fetch.send(Fetch.onResponse(Fetch.withAbortController(Fetch.get("http://example.com/api"), controller, () => "Aborted"), json => {
317      let dict = Core__JSON.Decode.object(json);
318      if (dict === undefined) {
319        return {
320          NAME: "DecodeError",
321          VAL: "not object"
322        };
323      }
324      let name = dict["name"];
325      if (name === undefined) {
326        return {
327          NAME: "DecodeError",
328          VAL: "missing"
329        };
330      }
331      let s = Core__JSON.Decode.string(name);
332      if (s !== undefined) {
333        return {
334          NAME: "Success",
335          VAL: s
336        };
337      } else {
338        return {
339          NAME: "DecodeError",
340          VAL: "not string"
341        };
342      }
343    }, (_status, _message) => "Error"));
344    t.expect(result).toEqual({
345      NAME: "Success",
346      VAL: "test"
347    });
348  });
349});
350
351export {
352  mockFetchJson,
353  setupMockWithCapture,
354  getContentType,
355  getCredentials,
356}
357/*  Not a pure module */