[{"data":1,"prerenderedAt":4459},["ShallowReactive",2],{"readme:zh":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-CN.md","README Zh CN",{"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,2756,2804,2812,2815,2888,2908,2912,2919,2923,2926,2949,2956,2971,2975,2990,3029,3089,3148,3152,3165,3172,3210,3270,3273,3277,3284,3342,3351,3357,3381,3410,3431,3434,3472,3532,3535,3554,3558,3565,3568,3585,3589,3592,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","本仓库的 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 提供商、仓库、提交、pull request、运行 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 产物放在一起，位于 ",[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 事件中：合并提交\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 事件中：合并提交\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,1451,1486,1496,1517,1539,1590],{},[1274,1439,1440,1448],{},[1301,1441,1442,270,1445],{},[31,1443,1444],{},"createdAt",[31,1446,1447],{},"updatedAt",[1301,1449,1450],{},"运行开始的时间以及文件最后一次被重写的时间（ISO 8601）",[1274,1452,1453,1458],{},[1301,1454,1455],{},[31,1456,1457],{},"platform",[1301,1459,1460,1463,1464,1467,1468,1467,1471,1474,1475,1478,1479,1482,1483],{},[31,1461,1462],{},"osPlatform","（",[31,1465,1466],{},"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],{},"CI","）为 ",[31,1511,1512],{},"{ \"provider\": null }","，不在 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,1467,1581,1467,1584,1467,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,1740,1775,1785,1818,1832,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 项目目录，不一定是仓库根目录：",[31,1637,1638],{},"ci.workspace"," 是 checkout 目录，因此 ",[31,1641,1642],{},"relative(ci.workspace, projectRoot)"," 即为仓库内的路径前缀。",[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,1463,1681,1467,1684,1467,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,1729,1730,1732,1733,1735,1736,1739],{},"每个条目都带有自己的 ",[31,1722,1457],{},[31,1724,1725],{},"viewport","，因此在拼接多份清单后，仍能区分来自机器矩阵中不同机器的条目。条目上的 ",[31,1728,1523],{}," 是 ",[31,1731,387],{}," 的精确输入（",[31,1734,1627],{}," 保留未展开的变量）；",[31,1737,1738],{},"comparison"," 是比对结果。",[117,1741,1742,1744,1745,1748,1749,1552,1752,1755,1756,1759,1760,1763,1764,491,1767,1770,1771,1774],{},[31,1743,1457],{}," 是测试运行的位置，",[31,1746,1747],{},"renderer"," 是像素的来源。目前每张截图都由 Cypress 驱动的浏览器拍摄，因此 ",[31,1750,1751],{},"renderer.backend",[31,1753,1754],{},"native","，",[31,1757,1758],{},"renderer.browser"," 与 ",[31,1761,1762],{},"platform.browser.name"," 相同。该字段的存在是为了让本地浏览器以外的渲染器（固定版本的 Docker 镜像、托管渲染器）能通过 ",[31,1765,1766],{},"rendererVersion",[31,1768,1769],{},"imageDigest"," 标识自己，也为了让不得不回退到本地浏览器的运行能用 ",[31,1772,1773],{},"renderer.fallback: true"," 标记出来。请将渲染器不同的条目视为不同的基线。",[117,1776,1777,1780,1781,1784],{},[31,1778,1779],{},"hashes"," 保存 ",[31,1782,1783],{},"images"," 中每个在磁盘上存在的文件的 sha256。可用它跳过重新上传未变化的基线、检查 artifact 是否与清单一致，或找出产生了完全相同像素的两个条目。",[117,1786,1787,1788,491,1791,1794,1795,1798,1799,1802,1803,1806,1807,1810,1811,491,1814,1817],{},"映射到 pull request：使用 ",[31,1789,1790],{},"ci.repositoryName",[31,1792,1793],{},"ci.pullRequest.number","。在 GitHub 的 ",[31,1796,1797],{},"pull_request"," 事件中，",[31,1800,1801],{},"ci.commit"," 是临时的合并提交，因此任何需要推送到 PR 分支的操作都必须使用 ",[31,1804,1805],{},"ci.pullRequest.headSha"," \u002F ",[31,1808,1809],{},"headRef","。工作流 artifact 可通过 ",[31,1812,1813],{},"ci.buildId",[31,1815,1816],{},"ci.runAttempt"," 找到。",[117,1819,1820,1821,1824,1825,1827,1828,1831],{},"重现一次运行：",[31,1822,1823],{},"npx cypress run --\u003Crunner.testingType> --browser \u003Crunner.browser.name> --config-file \u003Crunner.configFile> --spec \u003Crunner.specs joined with ,>","，再为 ",[31,1826,1523],{}," 中的每一项加上一个 ",[31,1829,1830],{},"--expose \"pluginVisualRegression\u003CKey>=\u003Cvalue>\"","。清单将这些内容按组成部分存储，而不是存成一条命令字符串，因此 shell 引号和包管理器由您自行决定。",[117,1833,1834,1835,1838,1839,1842,1843,1713,1845,1606,1848,1851],{},"该文件在每次比对后都会重写，因此即使运行被中止，它也是完整的。当 spec 在多台机器上并行运行时，每台机器都会写入自己的清单；",[31,1836,1837],{},"**\u002Fvisual-regression-manifest{,.*}.json","（包中的 ",[31,1840,1841],{},"MANIFEST_FILE_GLOB","）可以在 artifact 中找到所有清单，",[31,1844,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 作为分隔符，例如 windows 盘符写法：C:\u002Fmy-directory\u002Fnested\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 可用它们将不同操作系统\u002F浏览器的基线分开存放，参见下文 \"Per-platform baselines\"\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 应用确定性渲染预设，参见下文 \"Reducing cross-OS rendering noise\"\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 作为分隔符，例如 windows 盘符写法：C:\u002Fmy-directory\u002Fnested\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 可用它们将不同操作系统\u002F浏览器的基线分开存放，参见下文 \"Per-platform baselines\"\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 应用确定性渲染预设，参见下文 \"Reducing cross-OS rendering noise\"\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],{},"令牌",[1277,2607,2608],{},"展开为",[1296,2610,2611,2630,2661],{},[1274,2612,2613,2618],{},[1301,2614,2615],{},[31,2616,2617],{},"{os}",[1301,2619,2620,2623,2624,1467,2626,1391,2628],{},[31,2621,2622],{},"Cypress.platform","：",[31,2625,1466],{},[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,1467,2654,1467,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,1467,2677],{},[31,2671,2672],{},"{os}-{browser}","，例如 ",[31,2675,2676],{},"linux-chrome",[31,2678,2679],{},"darwin-electron",[20,2681,2682,2683,2685,2686,2688,2689,2692,2693,2695,2696,2699,2700,2586],{},"每张截图都由 Cypress 驱动的浏览器截取，因此 ",[31,2684,2636],{}," 就是那个浏览器；不带 ",[31,2687,2645],{}," 的 ",[31,2690,2691],{},"cypress run"," 使用 Electron，这就是为什么目录名是 ",[31,2694,2679],{}," 而不是 ",[31,2697,2698],{},"darwin-chrome","——除非 CI 传入了 ",[31,2701,2702],{},"--browser chrome",[20,2704,2705,2706,2708,2709,2712,2713,2716],{},"这些令牌是可选启用的：默认的 ",[31,2707,1627],{}," 仍为 ",[31,2710,2711],{},"{spec_path}\u002F__image_snapshots__","，即所有人共用一套基线。当每次运行都在相同的操作系统和浏览器上进行（例如在容器内，参见 FAQ），或者剩余的差异仍低于您的 ",[31,2714,2715],{},"maxDiffThreshold"," 时，这就是正确的布局。要按平台拆分，请全局添加该令牌：",[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,2744],{"__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,2743],{"class":40},"# Cypress \u003C15.10（在 15.10 中已废弃，16 中移除）\n",[34,2745,2746,2748,2750,2752,2754],{"class":36,"line":69},[34,2747,447],{"class":47},[34,2749,450],{"class":51},[34,2751,453],{"class":51},[34,2753,475],{"class":55},[34,2755,2738],{"class":51},[24,2757,2759],{"className":126,"code":2758,"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,2760,2761,2766,2776,2780,2785,2792,2798],{"__ignoreMap":29},[34,2762,2763],{"class":36,"line":37},[34,2764,2765],{"class":40},"\u002F\u002F cypress.config.ts（Cypress 15.10+；在 Cypress \u003C15.10 上请使用 `env` 而不是 `expose`）\n",[34,2767,2768,2770,2772,2774],{"class":36,"line":44},[34,2769,238],{"class":140},[34,2771,241],{"class":140},[34,2773,244],{"class":162},[34,2775,247],{"class":47},[34,2777,2778],{"class":36,"line":62},[34,2779,2478],{"class":147},[34,2781,2782],{"class":36,"line":69},[34,2783,2784],{"class":147},"    pluginVisualRegressionImagesPath:\n",[34,2786,2787,2790],{"class":36,"line":75},[34,2788,2789],{"class":51},"      '{spec_path}\u002F__image_snapshots__\u002F{platform}'",[34,2791,300],{"class":147},[34,2793,2794,2796],{"class":36,"line":89},[34,2795,297],{"class":147},[34,2797,300],{"class":47},[34,2799,2800,2802],{"class":36,"line":94},[34,2801,346],{"class":47},[34,2803,148],{"class":147},[24,2805,2810],{"className":2806,"code":2808,"language":2809},[2807],"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,2811,2808],{"__ignoreMap":29},[20,2813,2814],{},"拆分之后需要决定的事项：",[114,2816,2817,2854,2867],{},[117,2818,2819,2823,2824,2846,2849,2850,1632],{},[2820,2821,2822],"strong",{},"提交哪些基线。"," 大多数团队只提交 CI 平台的基线，并将本地基线排除在 git 之外，这样每位开发者都有自己的一套基线，又不会污染仓库：",[24,2825,2829],{"className":2826,"code":2827,"language":2828,"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,2830,2831,2836,2841],{"__ignoreMap":29},[34,2832,2833],{"class":36,"line":37},[34,2834,2835],{},"# 忽略除 CI 生成的平台目录之外的所有平台目录\n",[34,2837,2838],{"class":36,"line":44},[34,2839,2840],{},"**\u002F__image_snapshots__\u002F*\u002F\n",[34,2842,2843],{"class":36,"line":62},[34,2844,2845],{},"!**\u002F__image_snapshots__\u002Flinux-chrome\u002F\n",[2847,2848],"br",{},"此后，新的 CI 基线需要在 CI 上生成并从那里提交（或从 PR 中批准，参见",[353,2851,2853],{"href":2852},"#run-manifest-ci-integration","运行清单",[117,2855,2856,2859,2860,1391,2862,2673,2864,2586],{},[2820,2857,2858],{},"只按浏览器或只按操作系统拆分。"," 单独使用 ",[31,2861,2636],{},[31,2863,2617],{},[31,2865,2866],{},"{spec_path}\u002F__image_snapshots__\u002F{browser}",[117,2868,2869,2872,2873,2876,2877,2879,2880,2883,2884,2887],{},[2820,2870,2871],{},"清理功能会删除其他平台的基线。"," ",[31,2874,2875],{},"pluginVisualRegressionCleanupUnusedImages"," 会在整个项目中查找插件生成的 PNG 文件，它对平台一无所知：在 ",[31,2878,2679],{}," 上运行时，会把 ",[31,2881,2882],{},"linux-chrome\u002F"," 下的每个文件都视为未使用并删除。在存放了多个平台目录的机器上（开发者的 checkout 加上已提交的 CI 基线正是这种情况）请保持它关闭，只在仅存放单一平台基线的地方启用它，通常就是生成这些基线的 CI 任务。如果不小心触发了，可以用 ",[31,2885,2886],{},"git checkout -- \u003Cfolder>"," 恢复被删除的目录。",[20,2889,2890,2891,2896,2897,2899,2900,2902,2903,1744,2905,2907],{},"未来的方向：",[353,2892,2895],{"href":2893,"rel":2894},"https:\u002F\u002Fgithub.com\u002FFRSOURCE\u002Fcypress-plugin-visual-regression-diff\u002Fissues\u002F212",[423],"#212"," 的计划是一个渲染器，无论 Cypress 在哪里运行，都在一个固定版本的 Docker 镜像中生成像素，从而从根本上消除本地与 CI 图片之间的漂移。届时 ",[31,2898,2636],{}," 指的是渲染器的浏览器，而不是 Cypress 驱动的浏览器；",[31,2901,2667],{}," 仍然有用，但用途是区分多个被渲染的浏览器，而不是处理本地与 CI 之间的漂移。清单已经同时记录了这两方面：",[31,2904,1457],{},[31,2906,1747],{}," 是像素的来源。",[10,2909,2911],{"id":2910},"batch-review-mode","批量审查模式",[20,2913,2914,2915,2918],{},"批量审查模式（Batch Review Mode）",[2820,2916,2917],{},"默认启用","。它让您可以完整跑完整个测试套件，而不会在第一个视觉差异失败处停下。所有失败的快照会被收集起来，在测试结束后通过一个交互式审查界面展示，让您可以批量通过或跳过这些变更。",[15,2920,2922],{"id":2921},"additions-in-headed-mode-non-ci-environments","有头模式（非 CI 环境）下的额外功能",[20,2924,2925],{},"Cypress 测试运行器右下角会出现一个悬浮操作按钮（FAB）。测试运行过程中：",[114,2927,2928,2935,2938],{},[117,2929,2930,2931,2934],{},"每当某次 ",[31,2932,2933],{},"matchImage()"," 调用的差异超过阈值，FAB 上的计数徽标会加一，而不是立即抛出错误。",[117,2936,2937],{},"所有测试结束后，会抛出一个包含失败总数的错误。",[117,2939,2940,2941,2944,2945,2948],{},"点击 FAB 会打开一个轮播面板，您可以逐一并排审查每个失败的快照（新图 vs 旧图），然后选择",[2820,2942,2943],{},"替换","基线或",[2820,2946,2947],{},"跳过","该变更。",[20,2950,2951],{},[2952,2953],"img",{"alt":2954,"src":2955},"批量审查模式演示","https:\u002F\u002Fraw.githubusercontent.com\u002Fpixsame\u002Fpixsame\u002Fmain\u002Fassets\u002Fbatch-review-mode.gif",[2957,2958,2959],"blockquote",{},[20,2960,2961,2962,2965,2966,2586],{},"注意：在 ",[31,2963,2964],{},"@pixsame\u002Fcypress-plugin-visual-regression-diff"," 第 2 版之前，批量审查模式是可选启用的。如果您从 4.x 升级，请参阅",[353,2967,2970],{"href":2968,"rel":2969},"https:\u002F\u002Fgithub.com\u002Fpixsame\u002Fpixsame\u002Fblob\u002Fmain\u002Fpackages\u002Fcypress-plugin-visual-regression-diff\u002FMIGRATION.md#4x---5x",[423],"迁移指南",[15,2972,2974],{"id":2973},"how-to-disable","如何禁用",[20,2976,2977,2978,2980,2981,2983,2984,2987,2988,2623],{},"批量审查模式是一个全局选项（不能直接传给 ",[31,2979,387],{},"）。如需恢复为在第一次不匹配时立即让 ",[31,2982,2933],{}," 失败，请将 ",[31,2985,2986],{},"pluginVisualRegressionBatchReviewMode"," 键设为 ",[31,2989,1896],{},[24,2991,2993],{"className":26,"code":2992,"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,2994,2995,2999,3013,3017],{"__ignoreMap":29},[34,2996,2997],{"class":36,"line":37},[34,2998,442],{"class":40},[34,3000,3001,3003,3005,3008,3010],{"class":36,"line":44},[34,3002,447],{"class":47},[34,3004,450],{"class":51},[34,3006,3007],{"class":51}," open",[34,3009,456],{"class":55},[34,3011,3012],{"class":51}," \"pluginVisualRegressionBatchReviewMode=false\"\n",[34,3014,3015],{"class":36,"line":62},[34,3016,464],{"class":40},[34,3018,3019,3021,3023,3025,3027],{"class":36,"line":69},[34,3020,447],{"class":47},[34,3022,450],{"class":51},[34,3024,3007],{"class":51},[34,3026,475],{"class":55},[34,3028,3012],{"class":51},[24,3030,3032],{"className":126,"code":3031,"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,3033,3034,3038,3050,3054,3064,3068,3077,3083],{"__ignoreMap":29},[34,3035,3036],{"class":36,"line":37},[34,3037,2447],{"class":40},[34,3039,3040,3042,3044,3046,3048],{"class":36,"line":44},[34,3041,141],{"class":140},[34,3043,201],{"class":147},[34,3045,204],{"class":140},[34,3047,207],{"class":51},[34,3049,148],{"class":147},[34,3051,3052],{"class":36,"line":62},[34,3053,66],{"emptyLinePlaceholder":65},[34,3055,3056,3058,3060,3062],{"class":36,"line":69},[34,3057,238],{"class":140},[34,3059,241],{"class":140},[34,3061,244],{"class":162},[34,3063,247],{"class":47},[34,3065,3066],{"class":36,"line":75},[34,3067,2478],{"class":147},[34,3069,3070,3073,3075],{"class":36,"line":89},[34,3071,3072],{"class":147},"    pluginVisualRegressionBatchReviewMode: ",[34,3074,1896],{"class":55},[34,3076,300],{"class":147},[34,3078,3079,3081],{"class":36,"line":94},[34,3080,297],{"class":147},[34,3082,300],{"class":47},[34,3084,3085,3087],{"class":36,"line":100},[34,3086,346],{"class":47},[34,3088,148],{"class":147},[24,3090,3092],{"className":126,"code":3091,"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,3093,3094,3098,3110,3114,3124,3128,3136,3142],{"__ignoreMap":29},[34,3095,3096],{"class":36,"line":37},[34,3097,2519],{"class":40},[34,3099,3100,3102,3104,3106,3108],{"class":36,"line":44},[34,3101,141],{"class":140},[34,3103,201],{"class":147},[34,3105,204],{"class":140},[34,3107,207],{"class":51},[34,3109,148],{"class":147},[34,3111,3112],{"class":36,"line":62},[34,3113,66],{"emptyLinePlaceholder":65},[34,3115,3116,3118,3120,3122],{"class":36,"line":69},[34,3117,238],{"class":140},[34,3119,241],{"class":140},[34,3121,244],{"class":162},[34,3123,247],{"class":47},[34,3125,3126],{"class":36,"line":75},[34,3127,2550],{"class":147},[34,3129,3130,3132,3134],{"class":36,"line":89},[34,3131,3072],{"class":147},[34,3133,1896],{"class":55},[34,3135,300],{"class":147},[34,3137,3138,3140],{"class":36,"line":94},[34,3139,297],{"class":147},[34,3141,300],{"class":47},[34,3143,3144,3146],{"class":36,"line":100},[34,3145,346],{"class":47},[34,3147,148],{"class":147},[15,3149,3151],{"id":3150},"reviewing-passing-images","审查已通过的图片",[20,3153,3154,3155,3157,3158,3161,3162,3164],{},"与基线有差异但仍在 ",[31,3156,2715],{}," 范围内的图片不会导致测试失败，但同样会被收集。轮播面板中有一个 ",[2820,3159,3160],{},"Show passing"," 复选框，勾选后即可浏览这些图片（每张都带有 ",[31,3163,1305],{}," 标记），并同样可以替换它们的基线，例如用来消除逐渐累积的细微偏差。",[20,3166,3167,3168,3171],{},"该复选框默认不勾选。可通过 ",[31,3169,3170],{},"pluginVisualRegressionBatchReviewModeShowPassingImages"," 键将其设为默认勾选：",[24,3173,3175],{"className":26,"code":3174,"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,3176,3177,3181,3194,3198],{"__ignoreMap":29},[34,3178,3179],{"class":36,"line":37},[34,3180,442],{"class":40},[34,3182,3183,3185,3187,3189,3191],{"class":36,"line":44},[34,3184,447],{"class":47},[34,3186,450],{"class":51},[34,3188,3007],{"class":51},[34,3190,456],{"class":55},[34,3192,3193],{"class":51}," \"pluginVisualRegressionBatchReviewModeShowPassingImages=true\"\n",[34,3195,3196],{"class":36,"line":62},[34,3197,464],{"class":40},[34,3199,3200,3202,3204,3206,3208],{"class":36,"line":69},[34,3201,447],{"class":47},[34,3203,450],{"class":51},[34,3205,3007],{"class":51},[34,3207,475],{"class":55},[34,3209,3193],{"class":51},[24,3211,3213],{"className":126,"code":3212,"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,3214,3215,3219,3231,3235,3245,3249,3258,3264],{"__ignoreMap":29},[34,3216,3217],{"class":36,"line":37},[34,3218,2447],{"class":40},[34,3220,3221,3223,3225,3227,3229],{"class":36,"line":44},[34,3222,141],{"class":140},[34,3224,201],{"class":147},[34,3226,204],{"class":140},[34,3228,207],{"class":51},[34,3230,148],{"class":147},[34,3232,3233],{"class":36,"line":62},[34,3234,66],{"emptyLinePlaceholder":65},[34,3236,3237,3239,3241,3243],{"class":36,"line":69},[34,3238,238],{"class":140},[34,3240,241],{"class":140},[34,3242,244],{"class":162},[34,3244,247],{"class":47},[34,3246,3247],{"class":36,"line":75},[34,3248,2478],{"class":147},[34,3250,3251,3254,3256],{"class":36,"line":89},[34,3252,3253],{"class":147},"    pluginVisualRegressionBatchReviewModeShowPassingImages: ",[34,3255,2090],{"class":55},[34,3257,300],{"class":147},[34,3259,3260,3262],{"class":36,"line":94},[34,3261,297],{"class":147},[34,3263,300],{"class":47},[34,3265,3266,3268],{"class":36,"line":100},[34,3267,346],{"class":47},[34,3269,148],{"class":147},[20,3271,3272],{},"在运行器中切换该复选框的状态会记录在浏览器的 local storage 中，后续运行时将优先于配置中的值。",[10,3274,3276],{"id":3275},"reducing-cross-os-rendering-noise","Reducing cross-OS rendering noise",[20,3278,3279,3280,3283],{},"浏览器会把文字光栅化交给操作系统处理（macOS 上是 CoreText，Windows 上是 DirectWrite，Linux 上是 FreeType），因此同一个页面在开发者的笔记本和 Linux CI 机器上永远不会渲染出逐字节完全一致的结果。插件无法彻底消除这种差异，但 ",[31,3281,3282],{},"deterministicRendering"," 预设（默认启用）可以去掉其中产生于浏览器内部的那部分噪声：",[114,3285,3286,3308,3318,3331],{},[117,3287,3288,3291,3292,3295,3296,3299,3300,3303,3304,3307],{},[2820,3289,3290],{},"Chrome、Chromium、Edge"," 启动时会带上 ",[31,3293,3294],{},"--font-render-hinting=none --disable-font-subpixel-positioning --disable-lcd-text --force-color-profile=srgb --disable-gpu","（文字不使用操作系统 hinting 和子像素技巧，不做色彩管理，使用 CPU 光栅化），无头模式下还会加上 ",[31,3297,3298],{},"--hide-scrollbars","。该列表以 ",[31,3301,3302],{},"DETERMINISTIC_RENDERING_CHROMIUM_ARGS"," 之名从 ",[31,3305,3306],{},"@pixsame\u002Fcypress-plugin-visual-regression-diff\u002Fconstants"," 导出。",[117,3309,3310,3313,3314,3317],{},[2820,3311,3312],{},"Firefox"," 会设置 ",[31,3315,3316],{},"gfx.webrender.software"," 偏好项（CPU 渲染）。Firefox 没有跨平台的字体 hinting 开关，因此不同操作系统之间的文字仍可能存在差异。",[117,3319,3320,3323,3324,3326,3327,3330],{},[2820,3321,3322],{},"所有浏览器","：在 ",[31,3325,387],{}," 截图期间，会向被测页面注入一个 ",[31,3328,3329],{},"\u003Cstyle>"," 元素，用于隐藏文本光标、禁用 CSS 过渡、动画和平滑滚动，并隐藏滚动条。截图完成后立即移除。",[117,3332,3333,3334,3337,3338,3341],{},"比对时会以 ",[31,3335,3336],{},"includeAA: false"," 运行 ",[31,3339,3340],{},"pixelmatch","，因此抗锯齿边缘像素会被检测出来，不计入差异。",[20,3343,3344,3345,491,3348,3350],{},"该预设无法解决的问题：各操作系统上字体文件和回退字体不同（典型的 Arial 与 Liberation Sans 问题）、emoji 字体、WebKit 和 Firefox 的文字光栅化，以及 WebGL 绘制的图像。对于这些情况，请为每个平台各保留一份基线（参见 ",[31,3346,3347],{},"title",[31,3349,1627],{}," 选项，以及关于浏览器名称的 FAQ 条目），或者在与 CI 相同的环境中生成基线。",[20,3352,3353,3356],{},[2820,3354,3355],{},"Electron"," 会忽略插件设置的开关。请改为通过环境变量传入这些开关：",[24,3358,3360],{"className":26,"code":3359,"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,3361,3362],{"__ignoreMap":29},[34,3363,3364,3367,3370,3373,3376,3378],{"class":36,"line":37},[34,3365,3366],{"class":147},"ELECTRON_EXTRA_LAUNCH_ARGS",[34,3368,3369],{"class":140},"=",[34,3371,3372],{"class":51},"\"--font-render-hinting=none --disable-font-subpixel-positioning --disable-lcd-text --force-color-profile=srgb --disable-gpu --hide-scrollbars\"",[34,3374,3375],{"class":47}," npx",[34,3377,450],{"class":51},[34,3379,3380],{"class":51}," run\n",[20,3382,3383,2623,3386,3389,3390,3393,3394,3397,3398,3401,3402,3409],{},[2820,3384,3385],{},"WebGL",[31,3387,3388],{},"--disable-gpu"," 可能导致依赖 WebGL 的页面无法获得渲染上下文。要么禁用该预设，要么在您自己的 ",[31,3391,3392],{},"before:browser:launch"," 处理函数中加入 ",[31,3395,3396],{},"--use-gl=angle --use-angle=swiftshader","（较新的 Chrome 还需要 ",[31,3399,3400],{},"--enable-unsafe-swiftshader","），并通过 ",[353,3403,3406],{"href":3404,"rel":3405},"https:\u002F\u002Fgithub.com\u002Fbahmutov\u002Fcypress-on-fix",[423],[31,3407,3408],{},"cypress-on-fix"," 将其与插件自带的处理函数组合起来。",[20,3411,3412,3415,3416,491,3419,3422,3423,3426,3427,3430],{},[2820,3413,3414],{},"截图钩子","：插件会为它拍摄的每张截图传入自己的 ",[31,3417,3418],{},"onBeforeScreenshot",[31,3420,3421],{},"onAfterScreenshot","。通过 ",[31,3424,3425],{},"screenshotConfig"," 传入的钩子仍会被调用；通过 ",[31,3428,3429],{},"Cypress.Screenshot.defaults()"," 全局设置的钩子则不会。",[20,3432,3433],{},"要全局关闭该预设（浏览器开关和 CSS）：",[24,3435,3437],{"className":26,"code":3436,"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,3438,3439,3443,3456,3460],{"__ignoreMap":29},[34,3440,3441],{"class":36,"line":37},[34,3442,442],{"class":40},[34,3444,3445,3447,3449,3451,3453],{"class":36,"line":44},[34,3446,447],{"class":47},[34,3448,450],{"class":51},[34,3450,453],{"class":51},[34,3452,456],{"class":55},[34,3454,3455],{"class":51}," \"pluginVisualRegressionDeterministicRendering=false\"\n",[34,3457,3458],{"class":36,"line":62},[34,3459,464],{"class":40},[34,3461,3462,3464,3466,3468,3470],{"class":36,"line":69},[34,3463,447],{"class":47},[34,3465,450],{"class":51},[34,3467,453],{"class":51},[34,3469,475],{"class":55},[34,3471,3455],{"class":51},[24,3473,3475],{"className":126,"code":3474,"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,3476,3477,3481,3493,3497,3507,3511,3520,3526],{"__ignoreMap":29},[34,3478,3479],{"class":36,"line":37},[34,3480,2447],{"class":40},[34,3482,3483,3485,3487,3489,3491],{"class":36,"line":44},[34,3484,141],{"class":140},[34,3486,201],{"class":147},[34,3488,204],{"class":140},[34,3490,207],{"class":51},[34,3492,148],{"class":147},[34,3494,3495],{"class":36,"line":62},[34,3496,66],{"emptyLinePlaceholder":65},[34,3498,3499,3501,3503,3505],{"class":36,"line":69},[34,3500,238],{"class":140},[34,3502,241],{"class":140},[34,3504,244],{"class":162},[34,3506,247],{"class":47},[34,3508,3509],{"class":36,"line":75},[34,3510,2478],{"class":147},[34,3512,3513,3516,3518],{"class":36,"line":89},[34,3514,3515],{"class":147},"    pluginVisualRegressionDeterministicRendering: ",[34,3517,1896],{"class":55},[34,3519,300],{"class":147},[34,3521,3522,3524],{"class":36,"line":94},[34,3523,297],{"class":147},[34,3525,300],{"class":47},[34,3527,3528,3530],{"class":36,"line":100},[34,3529,346],{"class":47},[34,3531,148],{"class":147},[20,3533,3534],{},"要保留浏览器开关，只对单张截图跳过 CSS（例如您想捕获的正是动画的结束状态）：",[24,3536,3538],{"className":126,"code":3537,"language":128,"meta":29,"style":29},"cy.matchImage({ deterministicRendering: false });\n",[31,3539,3540],{"__ignoreMap":29},[34,3541,3542,3544,3546,3549,3551],{"class":36,"line":37},[34,3543,373],{"class":147},[34,3545,387],{"class":162},[34,3547,3548],{"class":147},"({ deterministicRendering: ",[34,3550,1896],{"class":55},[34,3552,3553],{"class":147}," });\n",[10,3555,3557],{"id":3556},"faq","常见问题",[15,3559,3561,3562,3564],{"id":3560},"why-screenshots-doesnt-conform-to-the-viewport-set-in-my-cypress-configuration","为什么截图与我 Cypress 配置中设置的 ",[31,3563,1725],{}," 不一致？",[20,3566,3567],{},"Cypress 的截图默认不会按视口尺寸裁剪。您可以这样修改此行为：",[114,3569,3570,3576],{},[117,3571,3572,3573],{},"全局修改，更改默认截图配置：",[31,3574,3575],{},"Cypress.Screenshot.defaults({ capture: 'viewport' });",[117,3577,3578,3579,1966,3582],{},"局部修改，将截图配置直接传给 ",[31,3580,3581],{},".matchImage",[31,3583,3584],{},"cy.matchImage({ screenshotConfig: { capture: 'viewport' } });",[15,3586,3588],{"id":3587},"ive-upgraded-version-of-this-plugin-and-all-on-my-baseline-images-has-been-automatically-updated-why","升级本插件版本后，我所有的基线图片都被自动更新了，这是为什么？",[20,3590,3591],{},"有时我们需要对图片比对或图片生成算法做破坏性变更。为了让您的升级过程尽可能顺畅，插件会自动更新您的基线图片。升级插件后，只需把这些图片提交到仓库即可！",[15,3593,3595,491,3597,3600],{"id":3594},"screenshots-look-different-between-cypress-run-and-cypress-open-how-do-i-fix-it",[31,3596,2691],{},[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,3553],{"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],{},"如果视口尺寸差异持续存在，可以考虑在 ",[31,3674,3675],{},"setupNodeEvents"," 中显式设置浏览器窗口大小（通过 ",[353,3678,3680],{"href":3404,"rel":3679},[423],[31,3681,3408],{}," 将其与插件自带的 ",[31,3684,3392],{}," 处理函数组合起来）：",[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,3276],{"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":3404,"rel":3793},[423],[31,3795,3408],{},[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 或其他会内嵌截图的报告工具集成？",[20,3925,3926,3927,3930,3931,3934],{},"本插件将基线图片存放在默认的 ",[31,3928,3929],{},"cypress\u002Fscreenshots\u002F"," 目录之外。而有些报告工具（如 ",[31,3932,3933],{},"cypress-mochawesome-reporter","）要求截图位于该目录下。",[20,3936,3937,3938,3941,3942,3944,3945,3948],{},"可以使用 ",[31,3939,3940],{},"processImgPath"," task 钩子控制截图文件的存放位置。在 ",[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 覆盖路径处理函数，让报告工具能够访问到截图\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 覆盖路径处理函数，让报告工具能够访问到截图\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,3553],{"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],{}," 文件会被保留，并且携带与基线图片相同的插件元数据。您可以放心地将它重命名或复制覆盖到基线图片上（例如在 CI 任务中用更新后的基线创建一个 Pull Request）——插件会将其视为最新的基线，下次运行时不会重新生成。",[20,4138,4139,4140,4142,4143,4145,4146],{},"如果您需要让实际截图对报告工具（例如 ",[31,4141,3933],{},"）保持可访问，请使用 ",[31,4144,3940],{}," task 钩子来控制截图的存放位置。参见",[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,3347],{}," 选项：",[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,3553],{"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,1467,4310,1467,4312,4314],{},"在 ",[31,4303,1627],{}," 中使用 ",[31,4306,2636],{}," 令牌；它会展开为渲染该截图的浏览器名称（",[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,3553],{"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,2743],{"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,1467,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,2875],{}," 关闭（它会删除其他浏览器的基线），请参见",[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 界面中内置了视觉比对浮层：在失败的测试上点击「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],{}," 之类的报告工具集成。配置细节参见",[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":2910,"depth":44,"text":2911,"children":4431},[4432,4433,4434],{"id":2921,"depth":62,"text":2922},{"id":2973,"depth":62,"text":2974},{"id":3150,"depth":62,"text":3151},{"id":3275,"depth":44,"text":3276},{"id":3556,"depth":44,"text":3557,"children":4437},[4438,4440,4441,4443,4445,4446,4447,4448,4449,4450],{"id":3560,"depth":62,"text":4439},"为什么截图与我 Cypress 配置中设置的 viewport 不一致？",{"id":3587,"depth":62,"text":3588},{"id":3594,"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-cn",false,{"description":29},"3f4ca9c7906dc926","readme\u002FREADME-zh-CN","FNMKUg_7fbCZajkgAwpHXKjJRgcYIFT6KvMHrRhw8CE",1794530806920]