vitest-plugin-vis 2.3.2 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/client/image_snapshot_matcher.d.ts +2 -2
- package/esm/client/image_snapshot_matcher.d.ts.map +1 -1
- package/esm/client/image_snapshot_matcher.js +3 -3
- package/esm/client/snapshot_options.js +1 -1
- package/esm/commands.d.ts +1 -2
- package/esm/commands.d.ts.map +1 -1
- package/esm/commands.js +1 -2
- package/esm/config/types.d.ts +3 -3
- package/esm/config/types.d.ts.map +1 -1
- package/esm/config/vis.d.ts +1 -2
- package/esm/config/vis.d.ts.map +1 -1
- package/esm/config/vis.js +4 -3
- package/esm/server/commands/browser_command_context.d.ts +14 -0
- package/esm/server/commands/browser_command_context.d.ts.map +1 -0
- package/esm/server/commands/browser_command_context.js +6 -0
- package/esm/server/commands/extend.d.ts +1 -3
- package/esm/server/commands/extend.d.ts.map +1 -1
- package/esm/server/commands/extend.js +0 -2
- package/esm/server/commands/has_image_snapshot.js +1 -1
- package/esm/server/commands/image_snapshot_next_index.js +1 -1
- package/esm/server/commands/match_image_snapshot.js +1 -1
- package/esm/server/commands/prepare_image_snapshot_comparison.d.ts +18 -0
- package/esm/server/commands/prepare_image_snapshot_comparison.d.ts.map +1 -1
- package/esm/server/commands/prepare_image_snapshot_comparison.js +8 -6
- package/esm/server/snapshot_path.js +2 -2
- package/esm/server/vis_context.d.ts +13 -12
- package/esm/server/vis_context.d.ts.map +1 -1
- package/esm/server/vis_context.logic.d.ts +16 -15
- package/esm/server/vis_context.logic.d.ts.map +1 -1
- package/esm/server/vis_context.logic.js +51 -42
- package/esm/server/vis_context.types.d.ts +16 -6
- package/esm/server/vis_context.types.d.ts.map +1 -1
- package/esm/testing/stubBrowserCommandContext.d.ts.map +1 -1
- package/esm/testing/stubBrowserCommandContext.js +7 -0
- package/package.json +2 -1
- package/src/client/image_snapshot_matcher.ts +6 -6
- package/src/client/snapshot_options.ts +1 -1
- package/src/commands.ts +1 -2
- package/src/config/types.ts +3 -3
- package/src/config/vis.ts +5 -3
- package/src/server/commands/browser_command_context.ts +9 -0
- package/src/server/commands/extend.ts +0 -3
- package/src/server/commands/has_image_snapshot.ts +1 -1
- package/src/server/commands/image_snapshot_next_index.ts +1 -1
- package/src/server/commands/match_image_snapshot.ts +1 -1
- package/src/server/commands/prepare_image_snapshot_comparison.ts +26 -7
- package/src/server/snapshot_path.ts +2 -2
- package/src/server/vis_context.logic.ts +94 -45
- package/src/server/vis_context.types.ts +18 -7
- package/src/testing/stubBrowserCommandContext.ts +7 -0
- package/esm/server/commands/write_image_snapshot.d.ts +0 -12
- package/esm/server/commands/write_image_snapshot.d.ts.map +0 -1
- package/esm/server/commands/write_image_snapshot.js +0 -9
- package/src/server/commands/write_image_snapshot.ts +0 -26
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export type VisState = {
|
|
2
|
-
projectPath: string
|
|
2
|
+
[projectPath: string]: Promise<VisProjectState>;
|
|
3
|
+
};
|
|
4
|
+
export type VisProjectState = {
|
|
5
|
+
projectRoot: string;
|
|
3
6
|
testTimeout: number;
|
|
4
7
|
hookTimeout: number;
|
|
5
8
|
snapshotRootDir: string;
|
|
@@ -27,14 +30,21 @@ export type PartialBrowserCommandContext = {
|
|
|
27
30
|
testTimeout: number;
|
|
28
31
|
hookTimeout: number;
|
|
29
32
|
};
|
|
33
|
+
vite: {
|
|
34
|
+
config: {
|
|
35
|
+
test?: {
|
|
36
|
+
name?: string | undefined;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
};
|
|
30
40
|
};
|
|
31
41
|
provider: {
|
|
32
42
|
name: string;
|
|
33
|
-
browserName
|
|
34
|
-
options
|
|
35
|
-
headless
|
|
36
|
-
screenshotFailures
|
|
37
|
-
screenshotDirectory
|
|
43
|
+
browserName?: string | undefined;
|
|
44
|
+
options?: {
|
|
45
|
+
headless?: boolean | undefined;
|
|
46
|
+
screenshotFailures?: boolean | undefined;
|
|
47
|
+
screenshotDirectory?: string | undefined;
|
|
38
48
|
};
|
|
39
49
|
};
|
|
40
50
|
testPath: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vis_context.types.d.ts","sourceRoot":"","sources":["../../src/server/vis_context.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG;IACtB,WAAW,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"vis_context.types.d.ts","sourceRoot":"","sources":["../../src/server/vis_context.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG;IACtB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;CAC/C,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC7B,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,MAAM,CAAA;IACvB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,iBAAiB,EAAE,MAAM,CAAA;IACzB,eAAe,EAAE,MAAM,CAAA;IACvB,gBAAgB,EAAE,MAAM,CAAA;IACxB,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAA;IACrC,MAAM,EAAE,MAAM,CACb,MAAM,EACN;QACC,WAAW,EAAE,MAAM,CAAA;QACnB,SAAS,EAAE,MAAM,CAAA;QACjB,OAAO,EAAE,MAAM,CAAA;QACf,KAAK,EAAE,MAAM,CACZ,MAAM,EACN;YACC,KAAK,EAAE,MAAM,CAAA;SACb,CACD,CAAA;KACD,CACD,CAAA;CACD,CAAA;AAED,MAAM,MAAM,4BAA4B,GAAG;IAC1C,OAAO,EAAE;QACR,MAAM,EAAE;YACP,IAAI,EAAE,MAAM,CAAA;YACZ,eAAe,EAAE;gBAChB,cAAc,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAA;aACtC,CAAA;YACD,WAAW,EAAE,MAAM,CAAA;YACnB,WAAW,EAAE,MAAM,CAAA;SACnB,CAAA;QACD,IAAI,EAAE;YACL,MAAM,EAAE;gBACP,IAAI,CAAC,EAAE;oBACN,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;iBACzB,CAAA;aACD,CAAA;SACD,CAAA;KACD,CAAA;IACD,QAAQ,EAAE;QACT,IAAI,EAAE,MAAM,CAAA;QACZ,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;QAChC,OAAO,CAAC,EAAE;YACT,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;YAC9B,kBAAkB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;YACxC,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;SACxC,CAAA;KACD,CAAA;IACD,QAAQ,EAAE,MAAM,CAAA;CAChB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stubBrowserCommandContext.d.ts","sourceRoot":"","sources":["../../src/testing/stubBrowserCommandContext.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACxD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAA;AAElF,eAAO,MAAM,yBAAyB,2GAAwC,CAAA;AAE9E,wBAAgB,sCAAsC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"stubBrowserCommandContext.d.ts","sourceRoot":"","sources":["../../src/testing/stubBrowserCommandContext.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACxD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAA;AAElF,eAAO,MAAM,yBAAyB,2GAAwC,CAAA;AAE9E,wBAAgB,sCAAsC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,2HAmB5G"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vitest-plugin-vis",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Vitest visual testing plugin",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"image-snapshot",
|
|
@@ -107,6 +107,7 @@
|
|
|
107
107
|
"build": "tsc",
|
|
108
108
|
"build:watch": "tsc -w",
|
|
109
109
|
"clean": "rimraf coverage esm *.tsbuildinfo vitest.*.timestamp*",
|
|
110
|
+
"clean:vis:local": "rimraf __vis__/local",
|
|
110
111
|
"cov": "cross-env COVERAGE=true vitest run --coverage",
|
|
111
112
|
"coverage": "cross-env COVERAGE=true vitest run --coverage",
|
|
112
113
|
"dev": "run-p build:watch w",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import type { BrowserCommands } from '@vitest/browser/context'
|
|
1
2
|
import dedent from 'dedent'
|
|
2
3
|
import { resolve } from 'pathe'
|
|
3
4
|
import type { ImageSnapshotNextIndexCommand } from '../commands.ts'
|
|
4
5
|
import type { PrepareImageSnapshotComparisonCommand } from '../server/commands/prepare_image_snapshot_comparison.ts'
|
|
5
|
-
import type { WriteImageSnapshotCommand } from '../server/commands/write_image_snapshot.ts'
|
|
6
6
|
import { isBase64String } from '../shared/base64.ts'
|
|
7
7
|
import { compareImage } from '../shared/compare_image.ts'
|
|
8
8
|
import type { ToMatchImageSnapshotOptions } from '../shared/types.ts'
|
|
@@ -15,7 +15,7 @@ import { server } from './vitest_browser_context_proxy.ts'
|
|
|
15
15
|
import type { CurrentTest } from './vitest_suite_proxy.ts'
|
|
16
16
|
|
|
17
17
|
export function imageSnapshotMatcher(
|
|
18
|
-
commands:
|
|
18
|
+
commands: BrowserCommands & PrepareImageSnapshotComparisonCommand & ImageSnapshotNextIndexCommand,
|
|
19
19
|
) {
|
|
20
20
|
return async function matchImageSnapshot(
|
|
21
21
|
test: CurrentTest & {},
|
|
@@ -65,11 +65,11 @@ export function imageSnapshotMatcher(
|
|
|
65
65
|
return
|
|
66
66
|
}
|
|
67
67
|
if (server.config.snapshotOptions.updateSnapshot === 'all' && !options?.expectToFail) {
|
|
68
|
-
await writeSnapshot(commands, info.baselinePath, resultImage)
|
|
68
|
+
await writeSnapshot(commands, resolve(info.projectRoot, info.baselinePath), resultImage)
|
|
69
69
|
return
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
await writeSnapshot(commands, info.diffPath, diffImage)
|
|
72
|
+
await writeSnapshot(commands, resolve(info.projectRoot, info.diffPath), diffImage)
|
|
73
73
|
|
|
74
74
|
throw new Error(
|
|
75
75
|
dedent`Snapshot \`${taskId}\` mismatched
|
|
@@ -103,9 +103,9 @@ export function parseImageSnapshotSubject(subject: any) {
|
|
|
103
103
|
)
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
async function writeSnapshot(commands:
|
|
106
|
+
async function writeSnapshot(commands: BrowserCommands, path: string, image: ImageData) {
|
|
107
107
|
const content = (await toDataURL(image)).split(',')[1]!
|
|
108
|
-
return commands.
|
|
108
|
+
return commands.writeFile(path, content, { encoding: 'base64' })
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
async function parseImageSnapshotOptions(
|
|
@@ -51,7 +51,7 @@ function parseArgs<M extends ComparisonMethod>(
|
|
|
51
51
|
args: [task: MetaTask, meta: SnapshotMeta<M> | boolean] | [meta: boolean | SnapshotMeta<M>],
|
|
52
52
|
): [MetaTask | undefined, SnapshotMeta<M>] {
|
|
53
53
|
return args.length === 1
|
|
54
|
-
? [ctx.getCurrentTest() ?? (ctx.getCurrentSuite()
|
|
54
|
+
? [ctx.getCurrentTest() ?? (ctx.getCurrentSuite()?.tasks?.[0] as any)?.file, parseMeta(args[0])]
|
|
55
55
|
: [args[0], parseMeta(args[1])]
|
|
56
56
|
}
|
|
57
57
|
|
package/src/commands.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export * from './server/commands/has_image_snapshot.ts'
|
|
2
2
|
export * from './server/commands/image_snapshot_next_index.ts'
|
|
3
3
|
export * from './server/commands/match_image_snapshot.ts'
|
|
4
|
-
export * from './server/commands/setup_vis_suite.ts'
|
|
5
4
|
export * from './server/commands/prepare_image_snapshot_comparison.ts'
|
|
6
|
-
export * from './server/commands/
|
|
5
|
+
export * from './server/commands/setup_vis_suite.ts'
|
package/src/config/types.ts
CHANGED
|
@@ -35,11 +35,11 @@ export type VisOptions<M extends ComparisonMethod = 'pixel'> = ImageSnapshotTime
|
|
|
35
35
|
| string
|
|
36
36
|
| ((context: {
|
|
37
37
|
ci: boolean
|
|
38
|
-
browserName
|
|
38
|
+
browserName?: string | undefined
|
|
39
39
|
providerName: string
|
|
40
40
|
platform: string
|
|
41
|
-
screenshotFailures
|
|
42
|
-
screenshotDirectory
|
|
41
|
+
screenshotFailures?: boolean | undefined
|
|
42
|
+
screenshotDirectory?: string | undefined
|
|
43
43
|
}) => string)
|
|
44
44
|
| undefined
|
|
45
45
|
/**
|
package/src/config/vis.ts
CHANGED
|
@@ -12,11 +12,13 @@ import type { VisOptions } from './types.ts'
|
|
|
12
12
|
* which enables the `auto` preset.
|
|
13
13
|
*/
|
|
14
14
|
export function vis<M extends ComparisonMethod = 'pixel'>(options: VisOptions<M> = { preset: 'auto' } as any) {
|
|
15
|
-
visContext.setOptions(options)
|
|
16
|
-
const preset = options?.preset
|
|
17
15
|
return {
|
|
18
16
|
name: NAME,
|
|
19
|
-
config() {
|
|
17
|
+
config(userConfig) {
|
|
18
|
+
const projectName = userConfig?.test?.name
|
|
19
|
+
|
|
20
|
+
visContext.setOptions(projectName, options)
|
|
21
|
+
const preset = options?.preset
|
|
20
22
|
return {
|
|
21
23
|
test: {
|
|
22
24
|
browser: {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BrowserCommandContext } from 'vitest/node'
|
|
2
|
+
|
|
3
|
+
export function getProjectName(context: { project: { vite: { config: { test?: { name?: string | undefined } } } } }) {
|
|
4
|
+
return context.project.vite.config.test?.name
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function getBrowserInstanceProjectName(context: BrowserCommandContext) {
|
|
8
|
+
return context.project.config
|
|
9
|
+
}
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
prepareImageSnapshotComparison,
|
|
7
7
|
} from './prepare_image_snapshot_comparison.ts'
|
|
8
8
|
import { type SetupVisSuiteCommand, setupVisSuite } from './setup_vis_suite.ts'
|
|
9
|
-
import { type WriteImageSnapshotCommand, writeImageSnapshot } from './write_image_snapshot.ts'
|
|
10
9
|
|
|
11
10
|
declare module '@vitest/browser/context' {
|
|
12
11
|
interface BrowserCommands
|
|
@@ -14,7 +13,6 @@ declare module '@vitest/browser/context' {
|
|
|
14
13
|
ImageSnapshotNextIndexCommand,
|
|
15
14
|
HasImageSnapshotCommand,
|
|
16
15
|
PrepareImageSnapshotComparisonCommand,
|
|
17
|
-
WriteImageSnapshotCommand,
|
|
18
16
|
MatchImageSnapshotCommand {}
|
|
19
17
|
}
|
|
20
18
|
|
|
@@ -24,5 +22,4 @@ export const commands = {
|
|
|
24
22
|
hasImageSnapshot,
|
|
25
23
|
matchImageSnapshot,
|
|
26
24
|
prepareImageSnapshotComparison,
|
|
27
|
-
writeImageSnapshot,
|
|
28
25
|
}
|
|
@@ -11,5 +11,5 @@ export const hasImageSnapshot: BrowserCommand<
|
|
|
11
11
|
> = async (context, taskId, snapshotId, isAutoSnapshot) => {
|
|
12
12
|
assertTestPathDefined(context, 'hasImageSnapshot')
|
|
13
13
|
|
|
14
|
-
return visContext.hasImageSnapshot(context
|
|
14
|
+
return visContext.hasImageSnapshot(context as any, taskId, snapshotId, isAutoSnapshot)
|
|
15
15
|
}
|
|
@@ -12,5 +12,5 @@ export interface ImageSnapshotNextIndexCommand {
|
|
|
12
12
|
export const imageSnapshotNextIndex: BrowserCommand<[taskId: string]> = async (context, taskId) => {
|
|
13
13
|
assertTestPathDefined(context, 'imageSnapshotNextIndex')
|
|
14
14
|
|
|
15
|
-
return visContext.getTaskCount(context
|
|
15
|
+
return visContext.getTaskCount(context, taskId)
|
|
16
16
|
}
|
|
@@ -43,7 +43,7 @@ export const matchImageSnapshot: BrowserCommand<
|
|
|
43
43
|
if (!options) options = {}
|
|
44
44
|
options.timeout = options.timeout ?? 30000
|
|
45
45
|
|
|
46
|
-
const info = visContext.getSnapshotInfo(context
|
|
46
|
+
const info = await visContext.getSnapshotInfo(context as any, taskId, isAutoSnapshot, options)
|
|
47
47
|
const baselineBuffer = await file.tryReadFile(info.baselinePath)
|
|
48
48
|
if (!baselineBuffer) {
|
|
49
49
|
if (isBase64String(subject)) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resolve } from 'pathe'
|
|
1
2
|
import type { BrowserCommand } from 'vitest/node'
|
|
2
3
|
import { isBase64String } from '../../shared/base64.ts'
|
|
3
4
|
import type {
|
|
@@ -13,11 +14,29 @@ import { assertTestPathDefined } from './_assertions.ts'
|
|
|
13
14
|
import type { MatchImageSnapshotOptions } from './match_image_snapshot.ts'
|
|
14
15
|
|
|
15
16
|
type ImageSnapshotComparisonInfo = {
|
|
17
|
+
/**
|
|
18
|
+
* Path to the project root.
|
|
19
|
+
*/
|
|
16
20
|
projectRoot: string
|
|
21
|
+
/**
|
|
22
|
+
* Path to the baseline image relative to the project root.
|
|
23
|
+
*/
|
|
17
24
|
baselinePath: string
|
|
25
|
+
/**
|
|
26
|
+
* Path to the result image relative to the project root.
|
|
27
|
+
*/
|
|
18
28
|
resultPath: string
|
|
29
|
+
/**
|
|
30
|
+
* Path to the diff image relative to the project root.
|
|
31
|
+
*/
|
|
19
32
|
diffPath: string
|
|
33
|
+
/**
|
|
34
|
+
* Base64 encoded baseline image.
|
|
35
|
+
*/
|
|
20
36
|
baseline: string
|
|
37
|
+
/**
|
|
38
|
+
* Base64 encoded result image.
|
|
39
|
+
*/
|
|
21
40
|
result: string
|
|
22
41
|
} & ImageSnapshotTimeoutOptions &
|
|
23
42
|
FailureThresholdOptions &
|
|
@@ -36,26 +55,26 @@ export const prepareImageSnapshotComparison: BrowserCommand<
|
|
|
36
55
|
[taskId: string, snapshotId: string, isAutoSnapshot: boolean, options?: MatchImageSnapshotOptions | undefined]
|
|
37
56
|
> = async (context, taskId, subject, isAutoSnapshot, options) => {
|
|
38
57
|
assertTestPathDefined(context, 'prepareImageSnapshotComparison')
|
|
39
|
-
|
|
40
58
|
// vitest:browser passes in `null` when not defined
|
|
41
59
|
if (!options) options = {}
|
|
42
60
|
options.timeout = options.timeout ?? 30000
|
|
43
61
|
|
|
44
|
-
const
|
|
45
|
-
const
|
|
62
|
+
const projectRoot = context.project.config.root
|
|
63
|
+
const info = await visContext.getSnapshotInfo(context as any, taskId, isAutoSnapshot, options)
|
|
64
|
+
const baselineBuffer = await file.tryReadFile(resolve(projectRoot, info.baselinePath))
|
|
46
65
|
if (!baselineBuffer) {
|
|
47
66
|
if (isBase64String(subject)) {
|
|
48
|
-
await writeSnapshot(info.baselinePath, subject)
|
|
67
|
+
await writeSnapshot(resolve(projectRoot, info.baselinePath), subject)
|
|
49
68
|
} else {
|
|
50
|
-
await takeSnapshotByBrowser(context, info.baselinePath, subject, options)
|
|
69
|
+
await takeSnapshotByBrowser(context, resolve(projectRoot, info.baselinePath), subject, options)
|
|
51
70
|
}
|
|
52
71
|
return
|
|
53
72
|
}
|
|
54
73
|
|
|
55
|
-
const resultBuffer = await takeSnapshot(context, info.resultPath, subject, options)
|
|
74
|
+
const resultBuffer = await takeSnapshot(context, resolve(projectRoot, info.resultPath), subject, options)
|
|
56
75
|
return {
|
|
57
76
|
...info,
|
|
58
|
-
projectRoot
|
|
77
|
+
projectRoot,
|
|
59
78
|
baseline: baselineBuffer.toString('base64'),
|
|
60
79
|
result: resultBuffer.toString('base64'),
|
|
61
80
|
}
|
|
@@ -13,8 +13,8 @@ export function resolveSnapshotRootDir(suite: PartialBrowserCommandContext, opti
|
|
|
13
13
|
browserName: suite.provider.browserName,
|
|
14
14
|
providerName: suite.provider.name,
|
|
15
15
|
platform: process.platform,
|
|
16
|
-
screenshotFailures: suite.provider.options
|
|
17
|
-
screenshotDirectory: suite.provider.options
|
|
16
|
+
screenshotFailures: suite.provider.options?.screenshotFailures,
|
|
17
|
+
screenshotDirectory: suite.provider.options?.screenshotDirectory,
|
|
18
18
|
})
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -1,29 +1,31 @@
|
|
|
1
|
-
import { join, relative } from 'pathe'
|
|
1
|
+
import { join, relative, resolve } from 'pathe'
|
|
2
2
|
import { pick } from 'type-plus'
|
|
3
3
|
import type { VisOptions } from '../config/types.ts'
|
|
4
4
|
import { BASELINE_DIR, DIFF_DIR, RESULT_DIR } from '../shared/constants.ts'
|
|
5
|
+
import { getProjectName } from './commands/browser_command_context.ts'
|
|
5
6
|
import { file } from './file.ts'
|
|
6
7
|
import { getSnapshotSubpath, resolveSnapshotRootDir } from './snapshot_path.ts'
|
|
7
8
|
import { ctx } from './vis_context.ctx.ts'
|
|
8
|
-
import type { PartialBrowserCommandContext, VisState } from './vis_context.types.ts'
|
|
9
|
+
import type { PartialBrowserCommandContext, VisProjectState, VisState } from './vis_context.types.ts'
|
|
9
10
|
|
|
10
11
|
export function createVisContext() {
|
|
11
|
-
let
|
|
12
|
-
let state: VisState
|
|
13
|
-
let globalStateReady: Promise<VisState>
|
|
12
|
+
let visOptionsRecord: Record<string, VisOptions<any>> = {}
|
|
13
|
+
let state: VisState = {}
|
|
14
14
|
|
|
15
15
|
const context = {
|
|
16
|
-
setOptions<M extends 'pixel' | 'ssim'>(options: VisOptions<M> = {} as any) {
|
|
17
|
-
|
|
16
|
+
setOptions<M extends 'pixel' | 'ssim'>(projectName: string | undefined, options: VisOptions<M> = {} as any) {
|
|
17
|
+
visOptionsRecord[projectName ?? '__default'] = options
|
|
18
18
|
},
|
|
19
|
-
__test__getOptions() {
|
|
20
|
-
return
|
|
19
|
+
__test__getOptions(projectName: string) {
|
|
20
|
+
return visOptionsRecord[projectName]
|
|
21
21
|
},
|
|
22
22
|
__test__reset() {
|
|
23
|
-
|
|
23
|
+
visOptionsRecord = {}
|
|
24
|
+
state = {}
|
|
24
25
|
},
|
|
25
|
-
__test__getState() {
|
|
26
|
-
|
|
26
|
+
__test__getState(context: PartialBrowserCommandContext) {
|
|
27
|
+
const projectRoot = getProjectRoot(context)
|
|
28
|
+
return state[projectRoot]!
|
|
27
29
|
},
|
|
28
30
|
/**
|
|
29
31
|
* Setup suite is called on each test file's beforeAll hook.
|
|
@@ -31,26 +33,33 @@ export function createVisContext() {
|
|
|
31
33
|
* It needs to make sure there is no race condition between the test files.
|
|
32
34
|
*/
|
|
33
35
|
async setupSuite(context: PartialBrowserCommandContext) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
await globalStateReady
|
|
36
|
+
const projectRoot = getProjectRoot(context)
|
|
37
|
+
|
|
38
|
+
if (!state[projectRoot]) {
|
|
39
|
+
state[projectRoot] = setupState(context, getVisOptions(visOptionsRecord, context) ?? {})
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
const
|
|
42
|
-
|
|
42
|
+
const projectState = await state[projectRoot]
|
|
43
|
+
|
|
44
|
+
const { suiteId, suite } = createSuite(projectState, context.testPath, visOptionsRecord)
|
|
45
|
+
projectState.suites[suiteId] = suite
|
|
46
|
+
|
|
43
47
|
await Promise.allSettled([ctx.rimraf(suite.diffDir), ctx.rimraf(suite.resultDir)])
|
|
44
|
-
return pick(
|
|
48
|
+
return pick(projectState, 'subjectDataTestId')
|
|
45
49
|
},
|
|
46
|
-
getSnapshotInfo(
|
|
47
|
-
|
|
50
|
+
async getSnapshotInfo(
|
|
51
|
+
browserContext: PartialBrowserCommandContext,
|
|
48
52
|
name: string,
|
|
49
53
|
isAutoSnapshot: boolean,
|
|
50
54
|
options?: { snapshotFileId?: string | undefined },
|
|
51
55
|
) {
|
|
52
|
-
const suiteInfo = context.getSuiteInfo(
|
|
53
|
-
const snapshotFilename = context.getSnapshotFilename(
|
|
56
|
+
const suiteInfo = await context.getSuiteInfo(browserContext, name)
|
|
57
|
+
const snapshotFilename = context.getSnapshotFilename(
|
|
58
|
+
browserContext,
|
|
59
|
+
suiteInfo,
|
|
60
|
+
options?.snapshotFileId,
|
|
61
|
+
isAutoSnapshot,
|
|
62
|
+
)
|
|
54
63
|
|
|
55
64
|
const { baselineDir, resultDir, diffDir, task } = suiteInfo
|
|
56
65
|
|
|
@@ -60,38 +69,62 @@ export function createVisContext() {
|
|
|
60
69
|
const diffPath = join(diffDir, snapshotFilename)
|
|
61
70
|
|
|
62
71
|
return {
|
|
63
|
-
...pick(
|
|
72
|
+
...pick(
|
|
73
|
+
getVisOptions(visOptionsRecord, browserContext),
|
|
74
|
+
'comparisonMethod',
|
|
75
|
+
'diffOptions',
|
|
76
|
+
'failureThreshold',
|
|
77
|
+
'failureThresholdType',
|
|
78
|
+
'timeout',
|
|
79
|
+
),
|
|
64
80
|
baselinePath,
|
|
65
81
|
resultPath,
|
|
66
82
|
diffPath,
|
|
67
83
|
}
|
|
68
84
|
},
|
|
69
|
-
getTaskCount(
|
|
70
|
-
return context.getSuiteInfo(
|
|
85
|
+
async getTaskCount(browserContext: PartialBrowserCommandContext, taskId: string) {
|
|
86
|
+
return (await context.getSuiteInfo(browserContext, taskId)).task.count
|
|
71
87
|
},
|
|
72
|
-
hasImageSnapshot(
|
|
73
|
-
|
|
74
|
-
|
|
88
|
+
async hasImageSnapshot(
|
|
89
|
+
browserContext: PartialBrowserCommandContext,
|
|
90
|
+
taskId: string,
|
|
91
|
+
snapshotFileId: string | undefined,
|
|
92
|
+
isAutoSnapshot: boolean,
|
|
93
|
+
) {
|
|
94
|
+
const info = await context.getSuiteInfo(browserContext, taskId)
|
|
95
|
+
|
|
96
|
+
return file.existFile(
|
|
97
|
+
resolve(
|
|
98
|
+
info.projectRoot,
|
|
99
|
+
info.baselineDir,
|
|
100
|
+
context.getSnapshotFilename(browserContext, info, snapshotFileId, isAutoSnapshot),
|
|
101
|
+
),
|
|
102
|
+
)
|
|
75
103
|
},
|
|
76
104
|
getSnapshotFilename(
|
|
105
|
+
browserContext: PartialBrowserCommandContext,
|
|
77
106
|
info: { taskId: string; task: { count: number } },
|
|
78
|
-
|
|
79
107
|
snapshotFileId: string | undefined,
|
|
80
108
|
isAutoSnapshot: boolean,
|
|
81
109
|
) {
|
|
82
110
|
if (snapshotFileId) return `${snapshotFileId}.png`
|
|
83
|
-
const customizeSnapshotId =
|
|
111
|
+
const customizeSnapshotId =
|
|
112
|
+
getVisOptions(visOptionsRecord, browserContext).customizeSnapshotId ?? (({ id, index }) => `${id}-${index}`)
|
|
84
113
|
return `${customizeSnapshotId({
|
|
85
114
|
id: info.taskId,
|
|
86
115
|
index: info.task.count,
|
|
87
116
|
isAutoSnapshot,
|
|
88
117
|
})}.png`
|
|
89
118
|
},
|
|
90
|
-
getSuiteInfo(
|
|
91
|
-
const
|
|
92
|
-
const
|
|
119
|
+
async getSuiteInfo(browserContext: PartialBrowserCommandContext, taskId: string) {
|
|
120
|
+
const projectRoot = getProjectRoot(browserContext)
|
|
121
|
+
const projectState = await state[projectRoot]!
|
|
122
|
+
|
|
123
|
+
const suiteId = getSuiteId(projectState, browserContext.testPath, visOptionsRecord)
|
|
124
|
+
const suite = projectState.suites[suiteId]!
|
|
93
125
|
const task = (suite.tasks[taskId] = suite.tasks[taskId] ?? { count: 1 })
|
|
94
126
|
return {
|
|
127
|
+
projectRoot,
|
|
95
128
|
suiteId,
|
|
96
129
|
taskId,
|
|
97
130
|
baselineDir: suite.baselineDir,
|
|
@@ -105,21 +138,21 @@ export function createVisContext() {
|
|
|
105
138
|
}
|
|
106
139
|
|
|
107
140
|
async function setupState(
|
|
108
|
-
|
|
141
|
+
browserContext: PartialBrowserCommandContext,
|
|
109
142
|
visOptions: Pick<VisOptions, 'snapshotRootDir' | 'platform' | 'subjectDataTestId'>,
|
|
110
143
|
) {
|
|
111
|
-
const snapshotRootDir = resolveSnapshotRootDir(
|
|
112
|
-
const
|
|
144
|
+
const snapshotRootDir = resolveSnapshotRootDir(browserContext, visOptions)
|
|
145
|
+
const projectRoot = getProjectRoot(browserContext)
|
|
113
146
|
|
|
114
147
|
const state = {
|
|
115
|
-
|
|
116
|
-
testTimeout:
|
|
117
|
-
hookTimeout:
|
|
148
|
+
projectRoot,
|
|
149
|
+
testTimeout: browserContext.project.config.testTimeout,
|
|
150
|
+
hookTimeout: browserContext.project.config.hookTimeout,
|
|
118
151
|
snapshotRootDir,
|
|
119
152
|
snapshotBaselineDir: join(snapshotRootDir, BASELINE_DIR),
|
|
120
153
|
snapshotResultDir: join(snapshotRootDir, RESULT_DIR),
|
|
121
154
|
snapshotDiffDir: join(snapshotRootDir, DIFF_DIR),
|
|
122
|
-
snapshotRootPath: join(
|
|
155
|
+
snapshotRootPath: join(projectRoot, snapshotRootDir),
|
|
123
156
|
subjectDataTestId: visOptions.subjectDataTestId,
|
|
124
157
|
suites: {},
|
|
125
158
|
}
|
|
@@ -127,7 +160,11 @@ async function setupState(
|
|
|
127
160
|
return state
|
|
128
161
|
}
|
|
129
162
|
|
|
130
|
-
export function createSuite(
|
|
163
|
+
export function createSuite(
|
|
164
|
+
state: VisProjectState,
|
|
165
|
+
testPath: string,
|
|
166
|
+
options: Pick<VisOptions, 'customizeSnapshotSubpath'>,
|
|
167
|
+
) {
|
|
131
168
|
const suiteId = getSuiteId(state, testPath, options)
|
|
132
169
|
return {
|
|
133
170
|
suiteId,
|
|
@@ -140,6 +177,18 @@ export function createSuite(state: VisState, testPath: string, options: Pick<Vis
|
|
|
140
177
|
}
|
|
141
178
|
}
|
|
142
179
|
|
|
143
|
-
export function getSuiteId(
|
|
144
|
-
|
|
180
|
+
export function getSuiteId(
|
|
181
|
+
state: VisProjectState,
|
|
182
|
+
testPath: string,
|
|
183
|
+
options: Pick<VisOptions, 'customizeSnapshotSubpath'>,
|
|
184
|
+
) {
|
|
185
|
+
return getSnapshotSubpath(relative(state.projectRoot, testPath), options)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function getVisOptions(visOptionsRecord: Record<string, VisOptions<any>>, context: PartialBrowserCommandContext) {
|
|
189
|
+
return visOptionsRecord[getProjectName(context) ?? '__default']!
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function getProjectRoot(context: PartialBrowserCommandContext) {
|
|
193
|
+
return context.project.config.root
|
|
145
194
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export type VisState = {
|
|
2
|
-
projectPath: string
|
|
3
|
-
|
|
2
|
+
[projectPath: string]: Promise<VisProjectState>
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export type VisProjectState = {
|
|
6
|
+
projectRoot: string
|
|
4
7
|
testTimeout: number
|
|
5
8
|
hookTimeout: number
|
|
6
9
|
snapshotRootDir: string
|
|
@@ -24,6 +27,7 @@ export type VisState = {
|
|
|
24
27
|
}
|
|
25
28
|
>
|
|
26
29
|
}
|
|
30
|
+
|
|
27
31
|
export type PartialBrowserCommandContext = {
|
|
28
32
|
project: {
|
|
29
33
|
config: {
|
|
@@ -34,14 +38,21 @@ export type PartialBrowserCommandContext = {
|
|
|
34
38
|
testTimeout: number
|
|
35
39
|
hookTimeout: number
|
|
36
40
|
}
|
|
41
|
+
vite: {
|
|
42
|
+
config: {
|
|
43
|
+
test?: {
|
|
44
|
+
name?: string | undefined
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
37
48
|
}
|
|
38
49
|
provider: {
|
|
39
50
|
name: string
|
|
40
|
-
browserName
|
|
41
|
-
options
|
|
42
|
-
headless
|
|
43
|
-
screenshotFailures
|
|
44
|
-
screenshotDirectory
|
|
51
|
+
browserName?: string | undefined
|
|
52
|
+
options?: {
|
|
53
|
+
headless?: boolean | undefined
|
|
54
|
+
screenshotFailures?: boolean | undefined
|
|
55
|
+
screenshotDirectory?: string | undefined
|
|
45
56
|
}
|
|
46
57
|
}
|
|
47
58
|
testPath: string
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { BrowserCommand } from 'vitest/node';
|
|
2
|
-
export interface WriteImageSnapshotCommand {
|
|
3
|
-
/**
|
|
4
|
-
* Writes the image snapshot to the file system.
|
|
5
|
-
* @param relativeFilePath The file path to write the image snapshot to.
|
|
6
|
-
* It is relative to the project root.
|
|
7
|
-
* @param imageBase64 The base64 encoded image.
|
|
8
|
-
*/
|
|
9
|
-
writeImageSnapshot(relativeFilePath: string, imageBase64: string): Promise<void>;
|
|
10
|
-
}
|
|
11
|
-
export declare const writeImageSnapshot: BrowserCommand<[relativeFilePath: string, imageBase64: string]>;
|
|
12
|
-
//# sourceMappingURL=write_image_snapshot.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"write_image_snapshot.d.ts","sourceRoot":"","sources":["../../../src/server/commands/write_image_snapshot.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAIjD,MAAM,WAAW,yBAAyB;IACzC;;;;;OAKG;IACH,kBAAkB,CAAC,gBAAgB,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAChF;AAED,eAAO,MAAM,kBAAkB,EAAE,cAAc,CAAC,CAAC,gBAAgB,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,CAS9F,CAAA"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { mkdirp } from 'mkdirp';
|
|
2
|
-
import { dirname, isAbsolute } from 'pathe';
|
|
3
|
-
import { file } from "../file.js";
|
|
4
|
-
import { assertIsRelativePath } from "./_assertions.js";
|
|
5
|
-
export const writeImageSnapshot = async (_, relativeFilePath, imageBase64) => {
|
|
6
|
-
assertIsRelativePath(relativeFilePath, 'relativeFilePath');
|
|
7
|
-
await mkdirp(dirname(relativeFilePath));
|
|
8
|
-
await file.writeFile(relativeFilePath, imageBase64, { encoding: 'base64' });
|
|
9
|
-
};
|