Backport 6.x tagcloud hashcode (#17642)
* Change hashing algo of tagcloud rotations (#17597) pulls in TimR's changes (#17594) to the hashing algorithm. This also replaces the reference screenshots to match the new rotations. * Revert screenshot comparison tests to old threshold parameters (#17626) Applies to Tagcloud. https://github.com/elastic/kibana/pull/17597 made them too strict, causing them to fail in CI.
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 9 KiB After Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 10 KiB |
|
@ -390,7 +390,7 @@ describe('tag cloud tests', function () {
|
|||
});
|
||||
|
||||
|
||||
it('should test', async function () {
|
||||
it('should render simple image', async function () {
|
||||
|
||||
tagCloud = new TagCloud(domNode);
|
||||
tagCloud.setData(baseTest.data);
|
||||
|
|
|
@ -65,6 +65,7 @@ describe('TagCloudVisualizationTest', function () {
|
|||
|
||||
it('simple draw', async function () {
|
||||
const tagcloudVisualization = new TagCloudVisualization(domNode, vis);
|
||||
|
||||
await tagcloudVisualization.render(dummyTableGroup, {
|
||||
resize: false,
|
||||
params: true,
|
||||
|
@ -72,7 +73,9 @@ describe('TagCloudVisualizationTest', function () {
|
|||
data: true,
|
||||
uiState: false
|
||||
});
|
||||
const mismatchedPixels = await imageComparator.compareDOMContents(domNode.innerHTML, 512, 512, basicdrawPng, THRESHOLD);
|
||||
|
||||
const svgNode = domNode.querySelector('svg');
|
||||
const mismatchedPixels = await imageComparator.compareDOMContents(svgNode.outerHTML, 512, 512, basicdrawPng, THRESHOLD);
|
||||
expect(mismatchedPixels).to.be.lessThan(PIXEL_DIFF);
|
||||
});
|
||||
|
||||
|
@ -97,14 +100,13 @@ describe('TagCloudVisualizationTest', function () {
|
|||
uiState: false
|
||||
});
|
||||
|
||||
|
||||
const mismatchedPixels = await imageComparator.compareDOMContents(domNode.innerHTML, 256, 368, afterresizePng, THRESHOLD);
|
||||
const svgNode = domNode.querySelector('svg');
|
||||
const mismatchedPixels = await imageComparator.compareDOMContents(svgNode.outerHTML, 256, 368, afterresizePng, THRESHOLD);
|
||||
expect(mismatchedPixels).to.be.lessThan(PIXEL_DIFF);
|
||||
});
|
||||
|
||||
it('with param change', async function () {
|
||||
|
||||
|
||||
const tagcloudVisualization = new TagCloudVisualization(domNode, vis);
|
||||
await tagcloudVisualization.render(dummyTableGroup, {
|
||||
resize: false,
|
||||
|
@ -126,8 +128,8 @@ describe('TagCloudVisualizationTest', function () {
|
|||
uiState: false
|
||||
});
|
||||
|
||||
|
||||
const mismatchedPixels = await imageComparator.compareDOMContents(domNode.innerHTML, 256, 368, afterparamChange, THRESHOLD);
|
||||
const svgNode = domNode.querySelector('svg');
|
||||
const mismatchedPixels = await imageComparator.compareDOMContents(svgNode.outerHTML, 256, 368, afterparamChange, THRESHOLD);
|
||||
expect(mismatchedPixels).to.be.lessThan(PIXEL_DIFF);
|
||||
});
|
||||
|
||||
|
|
|
@ -6,11 +6,10 @@ import { EventEmitter } from 'events';
|
|||
const ORIENTATIONS = {
|
||||
'single': () => 0,
|
||||
'right angled': (tag) => {
|
||||
return hashCode(tag.text) % 2 * 90;
|
||||
return hashWithinRange(tag.text, 2) * 90;
|
||||
},
|
||||
'multiple': (tag) => {
|
||||
const hashcode = Math.abs(hashCode(tag.text));
|
||||
return ((hashcode % 12) * 15) - 90;//fan out 12 * 15 degrees over top-right and bottom-right quadrant (=-90 deg offset)
|
||||
return ((hashWithinRange(tag.text, 12)) * 15) - 90;//fan out 12 * 15 degrees over top-right and bottom-right quadrant (=-90 deg offset)
|
||||
}
|
||||
};
|
||||
const D3_SCALING_FUNCTIONS = {
|
||||
|
@ -397,23 +396,13 @@ function getFill(tag) {
|
|||
return colorScale(tag.text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash a string to a number. Ensures there is no random element in positioning strings
|
||||
* Retrieved from http://stackoverflow.com/questions/26057572/string-to-unique-hash-in-javascript-jquery
|
||||
* @param string
|
||||
*/
|
||||
function hashCode(string) {
|
||||
string = JSON.stringify(string);
|
||||
function hashWithinRange(str, max) {
|
||||
str = JSON.stringify(str);
|
||||
let hash = 0;
|
||||
if (string.length === 0) {
|
||||
return hash;
|
||||
for (const ch of str) {
|
||||
hash = ((hash * 31) + ch.charCodeAt(0)) % max;
|
||||
}
|
||||
for (let i = 0; i < string.length; i++) {
|
||||
const char = string.charCodeAt(i);
|
||||
hash = ((hash << 5) - hash) + char;
|
||||
hash = hash & hash; // Convert to 32bit integer
|
||||
}
|
||||
return hash;
|
||||
return Math.abs(hash) % max;
|
||||
}
|
||||
|
||||
export default TagCloud;
|
||||
|
|
|
@ -52,13 +52,16 @@ export class ImageComparator {
|
|||
</svg>`;
|
||||
|
||||
const sourceImage = new Image();
|
||||
return new Promise((resolve) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
sourceImage.onload = async () => {
|
||||
sourceContext2d.drawImage(sourceImage, 0, 0);
|
||||
const mismatch = await this.compareImage(sourceCanvas, expectedImageSourcePng, threshold);
|
||||
document.body.removeChild(sourceCanvas);
|
||||
resolve(mismatch);
|
||||
};
|
||||
sourceImage.onerror = (e) => {
|
||||
reject(e.message);
|
||||
};
|
||||
sourceImage.src = 'data:image/svg+xml;base64,' + btoa(sourceData);
|
||||
});
|
||||
}
|
||||
|
@ -72,7 +75,7 @@ export class ImageComparator {
|
|||
*/
|
||||
async compareImage(actualCanvasFromUser, expectedImageSourcePng, threshold) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
window.setTimeout(() => {
|
||||
|
||||
|
@ -113,6 +116,11 @@ export class ImageComparator {
|
|||
|
||||
resolve(mismatchedPixels);
|
||||
};
|
||||
|
||||
expectedImage.onerror = (e) => {
|
||||
reject(e.message);
|
||||
};
|
||||
|
||||
expectedImage.src = expectedImageSourcePng;
|
||||
});
|
||||
});
|
||||
|
|