-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add a way to save only reference screenshots (#27)
- without checking for already existing screenshots - without diffing against previous - overwrite always
- Loading branch information
Showing
4 changed files
with
190 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export { default as LocalCompare } from './methods/LocalCompare'; | ||
export { default as SaveScreenshot } from './methods/SaveScreenshot'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import fs from 'fs-promise'; | ||
import BaseCompare from './BaseCompare'; | ||
import debug from 'debug'; | ||
|
||
const log = debug('wdio-visual-regression-service:SaveScreenshot'); | ||
|
||
export default class SaveScreenshot extends BaseCompare { | ||
|
||
constructor(options = {}) { | ||
super(); | ||
this.getScreenshotFile = options.screenshotName; | ||
} | ||
|
||
async afterScreenshot(context, base64Screenshot) { | ||
const screenshotPath = this.getScreenshotFile(context); | ||
|
||
log(`create screenshot file at ${screenshotPath}`); | ||
await fs.outputFile(screenshotPath, base64Screenshot, 'base64'); | ||
return this.createResultReport(0, true, true); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
import path from 'path'; | ||
import { assert } from 'chai'; | ||
import { stub } from 'sinon'; | ||
import fs from 'fs-promise'; | ||
|
||
import BaseCompare from '../../../src/methods/BaseCompare'; | ||
import SaveScreenshot from '../../../src/methods/SaveScreenshot'; | ||
|
||
const dirTmp = path.join(process.cwd(), '.tmp'); | ||
const dirFixture = path.join(__dirname, '../../fixture/'); | ||
|
||
|
||
async function readAsBase64(file) { | ||
// read binary data | ||
const content = await fs.readFile(file); | ||
// convert binary data to base64 encoded string | ||
return new Buffer(content).toString('base64'); | ||
} | ||
|
||
|
||
function pause(ms) { | ||
return new Promise((resolve) => { | ||
setTimeout(resolve, ms); | ||
}); | ||
} | ||
|
||
describe('SaveScreenshot', function () { | ||
beforeEach(async function () { | ||
await fs.remove(dirTmp); | ||
}); | ||
|
||
after(async function () { | ||
await fs.remove(dirTmp); | ||
}); | ||
|
||
it('creates a instance of BaseCompare', async function () { | ||
const saveScreenshot = new SaveScreenshot(); | ||
assert.instanceOf(saveScreenshot, BaseCompare, 'SaveScreenshot should extend BaseCompare'); | ||
}); | ||
|
||
context('afterScreenshot', function () { | ||
beforeEach(async function() { | ||
this.referencFile = path.join(dirTmp, 'reference.png'); | ||
this.getReferenceFile = stub().returns(this.referencFile); | ||
|
||
this.saveScreenshot = new SaveScreenshot({ | ||
screenshotName: this.getReferenceFile, | ||
}); | ||
|
||
this.resultIdentical = { | ||
misMatchPercentage: 0, | ||
isWithinMisMatchTolerance: true, | ||
isSameDimensions: true, | ||
isExactSameImage: true | ||
}; | ||
}); | ||
|
||
it('creates a reference file for the first run', async function () { | ||
const context = {}; | ||
const base64Screenshot = await readAsBase64(path.join(dirFixture, 'image/100x100.png')); | ||
|
||
const results = await this.saveScreenshot.afterScreenshot(context, base64Screenshot); | ||
|
||
// check reference getter | ||
assert.strictEqual(this.getReferenceFile.callCount, 1, 'Reference getter should be called once'); | ||
assert.isTrue(this.getReferenceFile.calledWithExactly(context), 'Reference getter should receive context as arg'); | ||
|
||
// check image results | ||
assert.deepEqual(results, this.resultIdentical, 'Result should be reported'); | ||
|
||
// check if reference image was created | ||
const existsReference = await fs.exists(this.referencFile); | ||
assert.isTrue(existsReference, 'Reference screenshot should exist'); | ||
|
||
}); | ||
|
||
it('updates the reference image when changes are in tolerance', async function () { | ||
const context = {}; | ||
const base64Screenshot = await readAsBase64(path.join(dirFixture, 'image/100x100.png')); | ||
|
||
// 1st run -> create reference | ||
const resultFirst = await this.saveScreenshot.afterScreenshot(context, base64Screenshot); | ||
|
||
// check reference getter | ||
assert.strictEqual(this.getReferenceFile.callCount, 1, 'Reference getter should be called once'); | ||
assert.isTrue(this.getReferenceFile.calledWithExactly(context), 'Reference getter should receive context as arg'); | ||
|
||
// check image results | ||
assert.deepEqual(resultFirst, this.resultIdentical, 'Result should be reported'); | ||
|
||
// check if reference was created | ||
const existsReference = await fs.exists(this.referencFile); | ||
assert.isTrue(existsReference, 'Captured screenshot should exist'); | ||
|
||
// check last modified | ||
const statsFirst = await fs.stat(this.referencFile); | ||
assert.isAbove(statsFirst.mtime.getTime(), 0); | ||
|
||
// wait to get a different last modified time | ||
await pause(100); | ||
|
||
// 2nd run --> update reference image | ||
const resultSecond = await this.saveScreenshot.afterScreenshot(context, base64Screenshot); | ||
|
||
// check reference getter | ||
assert.strictEqual(this.getReferenceFile.callCount, 2, 'Reference getter should be called once'); | ||
assert.isTrue(this.getReferenceFile.alwaysCalledWithExactly(context), 'Reference getter should receive context as arg'); | ||
|
||
// check if image is reported as same | ||
assert.deepEqual(resultSecond, this.resultIdentical, 'Result should be reported'); | ||
|
||
// check if reference was updated | ||
const statsSecond = await fs.stat(this.referencFile); | ||
assert.isAbove(statsSecond.mtime.getTime(), statsFirst.mtime.getTime(), 'File should be modified'); | ||
}); | ||
|
||
it('updates the reference image when changes are not in tolerance', async function () { | ||
const context = {}; | ||
const base64ScreenshotReference = await readAsBase64(path.join(dirFixture, 'image/100x100.png')); | ||
const base64ScreenshotNew = await readAsBase64(path.join(dirFixture, 'image/100x100-rotated.png')); | ||
|
||
// 1st run -> create reference | ||
const resultFirst = await this.saveScreenshot.afterScreenshot(context, base64ScreenshotReference); | ||
|
||
// check reference getter | ||
assert.strictEqual(this.getReferenceFile.callCount, 1, 'Reference getter should be called once'); | ||
assert.isTrue(this.getReferenceFile.calledWithExactly(context), 'Reference getter should receive context as arg'); | ||
|
||
// check image results | ||
assert.deepEqual(resultFirst, this.resultIdentical, 'Result should be reported'); | ||
|
||
// check if reference was created | ||
const existsReference = await fs.exists(this.referencFile); | ||
assert.isTrue(existsReference, 'Captured screenshot should exist'); | ||
|
||
// check last modified | ||
const statsFirst = await fs.stat(this.referencFile); | ||
assert.isAbove(statsFirst.mtime.getTime(), 0); | ||
|
||
// wait to get a different last modified time | ||
await pause(100); | ||
|
||
// 2nd run --> update refernece with diff image | ||
const resultSecond = await this.saveScreenshot.afterScreenshot(context, base64ScreenshotNew); | ||
|
||
// check reference getter | ||
assert.strictEqual(this.getReferenceFile.callCount, 2, 'Reference getter should be called once'); | ||
assert.isTrue(this.getReferenceFile.alwaysCalledWithExactly(context), 'Reference getter should receive context as arg'); | ||
|
||
// check if image is reported as same (we don't care about the results here, as we are just overwriting all reference screenshots) | ||
assert.deepEqual(resultSecond, this.resultIdentical, 'Result should be reported'); | ||
|
||
// check if reference was updated | ||
const statsSecond = await fs.stat(this.referencFile); | ||
assert.isAbove(statsSecond.mtime.getTime(), statsFirst.mtime.getTime(), 'File should be modified'); | ||
}); | ||
|
||
}); | ||
}); |