Search code examples
ember.jsstorybook

What is the best way to mock ember services that use ember-ajax in ember-cli-storybook to post and fetch data?


I'm using Ember CLI Storybook to create a story of a component than internally relies upon services that communicate to the internet, to fetch and post information to the backend. The way I'm doing that is using ember-ajax.

I see how to mock an ember model from this section but wondering if there is a workaround for ember ajax service.


Solution

  • I like to use mswjs.io for mocking remote requests. It uses a service worker so you can still use your network log as if you still used your real API.

    I have an example repo here showing how to set it up: https://github.com/NullVoxPopuli/ember-data-resources/

    But I'll copy the code, in case I change something.

    Now, in tests, you'd want something like this: https://github.com/NullVoxPopuli/ember-data-resources/blob/main/tests/unit/find-record-test.ts#L17

    module('findRecord', function (hooks) {
      setupMockData(hooks);
    

    But since you're using storybook, you'd instead want the contents of that function. (And without the setup/teardown hooks unique to tests)

    https://github.com/NullVoxPopuli/ember-data-resources/blob/main/tests/unit/-mock-data.ts#L22

    import { rest, setupWorker } from 'msw';
    
    let worker;
    
    export async function setupMockData() {
        if (!worker) {
          worker = setupWorker();
          await worker.start();
          // artificial timeout "just in case" worker takes a bit to boot
          await new Promise((resolve) => setTimeout(resolve, 1000));
          worker.printHandlers();
        }
    
        let data = [
          { id: '1', type: 'blogs', attributes: { name: `name:1` } },
          { id: '2', type: 'blogs', attributes: { name: `name:2` } },
          { id: '3', type: 'blogs', attributes: { name: `name:3` } },
        ];
    
        worker.use(
          rest.get('/blogs', (req, res, ctx) => {
            let id = req.url.searchParams.get('q[id]');
    
            if (id) {
              let record = data.find((datum) => datum.id === id);
    
              return res(ctx.json({ data: record }));
            }
    
            return res(ctx.json({ data }));
          }),
    
          rest.get('/blogs/:id', (req, res, ctx) => {
            let { id } = req.params;
    
            let record = data.find((datum) => datum.id === id);
    
            if (record) {
              return res(ctx.json({ data: record }));
            }
    
            return res(
              ctx.status(404),
              ctx.json({ errors: [{ status: '404', detail: 'Blog not found' }] })
            );
          })
        );
    }
    

    Docs for msw: https://mswjs.io/