forked from elastic/kibana
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Maps] Safe-erase text-field (elastic#94873)
- Loading branch information
1 parent
c49b91a
commit 941a6db
Showing
4 changed files
with
185 additions
and
2 deletions.
There are no files selected for viewing
109 changes: 109 additions & 0 deletions
109
x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_text_property.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
jest.mock('../components/vector_style_editor', () => ({ | ||
VectorStyleEditor: () => { | ||
return <div>mockVectorStyleEditor</div>; | ||
}, | ||
})); | ||
|
||
import React from 'react'; | ||
|
||
// @ts-ignore | ||
import { DynamicTextProperty } from './dynamic_text_property'; | ||
import { RawValue, VECTOR_STYLES } from '../../../../../common/constants'; | ||
import { IField } from '../../../fields/field'; | ||
import { Map as MbMap } from 'mapbox-gl'; | ||
import { mockField, MockLayer, MockStyle } from './test_helpers/test_util'; | ||
import { IVectorLayer } from '../../../layers/vector_layer'; | ||
|
||
export class MockMbMap { | ||
_paintPropertyCalls: unknown[]; | ||
_lastTextFieldValue: unknown | undefined; | ||
|
||
constructor(lastTextFieldValue?: unknown) { | ||
this._paintPropertyCalls = []; | ||
this._lastTextFieldValue = lastTextFieldValue; | ||
} | ||
setLayoutProperty(layerId: string, propName: string, value: undefined | 'string') { | ||
if (propName !== 'text-field') { | ||
throw new Error('should only use to test `text-field`'); | ||
} | ||
this._lastTextFieldValue = value; | ||
this._paintPropertyCalls.push([layerId, value]); | ||
} | ||
|
||
getLayoutProperty(layername: string, propName: string): unknown | undefined { | ||
if (propName !== 'text-field') { | ||
throw new Error('should only use to test `text-field`'); | ||
} | ||
return this._lastTextFieldValue; | ||
} | ||
|
||
getPaintPropertyCalls(): unknown[] { | ||
return this._paintPropertyCalls; | ||
} | ||
} | ||
|
||
const makeProperty = (mockStyle: MockStyle, field: IField | null) => { | ||
return new DynamicTextProperty( | ||
{}, | ||
VECTOR_STYLES.LABEL_TEXT, | ||
field, | ||
(new MockLayer(mockStyle) as unknown) as IVectorLayer, | ||
() => { | ||
return (value: RawValue) => value + '_format'; | ||
} | ||
); | ||
}; | ||
|
||
describe('syncTextFieldWithMb', () => { | ||
describe('with field', () => { | ||
test('Should set', async () => { | ||
const dynamicTextProperty = makeProperty(new MockStyle({ min: 0, max: 100 }), mockField); | ||
const mockMbMap = (new MockMbMap() as unknown) as MbMap; | ||
|
||
dynamicTextProperty.syncTextFieldWithMb('foobar', mockMbMap); | ||
|
||
// @ts-expect-error | ||
expect(mockMbMap.getPaintPropertyCalls()).toEqual([ | ||
['foobar', ['coalesce', ['get', '__kbn__dynamic__foobar__labelText'], '']], | ||
]); | ||
}); | ||
}); | ||
|
||
describe('without field', () => { | ||
test('Should clear', async () => { | ||
const dynamicTextProperty = makeProperty(new MockStyle({ min: 0, max: 100 }), null); | ||
const mockMbMap = (new MockMbMap([ | ||
'foobar', | ||
['coalesce', ['get', '__kbn__dynamic__foobar__labelText'], ''], | ||
]) as unknown) as MbMap; | ||
|
||
dynamicTextProperty.syncTextFieldWithMb('foobar', mockMbMap); | ||
|
||
// @ts-expect-error | ||
expect(mockMbMap.getPaintPropertyCalls()).toEqual([['foobar', undefined]]); | ||
}); | ||
|
||
test('Should not clear when already cleared', async () => { | ||
// This verifies a weird edge-case in mapbox-gl, where setting the `text-field` layout-property to null causes tiles to be invalidated. | ||
// This triggers a refetch of the tile during panning and zooming | ||
// This affects vector-tile rendering in tiled_vector_layers with custom vector_styles | ||
// It does _not_ affect EMS, since that does not have a code-path where a `text-field` need to be resynced. | ||
// Do not remove this logic without verifying that mapbox-gl does not re-issue tile-requests for previously requested tiles | ||
|
||
const dynamicTextProperty = makeProperty(new MockStyle({ min: 0, max: 100 }), null); | ||
const mockMbMap = (new MockMbMap(undefined) as unknown) as MbMap; | ||
|
||
dynamicTextProperty.syncTextFieldWithMb('foobar', mockMbMap); | ||
|
||
// @ts-expect-error | ||
expect(mockMbMap.getPaintPropertyCalls()).toEqual([]); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
x-pack/plugins/maps/public/classes/styles/vector/properties/static_text_property.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import { StaticTextProperty } from './static_text_property'; | ||
import { VECTOR_STYLES } from '../../../../../common/constants'; | ||
import { Map as MbMap } from 'mapbox-gl'; | ||
|
||
export class MockMbMap { | ||
_paintPropertyCalls: unknown[]; | ||
_lastTextFieldValue: unknown | undefined; | ||
|
||
constructor(lastTextFieldValue?: unknown) { | ||
this._paintPropertyCalls = []; | ||
this._lastTextFieldValue = lastTextFieldValue; | ||
} | ||
setLayoutProperty(layerId: string, propName: string, value: undefined | 'string') { | ||
if (propName !== 'text-field') { | ||
throw new Error('should only use to test `text-field`'); | ||
} | ||
this._lastTextFieldValue = value; | ||
this._paintPropertyCalls.push([layerId, value]); | ||
} | ||
|
||
getLayoutProperty(layername: string, propName: string): unknown | undefined { | ||
if (propName !== 'text-field') { | ||
throw new Error('should only use to test `text-field`'); | ||
} | ||
return this._lastTextFieldValue; | ||
} | ||
|
||
getPaintPropertyCalls(): unknown[] { | ||
return this._paintPropertyCalls; | ||
} | ||
} | ||
|
||
const makeProperty = (value: string) => { | ||
return new StaticTextProperty({ value }, VECTOR_STYLES.LABEL_TEXT); | ||
}; | ||
|
||
describe('syncTextFieldWithMb', () => { | ||
test('Should set with value', async () => { | ||
const dynamicTextProperty = makeProperty('foo'); | ||
const mockMbMap = (new MockMbMap() as unknown) as MbMap; | ||
|
||
dynamicTextProperty.syncTextFieldWithMb('foobar', mockMbMap); | ||
|
||
// @ts-expect-error | ||
expect(mockMbMap.getPaintPropertyCalls()).toEqual([['foobar', 'foo']]); | ||
}); | ||
|
||
test('Should not clear when already cleared', async () => { | ||
// This verifies a weird edge-case in mapbox-gl, where setting the `text-field` layout-property to null causes tiles to be invalidated. | ||
// This triggers a refetch of the tile during panning and zooming | ||
// This affects vector-tile rendering in tiled_vector_layers with custom vector_styles | ||
// It does _not_ affect EMS, since that does not have a code-path where a `text-field` need to be resynced. | ||
// Do not remove this logic without verifying that mapbox-gl does not re-issue tile-requests for previously requested tiles | ||
|
||
const dynamicTextProperty = makeProperty(''); | ||
const mockMbMap = (new MockMbMap(undefined) as unknown) as MbMap; | ||
|
||
dynamicTextProperty.syncTextFieldWithMb('foobar', mockMbMap); | ||
|
||
// @ts-expect-error | ||
expect(mockMbMap.getPaintPropertyCalls()).toEqual([]); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters