question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Rest PUT handler should not need search parameters

See original GitHub issue

Environment

Name Version
msw 0.26.0
browser Chrome Version 88.0.4324.192 (Official Build) (x86_64)
OS macOS Version 11.1

Request handlers

import { setupWorker } from 'msw';

const mockServiceWorker = setupWorker();

mockServiceWorker.setup = (handlers) => {
  beforeAll(() => {
    mockServiceWorker.start({
      onUnhandledRequest: (request) => {
        // Without overriding the default console error, Jasmine can't catch this and won't fail the test
        console.error(`Received request ${request.method} ${request.url.href}, which has no handler.`); // eslint-disable-line no-console
      },
      waitUntilReady: true,
    });
  });
  beforeEach(() => {
    mockServiceWorker.resetHandlers();
    mockServiceWorker.use(...handlers);
  });
  afterAll(() => {
    mockServiceWorker.stop();
  });
};

export default mockServiceWorker;

Then the actual test:

describe('timer', () => {
  mockServiceWorker.setup([
    rest.put('/api/v1/timer/start', (req, res, context) => {
      const params = {
        accumulated_time: req.url.searchParams.get('accumulated_time'),
      };

      if (isEqualWith(params, { accumulated_time: 0 })) {
        return res(
          context.status(200),
          context.json({ c: true }),
        );
      }
    }),
    rest.put('/api/v1/timer/start?accumulated_time=0', (req, res, context) => {
      return res(
        context.status(200),
        context.json({ b: true }),
      );
    }),
    rest.put('http://localhost:9876/api/v1/timer/start?accumulated_time=0', (req, res, context) => {
      return res(
        context.status(200),
        context.json({ a: true }),
      );
    }),
  ]);

  beforeEach(function () {
    mockServiceWorker.printHandlers();
  });

  it(...);
});

Actual request

export const startTimer = (durationInSeconds = 0) => {
  const url = `/api/v1/timer/start?accumulated_time=${durationInSeconds}`;
  const fetchOptions = {
    method: 'put',
    credentials: 'same-origin',
    headers: { 'X-CSRF-Token': window.authenticity_token },
  };

  return fetch(url, fetchOptions);
};

Current behavior

I am having trouble figuring out how to properly mock a PUT request.

As you can see in the handlers, I am testing out which of the 3 possible ways to specify the handler URL. The test warns about it not using the ideal pattern. See screenshot of dev tools:

image

And here is the preview of the response:

image

In addition, I am not sure why the worker is 404ing – almost like it is forwarding the request? Probably not related but here is a screenshot of the details:

image

Expected behavior

I expect the service worker to intercept the PUT request with the proper URL and without any parameters specified. Just like a GET request.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
juancacommented, Mar 18, 2021

Okay, the lesson here is:

The values of the search parameters are always strings. This was a lesson I learned after making this issue. Comparing the integer 0 and string 0 was the crux of the issue here.

@kettanaito Thanks for the explanation, it helped pinpoint the problem.

0reactions
juancacommented, Mar 18, 2021
  1. The rest.put('/api/v1/timer/start') handler is used if the request satisfies its if (isEqualWith(params, { accumulated_time: 0 })) { condition.
  2. If not, lookup jumps to the next matching handler: rest.put('/api/v1/timer/start?accumulated_time=0', which always returns a mocked response, so it will be used.

D:

This is good to know! I’ve been stuffing my handlers with a bunch of if(...)s.

But I digress.

Okay, I think perhaps there is something wrong with my isEqualWith. I’ll look into it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

REST API Design Best Practices for Parameter and Query ...
Best practices for parameter and query string usage in REST APIs. ... We can use this to tell the API that we need...
Read more >
REST API Best practices: Where to put parameters? [closed]
A REST API can have parameters in at least two ways: As part of the URL-path (i.e. /api/resource/parametervalue ); As a query argument...
Read more >
REST API Best Practices for Parameter and Query String ...
REST is one of the most widely used protocols for building API. ... Array and Map Parameters; When Should the Query String not...
Read more >
Best practices for REST API design
Learn how to design REST APIs to be easy to understand for anyone, future-proof, secure, and fast since they serve data to clients...
Read more >
Best Practices for Designing a Pragmatic RESTful API
An API is a user interface for a developer. Learn the best practices to make an API that is easy to adopt and...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found