Add ignore colors toggle to resemble mode Change-Id: Iead2ef0468f5ec719fd58476d63ad83b5dcf8ecb
diff --git a/gr-image-diff-tool/gr-image-diff-tool.html b/gr-image-diff-tool/gr-image-diff-tool.html index 68e7f07..7f55f9a 100644 --- a/gr-image-diff-tool/gr-image-diff-tool.html +++ b/gr-image-diff-tool/gr-image-diff-tool.html
@@ -21,7 +21,10 @@ <template> <style> :host { + border-top: 1px solid var(--border-color, #ddd); display: block; + margin-top: .5em; + padding: 1em var(--default-horizontal-margin); } </style>
diff --git a/gr-resemble-diff-mode/gr-resemble-diff-mode.html b/gr-resemble-diff-mode/gr-resemble-diff-mode.html index 6ec3b16..a3ea88e 100644 --- a/gr-resemble-diff-mode/gr-resemble-diff-mode.html +++ b/gr-resemble-diff-mode/gr-resemble-diff-mode.html
@@ -21,13 +21,37 @@ :host { display: block; } + h2 { + display: none; + } #imageDiff { border: 1px solid var(--border-color, #ddd); - display: block; - margin: 0 auto; + } + :host([loading]) #imageDiff { + display: none; + } + :host([loading]) h2 { + display: inline; + padding: 1em 0; + } + .diffContainer { + display: flex; + justify-content: space-around; + width: 100%; } </style> - <img id="imageDiff"> + <div class="diffContainer"> + <h2>Loading...</h2> + <img id="imageDiff"> + </div> + <label> + <input + id="ignoreColorsToggle" + type="checkbox" + checked$="[[_ignoreColors]]" + on-tap="_handleIgnoreColorsToggle"> + Ignore colors + </label> </template> <script src="gr-resemble-diff-mode.js"></script> </dom-module> \ No newline at end of file
diff --git a/gr-resemble-diff-mode/gr-resemble-diff-mode.js b/gr-resemble-diff-mode/gr-resemble-diff-mode.js index 50661b8..1bce2ee 100644 --- a/gr-resemble-diff-mode/gr-resemble-diff-mode.js +++ b/gr-resemble-diff-mode/gr-resemble-diff-mode.js
@@ -20,36 +20,83 @@ properties: { baseImage: Object, revisionImage: Object, + _ignoreColors: { + type: Boolean, + value: false, + }, + loading: { + type: Boolean, + value: false, + reflectToAttribute: true, + }, }, observers: [ '_handleImageDiff(baseImage, revisionImage)', ], - _handleImageDiff(base, revision) { - if (base && revision) { - const baseEncoded = this.getDataUrl(base); - const revisionEncoded = this.getDataUrl(revision); - return this.compareImages(baseEncoded, revisionEncoded).then(src => { - this.$.imageDiff.setAttribute('src', src); - }); - } + attached() { + resemble.outputSettings({ + errorType: 'movement', + largeImageThreshold: 450, + }); }, - compareImages(baseEncoded, revisionEncoded) { - return new Promise((resolve, reject) => - resemble(baseEncoded).compareTo(revisionEncoded).onComplete(data => { - if (data.error) { - reject(); - } else { - resolve(data.getImageDataUrl()); - } - }) - ); + _handleImageDiff() { + this.reload(); }, - getDataUrl(image) { + _setImageDiffSrc(src) { + delete this.$.imageDiff.src; + this.$.imageDiff.src = src; + }, + + _getDataUrl(image) { return 'data:' + image['type'] + ';base64,' + image['body']; }, + + _maybeIgnoreColors(diffProcess, ignoreColors) { + if (ignoreColors) { + diffProcess.ignoreColors(); + } else { + diffProcess.ignoreNothing(); + } + return diffProcess; + }, + + _createDiffProcess(base, rev, ignoreColors) { + const process = resemble(base).compareTo(rev); + return this._maybeIgnoreColors(process, ignoreColors); + }, + + /** + * Reloads the diff. Resemble 1.2.1 seems to have an issue with successive + * reloads via the repaint() function, so this implementation creates a + * fresh diff each time it is called. + * + * @return {Promise} resolves if and when the reload succeeds. + */ + reload() { + this.loading = true; + if (this.baseImage && this.revisionImage) { + const base = this._getDataUrl(this.baseImage); + const rev = this._getDataUrl(this.revisionImage); + + return new Promise((resolve, reject) => { + this._createDiffProcess(base, rev, this._ignoreColors) + .onComplete(data => { + this._setImageDiffSrc(data.getImageDataUrl()); + this.loading = false; + resolve(); + }); + }); + } + this.loading = false; + }, + + _handleIgnoreColorsToggle() { + this._ignoreColors = !this._ignoreColors; + this.reload(); + }, }); -})(); \ No newline at end of file +})();
diff --git a/gr-resemble-diff-mode/gr-resemble-diff-mode_test.html b/gr-resemble-diff-mode/gr-resemble-diff-mode_test.html index 65460cc..c9ffb5d 100644 --- a/gr-resemble-diff-mode/gr-resemble-diff-mode_test.html +++ b/gr-resemble-diff-mode/gr-resemble-diff-mode_test.html
@@ -38,46 +38,60 @@ <script> suite('gr-resemble-diff-mode tests', () => { let element; + let sandbox; setup(() => { + sandbox = sinon.sandbox.create(); element = fixture('basicFixture'); }); + teardown(() => { sandbox.restore(); }) + test('test initialization', () => { assert.notEqual(element, null); assert.equal(element.baseImage, null); assert.equal(element.revisionImage, null); }); - test('test getDataUrl', () => { - element.baseImage = { - type: 'image/png', - body: 'SGVsbG8=', - }; - const desiredOutput = 'data:image/png;base64,SGVsbG8='; - assert.equal(element.getDataUrl(element.baseImage), desiredOutput); + test('_setImageDiffSrc', () => { + const img = element.$.imageDiff; + const src = 'data:image/png;base64,SGVsbG8='; + assert.notOk(img.getAttribute('src')); + element._setImageDiffSrc(src); + assert.equal(img.getAttribute('src'), src); }); - test('test resemble mode image diff', () => { - const img = element.$.imageDiff; - const expected_result = 'data:image/png;base64,SGVsbG8V29ybGQ=='; - assert.isFalse(img.hasAttribute('src')); - element.baseImage = { - type: 'image/png', - body: 'SGVsbG8=', + test('_maybeIgnoreColors', () => { + const dummyProcess = { + ignoreColors: sandbox.stub(), + ignoreNothing: sandbox.stub(), }; - assert.isFalse(img.hasAttribute('src')); - element.revisionImage = { - type: 'image/png', - body: 'V29ybGQ=', - }; + element._maybeIgnoreColors(dummyProcess, false); + assert.isFalse(dummyProcess.ignoreColors.called); + assert.isTrue(dummyProcess.ignoreNothing.called); + element._maybeIgnoreColors(dummyProcess, true); + assert.isTrue(dummyProcess.ignoreColors.called); + }); + + test('_handleIgnoreColorsToggle', () => { + sandbox.stub(element, 'reload'); + element._ignoreColors = false; + assert.isFalse(element.$.ignoreColorsToggle.checked); + MockInteractions.tap(element.$.ignoreColorsToggle); flushAsynchronousOperations(); - sinon.stub(element, 'compareImages') - .returns(Promise.resolve(expected_result)); - return element._handleImageDiff(element.baseImage, element.revisionImage) - .then(() => { - assert.equal(img.src, expected_result); - }); + + assert.isTrue(element._ignoreColors); + assert.isTrue(element.reload.called); + }); + + test('calls reload', () => { + sandbox.stub(element, 'reload'); + element.baseImage = {}; + assert.equal(element.reload.callCount, 0); + element.revisionImage = {}; + assert.equal(element.reload.callCount, 1); + MockInteractions.tap(element.$.ignoreColorsToggle); + assert.equal(element.reload.callCount, 2); }); }); </script> \ No newline at end of file