astro-ghostcms/.pnpm-store/v3/files/bb/34de88b4ea70cfb0eeb7d9a7952...

272 lines
7.8 KiB
Plaintext

import crossFetch from 'cross-fetch';
// Modified from https://github.com/jimmywarting/node-domexception,
// which is commonjs only.
if (!globalThis.DOMException) {
try {
const { MessageChannel } = await import('worker_threads'),
port = new MessageChannel().port1,
ab = new ArrayBuffer();
port.postMessage(ab, [ab, ab]);
} catch (err) {
err.constructor.name === 'DOMException' && (globalThis.DOMException = err.constructor);
}
}
export default function createFetchMocker(vi) {
globalThis.fetch = crossFetch;
globalThis.Response = crossFetch.Response;
globalThis.Headers = crossFetch.Headers;
globalThis.Request = crossFetch.Request;
const ActualResponse = Response;
function responseWrapper(body, init) {
if (body && typeof body.constructor === 'function' && body.constructor.__isFallback) {
const response = new ActualResponse(null, init);
response.body = body;
const actualClone = response.clone;
response.clone = () => {
const clone = actualClone.call(response);
const [body1, body2] = body.tee();
response.body = body1;
clone.body = body2;
return clone;
};
return response;
}
return new ActualResponse(body, init);
}
function responseInit(resp, init) {
if (typeof resp.init === 'object') {
return resp.init;
} else {
init = Object.assign({}, init || {});
for (const field of ['status', 'statusText', 'headers', 'url']) {
if (field in resp) {
init[field] = resp[field];
}
}
return init;
}
}
function requestMatches(urlOrPredicate) {
const predicate =
urlOrPredicate instanceof RegExp
? (input) => urlOrPredicate.test(input.url)
: typeof urlOrPredicate === 'string'
? (input) => input.url === urlOrPredicate
: urlOrPredicate;
return (input, reqInit) => {
const req = normalizeRequest(input, reqInit);
return [predicate(req), req];
};
}
function requestNotMatches(urlOrPredicate) {
const matches = requestMatches(urlOrPredicate);
return (input) => {
const result = matches(input);
return [!result[0], result[1]];
};
}
function staticMatches(value) {
return (input, reqInit) => {
return [value, normalizeRequest(input, reqInit)];
};
}
const isFn = (unknown) => typeof unknown === 'function';
const isMocking = vi.fn(staticMatches(true));
const abortError = () => new DOMException('The operation was aborted. ', 'AbortError');
const abort = () => {
throw abortError();
};
const abortAsync = () => {
return Promise.reject(abortError());
};
const toPromise = (val) => (val instanceof Promise ? val : Promise.resolve(val));
const normalizeResponse = (bodyOrFunction, init) => (input, reqInit) => {
const [mocked, request] = isMocking(input, reqInit);
return mocked
? isFn(bodyOrFunction)
? toPromise(bodyOrFunction(request)).then((resp) => {
if (request.signal && request.signal.aborted) {
abort();
}
return typeof resp === 'string'
? responseWrapper(resp, init)
: responseWrapper(resp.body, responseInit(resp, init));
})
: new Promise((resolve, reject) => {
if (request.signal && request.signal.aborted) {
reject(abortError());
return;
}
resolve(responseWrapper(bodyOrFunction, init));
})
: crossFetch.fetch(input, reqInit);
};
const normalizeRequest = (input, reqInit) => {
if (input instanceof Request) {
if (input.signal && input.signal.aborted) {
abort();
}
return input;
} else if (typeof input === 'string') {
if (reqInit && reqInit.signal && reqInit.signal.aborted) {
abort();
}
return new Request(input, reqInit);
} else if (typeof input.toString === 'function') {
if (reqInit && reqInit.signal && reqInit.signal.aborted) {
abort();
}
return new Request(input.toString(), reqInit);
} else {
throw new TypeError('Unable to parse input as string or Request');
}
};
const normalizeError = (errorOrFunction) =>
isFn(errorOrFunction) ? errorOrFunction : () => Promise.reject(errorOrFunction);
const fetch = vi.fn(normalizeResponse(''));
fetch.Headers = Headers;
fetch.Response = responseWrapper;
fetch.Request = Request;
fetch.mockResponse = (bodyOrFunction, init) => fetch.mockImplementation(normalizeResponse(bodyOrFunction, init));
fetch.mockReject = (errorOrFunction) => fetch.mockImplementation(normalizeError(errorOrFunction));
fetch.mockAbort = () => fetch.mockImplementation(abortAsync);
fetch.mockAbortOnce = () => fetch.mockImplementationOnce(abortAsync);
const mockResponseOnce = (bodyOrFunction, init) =>
fetch.mockImplementationOnce(normalizeResponse(bodyOrFunction, init));
fetch.mockResponseOnce = mockResponseOnce;
fetch.once = mockResponseOnce;
fetch.mockRejectOnce = (errorOrFunction) => fetch.mockImplementationOnce(normalizeError(errorOrFunction));
fetch.mockResponses = (...responses) => {
responses.forEach((response) => {
if (Array.isArray(response)) {
const [body, init] = response;
fetch.mockImplementationOnce(normalizeResponse(body, init));
} else {
fetch.mockImplementationOnce(normalizeResponse(response));
}
});
return fetch;
};
fetch.isMocking = (req, reqInit) => isMocking(req, reqInit)[0];
fetch.mockIf = fetch.doMockIf = (urlOrPredicate, bodyOrFunction, init) => {
isMocking.mockImplementation(requestMatches(urlOrPredicate));
if (bodyOrFunction) {
fetch.mockResponse(bodyOrFunction, init);
}
return fetch;
};
fetch.dontMockIf = (urlOrPredicate, bodyOrFunction, init) => {
isMocking.mockImplementation(requestNotMatches(urlOrPredicate));
if (bodyOrFunction) {
fetch.mockResponse(bodyOrFunction, init);
}
return fetch;
};
fetch.mockOnceIf = fetch.doMockOnceIf = (urlOrPredicate, bodyOrFunction, init) => {
isMocking.mockImplementationOnce(requestMatches(urlOrPredicate));
if (bodyOrFunction) {
mockResponseOnce(bodyOrFunction, init);
}
return fetch;
};
fetch.dontMockOnceIf = (urlOrPredicate, bodyOrFunction, init) => {
isMocking.mockImplementationOnce(requestNotMatches(urlOrPredicate));
if (bodyOrFunction) {
mockResponseOnce(bodyOrFunction, init);
}
return fetch;
};
fetch.dontMock = () => {
isMocking.mockImplementation(staticMatches(false));
return fetch;
};
fetch.dontMockOnce = () => {
isMocking.mockImplementationOnce(staticMatches(false));
return fetch;
};
fetch.doMock = (bodyOrFunction, init) => {
isMocking.mockImplementation(staticMatches(true));
if (bodyOrFunction) {
fetch.mockResponse(bodyOrFunction, init);
}
return fetch;
};
fetch.mockOnce = fetch.doMockOnce = (bodyOrFunction, init) => {
isMocking.mockImplementationOnce(staticMatches(true));
if (bodyOrFunction) {
mockResponseOnce(bodyOrFunction, init);
}
return fetch;
};
fetch.requests = () => {
const requests = [];
fetch.mock.calls.forEach((call) => {
try {
let req = normalizeRequest(call[0], call[1]);
requests.push(req);
} catch(e) {
// ignore
}
});
return requests;
};
fetch.resetMocks = () => {
fetch.mockReset();
isMocking.mockReset();
// reset to default implementation with each reset
fetch.mockImplementation(normalizeResponse(''));
fetch.doMock();
fetch.isMocking = (req, reqInit) => isMocking(req, reqInit)[0];
};
fetch.enableMocks = () => {
globalThis.fetchMock = globalThis.fetch = fetch;
};
fetch.disableMocks = () => {
globalThis.fetch = crossFetch;
};
return fetch;
}