Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add storybook snapshot #458

Merged
merged 15 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 12 additions & 0 deletions .storybook/jest.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { config } from '../jest.config.mjs'

export default {
...config(),
moduleNameMapper: {
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/../__mocks__/file.ts',
'\\.(styl|css|less|scss)$': '<rootDir>/../__mocks__/style.ts',
'\\.(mdx)$': '<rootDir>/../__mocks__/mdx.ts',
},
setupFilesAfterEnv: ['../jest.setup.ts', './jest.setup.ts'],
}
34 changes: 34 additions & 0 deletions .storybook/jest.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { setProjectAnnotations } from '@storybook/react'

import * as projectAnnotations from './preview'

setProjectAnnotations(projectAnnotations)
Comment on lines +1 to +5
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://storybook.js.org/docs/writing-tests/storyshots-migration-guide#import-project-level-annotations-from-storybook

If you need project-level annotations (e.g., decorators, args, styles) enabled in your ./storybook/preview.js|ts included in your tests, adjust your test set up file to import the annotations as follows:


globalThis.location = {
...globalThis.location,
search: '',
}
window.location = {
...window.location,
search: '',
}

global.IntersectionObserver = jest.fn().mockImplementation(() => ({
observe() {
return null
},
disconnect() {
return null
},
}))

global.matchMedia = jest.fn().mockImplementation(() => ({
matches: true,
media: '(max-width: 600px)',
addEventListener() {
// Do Nothing
},
removeEventListener() {
// Do Nothing
},
}))
101 changes: 101 additions & 0 deletions .storybook/storybook.test.ts
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import path from 'path'
import * as glob from 'glob'

import { composeStories } from '@storybook/react'
import renderer from 'react-test-renderer'
import { addSerializer } from 'jest-specific-snapshot'

import type { Meta, StoryFn } from '@storybook/react'

import { styleSheetSerializer } from 'jest-styled-components'
addSerializer(styleSheetSerializer)

type StoryFile = {
default: Meta
[name: string]: StoryFn | Meta
}

const compose = (
entry: StoryFile
): ReturnType<typeof composeStories<StoryFile>> => {
try {
return composeStories(entry)
} catch (e) {
throw new Error(
`There was an issue composing stories for the module: ${JSON.stringify(
entry
)}, ${e}`
)
}
}

function getAllStoryFiles() {
// Place the glob you want to match your stories files
const storyFiles = glob.sync(
path.join(__dirname, '../packages/**/*.{stories,story}.{js,jsx,mjs,ts,tsx}')
)

return storyFiles.map((filePath) => {
const storyFile = require(filePath)
return { filePath, storyFile }
})
}

// Recreate similar options to Storyshots. Place your configuration below
const options = {
suite: 'Storybook Tests',
storyKindRegex: /^.*?DontTest$/,
storyNameRegex: /UNSET/,
snapshotsDirName: '__snapshots__',
snapshotExtension: '.storyshot',
}

describe(options.suite, () => {
getAllStoryFiles().forEach(({ storyFile, filePath }) => {
const meta = storyFile.default
const title = meta.title || filePath

if (
options.storyKindRegex.test(title) ||
meta.parameters?.storyshots?.disable
) {
// Skip component tests if they are disabled
return
}

describe(title, () => {
const stories = Object.entries(compose(storyFile))
.map(([name, story]) => ({ name, story }))
.filter(({ name, story }) => {
// Implements a filtering mechanism to avoid running stories that are disabled via parameters or that match a specific regex mirroring the default behavior of Storyshots.
return (
!options.storyNameRegex.test(name) &&
!story.parameters.storyshots?.disable
)
})

if (stories.length <= 0) {
throw new Error(
`No stories found for this module: ${title}. Make sure there is at least one valid story for this module, without a disable parameter, or add parameters.storyshots.disable in the default export of this file.`
)
}

stories.forEach(({ name, story }) => {
// Instead of not running the test, you can create logic to skip it, flagging it accordingly in the test results.
const testFn = story.parameters.storyshots?.skip ? it.skip : it
const snapshotPath = path.join(
path.dirname(filePath),
'__snapshots__',
`${path.basename(filePath, '.tsx')}.storyshot`
)

testFn(name, async () => {
const mounted = renderer.create(story()).toJSON()
// Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot.
await new Promise((resolve) => setTimeout(resolve, 1))
expect(mounted).toMatchSpecificSnapshot(snapshotPath)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

story があるディレクトリに snapshots を作成し個別に snapshot を生成する

これしかなかったのでこれを使用したが他にいいものがあれたら変えたい
https://github.com/igor-dv/jest-specific-snapshot

})
})
})
})
})
2 changes: 1 addition & 1 deletion jest.config.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** @type { import('@jest/types').Config.InitialOptions } */
const rootConfig = {
projects: ['packages/*'],
projects: ['packages/*', '.storybook'],
passWithNoTests: true,
}

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
"glob": "^7.2.0",
"husky": "^4.3.8",
"jest": "^27.4.7",
"jest-specific-snapshot": "^8.0.0",
"jsdom": "^19.0.0",
"lerna": "^6.6.2",
"npm-run-all": "^4.1.5",
Expand Down
6 changes: 6 additions & 0 deletions packages/icons/src/PixivIcon.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ export default {
},
},
},

parameters: {
storyshots: {
disable: true,
},
},
}

const groupedIcons = KNOWN_ICON_FILES.reduce<Record<string, KnownIconFile[]>>(
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"**/.*.cjs",
"**/.*.js",
"storyshots.*",
"__mocks__/*.ts"
"__mocks__/*.ts",
".storybook"
],
"exclude": ["docs"]
}
1 change: 1 addition & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -12225,6 +12225,7 @@ __metadata:
glob: ^7.2.0
husky: ^4.3.8
jest: ^27.4.7
jest-specific-snapshot: ^8.0.0
jsdom: ^19.0.0
lerna: ^6.6.2
npm-run-all: ^4.1.5
Expand Down