import { Response as ReactNativeResponse } from 'whatwg-fetch' import { isResponseLike, ResponseError, throwResponseError } from '../response_error' // Mimics Expo's winter `FetchResponse`: the full Response shape, but NOT an // instance of the global `Response` (so `instanceof Response` returns false). const fetchResponseLike = (status: number) => ({ status, ok: status >= 200 && status < 300, statusText: 'unauthorized', url: 'https://api.planningcenteronline.com/chat/v2/me', redirected: false, headers: {}, clone() { return this }, json: async () => ({ errors: [] }), text: async () => '', arrayBuffer: async () => new ArrayBuffer(0), }) describe('isResponseLike', () => { it('recognizes a Response by shape even when it is not an instanceof Response', () => { const notARealResponse = fetchResponseLike(401) expect(notARealResponse instanceof Response).toBe(false) expect(isResponseLike(notARealResponse)).toBe(true) }) it("recognizes React Native's fetch Response, which never assigns `redirected`", () => { const response = new ReactNativeResponse(JSON.stringify({ errors: [] }), { status: 401, statusText: 'Unauthorized', headers: { 'Content-Type': 'application/json' }, }) expect('redirected' in response).toBe(false) expect(isResponseLike(response)).toBe(true) }) it('rejects things that are not responses', () => { expect(isResponseLike(null)).toBe(false) expect(isResponseLike(new Error('boom'))).toBe(false) expect(isResponseLike(new ResponseError({ status: 401 } as never))).toBe(false) expect(isResponseLike({ status: 401 })).toBe(false) expect(isResponseLike({ status: 401, ok: false, clone() {}, json: async () => ({}) })).toBe( false ) }) }) describe('throwResponseError', () => { it('wraps a Response-like rejection into a ResponseError', () => { expect(() => throwResponseError(fetchResponseLike(401))).toThrow(ResponseError) }) it('rethrows non-response errors synchronously instead of returning a rejected promise', () => { const error = new Error('network down') expect(() => throwResponseError(error)).toThrow(error) }) it('rethrows an existing ResponseError without re-wrapping it', () => { const error = new ResponseError(fetchResponseLike(401) as never) expect(() => throwResponseError(error)).toThrow(error) }) })