storybook-addon-vis 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,6 @@ import { PixelmatchOptions } from 'pixelmatch';
2
2
  import { CDPSession, BrowserCommands, BrowserPage, Platform } from '@vitest/browser/context';
3
3
  import { SerializedConfig } from 'vitest';
4
4
  import { AsyncExpectationResult } from '@vitest/expect';
5
- import { StoryContext } from '@storybook/react';
6
5
 
7
6
  type ImageSnapshotOptions = {
8
7
  element?: Element;
@@ -75,8 +74,17 @@ declare const server: {
75
74
 
76
75
  declare function toMatchImageSnapshot(actual: any, options?: MatchImageSnapshotOptions | undefined): AsyncExpectationResult;
77
76
 
77
+ /**
78
+ * Determine should snapshot be taken.
79
+ *
80
+ * not story: false
81
+ * no `snapshot` tag: false
82
+ * disabled by `!snapshot` tag: false
83
+ */
78
84
  declare function shouldTakeSnapshot(ctx: {
79
- story?: StoryContext;
85
+ story?: {
86
+ tags: string[];
87
+ };
80
88
  }): boolean;
81
89
 
82
90
  declare function configureSnapshotBeforeAll(suite: {
@@ -1,6 +1,6 @@
1
- import {basename,join,dirname,relative}from'pathe';import {getByAltText,getByRole,getByTestId,getByText,getByTitle,getByPlaceholderText,getByLabelText}from'@storybook/test';import C from'dedent';import A from'pixelmatch';var s={name:"",testFilepath:"",taskName:"",snapshot:{}};var g=Symbol.for("storybook-addon-vis/imageSnapshot"),f=Symbol.for("storybook-addon-vis/imageSnapshotStub");function l(t){return new Promise((e,a)=>{let o=new Image;o.src=`data:image/png;base64,${t}`,o.onload=()=>{let r=document.createElement("canvas");r.width=o.width,r.height=o.height;let n=r.getContext("2d");n.drawImage(o,0,0),e(n.getImageData(0,0,r.width,r.height));},o.onerror=()=>{a(new Error("Failed to load image"));};})}async function w(t){let e=document.createElement("canvas");return e.width=t.width,e.height=t.height,e.getContext("2d").putImageData(t,0,0),new Promise(o=>{e.toBlob(r=>{let n=new FileReader;n.onload=()=>{o(n.result);},n.readAsDataURL(r);});})}function u(t){return !!t&&t.type===g}function I(t){if(!u(t))throw new Error("Expected subject to be an image snapshot")}function D(t){return `${t.replace(/[^a-z0-9]/gi,"-").toLowerCase()}`}async function P(t){let e=basename(s.testFilepath),a=`${D(s.taskName)}-${s.snapshot[s.taskName].index++}.png`,o=join(s.baselineDir,e,a),r=join(s.resultDir,e,a),n=join(s.diffDir,e,a),i=await this.screenshot({base64:!0,path:r,element:t?.element}),m=await l(i.base64);return {type:g,testfilename:e,snapshotFilename:a,baselinePath:o,resultPath:r,diffPath:n,base64:i.base64,image:m}}var h;globalThis.__vitest_browser__&&(h=await import('@vitest/browser/context'));function nt(){return h?.cdp()??{}}var d=new Proxy({},{get(t,e){return t[e]??(h?.commands)[e]}}),E=new Proxy({getByAltText:getByAltText,getByRole:getByRole,getByTestId:getByTestId,getByText:getByText,getByTitle:getByTitle,getByPlaceholder:getByPlaceholderText,getByLabelText:getByLabelText},{get(t,e){return t[e]??h?.page?(h?.page)[e]:()=>{if(e==="imageSnapshot")return {type:f};console.info(`\`page.${e.toString()}\` does not exist when running in browser`);}}}),it=new Proxy({},{get(t,e){return t[e]??(h?.server)[e]}});E.extend({imageSnapshot:P});async function dt(t,e){let a=await t;if(a?.type===f)return b;if(!u(a)){if(a?.path&&a?.base64)return {pass:!1,actual:t,message:()=>"`toMatchImageSnapshot()` expects the subject to be the result of `page.imageSnapshot()`, but seems like you are using `page.screenshot()`?"};if(typeof a!="object")return {pass:!1,actual:t,message:()=>`\`toMatchImageSnapshot()\` expects the subject to be an element, locator, or result of \`page.imageSnapshot()\`, but got: \`${t}\``}}I(a);let o=await R(a.baselinePath);if(!o)return await d.copyFile(a.resultPath,a.baselinePath),b;let r=await l(o),[n,i]=M(a.image,r),{pass:m,diffAmount:p,diffImage:c}=U(i,n,e);return m?b:(await z(`${a.diffPath}`,c),{pass:!1,actual:t,message:()=>C`${e?.failureThreshold?e?.failureThresholdType==="percent"?`Expected image to match within ${e.failureThreshold}% but was differ by ${p}%.`:`Expected image to match within ${e.failureThreshold} pixels but was differ by ${p} pixels.`:`Expected image to match but was differ by ${e?.failureThresholdType==="percent"?`${p}%`:`${p} pixels`}.`}
1
+ import {basename,join,dirname,relative}from'pathe';import {getByAltText,getByRole,getByTestId,getByText,getByTitle,getByPlaceholderText,getByLabelText}from'@storybook/test';import A from'dedent';import C from'pixelmatch';var s={name:"",testFilepath:"",taskName:"",snapshot:{}};var g=Symbol.for("storybook-addon-vis/imageSnapshot"),f=Symbol.for("storybook-addon-vis/imageSnapshotStub");function l(t){return new Promise((e,a)=>{let o=new Image;o.src=`data:image/png;base64,${t}`,o.onload=()=>{let n=document.createElement("canvas");n.width=o.width,n.height=o.height;let r=n.getContext("2d");r.drawImage(o,0,0),e(r.getImageData(0,0,n.width,n.height));},o.onerror=()=>{a(new Error("Failed to load image"));};})}async function S(t){let e=document.createElement("canvas");return e.width=t.width,e.height=t.height,e.getContext("2d").putImageData(t,0,0),new Promise(o=>{e.toBlob(n=>{let r=new FileReader;r.onload=()=>{o(r.result);},r.readAsDataURL(n);});})}function u(t){return !!t&&t.type===g}function I(t){if(!u(t))throw new Error("Expected subject to be an image snapshot")}function D(t){return `${t.replace(/[^a-z0-9]/gi,"-").toLowerCase()}`}async function P(t){let e=basename(s.testFilepath),a=`${D(s.taskName)}-${s.snapshot[s.taskName].index++}.png`,o=join(s.baselineDir,e,a),n=join(s.resultDir,e,a),r=join(s.diffDir,e,a),i=await this.screenshot({base64:!0,path:n,element:t?.element}),m=await l(i.base64);return {type:g,testfilename:e,snapshotFilename:a,baselinePath:o,resultPath:n,diffPath:r,base64:i.base64,image:m}}var h;globalThis.__vitest_browser__&&(h=await import('@vitest/browser/context'));function rt(){return h?.cdp()??{}}var d=new Proxy({},{get(t,e){return t[e]??(h?.commands)[e]}}),E=new Proxy({getByAltText:getByAltText,getByRole:getByRole,getByTestId:getByTestId,getByText:getByText,getByTitle:getByTitle,getByPlaceholder:getByPlaceholderText,getByLabelText:getByLabelText},{get(t,e){return t[e]??h?.page?(h?.page)[e]:()=>{if(e==="imageSnapshot")return {type:f};console.info(`\`page.${e.toString()}\` does not exist when running in browser`);}}}),it=new Proxy({},{get(t,e){return t[e]??(h?.server)[e]}});E.extend({imageSnapshot:P});async function dt(t,e){let a=await t;if(a?.type===f)return b;if(!u(a)){if(a?.path&&a?.base64)return {pass:!1,actual:t,message:()=>"`toMatchImageSnapshot()` expects the subject to be the result of `page.imageSnapshot()`, but seems like you are using `page.screenshot()`?"};if(typeof a!="object")return {pass:!1,actual:t,message:()=>`\`toMatchImageSnapshot()\` expects the subject to be an element, locator, or result of \`page.imageSnapshot()\`, but got: \`${t}\``}}I(a);let o=await R(a.baselinePath);if(!o)return await d.copyFile(a.resultPath,a.baselinePath),b;let n=await l(o),[r,i]=M(a.image,n),{pass:m,diffAmount:p,diffImage:c}=U(i,r,e);return m?b:(await z(`${a.diffPath}`,c),{pass:!1,actual:t,message:()=>A`${e?.failureThreshold?e?.failureThresholdType==="percent"?`Expected image to match within ${e.failureThreshold}% but was differ by ${p}%.`:`Expected image to match within ${e.failureThreshold} pixels but was differ by ${p} pixels.`:`Expected image to match but was differ by ${e?.failureThresholdType==="percent"?`${p}%`:`${p} pixels`}.`}
2
2
 
3
3
  Expected: '${a.baselinePath}'
4
4
  Actual: '${a.resultPath}'
5
- Difference: '${a.diffPath}'`})}var b={pass:!0,message:()=>""};function R(t){return d.readFile(t,{encoding:"base64"}).catch(()=>{})}async function z(t,e){let a=(await w(e)).split(",")[1];return d.writeFile(t,a,"base64url")}function M(t,e){if(O(t,e))return [t,e];let a=N(t,e),o=L(a);return [o(t),o(e)]}function N(t,e){let a=Math.max(t.width,e.width),o=Math.max(t.height,e.height);return {width:a,height:o}}function O(t,e){return t.width===e.width&&t.height===e.height}var L=({width:t,height:e})=>a=>{if(a.width===t&&a.height===e)return a;let o=(n,i)=>i<=a.height&&n<=a.width,r=new ImageData(t,e,{colorSpace:a.colorSpace});for(let n=0;n<e;n++)for(let i=0;i<t;i++){let m=t*n+i<<2;if(o(i,n)){let p=a.width*n+i<<2;r.data[m]=a.data[p],r.data[m+1]=a.data[p+1],r.data[m+2]=a.data[p+2],r.data[m+3]=a.data[p+3];}else r.data[m]=0,r.data[m+1]=0,r.data[m+2]=0,r.data[m+3]=64;}return r};function U(t,e,{failureThreshold:a=0,failureThresholdType:o="pixel",diffOptions:r}={}){let{width:n,height:i}=e,m=new ImageData(n,i),p=A(e.data,t.data,m.data,n,i,r),c=q({failureThresholdType:o,width:n,height:i},p);return {pass:c<=a,diffAmount:c,diffImage:m}}function q({failureThresholdType:t,width:e,height:a},o){switch(t){case"pixel":return o;case"percent":return o/(e*a)*100;default:throw new Error(`Invalid failureThresholdType: ${t}`)}}function yt(t){return t.story?.tags?t.story.tags.lastIndexOf("!snapshot")<t.story.tags.lastIndexOf("snapshot"):!1}function wt(t){s.name=t.name,s.testFilepath=t.file.filepath,s.testFilename=basename(s.testFilepath),s.projectDir=s.testFilepath.slice(0,-s.name.length);let e=dirname(s.testFilepath);s.baselineDir=relative(e,join(s.projectDir,"__snapshots__")),s.resultDir=relative(e,join(s.projectDir,"__snapshots__","__results__")),s.diffDir=relative(e,join(s.projectDir,"__snapshots__","__diff_output__"));}function It(t){s.taskName=t.task.name,s.snapshot[s.taskName]=s.snapshot[s.taskName]??{index:1};}export{nt as cdp,d as commands,wt as configureSnapshotBeforeAll,It as configureSnapshotBeforeEach,E as page,it as server,yt as shouldTakeSnapshot,dt as toMatchImageSnapshot};//# sourceMappingURL=vitest-setup.js.map
5
+ Difference: '${a.diffPath}'`})}var b={pass:!0,message:()=>""};function R(t){return d.readFile(t,{encoding:"base64"}).catch(()=>{})}async function z(t,e){let a=(await S(e)).split(",")[1];return d.writeFile(t,a,"base64url")}function M(t,e){if(O(t,e))return [t,e];let a=N(t,e),o=L(a);return [o(t),o(e)]}function N(t,e){let a=Math.max(t.width,e.width),o=Math.max(t.height,e.height);return {width:a,height:o}}function O(t,e){return t.width===e.width&&t.height===e.height}var L=({width:t,height:e})=>a=>{if(a.width===t&&a.height===e)return a;let o=(r,i)=>i<=a.height&&r<=a.width,n=new ImageData(t,e,{colorSpace:a.colorSpace});for(let r=0;r<e;r++)for(let i=0;i<t;i++){let m=t*r+i<<2;if(o(i,r)){let p=a.width*r+i<<2;n.data[m]=a.data[p],n.data[m+1]=a.data[p+1],n.data[m+2]=a.data[p+2],n.data[m+3]=a.data[p+3];}else n.data[m]=0,n.data[m+1]=0,n.data[m+2]=0,n.data[m+3]=64;}return n};function U(t,e,{failureThreshold:a=0,failureThresholdType:o="pixel",diffOptions:n}={}){let{width:r,height:i}=e,m=new ImageData(r,i),p=C(e.data,t.data,m.data,r,i,n),c=q({failureThresholdType:o,width:r,height:i},p);return {pass:c<=a,diffAmount:c,diffImage:m}}function q({failureThresholdType:t,width:e,height:a},o){switch(t){case"pixel":return o;case"percent":return o/(e*a)*100;default:throw new Error(`Invalid failureThresholdType: ${t}`)}}function yt(t){return t.story?.tags?t.story.tags.lastIndexOf("!snapshot")<t.story.tags.lastIndexOf("snapshot"):!1}function St(t){s.name=t.name,s.testFilepath=t.file.filepath,s.testFilename=basename(s.testFilepath),s.projectDir=s.testFilepath.slice(0,-s.name.length);let e=dirname(s.testFilepath);s.baselineDir=relative(e,join(s.projectDir,"__snapshots__")),s.resultDir=relative(e,join(s.projectDir,"__snapshots__","__results__")),s.diffDir=relative(e,join(s.projectDir,"__snapshots__","__diff_output__"));}function It(t){s.taskName=t.task.name,s.snapshot[s.taskName]=s.snapshot[s.taskName]??{index:1};}export{rt as cdp,d as commands,St as configureSnapshotBeforeAll,It as configureSnapshotBeforeEach,E as page,it as server,yt as shouldTakeSnapshot,dt as toMatchImageSnapshot};//# sourceMappingURL=vitest-setup.js.map
6
6
  //# sourceMappingURL=vitest-setup.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/state.ts","../src/@vitest/browser/constants.ts","../src/image_data.ts","../src/@vitest/browser/image_snapshot.logic.ts","../src/@vitest/browser/page.image_snapshot.ts","../src/@vitest/browser/context.ts","../src/expect.to_match_image_snapshot.ts","../src/tags.ts","../src/vitest-setup.ts"],"names":["state","imageSnapshotSymbol","imageSnapshotStubSymbol","toImageData","base64","resolve","reject","img","canvas","ctx","toDataURL","imageData","blob","reader","isImageSnapshot","subject","assertImageSnapshot","toSnapshotId","taskName","imageSnapshot","options","testfilename","basename","snapshotFilename","baselinePath","join","resultPath","diffPath","screenshot","image","cdp","commands","target","prop","page","getByAltText","getByRole","getByTestId","getByText","getByTitle","getByPlaceholderText","getByLabelText","server","toMatchImageSnapshot","actual","success","baseline","tryReadSnapshot","originalImage","resultImage","baselineImage","alignImagesToSameSize","pass","diffAmount","diffImage","compareImage","writeSnapshot","dedent","path","content","image1","image2","isSameSize","size","getMaxSize","resize","createImageResizer","width","height","inArea","x","y","result","idx","old","failureThreshold","failureThresholdType","diffOptions","pixelDiff","pixelmatch","toThresholdUnit","shouldTakeSnapshot","configureSnapshotBeforeAll","suite","currentDir","dirname","relative","configureSnapshotBeforeEach"],"mappings":"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","file":"vitest-setup.js","sourcesContent":["export const state = {\n\tname: '',\n\ttestFilepath: '',\n\ttaskName: '',\n\tsnapshot: {},\n} as {\n\tname: string\n\ttestFilepath: string\n\ttestFilename: string\n\tprojectDir: string\n\tbaselineDir: string\n\tresultDir: string\n\tdiffDir: string\n\ttaskName: string\n\tsnapshot: Record<string, { index: number }>\n}\n","export const imageSnapshotSymbol = Symbol.for('storybook-addon-vis/imageSnapshot')\n\nexport const imageSnapshotStubSymbol = Symbol.for('storybook-addon-vis/imageSnapshotStub')\n","export function toImageData(base64: string) {\n\treturn new Promise<ImageData>((resolve, reject) => {\n\t\tconst img = new Image()\n\t\timg.src = `data:image/png;base64,${base64}`\n\n\t\timg.onload = () => {\n\t\t\tconst canvas = document.createElement('canvas')\n\t\t\tcanvas.width = img.width\n\t\t\tcanvas.height = img.height\n\t\t\tconst ctx = canvas.getContext('2d')!\n\t\t\tctx.drawImage(img, 0, 0)\n\t\t\tresolve(ctx.getImageData(0, 0, canvas.width, canvas.height))\n\t\t}\n\n\t\timg.onerror = () => {\n\t\t\treject(new Error('Failed to load image'))\n\t\t}\n\t})\n}\n\nexport async function toDataURL(imageData: ImageData) {\n\tconst canvas = document.createElement('canvas')\n\tcanvas.width = imageData.width\n\tcanvas.height = imageData.height\n\tconst ctx = canvas.getContext('2d')!\n\tctx.putImageData(imageData, 0, 0)\n\treturn new Promise<string>((resolve) => {\n\t\tcanvas.toBlob((blob) => {\n\t\t\tconst reader = new FileReader()\n\t\t\treader.onload = () => {\n\t\t\t\tresolve(reader.result as string)\n\t\t\t}\n\t\t\treader.readAsDataURL(blob!)\n\t\t})\n\t})\n}\n","import { imageSnapshotSymbol } from './constants.js'\nimport type { ImageSnapshot } from './types.js'\n\nexport function isImageSnapshot(subject: any): subject is ImageSnapshot {\n\treturn !!subject && subject.type === imageSnapshotSymbol\n}\n\nexport function assertImageSnapshot(subject: any): asserts subject is ImageSnapshot {\n\tif (!isImageSnapshot(subject)) {\n\t\tthrow new Error('Expected subject to be an image snapshot')\n\t}\n}\n\nexport function toSnapshotId(taskName: string) {\n\treturn `${taskName.replace(/[^a-z0-9]/gi, '-').toLowerCase()}`\n}\n","import type { BrowserPage } from '@vitest/browser/context'\nimport { basename, join } from 'pathe'\nimport { toImageData } from '../../image_data.js'\nimport { state } from '../../state.js'\nimport { imageSnapshotSymbol } from './constants.js'\nimport { toSnapshotId } from './image_snapshot.logic.js'\nimport type { ImageSnapshot, ImageSnapshotOptions } from './types.js'\n\nexport async function imageSnapshot(this: BrowserPage, options?: ImageSnapshotOptions): Promise<ImageSnapshot> {\n\t// const rootDir = server.config.root\n\tconst testfilename = basename(state.testFilepath)\n\tconst snapshotFilename = `${toSnapshotId(state.taskName)}-${state.snapshot[state.taskName]!.index++}.png`\n\tconst baselinePath = join(state.baselineDir, testfilename, snapshotFilename)\n\tconst resultPath = join(state.resultDir, testfilename, snapshotFilename)\n\tconst diffPath = join(state.diffDir, testfilename, snapshotFilename)\n\tconst screenshot = await this.screenshot({\n\t\tbase64: true,\n\t\tpath: resultPath,\n\t\telement: options?.element,\n\t})\n\tconst image = await toImageData(screenshot.base64)\n\n\treturn {\n\t\ttype: imageSnapshotSymbol,\n\t\t// rootDir,\n\t\ttestfilename,\n\t\tsnapshotFilename,\n\t\tbaselinePath,\n\t\tresultPath,\n\t\tdiffPath,\n\t\tbase64: screenshot.base64,\n\t\timage,\n\t}\n}\n","import {\n\tgetByAltText,\n\tgetByLabelText,\n\tgetByPlaceholderText,\n\tgetByRole,\n\tgetByTestId,\n\tgetByText,\n\tgetByTitle,\n} from '@storybook/test'\nimport type { BrowserCommands, BrowserPage, CDPSession, Platform } from '@vitest/browser/context'\nimport type { SerializedConfig } from 'vitest'\nimport { imageSnapshotStubSymbol } from './constants'\nimport { imageSnapshot } from './page.image_snapshot'\n\nlet ctx: Awaited<typeof import('@vitest/browser/context')>\n\nif ((globalThis as any).__vitest_browser__) {\n\tctx = await import('@vitest/browser/context')\n\t// import('@vitest/browser/context').then((m) => (ctx = m))\n}\n\n// TODO: stub the functions within the `CDPSession`\n// when we better understands the use cases\nexport function cdp(): CDPSession {\n\treturn ctx?.cdp() ?? {}\n}\n\nexport const commands = new Proxy<BrowserCommands>({} as any, {\n\tget(target, prop) {\n\t\treturn (target as any)[prop] ?? (ctx?.commands as any)[prop]\n\t},\n})\n\nexport const page = new Proxy<BrowserPage>(\n\t{\n\t\tgetByAltText,\n\t\tgetByRole,\n\t\tgetByTestId,\n\t\tgetByText,\n\t\tgetByTitle,\n\t\tgetByPlaceholder: getByPlaceholderText,\n\t\tgetByLabelText,\n\t} as any,\n\t{\n\t\tget(target, prop) {\n\t\t\treturn ((target as any)[prop] ?? ctx?.page)\n\t\t\t\t? (ctx?.page as any)[prop]\n\t\t\t\t: () => {\n\t\t\t\t\t\tif (prop === 'imageSnapshot') {\n\t\t\t\t\t\t\treturn { type: imageSnapshotStubSymbol }\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconsole.info(`\\`page.${prop.toString()}\\` does not exist when running in browser`)\n\t\t\t\t\t}\n\t\t},\n\t},\n)\n\nexport const server = new Proxy<{\n\t/**\n\t * Platform the Vitest server is running on.\n\t * The same as calling `process.platform` on the server.\n\t */\n\tplatform: Platform\n\t/**\n\t * Runtime version of the Vitest server.\n\t * The same as calling `process.version` on the server.\n\t */\n\tversion: string\n\t/**\n\t * Name of the browser provider.\n\t */\n\tprovider: string\n\t/**\n\t * Name of the current browser.\n\t */\n\tbrowser: string\n\t/**\n\t * Available commands for the browser.\n\t * @see {@link https://vitest.dev/guide/browser/commands}\n\t */\n\tcommands: BrowserCommands\n\t/**\n\t * Serialized test config.\n\t */\n\tconfig: SerializedConfig\n}>({} as any, {\n\tget(target, prop) {\n\t\treturn (target as any)[prop] ?? (ctx?.server as any)[prop]\n\t},\n})\n\npage.extend({ imageSnapshot })\n","import type { AsyncExpectationResult } from '@vitest/expect'\nimport dedent from 'dedent'\nimport pixelmatch from 'pixelmatch'\nimport { imageSnapshotStubSymbol } from './@vitest/browser/constants.js'\nimport { commands } from './@vitest/browser/context.js'\nimport { assertImageSnapshot, isImageSnapshot } from './@vitest/browser/image_snapshot.logic.js'\nimport type { MatchImageSnapshotOptions } from './@vitest/browser/types.js'\nimport { toDataURL, toImageData } from './image_data.js'\n\nexport async function toMatchImageSnapshot(\n\tactual: any,\n\toptions?: MatchImageSnapshotOptions | undefined,\n): AsyncExpectationResult {\n\tconst subject = await actual\n\tif (subject?.type === imageSnapshotStubSymbol) {\n\t\treturn success\n\t}\n\tif (!isImageSnapshot(subject)) {\n\t\tif (subject?.path && subject?.base64) {\n\t\t\treturn {\n\t\t\t\tpass: false,\n\t\t\t\tactual,\n\t\t\t\tmessage: () =>\n\t\t\t\t\t'`toMatchImageSnapshot()` expects the subject to be the result of `page.imageSnapshot()`, but seems like you are using `page.screenshot()`?',\n\t\t\t}\n\t\t}\n\n\t\tif (typeof subject !== 'object') {\n\t\t\treturn {\n\t\t\t\tpass: false,\n\t\t\t\tactual,\n\t\t\t\tmessage: () =>\n\t\t\t\t\t`\\`toMatchImageSnapshot()\\` expects the subject to be an element, locator, or result of \\`page.imageSnapshot()\\`, but got: \\`${actual}\\``,\n\t\t\t}\n\t\t}\n\t\t// subject = await page.imageSnapshot({ element: actual })\n\t}\n\tassertImageSnapshot(subject)\n\tconst baseline = await tryReadSnapshot(subject.baselinePath)\n\tif (!baseline) {\n\t\tawait commands.copyFile(subject.resultPath, subject.baselinePath)\n\t\treturn success\n\t}\n\n\tconst originalImage = await toImageData(baseline)\n\tconst [resultImage, baselineImage] = alignImagesToSameSize(subject.image, originalImage)\n\n\tconst { pass, diffAmount, diffImage } = compareImage(baselineImage, resultImage, options)\n\tif (!pass) {\n\t\tawait writeSnapshot(`${subject.diffPath}`, diffImage)\n\t\treturn {\n\t\t\tpass: false,\n\t\t\tactual,\n\t\t\tmessage: () =>\n\t\t\t\tdedent`${\n\t\t\t\t\toptions?.failureThreshold\n\t\t\t\t\t\t? options?.failureThresholdType === 'percent'\n\t\t\t\t\t\t\t? `Expected image to match within ${options.failureThreshold}% but was differ by ${diffAmount}%.`\n\t\t\t\t\t\t\t: `Expected image to match within ${options.failureThreshold} pixels but was differ by ${diffAmount} pixels.`\n\t\t\t\t\t\t: `Expected image to match but was differ by ${options?.failureThresholdType === 'percent' ? `${diffAmount}%` : `${diffAmount} pixels`}.`\n\t\t\t\t}\n\n\t\t\tExpected: '${subject.baselinePath}'\n\t\t\tActual: '${subject.resultPath}'\n\t\t\tDifference: '${subject.diffPath}'`,\n\t\t}\n\t}\n\treturn success\n}\n\nconst success = {\n\tpass: true,\n\tmessage: () => '',\n}\n\nfunction tryReadSnapshot(path: string): Promise<string | undefined> {\n\treturn commands.readFile(path, { encoding: 'base64' }).catch(() => undefined)\n}\nasync function writeSnapshot(path: string, image: ImageData) {\n\tconst content = (await toDataURL(image)).split(',')[1]!\n\treturn commands.writeFile(path, content, 'base64url')\n}\n\nfunction alignImagesToSameSize(image1: ImageData, image2: ImageData): [image1: ImageData, image2: ImageData] {\n\tif (isSameSize(image1, image2)) {\n\t\treturn [image1, image2]\n\t}\n\tconst size = getMaxSize(image1, image2)\n\tconst resize = createImageResizer(size)\n\treturn [resize(image1), resize(image2)]\n}\n\nfunction getMaxSize(image1: ImageData, image2: ImageData) {\n\tconst width = Math.max(image1.width, image2.width)\n\tconst height = Math.max(image1.height, image2.height)\n\treturn { width, height }\n}\n\nfunction isSameSize(image1: ImageData, image2: ImageData) {\n\treturn image1.width === image2.width && image1.height === image2.height\n}\n\nconst createImageResizer =\n\t({ width, height }: { width: number; height: number }) =>\n\t(image: ImageData) => {\n\t\tif (image.width === width && image.height === height) {\n\t\t\treturn image\n\t\t}\n\t\tconst inArea = (x: number, y: number) => y <= image.height && x <= image.width\n\t\tconst result = new ImageData(width, height, { colorSpace: image.colorSpace })\n\n\t\tfor (let y = 0; y < height; y++) {\n\t\t\tfor (let x = 0; x < width; x++) {\n\t\t\t\tconst idx = (width * y + x) << 2\n\t\t\t\tif (inArea(x, y)) {\n\t\t\t\t\tconst old = (image.width * y + x) << 2\n\t\t\t\t\tresult.data[idx] = image.data[old]\n\t\t\t\t\tresult.data[idx + 1] = image.data[old + 1]\n\t\t\t\t\tresult.data[idx + 2] = image.data[old + 2]\n\t\t\t\t\tresult.data[idx + 3] = image.data[old + 3]\n\t\t\t\t} else {\n\t\t\t\t\tresult.data[idx] = 0\n\t\t\t\t\tresult.data[idx + 1] = 0\n\t\t\t\t\tresult.data[idx + 2] = 0\n\t\t\t\t\tresult.data[idx + 3] = 64\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\nfunction compareImage(\n\tbaselineImage: ImageData,\n\tresultImage: ImageData,\n\t{ failureThreshold = 0, failureThresholdType = 'pixel', diffOptions }: MatchImageSnapshotOptions = {},\n) {\n\tconst { width, height } = resultImage\n\tconst diffImage = new ImageData(width, height)\n\n\tconst pixelDiff = pixelmatch(resultImage.data, baselineImage.data, diffImage.data, width, height, diffOptions)\n\tconst diffAmount = toThresholdUnit({ failureThresholdType, width, height }, pixelDiff)\n\n\treturn {\n\t\tpass: diffAmount <= failureThreshold,\n\t\tdiffAmount,\n\t\tdiffImage,\n\t}\n}\n\nfunction toThresholdUnit(\n\t{ failureThresholdType, width, height }: { failureThresholdType: 'pixel' | 'percent'; width: number; height: number },\n\tpixelDiff: number,\n): number {\n\tswitch (failureThresholdType) {\n\t\tcase 'pixel':\n\t\t\treturn pixelDiff\n\t\tcase 'percent':\n\t\t\treturn (pixelDiff / (width * height)) * 100\n\t\tdefault:\n\t\t\tthrow new Error(`Invalid failureThresholdType: ${failureThresholdType}`)\n\t}\n}\n","import type { StoryContext } from '@storybook/react'\n\nexport function shouldTakeSnapshot(ctx: { story?: StoryContext }) {\n\tif (!ctx.story?.tags) return false\n\treturn ctx.story.tags.lastIndexOf('!snapshot') < ctx.story.tags.lastIndexOf('snapshot')\n}\n","import { basename, dirname, join, relative } from 'pathe'\nimport './augment.js'\nimport { state } from './state.js'\n\nexport * from './@vitest/browser/context.js'\nexport * from './expect.to_match_image_snapshot.js'\nexport * from './tags.js'\n\nexport function configureSnapshotBeforeAll(suite: { file: { filepath: string }; name: string }) {\n\tstate.name = suite.name\n\tstate.testFilepath = suite.file.filepath\n\tstate.testFilename = basename(state.testFilepath)\n\tstate.projectDir = state.testFilepath.slice(0, -state.name.length)\n\tconst currentDir = dirname(state.testFilepath)\n\tstate.baselineDir = relative(currentDir, join(state.projectDir, '__snapshots__'))\n\tstate.resultDir = relative(currentDir, join(state.projectDir, '__snapshots__', '__results__'))\n\tstate.diffDir = relative(currentDir, join(state.projectDir, '__snapshots__', '__diff_output__'))\n}\n\nexport function configureSnapshotBeforeEach(ctx: { task: { name: string } }) {\n\tstate.taskName = ctx.task.name\n\tstate.snapshot[state.taskName] = state.snapshot[state.taskName] ?? { index: 1 }\n}\n"]}
1
+ {"version":3,"sources":["../src/state.ts","../src/@vitest/browser/constants.ts","../src/image_data.ts","../src/@vitest/browser/image_snapshot.logic.ts","../src/@vitest/browser/page.image_snapshot.ts","../src/@vitest/browser/context.ts","../src/expect.to_match_image_snapshot.ts","../src/tags.ts","../src/vitest-setup.ts"],"names":["state","imageSnapshotSymbol","imageSnapshotStubSymbol","toImageData","base64","resolve","reject","img","canvas","ctx","toDataURL","imageData","blob","reader","isImageSnapshot","subject","assertImageSnapshot","toSnapshotId","taskName","imageSnapshot","options","testfilename","basename","snapshotFilename","baselinePath","join","resultPath","diffPath","screenshot","image","cdp","commands","target","prop","page","getByAltText","getByRole","getByTestId","getByText","getByTitle","getByPlaceholderText","getByLabelText","server","toMatchImageSnapshot","actual","success","baseline","tryReadSnapshot","originalImage","resultImage","baselineImage","alignImagesToSameSize","pass","diffAmount","diffImage","compareImage","writeSnapshot","dedent","path","content","image1","image2","isSameSize","size","getMaxSize","resize","createImageResizer","width","height","inArea","x","y","result","idx","old","failureThreshold","failureThresholdType","diffOptions","pixelDiff","pixelmatch","toThresholdUnit","shouldTakeSnapshot","configureSnapshotBeforeAll","suite","currentDir","dirname","relative","configureSnapshotBeforeEach"],"mappings":"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","file":"vitest-setup.js","sourcesContent":["export const state = {\n\tname: '',\n\ttestFilepath: '',\n\ttaskName: '',\n\tsnapshot: {},\n} as {\n\tname: string\n\ttestFilepath: string\n\ttestFilename: string\n\tprojectDir: string\n\tbaselineDir: string\n\tresultDir: string\n\tdiffDir: string\n\ttaskName: string\n\tsnapshot: Record<string, { index: number }>\n}\n","export const imageSnapshotSymbol = Symbol.for('storybook-addon-vis/imageSnapshot')\n\nexport const imageSnapshotStubSymbol = Symbol.for('storybook-addon-vis/imageSnapshotStub')\n","export function toImageData(base64: string) {\n\treturn new Promise<ImageData>((resolve, reject) => {\n\t\tconst img = new Image()\n\t\timg.src = `data:image/png;base64,${base64}`\n\n\t\timg.onload = () => {\n\t\t\tconst canvas = document.createElement('canvas')\n\t\t\tcanvas.width = img.width\n\t\t\tcanvas.height = img.height\n\t\t\tconst ctx = canvas.getContext('2d')!\n\t\t\tctx.drawImage(img, 0, 0)\n\t\t\tresolve(ctx.getImageData(0, 0, canvas.width, canvas.height))\n\t\t}\n\n\t\timg.onerror = () => {\n\t\t\treject(new Error('Failed to load image'))\n\t\t}\n\t})\n}\n\nexport async function toDataURL(imageData: ImageData) {\n\tconst canvas = document.createElement('canvas')\n\tcanvas.width = imageData.width\n\tcanvas.height = imageData.height\n\tconst ctx = canvas.getContext('2d')!\n\tctx.putImageData(imageData, 0, 0)\n\treturn new Promise<string>((resolve) => {\n\t\tcanvas.toBlob((blob) => {\n\t\t\tconst reader = new FileReader()\n\t\t\treader.onload = () => {\n\t\t\t\tresolve(reader.result as string)\n\t\t\t}\n\t\t\treader.readAsDataURL(blob!)\n\t\t})\n\t})\n}\n","import { imageSnapshotSymbol } from './constants.js'\nimport type { ImageSnapshot } from './types.js'\n\nexport function isImageSnapshot(subject: any): subject is ImageSnapshot {\n\treturn !!subject && subject.type === imageSnapshotSymbol\n}\n\nexport function assertImageSnapshot(subject: any): asserts subject is ImageSnapshot {\n\tif (!isImageSnapshot(subject)) {\n\t\tthrow new Error('Expected subject to be an image snapshot')\n\t}\n}\n\nexport function toSnapshotId(taskName: string) {\n\treturn `${taskName.replace(/[^a-z0-9]/gi, '-').toLowerCase()}`\n}\n","import type { BrowserPage } from '@vitest/browser/context'\nimport { basename, join } from 'pathe'\nimport { toImageData } from '../../image_data.js'\nimport { state } from '../../state.js'\nimport { imageSnapshotSymbol } from './constants.js'\nimport { toSnapshotId } from './image_snapshot.logic.js'\nimport type { ImageSnapshot, ImageSnapshotOptions } from './types.js'\n\nexport async function imageSnapshot(this: BrowserPage, options?: ImageSnapshotOptions): Promise<ImageSnapshot> {\n\t// const rootDir = server.config.root\n\tconst testfilename = basename(state.testFilepath)\n\tconst snapshotFilename = `${toSnapshotId(state.taskName)}-${state.snapshot[state.taskName]!.index++}.png`\n\tconst baselinePath = join(state.baselineDir, testfilename, snapshotFilename)\n\tconst resultPath = join(state.resultDir, testfilename, snapshotFilename)\n\tconst diffPath = join(state.diffDir, testfilename, snapshotFilename)\n\tconst screenshot = await this.screenshot({\n\t\tbase64: true,\n\t\tpath: resultPath,\n\t\telement: options?.element,\n\t})\n\tconst image = await toImageData(screenshot.base64)\n\n\treturn {\n\t\ttype: imageSnapshotSymbol,\n\t\t// rootDir,\n\t\ttestfilename,\n\t\tsnapshotFilename,\n\t\tbaselinePath,\n\t\tresultPath,\n\t\tdiffPath,\n\t\tbase64: screenshot.base64,\n\t\timage,\n\t}\n}\n","import {\n\tgetByAltText,\n\tgetByLabelText,\n\tgetByPlaceholderText,\n\tgetByRole,\n\tgetByTestId,\n\tgetByText,\n\tgetByTitle,\n} from '@storybook/test'\nimport type { BrowserCommands, BrowserPage, CDPSession, Platform } from '@vitest/browser/context'\nimport type { SerializedConfig } from 'vitest'\nimport { imageSnapshotStubSymbol } from './constants'\nimport { imageSnapshot } from './page.image_snapshot'\n\nlet ctx: Awaited<typeof import('@vitest/browser/context')>\n\nif ((globalThis as any).__vitest_browser__) {\n\tctx = await import('@vitest/browser/context')\n\t// import('@vitest/browser/context').then((m) => (ctx = m))\n}\n\n// TODO: stub the functions within the `CDPSession`\n// when we better understands the use cases\nexport function cdp(): CDPSession {\n\treturn ctx?.cdp() ?? {}\n}\n\nexport const commands = new Proxy<BrowserCommands>({} as any, {\n\tget(target, prop) {\n\t\treturn (target as any)[prop] ?? (ctx?.commands as any)[prop]\n\t},\n})\n\nexport const page = new Proxy<BrowserPage>(\n\t{\n\t\tgetByAltText,\n\t\tgetByRole,\n\t\tgetByTestId,\n\t\tgetByText,\n\t\tgetByTitle,\n\t\tgetByPlaceholder: getByPlaceholderText,\n\t\tgetByLabelText,\n\t} as any,\n\t{\n\t\tget(target, prop) {\n\t\t\treturn ((target as any)[prop] ?? ctx?.page)\n\t\t\t\t? (ctx?.page as any)[prop]\n\t\t\t\t: () => {\n\t\t\t\t\t\tif (prop === 'imageSnapshot') {\n\t\t\t\t\t\t\treturn { type: imageSnapshotStubSymbol }\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconsole.info(`\\`page.${prop.toString()}\\` does not exist when running in browser`)\n\t\t\t\t\t}\n\t\t},\n\t},\n)\n\nexport const server = new Proxy<{\n\t/**\n\t * Platform the Vitest server is running on.\n\t * The same as calling `process.platform` on the server.\n\t */\n\tplatform: Platform\n\t/**\n\t * Runtime version of the Vitest server.\n\t * The same as calling `process.version` on the server.\n\t */\n\tversion: string\n\t/**\n\t * Name of the browser provider.\n\t */\n\tprovider: string\n\t/**\n\t * Name of the current browser.\n\t */\n\tbrowser: string\n\t/**\n\t * Available commands for the browser.\n\t * @see {@link https://vitest.dev/guide/browser/commands}\n\t */\n\tcommands: BrowserCommands\n\t/**\n\t * Serialized test config.\n\t */\n\tconfig: SerializedConfig\n}>({} as any, {\n\tget(target, prop) {\n\t\treturn (target as any)[prop] ?? (ctx?.server as any)[prop]\n\t},\n})\n\npage.extend({ imageSnapshot })\n","import type { AsyncExpectationResult } from '@vitest/expect'\nimport dedent from 'dedent'\nimport pixelmatch from 'pixelmatch'\nimport { imageSnapshotStubSymbol } from './@vitest/browser/constants.js'\nimport { commands } from './@vitest/browser/context.js'\nimport { assertImageSnapshot, isImageSnapshot } from './@vitest/browser/image_snapshot.logic.js'\nimport type { MatchImageSnapshotOptions } from './@vitest/browser/types.js'\nimport { toDataURL, toImageData } from './image_data.js'\n\nexport async function toMatchImageSnapshot(\n\tactual: any,\n\toptions?: MatchImageSnapshotOptions | undefined,\n): AsyncExpectationResult {\n\tconst subject = await actual\n\tif (subject?.type === imageSnapshotStubSymbol) {\n\t\treturn success\n\t}\n\tif (!isImageSnapshot(subject)) {\n\t\tif (subject?.path && subject?.base64) {\n\t\t\treturn {\n\t\t\t\tpass: false,\n\t\t\t\tactual,\n\t\t\t\tmessage: () =>\n\t\t\t\t\t'`toMatchImageSnapshot()` expects the subject to be the result of `page.imageSnapshot()`, but seems like you are using `page.screenshot()`?',\n\t\t\t}\n\t\t}\n\n\t\tif (typeof subject !== 'object') {\n\t\t\treturn {\n\t\t\t\tpass: false,\n\t\t\t\tactual,\n\t\t\t\tmessage: () =>\n\t\t\t\t\t`\\`toMatchImageSnapshot()\\` expects the subject to be an element, locator, or result of \\`page.imageSnapshot()\\`, but got: \\`${actual}\\``,\n\t\t\t}\n\t\t}\n\t\t// subject = await page.imageSnapshot({ element: actual })\n\t}\n\tassertImageSnapshot(subject)\n\tconst baseline = await tryReadSnapshot(subject.baselinePath)\n\tif (!baseline) {\n\t\tawait commands.copyFile(subject.resultPath, subject.baselinePath)\n\t\treturn success\n\t}\n\n\tconst originalImage = await toImageData(baseline)\n\tconst [resultImage, baselineImage] = alignImagesToSameSize(subject.image, originalImage)\n\n\tconst { pass, diffAmount, diffImage } = compareImage(baselineImage, resultImage, options)\n\tif (!pass) {\n\t\tawait writeSnapshot(`${subject.diffPath}`, diffImage)\n\t\treturn {\n\t\t\tpass: false,\n\t\t\tactual,\n\t\t\tmessage: () =>\n\t\t\t\tdedent`${\n\t\t\t\t\toptions?.failureThreshold\n\t\t\t\t\t\t? options?.failureThresholdType === 'percent'\n\t\t\t\t\t\t\t? `Expected image to match within ${options.failureThreshold}% but was differ by ${diffAmount}%.`\n\t\t\t\t\t\t\t: `Expected image to match within ${options.failureThreshold} pixels but was differ by ${diffAmount} pixels.`\n\t\t\t\t\t\t: `Expected image to match but was differ by ${options?.failureThresholdType === 'percent' ? `${diffAmount}%` : `${diffAmount} pixels`}.`\n\t\t\t\t}\n\n\t\t\tExpected: '${subject.baselinePath}'\n\t\t\tActual: '${subject.resultPath}'\n\t\t\tDifference: '${subject.diffPath}'`,\n\t\t}\n\t}\n\treturn success\n}\n\nconst success = {\n\tpass: true,\n\tmessage: () => '',\n}\n\nfunction tryReadSnapshot(path: string): Promise<string | undefined> {\n\treturn commands.readFile(path, { encoding: 'base64' }).catch(() => undefined)\n}\nasync function writeSnapshot(path: string, image: ImageData) {\n\tconst content = (await toDataURL(image)).split(',')[1]!\n\treturn commands.writeFile(path, content, 'base64url')\n}\n\nfunction alignImagesToSameSize(image1: ImageData, image2: ImageData): [image1: ImageData, image2: ImageData] {\n\tif (isSameSize(image1, image2)) {\n\t\treturn [image1, image2]\n\t}\n\tconst size = getMaxSize(image1, image2)\n\tconst resize = createImageResizer(size)\n\treturn [resize(image1), resize(image2)]\n}\n\nfunction getMaxSize(image1: ImageData, image2: ImageData) {\n\tconst width = Math.max(image1.width, image2.width)\n\tconst height = Math.max(image1.height, image2.height)\n\treturn { width, height }\n}\n\nfunction isSameSize(image1: ImageData, image2: ImageData) {\n\treturn image1.width === image2.width && image1.height === image2.height\n}\n\nconst createImageResizer =\n\t({ width, height }: { width: number; height: number }) =>\n\t(image: ImageData) => {\n\t\tif (image.width === width && image.height === height) {\n\t\t\treturn image\n\t\t}\n\t\tconst inArea = (x: number, y: number) => y <= image.height && x <= image.width\n\t\tconst result = new ImageData(width, height, { colorSpace: image.colorSpace })\n\n\t\tfor (let y = 0; y < height; y++) {\n\t\t\tfor (let x = 0; x < width; x++) {\n\t\t\t\tconst idx = (width * y + x) << 2\n\t\t\t\tif (inArea(x, y)) {\n\t\t\t\t\tconst old = (image.width * y + x) << 2\n\t\t\t\t\tresult.data[idx] = image.data[old]\n\t\t\t\t\tresult.data[idx + 1] = image.data[old + 1]\n\t\t\t\t\tresult.data[idx + 2] = image.data[old + 2]\n\t\t\t\t\tresult.data[idx + 3] = image.data[old + 3]\n\t\t\t\t} else {\n\t\t\t\t\tresult.data[idx] = 0\n\t\t\t\t\tresult.data[idx + 1] = 0\n\t\t\t\t\tresult.data[idx + 2] = 0\n\t\t\t\t\tresult.data[idx + 3] = 64\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\nfunction compareImage(\n\tbaselineImage: ImageData,\n\tresultImage: ImageData,\n\t{ failureThreshold = 0, failureThresholdType = 'pixel', diffOptions }: MatchImageSnapshotOptions = {},\n) {\n\tconst { width, height } = resultImage\n\tconst diffImage = new ImageData(width, height)\n\n\tconst pixelDiff = pixelmatch(resultImage.data, baselineImage.data, diffImage.data, width, height, diffOptions)\n\tconst diffAmount = toThresholdUnit({ failureThresholdType, width, height }, pixelDiff)\n\n\treturn {\n\t\tpass: diffAmount <= failureThreshold,\n\t\tdiffAmount,\n\t\tdiffImage,\n\t}\n}\n\nfunction toThresholdUnit(\n\t{ failureThresholdType, width, height }: { failureThresholdType: 'pixel' | 'percent'; width: number; height: number },\n\tpixelDiff: number,\n): number {\n\tswitch (failureThresholdType) {\n\t\tcase 'pixel':\n\t\t\treturn pixelDiff\n\t\tcase 'percent':\n\t\t\treturn (pixelDiff / (width * height)) * 100\n\t\tdefault:\n\t\t\tthrow new Error(`Invalid failureThresholdType: ${failureThresholdType}`)\n\t}\n}\n","/**\n * Determine should snapshot be taken.\n *\n * not story: false\n * no `snapshot` tag: false\n * disabled by `!snapshot` tag: false\n */\nexport function shouldTakeSnapshot(ctx: { story?: { tags: string[] } }) {\n\tif (!ctx.story?.tags) return false\n\treturn ctx.story.tags.lastIndexOf('!snapshot') < ctx.story.tags.lastIndexOf('snapshot')\n}\n","import { basename, dirname, join, relative } from 'pathe'\nimport './augment.js'\nimport { state } from './state.js'\n\nexport * from './@vitest/browser/context.js'\nexport * from './expect.to_match_image_snapshot.js'\nexport * from './tags.js'\n\nexport function configureSnapshotBeforeAll(suite: { file: { filepath: string }; name: string }) {\n\tstate.name = suite.name\n\tstate.testFilepath = suite.file.filepath\n\tstate.testFilename = basename(state.testFilepath)\n\tstate.projectDir = state.testFilepath.slice(0, -state.name.length)\n\tconst currentDir = dirname(state.testFilepath)\n\tstate.baselineDir = relative(currentDir, join(state.projectDir, '__snapshots__'))\n\tstate.resultDir = relative(currentDir, join(state.projectDir, '__snapshots__', '__results__'))\n\tstate.diffDir = relative(currentDir, join(state.projectDir, '__snapshots__', '__diff_output__'))\n}\n\nexport function configureSnapshotBeforeEach(ctx: { task: { name: string } }) {\n\tstate.taskName = ctx.task.name\n\tstate.snapshot[state.taskName] = state.snapshot[state.taskName] ?? { index: 1 }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "storybook-addon-vis",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "Storybook Vitest Image Snapshot addon",
5
5
  "keywords": [
6
6
  "image-snapshot",
package/src/tags.ts CHANGED
@@ -1,6 +1,11 @@
1
- import type { StoryContext } from '@storybook/react'
2
-
3
- export function shouldTakeSnapshot(ctx: { story?: StoryContext }) {
1
+ /**
2
+ * Determine should snapshot be taken.
3
+ *
4
+ * not story: false
5
+ * no `snapshot` tag: false
6
+ * disabled by `!snapshot` tag: false
7
+ */
8
+ export function shouldTakeSnapshot(ctx: { story?: { tags: string[] } }) {
4
9
  if (!ctx.story?.tags) return false
5
10
  return ctx.story.tags.lastIndexOf('!snapshot') < ctx.story.tags.lastIndexOf('snapshot')
6
11
  }