Skip to content

Setup Mock Service Worker Integration

Hey and welcome. In this guide I will show you how to setup the msw integration for exposition and include it into your application.

Confused? 😕

Feel free to reach out if something seems weird, confusing or unnecessary complex.
I'm willing to learn and welcome any kind of feedback with open arms. 🤗

GitHubTwitter

Install dependencies

For this example you need to install the following dependencies:

pnpm add -D @exposition/{core,integrations} msw
yarn add -D @exposition/{core,integrations} msw
npm install -D @exposition/{core,integrations} msw

tl;dr setup ⚡

I'm like to fiddle around with code first, so a whole example to copy & paste is just nice.
Go ahead and grab the entire code from this cookbook and start building your mocks.

Example code 🍝
// #region imports
import { Exposition } from '@exposition/core'
import { createMswIntegration } from '@exposition/integrations/msw'
import { rest } from 'msw'
import { setupServer } from 'msw/node'
// #endregion imports

// ----------------------------------------------

// #region create-exposition
export const exampleExposition = new Exposition({
  cart: {
    options: ['filled', 'empty'],
  },
} as const)
// #endregion create-exposition

// ----------------------------------------------

// #region setup-msw-integration
export const mswIntegration = createMswIntegration(
  exampleExposition,
  {
    msw: setupServer(),
    config: {
      baseUrl: 'https://localhost:1337',
    },
  },
)
// #endregion setup-msw-integration

// ----------------------------------------------

// #region define-msw-handler
const cartItems = [
  // ... define mocks for cart items
]

mswIntegration.createHandler((expositionValues) => {
  return [
    rest.get('/cart', (_request, response, context) => {
      switch (expositionValues.cart) {
        case 'filled':
          return response(context.json({ items: cartItems }))
        default:
          return response(context.json({}))
      }
    }),
  ]
})
// #endregion define-msw-handler

// ----------------------------------------------

// #region init-exposition
exampleExposition.init()
// #endregion init-exposition

// #region define-msw-handler-with-config
mswIntegration.createHandler(
  (_expositionValues, config) => {
    return [
      rest.get(`${config.baseUrl}/cart`, () => {
        // ... your handler logic
      }),
    ]
  })
// #endregion define-msw-handler-with-config

Otherwise, if you wanna have a break down and a little bit of context follow the steps below.

Create Exposition

First create an Exposition instance by passing in your configuration.



 


export const exampleExposition = new Exposition({
  cart: {
    options: ['filled', 'empty'],
  },
} as const)

Next, use createMswIntegration and add as a setting parameter ether setupClient or setupServer. In this case we use setupServer.


 
 






export const mswIntegration = createMswIntegration(
  exampleExposition,
  {
    msw: setupServer(),
    config: {
      baseUrl: 'https://localhost:1337',
    },
  },
)

Define handler

You can import the integration and add new handler by calling createHandler. The spicy part is that the first parameter expositionValues will automatically be fully typed. With that you can use a switch statement and your cases will be auto suggested. 🌶️





 











const cartItems = [
  // ... define mocks for cart items
]

mswIntegration.createHandler((expositionValues) => {
  return [
    rest.get('/cart', (_request, response, context) => {
      switch (expositionValues.cart) {
        case 'filled':
          return response(context.json({ items: cartItems }))
        default:
          return response(context.json({}))
      }
    }),
  ]
})

Pro gamer tip 👑

You can also use the very good @mswjs/data library, in combination with @faker-js/faker to build and fill your mocks. A cookbook for that will follow in the future.

Check out this playground example
import { factory, primaryKey } from '@mswjs/data'
import { faker } from '@faker-js/faker'

export const mockDatabase = factory({
  items: {
    id: primaryKey(faker.datatype.uuid),
    name: () => faker.commerce.productName(),
    quantity: () => faker.datatype.number({ min: 1, max: 20, precision: 2 }),
  },
})

export function seedDatabase() {
  Array.from(Array(5)).forEach(() => {
    mockDatabase.items.create()
  })
}

Dynamic config

Sometimes you want to create dynamic configs between multiple environments. An example. Your local environment has different endpoint than your staging environment. For that you can define a dynamic config and pass it to the integration and then use it while creating MSW interceptors.





 
 
 


export const mswIntegration = createMswIntegration(
  exampleExposition,
  {
    msw: setupServer(),
    config: {
      baseUrl: 'https://localhost:1337',
    },
  },
)

This configuration can than be accessed as the second parameter of the handler function and used to define dynamic base paths or other creative ideas 💡.


 

 




mswIntegration.createHandler(
  (_expositionValues, config) => {
    return [
      rest.get(`${config.baseUrl}/cart`, () => {
        // ... your handler logic
      }),
    ]
  })

Finish 🏁

Initialize your exposition instance and test it in your app.

exampleExposition.init()

Next steps

Checkout the Vue-Devtools integration if you want to change settings in a conformable way.

Future 💫

I'm cooking new guides for the following topics:

Other topics in my head:

  • How to send links your colleagues — 🌐 @exposition/web looking at you
  • SSR — 🚌 Sync between backend and frontend

Got feedback &&|| ideas?

Feel free to reach out if something seems weird, confusing or unnecessary complex.
I'm willing to learn and welcome any kind of feedback with open arms. 🤗

GitHubTwitter

Released under the MIT License