fix(screenshot): show diff between previous and actual
Reference: https://github.com/microsoft/playwright/issues/32341
This commit is contained in:
parent
bcf4ff1e47
commit
34549cfbb2
|
|
@ -662,7 +662,7 @@ export class Page extends SdkObject {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (areEqualScreenshots(actual, options.expected, previous)) {
|
if (areEqualScreenshots(actual, options.expected, undefined)) {
|
||||||
progress.log(`screenshot matched expectation`);
|
progress.log(`screenshot matched expectation`);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -423,7 +423,7 @@ export async function toHaveScreenshot(
|
||||||
// - regular matcher (i.e. not a `.not`)
|
// - regular matcher (i.e. not a `.not`)
|
||||||
// - perhaps an 'all' flag to update non-matching screenshots
|
// - perhaps an 'all' flag to update non-matching screenshots
|
||||||
expectScreenshotOptions.expected = await fs.promises.readFile(helper.expectedPath);
|
expectScreenshotOptions.expected = await fs.promises.readFile(helper.expectedPath);
|
||||||
const { actual, diff, errorMessage, log } = await page._expectScreenshot(expectScreenshotOptions);
|
const { actual, previous, diff, errorMessage, log } = await page._expectScreenshot(expectScreenshotOptions);
|
||||||
|
|
||||||
if (!errorMessage)
|
if (!errorMessage)
|
||||||
return helper.handleMatching();
|
return helper.handleMatching();
|
||||||
|
|
@ -436,7 +436,7 @@ export async function toHaveScreenshot(
|
||||||
return helper.createMatcherResult(helper.expectedPath + ' running with --update-snapshots, writing actual.', true);
|
return helper.createMatcherResult(helper.expectedPath + ' running with --update-snapshots, writing actual.', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return helper.handleDifferent(actual, expectScreenshotOptions.expected, undefined, diff, errorMessage, log);
|
return helper.handleDifferent(actual, expectScreenshotOptions.expected, previous, diff, errorMessage, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeFileSync(aPath: string, content: Buffer | string) {
|
function writeFileSync(aPath: string, content: Buffer | string) {
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ export const ImageDiffView: React.FC<{
|
||||||
const [showSxsDiff, setShowSxsDiff] = React.useState<boolean>(false);
|
const [showSxsDiff, setShowSxsDiff] = React.useState<boolean>(false);
|
||||||
|
|
||||||
const [expectedImage, setExpectedImage] = React.useState<HTMLImageElement | null>(null);
|
const [expectedImage, setExpectedImage] = React.useState<HTMLImageElement | null>(null);
|
||||||
|
const [expectedImageTitle, setExpectedImageTitle] = React.useState<string>('Expected');
|
||||||
const [actualImage, setActualImage] = React.useState<HTMLImageElement | null>(null);
|
const [actualImage, setActualImage] = React.useState<HTMLImageElement | null>(null);
|
||||||
const [diffImage, setDiffImage] = React.useState<HTMLImageElement | null>(null);
|
const [diffImage, setDiffImage] = React.useState<HTMLImageElement | null>(null);
|
||||||
const [measure, ref] = useMeasure<HTMLDivElement>();
|
const [measure, ref] = useMeasure<HTMLDivElement>();
|
||||||
|
|
@ -73,6 +74,7 @@ export const ImageDiffView: React.FC<{
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
setExpectedImage(await loadImage(diff.expected?.attachment.path));
|
setExpectedImage(await loadImage(diff.expected?.attachment.path));
|
||||||
|
setExpectedImageTitle(diff.expected?.title || 'Expected');
|
||||||
setActualImage(await loadImage(diff.actual?.attachment.path));
|
setActualImage(await loadImage(diff.actual?.attachment.path));
|
||||||
setDiffImage(await loadImage(diff.diff?.attachment.path));
|
setDiffImage(await loadImage(diff.diff?.attachment.path));
|
||||||
})();
|
})();
|
||||||
|
|
@ -98,23 +100,23 @@ export const ImageDiffView: React.FC<{
|
||||||
<div data-testid='test-result-image-mismatch-tabs' style={{ display: 'flex', margin: '10px 0 20px' }}>
|
<div data-testid='test-result-image-mismatch-tabs' style={{ display: 'flex', margin: '10px 0 20px' }}>
|
||||||
{diff.diff && <div style={{ ...modeStyle, fontWeight: mode === 'diff' ? 600 : 'initial' }} onClick={() => setMode('diff')}>Diff</div>}
|
{diff.diff && <div style={{ ...modeStyle, fontWeight: mode === 'diff' ? 600 : 'initial' }} onClick={() => setMode('diff')}>Diff</div>}
|
||||||
<div style={{ ...modeStyle, fontWeight: mode === 'actual' ? 600 : 'initial' }} onClick={() => setMode('actual')}>Actual</div>
|
<div style={{ ...modeStyle, fontWeight: mode === 'actual' ? 600 : 'initial' }} onClick={() => setMode('actual')}>Actual</div>
|
||||||
<div style={{ ...modeStyle, fontWeight: mode === 'expected' ? 600 : 'initial' }} onClick={() => setMode('expected')}>Expected</div>
|
<div style={{ ...modeStyle, fontWeight: mode === 'expected' ? 600 : 'initial' }} onClick={() => setMode('expected')}>{expectedImageTitle}</div>
|
||||||
<div style={{ ...modeStyle, fontWeight: mode === 'sxs' ? 600 : 'initial' }} onClick={() => setMode('sxs')}>Side by side</div>
|
<div style={{ ...modeStyle, fontWeight: mode === 'sxs' ? 600 : 'initial' }} onClick={() => setMode('sxs')}>Side by side</div>
|
||||||
<div style={{ ...modeStyle, fontWeight: mode === 'slider' ? 600 : 'initial' }} onClick={() => setMode('slider')}>Slider</div>
|
<div style={{ ...modeStyle, fontWeight: mode === 'slider' ? 600 : 'initial' }} onClick={() => setMode('slider')}>Slider</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: 'flex', justifyContent: 'center', flex: 'auto', minHeight: fitHeight + 60 }}>
|
<div style={{ display: 'flex', justifyContent: 'center', flex: 'auto', minHeight: fitHeight + 60 }}>
|
||||||
{diff.diff && mode === 'diff' && <ImageWithSize image={diffImage} alt='Diff' canvasWidth={fitWidth} canvasHeight={fitHeight} scale={scale}/>}
|
{diff.diff && mode === 'diff' && <ImageWithSize image={diffImage} alt='Diff' canvasWidth={fitWidth} canvasHeight={fitHeight} scale={scale}/>}
|
||||||
{diff.diff && mode === 'actual' && <ImageWithSize image={actualImage} alt='Actual' canvasWidth={fitWidth} canvasHeight={fitHeight} scale={scale}/>}
|
{diff.diff && mode === 'actual' && <ImageWithSize image={actualImage} alt='Actual' canvasWidth={fitWidth} canvasHeight={fitHeight} scale={scale}/>}
|
||||||
{diff.diff && mode === 'expected' && <ImageWithSize image={expectedImage} alt='Expected' canvasWidth={fitWidth} canvasHeight={fitHeight} scale={scale}/>}
|
{diff.diff && mode === 'expected' && <ImageWithSize image={expectedImage} alt={expectedImageTitle} canvasWidth={fitWidth} canvasHeight={fitHeight} scale={scale}/>}
|
||||||
{diff.diff && mode === 'slider' && <ImageDiffSlider expectedImage={expectedImage} actualImage={actualImage} canvasWidth={fitWidth} canvasHeight={fitHeight} scale={scale} />}
|
{diff.diff && mode === 'slider' && <ImageDiffSlider expectedImage={expectedImage} actualImage={actualImage} canvasWidth={fitWidth} canvasHeight={fitHeight} scale={scale} expectedTitle={expectedImageTitle} />}
|
||||||
{diff.diff && mode === 'sxs' && <div style={{ display: 'flex' }}>
|
{diff.diff && mode === 'sxs' && <div style={{ display: 'flex' }}>
|
||||||
<ImageWithSize image={expectedImage} title='Expected' canvasWidth={sxsScale * imageWidth} canvasHeight={sxsScale * imageHeight} scale={sxsScale} />
|
<ImageWithSize image={expectedImage} title={expectedImageTitle} canvasWidth={sxsScale * imageWidth} canvasHeight={sxsScale * imageHeight} scale={sxsScale} />
|
||||||
<ImageWithSize image={showSxsDiff ? diffImage : actualImage} title={showSxsDiff ? 'Diff' : 'Actual'} onClick={() => setShowSxsDiff(!showSxsDiff)} canvasWidth={sxsScale * imageWidth} canvasHeight={sxsScale * imageHeight} scale={sxsScale} />
|
<ImageWithSize image={showSxsDiff ? diffImage : actualImage} title={showSxsDiff ? 'Diff' : 'Actual'} onClick={() => setShowSxsDiff(!showSxsDiff)} canvasWidth={sxsScale * imageWidth} canvasHeight={sxsScale * imageHeight} scale={sxsScale} />
|
||||||
</div>}
|
</div>}
|
||||||
{!diff.diff && mode === 'actual' && <ImageWithSize image={actualImage} title='Actual' canvasWidth={fitWidth} canvasHeight={fitHeight} scale={scale}/>}
|
{!diff.diff && mode === 'actual' && <ImageWithSize image={actualImage} title='Actual' canvasWidth={fitWidth} canvasHeight={fitHeight} scale={scale}/>}
|
||||||
{!diff.diff && mode === 'expected' && <ImageWithSize image={expectedImage} title='Expected' canvasWidth={fitWidth} canvasHeight={fitHeight} scale={scale}/>}
|
{!diff.diff && mode === 'expected' && <ImageWithSize image={expectedImage} title={expectedImageTitle} canvasWidth={fitWidth} canvasHeight={fitHeight} scale={scale}/>}
|
||||||
{!diff.diff && mode === 'sxs' && <div style={{ display: 'flex' }}>
|
{!diff.diff && mode === 'sxs' && <div style={{ display: 'flex' }}>
|
||||||
<ImageWithSize image={expectedImage} title='Expected' canvasWidth={sxsScale * imageWidth} canvasHeight={sxsScale * imageHeight} scale={sxsScale} />
|
<ImageWithSize image={expectedImage} title={expectedImageTitle} canvasWidth={sxsScale * imageWidth} canvasHeight={sxsScale * imageHeight} scale={sxsScale} />
|
||||||
<ImageWithSize image={actualImage} title='Actual' canvasWidth={sxsScale * imageWidth} canvasHeight={sxsScale * imageHeight} scale={sxsScale} />
|
<ImageWithSize image={actualImage} title='Actual' canvasWidth={sxsScale * imageWidth} canvasHeight={sxsScale * imageHeight} scale={sxsScale} />
|
||||||
</div>}
|
</div>}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -133,7 +135,8 @@ export const ImageDiffSlider: React.FC<{
|
||||||
canvasWidth: number,
|
canvasWidth: number,
|
||||||
canvasHeight: number,
|
canvasHeight: number,
|
||||||
scale: number,
|
scale: number,
|
||||||
}> = ({ expectedImage, actualImage, canvasWidth, canvasHeight, scale }) => {
|
expectedTitle: string,
|
||||||
|
}> = ({ expectedImage, actualImage, canvasWidth, canvasHeight, scale, expectedTitle }) => {
|
||||||
const absoluteStyle: React.CSSProperties = {
|
const absoluteStyle: React.CSSProperties = {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: 0,
|
top: 0,
|
||||||
|
|
@ -161,7 +164,7 @@ export const ImageDiffSlider: React.FC<{
|
||||||
setOffsets={offsets => setSlider(offsets[0])}
|
setOffsets={offsets => setSlider(offsets[0])}
|
||||||
resizerColor={'#57606a80'}
|
resizerColor={'#57606a80'}
|
||||||
resizerWidth={6}></ResizeView>
|
resizerWidth={6}></ResizeView>
|
||||||
<img alt='Expected' style={{
|
<img alt={expectedTitle} style={{
|
||||||
width: expectedImage.naturalWidth * scale,
|
width: expectedImage.naturalWidth * scale,
|
||||||
height: expectedImage.naturalHeight * scale,
|
height: expectedImage.naturalHeight * scale,
|
||||||
}} draggable='false' src={expectedImage.src} />
|
}} draggable='false' src={expectedImage.src} />
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue