Convert tag cloud tests to jest (#70066) (#70850)

* Convert tag cloud tests to jest

* Add mocks to test_utils and remove tests from legacy

* Revert changes made by accident

* Update tag_cloud_visualization.test.js

* Update tag_cloud.test.js

* Update jsdom_svg_mocks.ts

* Add restoring previous value to window.SVGElement.prototype.transform

* Get rid of some deep imports

* Reimport jsdom_svg_mocks functions from test_utils/public

* Get rid of ExprVis by inlining some of its params to vis object

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
Co-authored-by: Alexey Antonov <alexwizp@gmail.com>

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
Co-authored-by: Alexey Antonov <alexwizp@gmail.com>
This commit is contained in:
Diana Derevyankina 2020-07-07 10:11:08 +03:00 committed by GitHub
parent 8aa3c36762
commit b6aaf8a1a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 395 additions and 331 deletions

View file

@ -450,9 +450,10 @@
"is-path-inside": "^2.1.0",
"istanbul-instrumenter-loader": "3.0.1",
"jest": "^25.5.4",
"jest-environment-jsdom-thirteen": "^1.0.1",
"jest-canvas-mock": "^2.2.0",
"jest-circus": "^25.5.4",
"jest-cli": "^25.5.4",
"jest-environment-jsdom-thirteen": "^1.0.1",
"jest-raw-loader": "^1.0.1",
"jimp": "^0.9.6",
"json5": "^1.0.1",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

View file

@ -1,202 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { ImageComparator } from 'test_utils/image_comparator';
import basicdrawPng from './basicdraw.png';
import afterresizePng from './afterresize.png';
import afterparamChange from './afterparamchange.png';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { ExprVis } from '../../../../../../plugins/visualizations/public/expressions/vis';
// Replace with mock when converting to jest tests
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { seedColors } from '../../../../../../plugins/charts/public/services/colors/seed_colors';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { BaseVisType } from '../../../../../../plugins/visualizations/public/vis_types/base_vis_type';
// Will be replaced with new path when tests are moved
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { createTagCloudVisTypeDefinition } from '../../../../../../plugins/vis_type_tagcloud/public/tag_cloud_type';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { createTagCloudVisualization } from '../../../../../../plugins/vis_type_tagcloud/public/components/tag_cloud_visualization';
import { npStart } from 'ui/new_platform';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { setFormatService } from '../../../../../../plugins/vis_type_tagcloud/public/services';
const THRESHOLD = 0.65;
const PIXEL_DIFF = 64;
describe('TagCloudVisualizationTest', function () {
let domNode;
let vis;
let imageComparator;
const dummyTableGroup = {
columns: [
{
id: 'col-0',
title: 'geo.dest: Descending',
},
{
id: 'col-1',
title: 'Count',
},
],
rows: [
{ 'col-0': 'CN', 'col-1': 26 },
{ 'col-0': 'IN', 'col-1': 17 },
{ 'col-0': 'US', 'col-1': 6 },
{ 'col-0': 'DE', 'col-1': 4 },
{ 'col-0': 'BR', 'col-1': 3 },
],
};
const TagCloudVisualization = createTagCloudVisualization({
colors: {
seedColors,
},
});
before(() => setFormatService(npStart.plugins.data.fieldFormats));
beforeEach(ngMock.module('kibana'));
describe('TagCloudVisualization - basics', function () {
beforeEach(async function () {
const visType = new BaseVisType(createTagCloudVisTypeDefinition({ colors: seedColors }));
setupDOM('512px', '512px');
imageComparator = new ImageComparator();
vis = new ExprVis({
type: visType,
params: {
bucket: { accessor: 0, format: {} },
metric: { accessor: 0, format: {} },
},
data: {},
});
});
afterEach(function () {
teardownDOM();
imageComparator.destroy();
});
it('simple draw', async function () {
const tagcloudVisualization = new TagCloudVisualization(domNode, vis);
await tagcloudVisualization.render(dummyTableGroup, vis.params, {
resize: false,
params: true,
aggs: true,
data: true,
uiState: false,
});
const svgNode = domNode.querySelector('svg');
const mismatchedPixels = await imageComparator.compareDOMContents(
svgNode.outerHTML,
512,
512,
basicdrawPng,
THRESHOLD
);
expect(mismatchedPixels).to.be.lessThan(PIXEL_DIFF);
});
it('with resize', async function () {
const tagcloudVisualization = new TagCloudVisualization(domNode, vis);
await tagcloudVisualization.render(dummyTableGroup, vis.params, {
resize: false,
params: true,
aggs: true,
data: true,
uiState: false,
});
domNode.style.width = '256px';
domNode.style.height = '368px';
await tagcloudVisualization.render(dummyTableGroup, vis.params, {
resize: true,
params: false,
aggs: false,
data: false,
uiState: false,
});
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, vis.params, {
resize: false,
params: true,
aggs: true,
data: true,
uiState: false,
});
domNode.style.width = '256px';
domNode.style.height = '368px';
vis.params.orientation = 'right angled';
vis.params.minFontSize = 70;
await tagcloudVisualization.render(dummyTableGroup, vis.params, {
resize: true,
params: true,
aggs: false,
data: false,
uiState: false,
});
const svgNode = domNode.querySelector('svg');
const mismatchedPixels = await imageComparator.compareDOMContents(
svgNode.outerHTML,
256,
368,
afterparamChange,
THRESHOLD
);
expect(mismatchedPixels).to.be.lessThan(PIXEL_DIFF);
});
});
function setupDOM(width, height) {
domNode = document.createElement('div');
domNode.style.top = '0';
domNode.style.left = '0';
domNode.style.width = width;
domNode.style.height = height;
domNode.style.position = 'fixed';
domNode.style.border = '1px solid blue';
domNode.style['pointer-events'] = 'none';
document.body.appendChild(domNode);
}
function teardownDOM() {
domNode.innerHTML = '';
document.body.removeChild(domNode);
}
});

View file

@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`tag cloud tests tagcloudscreenshot should render simple image 1`] = `"<svg width=\\"512\\" height=\\"512\\"><g width=\\"512\\" height=\\"512\\"><text style=\\"font-size: 10px; font-style: normal; font-weight: normal; font-family: Open Sans, sans-serif; fill: #00a69b;\\" text-anchor=\\"middle\\" transform=\\"translate(1166, 1310)rotate(0)\\" data-test-subj=\\"foo\\">foo</text><text style=\\"font-size: 23px; font-style: normal; font-weight: normal; font-family: Open Sans, sans-serif; fill: #57c17b;\\" text-anchor=\\"middle\\" transform=\\"translate(1166, 1310)rotate(0)\\" data-test-subj=\\"bar\\">bar</text><text style=\\"font-size: 36px; font-style: normal; font-weight: normal; font-family: Open Sans, sans-serif; fill: #6f87d8;\\" text-anchor=\\"middle\\" transform=\\"translate(256, 256)rotate(0)\\" data-test-subj=\\"foobar\\">foobar</text></g></svg>"`;

View file

@ -0,0 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`TagCloudVisualizationTest TagCloudVisualization - basics simple draw 1`] = `"<svg width=\\"512\\" height=\\"512\\"><g width=\\"512\\" height=\\"512\\"><text style=\\"font-size: 0px; font-style: normal; font-weight: normal; font-family: Open Sans, sans-serif; fill: #00a69b;\\" text-anchor=\\"middle\\" transform=\\"translate(256, 256)rotate(0)\\" data-test-subj=\\"CN\\">CN</text><text style=\\"font-size: 0px; font-style: normal; font-weight: normal; font-family: Open Sans, sans-serif; fill: #57c17b;\\" text-anchor=\\"middle\\" transform=\\"translate(1166, 1310)rotate(0)\\" data-test-subj=\\"IN\\">IN</text><text style=\\"font-size: 0px; font-style: normal; font-weight: normal; font-family: Open Sans, sans-serif; fill: #6f87d8;\\" text-anchor=\\"middle\\" transform=\\"translate(1166, 1310)rotate(0)\\" data-test-subj=\\"US\\">US</text><text style=\\"font-size: 0px; font-style: normal; font-weight: normal; font-family: Open Sans, sans-serif; fill: #663db8;\\" text-anchor=\\"middle\\" transform=\\"translate(1166, 1310)rotate(0)\\" data-test-subj=\\"DE\\">DE</text><text style=\\"font-size: 0px; font-style: normal; font-weight: normal; font-family: Open Sans, sans-serif; fill: #bc52bc;\\" text-anchor=\\"middle\\" transform=\\"translate(1166, 1310)rotate(0)\\" data-test-subj=\\"BR\\">BR</text></g></svg>"`;
exports[`TagCloudVisualizationTest TagCloudVisualization - basics with param change 1`] = `"<svg width=\\"256\\" height=\\"386\\"><g width=\\"256\\" height=\\"386\\"><text style=\\"font-size: 0px; font-style: normal; font-weight: normal; font-family: Open Sans, sans-serif; fill: #00a69b;\\" text-anchor=\\"middle\\" transform=\\"\\" data-test-subj=\\"CN\\">CN</text><text style=\\"font-size: 0px; font-style: normal; font-weight: normal; font-family: Open Sans, sans-serif; fill: #57c17b;\\" text-anchor=\\"middle\\" transform=\\"\\" data-test-subj=\\"IN\\">IN</text><text style=\\"font-size: 0px; font-style: normal; font-weight: normal; font-family: Open Sans, sans-serif; fill: #6f87d8;\\" text-anchor=\\"middle\\" transform=\\"\\" data-test-subj=\\"US\\">US</text><text style=\\"font-size: 0px; font-style: normal; font-weight: normal; font-family: Open Sans, sans-serif; fill: #663db8;\\" text-anchor=\\"middle\\" transform=\\"\\" data-test-subj=\\"DE\\">DE</text><text style=\\"font-size: 0px; font-style: normal; font-weight: normal; font-family: Open Sans, sans-serif; fill: #bc52bc;\\" text-anchor=\\"middle\\" transform=\\"\\" data-test-subj=\\"BR\\">BR</text></g></svg>"`;
exports[`TagCloudVisualizationTest TagCloudVisualization - basics with resize 1`] = `"<svg width=\\"512\\" height=\\"512\\"><g width=\\"512\\" height=\\"512\\"><text style=\\"font-size: 0px; font-style: normal; font-weight: normal; font-family: Open Sans, sans-serif; fill: #00a69b;\\" text-anchor=\\"middle\\" transform=\\"translate(256, 256)rotate(0)\\" data-test-subj=\\"CN\\">CN</text><text style=\\"font-size: 0px; font-style: normal; font-weight: normal; font-family: Open Sans, sans-serif; fill: #57c17b;\\" text-anchor=\\"middle\\" transform=\\"translate(1166, 1310)rotate(0)\\" data-test-subj=\\"IN\\">IN</text><text style=\\"font-size: 0px; font-style: normal; font-weight: normal; font-family: Open Sans, sans-serif; fill: #6f87d8;\\" text-anchor=\\"middle\\" transform=\\"translate(1166, 1310)rotate(0)\\" data-test-subj=\\"US\\">US</text><text style=\\"font-size: 0px; font-style: normal; font-weight: normal; font-family: Open Sans, sans-serif; fill: #663db8;\\" text-anchor=\\"middle\\" transform=\\"translate(1166, 1310)rotate(0)\\" data-test-subj=\\"DE\\">DE</text><text style=\\"font-size: 0px; font-style: normal; font-weight: normal; font-family: Open Sans, sans-serif; fill: #bc52bc;\\" text-anchor=\\"middle\\" transform=\\"translate(1166, 1310)rotate(0)\\" data-test-subj=\\"BR\\">BR</text></g></svg>"`;

View file

@ -17,22 +17,27 @@
* under the License.
*/
import expect from '@kbn/expect';
import _ from 'lodash';
import d3 from 'd3';
import 'jest-canvas-mock';
import { fromNode, delay } from 'bluebird';
import { ImageComparator } from 'test_utils/image_comparator';
import simpleloadPng from './simpleload.png';
import { TagCloud } from './tag_cloud';
import { setHTMLElementOffset, setSVGElementGetBBox } from '../../../../test_utils/public';
// Replace with mock when converting to jest tests
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { seedColors } from '../../../../../../plugins/charts/public/services/colors/seed_colors';
// Will be replaced with new path when tests are moved
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { TagCloud } from '../../../../../../plugins/vis_type_tagcloud/public/components/tag_cloud';
describe('tag cloud tests', () => {
let SVGElementGetBBoxSpyInstance;
let HTMLElementOffsetMockInstance;
beforeEach(() => {
setupDOM();
});
afterEach(() => {
SVGElementGetBBoxSpyInstance.mockRestore();
HTMLElementOffsetMockInstance.mockRestore();
});
describe('tag cloud tests', function () {
const minValue = 1;
const maxValue = 9;
const midValue = (minValue + maxValue) / 2;
@ -100,16 +105,15 @@ describe('tag cloud tests', function () {
let domNode;
let tagCloud;
const colorScale = d3.scale.ordinal().range(seedColors);
const colorScale = d3.scale
.ordinal()
.range(['#00a69b', '#57c17b', '#6f87d8', '#663db8', '#bc52bc', '#9e3533', '#daa05d']);
function setupDOM() {
domNode = document.createElement('div');
domNode.style.top = '0';
domNode.style.left = '0';
domNode.style.width = '512px';
domNode.style.height = '512px';
domNode.style.position = 'fixed';
domNode.style['pointer-events'] = 'none';
SVGElementGetBBoxSpyInstance = setSVGElementGetBBox();
HTMLElementOffsetMockInstance = setHTMLElementOffset(512, 512);
document.body.appendChild(domNode);
}
@ -126,42 +130,39 @@ describe('tag cloud tests', function () {
sqrtScaleTest,
biggerFontTest,
trimDataTest,
].forEach(function (test) {
].forEach(function (currentTest) {
describe(`should position elements correctly for options: ${JSON.stringify(
test.options
)}`, function () {
beforeEach(async function () {
setupDOM();
currentTest.options
)}`, () => {
beforeEach(async () => {
tagCloud = new TagCloud(domNode, colorScale);
tagCloud.setData(test.data);
tagCloud.setOptions(test.options);
tagCloud.setData(currentTest.data);
tagCloud.setOptions(currentTest.options);
await fromNode((cb) => tagCloud.once('renderComplete', cb));
});
afterEach(teardownDOM);
it(
test(
'completeness should be ok',
handleExpectedBlip(function () {
expect(tagCloud.getStatus()).to.equal(TagCloud.STATUS.COMPLETE);
handleExpectedBlip(() => {
expect(tagCloud.getStatus()).toEqual(TagCloud.STATUS.COMPLETE);
})
);
it(
test(
'positions should be ok',
handleExpectedBlip(function () {
handleExpectedBlip(() => {
const textElements = domNode.querySelectorAll('text');
verifyTagProperties(test.expected, textElements, tagCloud);
verifyTagProperties(currentTest.expected, textElements, tagCloud);
})
);
});
});
[5, 100, 200, 300, 500].forEach(function (timeout) {
describe(`should only send single renderComplete event at the very end, using ${timeout}ms timeout`, function () {
beforeEach(async function () {
setupDOM();
[5, 100, 200, 300, 500].forEach((timeout) => {
describe(`should only send single renderComplete event at the very end, using ${timeout}ms timeout`, () => {
beforeEach(async () => {
//TagCloud takes at least 600ms to complete (due to d3 animation)
//renderComplete should only notify at the last one
tagCloud = new TagCloud(domNode, colorScale);
@ -176,16 +177,16 @@ describe('tag cloud tests', function () {
afterEach(teardownDOM);
it(
test(
'completeness should be ok',
handleExpectedBlip(function () {
expect(tagCloud.getStatus()).to.equal(TagCloud.STATUS.COMPLETE);
handleExpectedBlip(() => {
expect(tagCloud.getStatus()).toEqual(TagCloud.STATUS.COMPLETE);
})
);
it(
test(
'positions should be ok',
handleExpectedBlip(function () {
handleExpectedBlip(() => {
const textElements = domNode.querySelectorAll('text');
verifyTagProperties(logScaleTest.expected, textElements, tagCloud);
})
@ -193,9 +194,8 @@ describe('tag cloud tests', function () {
});
});
describe('should use the latest state before notifying (when modifying options multiple times)', function () {
beforeEach(async function () {
setupDOM();
describe('should use the latest state before notifying (when modifying options multiple times)', () => {
beforeEach(async () => {
tagCloud = new TagCloud(domNode, colorScale);
tagCloud.setData(baseTest.data);
tagCloud.setOptions(baseTest.options);
@ -205,53 +205,53 @@ describe('tag cloud tests', function () {
afterEach(teardownDOM);
it(
test(
'completeness should be ok',
handleExpectedBlip(function () {
expect(tagCloud.getStatus()).to.equal(TagCloud.STATUS.COMPLETE);
handleExpectedBlip(() => {
expect(tagCloud.getStatus()).toEqual(TagCloud.STATUS.COMPLETE);
})
);
it(
test(
'positions should be ok',
handleExpectedBlip(function () {
handleExpectedBlip(() => {
const textElements = domNode.querySelectorAll('text');
verifyTagProperties(logScaleTest.expected, textElements, tagCloud);
})
);
});
describe('should use the latest state before notifying (when modifying data multiple times)', function () {
beforeEach(async function () {
setupDOM();
describe('should use the latest state before notifying (when modifying data multiple times)', () => {
beforeEach(async () => {
tagCloud = new TagCloud(domNode, colorScale);
tagCloud.setData(baseTest.data);
tagCloud.setOptions(baseTest.options);
tagCloud.setData(trimDataTest.data);
await fromNode((cb) => tagCloud.once('renderComplete', cb));
});
afterEach(teardownDOM);
it(
test(
'completeness should be ok',
handleExpectedBlip(function () {
expect(tagCloud.getStatus()).to.equal(TagCloud.STATUS.COMPLETE);
handleExpectedBlip(() => {
expect(tagCloud.getStatus()).toEqual(TagCloud.STATUS.COMPLETE);
})
);
it(
test(
'positions should be ok',
handleExpectedBlip(function () {
handleExpectedBlip(() => {
const textElements = domNode.querySelectorAll('text');
verifyTagProperties(trimDataTest.expected, textElements, tagCloud);
})
);
});
describe('should not get multiple render-events', function () {
describe('should not get multiple render-events', () => {
let counter;
beforeEach(function () {
beforeEach(() => {
counter = 0;
setupDOM();
return new Promise((resolve, reject) => {
tagCloud = new TagCloud(domNode, colorScale);
tagCloud.setData(baseTest.data);
@ -281,31 +281,32 @@ describe('tag cloud tests', function () {
afterEach(teardownDOM);
it(
test(
'completeness should be ok',
handleExpectedBlip(function () {
expect(tagCloud.getStatus()).to.equal(TagCloud.STATUS.COMPLETE);
handleExpectedBlip(() => {
expect(tagCloud.getStatus()).toEqual(TagCloud.STATUS.COMPLETE);
})
);
it(
test(
'positions should be ok',
handleExpectedBlip(function () {
handleExpectedBlip(() => {
const textElements = domNode.querySelectorAll('text');
verifyTagProperties(logScaleTest.expected, textElements, tagCloud);
})
);
});
describe('should show correct data when state-updates are interleaved with resize event', function () {
beforeEach(async function () {
setupDOM();
describe('should show correct data when state-updates are interleaved with resize event', () => {
beforeEach(async () => {
tagCloud = new TagCloud(domNode, colorScale);
tagCloud.setData(logScaleTest.data);
tagCloud.setOptions(logScaleTest.options);
await delay(1000); //let layout run
domNode.style.width = '600px';
domNode.style.height = '600px';
SVGElementGetBBoxSpyInstance.mockRestore();
SVGElementGetBBoxSpyInstance = setSVGElementGetBBox(600, 600);
tagCloud.resize(); //triggers new layout
setTimeout(() => {
//change the options at the very end too
@ -317,26 +318,23 @@ describe('tag cloud tests', function () {
afterEach(teardownDOM);
it(
test(
'completeness should be ok',
handleExpectedBlip(function () {
expect(tagCloud.getStatus()).to.equal(TagCloud.STATUS.COMPLETE);
handleExpectedBlip(() => {
expect(tagCloud.getStatus()).toEqual(TagCloud.STATUS.COMPLETE);
})
);
it(
test(
'positions should be ok',
handleExpectedBlip(function () {
handleExpectedBlip(() => {
const textElements = domNode.querySelectorAll('text');
verifyTagProperties(baseTest.expected, textElements, tagCloud);
})
);
});
describe(`should not put elements in view when container is too small`, function () {
beforeEach(async function () {
setupDOM();
domNode.style.width = '1px';
domNode.style.height = '1px';
describe(`should not put elements in view when container is too small`, () => {
beforeEach(async () => {
tagCloud = new TagCloud(domNode, colorScale);
tagCloud.setData(baseTest.data);
tagCloud.setOptions(baseTest.options);
@ -345,10 +343,10 @@ describe('tag cloud tests', function () {
afterEach(teardownDOM);
it('completeness should not be ok', function () {
expect(tagCloud.getStatus()).to.equal(TagCloud.STATUS.INCOMPLETE);
test('completeness should not be ok', () => {
expect(tagCloud.getStatus()).toEqual(TagCloud.STATUS.INCOMPLETE);
});
it('positions should not be ok', function () {
test('positions should not be ok', () => {
const textElements = domNode.querySelectorAll('text');
for (let i = 0; i < textElements; i++) {
const bbox = textElements[i].getBoundingClientRect();
@ -357,96 +355,73 @@ describe('tag cloud tests', function () {
});
});
describe(`tags should fit after making container bigger`, function () {
beforeEach(async function () {
setupDOM();
domNode.style.width = '1px';
domNode.style.height = '1px';
describe(`tags should fit after making container bigger`, () => {
beforeEach(async () => {
tagCloud = new TagCloud(domNode, colorScale);
tagCloud.setData(baseTest.data);
tagCloud.setOptions(baseTest.options);
await fromNode((cb) => tagCloud.once('renderComplete', cb));
//make bigger
domNode.style.width = '512px';
domNode.style.height = '512px';
tagCloud._size = [600, 600];
tagCloud.resize();
await fromNode((cb) => tagCloud.once('renderComplete', cb));
});
afterEach(teardownDOM);
it(
test(
'completeness should be ok',
handleExpectedBlip(function () {
expect(tagCloud.getStatus()).to.equal(TagCloud.STATUS.COMPLETE);
handleExpectedBlip(() => {
expect(tagCloud.getStatus()).toEqual(TagCloud.STATUS.COMPLETE);
})
);
});
describe(`tags should no longer fit after making container smaller`, function () {
beforeEach(async function () {
setupDOM();
describe(`tags should no longer fit after making container smaller`, () => {
beforeEach(async () => {
tagCloud = new TagCloud(domNode, colorScale);
tagCloud.setData(baseTest.data);
tagCloud.setOptions(baseTest.options);
await fromNode((cb) => tagCloud.once('renderComplete', cb));
//make smaller
domNode.style.width = '1px';
domNode.style.height = '1px';
tagCloud._size = [];
tagCloud.resize();
await fromNode((cb) => tagCloud.once('renderComplete', cb));
});
afterEach(teardownDOM);
it('completeness should not be ok', function () {
expect(tagCloud.getStatus()).to.equal(TagCloud.STATUS.INCOMPLETE);
test('completeness should not be ok', () => {
expect(tagCloud.getStatus()).toEqual(TagCloud.STATUS.INCOMPLETE);
});
});
describe('tagcloudscreenshot', function () {
let imageComparator;
beforeEach(async function () {
setupDOM();
imageComparator = new ImageComparator();
});
describe('tagcloudscreenshot', () => {
afterEach(teardownDOM);
afterEach(() => {
imageComparator.destroy();
teardownDOM();
});
it('should render simple image', async function () {
test('should render simple image', async () => {
tagCloud = new TagCloud(domNode, colorScale);
tagCloud.setData(baseTest.data);
tagCloud.setOptions(baseTest.options);
await fromNode((cb) => tagCloud.once('renderComplete', cb));
const mismatchedPixels = await imageComparator.compareDOMContents(
domNode.innerHTML,
512,
512,
simpleloadPng,
0.5
);
expect(mismatchedPixels).to.be.lessThan(64);
expect(domNode.innerHTML).toMatchSnapshot();
});
});
function verifyTagProperties(expectedValues, actualElements, tagCloud) {
expect(actualElements.length).to.equal(expectedValues.length);
expect(actualElements.length).toEqual(expectedValues.length);
expectedValues.forEach((test, index) => {
try {
expect(actualElements[index].style.fontSize).to.equal(test.fontSize);
expect(actualElements[index].style.fontSize).toEqual(test.fontSize);
} catch (e) {
throw new Error('fontsize is not correct: ' + e.message);
}
try {
expect(actualElements[index].innerHTML).to.equal(test.text);
expect(actualElements[index].innerHTML).toEqual(test.text);
} catch (e) {
throw new Error('fontsize is not correct: ' + e.message);
}
@ -470,14 +445,14 @@ describe('tag cloud tests', function () {
debugInfo: ${JSON.stringify(tagCloud.getDebugInfo())}`;
try {
expect(bbox.top >= 0 && bbox.top <= domNode.offsetHeight).to.be(shouldBeInside);
expect(bbox.top >= 0 && bbox.top <= domNode.offsetHeight).toBe(shouldBeInside);
} catch (e) {
throw new Error(
'top boundary of tag should have been ' + (shouldBeInside ? 'inside' : 'outside') + message
);
}
try {
expect(bbox.bottom >= 0 && bbox.bottom <= domNode.offsetHeight).to.be(shouldBeInside);
expect(bbox.bottom >= 0 && bbox.bottom <= domNode.offsetHeight).toBe(shouldBeInside);
} catch (e) {
throw new Error(
'bottom boundary of tag should have been ' +
@ -486,14 +461,14 @@ describe('tag cloud tests', function () {
);
}
try {
expect(bbox.left >= 0 && bbox.left <= domNode.offsetWidth).to.be(shouldBeInside);
expect(bbox.left >= 0 && bbox.left <= domNode.offsetWidth).toBe(shouldBeInside);
} catch (e) {
throw new Error(
'left boundary of tag should have been ' + (shouldBeInside ? 'inside' : 'outside') + message
);
}
try {
expect(bbox.right >= 0 && bbox.right <= domNode.offsetWidth).to.be(shouldBeInside);
expect(bbox.right >= 0 && bbox.right <= domNode.offsetWidth).toBe(shouldBeInside);
} catch (e) {
throw new Error(
'right boundary of tag should have been ' +
@ -532,7 +507,7 @@ describe('tag cloud tests', function () {
}
function handleExpectedBlip(assertion) {
return function () {
return () => {
if (!shouldAssert()) {
return;
}

View file

@ -0,0 +1,176 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import 'jest-canvas-mock';
import { createTagCloudVisTypeDefinition } from '../tag_cloud_type';
import { createTagCloudVisualization } from './tag_cloud_visualization';
import { setFormatService } from '../services';
import { dataPluginMock } from '../../../data/public/mocks';
import { setHTMLElementOffset, setSVGElementGetBBox } from '../../../../test_utils/public';
const seedColors = ['#00a69b', '#57c17b', '#6f87d8', '#663db8', '#bc52bc', '#9e3533', '#daa05d'];
describe('TagCloudVisualizationTest', () => {
let domNode;
let vis;
let SVGElementGetBBoxSpyInstance;
let HTMLElementOffsetMockInstance;
const dummyTableGroup = {
columns: [
{
id: 'col-0',
title: 'geo.dest: Descending',
},
{
id: 'col-1',
title: 'Count',
},
],
rows: [
{ 'col-0': 'CN', 'col-1': 26 },
{ 'col-0': 'IN', 'col-1': 17 },
{ 'col-0': 'US', 'col-1': 6 },
{ 'col-0': 'DE', 'col-1': 4 },
{ 'col-0': 'BR', 'col-1': 3 },
],
};
const TagCloudVisualization = createTagCloudVisualization({
colors: {
seedColors,
},
});
const originTransformSVGElement = window.SVGElement.prototype.transform;
beforeAll(() => {
setFormatService(dataPluginMock.createStartContract().fieldFormats);
Object.defineProperties(window.SVGElement.prototype, {
transform: {
get: () => ({
baseVal: {
consolidate: () => {},
},
}),
configurable: true,
},
});
});
afterAll(() => {
SVGElementGetBBoxSpyInstance.mockRestore();
HTMLElementOffsetMockInstance.mockRestore();
window.SVGElement.prototype.transform = originTransformSVGElement;
});
describe('TagCloudVisualization - basics', () => {
beforeEach(async () => {
const visType = createTagCloudVisTypeDefinition({ colors: seedColors });
setupDOM(512, 512);
vis = {
type: visType,
params: {
bucket: { accessor: 0, format: {} },
metric: { accessor: 0, format: {} },
scale: 'linear',
orientation: 'single',
},
data: {},
};
});
test('simple draw', async () => {
const tagcloudVisualization = new TagCloudVisualization(domNode, vis);
await tagcloudVisualization.render(dummyTableGroup, vis.params, {
resize: false,
params: true,
aggs: true,
data: true,
uiState: false,
});
const svgNode = domNode.querySelector('svg');
expect(svgNode.outerHTML).toMatchSnapshot();
});
test('with resize', async () => {
const tagcloudVisualization = new TagCloudVisualization(domNode, vis);
await tagcloudVisualization.render(dummyTableGroup, vis.params, {
resize: false,
params: true,
aggs: true,
data: true,
uiState: false,
});
domNode.style.width = '256px';
domNode.style.height = '368px';
await tagcloudVisualization.render(dummyTableGroup, vis.params, {
resize: true,
params: false,
aggs: false,
data: false,
uiState: false,
});
const svgNode = domNode.querySelector('svg');
expect(svgNode.outerHTML).toMatchSnapshot();
});
test('with param change', async function () {
const tagcloudVisualization = new TagCloudVisualization(domNode, vis);
await tagcloudVisualization.render(dummyTableGroup, vis.params, {
resize: false,
params: true,
aggs: true,
data: true,
uiState: false,
});
SVGElementGetBBoxSpyInstance.mockRestore();
SVGElementGetBBoxSpyInstance = setSVGElementGetBBox(256, 368);
HTMLElementOffsetMockInstance.mockRestore();
HTMLElementOffsetMockInstance = setHTMLElementOffset(256, 386);
vis.params.orientation = 'right angled';
vis.params.minFontSize = 70;
await tagcloudVisualization.render(dummyTableGroup, vis.params, {
resize: true,
params: true,
aggs: false,
data: false,
uiState: false,
});
const svgNode = domNode.querySelector('svg');
expect(svgNode.outerHTML).toMatchSnapshot();
});
});
function setupDOM(width, height) {
domNode = document.createElement('div');
HTMLElementOffsetMockInstance = setHTMLElementOffset(width, height);
SVGElementGetBBoxSpyInstance = setSVGElementGetBBox(width, height);
}
});

View file

@ -24,3 +24,5 @@ export { WithStore } from './redux_helpers';
export { WithMemoryRouter, WithRoute, reactRouterMock } from './router_helpers';
export * from './utils';
export { setSVGElementGetBBox, setHTMLElementOffset } from './jsdom_svg_mocks';

View file

@ -0,0 +1,57 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
export const setSVGElementGetBBox = (
width: number,
height: number,
x: number = 0,
y: number = 0
) => {
const SVGElementPrototype = SVGElement.prototype as any;
const originalGetBBox = SVGElementPrototype.getBBox;
// getBBox is not in the SVGElement.prototype object by default, so we cannot use jest.spyOn for that case
SVGElementPrototype.getBBox = jest.fn(() => ({
x,
y,
width,
height,
}));
return {
mockRestore: () => {
SVGElementPrototype.getBBox = originalGetBBox;
},
};
};
export const setHTMLElementOffset = (width: number, height: number) => {
const offsetWidthSpy = jest.spyOn(window.HTMLElement.prototype, 'offsetWidth', 'get');
offsetWidthSpy.mockReturnValue(width);
const offsetHeightSpy = jest.spyOn(window.HTMLElement.prototype, 'offsetHeight', 'get');
offsetHeightSpy.mockReturnValue(height);
return {
mockRestore: () => {
offsetWidthSpy.mockRestore();
offsetHeightSpy.mockRestore();
},
};
};

View file

@ -0,0 +1,20 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
export { setSVGElementGetBBox, setHTMLElementOffset } from './helpers';

View file

@ -10433,6 +10433,11 @@ color-convert@^2.0.1:
dependencies:
color-name "~1.1.4"
color-convert@~0.5.0:
version "0.5.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-0.5.3.tgz#bdb6c69ce660fadffe0b0007cc447e1b9f7282bd"
integrity sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=
color-name@1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
@ -11509,6 +11514,11 @@ cssesc@^3.0.0:
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
cssfontparser@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/cssfontparser/-/cssfontparser-1.2.1.tgz#f4022fc8f9700c68029d542084afbaf425a3f3e3"
integrity sha1-9AIvyPlwDGgCnVQghK+69CWj8+M=
csso@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.2.tgz#e5f81ab3a56b8eefb7f0092ce7279329f454de3d"
@ -19000,6 +19010,14 @@ iterall@^1.2.2:
resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea"
integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==
jest-canvas-mock@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/jest-canvas-mock/-/jest-canvas-mock-2.2.0.tgz#45fbc58589c6ce9df50dc90bd8adce747cbdada7"
integrity sha512-DcJdchb7eWFZkt6pvyceWWnu3lsp5QWbUeXiKgEMhwB3sMm5qHM1GQhDajvJgBeiYpgKcojbzZ53d/nz6tXvJw==
dependencies:
cssfontparser "^1.2.1"
parse-color "^1.0.0"
jest-changed-files@^25.5.0:
version "25.5.0"
resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-25.5.0.tgz#141cc23567ceb3f534526f8614ba39421383634c"
@ -23809,6 +23827,13 @@ parse-bmfont-xml@^1.1.4:
xml-parse-from-string "^1.0.0"
xml2js "^0.4.5"
parse-color@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/parse-color/-/parse-color-1.0.0.tgz#7b748b95a83f03f16a94f535e52d7f3d94658619"
integrity sha1-e3SLlag/A/FqlPU15S1/PZRlhhk=
dependencies:
color-convert "~0.5.0"
parse-entities@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.1.1.tgz#8112d88471319f27abae4d64964b122fe4e1b890"