IanVS / vitest-fetch-mock

Vitest mock for fetch, forked from jest-fetch-mock
MIT License
59 stars 7 forks source link

Vitest error on fetching relative URLs #12

Open geoidesic opened 1 year ago

geoidesic commented 1 year ago

I don't get this error if I run the fetch via the app code but via vitest using this mocking library then it gives this error:

globalErrorHandler TypeError: Only absolute URLs are supported
    at getNodeRequestOptions (/Users/blah/node_modules/node-fetch/lib/index.js:1327:9)
    at /Users/blah/node_modules/node-fetch/lib/index.js:1450:19
    at new Promise (<anonymous>)
    at fetch (/Users/blah/node_modules/node-fetch/lib/index.js:1447:9)
    at fetch (/Users/blah/node_modules/cross-fetch/dist/node-ponyfill.js:10:20)
    at Object.fetch (/Users/blah/src/lib/database/requestWrapper.js:10:31)
    at SceneCollection.edit (/Users/blah/src/stores/scenes.ts:110:15)
    at TokenLayer.Add (/Users/blah/src/components/Map/TokenLayer.ts:41:19)
    at /Users/blah/src/components/Map/__tests__/TokenLayerShould.test.ts:18:15
    at file:///Users/blah/node_modules/@vitest/runner/dist/index.js:242:72

Here's the test:

import { Token } from "../../babylon/tokens/Token";
import { TokenLayer } from "../TokenLayer";
import { Location } from "../Location";
import createFetchMock from 'vitest-fetch-mock';
import { vi } from 'vitest';

const fetchMocker = createFetchMock(vi);

beforeEach(() => {
    fetchMocker.resetMocks();
    fetchMocker.doMock();
});

test('retrieve_token_from_location', () => {
    let newTokens = new TokenLayer();
    newTokens.Add(Location.At(5, 5), "New Token");
    expect(newTokens.TokenAt(Location.At(5, 5))).toBeInstanceOf(Token);
});
IanVS commented 1 year ago

Thanks for the report, would you be willing to put together a minimal reproduction in stackblitz or codesandbox?

jacobbogers commented 11 months ago

@geoidesic go the exact same error, it seems it uses node-fetch underneath, its better to mock the global fetch directly

jacobbogers commented 11 months ago

This workaround works just fine

Ofcourse set/restore global fetch back to the original in the afterEach/beforeEach

            it('user not logged in', async () => {
                // mock your fetch
                globalThis.fetch = async (input: RequestInfo | URL, init?: RequestInit) => {
                    const headers = new Headers({
                        'content-type': 'application/json',
                    });
                    console.log('incomming url: %o', input);
                    return new Response('{ "message": "Ok" }', { status: 200, statusText: 'ok', headers });
                };
                // @ts-ignore
                const boot = await import('../boot/preboot');
                const result = boot.default();
            });