Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

vi-fetch

Package Overview
Dependencies
Maintainers
1
Versions
29
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

vi-fetch

Easiest way to mock fetch

  • 0.2.1
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
7.6K
decreased by-16.18%
Maintainers
1
Weekly downloads
 
Created
Source

vi-fetch

Easiest way to mock fetch

Compatible with Jest when using ESM flag and Vitest.

Installing

# with npm
npm install -D vi-fetch

# with pnpm
pnpm install -D vi-fetch

# with yarn
yarn install -D vi-fetch

Usage

Setup

Before using mock API, you need to set up fetch mock. To do this, import vi-fetch/setup in your setup file:

import 'vi-fetch/setup';

If fetch is located on another object, you can manually setup it with prepareFetch function, imported from vi-fetch:

import { prepareFetch } from 'vi-fetch';

prepareFetch(globalThis, 'fetchNode');

Mock Instance

Calling fetch in browser can resolve in multiple situations:

  • resolve with ok: true
  • resolve with ok: false
  • throw TypeError if something is wrong

Usually we know the API endpoint and need to test only these three situations, and vi-fetch provides a wrapper around fetch to make it easy.

Use mockApi function to define fetch behavior. Aliases for popular methods are available: mockGet, mockPost, mockPut, mockPatch, mockDelete.

You can ignore query string when mocking, if you provide last argument as false. By default, query string is necessary.

willResolve

To mock fetch with ok: true, you can use willResolve/willResolveOnce methods.

  • By default, willResolve will resolve to {}, if no body is specified.
  • By default, willResolve will return status: 200. You can override it with second argument.
import { test, expect } from 'vitest';
import { mockGet } from 'vi-fetch';
import { renderApplesTable } from '../src/ApplesTable';

test('apples endpoint was called', async () => {
  // or just "/apples" if you configure baseUrl
  const mock = mockGet('https://api.com/v1/apples').willResolve([
    { count: 33 },
  ]);

  await renderApplesTable();

  expect(mock).toHaveFetched();
});
willFail

To mock fetch with ok: false, you can use willFail/willFailOnce methods.

  • By default, willFail will resolve to {}, if no body is specified.
  • By default, willFail will return status: 500 and statucCode: Internal error. You can override it with second and third arguments.
import { test, expect } from 'vitest';
import { mockGet } from 'vi-fetch';
import { renderApplesTable } from '../src/ApplesTable';

test('apples endpoint was called', async () => {
  // or just "/apples" if you configure baseUrl
  const mock = mockGet('https://api.com/v1/apples').willFail(
    { error: 'no apples' },
    404
  );

  await renderApplesTable();

  expect(mock).toHaveFetched();
});

Warning: calling willFail will override every other mock.

willThrow

If you have logic that depends on fetch throwing, you can test it with willThrow/willThrowOnce methods.

willThrow requires Error object or a message. If message is specified, fetch will throw TypeError.

import { test, expect } from 'vitest';
import { mockGet } from 'vi-fetch';
import { renderApplesTable } from '../src/ApplesTable';

test('apples endpoint was called', async () => {
  // or just "/apples" if you configure baseUrl
  const mock = mockGet('https://api.com/v1/apples').willThrow('cors error');

  await renderApplesTable();

  expect(mock).toHaveFetched();
});

Warning: calling willThrow will override every other mock.

willDo

If you want to do something when the fetch is invoking, you can use willDo method:

import { test, expect } from 'vitest';
import { mockGet } from 'vi-fetch';
import { renderApplesTable } from '../src/ApplesTable';

test('apples endpoint was called', async () => {
  // or just "/apples" if you configure baseUrl
  const mock = mockGet('https://api.com/v1/apples').willDo((url) => {
    if (url.searchParams.get('offset') > 2)) {
      return { body: [] };
    }
    return { body: [{ count: 3 }] };
  });

  await renderApplesTable();

  expect(mock).toHaveFetched();
});

Warning: calling willDo will override every other mock.

clear

You can clear on implementation details with clear method.

Configuration

To not repeat baseUrl every time you mock endpoint, you can configure it globally:

import { mockApi } from 'vi-fetch';

mockApi.setOptions({
  baseUrl: 'https://api.com/v1',
});

You can also create isolated mockApi with its own options to not collide with globals:

import { createMockApi } from 'vi-fetch';
import { test, expect } from 'vitest';

const { mockApi } = createMockApi({ baseUrl: 'https://api.com/v2' });

test('isolated', async () => {
  const mock = mockApi('GET', '/apples').willResolve(33);

  await fetch('http://api.com/v2/apples');

  expect(mock).toHaveFetched();
});

You can ignore queryString, if it doesn't matter for you and then check it with toHaveFetchedWithQuery, if it's needed:

import { test, expect } from 'vitest';
import { mockGet } from 'vi-fetch';

test('apples endpoint was called', async () => {
  const mock = mockGet('https://api.com/v1/apples', false).willResolve([
    { count: 33 },
  ]);

  await fetch('https://api.com/v1/apples?count=5&offset=2');

  expect(mock).toHaveFetched();
  expect(mock).toHaveFetchedWithQuery({ count: 5, offset: 2 });
});

Matchers

Imagine we have a test with this setup:

import { expect, test } from 'vitest';
import { mockApi } from 'vi-fetch';

mockApi.setOptions({ baseUrl: 'https://api.com/v1' });

// usually you would call fetch inside your source code
const callFetch = (url, options) => {
  return fetch('https://api.com/v1' + url, options);
};
toHaveFetched

If you want to check if fetch was called with appropriate URL and method, you can use toHaveFetched.

test('api was called', async () => {
  const mock = mockApi('GET', '/apples').willResolve({
    count: 0,
    apples: [],
  });

  await callFetch('/apples');

  expect(mock).toHaveFetched();
});
toHaveFetchedTimes

If you need to check if URL was called multiple times, you can use toHaveFetchedTimes.

test('api was called 3 times', async () => {
  const mock = mockApi('GET', '/apples', false).willResolve({
    count: 0,
    apples: [],
  });

  await callFetch('/apples');
  await callFetch('/apples?offset=2');
  await callFetch('/apples?offset=3');

  expect(mock).toHaveFetchedTimes(3);
});
toHaveFetchedWithBody

If you need to check if URL was called with the specific body, you can use toHaveFetchedWithBody/toHaveFetchedNthTimeWithBody.

test('api was called with json', async () => {
  const mock = mockApi('POST', '/apples').willResolve({
    count: 0,
    apples: [],
  });

  await callFetch('/apples', {
    method: 'POST',
    body: '{ "foo": "baz" }',
  });

  expect(mock).toHaveFetchedWithBody({ foo: 'baz' });
  expect(mock).toHaveFetchedWithBody('{ "foo": "baz" }');

  expect(mock).toHaveNthTimeFetchedWithBody(1, { foo: 'baz' });
});
toHaveFetchedWithQuery

If you need to check if URL was called with the specific query string, you can use toHaveFetchedWithQuery/toHaveFetchedNthTimeWithQuery.

test('api was called with json', async () => {
  const mock = mockApi('GET', '/apples').willResolve({
    count: 0,
    apples: [],
  });

  await callFetch('/apples?count=5&offset=2');

  expect(mock).toHaveFetchedWithQuery({ count: 5, offset: 2 });
  expect(mock).toHaveFetchedWithQuery(
    new URLSearchParams({ count: '5', offset: '2' })
  );
  expect(mock).toHaveFetchedWithQuery('count=5&offset=2');

  expect(mock).toHaveFetchedNthTimeWithQuery(1, { count: 5, offset: 2 });
  expect(mock).toHaveFetchedNthTimeWithQuery(1, 'count=5&offset=2');
});

Support string, object or URLSearchParams

FAQs

Package last updated on 05 Jan 2022

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc