diff --git a/.eslintignore b/.eslintignore index a7282e5a8..2c66a52c4 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1,5 @@ index_bundle.js config.js +diff.js +diverged.js +divergedWorker.js diff --git a/compare/output/diverged.js b/compare/output/diverged.js index 6f9ff2746..7e23d77be 100644 --- a/compare/output/diverged.js +++ b/compare/output/diverged.js @@ -12,12 +12,14 @@ if (typeof require !== 'undefined') { } } +const rowSpread = 1; + const spread = 50; // range of adjacent pixels to aggregate when calculating diff const IS_ADDED_WORD = '0_255_0_255'; const IS_REMOVED_WORD = '255_0_0_255'; const IS_ADDED_AND_REMOVED_WORD = '0_255_255_255'; const IS_SAME_WORD = ''; -const OPACITY = '30'; // 0-255 range +const OPACITY = '40'; // 0-255 range /** * Applies meyers-diff algorithm to imageData formatted arrays @@ -122,6 +124,7 @@ function reduceColumnDiffRaw(columnDiffs, h, w) { for (let depthIndex = 0; depthIndex < columnDiff.length; depthIndex++) { let segmentLength = 0; + // Categorize the current segment if (columnDiff[depthIndex].removed) { segmentLength = columnDiff[depthIndex].count; removedCounter += segmentLength; @@ -137,7 +140,6 @@ function reduceColumnDiffRaw(columnDiffs, h, w) { resultClass = IS_SAME_WORD; } - segmentLength = columnDiff[depthIndex].count; if (removedCounter > 0) { @@ -151,6 +153,7 @@ function reduceColumnDiffRaw(columnDiffs, h, w) { } } + // Limit segmentLength to total length of column if (!segmentLength) { continue; } else { @@ -220,26 +223,47 @@ function groupAdjacent(columns, spread, h, w) { return interpolated; } - function getCompositeColumnDepthValues(columns, range, depth) { - return range.reduce((acc, column) => { + function getCompositeColumnDepthValues(columns, sequence, depth) { + return sequence.reduce((acc, column) => { return acc.concat(columns[column][depth]); }, []) } - const interpolatedColumnsValues = new Array(); - let i = 0; - while (i < w) { - const adjacentBounds = getAdjacentArrayBounds(i, spread, w); - const interpolatedColumns = getInterpolatedSequence(...adjacentBounds); + function getCompositeRowIndexValues(groupedColumns, sequence, column) { + return sequence.reduce((acc, depth) => { + return acc.concat(groupedColumns[column][depth]); + }, []) + } + + const groupedColumns = new Array(); + let columnPointer = 0; + while (columnPointer < w) { + const adjacentColumnBounds = getAdjacentArrayBounds(columnPointer, spread, w); + const interpolatedColumns = getInterpolatedSequence(...adjacentColumnBounds); - const columnComposite = new Array(h); + const columnComposite = new Array(); for (var depth = 0; depth < h; depth++) { columnComposite[depth] = getCompositeColumnDepthValues(columns, interpolatedColumns, depth).join('|'); } - interpolatedColumnsValues.push(columnComposite); - i += spread; + groupedColumns.push(columnComposite); + columnPointer += spread; + } + + const groupedRows = new Array(); + if (rowSpread > 1) { + for (var index = 0; index < groupedColumns.length; index++) { + const rowComposite = new Array(); + let depthPointer = 0; + while (depthPointer < h) { + const adjacentRowBounds = getAdjacentArrayBounds(depthPointer, rowSpread, h); + const interpolatedRows = getInterpolatedSequence(...adjacentRowBounds); + rowComposite.push(getCompositeRowIndexValues(groupedColumns, interpolatedRows, index).join(',')); + depthPointer += rowSpread; + } + groupedRows[index] = rowComposite; + } } - return interpolatedColumnsValues; + return groupedRows.length ? groupedRows : groupedColumns ; } function ungroupAdjacent(grouped, spread, columnUnderlay, h, w) { @@ -251,16 +275,18 @@ function ungroupAdjacent(grouped, spread, columnUnderlay, h, w) { return Math.floor(index / spread); } + // expand columns const ungrouped = new Array(w); - for (let i = 0; i < w; i++) { - if (!ungrouped[i]) { - ungrouped[i] = new Array(h); + for (let index = 0; index < w; index++) { + if (!ungrouped[index]) { + ungrouped[index] = new Array(h); } - const groupedIndex = mapUngroupedColumnIndexToGroupedIndex(i, spread); - for (let j = 0; j < h; j++) { - const value = grouped[groupedIndex][j].split('|')[0]; - ungrouped[i][j] = value ? value : columnUnderlay[i][j].replace(/\d+$/, OPACITY); + const groupedIndexMap = mapUngroupedColumnIndexToGroupedIndex(index, spread); + for (let depth = 0; depth < h; depth++) { + const groupedDepthMap = rowSpread > 1 ? mapUngroupedColumnIndexToGroupedIndex(depth, rowSpread) : depth; + const value = grouped[groupedIndexMap][groupedDepthMap].split('|')[0]; + ungrouped[index][depth] = value ? value : columnUnderlay[index][depth].replace(/\d+$/, OPACITY); } } diff --git a/compare/output/divergedWorker.js b/compare/output/divergedWorker.js index b2fbe58ef..c41d85e54 100644 --- a/compare/output/divergedWorker.js +++ b/compare/output/divergedWorker.js @@ -3,4 +3,4 @@ importScripts('diverged.js'); self.addEventListener('message', function(e) { self.postMessage(diverged(...e.data.divergedInput)); self.close(); -}, false); \ No newline at end of file +}, false); diff --git a/compare/output/index_bundle.js b/compare/output/index_bundle.js index a40dc73bd..3b48b730c 100644 --- a/compare/output/index_bundle.js +++ b/compare/output/index_bundle.js @@ -33625,16 +33625,18 @@ var ImageScrubber = function (_React$Component) { // TODO: halp. i don't haz context. var that = this; - // TODO: concurrency? + function divergedWorker() { if (that.state.isLoading) { console.error('Diverged process is already running. Please hang on.'); return; } + if (divergedImage) { showScrubberDivergedImage(divergedImage); return; } + showScrubberDivergedImage(''); that.loadingDiverge(true); diff --git a/test/configs/responsiveDemo.json b/test/configs/responsiveDemo.json new file mode 100644 index 000000000..1e0cc6182 --- /dev/null +++ b/test/configs/responsiveDemo.json @@ -0,0 +1,54 @@ +{ + "id": "responsiveDemoPage", + "viewports": [ + { + "label": "phone", + "width": 320, + "height": 480 + }, + { + "label": "tablet", + "width": 1024, + "height": 768 + } + ], + "onBeforeScript": "puppet/onBefore.js", + "onReadyScript": "puppet/onReady.js", + "scenarios": [ + { + "label": "comparePage", + "cookiePath": "backstop_data/engine_scripts/cookies.json", + "url": "http://127.0.0.1:3000/responsiveDemoAlias/index.html", + "referenceUrl": "", + "readyEvent": "", + "readySelector": "", + "delay": 100, + "hideSelectors": [], + "removeSelectors": [], + "hoverSelector": "", + "clickSelector": "", + "postInteractionWait": 0, + "selectors": [], + "selectorExpansion": true, + "expect": 0, + "misMatchThreshold" : 0.1, + "requireSameDimensions": true + } + ], + "paths": { + "bitmaps_reference": "backstop_data/bitmaps_reference", + "bitmaps_test": "backstop_data/bitmaps_test", + "engine_scripts": "backstop_data/engine_scripts", + "html_report": "backstop_data/html_report", + "ci_report": "backstop_data/ci_report" + }, + "report": ["browser"], + "engine": "puppeteer", + "engineOptions": { + "args": ["--no-sandbox"] + }, + "asyncCaptureLimit": 5, + "asyncCompareLimit": 50, + "debug": false, + "debugWindow": false +} diff --git a/test/configs/responsiveDemoAlias b/test/configs/responsiveDemoAlias new file mode 120000 index 000000000..ff62b3000 --- /dev/null +++ b/test/configs/responsiveDemoAlias @@ -0,0 +1 @@ +../../examples/responsiveDemo \ No newline at end of file