Skip to content

Commit

Permalink
Merge pull request #30 from yannbf/vitest-integration
Browse files Browse the repository at this point in the history
add vitest plugin
  • Loading branch information
yannbf authored Aug 16, 2024
2 parents 25be115 + e3198e3 commit e7825f6
Show file tree
Hide file tree
Showing 19 changed files with 1,039 additions and 2,414 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
export default {
env: {
browser: true,
es2021: true,
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ jobs:
- name: Install dependencies
run: yarn install

- name: Install playwright dependencies
run: yarn exec playwright install chromium --with-deps

- name: Run tests
run: |
yarn test:ci
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ junit

# production
/build
.vite-inspect

# misc
.DS_Store
Expand All @@ -30,7 +31,7 @@ yarn-error.log*

# storybook
*-storybook.log

storybook-static

# Yarn berry
/**/.yarn/*
Expand All @@ -39,4 +40,4 @@ yarn-error.log*
!/**/.yarn/plugins
!/**/.yarn/sdks
!/**/.yarn/versions
/**/.pnp.*
/**/.pnp.*
1 change: 1 addition & 0 deletions .storybook/decorators.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { GlobalStyle } from '../src/styles/GlobalStyle'
import { darkTheme, lightTheme } from '../src/styles/theme'

initialize({
quiet: true,
onUnhandledRequest: ({ url, method }) => {
const pathname = new URL(url).pathname
if (pathname.startsWith('/.netlify/functions')) {
Expand Down
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"eslint.alwaysShowStatus": true,
"eslint.validate": ["javascript", "typescript"],
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
"source.fixAll.eslint": "explicit"
},
"workbench.colorCustomizations": {
"activityBar.background": "#156b68",
Expand Down
34 changes: 21 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "course-app",
"version": "0.1.0",
"private": true,
"type": "module",
"dependencies": {
"@reduxjs/toolkit": "^2.2.3",
"axios": "^1.6.8",
Expand All @@ -22,7 +23,7 @@
"start": "vite",
"build": "tsc && vite build",
"serve": "vite preview",
"test": "vitest run",
"test": "vitest",
"test:coverage": "vitest run --coverage",
"test:ci": "vitest run",
"storybook": "storybook dev -p 6006",
Expand Down Expand Up @@ -56,19 +57,23 @@
},
"devDependencies": {
"@babel/core": "^7.14.6",
"@chromatic-com/storybook": "^1.6.1",
"@chromatic-com/storybook": "1.6.2--canary.df0b83c.0",
"@ladle/react": "^4.0.3",
"@storybook/addon-a11y": "^8.2.1",
"@storybook/addon-a11y": "^8.3.0-alpha.6",
"@storybook/addon-coverage": "^1.0.4",
"@storybook/addon-designs": "^8.0.3",
"@storybook/addon-essentials": "^8.2.1",
"@storybook/addon-interactions": "^8.2.1",
"@storybook/addon-themes": "^8.2.1",
"@storybook/blocks": "^8.2.1",
"@storybook/react": "^8.2.1",
"@storybook/react-vite": "^8.2.1",
"@storybook/test": "^8.2.1",
"@storybook/addon-essentials": "^8.3.0-alpha.6",
"@storybook/addon-interactions": "^8.3.0-alpha.6",
"@storybook/addon-themes": "^8.3.0-alpha.6",
"@storybook/blocks": "^8.3.0-alpha.6",
"@storybook/experimental-addon-vitest": "^8.3.0-alpha.6",
"@storybook/experimental-vitest-plugin": "^0.0.4",
"@storybook/manager-api": "^8.3.0-alpha.6",
"@storybook/react": "^8.3.0-alpha.6",
"@storybook/react-vite": "^8.3.0-alpha.6",
"@storybook/test": "^8.3.0-alpha.6",
"@storybook/test-runner": "^0.19.0",
"@storybook/theming": "^8.3.0-alpha.6",
"@testing-library/jest-dom": "^6.4.6",
"@testing-library/react": "^16.0.0",
"@testing-library/user-event": "^14.5.2",
Expand All @@ -83,6 +88,8 @@
"@typescript-eslint/eslint-plugin": "^7.8.0",
"@typescript-eslint/parser": "^7.8.0",
"@vitejs/plugin-react": "^4.2.1",
"@vitest/browser": "^2.0.5",
"@vitest/coverage-istanbul": "^2.0.5",
"babel-loader": "8.1.0",
"babel-plugin-istanbul": "^6.1.1",
"babel-plugin-open-source": "^1.3.3",
Expand All @@ -98,21 +105,22 @@
"eslint-plugin-react": "^7.34.1",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-storybook": "^0.8.0",
"happy-dom": "^14.12.3",
"husky": ">=6",
"istanbul": "^0.4.5",
"jest-junit": "^16.0.0",
"jsdom": "^24.0.0",
"lint-staged": ">=10",
"msw": "^2.2.2",
"msw-storybook-addon": "^2.0.2",
"playwright": "^1.46.0",
"prettier": "^3.2.5",
"react-is": "^18.3.1",
"react-test-renderer": "^18.3.1",
"storybook": "^8.2.1",
"storybook": "^8.3.0-alpha.6",
"vite": "^4.0.0",
"vite-plugin-svgr": "^4.2.0",
"vite-tsconfig-paths": "^4.3.2",
"vitest": "^2.0.2",
"vitest": "^2.0.5",
"vitest-axe": "^0.1.0",
"vitest-canvas-mock": "^0.3.3",
"wait-on": "^7.2.0"
Expand Down
2 changes: 1 addition & 1 deletion public/mockServiceWorker.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* - Please do NOT serve this file on production.
*/

const PACKAGE_VERSION = '2.3.1'
const PACKAGE_VERSION = '2.3.4'
const INTEGRITY_CHECKSUM = '26357c79639bfa20d64c0efca2a87423'
const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
const activeClientIds = new Set()
Expand Down
2 changes: 1 addition & 1 deletion src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ interface BaseApi {

export const BASE_URL = 'https://mealdrop.netlify.app/.netlify/functions/restaurants'

const isMockedEnvironment = !!import.meta.env.STORYBOOK || import.meta.env.NODE_ENV === 'test'
const isMockedEnvironment = !!import.meta.env.STORYBOOK || import.meta.env.NODE_ENV === 'test' || (globalThis as any).__vitest_browser__

const apiCache = new Map()

Expand Down
5 changes: 5 additions & 0 deletions src/components/Button/Button.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { StoryObj, Meta } from '@storybook/react'
import { expect } from '@storybook/test'

import { Button } from './Button'

Expand All @@ -25,6 +26,10 @@ export const Disabled: Story = {
args: {
disabled: true,
},
play: async ({ canvas }) => {
const button = await canvas.findByRole('button')
await expect(button).toBeDisabled()
}
}

export const Clear: Story = {
Expand Down
6 changes: 3 additions & 3 deletions src/components/Button/Button.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,23 @@ import * as stories from './Button.stories'

const { Default, Disabled } = composeStories(stories)
test('renders button with custom children', async () => {
await Default.play()
await Default.run()
expect(screen.getByText(/Button/i)).toBeInTheDocument()
// @ts-ignore TODO fix Property 'toHaveNoViolations' does not exist on type 'Assertion<AxeResults>
expect(await axe(document.body.firstChild)).toHaveNoViolations()
})

test('onclick handler is called', async () => {
const onClickSpy = vi.fn()
await Default.play({ args: { ...Default.args, onClick: onClickSpy } })
await Default.run({ args: { ...Default.args, onClick: onClickSpy } })
const buttonElement = screen.getByRole('button')
buttonElement.click()
expect(onClickSpy).toHaveBeenCalled()
})

test('onclick handler is not called when disabled', async () => {
const onClickSpy = vi.fn()
await Disabled.play({ args: { ...Disabled.args, onClick: onClickSpy } })
await Disabled.run({ args: { ...Disabled.args, onClick: onClickSpy } })
screen.getByRole('button').click()
expect(onClickSpy).not.toHaveBeenCalled()
})
Expand Down
10 changes: 5 additions & 5 deletions src/components/RestaurantCard/RestaurantCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,24 @@ const { Default, Loading, New, Closed } = composeStories(stories)

describe('RestaurantCard', () => {
test('should render correctly', async () => {
await Default.play()
await Default.run()

expect(screen.getByText('Burger Kingdom')).toBeInTheDocument()
})

test('should provide a loading skeleton', async () => {
await Loading.play()
await Loading.run()
expect(screen.getByTestId('loading')).toBeInTheDocument()
})

test('should show a "new" tag', async () => {
await New.play()
await New.run()
expect(screen.getByText('new')).toBeInTheDocument()
})

test('should not trigger onclick when restaurant is closed', async () => {
const onClickSpy = vi.fn()
await Closed.play({ args: { ...Closed.args, onClick: onClickSpy } })
await Closed.run({ args: { ...Closed.args, onClick: onClickSpy } })

// display closed message
expect(screen.getByText('This restaurant is closed.')).toBeInTheDocument()
Expand All @@ -46,7 +46,7 @@ const testCases = Object.values(composeStories(stories)).map((Story) => [

// Go through all test cases to batch test accessibility
test.each(testCases)('%s story should be accessible', async (_storyName, Story) => {
await (Story as any).play()
await (Story as any).run()
// @ts-ignore TODO fix Property 'toHaveNoViolations' does not exist on type 'Assertion<AxeResults>
expect(await axe(document.body.firstChild)).toHaveNoViolations()
})
4 changes: 4 additions & 0 deletions src/components/forms/Input.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import type { Meta, StoryObj } from '@storybook/react'

import { Input } from './Input'
import { fn } from '@storybook/test'

const meta = {
title: 'Components/Form/Input',
component: Input,
args: {
onChange: fn(),
},
parameters: {
design: {
type: 'figma',
Expand Down
23 changes: 12 additions & 11 deletions src/pages/RestaurantDetailPage/RestaurantDetailPage.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,19 @@ export const Success = {
],
},
},
}
play: async ({ canvas }) => {
const item = await canvas.findByText(/Burger Kingdom/i)
await expect(item).toBeInTheDocument()
},
} satisfies Story

export const WithModalOpen: Story = {
...Success,
play: async ({ canvasElement }) => {
const canvas = within(canvasElement)
const item = await canvas.findByText(/Cheeseburger/i)
play: async (context) => {
await Success.play(context)
const item = await context.canvas.findByText(/Cheeseburger/i)
await userEvent.click(item)
await expect(canvas.getByTestId('modal')).toBeInTheDocument()
await expect(context.canvas.getByTestId('modal')).toBeInTheDocument()
},
}

Expand All @@ -83,8 +87,7 @@ export const Loading: Story = {
],
},
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement)
play: async ({ canvas }) => {
const item = await canvas.findByText(/Looking for some food.../i)
await expect(item).toBeInTheDocument()
},
Expand All @@ -104,8 +107,7 @@ export const NotFound: Story = {
},
},
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement)
play: async ({ canvas }) => {
const item = await canvas.findByText(/We can't find this page/i)
await expect(item).toBeInTheDocument()
},
Expand All @@ -125,8 +127,7 @@ export const Error: Story = {
],
},
},
play: async ({ canvasElement, step }) => {
const canvas = within(canvasElement)
play: async ({ canvas, step }) => {
await step('Name of step', async () => {
const item = await canvas.findByText(/Something went wrong!/i)
await expect(item).toBeInTheDocument()
Expand Down
10 changes: 5 additions & 5 deletions src/pages/RestaurantDetailPage/RestaurantDetailPage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const { Success, Loading, Error, NotFound, WithModalOpen } = composeStories(stor

describe('RestaurantDetailPage', () => {
test('Should add an item to cart', async () => {
await Success.play()
await Success.run()

const foodItem = await screen.findByText(/Cheeseburger/i)
userEvent.click(foodItem)
Expand All @@ -20,19 +20,19 @@ describe('RestaurantDetailPage', () => {
expect(foodQuantity.textContent).toEqual('1')
})
test('Should display an error screen', async () => {
await Error.play()
await Error.run()
await waitFor(() => expect(screen.getByText('Something went wrong!')).toBeInTheDocument())
})
test('Should display a loading screen', async () => {
await Loading.play()
await Loading.run()
await waitFor(() => expect(screen.getByText('Looking for some food...')).toBeInTheDocument())
})
test('Should display a 404 screen', async () => {
await NotFound.play()
await NotFound.run()
await waitFor(() => expect(screen.getByText("We can't find this page")).toBeInTheDocument())
})
test('Should execute story tests', async () => {
await WithModalOpen.play()
await WithModalOpen.run()
})
})

Expand Down
28 changes: 0 additions & 28 deletions src/setupTests.ts

This file was deleted.

11 changes: 11 additions & 0 deletions storybook.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
if(!globalThis.__vitest_browser__) {
await import('vitest-canvas-mock')
const { getComputedStyle } = window
window.getComputedStyle = (elt) => getComputedStyle(elt)
window.scrollTo = () => {}
}

import { setProjectAnnotations } from '@storybook/react'
import storybookAnnotations from './.storybook/preview'

setProjectAnnotations([storybookAnnotations])
1 change: 0 additions & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ export default defineConfig({
outDir: 'build',
},
server: {
open: true,
port: 3000,
},
})
Loading

0 comments on commit e7825f6

Please sign in to comment.