[{"data":1,"prerenderedAt":4459},["ShallowReactive",2],{"readme:zh-tw":3},{"id":4,"title":5,"body":6,"description":29,"extension":4451,"meta":4452,"navigation":65,"path":4453,"reviewed":4454,"seo":4455,"source":4456,"stem":4457,"__hash__":4458,"fallback":4454},"readme\u002Freadme\u002FREADME-zh-TW.md","README Zh TW",{"type":7,"value":8,"toc":4419},"minimark",[9,14,19,23,110,113,124,173,186,349,358,361,364,391,394,407,412,416,426,430,433,478,482,496,523,534,1267,1422,1425,1611,1614,1887,1898,1949,1952,1956,1959,1967,2356,2371,2428,2438,2510,2579,2587,2591,2597,2680,2703,2717,2755,2803,2811,2814,2887,2907,2911,2918,2922,2925,2948,2955,2970,2974,2989,3028,3088,3147,3151,3164,3171,3209,3269,3272,3276,3283,3341,3350,3356,3380,3409,3430,3433,3471,3531,3534,3553,3557,3564,3567,3584,3588,3591,3601,3611,3629,3632,3670,3686,3771,3777,3784,3796,3920,3924,3935,3949,4050,4054,4063,4081,4083,4121,4125,4131,4137,4149,4153,4162,4181,4191,4295,4299,4315,4334,4337,4375,4396,4400,4403,4415],[10,11,13],"h2",{"id":12},"getting-started","快速開始",[15,16,18],"h3",{"id":17},"installation","安裝",[20,21,22],"p",{},"此外掛需要 Node.js 20.9 或更新版本。您可以使用慣用的套件管理工具安裝這個函式庫：",[24,25,30],"pre",{"className":26,"code":27,"language":28,"meta":29,"style":29},"language-bash shiki shiki-themes github-light-high-contrast github-dark-high-contrast","# npm\nnpm install --save-dev @pixsame\u002Fcypress-plugin-visual-regression-diff\n\n# yarn\nyarn add -D @pixsame\u002Fcypress-plugin-visual-regression-diff\n\n# pnpm\npnpm add -D @pixsame\u002Fcypress-plugin-visual-regression-diff\n","bash","",[31,32,33,42,60,67,73,87,92,98],"code",{"__ignoreMap":29},[34,35,38],"span",{"class":36,"line":37},"line",1,[34,39,41],{"class":40},"sLBg1","# npm\n",[34,43,45,49,53,57],{"class":36,"line":44},2,[34,46,48],{"class":47},"soyes","npm",[34,50,52],{"class":51},"sT6z2"," install",[34,54,56],{"class":55},"s-5SL"," --save-dev",[34,58,59],{"class":51}," @pixsame\u002Fcypress-plugin-visual-regression-diff\n",[34,61,63],{"class":36,"line":62},3,[34,64,66],{"emptyLinePlaceholder":65},true,"\n",[34,68,70],{"class":36,"line":69},4,[34,71,72],{"class":40},"# yarn\n",[34,74,76,79,82,85],{"class":36,"line":75},5,[34,77,78],{"class":47},"yarn",[34,80,81],{"class":51}," add",[34,83,84],{"class":55}," -D",[34,86,59],{"class":51},[34,88,90],{"class":36,"line":89},6,[34,91,66],{"emptyLinePlaceholder":65},[34,93,95],{"class":36,"line":94},7,[34,96,97],{"class":40},"# pnpm\n",[34,99,101,104,106,108],{"class":36,"line":100},8,[34,102,103],{"class":47},"pnpm",[34,105,81],{"class":51},[34,107,84],{"class":55},[34,109,59],{"class":51},[20,111,112],{},"接著，您需要匯入這個函式庫：",[114,115,116],"ul",{},[117,118,119,120,123],"li",{},"首先，在 support 檔案中（預設位於 ",[31,121,122],{},"cypress\u002Fsupport\u002Findex.js","）：",[24,125,129],{"className":126,"code":127,"language":128,"meta":29,"style":29},"language-ts shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u002F\u002F typescript \u002F ES6\nimport '@pixsame\u002Fcypress-plugin-visual-regression-diff';\n\n\u002F\u002F javascript\nrequire('@pixsame\u002Fcypress-plugin-visual-regression-diff');\n","ts",[31,130,131,136,149,153,158],{"__ignoreMap":29},[34,132,133],{"class":36,"line":37},[34,134,135],{"class":40},"\u002F\u002F typescript \u002F ES6\n",[34,137,138,142,145],{"class":36,"line":44},[34,139,141],{"class":140},"sHUrx","import",[34,143,144],{"class":51}," '@pixsame\u002Fcypress-plugin-visual-regression-diff'",[34,146,148],{"class":147},"suds8",";\n",[34,150,151],{"class":36,"line":62},[34,152,66],{"emptyLinePlaceholder":65},[34,154,155],{"class":36,"line":69},[34,156,157],{"class":40},"\u002F\u002F javascript\n",[34,159,160,164,167,170],{"class":36,"line":75},[34,161,163],{"class":162},"sKwhi","require",[34,165,166],{"class":147},"(",[34,168,169],{"class":51},"'@pixsame\u002Fcypress-plugin-visual-regression-diff'",[34,171,172],{"class":147},");\n",[114,174,175],{},[117,176,177,178,181,182,185],{},"接著，在 ",[31,179,180],{},"cypress.config.js","（或 ",[31,183,184],{},"cypress.config.ts","）中：",[24,187,189],{"className":126,"code":188,"language":128,"meta":29,"style":29},"\u002F\u002F typescript \u002F ES6\nimport { defineConfig } from 'cypress';\nimport { initPlugin as initVisualRegressionPlugin } from '@pixsame\u002Fcypress-plugin-visual-regression-diff\u002Fplugins';\n\nexport default defineConfig({\n  \u002F\u002F initPlugin 必須在實際使用它的區段中呼叫：e2e 或 component\n  e2e: {\n    setupNodeEvents(on, config) {\n      initVisualRegressionPlugin(on, config);\n    },\n  },\n  component: {\n    setupNodeEvents(on, config) {\n      initVisualRegressionPlugin(on, config);\n    },\n  },\n});\n",[31,190,191,195,210,230,234,248,253,258,277,286,292,301,307,322,329,334,341],{"__ignoreMap":29},[34,192,193],{"class":36,"line":37},[34,194,135],{"class":40},[34,196,197,199,202,205,208],{"class":36,"line":44},[34,198,141],{"class":140},[34,200,201],{"class":147}," { defineConfig } ",[34,203,204],{"class":140},"from",[34,206,207],{"class":51}," 'cypress'",[34,209,148],{"class":147},[34,211,212,214,217,220,223,225,228],{"class":36,"line":62},[34,213,141],{"class":140},[34,215,216],{"class":147}," { initPlugin ",[34,218,219],{"class":140},"as",[34,221,222],{"class":147}," initVisualRegressionPlugin } ",[34,224,204],{"class":140},[34,226,227],{"class":51}," '@pixsame\u002Fcypress-plugin-visual-regression-diff\u002Fplugins'",[34,229,148],{"class":147},[34,231,232],{"class":36,"line":69},[34,233,66],{"emptyLinePlaceholder":65},[34,235,236,239,242,245],{"class":36,"line":75},[34,237,238],{"class":140},"export",[34,240,241],{"class":140}," default",[34,243,244],{"class":162}," defineConfig",[34,246,247],{"class":47},"({\n",[34,249,250],{"class":36,"line":89},[34,251,252],{"class":40},"  \u002F\u002F initPlugin 必須在實際使用它的區段中呼叫：e2e 或 component\n",[34,254,255],{"class":36,"line":94},[34,256,257],{"class":147},"  e2e: {\n",[34,259,260,263,265,268,271,274],{"class":36,"line":100},[34,261,262],{"class":162},"    setupNodeEvents",[34,264,166],{"class":147},[34,266,267],{"class":47},"on",[34,269,270],{"class":147},", ",[34,272,273],{"class":47},"config",[34,275,276],{"class":147},") {\n",[34,278,280,283],{"class":36,"line":279},9,[34,281,282],{"class":162},"      initVisualRegressionPlugin",[34,284,285],{"class":147},"(on, config);\n",[34,287,289],{"class":36,"line":288},10,[34,290,291],{"class":147},"    },\n",[34,293,295,298],{"class":36,"line":294},11,[34,296,297],{"class":147},"  }",[34,299,300],{"class":47},",\n",[34,302,304],{"class":36,"line":303},12,[34,305,306],{"class":147},"  component: {\n",[34,308,310,312,314,316,318,320],{"class":36,"line":309},13,[34,311,262],{"class":162},[34,313,166],{"class":147},[34,315,267],{"class":47},[34,317,270],{"class":147},[34,319,273],{"class":47},[34,321,276],{"class":147},[34,323,325,327],{"class":36,"line":324},14,[34,326,282],{"class":162},[34,328,285],{"class":147},[34,330,332],{"class":36,"line":331},15,[34,333,291],{"class":147},[34,335,337,339],{"class":36,"line":336},16,[34,338,297],{"class":147},[34,340,300],{"class":47},[34,342,344,347],{"class":36,"line":343},17,[34,345,346],{"class":47},"})",[34,348,148],{"class":147},[20,350,351,352,357],{},"這樣就完成了，接下來請到",[353,354,356],"a",{"href":355},"#usage","使用方式","章節看看如何使用這個函式庫。",[10,359,356],{"id":360},"usage",[20,362,363],{},"安裝完成後，只要在測試中這樣寫就能使用：",[24,365,367],{"className":126,"code":366,"language":128,"meta":29,"style":29},"cy.get('.an-element-of-your-choice').matchImage();\n",[31,368,369],{"__ignoreMap":29},[34,370,371,374,377,379,382,385,388],{"class":36,"line":37},[34,372,373],{"class":147},"cy.",[34,375,376],{"class":162},"get",[34,378,166],{"class":147},[34,380,381],{"class":51},"'.an-element-of-your-choice'",[34,383,384],{"class":147},").",[34,386,387],{"class":162},"matchImage",[34,389,390],{"class":147},"();\n",[20,392,393],{},"或者，若您想擷取整份文件的截圖：",[24,395,397],{"className":126,"code":396,"language":128,"meta":29,"style":29},"cy.matchImage();\n",[31,398,399],{"__ignoreMap":29},[34,400,401,403,405],{"class":36,"line":37},[34,402,373],{"class":147},[34,404,387],{"class":162},[34,406,390],{"class":147},[20,408,409,411],{},[31,410,387],{}," 指令會擷取一張截圖，並與上一次執行時的影像進行比對。一旦發生視覺回歸，測試就會失敗，並且會出現「See comparison」按鈕，讓您查看問題的根源。",[10,413,415],{"id":414},"example","範例",[20,417,418,419,425],{},"安裝上還是遇到問題嗎？請參考",[353,420,424],{"href":421,"rel":422},"https:\u002F\u002Fgithub.com\u002Fpixsame\u002Fpixsame\u002Ftree\u002Fmain\u002Fexamples",[423],"nofollow","這個 repo 的 examples 目錄","，看看如何在您專案的 Cypress e2e 或元件測試環境中使用這個外掛。",[10,427,429],{"id":428},"automatic-clean-up-of-unused-images","自動清理未使用的影像",[20,431,432],{},"把視覺回歸外掛產生、但已經沒有任何測試在使用的截圖清掉，是很實用的功能。\n透過 expose 變數啟用這項功能，即可釋放儲存空間 🚀：",[24,434,436],{"className":26,"code":435,"language":28,"meta":29,"style":29},"# Cypress 15.10+\nnpx cypress run --expose \"pluginVisualRegressionCleanupUnusedImages=true\"\n# Cypress \u003C15.10（15.10 起棄用，16 已移除）\nnpx cypress run --env \"pluginVisualRegressionCleanupUnusedImages=true\"\n",[31,437,438,443,460,465],{"__ignoreMap":29},[34,439,440],{"class":36,"line":37},[34,441,442],{"class":40},"# Cypress 15.10+\n",[34,444,445,448,451,454,457],{"class":36,"line":44},[34,446,447],{"class":47},"npx",[34,449,450],{"class":51}," cypress",[34,452,453],{"class":51}," run",[34,455,456],{"class":55}," --expose",[34,458,459],{"class":51}," \"pluginVisualRegressionCleanupUnusedImages=true\"\n",[34,461,462],{"class":36,"line":62},[34,463,464],{"class":40},"# Cypress \u003C15.10（15.10 起棄用，16 已移除）\n",[34,466,467,469,471,473,476],{"class":36,"line":69},[34,468,447],{"class":47},[34,470,450],{"class":51},[34,472,453],{"class":51},[34,474,475],{"class":55}," --env",[34,477,459],{"class":51},[10,479,481],{"id":480},"run-manifest-ci-integration","執行清單（CI 整合）",[20,483,484,485,487,488,491,492,495],{},"從 1.1 起，每次執行都會寫出一份 JSON 清單（manifest），列出每一次 ",[31,486,387],{}," 比對：來自哪個測試、是通過、失敗、建立還是更新了基準影像、差異比例，以及基準影像、",[31,489,490],{},".actual.png"," 與 ",[31,493,494],{},".diff.png"," 檔案相對於專案的路徑。在這些條目旁邊，它也會記錄這次執行發生的位置（CI 供應商、repository、commit、pull request、run id）與執行所用的環境（瀏覽器、spec、設定檔、外掛選項），因此讀取這個檔案的工具可以回報到正確的 PR、下載正確的 artifact，或重新執行同樣的比對。它是為了在 Cypress 跑完之後才執行的 CI 工具（PR 留言、審閱儀表板、核准機器人）而設計的。",[20,497,498,499,504,505,510,511,518,519,522],{},"這個格式是以 ",[353,500,503],{"href":501,"rel":502},"https:\u002F\u002Fctrf.io",[423],"CTRF"," 為基礎、與執行器無關的開放標準，文件位於 ",[353,506,509],{"href":507,"rel":508},"https:\u002F\u002Fvisual-regression.dev\u002Fmanifest",[423],"visual-regression.dev\u002Fmanifest","。npm 套件 ",[353,512,515],{"href":513,"rel":514},"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fvisual-regression-manifest",[423],[31,516,517],{},"visual-regression-manifest"," 提供 JSON Schema、TypeScript 型別、會驗證的讀取器、能合併整次執行所有清單的合併器，以及給本身不會寫出清單的工具使用的轉換器（Playwright 的 ",[31,520,521],{},"toHaveScreenshot","、Vitest、jest-image-snapshot、BackstopJS、CTRF 報告、單純的影像檔案）。請以該套件而非這個外掛為基礎來建構您的工具。",[20,524,525,526,529,530,533],{},"預設情況下，這個檔案會和您其他的 Cypress artifact 放在一起，位於 ",[31,527,528],{},"\u003CscreenshotsFolder>\u002Fvisual-regression-manifest.\u003CtestingType>.json","（例如 ",[31,531,532],{},"cypress\u002Fscreenshots\u002Fvisual-regression-manifest.e2e.json","）。請把它和您的快照目錄一起上傳為 CI artifact。",[24,535,539],{"className":536,"code":537,"language":538,"meta":29,"style":29},"language-jsonc shiki shiki-themes github-light-high-contrast github-dark-high-contrast","{\n  \"reportFormat\": \"visual-regression-manifest\",\n  \"specVersion\": \"1.0.0-beta.1\",\n  \"createdAt\": \"2026-09-22T10:00:00.000Z\",\n  \"updatedAt\": \"2026-09-22T10:03:12.481Z\",\n  \"projectRoot\": \"\u002Fhome\u002Frunner\u002Fwork\u002Fapp\u002Fapp\",\n  \"platform\": {\n    \"osPlatform\": \"linux\",\n    \"arch\": \"x64\",\n    \"osRelease\": \"6.8.0-1021-azure\",\n  },\n  \"ci\": {\n    \"provider\": \"github\",\n    \"repositoryName\": \"acme\u002Fapp\",\n    \"repositoryUrl\": \"https:\u002F\u002Fgithub.com\u002Facme\u002Fapp\",\n    \"commit\": \"0f1e2d…\", \u002F\u002F 在 pull_request 事件中：合併 commit\n    \"ref\": \"refs\u002Fpull\u002F42\u002Fmerge\",\n    \"branchName\": \"feat\u002Fnew-header\",\n    \"pullRequest\": {\n      \"number\": 42,\n      \"headSha\": \"9a8b7c…\",\n      \"headRef\": \"feat\u002Fnew-header\",\n      \"baseRef\": \"main\",\n    },\n    \"event\": \"pull_request\",\n    \"buildId\": \"1234567890\",\n    \"buildName\": \"CI\",\n    \"buildUrl\": \"https:\u002F\u002Fgithub.com\u002Facme\u002Fapp\u002Factions\u002Fruns\u002F1234567890\u002Fattempts\u002F1\",\n    \"runAttempt\": \"1\",\n    \"job\": \"e2e\",\n    \"workspace\": \"\u002Fhome\u002Frunner\u002Fwork\u002Fapp\u002Fapp\",\n  },\n  \"tool\": {\n    \"name\": \"@pixsame\u002Fcypress-plugin-visual-regression-diff\",\n    \"version\": \"1.1.0\",\n  }, \u002F\u002F 寫出這個檔案的工具\n  \"options\": { \"updateImages\": \"failures-only\" }, \u002F\u002F 全域的 pluginVisualRegression* 選項，已去除前綴\n  \"runner\": {\n    \"name\": \"cypress\",\n    \"version\": \"16.1.0\",\n    \"testingType\": \"e2e\",\n    \"mode\": \"run\",\n    \"configFile\": \"cypress.config.ts\",\n    \"browser\": {\n      \"name\": \"chrome\",\n      \"version\": \"130.0.0.0\",\n      \"family\": \"chromium\",\n      \"headless\": true,\n    },\n    \"specs\": [\"cypress\u002Fe2e\u002Fhome.cy.ts\"],\n    \"specPattern\": \"cypress\u002Fe2e\u002F**\u002F*.cy.{js,jsx,ts,tsx}\",\n    \"baseUrl\": \"http:\u002F\u002Flocalhost:3000\",\n    \"viewport\": { \"width\": 1280, \"height\": 720 },\n  },\n  \"summary\": {\n    \"entries\": 1,\n    \"passed\": 0,\n    \"failed\": 1,\n    \"missingBaseline\": 0,\n    \"created\": 0,\n    \"updated\": 0,\n    \"approved\": 0,\n    \"needsHuman\": 1,\n  },\n  \"entries\": [\n    {\n      \"name\": \"home page renders_#0\",\n      \"test\": {\n        \"filePath\": \"cypress\u002Fe2e\u002Fhome.cy.ts\",\n        \"titlePath\": [\"home page\", \"renders\"],\n        \"retry\": 0,\n      },\n      \"status\": \"failed\",\n      \"comparison\": { \"diffRatio\": 0.0231, \"threshold\": 0.01 },\n      \"images\": {\n        \"baseline\": {\n          \"path\": \"cypress\u002Fe2e\u002F__image_snapshots__\u002Fhome page renders_#0.png\",\n          \"width\": 1280,\n          \"height\": 720,\n        },\n        \"actual\": {\n          \"path\": \"cypress\u002Fe2e\u002F__image_snapshots__\u002Fhome page renders_#0.actual.png\",\n          \"width\": 1280,\n          \"height\": 720,\n        },\n        \"diff\": {\n          \"path\": \"cypress\u002Fe2e\u002F__image_snapshots__\u002Fhome page renders_#0.diff.png\",\n        },\n      },\n      \"baselineWritten\": false,\n      \"recordedAt\": \"2026-09-22T10:03:12.480Z\",\n      \"platform\": {\n        \"osPlatform\": \"linux\",\n        \"arch\": \"x64\",\n        \"browser\": {\n          \"name\": \"chrome\",\n          \"version\": \"130.0.0.0\",\n          \"family\": \"chromium\",\n          \"headless\": true,\n        },\n      },\n      \"viewport\": { \"width\": 1280, \"height\": 720 },\n      \"options\": {\n        \"imagesPath\": \"{spec_path}\u002F__image_snapshots__\",\n        \"maxDiffThreshold\": 0.01,\n        \"diffConfig\": {},\n        \"createMissingImages\": true,\n        \"updateImages\": false,\n        \"forceDeviceScaleFactor\": true,\n        \"screenshotConfig\": {},\n      },\n      \"renderer\": {\n        \"backend\": \"native\",\n        \"browser\": \"chrome\",\n        \"browserVersion\": \"130.0.0.0\",\n      },\n      \"hashes\": {\n        \"baseline\": \"3b7e…\", \u002F\u002F `images` 中所列檔案的 sha256，只有實際存在的檔案才會有\n        \"actual\": \"9d21…\",\n        \"diff\": \"c0ff…\",\n      },\n      \"message\": \"2310 pixels (2.31%) differ; the limit is 1%.\",\n    },\n  ],\n}\n","jsonc",[31,540,541,546,551,556,561,566,571,576,581,586,591,596,601,606,611,616,624,629,635,641,647,653,659,665,670,676,682,688,694,700,706,712,717,723,729,735,741,750,756,762,768,774,780,786,792,798,804,810,816,821,827,833,839,845,850,856,862,868,874,880,886,892,898,904,909,915,921,927,933,939,945,951,957,963,969,975,981,987,993,999,1005,1011,1017,1022,1027,1032,1038,1044,1049,1054,1060,1066,1072,1078,1084,1090,1096,1102,1108,1114,1119,1124,1130,1136,1142,1148,1154,1160,1166,1172,1178,1183,1189,1195,1201,1207,1212,1218,1227,1233,1239,1244,1250,1255,1261],{"__ignoreMap":29},[34,542,543],{"class":36,"line":37},[34,544,545],{},"{\n",[34,547,548],{"class":36,"line":44},[34,549,550],{},"  \"reportFormat\": \"visual-regression-manifest\",\n",[34,552,553],{"class":36,"line":62},[34,554,555],{},"  \"specVersion\": \"1.0.0-beta.1\",\n",[34,557,558],{"class":36,"line":69},[34,559,560],{},"  \"createdAt\": \"2026-09-22T10:00:00.000Z\",\n",[34,562,563],{"class":36,"line":75},[34,564,565],{},"  \"updatedAt\": \"2026-09-22T10:03:12.481Z\",\n",[34,567,568],{"class":36,"line":89},[34,569,570],{},"  \"projectRoot\": \"\u002Fhome\u002Frunner\u002Fwork\u002Fapp\u002Fapp\",\n",[34,572,573],{"class":36,"line":94},[34,574,575],{},"  \"platform\": {\n",[34,577,578],{"class":36,"line":100},[34,579,580],{},"    \"osPlatform\": \"linux\",\n",[34,582,583],{"class":36,"line":279},[34,584,585],{},"    \"arch\": \"x64\",\n",[34,587,588],{"class":36,"line":288},[34,589,590],{},"    \"osRelease\": \"6.8.0-1021-azure\",\n",[34,592,593],{"class":36,"line":294},[34,594,595],{},"  },\n",[34,597,598],{"class":36,"line":303},[34,599,600],{},"  \"ci\": {\n",[34,602,603],{"class":36,"line":309},[34,604,605],{},"    \"provider\": \"github\",\n",[34,607,608],{"class":36,"line":324},[34,609,610],{},"    \"repositoryName\": \"acme\u002Fapp\",\n",[34,612,613],{"class":36,"line":331},[34,614,615],{},"    \"repositoryUrl\": \"https:\u002F\u002Fgithub.com\u002Facme\u002Fapp\",\n",[34,617,618,621],{"class":36,"line":336},[34,619,620],{},"    \"commit\": \"0f1e2d…\",",[34,622,623],{}," \u002F\u002F 在 pull_request 事件中：合併 commit\n",[34,625,626],{"class":36,"line":343},[34,627,628],{},"    \"ref\": \"refs\u002Fpull\u002F42\u002Fmerge\",\n",[34,630,632],{"class":36,"line":631},18,[34,633,634],{},"    \"branchName\": \"feat\u002Fnew-header\",\n",[34,636,638],{"class":36,"line":637},19,[34,639,640],{},"    \"pullRequest\": {\n",[34,642,644],{"class":36,"line":643},20,[34,645,646],{},"      \"number\": 42,\n",[34,648,650],{"class":36,"line":649},21,[34,651,652],{},"      \"headSha\": \"9a8b7c…\",\n",[34,654,656],{"class":36,"line":655},22,[34,657,658],{},"      \"headRef\": \"feat\u002Fnew-header\",\n",[34,660,662],{"class":36,"line":661},23,[34,663,664],{},"      \"baseRef\": \"main\",\n",[34,666,668],{"class":36,"line":667},24,[34,669,291],{},[34,671,673],{"class":36,"line":672},25,[34,674,675],{},"    \"event\": \"pull_request\",\n",[34,677,679],{"class":36,"line":678},26,[34,680,681],{},"    \"buildId\": \"1234567890\",\n",[34,683,685],{"class":36,"line":684},27,[34,686,687],{},"    \"buildName\": \"CI\",\n",[34,689,691],{"class":36,"line":690},28,[34,692,693],{},"    \"buildUrl\": \"https:\u002F\u002Fgithub.com\u002Facme\u002Fapp\u002Factions\u002Fruns\u002F1234567890\u002Fattempts\u002F1\",\n",[34,695,697],{"class":36,"line":696},29,[34,698,699],{},"    \"runAttempt\": \"1\",\n",[34,701,703],{"class":36,"line":702},30,[34,704,705],{},"    \"job\": \"e2e\",\n",[34,707,709],{"class":36,"line":708},31,[34,710,711],{},"    \"workspace\": \"\u002Fhome\u002Frunner\u002Fwork\u002Fapp\u002Fapp\",\n",[34,713,715],{"class":36,"line":714},32,[34,716,595],{},[34,718,720],{"class":36,"line":719},33,[34,721,722],{},"  \"tool\": {\n",[34,724,726],{"class":36,"line":725},34,[34,727,728],{},"    \"name\": \"@pixsame\u002Fcypress-plugin-visual-regression-diff\",\n",[34,730,732],{"class":36,"line":731},35,[34,733,734],{},"    \"version\": \"1.1.0\",\n",[34,736,738],{"class":36,"line":737},36,[34,739,740],{},"  }, \u002F\u002F 寫出這個檔案的工具\n",[34,742,744,747],{"class":36,"line":743},37,[34,745,746],{},"  \"options\": { \"updateImages\": \"failures-only\" },",[34,748,749],{}," \u002F\u002F 全域的 pluginVisualRegression* 選項，已去除前綴\n",[34,751,753],{"class":36,"line":752},38,[34,754,755],{},"  \"runner\": {\n",[34,757,759],{"class":36,"line":758},39,[34,760,761],{},"    \"name\": \"cypress\",\n",[34,763,765],{"class":36,"line":764},40,[34,766,767],{},"    \"version\": \"16.1.0\",\n",[34,769,771],{"class":36,"line":770},41,[34,772,773],{},"    \"testingType\": \"e2e\",\n",[34,775,777],{"class":36,"line":776},42,[34,778,779],{},"    \"mode\": \"run\",\n",[34,781,783],{"class":36,"line":782},43,[34,784,785],{},"    \"configFile\": \"cypress.config.ts\",\n",[34,787,789],{"class":36,"line":788},44,[34,790,791],{},"    \"browser\": {\n",[34,793,795],{"class":36,"line":794},45,[34,796,797],{},"      \"name\": \"chrome\",\n",[34,799,801],{"class":36,"line":800},46,[34,802,803],{},"      \"version\": \"130.0.0.0\",\n",[34,805,807],{"class":36,"line":806},47,[34,808,809],{},"      \"family\": \"chromium\",\n",[34,811,813],{"class":36,"line":812},48,[34,814,815],{},"      \"headless\": true,\n",[34,817,819],{"class":36,"line":818},49,[34,820,291],{},[34,822,824],{"class":36,"line":823},50,[34,825,826],{},"    \"specs\": [\"cypress\u002Fe2e\u002Fhome.cy.ts\"],\n",[34,828,830],{"class":36,"line":829},51,[34,831,832],{},"    \"specPattern\": \"cypress\u002Fe2e\u002F**\u002F*.cy.{js,jsx,ts,tsx}\",\n",[34,834,836],{"class":36,"line":835},52,[34,837,838],{},"    \"baseUrl\": \"http:\u002F\u002Flocalhost:3000\",\n",[34,840,842],{"class":36,"line":841},53,[34,843,844],{},"    \"viewport\": { \"width\": 1280, \"height\": 720 },\n",[34,846,848],{"class":36,"line":847},54,[34,849,595],{},[34,851,853],{"class":36,"line":852},55,[34,854,855],{},"  \"summary\": {\n",[34,857,859],{"class":36,"line":858},56,[34,860,861],{},"    \"entries\": 1,\n",[34,863,865],{"class":36,"line":864},57,[34,866,867],{},"    \"passed\": 0,\n",[34,869,871],{"class":36,"line":870},58,[34,872,873],{},"    \"failed\": 1,\n",[34,875,877],{"class":36,"line":876},59,[34,878,879],{},"    \"missingBaseline\": 0,\n",[34,881,883],{"class":36,"line":882},60,[34,884,885],{},"    \"created\": 0,\n",[34,887,889],{"class":36,"line":888},61,[34,890,891],{},"    \"updated\": 0,\n",[34,893,895],{"class":36,"line":894},62,[34,896,897],{},"    \"approved\": 0,\n",[34,899,901],{"class":36,"line":900},63,[34,902,903],{},"    \"needsHuman\": 1,\n",[34,905,907],{"class":36,"line":906},64,[34,908,595],{},[34,910,912],{"class":36,"line":911},65,[34,913,914],{},"  \"entries\": [\n",[34,916,918],{"class":36,"line":917},66,[34,919,920],{},"    {\n",[34,922,924],{"class":36,"line":923},67,[34,925,926],{},"      \"name\": \"home page renders_#0\",\n",[34,928,930],{"class":36,"line":929},68,[34,931,932],{},"      \"test\": {\n",[34,934,936],{"class":36,"line":935},69,[34,937,938],{},"        \"filePath\": \"cypress\u002Fe2e\u002Fhome.cy.ts\",\n",[34,940,942],{"class":36,"line":941},70,[34,943,944],{},"        \"titlePath\": [\"home page\", \"renders\"],\n",[34,946,948],{"class":36,"line":947},71,[34,949,950],{},"        \"retry\": 0,\n",[34,952,954],{"class":36,"line":953},72,[34,955,956],{},"      },\n",[34,958,960],{"class":36,"line":959},73,[34,961,962],{},"      \"status\": \"failed\",\n",[34,964,966],{"class":36,"line":965},74,[34,967,968],{},"      \"comparison\": { \"diffRatio\": 0.0231, \"threshold\": 0.01 },\n",[34,970,972],{"class":36,"line":971},75,[34,973,974],{},"      \"images\": {\n",[34,976,978],{"class":36,"line":977},76,[34,979,980],{},"        \"baseline\": {\n",[34,982,984],{"class":36,"line":983},77,[34,985,986],{},"          \"path\": \"cypress\u002Fe2e\u002F__image_snapshots__\u002Fhome page renders_#0.png\",\n",[34,988,990],{"class":36,"line":989},78,[34,991,992],{},"          \"width\": 1280,\n",[34,994,996],{"class":36,"line":995},79,[34,997,998],{},"          \"height\": 720,\n",[34,1000,1002],{"class":36,"line":1001},80,[34,1003,1004],{},"        },\n",[34,1006,1008],{"class":36,"line":1007},81,[34,1009,1010],{},"        \"actual\": {\n",[34,1012,1014],{"class":36,"line":1013},82,[34,1015,1016],{},"          \"path\": \"cypress\u002Fe2e\u002F__image_snapshots__\u002Fhome page renders_#0.actual.png\",\n",[34,1018,1020],{"class":36,"line":1019},83,[34,1021,992],{},[34,1023,1025],{"class":36,"line":1024},84,[34,1026,998],{},[34,1028,1030],{"class":36,"line":1029},85,[34,1031,1004],{},[34,1033,1035],{"class":36,"line":1034},86,[34,1036,1037],{},"        \"diff\": {\n",[34,1039,1041],{"class":36,"line":1040},87,[34,1042,1043],{},"          \"path\": \"cypress\u002Fe2e\u002F__image_snapshots__\u002Fhome page renders_#0.diff.png\",\n",[34,1045,1047],{"class":36,"line":1046},88,[34,1048,1004],{},[34,1050,1052],{"class":36,"line":1051},89,[34,1053,956],{},[34,1055,1057],{"class":36,"line":1056},90,[34,1058,1059],{},"      \"baselineWritten\": false,\n",[34,1061,1063],{"class":36,"line":1062},91,[34,1064,1065],{},"      \"recordedAt\": \"2026-09-22T10:03:12.480Z\",\n",[34,1067,1069],{"class":36,"line":1068},92,[34,1070,1071],{},"      \"platform\": {\n",[34,1073,1075],{"class":36,"line":1074},93,[34,1076,1077],{},"        \"osPlatform\": \"linux\",\n",[34,1079,1081],{"class":36,"line":1080},94,[34,1082,1083],{},"        \"arch\": \"x64\",\n",[34,1085,1087],{"class":36,"line":1086},95,[34,1088,1089],{},"        \"browser\": {\n",[34,1091,1093],{"class":36,"line":1092},96,[34,1094,1095],{},"          \"name\": \"chrome\",\n",[34,1097,1099],{"class":36,"line":1098},97,[34,1100,1101],{},"          \"version\": \"130.0.0.0\",\n",[34,1103,1105],{"class":36,"line":1104},98,[34,1106,1107],{},"          \"family\": \"chromium\",\n",[34,1109,1111],{"class":36,"line":1110},99,[34,1112,1113],{},"          \"headless\": true,\n",[34,1115,1117],{"class":36,"line":1116},100,[34,1118,1004],{},[34,1120,1122],{"class":36,"line":1121},101,[34,1123,956],{},[34,1125,1127],{"class":36,"line":1126},102,[34,1128,1129],{},"      \"viewport\": { \"width\": 1280, \"height\": 720 },\n",[34,1131,1133],{"class":36,"line":1132},103,[34,1134,1135],{},"      \"options\": {\n",[34,1137,1139],{"class":36,"line":1138},104,[34,1140,1141],{},"        \"imagesPath\": \"{spec_path}\u002F__image_snapshots__\",\n",[34,1143,1145],{"class":36,"line":1144},105,[34,1146,1147],{},"        \"maxDiffThreshold\": 0.01,\n",[34,1149,1151],{"class":36,"line":1150},106,[34,1152,1153],{},"        \"diffConfig\": {},\n",[34,1155,1157],{"class":36,"line":1156},107,[34,1158,1159],{},"        \"createMissingImages\": true,\n",[34,1161,1163],{"class":36,"line":1162},108,[34,1164,1165],{},"        \"updateImages\": false,\n",[34,1167,1169],{"class":36,"line":1168},109,[34,1170,1171],{},"        \"forceDeviceScaleFactor\": true,\n",[34,1173,1175],{"class":36,"line":1174},110,[34,1176,1177],{},"        \"screenshotConfig\": {},\n",[34,1179,1181],{"class":36,"line":1180},111,[34,1182,956],{},[34,1184,1186],{"class":36,"line":1185},112,[34,1187,1188],{},"      \"renderer\": {\n",[34,1190,1192],{"class":36,"line":1191},113,[34,1193,1194],{},"        \"backend\": \"native\",\n",[34,1196,1198],{"class":36,"line":1197},114,[34,1199,1200],{},"        \"browser\": \"chrome\",\n",[34,1202,1204],{"class":36,"line":1203},115,[34,1205,1206],{},"        \"browserVersion\": \"130.0.0.0\",\n",[34,1208,1210],{"class":36,"line":1209},116,[34,1211,956],{},[34,1213,1215],{"class":36,"line":1214},117,[34,1216,1217],{},"      \"hashes\": {\n",[34,1219,1221,1224],{"class":36,"line":1220},118,[34,1222,1223],{},"        \"baseline\": \"3b7e…\",",[34,1225,1226],{}," \u002F\u002F `images` 中所列檔案的 sha256，只有實際存在的檔案才會有\n",[34,1228,1230],{"class":36,"line":1229},119,[34,1231,1232],{},"        \"actual\": \"9d21…\",\n",[34,1234,1236],{"class":36,"line":1235},120,[34,1237,1238],{},"        \"diff\": \"c0ff…\",\n",[34,1240,1242],{"class":36,"line":1241},121,[34,1243,956],{},[34,1245,1247],{"class":36,"line":1246},122,[34,1248,1249],{},"      \"message\": \"2310 pixels (2.31%) differ; the limit is 1%.\",\n",[34,1251,1253],{"class":36,"line":1252},123,[34,1254,291],{},[34,1256,1258],{"class":36,"line":1257},124,[34,1259,1260],{},"  ],\n",[34,1262,1264],{"class":36,"line":1263},125,[34,1265,1266],{},"}\n",[1268,1269,1270,1295],"table",{},[1271,1272,1273],"thead",{},[1274,1275,1276,1282,1285,1290],"tr",{},[1277,1278,1279],"th",{},[31,1280,1281],{},"status",[1277,1283,1284],{},"意義",[1277,1286,1287],{},[31,1288,1289],{},"images.actual.path",[1277,1291,1292],{},[31,1293,1294],{},"images.diff.path",[1296,1297,1298,1318,1338,1357,1378,1404],"tbody",{},[1274,1299,1300,1306,1309,1314],{},[1301,1302,1303],"td",{},[31,1304,1305],{},"passed",[1301,1307,1308],{},"在門檻值範圍內",[1301,1310,1311],{},[31,1312,1313],{},"null",[1301,1315,1316],{},[31,1317,1313],{},[1274,1319,1320,1325,1333,1336],{},[1301,1321,1322],{},[31,1323,1324],{},"failed",[1301,1326,1327,1328,491,1330,1332],{},"超過門檻值，保留 ",[31,1329,490],{},[31,1331,494],{}," 供審閱",[1301,1334,1335],{},"路徑",[1301,1337,1335],{},[1274,1339,1340,1345,1351,1353],{},[1301,1341,1342],{},[31,1343,1344],{},"missing-baseline",[1301,1346,1347,1348],{},"沒有基準影像，且 ",[31,1349,1350],{},"createMissingImages: false",[1301,1352,1335],{},[1301,1354,1355],{},[31,1356,1313],{},[1274,1358,1359,1364,1370,1374],{},[1301,1360,1361],{},[31,1362,1363],{},"created",[1301,1365,1366,1367,1369],{},"沒有基準影像，",[31,1368,490],{}," 成為基準影像",[1301,1371,1372],{},[31,1373,1313],{},[1301,1375,1376],{},[31,1377,1313],{},[1274,1379,1380,1385,1396,1400],{},[1301,1381,1382],{},[31,1383,1384],{},"updated",[1301,1386,1387,1388,1391,1392,1395],{},"基準影像已被覆寫（",[31,1389,1390],{},"updateImages: true"," 或 ",[31,1393,1394],{},"'failures-only'","）",[1301,1397,1398],{},[31,1399,1313],{},[1301,1401,1402],{},[31,1403,1313],{},[1274,1405,1406,1411,1414,1418],{},[1301,1407,1408],{},[31,1409,1410],{},"approved",[1301,1412,1413],{},"基準影像已從有頭模式的審閱介面取代（「Replace image」）",[1301,1415,1416],{},[31,1417,1313],{},[1301,1419,1420],{},[31,1421,1313],{},[20,1423,1424],{},"執行層級的欄位：",[1268,1426,1427,1436],{},[1271,1428,1429],{},[1274,1430,1431,1434],{},[1277,1432,1433],{},"欄位",[1277,1435,1284],{},[1296,1437,1438,1452,1486,1496,1517,1539,1590],{},[1274,1439,1440,1449],{},[1301,1441,1442,1445,1446],{},[31,1443,1444],{},"createdAt","、",[31,1447,1448],{},"updatedAt",[1301,1450,1451],{},"執行開始的時間，以及檔案最後一次被重寫的時間（ISO 8601）",[1274,1453,1454,1459],{},[1301,1455,1456],{},[31,1457,1458],{},"platform",[1301,1460,1461,1464,1465,1445,1468,1445,1471,1474,1475,1478,1479,1482,1483],{},[31,1462,1463],{},"osPlatform","（",[31,1466,1467],{},"linux",[31,1469,1470],{},"darwin",[31,1472,1473],{},"win32","）、",[31,1476,1477],{},"arch","、核心的 ",[31,1480,1481],{},"osRelease","，以及在 run 模式下，執行測試的機器可讀性較高的 ",[31,1484,1485],{},"osVersion",[1274,1487,1488,1493],{},[1301,1489,1490],{},[31,1491,1492],{},"tool",[1301,1494,1495],{},"寫出這個檔案的工具：這個外掛及其版本",[1274,1497,1498,1503],{},[1301,1499,1500],{},[31,1501,1502],{},"ci",[1301,1504,1505,1506,1509,1510,1513,1514,1516],{},"在 GitHub Actions 與 GitLab CI 上由環境變數偵測；在其他 CI 系統上為 ",[31,1507,1508],{},"{ \"provider\": null }","（只有 ",[31,1511,1512],{},"CI"," 被設定），不在 CI 上時為 ",[31,1515,1313],{},"。只有列出的這些鍵會從環境變數複製",[1274,1518,1519,1524],{},[1301,1520,1521],{},[31,1522,1523],{},"options",[1301,1525,1526,1527,1530,1531,1534,1535,1538],{},"來自 ",[31,1528,1529],{},"expose","\u002F",[31,1532,1533],{},"env"," 的每個 ",[31,1536,1537],{},"pluginVisualRegression*"," 選項，已去除前綴，值與設定時相同（CLI 傳入的值維持字串）",[1274,1540,1541,1546],{},[1301,1542,1543],{},[31,1544,1545],{},"runner",[1301,1547,1548,1549,1552,1553,1391,1556,1559,1560,1563,1564,1567,1568,491,1571,1573,1574,1577,1578,1445,1581,1445,1584,1445,1587],{},"執行測試的工具。",[31,1550,1551],{},"mode"," 為 ",[31,1554,1555],{},"run",[31,1557,1558],{},"open","；",[31,1561,1562],{},"browser"," 是啟動的瀏覽器；",[31,1565,1566],{},"specs"," 只在 run 模式下才知道；",[31,1569,1570],{},"configFile",[31,1572,1566],{}," 相對於 ",[31,1575,1576],{},"projectRoot","。Cypress Cloud 的執行還會有 ",[31,1579,1580],{},"cloud.runUrl",[31,1582,1583],{},"group",[31,1585,1586],{},"tag",[31,1588,1589],{},"parallel",[1274,1591,1592,1597],{},[1301,1593,1594],{},[31,1595,1596],{},"summary",[1301,1598,1599,1600,1603,1604,1606,1607,1610],{},"各狀態的條目數量；",[31,1601,1602],{},"needsHuman"," 是 ",[31,1605,1324],{}," + ",[31,1608,1609],{},"missingBaseline","，讓消費端不必讀取條目就能做決定",[20,1612,1613],{},"給消費端的注意事項：",[114,1615,1616,1644,1658,1667,1718,1739,1774,1784,1817,1831,1852,1873],{},[117,1617,1618,1619,1621,1622,1624,1625,1628,1629,1632,1633,1635,1636,1639,1640,1643],{},"所有路徑都相對於 ",[31,1620,1576],{},"，並使用 ",[31,1623,1530],{}," 作為分隔符號；當 ",[31,1626,1627],{},"imagesPath"," 是絕對路徑時，路徑可能指向專案之外（",[31,1630,1631],{},"..\u002F…","）。",[31,1634,1576],{}," 是 Cypress 專案，不一定是 repository 的根目錄：",[31,1637,1638],{},"ci.workspace"," 是 checkout 目錄，所以 ",[31,1641,1642],{},"relative(ci.workspace, projectRoot)"," 就是 repository 內的路徑前綴。",[117,1645,1646,491,1648,1650,1651,1653,1654,1657],{},[31,1647,1324],{},[31,1649,1344],{}," 是需要人工處理的條目：把 ",[31,1652,1289],{}," 複製到 ",[31,1655,1656],{},"images.baseline.path"," 即可核准它們。",[117,1659,1660,1663,1664,1666],{},[31,1661,1662],{},"baselineWritten"," 表示該張截圖的工作樹是否有變更，與 ",[31,1665,1281],{}," 無關。",[117,1668,1669,1670,1673,1674,1677,1678,1464,1681,1445,1684,1445,1687,1391,1690,1693,1694,1697,1698,1701,1702,1705,1706,1709,1710,1713,1714,1717],{},"比對發現差異的項目帶有 ",[31,1671,1672],{},"extra.pixsame.analysis","（除非關閉了 ",[31,1675,1676],{},"analysis","）：一個 ",[31,1679,1680],{},"label",[31,1682,1683],{},"content-change",[31,1685,1686],{},"moved",[31,1688,1689],{},"noise-like",[31,1691,1692],{},"size-change","）、一句話的 ",[31,1695,1696],{},"description","、發生變化的 ",[31,1699,1700],{},"regions"," 及其邊框、偵測到的 ",[31,1703,1704],{},"shift","，以及一個 ",[31,1707,1708],{},"bundleKey","，以相同方式變化的項目其值相同。",[31,1711,1712],{},"@pixsame\u002Fanalysis"," 中的 ",[31,1715,1716],{},"bundle()"," 會依它將項目分組。",[117,1719,1720,1721,491,1723,1726,1727,1603,1729,1731,1732,1734,1735,1738],{},"每個條目都帶有自己的 ",[31,1722,1458],{},[31,1724,1725],{},"viewport","，因此把多份清單串接後，仍能分辨來自不同機器矩陣的條目。條目上的 ",[31,1728,1523],{},[31,1730,387],{}," 確切的輸入（",[31,1733,1627],{}," 保留未展開的 token）；",[31,1736,1737],{},"comparison"," 則是結果。",[117,1740,1741,1743,1744,1747,1748,1603,1751,1754,1755,1758,1759,1762,1763,491,1766,1769,1770,1773],{},[31,1742,1458],{}," 是測試執行的位置，",[31,1745,1746],{},"renderer"," 是像素的來源。目前每張截圖都是由 Cypress 驅動的瀏覽器拍攝的，所以 ",[31,1749,1750],{},"renderer.backend",[31,1752,1753],{},"native","，而 ",[31,1756,1757],{},"renderer.browser"," 會重複 ",[31,1760,1761],{},"platform.browser.name","。這個欄位的存在，是為了讓本機瀏覽器以外的算繪器（固定版本的 Docker 映像、託管的算繪器）能以 ",[31,1764,1765],{},"rendererVersion",[31,1767,1768],{},"imageDigest"," 表明身分，也讓不得不退回本機瀏覽器的執行能以 ",[31,1771,1772],{},"renderer.fallback: true"," 標記。請把算繪器不同的條目視為不同的基準影像。",[117,1775,1776,1779,1780,1783],{},[31,1777,1778],{},"hashes"," 保存 ",[31,1781,1782],{},"images"," 中每個實際存在於磁碟上的檔案的 sha256。可以用來略過重新上傳未變更的基準影像、檢查 artifact 是否與清單相符，或找出產生完全相同像素的兩個條目。",[117,1785,1786,1787,491,1790,1793,1794,1797,1798,1801,1802,1805,1806,1809,1810,491,1813,1816],{},"對應到 pull request：請使用 ",[31,1788,1789],{},"ci.repositoryName",[31,1791,1792],{},"ci.pullRequest.number","。在 GitHub 的 ",[31,1795,1796],{},"pull_request"," 事件中，",[31,1799,1800],{},"ci.commit"," 是暫時性的合併 commit，所以任何要推送到 PR 分支的操作都必須使用 ",[31,1803,1804],{},"ci.pullRequest.headSha"," \u002F ",[31,1807,1808],{},"headRef","。工作流程的 artifact 可透過 ",[31,1811,1812],{},"ci.buildId",[31,1814,1815],{},"ci.runAttempt"," 找到。",[117,1818,1819,1820,1823,1824,1826,1827,1830],{},"重現一次執行：",[31,1821,1822],{},"npx cypress run --\u003Crunner.testingType> --browser \u003Crunner.browser.name> --config-file \u003Crunner.configFile> --spec \u003Crunner.specs joined with ,>","，再為 ",[31,1825,1523],{}," 的每個條目加上一個 ",[31,1828,1829],{},"--expose \"pluginVisualRegression\u003CKey>=\u003Cvalue>\"","。清單以各個部分而非一整串指令字串的形式儲存這些資訊，因此 shell 的引號處理與套件管理工具仍由您決定。",[117,1832,1833,1834,1837,1838,1841,1842,1844,1845,1606,1848,1851],{},"這個檔案會在每次比對後重寫，所以即使執行中途中止，它仍是完整的。當 spec 在多台機器上平行執行時，每台機器會寫出自己的清單；",[31,1835,1836],{},"**\u002Fvisual-regression-manifest{,.*}.json","（套件中的 ",[31,1839,1840],{},"MANIFEST_FILE_GLOB","）可以在 artifact 中找出所有清單，而 ",[31,1843,517],{}," 的 ",[31,1846,1847],{},"readManifestFiles",[31,1849,1850],{},"mergeManifests"," 會把它們合併成一份清單，較晚的 CI attempt 會覆蓋較早的。",[117,1853,1854,1855,1857,1858,1860,1861,1864,1865,1868,1869,1872],{},"只有 ",[31,1856,1545],{}," 區塊與 ",[31,1859,1523],{}," 的鍵是 Cypress 專屬的；格式的其餘部分與所有其他寫入者共用。",[31,1862,1863],{},"specVersion"," 遵循 semver，只有在格式發生破壞性變更時才會提高主版號；消費端會忽略不認識的鍵。由於欄位名稱遵循 CTRF，套件中的 ",[31,1866,1867],{},"toCtrf"," 可以把清單轉成 ",[353,1870,503],{"href":501,"rel":1871},[423]," 報告，供讀取該格式的工具使用。",[117,1874,1875,1876,1879,1880,1883,1884,1886],{},"為了方便起見，",[31,1877,1878],{},"Manifest*"," 型別也從 ",[31,1881,1882],{},"@pixsame\u002Fcypress-plugin-visual-regression-diff\u002Fplugins"," 重新匯出；它們就是 ",[31,1885,517],{}," 的型別。",[20,1888,1889,1890,1893,1894,1897],{},"清單預設為開啟。若要把它寫到其他位置（路徑會以專案根目錄為基準解析）或關閉它，請使用 ",[31,1891,1892],{},"pluginVisualRegressionManifestPath"," 鍵（",[31,1895,1896],{},"false"," 會停用它，其他行為不變）：",[24,1899,1901],{"className":26,"code":1900,"language":28,"meta":29,"style":29},"# Cypress 15.10+\nnpx cypress run --expose \"pluginVisualRegressionManifestPath=reports\u002Fvisual-regression.json\"\nnpx cypress run --expose \"pluginVisualRegressionManifestPath=false\"\n# Cypress \u003C15.10（15.10 起棄用，16 已移除）\nnpx cypress run --env \"pluginVisualRegressionManifestPath=false\"\n",[31,1902,1903,1907,1920,1933,1937],{"__ignoreMap":29},[34,1904,1905],{"class":36,"line":37},[34,1906,442],{"class":40},[34,1908,1909,1911,1913,1915,1917],{"class":36,"line":44},[34,1910,447],{"class":47},[34,1912,450],{"class":51},[34,1914,453],{"class":51},[34,1916,456],{"class":55},[34,1918,1919],{"class":51}," \"pluginVisualRegressionManifestPath=reports\u002Fvisual-regression.json\"\n",[34,1921,1922,1924,1926,1928,1930],{"class":36,"line":62},[34,1923,447],{"class":47},[34,1925,450],{"class":51},[34,1927,453],{"class":51},[34,1929,456],{"class":55},[34,1931,1932],{"class":51}," \"pluginVisualRegressionManifestPath=false\"\n",[34,1934,1935],{"class":36,"line":69},[34,1936,464],{"class":40},[34,1938,1939,1941,1943,1945,1947],{"class":36,"line":75},[34,1940,447],{"class":47},[34,1942,450],{"class":51},[34,1944,453],{"class":51},[34,1946,475],{"class":55},[34,1948,1932],{"class":51},[20,1950,1951],{},"當您以自訂路徑同時執行 e2e 與元件測試時，請自行把測試類型加進路徑中；否則兩次執行會互相覆寫對方的檔案。",[10,1953,1955],{"id":1954},"configuration","設定",[20,1957,1958],{},"您可以透過以下方式設定這個外掛：",[114,1960,1961],{},[117,1962,1963,1964,1966],{},"將設定以參數的形式傳給 ",[31,1965,387],{}," 指令：",[24,1968,1970],{"className":126,"code":1969,"language":128,"meta":29,"style":29},"cy.matchImage({\n  \u002F\u002F 截圖設定，會直接傳給 Cypress 的 screenshot 方法：https:\u002F\u002Fdocs.cypress.io\u002Fapi\u002Fcypress-api\u002Fscreenshot-api#Arguments\n  \u002F\u002F 預設值：{ }\n  screenshotConfig: {\n    blackout: ['.element-to-be-blackouted'],\n  },\n  \u002F\u002F pixelmatch 選項，請參考：https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fpixelmatch#pixelmatchimg1-img2-output-width-height-options\n  \u002F\u002F 預設值：{ }，即 pixelmatch 的預設值，其中特別是 includeAA: false（抗鋸齒的邊緣像素不會被計為差異）\n  diffConfig: {\n    threshold: 0.01,\n  },\n  \u002F\u002F 是否自動建立缺少的基準影像\n  \u002F\u002F 預設值：true\n  createMissingImages: false,\n  \u002F\u002F 是否自動更新影像，在 CI 上很實用\n  \u002F\u002F - true：不比對，直接覆寫所有基準影像（最快）\n  \u002F\u002F - 'failures-only'：先比對，只在差異超過門檻值時才更新基準影像\n  \u002F\u002F - false：永遠不自動更新基準影像\n  \u002F\u002F 預設值：false\n  updateImages: true,\n  \u002F\u002F 儲存截圖影像的目錄路徑\n  \u002F\u002F 相對路徑會以專案根目錄為基準解析\n  \u002F\u002F 支援絕對路徑（unix 與 windows 作業系統皆可）\n  \u002F\u002F 外掛會依作業系統正規化路徑分隔符號，您應一律使用 \u002F 作為分隔符號，例如：C:\u002Fmy-directory\u002Fnested 表示 windows 風格的磁碟機路徑\n  \u002F\u002F 路徑中可使用下列變數：\n  \u002F\u002F - {spec_path}：從專案根目錄到目前 spec 檔案所在目錄的相對路徑（例如 `\u002Fsrc\u002Fcomponents\u002Fmy-tested-component`）；必須自成一個完整的路徑片段\n  \u002F\u002F - {platform}：`{os}-{browser}`，例如 `linux-chrome`、`darwin-electron`、`win32-firefox`\n  \u002F\u002F - {os}：Cypress.platform，即 `linux`、`darwin` 或 `win32`\n  \u002F\u002F - {browser}：Cypress 執行該 spec 所用的瀏覽器（Cypress.browser.name）：未以 `--browser` 指定時為 `electron`，否則為 `chrome`、`firefox`、`edge` 等\n  \u002F\u002F {platform}、{os} 與 {browser} 也可以只是片段的一部分（`shots-{platform}`）；`matchAgainstPath` 永遠不會被展開\n  \u002F\u002F 可用它們把不同作業系統／瀏覽器的基準影像分開存放，請見下方「依平台區分的基準影像」\n  \u002F\u002F 預設值：'{spec_path}\u002F__image_snapshots__'\n  imagesPath: 'this-might-be-your-custom\u002Fmaybe-nested-directory',\n  \u002F\u002F 測試失敗的最大門檻值，差異超過此值即失敗\n  \u002F\u002F 預設值：0.01\n  maxDiffThreshold: 0.1,\n  \u002F\u002F 當比對發現差異時，描述發生了什麼變化，例如 \"Everything below y=340 moved down by 12 px.\"\n  \u002F\u002F 這句話會附在失敗訊息結尾，顯示在審查輪播中，並記錄到執行清單裡\n  \u002F\u002F 它不會改變比對是否通過\n  \u002F\u002F 預設值：true\n  analysis: false,\n  \u002F\u002F 強制將縮放比例設為 \"1\"\n  \u002F\u002F 可解決在 Mac Retina 等高解析度螢幕上截圖被放大 2 倍的問題\n  \u002F\u002F 預設值：true\n  forceDeviceScaleFactor: false,\n  \u002F\u002F 套用確定性算繪預設組合，請見下方「降低跨作業系統的算繪雜訊」\n  \u002F\u002F 在單次呼叫中，它只控制為截圖注入頁面的 CSS（游標、動畫、捲軸）；\n  \u002F\u002F 瀏覽器的啟動參數是整個程序共用的，由全域的 pluginVisualRegressionDeterministicRendering 選項決定\n  \u002F\u002F 預設值：true\n  deterministicRendering: false,\n  \u002F\u002F 用來命名影像檔案的標題\n  \u002F\u002F 預設值：Cypress.currentTest.titlePath（您的測試標題）\n  title: `${Cypress.currentTest.titlePath.join(' ')} (${Cypress.browser.displayName})`,\n  \u002F\u002F 傳入自訂影像的路徑作為比對對象\n  \u002F\u002F 而不是與上一次執行的影像比對\n  \u002F\u002F 預設值：undefined\n  matchAgainstPath: '\u002Fpath\u002Fto\u002Freference-image.png',\n});\n",[31,1971,1972,1980,1985,1990,1995,2006,2010,2015,2020,2025,2035,2039,2044,2049,2058,2063,2068,2073,2078,2083,2093,2098,2103,2108,2113,2118,2123,2128,2133,2138,2143,2148,2153,2163,2168,2173,2183,2188,2193,2198,2202,2211,2216,2221,2225,2234,2239,2244,2249,2253,2262,2267,2272,2326,2331,2336,2341,2351],{"__ignoreMap":29},[34,1973,1974,1976,1978],{"class":36,"line":37},[34,1975,373],{"class":147},[34,1977,387],{"class":162},[34,1979,247],{"class":147},[34,1981,1982],{"class":36,"line":44},[34,1983,1984],{"class":40},"  \u002F\u002F 截圖設定，會直接傳給 Cypress 的 screenshot 方法：https:\u002F\u002Fdocs.cypress.io\u002Fapi\u002Fcypress-api\u002Fscreenshot-api#Arguments\n",[34,1986,1987],{"class":36,"line":62},[34,1988,1989],{"class":40},"  \u002F\u002F 預設值：{ }\n",[34,1991,1992],{"class":36,"line":69},[34,1993,1994],{"class":147},"  screenshotConfig: {\n",[34,1996,1997,2000,2003],{"class":36,"line":75},[34,1998,1999],{"class":147},"    blackout: [",[34,2001,2002],{"class":51},"'.element-to-be-blackouted'",[34,2004,2005],{"class":147},"],\n",[34,2007,2008],{"class":36,"line":89},[34,2009,595],{"class":147},[34,2011,2012],{"class":36,"line":94},[34,2013,2014],{"class":40},"  \u002F\u002F pixelmatch 選項，請參考：https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fpixelmatch#pixelmatchimg1-img2-output-width-height-options\n",[34,2016,2017],{"class":36,"line":100},[34,2018,2019],{"class":40},"  \u002F\u002F 預設值：{ }，即 pixelmatch 的預設值，其中特別是 includeAA: false（抗鋸齒的邊緣像素不會被計為差異）\n",[34,2021,2022],{"class":36,"line":279},[34,2023,2024],{"class":147},"  diffConfig: {\n",[34,2026,2027,2030,2033],{"class":36,"line":288},[34,2028,2029],{"class":147},"    threshold: ",[34,2031,2032],{"class":55},"0.01",[34,2034,300],{"class":147},[34,2036,2037],{"class":36,"line":294},[34,2038,595],{"class":147},[34,2040,2041],{"class":36,"line":303},[34,2042,2043],{"class":40},"  \u002F\u002F 是否自動建立缺少的基準影像\n",[34,2045,2046],{"class":36,"line":309},[34,2047,2048],{"class":40},"  \u002F\u002F 預設值：true\n",[34,2050,2051,2054,2056],{"class":36,"line":324},[34,2052,2053],{"class":147},"  createMissingImages: ",[34,2055,1896],{"class":55},[34,2057,300],{"class":147},[34,2059,2060],{"class":36,"line":331},[34,2061,2062],{"class":40},"  \u002F\u002F 是否自動更新影像，在 CI 上很實用\n",[34,2064,2065],{"class":36,"line":336},[34,2066,2067],{"class":40},"  \u002F\u002F - true：不比對，直接覆寫所有基準影像（最快）\n",[34,2069,2070],{"class":36,"line":343},[34,2071,2072],{"class":40},"  \u002F\u002F - 'failures-only'：先比對，只在差異超過門檻值時才更新基準影像\n",[34,2074,2075],{"class":36,"line":631},[34,2076,2077],{"class":40},"  \u002F\u002F - false：永遠不自動更新基準影像\n",[34,2079,2080],{"class":36,"line":637},[34,2081,2082],{"class":40},"  \u002F\u002F 預設值：false\n",[34,2084,2085,2088,2091],{"class":36,"line":643},[34,2086,2087],{"class":147},"  updateImages: ",[34,2089,2090],{"class":55},"true",[34,2092,300],{"class":147},[34,2094,2095],{"class":36,"line":649},[34,2096,2097],{"class":40},"  \u002F\u002F 儲存截圖影像的目錄路徑\n",[34,2099,2100],{"class":36,"line":655},[34,2101,2102],{"class":40},"  \u002F\u002F 相對路徑會以專案根目錄為基準解析\n",[34,2104,2105],{"class":36,"line":661},[34,2106,2107],{"class":40},"  \u002F\u002F 支援絕對路徑（unix 與 windows 作業系統皆可）\n",[34,2109,2110],{"class":36,"line":667},[34,2111,2112],{"class":40},"  \u002F\u002F 外掛會依作業系統正規化路徑分隔符號，您應一律使用 \u002F 作為分隔符號，例如：C:\u002Fmy-directory\u002Fnested 表示 windows 風格的磁碟機路徑\n",[34,2114,2115],{"class":36,"line":672},[34,2116,2117],{"class":40},"  \u002F\u002F 路徑中可使用下列變數：\n",[34,2119,2120],{"class":36,"line":678},[34,2121,2122],{"class":40},"  \u002F\u002F - {spec_path}：從專案根目錄到目前 spec 檔案所在目錄的相對路徑（例如 `\u002Fsrc\u002Fcomponents\u002Fmy-tested-component`）；必須自成一個完整的路徑片段\n",[34,2124,2125],{"class":36,"line":684},[34,2126,2127],{"class":40},"  \u002F\u002F - {platform}：`{os}-{browser}`，例如 `linux-chrome`、`darwin-electron`、`win32-firefox`\n",[34,2129,2130],{"class":36,"line":690},[34,2131,2132],{"class":40},"  \u002F\u002F - {os}：Cypress.platform，即 `linux`、`darwin` 或 `win32`\n",[34,2134,2135],{"class":36,"line":696},[34,2136,2137],{"class":40},"  \u002F\u002F - {browser}：Cypress 執行該 spec 所用的瀏覽器（Cypress.browser.name）：未以 `--browser` 指定時為 `electron`，否則為 `chrome`、`firefox`、`edge` 等\n",[34,2139,2140],{"class":36,"line":702},[34,2141,2142],{"class":40},"  \u002F\u002F {platform}、{os} 與 {browser} 也可以只是片段的一部分（`shots-{platform}`）；`matchAgainstPath` 永遠不會被展開\n",[34,2144,2145],{"class":36,"line":708},[34,2146,2147],{"class":40},"  \u002F\u002F 可用它們把不同作業系統／瀏覽器的基準影像分開存放，請見下方「依平台區分的基準影像」\n",[34,2149,2150],{"class":36,"line":714},[34,2151,2152],{"class":40},"  \u002F\u002F 預設值：'{spec_path}\u002F__image_snapshots__'\n",[34,2154,2155,2158,2161],{"class":36,"line":719},[34,2156,2157],{"class":147},"  imagesPath: ",[34,2159,2160],{"class":51},"'this-might-be-your-custom\u002Fmaybe-nested-directory'",[34,2162,300],{"class":147},[34,2164,2165],{"class":36,"line":725},[34,2166,2167],{"class":40},"  \u002F\u002F 測試失敗的最大門檻值，差異超過此值即失敗\n",[34,2169,2170],{"class":36,"line":731},[34,2171,2172],{"class":40},"  \u002F\u002F 預設值：0.01\n",[34,2174,2175,2178,2181],{"class":36,"line":737},[34,2176,2177],{"class":147},"  maxDiffThreshold: ",[34,2179,2180],{"class":55},"0.1",[34,2182,300],{"class":147},[34,2184,2185],{"class":36,"line":743},[34,2186,2187],{"class":40},"  \u002F\u002F 當比對發現差異時，描述發生了什麼變化，例如 \"Everything below y=340 moved down by 12 px.\"\n",[34,2189,2190],{"class":36,"line":752},[34,2191,2192],{"class":40},"  \u002F\u002F 這句話會附在失敗訊息結尾，顯示在審查輪播中，並記錄到執行清單裡\n",[34,2194,2195],{"class":36,"line":758},[34,2196,2197],{"class":40},"  \u002F\u002F 它不會改變比對是否通過\n",[34,2199,2200],{"class":36,"line":764},[34,2201,2048],{"class":40},[34,2203,2204,2207,2209],{"class":36,"line":770},[34,2205,2206],{"class":147},"  analysis: ",[34,2208,1896],{"class":55},[34,2210,300],{"class":147},[34,2212,2213],{"class":36,"line":776},[34,2214,2215],{"class":40},"  \u002F\u002F 強制將縮放比例設為 \"1\"\n",[34,2217,2218],{"class":36,"line":782},[34,2219,2220],{"class":40},"  \u002F\u002F 可解決在 Mac Retina 等高解析度螢幕上截圖被放大 2 倍的問題\n",[34,2222,2223],{"class":36,"line":788},[34,2224,2048],{"class":40},[34,2226,2227,2230,2232],{"class":36,"line":794},[34,2228,2229],{"class":147},"  forceDeviceScaleFactor: ",[34,2231,1896],{"class":55},[34,2233,300],{"class":147},[34,2235,2236],{"class":36,"line":800},[34,2237,2238],{"class":40},"  \u002F\u002F 套用確定性算繪預設組合，請見下方「降低跨作業系統的算繪雜訊」\n",[34,2240,2241],{"class":36,"line":806},[34,2242,2243],{"class":40},"  \u002F\u002F 在單次呼叫中，它只控制為截圖注入頁面的 CSS（游標、動畫、捲軸）；\n",[34,2245,2246],{"class":36,"line":812},[34,2247,2248],{"class":40},"  \u002F\u002F 瀏覽器的啟動參數是整個程序共用的，由全域的 pluginVisualRegressionDeterministicRendering 選項決定\n",[34,2250,2251],{"class":36,"line":818},[34,2252,2048],{"class":40},[34,2254,2255,2258,2260],{"class":36,"line":823},[34,2256,2257],{"class":147},"  deterministicRendering: ",[34,2259,1896],{"class":55},[34,2261,300],{"class":147},[34,2263,2264],{"class":36,"line":829},[34,2265,2266],{"class":40},"  \u002F\u002F 用來命名影像檔案的標題\n",[34,2268,2269],{"class":36,"line":835},[34,2270,2271],{"class":40},"  \u002F\u002F 預設值：Cypress.currentTest.titlePath（您的測試標題）\n",[34,2273,2274,2277,2280,2283,2286,2289,2291,2294,2296,2299,2301,2304,2307,2310,2312,2314,2316,2318,2321,2324],{"class":36,"line":841},[34,2275,2276],{"class":147},"  title: ",[34,2278,2279],{"class":51},"`${",[34,2281,2282],{"class":147},"Cypress",[34,2284,2285],{"class":51},".",[34,2287,2288],{"class":147},"currentTest",[34,2290,2285],{"class":51},[34,2292,2293],{"class":147},"titlePath",[34,2295,2285],{"class":51},[34,2297,2298],{"class":162},"join",[34,2300,166],{"class":51},[34,2302,2303],{"class":51},"' '",[34,2305,2306],{"class":51},")",[34,2308,2309],{"class":51},"} (${",[34,2311,2282],{"class":147},[34,2313,2285],{"class":51},[34,2315,1562],{"class":147},[34,2317,2285],{"class":51},[34,2319,2320],{"class":147},"displayName",[34,2322,2323],{"class":51},"})`",[34,2325,300],{"class":147},[34,2327,2328],{"class":36,"line":847},[34,2329,2330],{"class":40},"  \u002F\u002F 傳入自訂影像的路徑作為比對對象\n",[34,2332,2333],{"class":36,"line":852},[34,2334,2335],{"class":40},"  \u002F\u002F 而不是與上一次執行的影像比對\n",[34,2337,2338],{"class":36,"line":858},[34,2339,2340],{"class":40},"  \u002F\u002F 預設值：undefined\n",[34,2342,2343,2346,2349],{"class":36,"line":864},[34,2344,2345],{"class":147},"  matchAgainstPath: ",[34,2347,2348],{"class":51},"'\u002Fpath\u002Fto\u002Freference-image.png'",[34,2350,300],{"class":147},[34,2352,2353],{"class":36,"line":870},[34,2354,2355],{"class":147},"});\n",[114,2357,2358],{},[117,2359,2360,2361,2366,2367,2370],{},"透過",[353,2362,2365],{"href":2363,"rel":2364},"https:\u002F\u002Fon.cypress.io\u002Fexpose",[423],"全域 expose 設定","（Cypress 15.10+）。設定鍵的名稱與上方設定物件的鍵相同，只是多了 ",[31,2368,2369],{},"pluginVisualRegression"," 前綴，例如：",[24,2372,2374],{"className":26,"code":2373,"language":28,"meta":29,"style":29},"# Cypress 15.10+\nnpx cypress run --expose \"pluginVisualRegressionUpdateImages=true,pluginVisualRegressionDiffConfig={\\\"threshold\\\":0.01}\"\n# Cypress \u003C15.10（15.10 起棄用，16 已移除）\nnpx cypress run --env \"pluginVisualRegressionUpdateImages=true,pluginVisualRegressionDiffConfig={\\\"threshold\\\":0.01}\"\n",[31,2375,2376,2380,2404,2408],{"__ignoreMap":29},[34,2377,2378],{"class":36,"line":37},[34,2379,442],{"class":40},[34,2381,2382,2384,2386,2388,2390,2393,2396,2399,2401],{"class":36,"line":44},[34,2383,447],{"class":47},[34,2385,450],{"class":51},[34,2387,453],{"class":51},[34,2389,456],{"class":55},[34,2391,2392],{"class":51}," \"pluginVisualRegressionUpdateImages=true,pluginVisualRegressionDiffConfig={",[34,2394,2395],{"class":140},"\\\"",[34,2397,2398],{"class":51},"threshold",[34,2400,2395],{"class":140},[34,2402,2403],{"class":51},":0.01}\"\n",[34,2405,2406],{"class":36,"line":62},[34,2407,464],{"class":40},[34,2409,2410,2412,2414,2416,2418,2420,2422,2424,2426],{"class":36,"line":69},[34,2411,447],{"class":47},[34,2413,450],{"class":51},[34,2415,453],{"class":51},[34,2417,475],{"class":55},[34,2419,2392],{"class":51},[34,2421,2395],{"class":140},[34,2423,2398],{"class":51},[34,2425,2395],{"class":140},[34,2427,2403],{"class":51},[20,2429,2430,2431,181,2434,2437],{},"請在同一個旗標中以逗號分隔傳入多個選項。若重複使用 ",[31,2432,2433],{},"--expose",[31,2435,2436],{},"--env","），Cypress 只會保留最後一個。",[24,2439,2441],{"className":126,"code":2440,"language":128,"meta":29,"style":29},"\u002F\u002F cypress.config.ts (Cypress 15.10+)\nimport { defineConfig } from 'cypress';\n\nexport default defineConfig({\n  expose: {\n    pluginVisualRegressionUpdateImages: true,\n    pluginVisualRegressionDiffConfig: { threshold: 0.01 },\n  },\n});\n",[31,2442,2443,2448,2460,2464,2474,2479,2488,2498,2504],{"__ignoreMap":29},[34,2444,2445],{"class":36,"line":37},[34,2446,2447],{"class":40},"\u002F\u002F cypress.config.ts (Cypress 15.10+)\n",[34,2449,2450,2452,2454,2456,2458],{"class":36,"line":44},[34,2451,141],{"class":140},[34,2453,201],{"class":147},[34,2455,204],{"class":140},[34,2457,207],{"class":51},[34,2459,148],{"class":147},[34,2461,2462],{"class":36,"line":62},[34,2463,66],{"emptyLinePlaceholder":65},[34,2465,2466,2468,2470,2472],{"class":36,"line":69},[34,2467,238],{"class":140},[34,2469,241],{"class":140},[34,2471,244],{"class":162},[34,2473,247],{"class":47},[34,2475,2476],{"class":36,"line":75},[34,2477,2478],{"class":147},"  expose: {\n",[34,2480,2481,2484,2486],{"class":36,"line":89},[34,2482,2483],{"class":147},"    pluginVisualRegressionUpdateImages: ",[34,2485,2090],{"class":55},[34,2487,300],{"class":147},[34,2489,2490,2493,2495],{"class":36,"line":94},[34,2491,2492],{"class":147},"    pluginVisualRegressionDiffConfig: { threshold: ",[34,2494,2032],{"class":55},[34,2496,2497],{"class":147}," },\n",[34,2499,2500,2502],{"class":36,"line":100},[34,2501,297],{"class":147},[34,2503,300],{"class":47},[34,2505,2506,2508],{"class":36,"line":279},[34,2507,346],{"class":47},[34,2509,148],{"class":147},[24,2511,2513],{"className":126,"code":2512,"language":128,"meta":29,"style":29},"\u002F\u002F cypress.config.ts（Cypress \u003C15.10，新版已棄用）\nimport { defineConfig } from 'cypress';\n\nexport default defineConfig({\n  env: {\n    pluginVisualRegressionUpdateImages: true,\n    pluginVisualRegressionDiffConfig: { threshold: 0.01 },\n  },\n});\n",[31,2514,2515,2520,2532,2536,2546,2551,2559,2567,2573],{"__ignoreMap":29},[34,2516,2517],{"class":36,"line":37},[34,2518,2519],{"class":40},"\u002F\u002F cypress.config.ts（Cypress \u003C15.10，新版已棄用）\n",[34,2521,2522,2524,2526,2528,2530],{"class":36,"line":44},[34,2523,141],{"class":140},[34,2525,201],{"class":147},[34,2527,204],{"class":140},[34,2529,207],{"class":51},[34,2531,148],{"class":147},[34,2533,2534],{"class":36,"line":62},[34,2535,66],{"emptyLinePlaceholder":65},[34,2537,2538,2540,2542,2544],{"class":36,"line":69},[34,2539,238],{"class":140},[34,2541,241],{"class":140},[34,2543,244],{"class":162},[34,2545,247],{"class":47},[34,2547,2548],{"class":36,"line":75},[34,2549,2550],{"class":147},"  env: {\n",[34,2552,2553,2555,2557],{"class":36,"line":89},[34,2554,2483],{"class":147},[34,2556,2090],{"class":55},[34,2558,300],{"class":147},[34,2560,2561,2563,2565],{"class":36,"line":94},[34,2562,2492],{"class":147},[34,2564,2032],{"class":55},[34,2566,2497],{"class":147},[34,2568,2569,2571],{"class":36,"line":100},[34,2570,297],{"class":147},[34,2572,300],{"class":47},[34,2574,2575,2577],{"class":36,"line":279},[34,2576,346],{"class":47},[34,2578,148],{"class":147},[20,2580,2581,2582,2586],{},"更多設定 expose 變數的方式",[353,2583,2585],{"href":2363,"rel":2584},[423],"請參考這裡","。",[10,2588,2590],{"id":2589},"per-platform-baselines","依平台區分的基準影像",[20,2592,2593,2594,2596],{},"Chrome 會把文字點陣化交給作業系統處理，因此同一個頁面在 macOS、Linux 與 Windows 上永遠不會算繪出逐位元組完全相同的結果，而各瀏覽器之間又還有各自的差異。所以在開發者的 Mac 上錄製的基準影像，很少能和 Linux CI 工作對同一個頁面拍下的截圖吻合。",[31,2595,1627],{}," 支援三個 token，可以把不同平台的基準影像分開存放，而不是讓它們互相覆蓋：",[1268,2598,2599,2609],{},[1271,2600,2601],{},[1274,2602,2603,2606],{},[1277,2604,2605],{},"token",[1277,2607,2608],{},"展開為",[1296,2610,2611,2630,2661],{},[1274,2612,2613,2618],{},[1301,2614,2615],{},[31,2616,2617],{},"{os}",[1301,2619,2620,2623,2624,1445,2626,1391,2628],{},[31,2621,2622],{},"Cypress.platform","：",[31,2625,1467],{},[31,2627,1470],{},[31,2629,1473],{},[1274,2631,2632,2637],{},[1301,2633,2634],{},[31,2635,2636],{},"{browser}",[1301,2638,2639,2642,2643,2646,2647,2650,2651,1445,2654,1445,2657,2660],{},[31,2640,2641],{},"Cypress.browser.name","，即 Cypress 執行該 spec 所用的瀏覽器：未傳入 ",[31,2644,2645],{},"--browser"," 時為 ",[31,2648,2649],{},"electron","，否則為 ",[31,2652,2653],{},"chrome",[31,2655,2656],{},"firefox",[31,2658,2659],{},"edge"," 等",[1274,2662,2663,2668],{},[1301,2664,2665],{},[31,2666,2667],{},"{platform}",[1301,2669,2670,2673,2674,1445,2677],{},[31,2671,2672],{},"{os}-{browser}","，例如 ",[31,2675,2676],{},"linux-chrome",[31,2678,2679],{},"darwin-electron",[20,2681,2682,2683,2685,2686,2689,2690,2692,2693,2696,2697,2699,2700,2586],{},"每張截圖都是由 Cypress 驅動的瀏覽器拍攝的，所以 ",[31,2684,2636],{}," 就是那個瀏覽器；",[31,2687,2688],{},"cypress run"," 未加 ",[31,2691,2645],{}," 時使用 Electron，這就是為什麼除非 CI 傳入 ",[31,2694,2695],{},"--browser chrome","，否則資料夾會是 ",[31,2698,2679],{}," 而不是 ",[31,2701,2702],{},"darwin-chrome",[20,2704,2705,2706,2708,2709,2712,2713,2716],{},"這些 token 是選用的：預設的 ",[31,2707,1627],{}," 仍然是 ",[31,2710,2711],{},"{spec_path}\u002F__image_snapshots__","，也就是所有人共用一組基準影像。當每次執行都在同一個作業系統與瀏覽器上進行（例如在容器內，請見常見問題），或是剩餘的差異仍低於您的 ",[31,2714,2715],{},"maxDiffThreshold"," 時，這就是正確的配置。若要依平台拆分，請全域加入這個 token：",[24,2718,2720],{"className":26,"code":2719,"language":28,"meta":29,"style":29},"# Cypress 15.10+\nnpx cypress run --expose \"pluginVisualRegressionImagesPath={spec_path}\u002F__image_snapshots__\u002F{platform}\"\n# Cypress \u003C15.10（15.10 起棄用，16 已移除）\nnpx cypress run --env \"pluginVisualRegressionImagesPath={spec_path}\u002F__image_snapshots__\u002F{platform}\"\n",[31,2721,2722,2726,2739,2743],{"__ignoreMap":29},[34,2723,2724],{"class":36,"line":37},[34,2725,442],{"class":40},[34,2727,2728,2730,2732,2734,2736],{"class":36,"line":44},[34,2729,447],{"class":47},[34,2731,450],{"class":51},[34,2733,453],{"class":51},[34,2735,456],{"class":55},[34,2737,2738],{"class":51}," \"pluginVisualRegressionImagesPath={spec_path}\u002F__image_snapshots__\u002F{platform}\"\n",[34,2740,2741],{"class":36,"line":62},[34,2742,464],{"class":40},[34,2744,2745,2747,2749,2751,2753],{"class":36,"line":69},[34,2746,447],{"class":47},[34,2748,450],{"class":51},[34,2750,453],{"class":51},[34,2752,475],{"class":55},[34,2754,2738],{"class":51},[24,2756,2758],{"className":126,"code":2757,"language":128,"meta":29,"style":29},"\u002F\u002F cypress.config.ts（Cypress 15.10+；Cypress \u003C15.10 請改用 `env` 取代 `expose`）\nexport default defineConfig({\n  expose: {\n    pluginVisualRegressionImagesPath:\n      '{spec_path}\u002F__image_snapshots__\u002F{platform}',\n  },\n});\n",[31,2759,2760,2765,2775,2779,2784,2791,2797],{"__ignoreMap":29},[34,2761,2762],{"class":36,"line":37},[34,2763,2764],{"class":40},"\u002F\u002F cypress.config.ts（Cypress 15.10+；Cypress \u003C15.10 請改用 `env` 取代 `expose`）\n",[34,2766,2767,2769,2771,2773],{"class":36,"line":44},[34,2768,238],{"class":140},[34,2770,241],{"class":140},[34,2772,244],{"class":162},[34,2774,247],{"class":47},[34,2776,2777],{"class":36,"line":62},[34,2778,2478],{"class":147},[34,2780,2781],{"class":36,"line":69},[34,2782,2783],{"class":147},"    pluginVisualRegressionImagesPath:\n",[34,2785,2786,2789],{"class":36,"line":75},[34,2787,2788],{"class":51},"      '{spec_path}\u002F__image_snapshots__\u002F{platform}'",[34,2790,300],{"class":147},[34,2792,2793,2795],{"class":36,"line":89},[34,2794,297],{"class":147},[34,2796,300],{"class":47},[34,2798,2799,2801],{"class":36,"line":94},[34,2800,346],{"class":47},[34,2802,148],{"class":147},[24,2804,2809],{"className":2805,"code":2807,"language":2808},[2806],"language-text","cypress\u002Fe2e\u002F__image_snapshots__\u002F\n├── darwin-electron\u002F   # 在 Mac 上執行 `cypress open` 所寫入的內容\n│   └── home page renders_#0.png\n└── linux-chrome\u002F      # 您的 CI 工作所寫入的內容\n    └── home page renders_#0.png\n","text",[31,2810,2807],{"__ignoreMap":29},[20,2812,2813],{},"拆分之後需要決定的事項：",[114,2815,2816,2853,2866],{},[117,2817,2818,2822,2823,2845,2848,2849,1632],{},[2819,2820,2821],"strong",{},"要提交哪些基準影像。"," 多數團隊只提交 CI 平台的基準影像，本機的則不納入 git，這樣每位開發者都有自己的一組，又不會污染儲存庫：",[24,2824,2828],{"className":2825,"code":2826,"language":2827,"meta":29,"style":29},"language-gitignore shiki shiki-themes github-light-high-contrast github-dark-high-contrast","# 忽略所有平台資料夾，只保留 CI 產生的那一個\n**\u002F__image_snapshots__\u002F*\u002F\n!**\u002F__image_snapshots__\u002Flinux-chrome\u002F\n","gitignore",[31,2829,2830,2835,2840],{"__ignoreMap":29},[34,2831,2832],{"class":36,"line":37},[34,2833,2834],{},"# 忽略所有平台資料夾，只保留 CI 產生的那一個\n",[34,2836,2837],{"class":36,"line":44},[34,2838,2839],{},"**\u002F__image_snapshots__\u002F*\u002F\n",[34,2841,2842],{"class":36,"line":62},[34,2843,2844],{},"!**\u002F__image_snapshots__\u002Flinux-chrome\u002F\n",[2846,2847],"br",{},"如此一來，新的 CI 基準影像就必須在 CI 上產生並從那裡提交（或從 PR 核准，請見",[353,2850,2852],{"href":2851},"#run-manifest-ci-integration","執行清單",[117,2854,2855,2858,2859,1391,2861,2673,2863,2586],{},[2819,2856,2857],{},"只依瀏覽器或只依作業系統拆分。"," 單獨使用 ",[31,2860,2636],{},[31,2862,2617],{},[31,2864,2865],{},"{spec_path}\u002F__image_snapshots__\u002F{browser}",[117,2867,2868,2871,2872,2875,2876,2878,2879,2882,2883,2886],{},[2819,2869,2870],{},"清理功能會刪除其他平台的基準影像。"," ",[31,2873,2874],{},"pluginVisualRegressionCleanupUnusedImages"," 會在整個專案中搜尋外掛產生的 PNG，而且完全不知道平台的存在：在 ",[31,2877,2679],{}," 上執行時，會把 ",[31,2880,2881],{},"linux-chrome\u002F"," 底下的每個檔案都視為未使用並刪除。在存有多個平台資料夾的機器上（開發者的本機檢出加上已提交的 CI 基準影像正是這種情況）請保持關閉，只在單一平台基準影像所在之處啟用，通常就是產生這些影像的 CI 工作。萬一真的誤刪了，用 ",[31,2884,2885],{},"git checkout -- \u003Cfolder>"," 就能把被刪除的資料夾找回來。",[20,2888,2889,2890,2895,2896,2898,2899,2901,2902,1743,2904,2906],{},"未來的方向：",[353,2891,2894],{"href":2892,"rel":2893},"https:\u002F\u002Fgithub.com\u002FFRSOURCE\u002Fcypress-plugin-visual-regression-diff\u002Fissues\u002F212",[423],"#212"," 的計畫是一個算繪器，不論 Cypress 在哪裡執行，都在固定版本的 Docker 映像中產生像素，讓本機與 CI 的影像從根本上不再漂移。屆時 ",[31,2897,2636],{}," 指的會是算繪器的瀏覽器，而不是 Cypress 驅動的那個；",[31,2900,2667],{}," 則仍可用來區分多個被算繪的瀏覽器，而不再是為了處理本機與 CI 之間的漂移。清單已經同時記錄了這兩邊：",[31,2903,1458],{},[31,2905,1746],{}," 是像素的來源。",[10,2908,2910],{"id":2909},"batch-review-mode","批次審閱模式",[20,2912,2913,2914,2917],{},"批次審閱模式（Batch Review Mode）",[2819,2915,2916],{},"預設為啟用","。它讓您可以跑完整個測試套件，而不會在第一個視覺差異失敗時就停下來。所有失敗的快照會被收集起來，在測試結束後呈現在互動式的審閱介面中，讓您可以批次核准或略過變更。",[15,2919,2921],{"id":2920},"additions-in-headed-mode-non-ci-environments","有頭模式（非 CI 環境）下的額外功能",[20,2923,2924],{},"Cypress 測試執行器的右下角會出現一個浮動操作按鈕（FAB）。測試執行期間：",[114,2926,2927,2934,2937],{},[117,2928,2929,2930,2933],{},"每當 ",[31,2931,2932],{},"matchImage()"," 呼叫的差異超過門檻值時，FAB 上的計數徽章會加一，而不是立即拋出錯誤。",[117,2935,2936],{},"所有測試跑完後，會拋出一個錯誤，列出失敗的總數。",[117,2938,2939,2940,2943,2944,2947],{},"點擊 FAB 會開啟一個輪播介面，讓您逐一並排檢視每張失敗的快照（新 vs. 舊），並選擇",[2819,2941,2942],{},"取代","基準影像或",[2819,2945,2946],{},"略過","這項變更。",[20,2949,2950],{},[2951,2952],"img",{"alt":2953,"src":2954},"批次審閱模式示範","https:\u002F\u002Fraw.githubusercontent.com\u002Fpixsame\u002Fpixsame\u002Fmain\u002Fassets\u002Fbatch-review-mode.gif",[2956,2957,2958],"blockquote",{},[20,2959,2960,2961,2964,2965,2586],{},"注意：在 ",[31,2962,2963],{},"@pixsame\u002Fcypress-plugin-visual-regression-diff"," 第 2 版之前，批次審閱模式是選用功能。如果您是從 4.x 升級，請參閱",[353,2966,2969],{"href":2967,"rel":2968},"https:\u002F\u002Fgithub.com\u002Fpixsame\u002Fpixsame\u002Fblob\u002Fmain\u002Fpackages\u002Fcypress-plugin-visual-regression-diff\u002FMIGRATION.md#4x---5x",[423],"遷移指南",[15,2971,2973],{"id":2972},"how-to-disable","如何停用",[20,2975,2976,2977,2979,2980,2982,2983,2986,2987,2623],{},"批次審閱模式是全域選項（無法直接傳給 ",[31,2978,387],{},"）。若要恢復成第一次不符時就立即讓 ",[31,2981,2932],{}," 失敗，請將 ",[31,2984,2985],{},"pluginVisualRegressionBatchReviewMode"," 鍵設為 ",[31,2988,1896],{},[24,2990,2992],{"className":26,"code":2991,"language":28,"meta":29,"style":29},"# Cypress 15.10+\nnpx cypress open --expose \"pluginVisualRegressionBatchReviewMode=false\"\n# Cypress \u003C15.10（15.10 起棄用，16 已移除）\nnpx cypress open --env \"pluginVisualRegressionBatchReviewMode=false\"\n",[31,2993,2994,2998,3012,3016],{"__ignoreMap":29},[34,2995,2996],{"class":36,"line":37},[34,2997,442],{"class":40},[34,2999,3000,3002,3004,3007,3009],{"class":36,"line":44},[34,3001,447],{"class":47},[34,3003,450],{"class":51},[34,3005,3006],{"class":51}," open",[34,3008,456],{"class":55},[34,3010,3011],{"class":51}," \"pluginVisualRegressionBatchReviewMode=false\"\n",[34,3013,3014],{"class":36,"line":62},[34,3015,464],{"class":40},[34,3017,3018,3020,3022,3024,3026],{"class":36,"line":69},[34,3019,447],{"class":47},[34,3021,450],{"class":51},[34,3023,3006],{"class":51},[34,3025,475],{"class":55},[34,3027,3011],{"class":51},[24,3029,3031],{"className":126,"code":3030,"language":128,"meta":29,"style":29},"\u002F\u002F cypress.config.ts (Cypress 15.10+)\nimport { defineConfig } from 'cypress';\n\nexport default defineConfig({\n  expose: {\n    pluginVisualRegressionBatchReviewMode: false,\n  },\n});\n",[31,3032,3033,3037,3049,3053,3063,3067,3076,3082],{"__ignoreMap":29},[34,3034,3035],{"class":36,"line":37},[34,3036,2447],{"class":40},[34,3038,3039,3041,3043,3045,3047],{"class":36,"line":44},[34,3040,141],{"class":140},[34,3042,201],{"class":147},[34,3044,204],{"class":140},[34,3046,207],{"class":51},[34,3048,148],{"class":147},[34,3050,3051],{"class":36,"line":62},[34,3052,66],{"emptyLinePlaceholder":65},[34,3054,3055,3057,3059,3061],{"class":36,"line":69},[34,3056,238],{"class":140},[34,3058,241],{"class":140},[34,3060,244],{"class":162},[34,3062,247],{"class":47},[34,3064,3065],{"class":36,"line":75},[34,3066,2478],{"class":147},[34,3068,3069,3072,3074],{"class":36,"line":89},[34,3070,3071],{"class":147},"    pluginVisualRegressionBatchReviewMode: ",[34,3073,1896],{"class":55},[34,3075,300],{"class":147},[34,3077,3078,3080],{"class":36,"line":94},[34,3079,297],{"class":147},[34,3081,300],{"class":47},[34,3083,3084,3086],{"class":36,"line":100},[34,3085,346],{"class":47},[34,3087,148],{"class":147},[24,3089,3091],{"className":126,"code":3090,"language":128,"meta":29,"style":29},"\u002F\u002F cypress.config.ts（Cypress \u003C15.10，新版已棄用）\nimport { defineConfig } from 'cypress';\n\nexport default defineConfig({\n  env: {\n    pluginVisualRegressionBatchReviewMode: false,\n  },\n});\n",[31,3092,3093,3097,3109,3113,3123,3127,3135,3141],{"__ignoreMap":29},[34,3094,3095],{"class":36,"line":37},[34,3096,2519],{"class":40},[34,3098,3099,3101,3103,3105,3107],{"class":36,"line":44},[34,3100,141],{"class":140},[34,3102,201],{"class":147},[34,3104,204],{"class":140},[34,3106,207],{"class":51},[34,3108,148],{"class":147},[34,3110,3111],{"class":36,"line":62},[34,3112,66],{"emptyLinePlaceholder":65},[34,3114,3115,3117,3119,3121],{"class":36,"line":69},[34,3116,238],{"class":140},[34,3118,241],{"class":140},[34,3120,244],{"class":162},[34,3122,247],{"class":47},[34,3124,3125],{"class":36,"line":75},[34,3126,2550],{"class":147},[34,3128,3129,3131,3133],{"class":36,"line":89},[34,3130,3071],{"class":147},[34,3132,1896],{"class":55},[34,3134,300],{"class":147},[34,3136,3137,3139],{"class":36,"line":94},[34,3138,297],{"class":147},[34,3140,300],{"class":47},[34,3142,3143,3145],{"class":36,"line":100},[34,3144,346],{"class":47},[34,3146,148],{"class":147},[15,3148,3150],{"id":3149},"reviewing-passing-images","審閱通過的影像",[20,3152,3153,3154,3156,3157,3160,3161,3163],{},"與基準影像有差異、但仍在 ",[31,3155,2715],{}," 範圍內的影像不會讓測試失敗，但同樣會被收集起來。輪播介面中有一個 ",[2819,3158,3159],{},"Show passing"," 核取方塊，勾選後即可瀏覽這些影像（每張都會標示 ",[31,3162,1305],{}," 徽章），並同樣可以取代它們的基準影像，例如用來消除逐漸累積的細微偏移。",[20,3165,3166,3167,3170],{},"這個核取方塊預設為未勾選。若想讓它預設勾選，請使用 ",[31,3168,3169],{},"pluginVisualRegressionBatchReviewModeShowPassingImages"," 鍵：",[24,3172,3174],{"className":26,"code":3173,"language":28,"meta":29,"style":29},"# Cypress 15.10+\nnpx cypress open --expose \"pluginVisualRegressionBatchReviewModeShowPassingImages=true\"\n# Cypress \u003C15.10（15.10 起棄用，16 已移除）\nnpx cypress open --env \"pluginVisualRegressionBatchReviewModeShowPassingImages=true\"\n",[31,3175,3176,3180,3193,3197],{"__ignoreMap":29},[34,3177,3178],{"class":36,"line":37},[34,3179,442],{"class":40},[34,3181,3182,3184,3186,3188,3190],{"class":36,"line":44},[34,3183,447],{"class":47},[34,3185,450],{"class":51},[34,3187,3006],{"class":51},[34,3189,456],{"class":55},[34,3191,3192],{"class":51}," \"pluginVisualRegressionBatchReviewModeShowPassingImages=true\"\n",[34,3194,3195],{"class":36,"line":62},[34,3196,464],{"class":40},[34,3198,3199,3201,3203,3205,3207],{"class":36,"line":69},[34,3200,447],{"class":47},[34,3202,450],{"class":51},[34,3204,3006],{"class":51},[34,3206,475],{"class":55},[34,3208,3192],{"class":51},[24,3210,3212],{"className":126,"code":3211,"language":128,"meta":29,"style":29},"\u002F\u002F cypress.config.ts (Cypress 15.10+)\nimport { defineConfig } from 'cypress';\n\nexport default defineConfig({\n  expose: {\n    pluginVisualRegressionBatchReviewModeShowPassingImages: true,\n  },\n});\n",[31,3213,3214,3218,3230,3234,3244,3248,3257,3263],{"__ignoreMap":29},[34,3215,3216],{"class":36,"line":37},[34,3217,2447],{"class":40},[34,3219,3220,3222,3224,3226,3228],{"class":36,"line":44},[34,3221,141],{"class":140},[34,3223,201],{"class":147},[34,3225,204],{"class":140},[34,3227,207],{"class":51},[34,3229,148],{"class":147},[34,3231,3232],{"class":36,"line":62},[34,3233,66],{"emptyLinePlaceholder":65},[34,3235,3236,3238,3240,3242],{"class":36,"line":69},[34,3237,238],{"class":140},[34,3239,241],{"class":140},[34,3241,244],{"class":162},[34,3243,247],{"class":47},[34,3245,3246],{"class":36,"line":75},[34,3247,2478],{"class":147},[34,3249,3250,3253,3255],{"class":36,"line":89},[34,3251,3252],{"class":147},"    pluginVisualRegressionBatchReviewModeShowPassingImages: ",[34,3254,2090],{"class":55},[34,3256,300],{"class":147},[34,3258,3259,3261],{"class":36,"line":94},[34,3260,297],{"class":147},[34,3262,300],{"class":47},[34,3264,3265,3267],{"class":36,"line":100},[34,3266,346],{"class":47},[34,3268,148],{"class":147},[20,3270,3271],{},"在執行器中切換這個核取方塊的狀態會記錄在瀏覽器的 local storage 中，之後的執行會以它為準，優先於設定檔中的值。",[10,3273,3275],{"id":3274},"reducing-cross-os-rendering-noise","降低跨作業系統的算繪雜訊",[20,3277,3278,3279,3282],{},"瀏覽器會把文字的點陣化交給作業系統處理（macOS 用 CoreText、Windows 用 DirectWrite、Linux 用 FreeType），因此同一個頁面在開發者的筆電與 Linux CI 執行器上，永遠不會算繪出逐位元組完全相同的結果。外掛無法完全消除這個問題，但 ",[31,3280,3281],{},"deterministicRendering"," 預設組合（預設啟用）可以去除發生在瀏覽器內部的那一部分雜訊：",[114,3284,3285,3307,3317,3330],{},[117,3286,3287,3290,3291,3294,3295,3298,3299,3302,3303,3306],{},[2819,3288,3289],{},"Chrome、Chromium、Edge"," 會以 ",[31,3292,3293],{},"--font-render-hinting=none --disable-font-subpixel-positioning --disable-lcd-text --force-color-profile=srgb --disable-gpu"," 啟動（文字不使用作業系統的 hinting 與次像素技巧、不做色彩管理、以 CPU 點陣化），無頭模式下另外加上 ",[31,3296,3297],{},"--hide-scrollbars","。這份清單以 ",[31,3300,3301],{},"DETERMINISTIC_RENDERING_CHROMIUM_ARGS"," 的名稱從 ",[31,3304,3305],{},"@pixsame\u002Fcypress-plugin-visual-regression-diff\u002Fconstants"," 匯出。",[117,3308,3309,3312,3313,3316],{},[2819,3310,3311],{},"Firefox"," 會設定 ",[31,3314,3315],{},"gfx.webrender.software"," 偏好設定（CPU 算繪）。Firefox 沒有跨平台的字型 hinting 開關，因此文字在不同作業系統之間仍可能有差異。",[117,3318,3319,3322,3323,3325,3326,3329],{},[2819,3320,3321],{},"所有瀏覽器","：在 ",[31,3324,387],{}," 截圖期間，會在受測頁面注入一個 ",[31,3327,3328],{},"\u003Cstyle>"," 元素，用來隱藏文字游標、停用 CSS transition、動畫與平滑捲動，並隱藏捲軸。截圖一結束就會移除。",[117,3331,3332,3333,3336,3337,3340],{},"比對時會以 ",[31,3334,3335],{},"includeAA: false"," 執行 ",[31,3338,3339],{},"pixelmatch","，因此抗鋸齒的邊緣像素會被偵測出來，且不會被計為差異。",[20,3342,3343,3344,491,3347,3349],{},"這個預設組合無法解決的問題：各作業系統使用不同的字型檔與備用字型（經典的 Arial 對 Liberation Sans 情況）、emoji 字型、WebKit 與 Firefox 的文字點陣化，以及 WebGL 繪製的影像。對於這些情況，請為每個平台各保留一份基準影像（請參考 ",[31,3345,3346],{},"title",[31,3348,1627],{}," 選項，以及常見問題中關於瀏覽器名稱的條目），或是在與 CI 相同的環境中產生基準影像。",[20,3351,3352,3355],{},[2819,3353,3354],{},"Electron"," 會忽略外掛設定的啟動參數。請改用環境變數傳入這些參數：",[24,3357,3359],{"className":26,"code":3358,"language":28,"meta":29,"style":29},"ELECTRON_EXTRA_LAUNCH_ARGS=\"--font-render-hinting=none --disable-font-subpixel-positioning --disable-lcd-text --force-color-profile=srgb --disable-gpu --hide-scrollbars\" npx cypress run\n",[31,3360,3361],{"__ignoreMap":29},[34,3362,3363,3366,3369,3372,3375,3377],{"class":36,"line":37},[34,3364,3365],{"class":147},"ELECTRON_EXTRA_LAUNCH_ARGS",[34,3367,3368],{"class":140},"=",[34,3370,3371],{"class":51},"\"--font-render-hinting=none --disable-font-subpixel-positioning --disable-lcd-text --force-color-profile=srgb --disable-gpu --hide-scrollbars\"",[34,3373,3374],{"class":47}," npx",[34,3376,450],{"class":51},[34,3378,3379],{"class":51}," run\n",[20,3381,3382,2623,3385,3388,3389,3392,3393,3396,3397,3400,3401,3408],{},[2819,3383,3384],{},"WebGL",[31,3386,3387],{},"--disable-gpu"," 可能讓依賴 WebGL 的頁面無法取得算繪環境。您可以停用預設組合，或是在自己的 ",[31,3390,3391],{},"before:browser:launch"," 處理常式中加入 ",[31,3394,3395],{},"--use-gl=angle --use-angle=swiftshader","（較新的 Chrome 還需要 ",[31,3398,3399],{},"--enable-unsafe-swiftshader","），並透過 ",[353,3402,3405],{"href":3403,"rel":3404},"https:\u002F\u002Fgithub.com\u002Fbahmutov\u002Fcypress-on-fix",[423],[31,3406,3407],{},"cypress-on-fix"," 與外掛本身的處理常式組合使用。",[20,3410,3411,3414,3415,491,3418,3421,3422,3425,3426,3429],{},[2819,3412,3413],{},"截圖 hook","：外掛會為它拍攝的每一張截圖傳入自己的 ",[31,3416,3417],{},"onBeforeScreenshot",[31,3419,3420],{},"onAfterScreenshot","。透過 ",[31,3423,3424],{},"screenshotConfig"," 傳入的 hook 仍會被呼叫；以 ",[31,3427,3428],{},"Cypress.Screenshot.defaults()"," 全域設定的 hook 則不會。",[20,3431,3432],{},"若要全域關閉這個預設組合（瀏覽器啟動參數與 CSS）：",[24,3434,3436],{"className":26,"code":3435,"language":28,"meta":29,"style":29},"# Cypress 15.10+\nnpx cypress run --expose \"pluginVisualRegressionDeterministicRendering=false\"\n# Cypress \u003C15.10（15.10 起棄用，16 已移除）\nnpx cypress run --env \"pluginVisualRegressionDeterministicRendering=false\"\n",[31,3437,3438,3442,3455,3459],{"__ignoreMap":29},[34,3439,3440],{"class":36,"line":37},[34,3441,442],{"class":40},[34,3443,3444,3446,3448,3450,3452],{"class":36,"line":44},[34,3445,447],{"class":47},[34,3447,450],{"class":51},[34,3449,453],{"class":51},[34,3451,456],{"class":55},[34,3453,3454],{"class":51}," \"pluginVisualRegressionDeterministicRendering=false\"\n",[34,3456,3457],{"class":36,"line":62},[34,3458,464],{"class":40},[34,3460,3461,3463,3465,3467,3469],{"class":36,"line":69},[34,3462,447],{"class":47},[34,3464,450],{"class":51},[34,3466,453],{"class":51},[34,3468,475],{"class":55},[34,3470,3454],{"class":51},[24,3472,3474],{"className":126,"code":3473,"language":128,"meta":29,"style":29},"\u002F\u002F cypress.config.ts (Cypress 15.10+)\nimport { defineConfig } from 'cypress';\n\nexport default defineConfig({\n  expose: {\n    pluginVisualRegressionDeterministicRendering: false,\n  },\n});\n",[31,3475,3476,3480,3492,3496,3506,3510,3519,3525],{"__ignoreMap":29},[34,3477,3478],{"class":36,"line":37},[34,3479,2447],{"class":40},[34,3481,3482,3484,3486,3488,3490],{"class":36,"line":44},[34,3483,141],{"class":140},[34,3485,201],{"class":147},[34,3487,204],{"class":140},[34,3489,207],{"class":51},[34,3491,148],{"class":147},[34,3493,3494],{"class":36,"line":62},[34,3495,66],{"emptyLinePlaceholder":65},[34,3497,3498,3500,3502,3504],{"class":36,"line":69},[34,3499,238],{"class":140},[34,3501,241],{"class":140},[34,3503,244],{"class":162},[34,3505,247],{"class":47},[34,3507,3508],{"class":36,"line":75},[34,3509,2478],{"class":147},[34,3511,3512,3515,3517],{"class":36,"line":89},[34,3513,3514],{"class":147},"    pluginVisualRegressionDeterministicRendering: ",[34,3516,1896],{"class":55},[34,3518,300],{"class":147},[34,3520,3521,3523],{"class":36,"line":94},[34,3522,297],{"class":147},[34,3524,300],{"class":47},[34,3526,3527,3529],{"class":36,"line":100},[34,3528,346],{"class":47},[34,3530,148],{"class":147},[20,3532,3533],{},"若要保留瀏覽器啟動參數，但在單張截圖中略過 CSS（例如您想擷取動畫結束時的狀態）：",[24,3535,3537],{"className":126,"code":3536,"language":128,"meta":29,"style":29},"cy.matchImage({ deterministicRendering: false });\n",[31,3538,3539],{"__ignoreMap":29},[34,3540,3541,3543,3545,3548,3550],{"class":36,"line":37},[34,3542,373],{"class":147},[34,3544,387],{"class":162},[34,3546,3547],{"class":147},"({ deterministicRendering: ",[34,3549,1896],{"class":55},[34,3551,3552],{"class":147}," });\n",[10,3554,3556],{"id":3555},"faq","常見問題",[15,3558,3560,3561,3563],{"id":3559},"why-screenshots-doesnt-conform-to-the-viewport-set-in-my-cypress-configuration","為什麼截圖不符合我在 Cypress 設定中指定的 ",[31,3562,1725],{},"？",[20,3565,3566],{},"Cypress 的截圖預設不會依 viewport 大小縮放。您可以這樣調整：",[114,3568,3569,3575],{},[117,3570,3571,3572],{},"全域：修改預設的截圖設定：",[31,3573,3574],{},"Cypress.Screenshot.defaults({ capture: 'viewport' });",[117,3576,3577,3578,1966,3581],{},"區域：直接把截圖設定傳給 ",[31,3579,3580],{},".matchImage",[31,3582,3583],{},"cy.matchImage({ screenshotConfig: { capture: 'viewport' } });",[15,3585,3587],{"id":3586},"ive-upgraded-version-of-this-plugin-and-all-on-my-baseline-images-has-been-automatically-updated-why","我升級了這個外掛的版本，結果所有基準影像都被自動更新了。為什麼？",[20,3589,3590],{},"有時候我們必須對影像比對或影像產生的演算法做出破壞性變更。為了讓您的升級過程盡可能輕鬆，外掛會自動更新您的基準影像。升級外掛後，只要把這些影像 commit 進您的 repository 就可以了！",[15,3592,3594,3596,3597,3600],{"id":3593},"screenshots-look-different-between-cypress-run-and-cypress-open-how-do-i-fix-it",[31,3595,2688],{}," 和 ",[31,3598,3599],{},"cypress open"," 的截圖看起來不一樣，該怎麼解決？",[20,3602,3603,3604,3607,3608,2623],{},"這通常是無頭模式與有頭模式之間 device pixel ratio 不同所造成的。請使用 ",[31,3605,3606],{},"forceDeviceScaleFactor"," 選項將縮放比例統一為 ",[31,3609,3610],{},"1",[24,3612,3614],{"className":126,"code":3613,"language":128,"meta":29,"style":29},"cy.matchImage({ forceDeviceScaleFactor: true });\n",[31,3615,3616],{"__ignoreMap":29},[34,3617,3618,3620,3622,3625,3627],{"class":36,"line":37},[34,3619,373],{"class":147},[34,3621,387],{"class":162},[34,3623,3624],{"class":147},"({ forceDeviceScaleFactor: ",[34,3626,2090],{"class":55},[34,3628,3552],{"class":147},[20,3630,3631],{},"或透過 expose 變數全域設定：",[24,3633,3635],{"className":26,"code":3634,"language":28,"meta":29,"style":29},"# Cypress 15.10+\nnpx cypress run --expose \"pluginVisualRegressionForceDeviceScaleFactor=true\"\n# Cypress \u003C15.10（15.10 起棄用，16 已移除）\nnpx cypress run --env \"pluginVisualRegressionForceDeviceScaleFactor=true\"\n",[31,3636,3637,3641,3654,3658],{"__ignoreMap":29},[34,3638,3639],{"class":36,"line":37},[34,3640,442],{"class":40},[34,3642,3643,3645,3647,3649,3651],{"class":36,"line":44},[34,3644,447],{"class":47},[34,3646,450],{"class":51},[34,3648,453],{"class":51},[34,3650,456],{"class":55},[34,3652,3653],{"class":51}," \"pluginVisualRegressionForceDeviceScaleFactor=true\"\n",[34,3655,3656],{"class":36,"line":62},[34,3657,464],{"class":40},[34,3659,3660,3662,3664,3666,3668],{"class":36,"line":69},[34,3661,447],{"class":47},[34,3663,450],{"class":51},[34,3665,453],{"class":51},[34,3667,475],{"class":55},[34,3669,3653],{"class":51},[20,3671,3672,3673,3676,3677,3682,3683,3685],{},"若 viewport 大小的差異持續存在，可以考慮在 ",[31,3674,3675],{},"setupNodeEvents"," 中明確指定瀏覽器視窗大小（請透過 ",[353,3678,3680],{"href":3403,"rel":3679},[423],[31,3681,3407],{}," 與外掛本身的 ",[31,3684,3391],{}," 處理常式組合使用）：",[24,3687,3689],{"className":126,"code":3688,"language":128,"meta":29,"style":29},"on('before:browser:launch', (browser, launchOptions) => {\n  if (browser.family === 'chromium' && browser.isHeadless) {\n    launchOptions.args.push('--window-size=1280,720');\n  }\n  return launchOptions;\n});\n",[31,3690,3691,3719,3739,3754,3759,3767],{"__ignoreMap":29},[34,3692,3693,3695,3697,3700,3703,3705,3707,3710,3713,3716],{"class":36,"line":37},[34,3694,267],{"class":162},[34,3696,166],{"class":147},[34,3698,3699],{"class":51},"'before:browser:launch'",[34,3701,3702],{"class":147},", (",[34,3704,1562],{"class":47},[34,3706,270],{"class":147},[34,3708,3709],{"class":47},"launchOptions",[34,3711,3712],{"class":147},") ",[34,3714,3715],{"class":140},"=>",[34,3717,3718],{"class":147}," {\n",[34,3720,3721,3724,3727,3730,3733,3736],{"class":36,"line":44},[34,3722,3723],{"class":140},"  if",[34,3725,3726],{"class":147}," (browser.family ",[34,3728,3729],{"class":140},"===",[34,3731,3732],{"class":51}," 'chromium'",[34,3734,3735],{"class":140}," &&",[34,3737,3738],{"class":147}," browser.isHeadless) {\n",[34,3740,3741,3744,3747,3749,3752],{"class":36,"line":62},[34,3742,3743],{"class":147},"    launchOptions.args.",[34,3745,3746],{"class":162},"push",[34,3748,166],{"class":147},[34,3750,3751],{"class":51},"'--window-size=1280,720'",[34,3753,172],{"class":147},[34,3755,3756],{"class":36,"line":69},[34,3757,3758],{"class":147},"  }\n",[34,3760,3761,3764],{"class":36,"line":75},[34,3762,3763],{"class":140},"  return",[34,3765,3766],{"class":147}," launchOptions;\n",[34,3768,3769],{"class":36,"line":89},[34,3770,2355],{"class":147},[20,3772,3773,3774,2586],{},"若兩次執行是在不同的作業系統上（macOS 筆電對 Linux CI 執行器），剩下的差異來自字型算繪。請參考",[353,3775,3275],{"href":3776},"#reducing-cross-os-rendering-noise",[15,3778,3780,3781,3783],{"id":3779},"how-do-i-use-this-plugin-alongside-other-cypress-plugins-that-also-register-setupnodeevents-events","如何讓這個外掛與其他同樣在 ",[31,3782,3675],{}," 註冊事件的 Cypress 外掛並用？",[20,3785,3786,3787,3790,3791,2623],{},"Cypress 每個事件只支援一個處理函式。如果多個外掛註冊了同一個事件（例如 ",[31,3788,3789],{},"after:screenshot","），只有最後一個會被呼叫。若要安全地組合多個外掛，請使用 ",[353,3792,3794],{"href":3403,"rel":3793},[423],[31,3795,3407],{},[24,3797,3799],{"className":126,"code":3798,"language":128,"meta":29,"style":29},"import { defineConfig } from 'cypress';\nimport { initPlugin as initVisualRegressionPlugin } from '@pixsame\u002Fcypress-plugin-visual-regression-diff\u002Fplugins';\nimport fix from 'cypress-on-fix';\n\nexport default defineConfig({\n  e2e: {\n    setupNodeEvents(on, config) {\n      const fixedOn = fix(on);\n      initVisualRegressionPlugin(fixedOn, config);\n      \u002F\u002F 在這裡使用 fixedOn 註冊其他外掛\n    },\n  },\n});\n",[31,3800,3801,3813,3829,3843,3847,3857,3861,3875,3892,3899,3904,3908,3914],{"__ignoreMap":29},[34,3802,3803,3805,3807,3809,3811],{"class":36,"line":37},[34,3804,141],{"class":140},[34,3806,201],{"class":147},[34,3808,204],{"class":140},[34,3810,207],{"class":51},[34,3812,148],{"class":147},[34,3814,3815,3817,3819,3821,3823,3825,3827],{"class":36,"line":44},[34,3816,141],{"class":140},[34,3818,216],{"class":147},[34,3820,219],{"class":140},[34,3822,222],{"class":147},[34,3824,204],{"class":140},[34,3826,227],{"class":51},[34,3828,148],{"class":147},[34,3830,3831,3833,3836,3838,3841],{"class":36,"line":62},[34,3832,141],{"class":140},[34,3834,3835],{"class":147}," fix ",[34,3837,204],{"class":140},[34,3839,3840],{"class":51}," 'cypress-on-fix'",[34,3842,148],{"class":147},[34,3844,3845],{"class":36,"line":69},[34,3846,66],{"emptyLinePlaceholder":65},[34,3848,3849,3851,3853,3855],{"class":36,"line":75},[34,3850,238],{"class":140},[34,3852,241],{"class":140},[34,3854,244],{"class":162},[34,3856,247],{"class":47},[34,3858,3859],{"class":36,"line":89},[34,3860,257],{"class":147},[34,3862,3863,3865,3867,3869,3871,3873],{"class":36,"line":94},[34,3864,262],{"class":162},[34,3866,166],{"class":147},[34,3868,267],{"class":47},[34,3870,270],{"class":147},[34,3872,273],{"class":47},[34,3874,276],{"class":147},[34,3876,3877,3880,3883,3886,3889],{"class":36,"line":100},[34,3878,3879],{"class":140},"      const",[34,3881,3882],{"class":55}," fixedOn",[34,3884,3885],{"class":140}," =",[34,3887,3888],{"class":162}," fix",[34,3890,3891],{"class":147},"(on);\n",[34,3893,3894,3896],{"class":36,"line":279},[34,3895,282],{"class":162},[34,3897,3898],{"class":147},"(fixedOn, config);\n",[34,3900,3901],{"class":36,"line":288},[34,3902,3903],{"class":40},"      \u002F\u002F 在這裡使用 fixedOn 註冊其他外掛\n",[34,3905,3906],{"class":36,"line":294},[34,3907,291],{"class":147},[34,3909,3910,3912],{"class":36,"line":303},[34,3911,297],{"class":147},[34,3913,300],{"class":47},[34,3915,3916,3918],{"class":36,"line":309},[34,3917,346],{"class":47},[34,3919,148],{"class":147},[15,3921,3923],{"id":3922},"how-do-i-integrate-with-mochawesome-or-other-reporters-that-embed-screenshot-images","如何整合 mochawesome 或其他會嵌入截圖的 reporter？",[20,3925,3926,3927,3930,3931,3934],{},"這個外掛會把基準影像存放在預設的 ",[31,3928,3929],{},"cypress\u002Fscreenshots\u002F"," 目錄之外。有些 reporter（例如 ",[31,3932,3933],{},"cypress-mochawesome-reporter","）則預期截圖會放在那個資料夾裡。",[20,3936,3937,3938,3941,3942,3944,3945,3948],{},"請使用 ",[31,3939,3940],{},"processImgPath"," task hook 來控制截圖檔案的存放位置。在 ",[31,3943,3675],{}," 中呼叫 ",[31,3946,3947],{},"initPlugin"," 之後覆寫它：",[24,3950,3952],{"className":126,"code":3951,"language":128,"meta":29,"style":29},"setupNodeEvents(on, config) {\n  initVisualRegressionPlugin(on, config);\n\n  \u002F\u002F 覆寫路徑處理函式，讓 reporter 能存取截圖\n  on('task', {\n    'cp-visual-regression-diff-processImgPath': ({ path }: { path: string }) => {\n      \u002F\u002F 回傳新的路徑，或回傳原路徑以保留預設行為\n      return path;\n    },\n  });\n}\n",[31,3953,3954,3961,3968,3972,3977,3990,4024,4029,4037,4041,4046],{"__ignoreMap":29},[34,3955,3956,3958],{"class":36,"line":37},[34,3957,3675],{"class":162},[34,3959,3960],{"class":147},"(on, config) {\n",[34,3962,3963,3966],{"class":36,"line":44},[34,3964,3965],{"class":162},"  initVisualRegressionPlugin",[34,3967,285],{"class":147},[34,3969,3970],{"class":36,"line":62},[34,3971,66],{"emptyLinePlaceholder":65},[34,3973,3974],{"class":36,"line":69},[34,3975,3976],{"class":40},"  \u002F\u002F 覆寫路徑處理函式，讓 reporter 能存取截圖\n",[34,3978,3979,3982,3984,3987],{"class":36,"line":75},[34,3980,3981],{"class":162},"  on",[34,3983,166],{"class":147},[34,3985,3986],{"class":51},"'task'",[34,3988,3989],{"class":147},", {\n",[34,3991,3992,3995,3998,4001,4004,4007,4010,4012,4014,4017,4020,4022],{"class":36,"line":89},[34,3993,3994],{"class":51},"    'cp-visual-regression-diff-processImgPath'",[34,3996,3997],{"class":147},": ({ ",[34,3999,4000],{"class":47},"path",[34,4002,4003],{"class":147}," }",[34,4005,4006],{"class":140},":",[34,4008,4009],{"class":147}," { ",[34,4011,4000],{"class":47},[34,4013,4006],{"class":140},[34,4015,4016],{"class":55}," string",[34,4018,4019],{"class":147}," }) ",[34,4021,3715],{"class":140},[34,4023,3718],{"class":147},[34,4025,4026],{"class":36,"line":94},[34,4027,4028],{"class":40},"      \u002F\u002F 回傳新的路徑，或回傳原路徑以保留預設行為\n",[34,4030,4031,4034],{"class":36,"line":100},[34,4032,4033],{"class":140},"      return",[34,4035,4036],{"class":147}," path;\n",[34,4038,4039],{"class":36,"line":279},[34,4040,291],{"class":147},[34,4042,4043],{"class":36,"line":288},[34,4044,4045],{"class":147},"  });\n",[34,4047,4048],{"class":36,"line":294},[34,4049,1266],{"class":147},[15,4051,4053],{"id":4052},"how-to-fail-on-any-visual-difference-no-matter-how-small","如何讓任何視覺差異（不論多細微）都導致測試失敗？",[20,4055,4056,4057,4059,4060,2623],{},"將 ",[31,4058,2715],{}," 設為 ",[31,4061,4062],{},"0",[24,4064,4066],{"className":126,"code":4065,"language":128,"meta":29,"style":29},"cy.matchImage({ maxDiffThreshold: 0 });\n",[31,4067,4068],{"__ignoreMap":29},[34,4069,4070,4072,4074,4077,4079],{"class":36,"line":37},[34,4071,373],{"class":147},[34,4073,387],{"class":162},[34,4075,4076],{"class":147},"({ maxDiffThreshold: ",[34,4078,4062],{"class":55},[34,4080,3552],{"class":147},[20,4082,3631],{},[24,4084,4086],{"className":26,"code":4085,"language":28,"meta":29,"style":29},"# Cypress 15.10+\nnpx cypress run --expose \"pluginVisualRegressionMaxDiffThreshold=0\"\n# Cypress \u003C15.10（15.10 起棄用，16 已移除）\nnpx cypress run --env \"pluginVisualRegressionMaxDiffThreshold=0\"\n",[31,4087,4088,4092,4105,4109],{"__ignoreMap":29},[34,4089,4090],{"class":36,"line":37},[34,4091,442],{"class":40},[34,4093,4094,4096,4098,4100,4102],{"class":36,"line":44},[34,4095,447],{"class":47},[34,4097,450],{"class":51},[34,4099,453],{"class":51},[34,4101,456],{"class":55},[34,4103,4104],{"class":51}," \"pluginVisualRegressionMaxDiffThreshold=0\"\n",[34,4106,4107],{"class":36,"line":62},[34,4108,464],{"class":40},[34,4110,4111,4113,4115,4117,4119],{"class":36,"line":69},[34,4112,447],{"class":47},[34,4114,450],{"class":51},[34,4116,453],{"class":51},[34,4118,475],{"class":55},[34,4120,4104],{"class":51},[15,4122,4124],{"id":4123},"why-is-the-actual-screenshot-deleted-after-a-successful-image-comparison","為什麼影像比對成功後，實際截圖就被刪除了？",[20,4126,4127,4128,4130],{},"當影像相符時，",[31,4129,490],{}," 檔案只是暫時性的，比對完成後就會被清掉，只會保留基準影像（沒有後綴的那個）。這樣可以避免儲存多餘的檔案。",[20,4132,4133,4134,4136],{},"當影像不相符時，",[31,4135,490],{}," 檔案會被保留，並帶有與基準影像相同的外掛 metadata。您可以放心地將它重新命名或複製來覆蓋基準影像（例如在 CI 工作中開一個帶有更新後基準影像的 Pull Request），外掛會把它視為最新的基準影像，下次執行時不會再重寫它。",[20,4138,4139,4140,4142,4143,4145,4146],{},"如果您需要讓實際截圖持續可供 reporter 存取（例如 ",[31,4141,3933],{},"），請使用 ",[31,4144,3940],{}," task hook 來控制截圖的儲存位置。請參考",[353,4147,3923],{"href":4148},"#how-do-i-integrate-with-mochawesome-or-other-reporters-that-embed-screenshot-images",[15,4150,4152],{"id":4151},"how-to-remove-spaces-from-screenshot-filenames","如何移除截圖檔名中的空格？",[20,4154,4155,4156,4158,4159,4161],{},"截圖檔名取自 Cypress 的測試標題，而標題中可能包含空格。若想使用不含空格的檔名，請在每次呼叫 ",[31,4157,387],{}," 時傳入自訂的 ",[31,4160,3346],{}," 選項：",[24,4163,4165],{"className":126,"code":4164,"language":128,"meta":29,"style":29},"cy.matchImage({ title: 'my-screenshot-without-spaces' });\n",[31,4166,4167],{"__ignoreMap":29},[34,4168,4169,4171,4173,4176,4179],{"class":36,"line":37},[34,4170,373],{"class":147},[34,4172,387],{"class":162},[34,4174,4175],{"class":147},"({ title: ",[34,4177,4178],{"class":51},"'my-screenshot-without-spaces'",[34,4180,3552],{"class":147},[20,4182,4183,4184,4186,4187,4190],{},"若要套用到所有 ",[31,4185,387],{}," 呼叫，請在 support 檔案（",[31,4188,4189],{},"cypress\u002Fsupport\u002Fcommands.ts","）中覆寫這個指令：",[24,4192,4194],{"className":126,"code":4193,"language":128,"meta":29,"style":29},"Cypress.Commands.overwrite('matchImage', (originalFn, subject, options = {}) =>\n  originalFn(subject, {\n    title: Cypress.currentTest.titlePath.join(' ').replace(\u002F\\s+\u002Fg, '-'),\n    ...options,\n  }),\n);\n",[31,4195,4196,4231,4239,4278,4286,4291],{"__ignoreMap":29},[34,4197,4198,4201,4204,4206,4209,4211,4214,4216,4219,4221,4223,4225,4228],{"class":36,"line":37},[34,4199,4200],{"class":147},"Cypress.Commands.",[34,4202,4203],{"class":162},"overwrite",[34,4205,166],{"class":147},[34,4207,4208],{"class":51},"'matchImage'",[34,4210,3702],{"class":147},[34,4212,4213],{"class":47},"originalFn",[34,4215,270],{"class":147},[34,4217,4218],{"class":47},"subject",[34,4220,270],{"class":147},[34,4222,1523],{"class":47},[34,4224,3885],{"class":140},[34,4226,4227],{"class":147}," {}) ",[34,4229,4230],{"class":140},"=>\n",[34,4232,4233,4236],{"class":36,"line":44},[34,4234,4235],{"class":162},"  originalFn",[34,4237,4238],{"class":147},"(subject, {\n",[34,4240,4241,4244,4246,4248,4250,4252,4255,4257,4259,4262,4265,4267,4270,4272,4275],{"class":36,"line":62},[34,4242,4243],{"class":147},"    title: Cypress.currentTest.titlePath.",[34,4245,2298],{"class":162},[34,4247,166],{"class":147},[34,4249,2303],{"class":51},[34,4251,384],{"class":147},[34,4253,4254],{"class":162},"replace",[34,4256,166],{"class":147},[34,4258,1530],{"class":51},[34,4260,4261],{"class":55},"\\s",[34,4263,4264],{"class":140},"+",[34,4266,1530],{"class":51},[34,4268,4269],{"class":140},"g",[34,4271,270],{"class":147},[34,4273,4274],{"class":51},"'-'",[34,4276,4277],{"class":147},"),\n",[34,4279,4280,4283],{"class":36,"line":69},[34,4281,4282],{"class":140},"    ...",[34,4284,4285],{"class":147},"options,\n",[34,4287,4288],{"class":36,"line":75},[34,4289,4290],{"class":147},"  }),\n",[34,4292,4293],{"class":36,"line":89},[34,4294,172],{"class":147},[15,4296,4298],{"id":4297},"how-to-include-the-browser-name-in-image-filenames-for-cross-browser-testing","如何在影像檔名中加入瀏覽器名稱（用於跨瀏覽器測試）？",[20,4300,4301,4302,4304,4305,4307,4308,1445,4310,1445,4312,4314],{},"請在 ",[31,4303,1627],{}," 中使用 ",[31,4306,2636],{}," token；它會展開為拍攝該截圖的瀏覽器名稱（",[31,4309,2653],{},[31,4311,2656],{},[31,4313,2649],{}," 等）：",[24,4316,4318],{"className":126,"code":4317,"language":128,"meta":29,"style":29},"cy.matchImage({ imagesPath: '{spec_path}\u002F__image_snapshots__\u002F{browser}' });\n",[31,4319,4320],{"__ignoreMap":29},[34,4321,4322,4324,4326,4329,4332],{"class":36,"line":37},[34,4323,373],{"class":147},[34,4325,387],{"class":162},[34,4327,4328],{"class":147},"({ imagesPath: ",[34,4330,4331],{"class":51},"'{spec_path}\u002F__image_snapshots__\u002F{browser}'",[34,4333,3552],{"class":147},[20,4335,4336],{},"或是全域設定：",[24,4338,4340],{"className":26,"code":4339,"language":28,"meta":29,"style":29},"# Cypress 15.10+\nnpx cypress run --expose \"pluginVisualRegressionImagesPath={spec_path}\u002F__image_snapshots__\u002F{browser}\"\n# Cypress \u003C15.10（15.10 起棄用，16 已移除）\nnpx cypress run --env \"pluginVisualRegressionImagesPath={spec_path}\u002F__image_snapshots__\u002F{browser}\"\n",[31,4341,4342,4346,4359,4363],{"__ignoreMap":29},[34,4343,4344],{"class":36,"line":37},[34,4345,442],{"class":40},[34,4347,4348,4350,4352,4354,4356],{"class":36,"line":44},[34,4349,447],{"class":47},[34,4351,450],{"class":51},[34,4353,453],{"class":51},[34,4355,456],{"class":55},[34,4357,4358],{"class":51}," \"pluginVisualRegressionImagesPath={spec_path}\u002F__image_snapshots__\u002F{browser}\"\n",[34,4360,4361],{"class":36,"line":62},[34,4362,464],{"class":40},[34,4364,4365,4367,4369,4371,4373],{"class":36,"line":69},[34,4366,447],{"class":47},[34,4368,450],{"class":51},[34,4370,453],{"class":51},[34,4372,475],{"class":55},[34,4374,4358],{"class":51},[20,4376,4377,4378,1445,4381,4384,4385,491,4387,4389,4390,4392,4393,2586],{},"這樣會為每個瀏覽器建立各自的影像目錄（",[31,4379,4380],{},"__image_snapshots__\u002Fchrome\u002F",[31,4382,4383],{},"__image_snapshots__\u002Ffirefox\u002F","）。關於同時也依作業系統拆分的 ",[31,4386,2667],{},[31,4388,2617],{},"、該提交哪些資料夾，以及為什麼在存有多個瀏覽器資料夾的機器上必須保持關閉 ",[31,4391,2874],{},"（它會刪除其他瀏覽器的基準影像），請見",[353,4394,2590],{"href":4395},"#per-platform-baselines",[15,4397,4399],{"id":4398},"how-to-generate-an-html-report-showing-baseline-diff-and-actual-images","如何產生同時顯示基準、差異與實際影像的 HTML 報告？",[20,4401,4402],{},"這個外掛在 Cypress UI 中內建了視覺比對的覆蓋介面，在失敗的測試上點擊「See comparison」，就能並排檢視基準、差異與實際影像。",[20,4404,4405,4406,4412,4413,2586],{},"若需要用於 CI 或可分享的 HTML 報告，請整合像 ",[353,4407,4410],{"href":4408,"rel":4409},"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fcypress-mochawesome-reporter",[423],[31,4411,3933],{}," 這類的 reporter。設定細節請參考",[353,4414,3923],{"href":4148},[4416,4417,4418],"style",{},"html pre.shiki code .sLBg1, html code.shiki .sLBg1{--shiki-default:#66707B;--shiki-dark:#BDC4CC}html pre.shiki code .soyes, html code.shiki .soyes{--shiki-default:#702C00;--shiki-dark:#FFB757}html pre.shiki code .sT6z2, html code.shiki .sT6z2{--shiki-default:#032563;--shiki-dark:#ADDCFF}html pre.shiki code .s-5SL, html code.shiki .s-5SL{--shiki-default:#023B95;--shiki-dark:#91CBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHUrx, html code.shiki .sHUrx{--shiki-default:#A0111F;--shiki-dark:#FF9492}html pre.shiki code .suds8, html code.shiki .suds8{--shiki-default:#0E1116;--shiki-dark:#F0F3F6}html pre.shiki code .sKwhi, html code.shiki .sKwhi{--shiki-default:#622CBC;--shiki-dark:#DBB7FF}",{"title":29,"searchDepth":44,"depth":44,"links":4420},[4421,4424,4425,4426,4427,4428,4429,4430,4435,4436],{"id":12,"depth":44,"text":13,"children":4422},[4423],{"id":17,"depth":62,"text":18},{"id":360,"depth":44,"text":356},{"id":414,"depth":44,"text":415},{"id":428,"depth":44,"text":429},{"id":480,"depth":44,"text":481},{"id":1954,"depth":44,"text":1955},{"id":2589,"depth":44,"text":2590},{"id":2909,"depth":44,"text":2910,"children":4431},[4432,4433,4434],{"id":2920,"depth":62,"text":2921},{"id":2972,"depth":62,"text":2973},{"id":3149,"depth":62,"text":3150},{"id":3274,"depth":44,"text":3275},{"id":3555,"depth":44,"text":3556,"children":4437},[4438,4440,4441,4443,4445,4446,4447,4448,4449,4450],{"id":3559,"depth":62,"text":4439},"為什麼截圖不符合我在 Cypress 設定中指定的 viewport？",{"id":3586,"depth":62,"text":3587},{"id":3593,"depth":62,"text":4442},"cypress run 和 cypress open 的截圖看起來不一樣，該怎麼解決？",{"id":3779,"depth":62,"text":4444},"如何讓這個外掛與其他同樣在 setupNodeEvents 註冊事件的 Cypress 外掛並用？",{"id":3922,"depth":62,"text":3923},{"id":4052,"depth":62,"text":4053},{"id":4123,"depth":62,"text":4124},{"id":4151,"depth":62,"text":4152},{"id":4297,"depth":62,"text":4298},{"id":4398,"depth":62,"text":4399},"md",{},"\u002Freadme\u002Freadme-zh-tw",false,{"description":29},"3f4ca9c7906dc926","readme\u002FREADME-zh-TW","J-02URu8h8icZvMQkmEE_ZMo4s2YQgfwBXPJPSiHFSc",1794530806930]