diff --git a/modules/layers/src/text-layer/text-layer.js b/modules/layers/src/text-layer/text-layer.js index 94fa9dec7a4..0f1ecbda957 100644 --- a/modules/layers/src/text-layer/text-layer.js +++ b/modules/layers/src/text-layer/text-layer.js @@ -213,33 +213,46 @@ export default class TextLayer extends CompositeLayer { _getAccessor(accessor) { if (typeof accessor === 'function') { - return x => accessor(x.object); + const objectInfo = { + data: this.props.data, + target: [] + }; + return x => { + objectInfo.index = x.objectIndex; + return accessor(x.object, objectInfo); + }; } return accessor; } getAnchorXFromTextAnchor(getTextAnchor) { - return x => { - const textAnchor = - typeof getTextAnchor === 'function' ? getTextAnchor(x.object) : getTextAnchor; - if (!TEXT_ANCHOR.hasOwnProperty(textAnchor)) { - throw new Error(`Invalid text anchor parameter: ${textAnchor}`); - } - return TEXT_ANCHOR[textAnchor]; - }; + if (typeof getTextAnchor === 'function') { + const objectInfo = { + data: this.props.data, + target: [] + }; + return x => { + objectInfo.index = x.objectIndex; + const textAnchor = getTextAnchor(x.object, objectInfo); + return TEXT_ANCHOR[textAnchor] || 0; + }; + } + return () => TEXT_ANCHOR[getTextAnchor] || 0; } getAnchorYFromAlignmentBaseline(getAlignmentBaseline) { - return x => { - const alignmentBaseline = - typeof getAlignmentBaseline === 'function' - ? getAlignmentBaseline(x.object) - : getAlignmentBaseline; - if (!ALIGNMENT_BASELINE.hasOwnProperty(alignmentBaseline)) { - throw new Error(`Invalid alignment baseline parameter: ${alignmentBaseline}`); - } - return ALIGNMENT_BASELINE[alignmentBaseline]; - }; + if (typeof getAlignmentBaseline === 'function') { + const objectInfo = { + data: this.props.data, + target: [] + }; + return x => { + objectInfo.index = x.objectIndex; + const alignmentBaseline = getAlignmentBaseline(x.object, objectInfo); + return ALIGNMENT_BASELINE[alignmentBaseline] || 0; + }; + } + return () => ALIGNMENT_BASELINE[getAlignmentBaseline] || 0; } renderLayers() { @@ -272,7 +285,7 @@ export default class TextLayer extends CompositeLayer { iconAtlas, iconMapping, - getPosition: d => getPosition(d.object), + getPosition: this._getAccessor(getPosition), getColor: this._getAccessor(getColor), getSize: this._getAccessor(getSize), getAngle: this._getAccessor(getAngle), diff --git a/package.json b/package.json index f0e165043a7..dda0b481aea 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "babel-plugin-inline-webgl-constants": "^1.0.0", "babel-plugin-remove-glsl-comments": "^0.1.0", "babel-preset-minify": "^0.5.0", + "canvas": "^2.6.0", "coveralls": "^3.0.0", "eslint-config-prettier": "^4.1.0", "eslint-config-uber-jsx": "^3.3.3", diff --git a/test/modules/index.js b/test/modules/index.js index e55f4274bc3..ae6d613bcfb 100644 --- a/test/modules/index.js +++ b/test/modules/index.js @@ -29,12 +29,23 @@ import './json'; import './react'; import './jupyter-widget'; -// TODO - Tests currently only work in browser if (typeof document !== 'undefined') { + // Tests currently only work in browser require('./react/deckgl.spec'); + require('./json/json-render.spec'); require('./main/bundle'); require('./aggregation-layers/utils/gpu-grid-aggregator.spec'); require('./aggregation-layers/utils/grid-aggregation-utils.spec'); require('./core/lib/pick-layers.spec'); +} else if (typeof global !== 'undefined') { + // Running in Node + const {JSDOM} = require('jsdom'); + const dom = new JSDOM(``); + // These globals are required by @jupyter-widgets/base + /* global global */ + global.window = dom.window; + global.navigator = dom.window.navigator; + global.document = dom.window.document; + global.Element = dom.window.Element; } diff --git a/test/modules/json/json-converter.spec.js b/test/modules/json/json-converter.spec.js index 3c17471dd2f..b97ba09f162 100644 --- a/test/modules/json/json-converter.spec.js +++ b/test/modules/json/json-converter.spec.js @@ -1,11 +1,10 @@ import test from 'tape-catch'; -import {Deck} from '@deck.gl/core'; import {_JSONConverter as JSONConverter} from '@deck.gl/json'; import {COORDINATE_SYSTEM} from '@deck.gl/core'; import GL from '@luma.gl/constants'; -const configuration = { +export const configuration = { // a map of all layers that should be exposes as JSONLayers layers: Object.assign({}, require('@deck.gl/layers')), // Any non-standard views @@ -18,7 +17,7 @@ const configuration = { } }; -const JSON_DATA = { +export const JSON_DATA = { initialViewState: { longitude: -122.45, latitude: 37.8, @@ -57,30 +56,3 @@ test('JSONConverter#convert', t => { t.ok(deckProps, 'JSONConverter converted correctly'); t.end(); }); - -test('JSONConverter#render', t => { - if (typeof document === 'undefined') { - t.comment('test only available in browser'); - t.end(); - return; - } - - const jsonConverter = new JSONConverter({configuration}); - t.ok(jsonConverter, 'JSONConverter created'); - - const deckProps = jsonConverter.convertJsonToDeckProps(JSON_DATA); - t.ok(deckProps, 'JSONConverter converted correctly'); - - const jsonDeck = new Deck( - Object.assign( - { - onAfterRender: () => { - t.ok(jsonDeck, 'JSONConverter rendered'); - jsonDeck.finalize(); - t.end(); - } - }, - deckProps - ) - ); -}); diff --git a/test/modules/json/json-render.spec.js b/test/modules/json/json-render.spec.js new file mode 100644 index 00000000000..fe2bcdfa7dc --- /dev/null +++ b/test/modules/json/json-render.spec.js @@ -0,0 +1,26 @@ +import test from 'tape-catch'; +import {Deck} from '@deck.gl/core'; +import {_JSONConverter as JSONConverter} from '@deck.gl/json'; + +import {configuration, JSON_DATA} from './json-converter.spec'; + +test('JSONConverter#render', t => { + const jsonConverter = new JSONConverter({configuration}); + t.ok(jsonConverter, 'JSONConverter created'); + + const deckProps = jsonConverter.convertJsonToDeckProps(JSON_DATA); + t.ok(deckProps, 'JSONConverter converted correctly'); + + const jsonDeck = new Deck( + Object.assign( + { + onAfterRender: () => { + t.ok(jsonDeck, 'JSONConverter rendered'); + jsonDeck.finalize(); + t.end(); + } + }, + deckProps + ) + ); +}); diff --git a/test/modules/jupyter-widget/index.spec.js b/test/modules/jupyter-widget/index.spec.js index b2052f20215..8239dd45d32 100644 --- a/test/modules/jupyter-widget/index.spec.js +++ b/test/modules/jupyter-widget/index.spec.js @@ -1,34 +1,11 @@ import test from 'tape-catch'; function getDeckModel(state) { - let polyfilled = false; - /* global global */ - if (typeof document === 'undefined' && typeof global !== 'undefined') { - // Running in Node - const {JSDOM} = require('jsdom'); - const dom = new JSDOM(``); - // These globals are required prior to importing @jupyter-widgets/base - global.window = dom.window; - global.navigator = dom.window.navigator; - global.document = dom.window.document; - global.Element = dom.window.Element; - - polyfilled = true; - } - + // Require at runtime, after the environment is polyfilled const {DeckGLModel} = require('@deck.gl/jupyter-widget'); const {createTestModel} = require('./utils.spec'); const model = createTestModel(DeckGLModel, state); - - if (polyfilled) { - // Reset to avoid polluting the environment for other tests - delete global.window; - delete global.navigator; - delete global.document; - delete global.Element; - } - return model; } diff --git a/test/modules/layers/index.js b/test/modules/layers/index.js index ccf775ce8dc..906ae0137e0 100644 --- a/test/modules/layers/index.js +++ b/test/modules/layers/index.js @@ -31,4 +31,5 @@ import './path-layer/path-layer-vertex.spec'; import './icon-manager.spec'; import './text-layer/font-atlas-utils.spec'; import './text-layer/lru-cache.spec'; +import './text-layer/text-layer.spec'; import './column-geometry.spec'; diff --git a/test/modules/layers/text-layer/text-layer.spec.js b/test/modules/layers/text-layer/text-layer.spec.js new file mode 100644 index 00000000000..a82574e470f --- /dev/null +++ b/test/modules/layers/text-layer/text-layer.spec.js @@ -0,0 +1,27 @@ +import test from 'tape-catch'; + +import {TextLayer} from '@deck.gl/layers'; +import * as FIXTURES from 'deck.gl-test/data'; +import {testLayer, generateLayerTests} from '@deck.gl/test-utils'; + +test('TextLayer', t => { + const testCases = generateLayerTests({ + Layer: TextLayer, + sampleProps: { + data: FIXTURES.points, + getText: d => d.ADDRESS, + getPosition: d => d.COORDINATES + }, + assert: t.ok, + onBeforeUpdate: ({testCase}) => t.comment(testCase.title), + onAfterUpdate: ({layer, subLayer}) => { + if (layer.props.data.length) { + t.ok(layer.state.data.length, 'Creates sublayer data'); + t.ok(subLayer, 'Renders sublayer'); + } + } + }); + testLayer({Layer: TextLayer, testCases, onError: t.notOk}); + + t.end(); +}); diff --git a/yarn.lock b/yarn.lock index 63681451dfb..991ef13c38e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3058,6 +3058,15 @@ canvas-to-blob@0.0.0: resolved "https://registry.yarnpkg.com/canvas-to-blob/-/canvas-to-blob-0.0.0.tgz#f1db4dd083ddc74a78fe5bce6a869786b59f51f3" integrity sha1-8dtN0IPdx0p4/lvOaoaXhrWfUfM= +canvas@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/canvas/-/canvas-2.6.0.tgz#7a8f87b6148845d97e6ee30947fba1508bed4941" + integrity sha512-bEO9f1ThmbknLPxCa8Es7obPlN9W3stB1bo7njlhOFKIdUTldeTqXCh9YclCPAi2pSQs84XA0jq/QEZXSzgyMw== + dependencies: + nan "^2.14.0" + node-pre-gyp "^0.11.0" + simple-get "^3.0.3" + cardinal@~0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/cardinal/-/cardinal-0.4.4.tgz#ca5bb68a5b511b90fe93b9acea49bdee5c32bfe2" @@ -7284,6 +7293,11 @@ mute-stream@~0.0.4: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== +nan@^2.14.0: + version "2.14.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" + integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== + nan@^2.6.2, nan@^2.9.2: version "2.11.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.0.tgz#574e360e4d954ab16966ec102c0c049fd961a099" @@ -7489,6 +7503,22 @@ node-pre-gyp@^0.10.0: semver "^5.3.0" tar "^4" +node-pre-gyp@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz#db1f33215272f692cd38f03238e3e9b47c5dd054" + integrity sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + node-releases@^1.1.3: version "1.1.5" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.5.tgz#1dbee1380742125fe99e0476c456670bf3590b89" @@ -9540,6 +9570,15 @@ simple-get@^2.7.0: once "^1.3.1" simple-concat "^1.0.0" +simple-get@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.0.3.tgz#924528ac3f9d7718ce5e9ec1b1a69c0be4d62efa" + integrity sha512-Wvre/Jq5vgoz31Z9stYWPLn0PqRqmBDpFSdypAnHu5AvRVCYPRYGnvryNLiXu8GOBNDH82J2FRHUGMjjHUpXFw== + dependencies: + decompress-response "^3.3.0" + once "^1.3.1" + simple-concat "^1.0.0" + slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"