storybook-addon-vis 0.0.8 → 0.0.9

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.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import F from'dedent';import M from'pixelmatch';import {getByAltText,getByRole,getByTestId,getByText,getByTitle,getByPlaceholderText,getByLabelText}from'@storybook/test';import {basename,join}from'pathe';var g=Symbol.for("storybook-addon-vis/imageSnapshot"),d=Symbol.for("storybook-addon-vis/imageSnapshotStub");function f(t){return new Promise((e,a)=>{let n=new Image;n.src=`data:image/png;base64,${t}`,n.onload=()=>{let o=document.createElement("canvas");o.width=n.width,o.height=n.height;let r=o.getContext("2d");r.drawImage(n,0,0),e(r.getImageData(0,0,o.width,o.height));},n.onerror=()=>{a(new Error("Failed to load image"));};})}async function x(t){let e=document.createElement("canvas");return e.width=t.width,e.height=t.height,e.getContext("2d").putImageData(t,0,0),new Promise(n=>{e.toBlob(o=>{let r=new FileReader;r.onload=()=>{n(r.result);},r.readAsDataURL(o);});})}var p={name:"",testFilepath:"",taskName:"",snapshot:{}};function u(t){return !!t&&t.type===g}function S(t){if(!u(t))throw new Error("Expected subject to be an image snapshot")}function w(t){return `${t.replace(/[^a-z0-9]/gi,"-").toLowerCase()}`}async function I(t){let e=basename(p.testFilepath),a=`${w(p.taskName)}-${p.snapshot[p.taskName].index++}.png`,n=join(p.baselineDir,e,a),o=join(p.resultDir,e,a),r=join(p.diffDir,e,a),s=await this.screenshot({base64:!0,path:o,element:t?.element}),i=await f(s.base64);return {type:g,testfilename:e,snapshotFilename:a,baselinePath:n,resultPath:o,diffPath:r,base64:s.base64,image:i}}var h;globalThis.__vitest_browser__&&(h=await import('@vitest/browser/context'));function at(){return h?.cdp()??{}}var l=new Proxy({},{get(t,e){return t[e]??(h?.commands)[e]}}),C=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:d};console.info(`\`page.${e.toString()}\` does not exist when running in browser`);}}}),nt=new Proxy({},{get(t,e){return t[e]??(h?.server)[e]}});C.extend({imageSnapshot:I});async function ct(t,e){let a=await t;if(a?.type===d)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}\``}}S(a);let n=await R(a.baselinePath);if(!n)return await l.copyFile(a.resultPath,a.baselinePath),b;let o=await f(n),[r,s]=A(a.image,o),{pass:i,diffAmount:m,diffImage:c}=_(s,r,e);return i?b:(await z(`${a.diffPath}`,c),{pass:!1,actual:t,message:()=>F`${e?.failureThreshold?e?.failureThresholdType==="percent"?`Expected image to match within ${e.failureThreshold}% but was differ by ${m}%.`:`Expected image to match within ${e.failureThreshold} pixels but was differ by ${m} pixels.`:`Expected image to match but was differ by ${e?.failureThresholdType==="percent"?`${m}%`:`${m} pixels`}.`}
1
+ import F from'dedent';import M from'pixelmatch';import {getByAltText,getByRole,getByTestId,getByText,getByTitle,getByPlaceholderText,getByLabelText}from'@storybook/test';import {basename,join}from'pathe';var g=Symbol.for("storybook-addon-vis/imageSnapshot"),d=Symbol.for("storybook-addon-vis/imageSnapshotStub");function f(t){return new Promise((e,a)=>{let n=new Image;n.src=`data:image/png;base64,${t}`,n.onload=()=>{let o=document.createElement("canvas");o.width=n.width,o.height=n.height;let r=o.getContext("2d");r.drawImage(n,0,0),e(r.getImageData(0,0,o.width,o.height));},n.onerror=()=>{a(new Error("Failed to load image"));};})}async function x(t){let e=document.createElement("canvas");return e.width=t.width,e.height=t.height,e.getContext("2d").putImageData(t,0,0),new Promise(n=>{e.toBlob(o=>{let r=new FileReader;r.onload=()=>{n(r.result);},r.readAsDataURL(o);});})}var p={name:"",testFilepath:"",taskName:"",snapshot:{}};function u(t){return !!t&&t.type===g}function S(t){if(!u(t))throw new Error("Expected subject to be an image snapshot")}function w(t){return `${t.replace(/[^a-z0-9]/gi,"-").toLowerCase()}`}async function I(t){let e=basename(p.testFilepath),a=`${w(p.taskName)}-${p.snapshot[p.taskName].index++}.png`,n=join(p.baselineDir,e,a),o=join(p.resultDir,e,a),r=join(p.diffDir,e,a),s=await this.screenshot({base64:!0,path:o,element:t?.element}),i=await f(s.base64);return {type:g,testfilename:e,snapshotFilename:a,baselinePath:n,resultPath:o,diffPath:r,base64:s.base64,image:i}}var h;globalThis.__vitest_browser__&&import('@vitest/browser/context').then(t=>{h=t,C.extend({imageSnapshot:I});});function at(){return h?.cdp()??{}}var l=new Proxy({},{get(t,e){return t[e]??(h?.commands)[e]}}),C=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:d};console.info(`\`page.${e.toString()}\` does not exist when running in browser`);}}}),nt=new Proxy({},{get(t,e){return t[e]??(h?.server)[e]}});async function ct(t,e){let a=await t;if(a?.type===d)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}\``}}S(a);let n=await R(a.baselinePath);if(!n)return await l.copyFile(a.resultPath,a.baselinePath),b;let o=await f(n),[r,s]=A(a.image,o),{pass:i,diffAmount:m,diffImage:c}=_(s,r,e);return i?b:(await z(`${a.diffPath}`,c),{pass:!1,actual:t,message:()=>F`${e?.failureThreshold?e?.failureThresholdType==="percent"?`Expected image to match within ${e.failureThreshold}% but was differ by ${m}%.`:`Expected image to match within ${e.failureThreshold} pixels but was differ by ${m} pixels.`:`Expected image to match but was differ by ${e?.failureThresholdType==="percent"?`${m}%`:`${m} pixels`}.`}
2
2
 
3
3
  Expected: '${a.baselinePath}'
4
4
  Actual: '${a.resultPath}'
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/@vitest/browser/constants.ts","../src/image_data.ts","../src/state.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/param.ts"],"names":["imageSnapshotSymbol","imageSnapshotStubSymbol","toImageData","base64","resolve","reject","img","canvas","ctx","toDataURL","imageData","blob","reader","state","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","defineSnapshotProjectParam","snapshot","defineSnapshotParam"],"mappings":"4MAAO,IAAMA,CAAAA,CAAsB,MAAO,CAAA,GAAA,CAAI,mCAAmC,CAAA,CAEpEC,CAA0B,CAAA,MAAA,CAAO,IAAI,uCAAuC,CAAA,CCFlF,SAASC,CAAAA,CAAYC,EAAgB,CAC3C,OAAO,IAAI,OAAA,CAAmB,CAACC,CAAAA,CAASC,CAAW,GAAA,CAClD,IAAMC,CAAM,CAAA,IAAI,KAChBA,CAAAA,CAAAA,CAAI,GAAM,CAAA,CAAA,sBAAA,EAAyBH,CAAM,CAAA,CAAA,CAEzCG,EAAI,MAAS,CAAA,IAAM,CAClB,IAAMC,EAAS,QAAS,CAAA,aAAA,CAAc,QAAQ,CAAA,CAC9CA,EAAO,KAAQD,CAAAA,CAAAA,CAAI,KACnBC,CAAAA,CAAAA,CAAO,MAASD,CAAAA,CAAAA,CAAI,MACpB,CAAA,IAAME,EAAMD,CAAO,CAAA,UAAA,CAAW,IAAI,CAAA,CAClCC,CAAI,CAAA,SAAA,CAAUF,CAAK,CAAA,CAAA,CAAG,CAAC,CACvBF,CAAAA,CAAAA,CAAQI,CAAI,CAAA,YAAA,CAAa,CAAG,CAAA,CAAA,CAAGD,CAAO,CAAA,KAAA,CAAOA,EAAO,MAAM,CAAC,EAC5D,CAAA,CAEAD,EAAI,OAAU,CAAA,IAAM,CACnBD,CAAAA,CAAO,IAAI,KAAM,CAAA,sBAAsB,CAAC,EACzC,EACD,CAAC,CACF,CAEA,eAAsBI,CAAUC,CAAAA,CAAAA,CAAsB,CACrD,IAAMH,CAAS,CAAA,QAAA,CAAS,aAAc,CAAA,QAAQ,EAC9C,OAAAA,CAAAA,CAAO,KAAQG,CAAAA,CAAAA,CAAU,KACzBH,CAAAA,CAAAA,CAAO,MAASG,CAAAA,CAAAA,CAAU,OACdH,CAAO,CAAA,UAAA,CAAW,IAAI,CAAA,CAC9B,aAAaG,CAAW,CAAA,CAAA,CAAG,CAAC,CAAA,CACzB,IAAI,OAAiBN,CAAAA,CAAAA,EAAY,CACvCG,CAAAA,CAAO,MAAQI,CAAAA,CAAAA,EAAS,CACvB,IAAMC,EAAS,IAAI,UAAA,CACnBA,CAAO,CAAA,MAAA,CAAS,IAAM,CACrBR,CAAQQ,CAAAA,CAAAA,CAAO,MAAgB,EAChC,CAAA,CACAA,CAAO,CAAA,aAAA,CAAcD,CAAK,EAC3B,CAAC,EACF,CAAC,CACF,CCnCO,IAAME,CAAAA,CAAQ,CACpB,IAAM,CAAA,EAAA,CACN,YAAc,CAAA,EAAA,CACd,SAAU,EACV,CAAA,QAAA,CAAU,EACX,CCFO,CAAA,SAASC,CAAgBC,CAAAA,CAAAA,CAAwC,CACvE,OAAO,CAAC,CAACA,CAAAA,EAAWA,CAAQ,CAAA,IAAA,GAASf,CACtC,CAEO,SAASgB,CAAoBD,CAAAA,CAAAA,CAAgD,CACnF,GAAI,CAACD,CAAAA,CAAgBC,CAAO,CAAA,CAC3B,MAAM,IAAI,KAAA,CAAM,0CAA0C,CAE5D,CAEO,SAASE,CAAAA,CAAaC,CAAkB,CAAA,CAC9C,OAAO,CAAGA,EAAAA,CAAAA,CAAS,OAAQ,CAAA,aAAA,CAAe,GAAG,CAAA,CAAE,WAAY,EAAC,EAC7D,CCPA,eAAsBC,CAAiCC,CAAAA,CAAAA,CAAwD,CAE9G,IAAMC,CAAeC,CAAAA,QAAAA,CAAST,EAAM,YAAY,CAAA,CAC1CU,CAAmB,CAAA,CAAA,EAAGN,CAAaJ,CAAAA,CAAAA,CAAM,QAAQ,CAAC,IAAIA,CAAM,CAAA,QAAA,CAASA,CAAM,CAAA,QAAQ,EAAG,KAAO,EAAA,CAAA,IAAA,CAAA,CAC7FW,CAAeC,CAAAA,IAAAA,CAAKZ,EAAM,WAAaQ,CAAAA,CAAAA,CAAcE,CAAgB,CAAA,CACrEG,CAAaD,CAAAA,IAAAA,CAAKZ,CAAM,CAAA,SAAA,CAAWQ,EAAcE,CAAgB,CAAA,CACjEI,CAAWF,CAAAA,IAAAA,CAAKZ,CAAM,CAAA,OAAA,CAASQ,CAAcE,CAAAA,CAAgB,EAC7DK,CAAa,CAAA,MAAM,IAAK,CAAA,UAAA,CAAW,CACxC,MAAA,CAAQ,CACR,CAAA,CAAA,IAAA,CAAMF,EACN,OAASN,CAAAA,CAAAA,EAAS,OACnB,CAAC,EACKS,CAAQ,CAAA,MAAM3B,CAAY0B,CAAAA,CAAAA,CAAW,MAAM,CAEjD,CAAA,OAAO,CACN,IAAA,CAAM5B,CAEN,CAAA,YAAA,CAAAqB,CACA,CAAA,gBAAA,CAAAE,EACA,YAAAC,CAAAA,CAAAA,CACA,UAAAE,CAAAA,CAAAA,CACA,QAAAC,CAAAA,CAAAA,CACA,MAAQC,CAAAA,CAAAA,CAAW,OACnB,KAAAC,CAAAA,CACD,CACD,CCnBA,IAAIrB,CAAAA,CAEC,UAAmB,CAAA,kBAAA,GACvBA,EAAM,MAAM,OAAO,yBAAyB,CAAA,CAAA,CAMtC,SAASsB,EAAkB,EAAA,CACjC,OAAOtB,CAAAA,EAAK,KAAS,EAAA,EACtB,CAEauB,IAAAA,CAAAA,CAAW,IAAI,KAAA,CAAuB,EAAW,CAAA,CAC7D,GAAIC,CAAAA,CAAAA,CAAQC,CAAM,CAAA,CACjB,OAAQD,CAAAA,CAAeC,CAAI,CAAMzB,EAAAA,CAAAA,CAAAA,EAAK,QAAiByB,EAAAA,CAAI,CAC5D,CACD,CAAC,CAAA,CAEYC,EAAO,IAAI,KAAA,CACvB,CACC,YAAA,CAAAC,aACA,SAAAC,CAAAA,SAAAA,CACA,WAAAC,CAAAA,WAAAA,CACA,UAAAC,SACA,CAAA,UAAA,CAAAC,UACA,CAAA,gBAAA,CAAkBC,oBAClB,CAAA,cAAA,CAAAC,cACD,CAAA,CACA,CACC,GAAIT,CAAAA,CAAAA,CAAQC,CAAM,CAAA,CACjB,OAASD,CAAAA,CAAeC,CAAI,CAAA,EAAKzB,GAAK,IAClCA,CAAAA,CAAAA,CAAAA,EAAK,IAAayB,EAAAA,CAAI,CACvB,CAAA,IAAM,CACN,GAAIA,IAAS,eACZ,CAAA,OAAO,CAAE,IAAA,CAAMhC,CAAwB,CAExC,CAAA,OAAA,CAAQ,IAAK,CAAA,CAAA,OAAA,EAAUgC,EAAK,QAAS,EAAC,CAA2C,yCAAA,CAAA,EAClF,CACH,CACD,CACD,CAAA,CAEaS,GAAS,IAAI,KAAA,CA4BvB,EAAC,CAAU,CACb,GAAA,CAAIV,CAAQC,CAAAA,CAAAA,CAAM,CACjB,OAAQD,CAAAA,CAAeC,CAAI,CAAA,EAAA,CAAMzB,CAAK,EAAA,MAAA,EAAeyB,CAAI,CAC1D,CACD,CAAC,EAEDC,CAAK,CAAA,MAAA,CAAO,CAAE,aAAAf,CAAAA,CAAc,CAAC,CAAA,CClF7B,eAAsBwB,EACrBC,CAAAA,CAAAA,CACAxB,CACyB,CAAA,CACzB,IAAML,CAAAA,CAAU,MAAM6B,CAAAA,CACtB,GAAI7B,CAAS,EAAA,IAAA,GAASd,CACrB,CAAA,OAAO4C,CAER,CAAA,GAAI,CAAC/B,CAAAA,CAAgBC,CAAO,CAAG,CAAA,CAC9B,GAAIA,CAAAA,EAAS,IAAQA,EAAAA,CAAAA,EAAS,MAC7B,CAAA,OAAO,CACN,IAAM,CAAA,CAAA,CAAA,CACN,MAAA6B,CAAAA,CAAAA,CACA,QAAS,IACR,4IACF,CAGD,CAAA,GAAI,OAAO7B,CAAY,EAAA,QAAA,CACtB,OAAO,CACN,IAAM,CAAA,CAAA,CAAA,CACN,MAAA6B,CAAAA,CAAAA,CACA,QAAS,IACR,CAAA,4HAAA,EAA+HA,CAAM,CAAA,EAAA,CACvI,CAGF,CACA5B,CAAoBD,CAAAA,CAAO,EAC3B,IAAM+B,CAAAA,CAAW,MAAMC,CAAAA,CAAgBhC,CAAQ,CAAA,YAAY,CAC3D,CAAA,GAAI,CAAC+B,CACJ,CAAA,OAAA,MAAMf,CAAS,CAAA,QAAA,CAAShB,EAAQ,UAAYA,CAAAA,CAAAA,CAAQ,YAAY,CAAA,CACzD8B,EAGR,IAAMG,CAAAA,CAAgB,MAAM9C,CAAAA,CAAY4C,CAAQ,CAAA,CAC1C,CAACG,CAAAA,CAAaC,CAAa,CAAIC,CAAAA,CAAAA,CAAsBpC,CAAQ,CAAA,KAAA,CAAOiC,CAAa,CAAA,CAEjF,CAAE,IAAA,CAAAI,EAAM,UAAAC,CAAAA,CAAAA,CAAY,SAAAC,CAAAA,CAAU,CAAIC,CAAAA,CAAAA,CAAaL,CAAeD,CAAAA,CAAAA,CAAa7B,CAAO,CACxF,CAAA,OAAKgC,CAmBEP,CAAAA,CAAAA,EAlBN,MAAMW,CAAc,CAAA,CAAA,EAAGzC,CAAQ,CAAA,QAAQ,GAAIuC,CAAS,CAAA,CAC7C,CACN,IAAA,CAAM,CACN,CAAA,CAAA,MAAA,CAAAV,CACA,CAAA,OAAA,CAAS,IACRa,CACCrC,CAAAA,EAAAA,CAAAA,EAAS,gBACNA,CAAAA,CAAAA,EAAS,oBAAyB,GAAA,SAAA,CACjC,CAAkCA,+BAAAA,EAAAA,CAAAA,CAAQ,gBAAgB,CAAuBiC,oBAAAA,EAAAA,CAAU,CAC3F,EAAA,CAAA,CAAA,CAAA,+BAAA,EAAkCjC,CAAQ,CAAA,gBAAgB,CAA6BiC,0BAAAA,EAAAA,CAAU,WAClG,CAA6CjC,0CAAAA,EAAAA,CAAAA,EAAS,oBAAyB,GAAA,SAAA,CAAY,GAAGiC,CAAU,CAAA,CAAA,CAAA,CAAM,CAAGA,EAAAA,CAAU,SAAS,CACxI,CAAA,CAAA,CAAA;AAAA;AAAA,gBAAA,EAEctC,EAAQ,YAAY,CAAA;AAAA,gBAAA,EACpBA,EAAQ,UAAU,CAAA;AAAA,gBAClBA,EAAAA,CAAAA,CAAQ,QAAQ,CAChC,CAAA,CAAA,CAAA,CAGF,CAEA,IAAM8B,CAAAA,CAAU,CACf,IAAM,CAAA,CAAA,CAAA,CACN,QAAS,IAAM,EAChB,EAEA,SAASE,CAAAA,CAAgBW,EAA2C,CACnE,OAAO3B,CAAS,CAAA,QAAA,CAAS2B,CAAM,CAAA,CAAE,SAAU,QAAS,CAAC,EAAE,KAAM,CAAA,IAAG,EAAY,CAC7E,CACA,eAAeF,CAAcE,CAAAA,CAAAA,CAAc7B,EAAkB,CAC5D,IAAM8B,GAAW,MAAMlD,CAAAA,CAAUoB,CAAK,CAAG,EAAA,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,CACrD,OAAOE,CAAS,CAAA,SAAA,CAAU2B,EAAMC,CAAS,CAAA,WAAW,CACrD,CAEA,SAASR,EAAsBS,CAAmBC,CAAAA,CAAAA,CAA2D,CAC5G,GAAIC,CAAAA,CAAWF,EAAQC,CAAM,CAAA,CAC5B,OAAO,CAACD,CAAAA,CAAQC,CAAM,CAAA,CAEvB,IAAME,CAAAA,CAAOC,EAAWJ,CAAQC,CAAAA,CAAM,EAChCI,CAASC,CAAAA,CAAAA,CAAmBH,CAAI,CACtC,CAAA,OAAO,CAACE,CAAOL,CAAAA,CAAM,EAAGK,CAAOJ,CAAAA,CAAM,CAAC,CACvC,CAEA,SAASG,CAAWJ,CAAAA,CAAAA,CAAmBC,CAAmB,CAAA,CACzD,IAAMM,CAAAA,CAAQ,KAAK,GAAIP,CAAAA,CAAAA,CAAO,MAAOC,CAAO,CAAA,KAAK,EAC3CO,CAAS,CAAA,IAAA,CAAK,IAAIR,CAAO,CAAA,MAAA,CAAQC,EAAO,MAAM,CAAA,CACpD,OAAO,CAAE,KAAA,CAAAM,EAAO,MAAAC,CAAAA,CAAO,CACxB,CAEA,SAASN,CAAAA,CAAWF,EAAmBC,CAAmB,CAAA,CACzD,OAAOD,CAAO,CAAA,KAAA,GAAUC,EAAO,KAASD,EAAAA,CAAAA,CAAO,SAAWC,CAAO,CAAA,MAClE,CAEA,IAAMK,CAAAA,CACL,CAAC,CAAE,KAAA,CAAAC,EAAO,MAAAC,CAAAA,CAAO,CAChBvC,GAAAA,CAAAA,EAAqB,CACrB,GAAIA,EAAM,KAAUsC,GAAAA,CAAAA,EAAStC,EAAM,MAAWuC,GAAAA,CAAAA,CAC7C,OAAOvC,CAER,CAAA,IAAMwC,EAAS,CAACC,CAAAA,CAAWC,IAAcA,CAAK1C,EAAAA,CAAAA,CAAM,QAAUyC,CAAKzC,EAAAA,CAAAA,CAAM,MACnE2C,CAAS,CAAA,IAAI,SAAUL,CAAAA,CAAAA,CAAOC,CAAQ,CAAA,CAAE,WAAYvC,CAAM,CAAA,UAAW,CAAC,CAE5E,CAAA,IAAA,IAAS0C,EAAI,CAAGA,CAAAA,CAAAA,CAAIH,EAAQG,CAC3B,EAAA,CAAA,IAAA,IAASD,EAAI,CAAGA,CAAAA,CAAAA,CAAIH,EAAOG,CAAK,EAAA,CAAA,CAC/B,IAAMG,CAAON,CAAAA,CAAAA,CAAQI,CAAID,CAAAA,CAAAA,EAAM,CAC/B,CAAA,GAAID,EAAOC,CAAGC,CAAAA,CAAC,EAAG,CACjB,IAAMG,EAAO7C,CAAM,CAAA,KAAA,CAAQ0C,EAAID,CAAM,EAAA,CAAA,CACrCE,EAAO,IAAKC,CAAAA,CAAG,EAAI5C,CAAM,CAAA,IAAA,CAAK6C,CAAG,CACjCF,CAAAA,CAAAA,CAAO,IAAKC,CAAAA,CAAAA,CAAM,CAAC,CAAA,CAAI5C,EAAM,IAAK6C,CAAAA,CAAAA,CAAM,CAAC,CACzCF,CAAAA,CAAAA,CAAO,KAAKC,CAAM,CAAA,CAAC,EAAI5C,CAAM,CAAA,IAAA,CAAK6C,EAAM,CAAC,CAAA,CACzCF,EAAO,IAAKC,CAAAA,CAAAA,CAAM,CAAC,CAAI5C,CAAAA,CAAAA,CAAM,IAAK6C,CAAAA,CAAAA,CAAM,CAAC,EAC1C,MACCF,CAAO,CAAA,IAAA,CAAKC,CAAG,CAAI,CAAA,CAAA,CACnBD,EAAO,IAAKC,CAAAA,CAAAA,CAAM,CAAC,CAAI,CAAA,CAAA,CACvBD,EAAO,IAAKC,CAAAA,CAAAA,CAAM,CAAC,CAAI,CAAA,CAAA,CACvBD,EAAO,IAAKC,CAAAA,CAAAA,CAAM,CAAC,CAAA,CAAI,GAEzB,CAED,OAAOD,CACR,CAAA,CAED,SAASjB,CACRL,CAAAA,CAAAA,CACAD,EACA,CAAE,gBAAA,CAAA0B,EAAmB,CAAG,CAAA,oBAAA,CAAAC,EAAuB,OAAS,CAAA,WAAA,CAAAC,CAAY,CAA+B,CAAA,GAClG,CACD,GAAM,CAAE,KAAA,CAAAV,CAAO,CAAA,MAAA,CAAAC,CAAO,CAAInB,CAAAA,CAAAA,CACpBK,EAAY,IAAI,SAAA,CAAUa,EAAOC,CAAM,CAAA,CAEvCU,EAAYC,CAAW9B,CAAAA,CAAAA,CAAY,KAAMC,CAAc,CAAA,IAAA,CAAMI,EAAU,IAAMa,CAAAA,CAAAA,CAAOC,EAAQS,CAAW,CAAA,CACvGxB,CAAa2B,CAAAA,CAAAA,CAAgB,CAAE,oBAAA,CAAAJ,EAAsB,KAAAT,CAAAA,CAAAA,CAAO,OAAAC,CAAO,CAAA,CAAGU,CAAS,CAErF,CAAA,OAAO,CACN,IAAMzB,CAAAA,CAAAA,EAAcsB,EACpB,UAAAtB,CAAAA,CAAAA,CACA,UAAAC,CACD,CACD,CAEA,SAAS0B,CAAAA,CACR,CAAE,oBAAA,CAAAJ,CAAsB,CAAA,KAAA,CAAAT,EAAO,MAAAC,CAAAA,CAAO,EACtCU,CACS,CAAA,CACT,OAAQF,CAAsB,EAC7B,IAAK,OACJ,CAAA,OAAOE,EACR,IAAK,SAAA,CACJ,OAAQA,CAAaX,EAAAA,CAAAA,CAAQC,GAAW,GACzC,CAAA,QACC,MAAM,IAAI,KAAM,CAAA,CAAA,8BAAA,EAAiCQ,CAAoB,CAAE,CAAA,CACzE,CACD,CCnIO,SAASK,GAA2BC,CAAyC,CAAA,CACnF,OAAO,CAAE,QAAA,CAAAA,CAAS,CACnB,CA0BO,SAASC,EAAoBD,CAAAA,CAAAA,CAA8B,CACjE,OAAO,CAAE,QAAAA,CAAAA,CAAS,CACnB","file":"index.js","sourcesContent":["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","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","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 { PixelmatchOptions } from 'pixelmatch'\n\n/**\n * The project parameters for the snapshot.\n *\n * These parameters are set per project in the `.storybook/preview.ts` file.\n */\nexport type SnapshotProjectParam = {\n\t/**\n\t * The snapshot folder relative to the root of the project.\n\t */\n\tsnapshotPath: string\n\t/**\n\t * The baseline folder under the snapshot folder specified in `snapshotPath`.\n\t */\n\tbaseline: string\n\t/**\n\t * The result folder under the snapshot folder specified in `snapshotPath`.\n\t *\n\t * This folder stores the snapshot of the current test run.\n\t */\n\tresult: string\n\t/**\n\t * The diff folder under the snapshot folder specified in `snapshotPath`.\n\t *\n\t * This folder stores the diff of the current test run if the test fails.\n\t */\n\tdiff: string\n}\n\nexport function defineSnapshotProjectParam(snapshot: Partial<SnapshotProjectParam>) {\n\treturn { snapshot }\n}\n\nexport type SnapshotStoryParam = {\n\t/**\n\t * Add a delay to the story snapshot comparison to allow for async rendering.\n\t *\n\t * This only apply to the automatic snapshot taken when the story is rendered.\n\t * In general, it's a good idea to not rely on this delay,\n\t * and instead use the make sure your component is fully rendered before the `play()` function returns.\n\t */\n\tdelay?: number | undefined\n\t/**\n\t * The method by which images are compared.\n\t * `pixelmatch` does a pixel by pixel comparison, whereas `ssim` does a structural similarity comparison.\n\t * @default 'pixelmatch'\n\t */\n\tcomparisonMethod?: 'pixelmatch' | 'ssim' | undefined\n\t/**\n\t * Custom config passed to 'pixelmatch' or 'ssim'\n\t */\n\tcustomDiffConfig?: PixelmatchOptions | undefined\n\tfailureThreshold?: number | undefined\n\tfailureThresholdType?: 'percent' | 'pixel' | undefined\n\tblur?: number | undefined\n}\n\nexport function defineSnapshotParam(snapshot: SnapshotStoryParam) {\n\treturn { snapshot }\n}\n"]}
1
+ {"version":3,"sources":["../src/@vitest/browser/constants.ts","../src/image_data.ts","../src/state.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/param.ts"],"names":["imageSnapshotSymbol","imageSnapshotStubSymbol","toImageData","base64","resolve","reject","img","canvas","ctx","toDataURL","imageData","blob","reader","state","isImageSnapshot","subject","assertImageSnapshot","toSnapshotId","taskName","imageSnapshot","options","testfilename","basename","snapshotFilename","baselinePath","join","resultPath","diffPath","screenshot","image","m","page","cdp","commands","target","prop","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","defineSnapshotProjectParam","snapshot","defineSnapshotParam"],"mappings":"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","file":"index.js","sourcesContent":["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","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","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\timport('@vitest/browser/context').then((m) => {\n\t\tctx = m\n\t\tpage.extend({ imageSnapshot })\n\t})\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","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 { PixelmatchOptions } from 'pixelmatch'\n\n/**\n * The project parameters for the snapshot.\n *\n * These parameters are set per project in the `.storybook/preview.ts` file.\n */\nexport type SnapshotProjectParam = {\n\t/**\n\t * The snapshot folder relative to the root of the project.\n\t */\n\tsnapshotPath: string\n\t/**\n\t * The baseline folder under the snapshot folder specified in `snapshotPath`.\n\t */\n\tbaseline: string\n\t/**\n\t * The result folder under the snapshot folder specified in `snapshotPath`.\n\t *\n\t * This folder stores the snapshot of the current test run.\n\t */\n\tresult: string\n\t/**\n\t * The diff folder under the snapshot folder specified in `snapshotPath`.\n\t *\n\t * This folder stores the diff of the current test run if the test fails.\n\t */\n\tdiff: string\n}\n\nexport function defineSnapshotProjectParam(snapshot: Partial<SnapshotProjectParam>) {\n\treturn { snapshot }\n}\n\nexport type SnapshotStoryParam = {\n\t/**\n\t * Add a delay to the story snapshot comparison to allow for async rendering.\n\t *\n\t * This only apply to the automatic snapshot taken when the story is rendered.\n\t * In general, it's a good idea to not rely on this delay,\n\t * and instead use the make sure your component is fully rendered before the `play()` function returns.\n\t */\n\tdelay?: number | undefined\n\t/**\n\t * The method by which images are compared.\n\t * `pixelmatch` does a pixel by pixel comparison, whereas `ssim` does a structural similarity comparison.\n\t * @default 'pixelmatch'\n\t */\n\tcomparisonMethod?: 'pixelmatch' | 'ssim' | undefined\n\t/**\n\t * Custom config passed to 'pixelmatch' or 'ssim'\n\t */\n\tcustomDiffConfig?: PixelmatchOptions | undefined\n\tfailureThreshold?: number | undefined\n\tfailureThresholdType?: 'percent' | 'pixel' | undefined\n\tblur?: number | undefined\n}\n\nexport function defineSnapshotParam(snapshot: SnapshotStoryParam) {\n\treturn { snapshot }\n}\n"]}
@@ -1,4 +1,4 @@
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`}.`}
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__&&import('@vitest/browser/context').then(t=>{h=t,E.extend({imageSnapshot:P});});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]}});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}'
@@ -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","/**\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"]}
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","m","page","cdp","commands","target","prop","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":"6NAAO,IAAMA,CAAAA,CAAQ,CACpB,IAAA,CAAM,GACN,YAAc,CAAA,EAAA,CACd,QAAU,CAAA,EAAA,CACV,QAAU,CAAA,EACX,CAAA,CCLO,IAAMC,CAAsB,CAAA,MAAA,CAAO,IAAI,mCAAmC,CAAA,CAEpEC,CAA0B,CAAA,MAAA,CAAO,IAAI,uCAAuC,CAAA,CCFlF,SAASC,CAAYC,CAAAA,CAAAA,CAAgB,CAC3C,OAAO,IAAI,OAAmB,CAAA,CAACC,CAASC,CAAAA,CAAAA,GAAW,CAClD,IAAMC,CAAAA,CAAM,IAAI,KAAA,CAChBA,EAAI,GAAM,CAAA,CAAA,sBAAA,EAAyBH,CAAM,CAAA,CAAA,CAEzCG,CAAI,CAAA,MAAA,CAAS,IAAM,CAClB,IAAMC,CAAS,CAAA,QAAA,CAAS,aAAc,CAAA,QAAQ,EAC9CA,CAAO,CAAA,KAAA,CAAQD,CAAI,CAAA,KAAA,CACnBC,EAAO,MAASD,CAAAA,CAAAA,CAAI,MACpB,CAAA,IAAME,CAAMD,CAAAA,CAAAA,CAAO,UAAW,CAAA,IAAI,EAClCC,CAAI,CAAA,SAAA,CAAUF,CAAK,CAAA,CAAA,CAAG,CAAC,CACvBF,CAAAA,CAAAA,CAAQI,CAAI,CAAA,YAAA,CAAa,EAAG,CAAGD,CAAAA,CAAAA,CAAO,KAAOA,CAAAA,CAAAA,CAAO,MAAM,CAAC,EAC5D,CAAA,CAEAD,EAAI,OAAU,CAAA,IAAM,CACnBD,CAAAA,CAAO,IAAI,KAAM,CAAA,sBAAsB,CAAC,EACzC,EACD,CAAC,CACF,CAEA,eAAsBI,CAAUC,CAAAA,CAAAA,CAAsB,CACrD,IAAMH,EAAS,QAAS,CAAA,aAAA,CAAc,QAAQ,CAAA,CAC9C,OAAAA,CAAO,CAAA,KAAA,CAAQG,CAAU,CAAA,KAAA,CACzBH,EAAO,MAASG,CAAAA,CAAAA,CAAU,MACdH,CAAAA,CAAAA,CAAO,UAAW,CAAA,IAAI,CAC9B,CAAA,YAAA,CAAaG,EAAW,CAAG,CAAA,CAAC,CACzB,CAAA,IAAI,QAAiBN,CAAY,EAAA,CACvCG,CAAO,CAAA,MAAA,CAAQI,GAAS,CACvB,IAAMC,CAAS,CAAA,IAAI,UACnBA,CAAAA,CAAAA,CAAO,MAAS,CAAA,IAAM,CACrBR,CAAQQ,CAAAA,CAAAA,CAAO,MAAgB,EAChC,EACAA,CAAO,CAAA,aAAA,CAAcD,CAAK,EAC3B,CAAC,EACF,CAAC,CACF,CChCO,SAASE,CAAAA,CAAgBC,CAAwC,CAAA,CACvE,OAAO,CAAC,CAACA,CAAWA,EAAAA,CAAAA,CAAQ,OAASd,CACtC,CAEO,SAASe,CAAAA,CAAoBD,EAAgD,CACnF,GAAI,CAACD,CAAAA,CAAgBC,CAAO,CAAA,CAC3B,MAAM,IAAI,MAAM,0CAA0C,CAE5D,CAEO,SAASE,EAAaC,CAAkB,CAAA,CAC9C,OAAO,CAAA,EAAGA,EAAS,OAAQ,CAAA,aAAA,CAAe,GAAG,CAAA,CAAE,WAAY,EAAC,CAC7D,CAAA,CCPA,eAAsBC,CAAiCC,CAAAA,CAAAA,CAAwD,CAE9G,IAAMC,EAAeC,QAAStB,CAAAA,CAAAA,CAAM,YAAY,CAAA,CAC1CuB,EAAmB,CAAGN,EAAAA,CAAAA,CAAajB,CAAM,CAAA,QAAQ,CAAC,CAAA,CAAA,EAAIA,CAAM,CAAA,QAAA,CAASA,EAAM,QAAQ,CAAA,CAAG,KAAO,EAAA,CAAA,IAAA,CAAA,CAC7FwB,EAAeC,IAAKzB,CAAAA,CAAAA,CAAM,WAAaqB,CAAAA,CAAAA,CAAcE,CAAgB,CACrEG,CAAAA,CAAAA,CAAaD,IAAKzB,CAAAA,CAAAA,CAAM,SAAWqB,CAAAA,CAAAA,CAAcE,CAAgB,CAAA,CACjEI,EAAWF,IAAKzB,CAAAA,CAAAA,CAAM,OAASqB,CAAAA,CAAAA,CAAcE,CAAgB,CAC7DK,CAAAA,CAAAA,CAAa,MAAM,IAAA,CAAK,WAAW,CACxC,MAAA,CAAQ,CACR,CAAA,CAAA,IAAA,CAAMF,CACN,CAAA,OAAA,CAASN,CAAS,EAAA,OACnB,CAAC,CACKS,CAAAA,CAAAA,CAAQ,MAAM1B,CAAAA,CAAYyB,EAAW,MAAM,CAAA,CAEjD,OAAO,CACN,KAAM3B,CAEN,CAAA,YAAA,CAAAoB,CACA,CAAA,gBAAA,CAAAE,CACA,CAAA,YAAA,CAAAC,CACA,CAAA,UAAA,CAAAE,EACA,QAAAC,CAAAA,CAAAA,CACA,MAAQC,CAAAA,CAAAA,CAAW,MACnB,CAAA,KAAA,CAAAC,CACD,CACD,CCnBA,IAAIpB,CAAAA,CAEC,UAAmB,CAAA,kBAAA,EACvB,OAAO,yBAAyB,CAAE,CAAA,IAAA,CAAMqB,GAAM,CAC7CrB,CAAAA,CAAMqB,CACNC,CAAAA,CAAAA,CAAK,OAAO,CAAE,aAAA,CAAAZ,CAAc,CAAC,EAC9B,CAAC,CAAA,CAKK,SAASa,EAAAA,EAAkB,CACjC,OAAOvB,CAAK,EAAA,GAAA,IAAS,EACtB,CAEO,IAAMwB,EAAW,IAAI,KAAA,CAAuB,EAAC,CAAU,CAC7D,GAAIC,CAAAA,CAAAA,CAAQC,CAAM,CAAA,CACjB,OAAQD,CAAAA,CAAeC,CAAI,CAAA,EAAA,CAAM1B,GAAK,QAAiB0B,EAAAA,CAAI,CAC5D,CACD,CAAC,CAEYJ,CAAAA,CAAAA,CAAO,IAAI,KAAA,CACvB,CACC,YAAAK,CAAAA,YAAAA,CACA,SAAAC,CAAAA,SAAAA,CACA,WAAAC,CAAAA,WAAAA,CACA,SAAAC,CAAAA,SAAAA,CACA,WAAAC,UACA,CAAA,gBAAA,CAAkBC,oBAClB,CAAA,cAAA,CAAAC,cACD,CACA,CAAA,CACC,GAAIR,CAAAA,CAAAA,CAAQC,EAAM,CACjB,OAASD,CAAeC,CAAAA,CAAI,CAAK1B,EAAAA,CAAAA,EAAK,IAClCA,CAAAA,CAAAA,CAAAA,EAAK,MAAa0B,CAAI,CAAA,CACvB,IAAM,CACN,GAAIA,CAAS,GAAA,eAAA,CACZ,OAAO,CAAE,KAAMjC,CAAwB,CAAA,CAExC,OAAQ,CAAA,IAAA,CAAK,CAAUiC,OAAAA,EAAAA,CAAAA,CAAK,QAAS,EAAC,2CAA2C,EAClF,CACH,CACD,CACD,EAEaQ,EAAS,CAAA,IAAI,KA4BvB,CAAA,GAAW,CACb,GAAA,CAAIT,CAAQC,CAAAA,CAAAA,CAAM,CACjB,OAAQD,CAAeC,CAAAA,CAAI,IAAM1B,CAAK,EAAA,MAAA,EAAe0B,CAAI,CAC1D,CACD,CAAC,EClFD,eAAsBS,EACrBC,CAAAA,CAAAA,CACAzB,CACyB,CAAA,CACzB,IAAML,CAAU,CAAA,MAAM8B,CACtB,CAAA,GAAI9B,GAAS,IAASb,GAAAA,CAAAA,CACrB,OAAO4C,CAAAA,CAER,GAAI,CAAChC,CAAAA,CAAgBC,CAAO,CAAA,CAAG,CAC9B,GAAIA,CAAS,EAAA,IAAA,EAAQA,GAAS,MAC7B,CAAA,OAAO,CACN,IAAA,CAAM,GACN,MAAA8B,CAAAA,CAAAA,CACA,OAAS,CAAA,IACR,4IACF,CAGD,CAAA,GAAI,OAAO9B,CAAAA,EAAY,QACtB,CAAA,OAAO,CACN,IAAA,CAAM,GACN,MAAA8B,CAAAA,CAAAA,CACA,OAAS,CAAA,IACR,+HAA+HA,CAAM,CAAA,EAAA,CACvI,CAGF,CACA7B,EAAoBD,CAAO,CAAA,CAC3B,IAAMgC,CAAAA,CAAW,MAAMC,CAAAA,CAAgBjC,CAAQ,CAAA,YAAY,EAC3D,GAAI,CAACgC,CACJ,CAAA,OAAA,MAAMd,EAAS,QAASlB,CAAAA,CAAAA,CAAQ,UAAYA,CAAAA,CAAAA,CAAQ,YAAY,CACzD+B,CAAAA,CAAAA,CAGR,IAAMG,CAAAA,CAAgB,MAAM9C,CAAAA,CAAY4C,CAAQ,CAAA,CAC1C,CAACG,CAAaC,CAAAA,CAAa,CAAIC,CAAAA,CAAAA,CAAsBrC,EAAQ,KAAOkC,CAAAA,CAAa,CAEjF,CAAA,CAAE,KAAAI,CAAM,CAAA,UAAA,CAAAC,CAAY,CAAA,SAAA,CAAAC,CAAU,CAAA,CAAIC,CAAaL,CAAAA,CAAAA,CAAeD,EAAa9B,CAAO,CAAA,CACxF,OAAKiC,CAAAA,CAmBEP,GAlBN,MAAMW,CAAAA,CAAc,CAAG1C,EAAAA,CAAAA,CAAQ,QAAQ,CAAIwC,CAAAA,CAAAA,CAAS,CAC7C,CAAA,CACN,IAAM,CAAA,CAAA,CAAA,CACN,MAAAV,CAAAA,CAAAA,CACA,QAAS,IACRa,CAAAA,CAAAA,EACCtC,CAAS,EAAA,gBAAA,CACNA,GAAS,oBAAyB,GAAA,SAAA,CACjC,CAAkCA,+BAAAA,EAAAA,CAAAA,CAAQ,gBAAgB,CAAuBkC,oBAAAA,EAAAA,CAAU,CAC3F,EAAA,CAAA,CAAA,CAAA,+BAAA,EAAkClC,CAAQ,CAAA,gBAAgB,CAA6BkC,0BAAAA,EAAAA,CAAU,WAClG,CAA6ClC,0CAAAA,EAAAA,CAAAA,EAAS,oBAAyB,GAAA,SAAA,CAAY,GAAGkC,CAAU,CAAA,CAAA,CAAA,CAAM,CAAGA,EAAAA,CAAU,SAAS,CACxI,CAAA,CAAA,CAAA;AAAA;AAAA,gBAAA,EAEcvC,EAAQ,YAAY,CAAA;AAAA,gBAAA,EACpBA,EAAQ,UAAU,CAAA;AAAA,gBAClBA,EAAAA,CAAAA,CAAQ,QAAQ,CAAA,CAAA,CAChC,CAGF,CAAA,CAEA,IAAM+B,CAAAA,CAAU,CACf,IAAA,CAAM,CACN,CAAA,CAAA,OAAA,CAAS,IAAM,EAChB,EAEA,SAASE,CAAAA,CAAgBW,CAA2C,CAAA,CACnE,OAAO1B,CAAAA,CAAS,QAAS0B,CAAAA,CAAAA,CAAM,CAAE,QAAA,CAAU,QAAS,CAAC,CAAE,CAAA,KAAA,CAAM,IAAG,EAAY,CAC7E,CACA,eAAeF,CAAcE,CAAAA,CAAAA,CAAc9B,CAAkB,CAAA,CAC5D,IAAM+B,CAAAA,CAAAA,CAAW,MAAMlD,CAAAA,CAAUmB,CAAK,CAAA,EAAG,KAAM,CAAA,GAAG,CAAE,CAAA,CAAC,CACrD,CAAA,OAAOI,CAAS,CAAA,SAAA,CAAU0B,CAAMC,CAAAA,CAAAA,CAAS,WAAW,CACrD,CAEA,SAASR,CAAsBS,CAAAA,CAAAA,CAAmBC,EAA2D,CAC5G,GAAIC,CAAWF,CAAAA,CAAAA,CAAQC,CAAM,CAAA,CAC5B,OAAO,CAACD,CAAQC,CAAAA,CAAM,CAEvB,CAAA,IAAME,CAAOC,CAAAA,CAAAA,CAAWJ,CAAQC,CAAAA,CAAM,CAChCI,CAAAA,CAAAA,CAASC,CAAmBH,CAAAA,CAAI,CACtC,CAAA,OAAO,CAACE,CAAAA,CAAOL,CAAM,CAAA,CAAGK,CAAOJ,CAAAA,CAAM,CAAC,CACvC,CAEA,SAASG,CAAAA,CAAWJ,CAAmBC,CAAAA,CAAAA,CAAmB,CACzD,IAAMM,CAAQ,CAAA,IAAA,CAAK,GAAIP,CAAAA,CAAAA,CAAO,KAAOC,CAAAA,CAAAA,CAAO,KAAK,CAAA,CAC3CO,CAAS,CAAA,IAAA,CAAK,GAAIR,CAAAA,CAAAA,CAAO,MAAQC,CAAAA,CAAAA,CAAO,MAAM,CAAA,CACpD,OAAO,CAAE,KAAAM,CAAAA,CAAAA,CAAO,MAAAC,CAAAA,CAAO,CACxB,CAEA,SAASN,CAAWF,CAAAA,CAAAA,CAAmBC,CAAmB,CAAA,CACzD,OAAOD,CAAAA,CAAO,KAAUC,GAAAA,CAAAA,CAAO,KAASD,EAAAA,CAAAA,CAAO,MAAWC,GAAAA,CAAAA,CAAO,MAClE,CAEA,IAAMK,CAAAA,CACL,CAAC,CAAE,KAAAC,CAAAA,CAAAA,CAAO,MAAAC,CAAAA,CAAO,CAChBxC,GAAAA,CAAAA,EAAqB,CACrB,GAAIA,CAAM,CAAA,KAAA,GAAUuC,CAASvC,EAAAA,CAAAA,CAAM,SAAWwC,CAC7C,CAAA,OAAOxC,CAER,CAAA,IAAMyC,CAAS,CAAA,CAACC,CAAWC,CAAAA,CAAAA,GAAcA,CAAK3C,EAAAA,CAAAA,CAAM,MAAU0C,EAAAA,CAAAA,EAAK1C,CAAM,CAAA,KAAA,CACnE4C,CAAS,CAAA,IAAI,SAAUL,CAAAA,CAAAA,CAAOC,CAAQ,CAAA,CAAE,UAAYxC,CAAAA,CAAAA,CAAM,UAAW,CAAC,CAE5E,CAAA,IAAA,IAAS2C,CAAI,CAAA,CAAA,CAAGA,CAAIH,CAAAA,CAAAA,CAAQG,IAC3B,IAASD,IAAAA,CAAAA,CAAI,CAAGA,CAAAA,CAAAA,CAAIH,CAAOG,CAAAA,CAAAA,EAAAA,CAAK,CAC/B,IAAMG,CAAON,CAAAA,CAAAA,CAAQI,CAAID,CAAAA,CAAAA,EAAM,CAC/B,CAAA,GAAID,CAAOC,CAAAA,CAAAA,CAAGC,CAAC,CAAA,CAAG,CACjB,IAAMG,CAAO9C,CAAAA,CAAAA,CAAM,KAAQ2C,CAAAA,CAAAA,CAAID,CAAM,EAAA,CAAA,CACrCE,CAAO,CAAA,IAAA,CAAKC,CAAG,CAAA,CAAI7C,EAAM,IAAK8C,CAAAA,CAAG,CACjCF,CAAAA,CAAAA,CAAO,IAAKC,CAAAA,CAAAA,CAAM,CAAC,CAAA,CAAI7C,CAAM,CAAA,IAAA,CAAK8C,CAAM,CAAA,CAAC,CACzCF,CAAAA,CAAAA,CAAO,IAAKC,CAAAA,CAAAA,CAAM,CAAC,CAAA,CAAI7C,CAAM,CAAA,IAAA,CAAK8C,CAAM,CAAA,CAAC,CACzCF,CAAAA,CAAAA,CAAO,IAAKC,CAAAA,CAAAA,CAAM,CAAC,CAAA,CAAI7C,CAAM,CAAA,IAAA,CAAK8C,EAAM,CAAC,EAC1C,CACCF,KAAAA,CAAAA,CAAO,IAAKC,CAAAA,CAAG,CAAI,CAAA,CAAA,CACnBD,CAAO,CAAA,IAAA,CAAKC,CAAM,CAAA,CAAC,CAAI,CAAA,CAAA,CACvBD,CAAO,CAAA,IAAA,CAAKC,CAAM,CAAA,CAAC,CAAI,CAAA,CAAA,CACvBD,CAAO,CAAA,IAAA,CAAKC,CAAM,CAAA,CAAC,CAAI,CAAA,GAEzB,CAED,OAAOD,CACR,CAAA,CAED,SAASjB,CACRL,CAAAA,CAAAA,CACAD,CACA,CAAA,CAAE,gBAAA0B,CAAAA,CAAAA,CAAmB,CAAG,CAAA,oBAAA,CAAAC,CAAuB,CAAA,OAAA,CAAS,WAAAC,CAAAA,CAAY,CAA+B,CAAA,EAClG,CAAA,CACD,GAAM,CAAE,KAAAV,CAAAA,CAAAA,CAAO,MAAAC,CAAAA,CAAO,CAAInB,CAAAA,CAAAA,CACpBK,CAAY,CAAA,IAAI,SAAUa,CAAAA,CAAAA,CAAOC,CAAM,CAAA,CAEvCU,EAAYC,CAAW9B,CAAAA,CAAAA,CAAY,IAAMC,CAAAA,CAAAA,CAAc,IAAMI,CAAAA,CAAAA,CAAU,IAAMa,CAAAA,CAAAA,CAAOC,CAAQS,CAAAA,CAAW,CACvGxB,CAAAA,CAAAA,CAAa2B,CAAgB,CAAA,CAAE,oBAAAJ,CAAAA,CAAAA,CAAsB,KAAAT,CAAAA,CAAAA,CAAO,MAAAC,CAAAA,CAAO,CAAGU,CAAAA,CAAS,CAErF,CAAA,OAAO,CACN,IAAA,CAAMzB,CAAcsB,EAAAA,CAAAA,CACpB,UAAAtB,CAAAA,CAAAA,CACA,UAAAC,CACD,CACD,CAEA,SAAS0B,CACR,CAAA,CAAE,oBAAAJ,CAAAA,CAAAA,CAAsB,KAAAT,CAAAA,CAAAA,CAAO,MAAAC,CAAAA,CAAO,CACtCU,CAAAA,CAAAA,CACS,CACT,OAAQF,CAAsB,EAC7B,IAAK,OAAA,CACJ,OAAOE,CAAAA,CACR,IAAK,SAAA,CACJ,OAAQA,CAAAA,EAAaX,CAAQC,CAAAA,CAAAA,CAAAA,CAAW,GACzC,CAAA,QACC,MAAM,IAAI,KAAA,CAAM,CAAiCQ,8BAAAA,EAAAA,CAAoB,CAAE,CAAA,CACzE,CACD,CC1JO,SAASK,EAAAA,CAAmBzE,CAAqC,CAAA,CACvE,OAAKA,CAAAA,CAAI,KAAO,EAAA,IAAA,CACTA,CAAI,CAAA,KAAA,CAAM,IAAK,CAAA,WAAA,CAAY,WAAW,CAAA,CAAIA,CAAI,CAAA,KAAA,CAAM,IAAK,CAAA,WAAA,CAAY,UAAU,CAAA,CADzD,CAE9B,CAAA,CCFO,SAAS0E,EAA2BC,CAAAA,CAAAA,CAAqD,CAC/FpF,CAAAA,CAAM,IAAOoF,CAAAA,CAAAA,CAAM,IACnBpF,CAAAA,CAAAA,CAAM,YAAeoF,CAAAA,CAAAA,CAAM,IAAK,CAAA,QAAA,CAChCpF,CAAM,CAAA,YAAA,CAAesB,QAAStB,CAAAA,CAAAA,CAAM,YAAY,CAAA,CAChDA,CAAM,CAAA,UAAA,CAAaA,CAAM,CAAA,YAAA,CAAa,KAAM,CAAA,CAAA,CAAG,CAACA,CAAAA,CAAM,IAAK,CAAA,MAAM,CACjE,CAAA,IAAMqF,EAAaC,OAAQtF,CAAAA,CAAAA,CAAM,YAAY,CAAA,CAC7CA,CAAM,CAAA,WAAA,CAAcuF,QAASF,CAAAA,CAAAA,CAAY5D,IAAKzB,CAAAA,CAAAA,CAAM,UAAY,CAAA,eAAe,CAAC,CAAA,CAChFA,CAAM,CAAA,SAAA,CAAYuF,QAASF,CAAAA,CAAAA,CAAY5D,IAAKzB,CAAAA,CAAAA,CAAM,UAAY,CAAA,eAAA,CAAiB,aAAa,CAAC,CAC7FA,CAAAA,CAAAA,CAAM,OAAUuF,CAAAA,QAAAA,CAASF,CAAY5D,CAAAA,IAAAA,CAAKzB,EAAM,UAAY,CAAA,eAAA,CAAiB,iBAAiB,CAAC,EAChG,CAEO,SAASwF,EAAAA,CAA4B/E,CAAiC,CAAA,CAC5ET,CAAM,CAAA,QAAA,CAAWS,CAAI,CAAA,IAAA,CAAK,IAC1BT,CAAAA,CAAAA,CAAM,QAASA,CAAAA,CAAAA,CAAM,QAAQ,CAAA,CAAIA,CAAM,CAAA,QAAA,CAASA,CAAM,CAAA,QAAQ,CAAK,EAAA,CAAE,KAAO,CAAA,CAAE,EAC/E","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\timport('@vitest/browser/context').then((m) => {\n\t\tctx = m\n\t\tpage.extend({ imageSnapshot })\n\t})\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","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.8",
3
+ "version": "0.0.9",
4
4
  "description": "Storybook Vitest Image Snapshot addon",
5
5
  "keywords": [
6
6
  "image-snapshot",
@@ -15,8 +15,10 @@ import { imageSnapshot } from './page.image_snapshot'
15
15
  let ctx: Awaited<typeof import('@vitest/browser/context')>
16
16
 
17
17
  if ((globalThis as any).__vitest_browser__) {
18
- ctx = await import('@vitest/browser/context')
19
- // import('@vitest/browser/context').then((m) => (ctx = m))
18
+ import('@vitest/browser/context').then((m) => {
19
+ ctx = m
20
+ page.extend({ imageSnapshot })
21
+ })
20
22
  }
21
23
 
22
24
  // TODO: stub the functions within the `CDPSession`
@@ -88,5 +90,3 @@ export const server = new Proxy<{
88
90
  return (target as any)[prop] ?? (ctx?.server as any)[prop]
89
91
  },
90
92
  })
91
-
92
- page.extend({ imageSnapshot })