From c6335656d15afaec56767c99d4f02e126e992bda Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 15 Aug 2019 12:21:28 -0600 Subject: [PATCH] [Maps] custom color ramp (#41603) * [Maps] custom color ramp * round value down to find center color * do not update redux state with invalide color stops * rename EuiColorStop to ColorStop * remove untracked file * fix jest tests * review feedback * use steps instead of interpolate * add percy functional test to verify rendering of interpolate and step color expressions * add padding to color stop row so add/remove icons do not overlap color select --- .../maps/public/layers/styles/_index.scss | 1 + .../maps/public/layers/styles/color_utils.js | 1 - .../public/layers/styles/color_utils.test.js | 1 - .../heatmap_style_editor.test.js.snap | 6 - .../components/vector/color/_color_stops.scss | 29 +++ .../vector/color/color_ramp_select.js | 96 ++++++++-- .../components/vector/color/color_stops.js | 169 ++++++++++++++++++ .../vector/color/color_stops_utils.js | 66 +++++++ .../vector/color/dynamic_color_selection.js | 6 +- .../components/vector/legend/vector_icon.js | 11 ++ .../components/vector/style_option_shapes.js | 4 +- .../maps/public/layers/styles/vector_style.js | 56 ++++-- .../es_archives/maps/data/data.json | 12 +- .../es_archives/maps/data/mappings.json | 3 + .../es_archives/maps/kibana/data.json | 63 ++++++- .../tests/maps/vector_styling.js | 14 ++ 16 files changed, 497 insertions(+), 41 deletions(-) create mode 100644 x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/_color_stops.scss create mode 100644 x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_stops.js create mode 100644 x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_stops_utils.js diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/_index.scss b/x-pack/legacy/plugins/maps/public/layers/styles/_index.scss index f46932e44b1a..87c7bd1face6 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/_index.scss +++ b/x-pack/legacy/plugins/maps/public/layers/styles/_index.scss @@ -1,2 +1,3 @@ @import './components/color_gradient'; @import './components/static_dynamic_style_row'; +@import './components/vector/color/color_stops'; diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/color_utils.js b/x-pack/legacy/plugins/maps/public/layers/styles/color_utils.js index 9238564d4476..c82dd5393d63 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/color_utils.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/color_utils.js @@ -49,7 +49,6 @@ export function getColorRampStops(colorRampName, numberColors = GRADIENT_INTERVA export const COLOR_GRADIENTS = Object.keys(vislibColorMaps).map(colorRampName => ({ value: colorRampName, - text: colorRampName, inputDisplay: })); diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/color_utils.test.js b/x-pack/legacy/plugins/maps/public/layers/styles/color_utils.test.js index 91264c666a6c..f60c0e71a9b2 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/color_utils.test.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/color_utils.test.js @@ -17,7 +17,6 @@ describe('COLOR_GRADIENTS', () => { it('Should contain EuiSuperSelect options list of color ramps', () => { expect(COLOR_GRADIENTS.length).toBe(6); const colorGradientOption = COLOR_GRADIENTS[0]; - expect(colorGradientOption.text).toBe('Blues'); expect(colorGradientOption.value).toBe('Blues'); }); }); diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/__snapshots__/heatmap_style_editor.test.js.snap b/x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/__snapshots__/heatmap_style_editor.test.js.snap index a358fc7a31a3..fadfc62d11fd 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/__snapshots__/heatmap_style_editor.test.js.snap +++ b/x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/__snapshots__/heatmap_style_editor.test.js.snap @@ -35,42 +35,36 @@ exports[`HeatmapStyleEditor is rendered 1`] = ` "inputDisplay": , - "text": "Blues", "value": "Blues", }, Object { "inputDisplay": , - "text": "Greens", "value": "Greens", }, Object { "inputDisplay": , - "text": "Greys", "value": "Greys", }, Object { "inputDisplay": , - "text": "Reds", "value": "Reds", }, Object { "inputDisplay": , - "text": "Yellow to Red", "value": "Yellow to Red", }, Object { "inputDisplay": , - "text": "Green to Red", "value": "Green to Red", }, ] diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/_color_stops.scss b/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/_color_stops.scss new file mode 100644 index 000000000000..e7e7c0ef88ae --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/_color_stops.scss @@ -0,0 +1,29 @@ +.mapColorStop { + position: relative; + padding-right: $euiSizeXL + $euiSizeXS; + + &:hover, + &:focus { + .mapColorStop__icons { + visibility: visible; + opacity: 1; + display: block; + animation: mapColorStopBecomeVisible $euiAnimSpeedFast $euiAnimSlightResistance; + } + } +} + +.mapColorStop__icons { + flex-shrink: 0; + display: none; + position: absolute; + right: 0; + top: 50%; + margin-right: -$euiSizeS; + margin-top: -$euiSizeM; +} + +@keyframes mapColorStopBecomeVisible { + 0% { opacity: 0; } + 100% { opacity: 1; } +} diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_ramp_select.js b/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_ramp_select.js index 67d0e5e10f7c..119f9063df41 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_ramp_select.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_ramp_select.js @@ -4,29 +4,95 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import React, { Component, Fragment } from 'react'; import PropTypes from 'prop-types'; -import { EuiSuperSelect } from '@elastic/eui'; +import { EuiSuperSelect, EuiSpacer } from '@elastic/eui'; import { COLOR_GRADIENTS } from '../../../color_utils'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { ColorStops } from './color_stops'; -export function ColorRampSelect({ color, onChange }) { - const onColorRampChange = (selectedColorRampString) => { - onChange({ - color: selectedColorRampString +const CUSTOM_COLOR_RAMP = 'CUSTOM_COLOR_RAMP'; + +export class ColorRampSelect extends Component { + + state = {}; + + static getDerivedStateFromProps(nextProps, prevState) { + if (nextProps.customColorRamp !== prevState.prevPropsCustomColorRamp) { + return { + prevPropsCustomColorRamp: nextProps.customColorRamp, // reset tracker to latest value + customColorRamp: nextProps.customColorRamp, // reset customColorRamp to latest value + }; + } + + return null; + } + + _onColorRampSelect = (selectedValue) => { + const useCustomColorRamp = selectedValue === CUSTOM_COLOR_RAMP; + this.props.onChange({ + color: useCustomColorRamp ? null : selectedValue, + useCustomColorRamp, }); }; - return ( - - ); + + _onCustomColorRampChange = ({ colorStops, isInvalid }) => { + // Manage invalid custom color ramp in local state + if (isInvalid) { + this.setState({ customColorRamp: colorStops }); + return; + } + + this.props.onChange({ + customColorRamp: colorStops, + }); + }; + + render() { + let colorStopsInput; + if (this.props.useCustomColorRamp) { + colorStopsInput = ( + + + + + ); + } + + const colorRampOptions = [ + { + value: CUSTOM_COLOR_RAMP, + inputDisplay: ( + + ) + }, + ...COLOR_GRADIENTS + ]; + + return ( + + + {colorStopsInput} + + ); + } } ColorRampSelect.propTypes = { - color: PropTypes.string.isRequired, + color: PropTypes.string, onChange: PropTypes.func.isRequired, + useCustomColorRamp: PropTypes.bool, + customColorRamp: PropTypes.array, }; diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_stops.js b/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_stops.js new file mode 100644 index 000000000000..4ddbde11b02c --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_stops.js @@ -0,0 +1,169 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import _ from 'lodash'; +import React from 'react'; +import PropTypes from 'prop-types'; + +import { + EuiColorPicker, + EuiFormRow, + EuiFieldNumber, + EuiFlexGroup, + EuiFlexItem, + EuiButtonIcon +} from '@elastic/eui'; +import { + addRow, + removeRow, + isColorInvalid, + isStopInvalid, + isInvalid, +} from './color_stops_utils'; + +const DEFAULT_COLOR = '#FF0000'; + +export const ColorStops = ({ + colorStops = [{ stop: 0, color: DEFAULT_COLOR }], + onChange, +}) => { + function getStopInput(stop, index) { + const onStopChange = e => { + const newColorStops = _.cloneDeep(colorStops); + const sanitizedValue = parseFloat(e.target.value); + newColorStops[index].stop = isNaN(sanitizedValue) ? '' : sanitizedValue; + onChange({ + colorStops: newColorStops, + isInvalid: isInvalid(newColorStops), + }); + }; + + let error; + if (isStopInvalid(stop)) { + error = 'Stop must be a number'; + } else if (index !== 0 && colorStops[index - 1].stop >= stop) { + error = 'Stop must be greater than previous stop value'; + } + + return { + stopError: error, + stopInput: ( + + ), + }; + } + + function getColorInput(color, index) { + const onColorChange = color => { + const newColorStops = _.cloneDeep(colorStops); + newColorStops[index].color = color; + onChange({ + colorStops: newColorStops, + isInvalid: isInvalid(newColorStops), + }); + }; + + return { + colorError: isColorInvalid(color) + ? 'Color must provide a valid hex value' + : undefined, + colorInput: , + }; + } + + const rows = colorStops.map((colorStop, index) => { + const { stopError, stopInput } = getStopInput(colorStop.stop, index); + const { colorError, colorInput } = getColorInput(colorStop.color, index); + const errors = []; + if (stopError) { + errors.push(stopError); + } + if (colorError) { + errors.push(colorError); + } + + const onRemove = () => { + const newColorStops = removeRow(colorStops, index); + onChange({ + colorStops: newColorStops, + isInvalid: isInvalid(newColorStops), + }); + }; + + const onAdd = () => { + const newColorStops = addRow(colorStops, index); + + onChange({ + colorStops: newColorStops, + isInvalid: isInvalid(newColorStops), + }); + }; + + let deleteButton; + if (colorStops.length > 1) { + deleteButton = ( + + ); + } + + return ( + +
+ + {stopInput} + {colorInput} + +
+ {deleteButton} + +
+
+
+ ); + }); + + return
{rows}
; +}; + +ColorStops.propTypes = { + /** + * Array of { stop, color }. + * Stops are numbers in strictly ascending order. + * The range is from the given stop number (inclusive) to the next stop number (exclusive). + * Colors are color hex strings (3 or 6 character). + */ + colorStops: PropTypes.arrayOf( + PropTypes.shape({ + stopKey: PropTypes.number, + color: PropTypes.string, + }) + ), + /** + * Callback for when the color stops changes. Called with { colorStops, isInvalid } + */ + onChange: PropTypes.func.isRequired, +}; diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_stops_utils.js b/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_stops_utils.js new file mode 100644 index 000000000000..51aba2272905 --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_stops_utils.js @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { isValidHex } from '@elastic/eui'; + +export function removeRow(colorStops, index) { + if (colorStops.length === 1) { + return colorStops; + } + + return [...colorStops.slice(0, index), ...colorStops.slice(index + 1)]; +} + +export function addRow(colorStops, index) { + const currentStop = colorStops[index].stop; + let delta = 1; + if (index === colorStops.length - 1) { + // Adding row to end of list. + if (index !== 0) { + const prevStop = colorStops[index - 1].stop; + delta = currentStop - prevStop; + } + } else { + // Adding row in middle of list. + const nextStop = colorStops[index + 1].stop; + delta = (nextStop - currentStop) / 2; + } + + const newRow = { + stop: currentStop + delta, + color: '#FF0000', + }; + return [ + ...colorStops.slice(0, index + 1), + newRow, + ...colorStops.slice(index + 1), + ]; +} + +export function isColorInvalid(color) { + return !isValidHex(color) || color === ''; +} + +export function isStopInvalid(stop) { + return stop === '' || isNaN(stop); +} + +export function isInvalid(colorStops) { + return colorStops.some((colorStop, index) => { + // expect stops to be in ascending order + let isDescending = false; + if (index !== 0) { + const prevStop = colorStops[index - 1].stop; + isDescending = prevStop >= colorStop.stop; + } + + return ( + isColorInvalid(colorStop.color) || + isStopInvalid(colorStop.stop) || + isDescending + ); + }); +} diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/dynamic_color_selection.js b/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/dynamic_color_selection.js index ea8bcf08d8b7..28b75bd91c36 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/dynamic_color_selection.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/dynamic_color_selection.js @@ -17,8 +17,8 @@ export function DynamicColorSelection({ ordinalFields, onChange, styleOptions }) onChange({ ...styleOptions, field }); }; - const onColorChange = ({ color }) => { - onChange({ ...styleOptions, color }); + const onColorChange = colorOptions => { + onChange({ ...styleOptions, ...colorOptions }); }; return ( @@ -26,6 +26,8 @@ export function DynamicColorSelection({ ordinalFields, onChange, styleOptions }) { + return [...accumulatedStops, nextStop.stop, nextStop.color]; + }, []); + } + + return getColorRampStops(styleDescriptor.options.color); } _isSizeDynamicConfigComplete(styleDescriptor) { diff --git a/x-pack/test/functional/es_archives/maps/data/data.json b/x-pack/test/functional/es_archives/maps/data/data.json index dfcaaf3b8ca1..41f4dda80b5e 100644 --- a/x-pack/test/functional/es_archives/maps/data/data.json +++ b/x-pack/test/functional/es_archives/maps/data/data.json @@ -27,7 +27,8 @@ ], "type": "polygon" }, - "name": "alpha" + "name": "alpha", + "prop1": 1 } } } @@ -61,7 +62,8 @@ ], "type": "polygon" }, - "name": "bravo" + "name": "bravo", + "prop1": 2 } } } @@ -95,7 +97,8 @@ ], "type": "polygon" }, - "name": "charlie" + "name": "charlie", + "prop1": 3 } } } @@ -127,7 +130,8 @@ ], "type": "linestring" }, - "name": "tango" + "name": "tango", + "prop1": 4 } } } diff --git a/x-pack/test/functional/es_archives/maps/data/mappings.json b/x-pack/test/functional/es_archives/maps/data/mappings.json index 63b5fc3e8cf5..2c394b8e3b75 100644 --- a/x-pack/test/functional/es_archives/maps/data/mappings.json +++ b/x-pack/test/functional/es_archives/maps/data/mappings.json @@ -9,6 +9,9 @@ }, "name": { "type": "keyword" + }, + "prop1": { + "type": "byte" } } }, diff --git a/x-pack/test/functional/es_archives/maps/kibana/data.json b/x-pack/test/functional/es_archives/maps/kibana/data.json index 3b7115961f7e..8dc4f08f59b8 100644 --- a/x-pack/test/functional/es_archives/maps/kibana/data.json +++ b/x-pack/test/functional/es_archives/maps/kibana/data.json @@ -36,7 +36,7 @@ "index": ".kibana", "source": { "index-pattern": { - "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"geometry\",\"type\":\"geo_shape\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", + "fields" : "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"geometry\",\"type\":\"geo_shape\",\"esTypes\":[\"geo_shape\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"prop1\",\"type\":\"number\",\"esTypes\":[\"byte\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", "title": "geo_shapes*" }, "type": "index-pattern" @@ -556,6 +556,67 @@ } } +{ + "type": "doc", + "value": { + "id": "map:4cd3e220-bf64-11e9-bbcc-7db09a1519e9", + "index": ".kibana", + "source": { + "map": { + "title" : "join and dynamic coloring demo", + "description" : "", + "mapStateJSON" : "{\"zoom\":3.42,\"center\":{\"lon\":81.67747,\"lat\":1.80586},\"timeFilters\":{\"from\":\"now-17m\",\"to\":\"now\",\"mode\":\"quick\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":1000},\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filters\":[]}", + "layerListJSON" : "[{\"id\":\"n1t6f\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"62eca1fc-fe42-11e8-8eb2-f2801f1b9fd1\",\"type\":\"ES_SEARCH\",\"geoField\":\"geometry\",\"limit\":2048,\"filterByMapBounds\":false,\"showTooltip\":true,\"tooltipProperties\":[\"name\"],\"indexPatternRefName\":\"layer_0_source_index_pattern\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"max(prop1) group by meta_for_geo_shapes*.shape_name\",\"name\":\"__kbnjoin__max_of_prop1_groupby_meta_for_geo_shapes*.shape_name\",\"origin\":\"join\"},\"color\":null,\"useCustomColorRamp\":true,\"customColorRamp\":[{\"stop\":0,\"color\":\"#E6C220\"},{\"stop\":5,\"color\":\"#F98510\"},{\"stop\":11,\"color\":\"#DB1374\"}]}},\"lineColor\":{\"type\":\"DYNAMIC\",\"options\":{\"color\":\"Blues\",\"field\":{\"label\":\"prop1\",\"name\":\"prop1\",\"origin\":\"source\"},\"useCustomColorRamp\":false}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"iconOrientation\":{\"type\":\"STATIC\",\"options\":{\"orientation\":0}},\"symbol\":{\"options\":{\"symbolizeAs\":\"circle\",\"symbolId\":\"airfield\"}}}},\"type\":\"VECTOR\",\"joins\":[{\"leftField\":\"name\",\"right\":{\"id\":\"855ccb86-fe42-11e8-8eb2-f2801f1b9fd1\",\"indexPatternTitle\":\"meta_for_geo_shapes*\",\"term\":\"shape_name\",\"metrics\":[{\"type\":\"max\",\"field\":\"prop1\"}],\"indexPatternRefName\":\"layer_0_join_0_index_pattern\"}}]}]", + "uiStateJSON" : "{\"isLayerTOCOpen\":true,\"openTOCDetails\":[]}", + "bounds" : { + "type" : "Polygon", + "coordinates" : [ + [ + [ + 29.45263, + 23.75812 + ], + [ + 29.45263, + -20.41148 + ], + [ + 133.90231, + -20.41148 + ], + [ + 133.90231, + 23.75812 + ], + [ + 29.45263, + 23.75812 + ] + ] + ] + } + }, + "type": "map", + "references" : [ + { + "name" : "layer_0_source_index_pattern", + "type" : "index-pattern", + "id" : "561253e0-f731-11e8-8487-11b9dd924f96" + }, + { + "name" : "layer_0_join_0_index_pattern", + "type" : "index-pattern", + "id" : "e20b2a30-f735-11e8-8ce0-9723965e01e3" + } + ], + "migrationVersion" : { + "map" : "7.2.0" + }, + "updated_at" : "2019-08-15T13:56:15.793Z" + } + } +} + { "type": "doc", "value": { diff --git a/x-pack/test/visual_regression/tests/maps/vector_styling.js b/x-pack/test/visual_regression/tests/maps/vector_styling.js index 9ae4ac0c31bb..9b398fd56610 100644 --- a/x-pack/test/visual_regression/tests/maps/vector_styling.js +++ b/x-pack/test/visual_regression/tests/maps/vector_styling.js @@ -21,5 +21,19 @@ export default function ({ getPageObjects, getService }) { }); }); + + describe('dynamic coloring', () => { + before(async () => { + await PageObjects.maps.loadSavedMap('join and dynamic coloring demo'); + await PageObjects.maps.enterFullScreen(); + await PageObjects.maps.closeLegend(); + }); + + // eslint-disable-next-line max-len + it('should symbolize fill color with custom steps from join value and border color with dynamic color ramp from prop value', async () => { + await visualTesting.snapshot(); + }); + + }); }); }