Skip to content

Commit

Permalink
Make it easier to work with fetch responses
Browse files Browse the repository at this point in the history
Refs #1834, #2186
  • Loading branch information
thewilkybarkid committed Mar 3, 2025
1 parent 9288158 commit 2901b6f
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 22 deletions.
37 changes: 22 additions & 15 deletions test/fc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ import { capitalCase } from 'case-anything'
import { mod11_2 } from 'cdigit'
import { type Doi, isDoi } from 'doi-ts'
import { Array, DateTime, Duration, Either, HashSet, Option, Predicate } from 'effect'
import type { Request, Response } from 'express'
import type { Response as ExpressResponse, Request } from 'express'
import * as fc from 'fast-check'
import type * as F from 'fetch-fp-ts'
import type { Json, JsonRecord } from 'fp-ts/lib/Json.js'
import type * as H from 'hyper-ts'
import { Status } from 'hyper-ts'
Expand Down Expand Up @@ -122,7 +121,6 @@ import { type NonEmptyString, isNonEmptyString } from '../src/types/string.js'
import { type SubfieldId, subfieldIds } from '../src/types/subfield.js'
import type { UserOnboarding } from '../src/user-onboarding.js'
import type { User } from '../src/user.js'
import { shouldNotBeCalled } from './should-not-be-called.js'

export type Arbitrary<T> = fc.Arbitrary<T>

Expand Down Expand Up @@ -1159,24 +1157,33 @@ export const fetchResponse = ({
text,
}: {
headers?: fc.Arbitrary<Headers>
status?: fc.Arbitrary<number>
status?: fc.Arbitrary<Status>
json?: fc.Arbitrary<Json>
text?: fc.Arbitrary<string>
} = {}): fc.Arbitrary<F.Response> =>
} = {}): fc.Arbitrary<Response> =>
fc
.record({
headers: headers_ ?? headers(),
status: status ?? fc.integer(),
statusText: fc.string(),
url: fc.string(),
status: status ?? statusCode(),
text: json ? json.map(JSON.stringify) : (text ?? fc.string()),
})
.map(args =>
Object.defineProperties(
{ ...args, clone: shouldNotBeCalled, text: () => Promise.resolve(args.text) },
{ [fc.toStringMethod]: { value: () => fc.stringify(args) } },
),
)
.map(args => {
return Object.defineProperties(
new Response(
![Status.NoContent, Status.ResetContent].includes(args.status as never) &&
(args.status < 300 || args.status >= 400)
? args.text
: undefined,
{
headers: args.headers,
status: args.status,
},
),
{
[fc.toStringMethod]: { value: () => fc.stringify({ ...args, headers: { ...args.headers } }) },
},
)
})

export const request = ({
body,
Expand All @@ -1202,7 +1209,7 @@ export const request = ({
Object.defineProperties(createRequest(args), { [fc.toStringMethod]: { value: () => fc.stringify(args) } }),
)

export const response = (): fc.Arbitrary<Response> =>
export const response = (): fc.Arbitrary<ExpressResponse> =>
fc
.record({ req: request() })
.map(args =>
Expand Down
2 changes: 1 addition & 1 deletion test/openalex/work.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('getWorkByDoi', () => {
test.prop([
fc.doi(),
fc.fetchResponse({
status: fc.integer().filter(status => ![Status.OK, Status.NotFound, Status.Gone].includes(status as never)),
status: fc.statusCode().filter(status => ![Status.OK, Status.NotFound, Status.Gone].includes(status as never)),
}),
])('when the status code is not ok', async (doi, response) => {
const actual = await _.getWorkByDoi(doi)({ fetch: () => Promise.resolve(response) })()
Expand Down
4 changes: 2 additions & 2 deletions test/prereview-coar-notify/get-recent-review-requests.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ describe('getRecentReviewRequests', () => {
),
),
])('when a list is found', async (origin, [requests, response]) => {
const fetch = jest.fn<Fetch>(_ => Promise.resolve(response))
const fetch = jest.fn<Fetch>(_ => Promise.resolve(response.clone()))

const result = await _.getRecentReviewRequests(origin)({
fetch,
Expand Down Expand Up @@ -73,7 +73,7 @@ describe('getRecentReviewRequests', () => {
),
),
])('when the response is stale', async (origin, [requests, response]) => {
const fetch = jest.fn<Fetch>(_ => Promise.resolve(response))
const fetch = jest.fn<Fetch>(_ => Promise.resolve(response.clone()))

const result = await _.getRecentReviewRequests(origin)({
fetch,
Expand Down
16 changes: 12 additions & 4 deletions test/zenodo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4154,7 +4154,9 @@ describe('addAuthorToRecordOnZenodo', () => {
fc.user(),
fc.constantFrom('public', 'pseudonym'),
fc.oneof(
fc.fetchResponse({ status: fc.integer({ min: 400 }) }).map(response => Promise.resolve(response)),
fc
.fetchResponse({ status: fc.statusCode().filter(status => status >= 400) })
.map(response => Promise.resolve(response)),
fc.error().map(error => Promise.reject(error)),
),
])('Zenodo is unavailable', async (zenodoApiKey, id, user, persona, response) => {
Expand Down Expand Up @@ -4293,7 +4295,9 @@ ${comment.comment.toString()}`,
fc.string(),
fc.origin(),
fc.oneof(
fc.fetchResponse({ status: fc.integer({ min: 400 }) }).map(response => Promise.resolve(response)),
fc
.fetchResponse({ status: fc.statusCode().filter(status => status >= 400) })
.map(response => Promise.resolve(response)),
fc.error().map(error => Promise.reject(error)),
),
])('Zenodo is unavailable', async (comment, zenodoApiKey, publicUrl, response) => {
Expand Down Expand Up @@ -4441,7 +4445,9 @@ describe('publishDepositionOnZenodo', () => {
fc.integer(),
fc.string(),
fc.oneof(
fc.fetchResponse({ status: fc.integer({ min: 400 }) }).map(response => Promise.resolve(response)),
fc
.fetchResponse({ status: fc.statusCode().filter(status => status >= 400) })
.map(response => Promise.resolve(response)),
fc.error().map(error => Promise.reject(error)),
),
])('Zenodo is unavailable', async (id, zenodoApiKey, response) => {
Expand Down Expand Up @@ -5105,7 +5111,9 @@ ${newPrereview.review.toString()}`,
fc.string(),
fc.origin(),
fc.oneof(
fc.fetchResponse({ status: fc.integer({ min: 400 }) }).map(response => Promise.resolve(response)),
fc
.fetchResponse({ status: fc.statusCode().filter(status => status >= 400) })
.map(response => Promise.resolve(response)),
fc.error().map(error => Promise.reject(error)),
),
])('Zenodo is unavailable', async (newPrereview, subjects, requested, zenodoApiKey, publicUrl, response) => {
Expand Down

0 comments on commit 2901b6f

Please sign in to comment.