Skip to content

Commit b82b068

Browse files
feat: inline images support (#244)
Co-authored-by: Marcus R. Brown <marcus.r.brown@aexp.com>
1 parent 07765f5 commit b82b068

4 files changed

Lines changed: 118 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ See [the examples](./examples/README.md) for more detailed usage or read about a
118118
* `blur`: (default `0`) Applies Gaussian Blur on compared images, accepts radius in pixels as value. Useful when you have noise after scaling images per different resolutions on your target website, usually setting its value to 1-2 should be enough to solve that problem.
119119
* `runInProcess`: (default `false`) Runs the diff in process without spawning a child process.
120120
* `dumpDiffToConsole`: (default `false`) Will output base64 string of a diff image to console in case of failed tests (in addition to creating a diff image). This string can be copy-pasted to a browser address string to preview the diff for a failed test.
121+
* `dumpInlineDiffToConsole`: (default `false`) Will output the image to the terminal using iTerm's [Inline Images Protocol](https://iterm2.com/documentation-images.html). If the term is not compatible, it does the same thing as `dumpDiffToConsole`.
121122
* `allowSizeMismatch`: (default `false`) If set to true, the build will not fail when the screenshots to compare have different sizes.
122123

123124
```javascript

__tests__/__snapshots__/index.spec.js.snap

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,31 @@ exports[`toMatchImageSnapshot dumpDiffToConsole imgSrcString is not added to con
1212
See diff for details: path/to/result.png"
1313
`;
1414

15+
exports[`toMatchImageSnapshot dumpInlineDiffToConsole falls back to dumpDiffToConsole if the terminal is unsupported 2`] = `
16+
"Expected image to match or be a close match to snapshot but was 80% different from snapshot (600 differing pixels).
17+
See diff for details: path/to/result.png
18+
Or paste below image diff string to your browser\`s URL bar.
19+
pretendthisisanimagebase64string"
20+
`;
21+
22+
exports[`toMatchImageSnapshot dumpInlineDiffToConsole uses Inline Image Protocol in iTerm 2`] = `
23+
"Expected image to match or be a close match to snapshot but was 80% different from snapshot (600 differing pixels).
24+
See diff for details: path/to/result.png
25+
26+
]1337;File=name=cGF0aC90by9yZXN1bHQucG5n;inline=1;width=40:pretendthisisanimagebase64string
27+
28+
"
29+
`;
30+
31+
exports[`toMatchImageSnapshot dumpInlineDiffToConsole uses Inline Image Protocol when ENABLE_INLINE_DIFF is set 2`] = `
32+
"Expected image to match or be a close match to snapshot but was 80% different from snapshot (600 differing pixels).
33+
See diff for details: path/to/result.png
34+
35+
]1337;File=name=cGF0aC90by9yZXN1bHQucG5n;inline=1;width=40:pretendthisisanimagebase64string
36+
37+
"
38+
`;
39+
1540
exports[`toMatchImageSnapshot passes diffImageToSnapshot everything it needs to create a snapshot and compare if needed 1`] = `
1641
Object {
1742
"allowSizeMismatch": false,

__tests__/index.spec.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,86 @@ describe('toMatchImageSnapshot', () => {
675675
.toThrowErrorMatchingSnapshot();
676676
});
677677
});
678+
679+
describe('dumpInlineDiffToConsole', () => {
680+
const { TERM_PROGRAM } = process.env;
681+
682+
afterEach(() => { process.env.TERM_PROGRAM = TERM_PROGRAM; });
683+
684+
it('falls back to dumpDiffToConsole if the terminal is unsupported', () => {
685+
const mockDiffResult = {
686+
pass: false,
687+
diffOutputPath: 'path/to/result.png',
688+
diffRatio: 0.8,
689+
diffPixelCount: 600,
690+
imgSrcString: 'pretendthisisanimagebase64string',
691+
};
692+
setupMock(mockDiffResult);
693+
const { toMatchImageSnapshot } = require('../src/index');
694+
expect.extend({ toMatchImageSnapshot });
695+
696+
jest.doMock('chalk', () => ({
697+
constructor: ChalkMock,
698+
}));
699+
700+
process.env.TERM_PROGRAM = 'xterm';
701+
702+
expect(() => expect('pretendthisisanimagebuffer').toMatchImageSnapshot({ dumpInlineDiffToConsole: true }))
703+
.toThrowErrorMatchingSnapshot();
704+
});
705+
706+
it('uses Inline Image Protocol in iTerm', () => {
707+
const mockDiffResult = {
708+
pass: false,
709+
diffOutputPath: 'path/to/result.png',
710+
diffRatio: 0.8,
711+
diffPixelCount: 600,
712+
imgSrcString: 'pretendthisisanimagebase64string',
713+
imageDimensions: {
714+
receivedHeight: 100,
715+
receivedWidth: 200,
716+
},
717+
};
718+
setupMock(mockDiffResult);
719+
const { toMatchImageSnapshot } = require('../src/index');
720+
expect.extend({ toMatchImageSnapshot });
721+
722+
jest.doMock('chalk', () => ({
723+
constructor: ChalkMock,
724+
}));
725+
726+
process.env.TERM_PROGRAM = 'iTerm.app';
727+
728+
expect(() => expect('pretendthisisanimagebuffer').toMatchImageSnapshot({ dumpInlineDiffToConsole: true }))
729+
.toThrowErrorMatchingSnapshot();
730+
});
731+
732+
it('uses Inline Image Protocol when ENABLE_INLINE_DIFF is set', () => {
733+
const mockDiffResult = {
734+
pass: false,
735+
diffOutputPath: 'path/to/result.png',
736+
diffRatio: 0.8,
737+
diffPixelCount: 600,
738+
imgSrcString: 'pretendthisisanimagebase64string',
739+
imageDimensions: {
740+
receivedHeight: 100,
741+
receivedWidth: 200,
742+
},
743+
};
744+
setupMock(mockDiffResult);
745+
const { toMatchImageSnapshot } = require('../src/index');
746+
expect.extend({ toMatchImageSnapshot });
747+
748+
jest.doMock('chalk', () => ({
749+
constructor: ChalkMock,
750+
}));
751+
752+
process.env.ENABLE_INLINE_DIFF = true;
753+
754+
expect(() => expect('pretendthisisanimagebuffer').toMatchImageSnapshot({ dumpInlineDiffToConsole: true }))
755+
.toThrowErrorMatchingSnapshot();
756+
});
757+
});
678758
});
679759

680760
describe('updateSnapshotState', () => {

src/index.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ function checkResult({
3838
snapshotIdentifier,
3939
chalk,
4040
dumpDiffToConsole,
41+
dumpInlineDiffToConsole,
4142
allowSizeMismatch,
4243
}) {
4344
let pass = true;
@@ -75,7 +76,14 @@ function checkResult({
7576

7677
failure += `${chalk.bold.red('See diff for details:')} ${chalk.red(result.diffOutputPath)}`;
7778

78-
if (dumpDiffToConsole) {
79+
const supportedInlineTerms = [
80+
'iTerm.app',
81+
'WezTerm',
82+
];
83+
84+
if (dumpInlineDiffToConsole && (supportedInlineTerms.includes(process.env.TERM_PROGRAM) || 'ENABLE_INLINE_DIFF' in process.env)) {
85+
failure += `\n\n\t\x1b]1337;File=name=${Buffer.from(result.diffOutputPath).toString('base64')};inline=1;width=40:${result.imgSrcString.replace('data:image/png;base64,', '')}\x07\x1b\n\n`;
86+
} else if (dumpDiffToConsole || dumpInlineDiffToConsole) {
7987
failure += `\n${chalk.bold.red('Or paste below image diff string to your browser`s URL bar.')}\n ${result.imgSrcString}`;
8088
}
8189

@@ -136,6 +144,7 @@ function configureToMatchImageSnapshot({
136144
blur: commonBlur = 0,
137145
runInProcess: commonRunInProcess = false,
138146
dumpDiffToConsole: commonDumpDiffToConsole = false,
147+
dumpInlineDiffToConsole: commonDumpInlineDiffToConsole = false,
139148
allowSizeMismatch: commonAllowSizeMismatch = false,
140149
comparisonMethod: commonComparisonMethod = 'pixelmatch',
141150
} = {}) {
@@ -152,6 +161,7 @@ function configureToMatchImageSnapshot({
152161
blur = commonBlur,
153162
runInProcess = commonRunInProcess,
154163
dumpDiffToConsole = commonDumpDiffToConsole,
164+
dumpInlineDiffToConsole = commonDumpInlineDiffToConsole,
155165
allowSizeMismatch = commonAllowSizeMismatch,
156166
comparisonMethod = commonComparisonMethod,
157167
} = {}) {
@@ -218,6 +228,7 @@ function configureToMatchImageSnapshot({
218228
snapshotIdentifier,
219229
chalk,
220230
dumpDiffToConsole,
231+
dumpInlineDiffToConsole,
221232
allowSizeMismatch,
222233
});
223234
};

0 commit comments

Comments
 (0)