From f0961a93832711726ec47cd78299508a81e910a2 Mon Sep 17 00:00:00 2001 From: rldhont Date: Thu, 29 Jun 2023 12:25:22 +0200 Subject: [PATCH] [JavaScript] Managed Rule based Symbology like QGIS * The parentRuleKey is used to build the rule based symbology tree * The layer visibility changed when all the rules are disabled * the symbology directly build the legend ON/OFF WMS parameters --- assets/src/modules/state/Layer.js | 45 ++- assets/src/modules/state/Symbology.js | 193 +++++++++- tests/js-units/data/quickosm-road-legend.json | 154 ++++++++ tests/js-units/node/state/layer.test.js | 353 ++++++++++++++++++ tests/js-units/node/state/layerTree.test.js | 182 ++++++++- tests/js-units/node/state/maplayer.test.js | 234 +++++++++++- tests/js-units/node/state/symbology.test.js | 346 ++++++++++++++++- 7 files changed, 1440 insertions(+), 67 deletions(-) create mode 100644 tests/js-units/data/quickosm-road-legend.json diff --git a/assets/src/modules/state/Layer.js b/assets/src/modules/state/Layer.js index 17d5e1ee33..46a05125f8 100644 --- a/assets/src/modules/state/Layer.js +++ b/assets/src/modules/state/Layer.js @@ -344,6 +344,9 @@ export class LayerItemState extends EventDispatcher { ruleKey: evt.ruleKey, checked: evt.checked, }); + if (self.visibility != self.symbology.legendOn) { + self.calculateVisibility(); + } }, 'symbol.checked.changed'); } } @@ -632,27 +635,33 @@ export class LayerLayerState extends LayerItemState { 'DPI': 96 } if (this.symbology instanceof LayerSymbolsSymbology) { - let keyChecked = []; - let keyUnchecked = []; - for (const symbol of this.symbology.getChildren()) { - if (symbol.rulekey === '') { - keyChecked = []; - keyUnchecked = []; - break; - } - if (symbol.checked) { - keyChecked.push(symbol.ruleKey); - } else { - keyUnchecked.push(symbol.ruleKey); - } - } - if (keyChecked.length != 0 && keyUnchecked.length != 0) { - params['LEGEND_ON'] = this.wmsName+':'+keyChecked.join(); - params['LEGEND_OFF'] = this.wmsName+':'+keyUnchecked.join(); - } + params = Object.assign(params, this.symbology.wmsParameters(this.wmsName)) } return params; } + + /** + * Calculate and save visibility + * + * @returns {boolean} the calculated visibility + **/ + calculateVisibility() { + if (this.symbology instanceof LayerSymbolsSymbology + && !this.symbology.legendOn) { + const oldVisibility = this._visibility; + this._visibility = false; + // Only dispatch event if visibility has changed + if (oldVisibility !== null && oldVisibility != this.visibility) { + this.dispatch({ + type: this.type+'.visibility.changed', + name: this.name, + visibility: this.visibility, + }) + } + return false; + } + return super.calculateVisibility(); + } } /** diff --git a/assets/src/modules/state/Symbology.js b/assets/src/modules/state/Symbology.js index eae9b0f0cf..3c79f565cb 100644 --- a/assets/src/modules/state/Symbology.js +++ b/assets/src/modules/state/Symbology.js @@ -163,8 +163,6 @@ const symbolIconProperties = { const symbolIconOptionalProperties = { 'ruleKey': {type: 'string', default: ''}, 'checked': {type: 'boolean', default: true}, - 'scaleMinDenom': {type: 'number', default: -1}, - 'scaleMaxDenom': {type: 'number', default: -1}, } /** * Class representing the symbol icon symbology @@ -183,6 +181,7 @@ export class SymbolIconSymbology extends BaseIconSymbology { **/ constructor(node) { super(node, symbolIconProperties, symbolIconOptionalProperties) + this._childrenRules = [] } /** @@ -224,6 +223,74 @@ export class SymbolIconSymbology extends BaseIconSymbology { }) } + /** + * Is legend ON ? + * + * @type {Boolean} + **/ + get legendOn() { + return this._checked; + } +} + +const symbolRuleProperties = Object.assign( + symbolIconProperties, + {} +); +const symbolRuleOptionalProperties = Object.assign( + symbolIconOptionalProperties, + { + 'scaleMinDenom': {type: 'number', default: -1}, + 'scaleMaxDenom': {type: 'number', default: -1}, + 'parentRuleKey': {type: 'string', default: ''}, + } +); + +/** + * Class representing the symbol rule symbology + * @class + * @augments SymbolIconSymbology + */ +export class SymbolRuleSymbology extends SymbolIconSymbology { + constructor(node) { + super(node, symbolRuleProperties, symbolRuleOptionalProperties) + this._parentRule = null; + this._childrenRules = [] + } + + /** + * Is legend ON ? + * + * @type {Boolean} + **/ + get legendOn() { + if (this.parentRule === null) { + return this._checked; + } + if (this.parentRule.legendOn) { + return this._checked; + } + return false; + } + + /** + * The parent rule key + * + * @type {String} + **/ + get parentRuleKey() { + return this._parentRuleKey; + } + + /** + * The parent rule + * + * @type {?SymbolRuleSymbology} + **/ + get parentRule() { + return this._parentRule; + } + /** * The minimum scale denominator * @@ -241,6 +308,36 @@ export class SymbolIconSymbology extends BaseIconSymbology { get maxScaleDenominator() { return this._scaleMaxDenom; } + + /** + * Children rules count + * + * @type {Number} + **/ + get childrenCount() { + return this._childrenRules.length; + } + + /** + * The children rule + * + * @type {BaseIconSymbology[]} + **/ + get children() { + return [...this._childrenRules]; + } + + /** + * Iterate through children rules + * + * @generator + * @yields {BaseIconSymbology} The next child icon + **/ + *getChildren() { + for (const icon of this._childrenRules) { + yield icon; + } + } } /** @@ -260,7 +357,7 @@ export class BaseSymbolsSymbology extends BaseObjectSymbology { * @param {Object} [requiredProperties={}] - the required properties definition * @param {Object} [optionalProperties={}] - the optional properties definition **/ - constructor(node, requiredProperties={}, optionalProperties = {}) { + constructor(node, requiredProperties={}, optionalProperties = {}, iconClass = BaseIconSymbology) { if (!node.hasOwnProperty('type') || node.type != 'layer') { throw new ValidationError('The layer symbols symbology is only available for layer type!'); @@ -274,7 +371,7 @@ export class BaseSymbolsSymbology extends BaseObjectSymbology { this._icons = []; for(const symbol of this._symbols) { - this._icons.push(new BaseIconSymbology(symbol)); + this._icons.push(new iconClass(symbol)); } } @@ -336,11 +433,26 @@ export class LayerSymbolsSymbology extends BaseSymbolsSymbology { throw new ValidationError('The layer symbols symbology is only available for layer type!'); } - super(node, layerSymbolsProperties, {}) - - this._icons = []; - for(const symbol of this._symbols) { - this._icons.push(new SymbolIconSymbology(symbol)); + if (node.symbols[0].hasOwnProperty('ruleKey') + && node.symbols[0].ruleKey !== '' + && node.symbols[0].hasOwnProperty('parentRuleKey') + && node.symbols[0].parentRuleKey !== '') { + super(node, layerSymbolsProperties, {}, SymbolRuleSymbology) + this._ruleMap = new Map(this._icons.map(i => [i.ruleKey, i])); + let root = new Map(); + for (const icon of this._icons) { + const parent = this._ruleMap.get(icon.parentRuleKey); + if (parent === undefined) { + root.set(icon.ruleKey, icon); + } else { + parent._childrenRules.push(icon) + icon._parentRule = parent; + } + } + this._root = root; + } else { + super(node, layerSymbolsProperties, {}, SymbolIconSymbology) + this._root = null; } } @@ -353,21 +465,44 @@ export class LayerSymbolsSymbology extends BaseSymbolsSymbology { return this._name; } + /** + * Is legend ON ? + * + * @type {Boolean} + **/ + get legendOn() { + for (const symbol of this._icons) { + if (symbol.rulekey === '') { + return true; + } + if (symbol.legendOn) { + return true; + } + } + return false; + } + /** * Children icons count * * @type {Number} **/ get childrenCount() { + if (this._root !== null) { + return this._root.size; + } return this._icons.length; } /** * The children icons * - * @type {SymbolIconSymbology[]} + * @type {Array} **/ get children() { + if (this._root !== null) { + return [...this._root.values()]; + } return [...this._icons]; } @@ -375,12 +510,44 @@ export class LayerSymbolsSymbology extends BaseSymbolsSymbology { * Iterate through children icons * * @generator - * @yields {SymbolIconSymbology} The next child icon + * @yields {SymbolIconSymbology|SymbolRuleSymbology} The next child icon **/ *getChildren() { - for (const icon of this._icons) { - yield icon; + for (const child of this.children) { + yield child; + } + } + + /** + * Parameters for OGC WMS Request + * + * @param {String} wmsName + * + * @returns {Object} can contain LEGEND_ON and LEGEND_OFF parameters + **/ + wmsParameters(wmsName) { + let params = { + } + let keyChecked = []; + let keyUnchecked = []; + for (const symbol of this._icons) { + if (symbol.rulekey === '') { + keyChecked = []; + keyUnchecked = []; + break; + } + if (symbol.legendOn) { + keyChecked.push(symbol.ruleKey); + } else { + keyUnchecked.push(symbol.ruleKey); + } + } + if ((keyChecked.length != 0 || keyUnchecked.length != 0) + && keyChecked.length != this._icons.length) { + params['LEGEND_ON'] = wmsName+':'+keyChecked.join(); + params['LEGEND_OFF'] = wmsName+':'+keyUnchecked.join(); } + return params; } } diff --git a/tests/js-units/data/quickosm-road-legend.json b/tests/js-units/data/quickosm-road-legend.json new file mode 100644 index 0000000000..cecb43e06d --- /dev/null +++ b/tests/js-units/data/quickosm-road-legend.json @@ -0,0 +1,154 @@ +{ + "nodes": [ + { + "symbols": [ + { + "title": "1:25000", + "ruleKey": "{1a0c9345-0ffd-4743-bf78-82ca39f64d40}", + "checked": true, + "parentRuleKey": "{a5359e9e-eecc-437d-a636-38237822ea81}", + "scaleMaxDenom": 25000, + "scaleMinDenom": 1, + "expression": "" + }, + { + "icon": "iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAYAAABSO15qAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAKUlEQVQ4jWNgGPKAUcTI6D8lBrB4JSRR5AIminSPGjBqABRQnJSHAQAA\/s4EEwOIIHMAAAAASUVORK5CYII=", + "title": "Motorway or highway", + "ruleKey": "{1be63a51-ccb6-4c5c-acdf-fdee5f8408c1}", + "checked": true, + "parentRuleKey": "{2df87245-1aca-463a-a8eb-a5f2ea287a44}", + "expression": "" + }, + { + "icon": "iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAYAAABSO15qAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAIUlEQVQ4jWNgGAUUA8aUpUv\/U2IAE6UuGDVgMBgwCqgAAPXFAr2yVKEzAAAAAElFTkSuQmCC", + "title": "Motorway Link", + "ruleKey": "{a9fac601-7bc7-4150-9783-19d7827b2ef8}", + "checked": true, + "parentRuleKey": "{1a0c9345-0ffd-4743-bf78-82ca39f64d40}", + "expression": "" + }, + { + "icon": "iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAYAAABSO15qAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAKUlEQVQ4jWNgGGjA6KPG8J8iA\/6fa6DIACZKNI8aMGrA4DGA4sw08AAAse8GSDAKga8AAAAASUVORK5CYII=", + "title": "Primary road", + "ruleKey": "{e2c3dbec-7274-4149-8b0b-959b2e758b9a}", + "checked": true, + "parentRuleKey": "{1a0c9345-0ffd-4743-bf78-82ca39f64d40}", + "expression": "" + }, + { + "icon": "iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAYAAABSO15qAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAIUlEQVQ4jWNgGAUUA8b\/5xr+U2IAE6UuGDVgMBgwCqgAAAJHA1zUTHY0AAAAAElFTkSuQmCC", + "title": "Primary link", + "ruleKey": "{78db6f50-70cc-417d-995d-97ad897bf52b}", + "checked": true, + "parentRuleKey": "{1a0c9345-0ffd-4743-bf78-82ca39f64d40}", + "expression": "" + }, + { + "icon": "iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAYAAABSO15qAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAMElEQVQ4jWNgGAUUA8Zr1679p8QAJkpdwHKe4zpFBlDsgoE3gMXwh+bAumAUUAEAAL2UBpWoZzLbAAAAAElFTkSuQmCC", + "title": "Tertiary", + "ruleKey": "{26f18044-95a7-4170-9ce3-0137ce4a2232}", + "checked": true, + "parentRuleKey": "{1a0c9345-0ffd-4743-bf78-82ca39f64d40}", + "expression": "" + }, + { + "icon": "iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAYAAABSO15qAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAALElEQVQ4jWNgGAUUA8b79+\/\/p8QAJkpdwHLs\/zmKDKDYBQNvwMDHwiigAgAAmkoJ3Kjim3oAAAAASUVORK5CYII=", + "title": "Tertiary link", + "ruleKey": "{f215859b-f963-4872-8f4b-b2e39e5f0c35}", + "checked": true, + "parentRuleKey": "{1a0c9345-0ffd-4743-bf78-82ca39f64d40}", + "expression": "" + }, + { + "icon": "iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAYAAABSO15qAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAH0lEQVQ4jWNgGAUDDxj\/n7v8nxIDmCh1wagBo2BwAAAegQOryAULBwAAAABJRU5ErkJggg==", + "title": "Secondary", + "ruleKey": "{aac3fe77-b7ff-4c47-8f28-c33de0dc4b2b}", + "checked": true, + "parentRuleKey": "{1a0c9345-0ffd-4743-bf78-82ca39f64d40}", + "expression": "" + }, + { + "icon": "iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAYAAABSO15qAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAALUlEQVQ4jWNgGAUDDxjv37\/\/nxIDWBTef6HIBUwU6R4UBrA8EOSh1IxRMOAAAHjQBqzhew\/aAAAAAElFTkSuQmCC", + "title": "Secondary link", + "ruleKey": "{960d07d3-ac1a-40c8-8f2e-1b499f3ccafc}", + "checked": true, + "parentRuleKey": "{1a0c9345-0ffd-4743-bf78-82ca39f64d40}", + "expression": "" + }, + { + "icon": "iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAYAAABSO15qAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAH0lEQVQ4jWNgGAUDDxh\/\/PjxnxIDmCh1wagBo2BwAAD5JQPzwsyIGgAAAABJRU5ErkJggg==", + "title": "Road, residential, living street, etc.", + "ruleKey": "{303a360c-638b-4c9f-adee-eff33d3e95f1}", + "checked": true, + "parentRuleKey": "{1a0c9345-0ffd-4743-bf78-82ca39f64d40}", + "expression": "" + }, + { + "icon": "iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAYAAABSO15qAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAMElEQVQ4jWNgGAUUA8b79+\/\/p8QAJkpdwPLr93GKDKDYBQNvAAsbq+XAumAUUAEAACjTBrDEG11BAAAAAElFTkSuQmCC", + "title": "Track", + "ruleKey": "{c63b61f8-f9e5-4a57-9231-9001ffd07bad}", + "checked": true, + "parentRuleKey": "{1a0c9345-0ffd-4743-bf78-82ca39f64d40}", + "expression": "" + }, + { + "icon": "iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAYAAABSO15qAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAALUlEQVQ4jWNgGAWjgIGB8f\/\/\/\/9hnNX5\/QwMDAwMoRMLURThE2eitQtHwcgAAHwMC6mBhxP2AAAAAElFTkSuQmCC", + "title": "Cycleway, footpath etc.", + "ruleKey": "{245c23be-e45f-4f80-9ea4-f1676315f178}", + "checked": true, + "parentRuleKey": "{1a0c9345-0ffd-4743-bf78-82ca39f64d40}", + "expression": "" + }, + { + "icon": "iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAYAAABSO15qAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAIElEQVQ4jWNgGAXDADD++PHjPyUGMFHqgoE3YBQMCwAA8goD711BN1YAAAAASUVORK5CYII=", + "scaleMaxDenom": 50000, + "scaleMinDenom": 25001, + "title": "25k to 50k", + "ruleKey": "{b3334f5f-daaf-4dc2-a2dc-f5f8485a1b37}", + "checked": true, + "parentRuleKey": "{a5359e9e-eecc-437d-a636-38237822ea81}", + "expression": "" + }, + { + "icon": "iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAYAAABSO15qAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAHklEQVQ4jWNgGAWMcZOm\/KfEACZKXTBqwKgBowACABg5ApcidJEdAAAAAElFTkSuQmCC", + "title": "Motorway or highway", + "ruleKey": "{1be63a51-ccb6-4c5c-acdf-fdee5f8408c1}", + "checked": true, + "parentRuleKey": "{2df87245-1aca-463a-a8eb-a5f2ea287a44}", + "expression": "" + }, + { + "icon": "iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAYAAABSO15qAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAKElEQVQ4jWNgGAUUA0YfNYb\/FBnw\/1wDRQYwUaJ51AAIoDgaRwEVAAASvgY8+kLcRgAAAABJRU5ErkJggg==", + "title": "Primary", + "ruleKey": "{97c219cb-9b1a-4a9d-bba5-cfe3006fe48a}", + "checked": true, + "parentRuleKey": "{b3334f5f-daaf-4dc2-a2dc-f5f8485a1b37}", + "expression": "" + }, + { + "icon": "iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAYAAABSO15qAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAG0lEQVQ4jWNgGAWjgAqAMSQk5NdAO2IUDH0AAHxdAfgkeO85AAAAAElFTkSuQmCC", + "scaleMaxDenom": 10000000, + "scaleMinDenom": 50001, + "title": "50k +", + "ruleKey": "{2df87245-1aca-463a-a8eb-a5f2ea287a44}", + "checked": true, + "parentRuleKey": "{a5359e9e-eecc-437d-a636-38237822ea81}", + "expression": "" + }, + { + "icon": "iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAYAAABSO15qAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAIElEQVQ4jWNgGAXDADCmLF36nxIDmCh1wcAbMAqGBQAAhxICtTZBYRgAAAAASUVORK5CYII=", + "title": "Motorway or highway", + "ruleKey": "{1be63a51-ccb6-4c5c-acdf-fdee5f8408c1}", + "checked": true, + "parentRuleKey": "{2df87245-1aca-463a-a8eb-a5f2ea287a44}", + "expression": "" + } + ], + "title": "road", + "type": "layer", + "name": "road", + "layerName": "road" + } + ], + "title": "" +} diff --git a/tests/js-units/node/state/layer.test.js b/tests/js-units/node/state/layer.test.js index abe6f8bc35..31eb95e7f4 100644 --- a/tests/js-units/node/state/layer.test.js +++ b/tests/js-units/node/state/layer.test.js @@ -5,6 +5,7 @@ import { readFileSync } from 'fs'; import { ValidationError } from '../../../../assets/src/modules/Errors.js'; import { LayersConfig } from '../../../../assets/src/modules/config/Layer.js'; import { LayerGeographicBoundingBoxConfig, LayerBoundingBoxConfig, LayerTreeGroupConfig, buildLayerTreeConfig } from '../../../../assets/src/modules/config/LayerTree.js'; +import { LayerIconSymbology, LayerSymbolsSymbology, SymbolIconSymbology } from '../../../../assets/src/modules/state/Symbology.js'; import { buildLayersOrder } from '../../../../assets/src/modules/config/LayersOrder.js'; import { Extent } from '../../../../assets/src/modules/utils/Extent.js'; @@ -1438,4 +1439,356 @@ describe('LayersAndGroupsCollection', function () { expect(collectionLayerVisibilityChangedEvt[1].name).to.be.eq('tramway') expect(collectionLayerVisibilityChangedEvt[2].name).to.be.eq('publicbuildings') }) + + it('Legend ON/OFF', function () { + const capabilities = JSON.parse(readFileSync('./data/montpellier-capabilities.json', 'utf8')); + expect(capabilities).to.not.be.undefined + expect(capabilities.Capability).to.not.be.undefined + const config = JSON.parse(readFileSync('./data/montpellier-config.json', 'utf8')); + expect(config).to.not.be.undefined + + const layers = new LayersConfig(config.layers); + + const rootCfg = buildLayerTreeConfig(capabilities.Capability.Layer, layers); + expect(rootCfg).to.be.instanceOf(LayerTreeGroupConfig) + + const layersOrder = buildLayersOrder(config, rootCfg); + + const collection = new LayersAndGroupsCollection(rootCfg, layersOrder); + + const sousquartiers = collection.getLayerByName('SousQuartiers') + expect(sousquartiers).to.be.instanceOf(LayerVectorState) + expect(sousquartiers.name).to.be.eq('SousQuartiers') + expect(sousquartiers.wmsSelectedStyleName).to.be.eq('default') + expect(sousquartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'SousQuartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'DPI': 96 + }) + expect(sousquartiers.symbology).to.be.null + + let collectionLayerSymbologyChangedEvt = null; + let sousquartiersSymbologyChangedEvt = null; + + collection.addListener(evt => { + collectionLayerSymbologyChangedEvt = evt + }, 'layer.symbology.changed'); + sousquartiers.addListener(evt => { + sousquartiersSymbologyChangedEvt = evt + }, 'layer.symbology.changed'); + + const legend = JSON.parse(readFileSync('./data/montpellier-legend.json', 'utf8')); + expect(legend).to.not.be.undefined + + // Set symbology + sousquartiers.symbology = legend.nodes[1] + expect(sousquartiers.symbology).to.be.instanceOf(LayerIconSymbology) + // Event dispatched + expect(sousquartiersSymbologyChangedEvt).to.not.be.null + expect(sousquartiersSymbologyChangedEvt.name).to.be.eq('SousQuartiers') + expect(collectionLayerSymbologyChangedEvt).to.not.be.null + expect(collectionLayerSymbologyChangedEvt.name).to.be.eq('SousQuartiers') + + // Reset + collectionLayerSymbologyChangedEvt = null; + sousquartiersSymbologyChangedEvt = null; + + const quartiers = collection.getLayerByName('Quartiers') + expect(quartiers).to.be.instanceOf(LayerVectorState) + expect(quartiers.name).to.be.eq('Quartiers') + expect(quartiers.wmsSelectedStyleName).to.be.eq('default') + expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'Quartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'DPI': 96 + }) + expect(quartiers.symbology).to.be.null + + // Set symbology + quartiers.symbology = legend.nodes[0] + // Check symbology + expect(quartiers.symbology).to.be.instanceOf(LayerSymbolsSymbology) + expect(quartiers.symbology.childrenCount).to.be.eq(8) + expect(quartiers.symbology.children[0]).to.be.instanceOf(SymbolIconSymbology) + expect(quartiers.symbology.children[0].checked).to.be.true + expect(quartiers.symbology.children[0].ruleKey).to.be.eq('0') + // Event dispatched + expect(sousquartiersSymbologyChangedEvt).to.be.null + expect(collectionLayerSymbologyChangedEvt).to.not.be.null + expect(collectionLayerSymbologyChangedEvt.name).to.be.eq('Quartiers') + + // Unchecked rules + quartiers.symbology.children[0].checked = false; + quartiers.symbology.children[2].checked = false; + quartiers.symbology.children[4].checked = false; + quartiers.symbology.children[6].checked = false; + expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'Quartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'LEGEND_ON': 'Quartiers:1,3,5,7', + 'LEGEND_OFF': 'Quartiers:0,2,4,6', + 'DPI': 96 + }) + + // Checked rules + quartiers.symbology.children[0].checked = true; + quartiers.symbology.children[2].checked = true; + quartiers.symbology.children[4].checked = true; + expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'Quartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'LEGEND_ON': 'Quartiers:0,1,2,3,4,5,7', + 'LEGEND_OFF': 'Quartiers:6', + 'DPI': 96 + }) + + + // Checked all rules and events + let collectionLayerSymbolCheckedChangedEvt = []; + let collectionLayerVisibilityChangedEvt = []; + let layerSymbolCheckedChangedEvt = []; + let layerVisibilityChangedEvt = []; + let symbolCheckedChangedEvt = null; + quartiers.symbology.children[6].addListener(evt => { + symbolCheckedChangedEvt = evt + }, 'symbol.checked.changed'); + quartiers.addListener(evt => { + layerSymbolCheckedChangedEvt.push(evt) + }, 'layer.symbol.checked.changed'); + quartiers.addListener(evt => { + layerVisibilityChangedEvt.push(evt) + }, 'layer.visibility.changed'); + collection.addListener(evt => { + collectionLayerSymbolCheckedChangedEvt.push(evt) + }, 'layer.symbol.checked.changed'); + collection.addListener(evt => { + collectionLayerVisibilityChangedEvt.push(evt) + }, 'layer.visibility.changed'); + quartiers.symbology.children[6].checked = true; + expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'Quartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'DPI': 96 + }) + expect(symbolCheckedChangedEvt).to.not.be.null + expect(symbolCheckedChangedEvt.title).to.be.eq('PRES D\'ARENE') + expect(symbolCheckedChangedEvt.ruleKey).to.be.eq('6') + expect(symbolCheckedChangedEvt.checked).to.be.true + expect(layerSymbolCheckedChangedEvt).to.have.length(1) + expect(layerSymbolCheckedChangedEvt[0].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[0].title).to.be.eq('PRES D\'ARENE') + expect(layerSymbolCheckedChangedEvt[0].ruleKey).to.be.eq('6') + expect(layerSymbolCheckedChangedEvt[0].checked).to.be.true + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(collectionLayerSymbolCheckedChangedEvt).to.have.length(1) + expect(collectionLayerSymbolCheckedChangedEvt[0]).to.be.deep.eq(layerSymbolCheckedChangedEvt[0]) + expect(collectionLayerVisibilityChangedEvt).to.have.length(0) + + // Reset + collectionLayerSymbolCheckedChangedEvt = []; + collectionLayerVisibilityChangedEvt = []; + layerSymbolCheckedChangedEvt = []; + layerVisibilityChangedEvt = []; + symbolCheckedChangedEvt = null; + + // Check layer visibility changed with symbols checked changed + // Rule 0 + quartiers.symbology.children[0].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(1) + expect(layerSymbolCheckedChangedEvt[0].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[0].ruleKey).to.be.eq('0') + expect(layerSymbolCheckedChangedEvt[0].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(collectionLayerSymbolCheckedChangedEvt).to.have.length(1) + expect(collectionLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(collectionLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'Quartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'LEGEND_ON': 'Quartiers:1,2,3,4,5,6,7', + 'LEGEND_OFF': 'Quartiers:0', + 'DPI': 96 + }) + + // Rule 1 + quartiers.symbology.children[1].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(2) + expect(layerSymbolCheckedChangedEvt[1].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[1].ruleKey).to.be.eq('1') + expect(layerSymbolCheckedChangedEvt[1].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(collectionLayerSymbolCheckedChangedEvt).to.have.length(2) + expect(collectionLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(collectionLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'Quartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'LEGEND_ON': 'Quartiers:2,3,4,5,6,7', + 'LEGEND_OFF': 'Quartiers:0,1', + 'DPI': 96 + }) + + // Rule 2 + quartiers.symbology.children[2].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(3) + expect(layerSymbolCheckedChangedEvt[2].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[2].ruleKey).to.be.eq('2') + expect(layerSymbolCheckedChangedEvt[2].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(collectionLayerSymbolCheckedChangedEvt).to.have.length(3) + expect(collectionLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(collectionLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'Quartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'LEGEND_ON': 'Quartiers:3,4,5,6,7', + 'LEGEND_OFF': 'Quartiers:0,1,2', + 'DPI': 96 + }) + + // Rule 3 + quartiers.symbology.children[3].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(4) + expect(layerSymbolCheckedChangedEvt[3].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[3].ruleKey).to.be.eq('3') + expect(layerSymbolCheckedChangedEvt[3].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(collectionLayerSymbolCheckedChangedEvt).to.have.length(4) + expect(collectionLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(collectionLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'Quartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'LEGEND_ON': 'Quartiers:4,5,6,7', + 'LEGEND_OFF': 'Quartiers:0,1,2,3', + 'DPI': 96 + }) + + // Rule 4 + quartiers.symbology.children[4].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(5) + expect(layerSymbolCheckedChangedEvt[4].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[4].ruleKey).to.be.eq('4') + expect(layerSymbolCheckedChangedEvt[4].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(collectionLayerSymbolCheckedChangedEvt).to.have.length(5) + expect(collectionLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(collectionLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'Quartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'LEGEND_ON': 'Quartiers:5,6,7', + 'LEGEND_OFF': 'Quartiers:0,1,2,3,4', + 'DPI': 96 + }) + + // Rule 5 + quartiers.symbology.children[5].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(6) + expect(layerSymbolCheckedChangedEvt[5].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[5].ruleKey).to.be.eq('5') + expect(layerSymbolCheckedChangedEvt[5].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(collectionLayerSymbolCheckedChangedEvt).to.have.length(6) + expect(collectionLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(collectionLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'Quartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'LEGEND_ON': 'Quartiers:6,7', + 'LEGEND_OFF': 'Quartiers:0,1,2,3,4,5', + 'DPI': 96 + }) + + // Rule 6 + quartiers.symbology.children[6].checked = false; + expect(symbolCheckedChangedEvt).to.not.be.null + expect(symbolCheckedChangedEvt.ruleKey).to.be.eq('6') + expect(symbolCheckedChangedEvt.checked).to.be.false + expect(layerSymbolCheckedChangedEvt).to.have.length(7) + expect(layerSymbolCheckedChangedEvt[6].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[6].ruleKey).to.be.eq('6') + expect(layerSymbolCheckedChangedEvt[6].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(collectionLayerSymbolCheckedChangedEvt).to.have.length(7) + expect(collectionLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(collectionLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'Quartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'LEGEND_ON': 'Quartiers:7', + 'LEGEND_OFF': 'Quartiers:0,1,2,3,4,5,6', + 'DPI': 96 + }) + + // Reset + symbolCheckedChangedEvt = null + + // Rule 7 + quartiers.symbology.children[7].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(8) + expect(layerSymbolCheckedChangedEvt[7].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[7].ruleKey).to.be.eq('7') + expect(layerSymbolCheckedChangedEvt[7].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(1) + expect(layerVisibilityChangedEvt[0].name).to.be.eq('Quartiers') + expect(layerVisibilityChangedEvt[0].visibility).to.be.false + expect(collectionLayerSymbolCheckedChangedEvt).to.have.length(8) + expect(collectionLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(collectionLayerVisibilityChangedEvt).to.have.length(1) + expect(collectionLayerVisibilityChangedEvt).to.be.deep.eq(layerVisibilityChangedEvt) + expect(quartiers.visibility).to.be.false + + // Rule 6 + quartiers.symbology.children[6].checked = true; + expect(symbolCheckedChangedEvt).to.not.be.null + expect(symbolCheckedChangedEvt.ruleKey).to.be.eq('6') + expect(symbolCheckedChangedEvt.checked).to.be.true + expect(layerSymbolCheckedChangedEvt).to.have.length(9) + expect(layerSymbolCheckedChangedEvt[8].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[8].ruleKey).to.be.eq('6') + expect(layerSymbolCheckedChangedEvt[8].checked).to.be.true + expect(layerVisibilityChangedEvt).to.have.length(2) + expect(layerVisibilityChangedEvt[1].name).to.be.eq('Quartiers') + expect(layerVisibilityChangedEvt[1].visibility).to.be.true + expect(collectionLayerSymbolCheckedChangedEvt).to.have.length(9) + expect(collectionLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(collectionLayerVisibilityChangedEvt).to.have.length(2) + expect(collectionLayerVisibilityChangedEvt).to.be.deep.eq(layerVisibilityChangedEvt) + expect(quartiers.visibility).to.be.true + expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'Quartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'LEGEND_ON': 'Quartiers:6', + 'LEGEND_OFF': 'Quartiers:0,1,2,3,4,5,7', + 'DPI': 96 + }) + }) }) diff --git a/tests/js-units/node/state/layerTree.test.js b/tests/js-units/node/state/layerTree.test.js index 5dfd9078a7..a8e6d23a48 100644 --- a/tests/js-units/node/state/layerTree.test.js +++ b/tests/js-units/node/state/layerTree.test.js @@ -838,18 +838,26 @@ describe('LayerTreeGroupState', function () { }) // Checked all rules and events - let rootLayerSymbologyChangedEvt = null; - let layerSymbologyChangedEvt = null; - let symbologyChangedEvt = null; + let rootLayerSymbolCheckedChangedEvt = []; + let rootLayerVisibilityChangedEvt = []; + let layerSymbolCheckedChangedEvt = []; + let layerVisibilityChangedEvt = []; + let symbolCheckedChangedEvt = null; quartiers.symbology.children[6].addListener(evt => { - symbologyChangedEvt = evt + symbolCheckedChangedEvt = evt }, 'symbol.checked.changed'); quartiers.addListener(evt => { - layerSymbologyChangedEvt = evt + layerSymbolCheckedChangedEvt.push(evt) }, 'layer.symbol.checked.changed'); + quartiers.addListener(evt => { + layerVisibilityChangedEvt.push(evt) + }, 'layer.visibility.changed'); root.addListener(evt => { - rootLayerSymbologyChangedEvt = evt + rootLayerSymbolCheckedChangedEvt.push(evt) }, 'layer.symbol.checked.changed'); + root.addListener(evt => { + rootLayerVisibilityChangedEvt.push(evt) + }, 'layer.visibility.changed'); quartiers.symbology.children[6].checked = true; expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ 'LAYERS': 'Quartiers', @@ -857,16 +865,156 @@ describe('LayerTreeGroupState', function () { 'FORMAT': 'image/png', 'DPI': 96 }) - expect(symbologyChangedEvt).to.not.be.null - expect(symbologyChangedEvt.title).to.be.eq('PRES D\'ARENE') - expect(symbologyChangedEvt.ruleKey).to.be.eq('6') - expect(symbologyChangedEvt.checked).to.be.true - expect(layerSymbologyChangedEvt).to.not.be.null - expect(layerSymbologyChangedEvt.name).to.be.eq('Quartiers') - expect(layerSymbologyChangedEvt.title).to.be.eq('PRES D\'ARENE') - expect(layerSymbologyChangedEvt.ruleKey).to.be.eq('6') - expect(layerSymbologyChangedEvt.checked).to.be.true - expect(rootLayerSymbologyChangedEvt).to.not.be.null - expect(rootLayerSymbologyChangedEvt).to.be.eq(layerSymbologyChangedEvt) + expect(symbolCheckedChangedEvt).to.not.be.null + expect(symbolCheckedChangedEvt.title).to.be.eq('PRES D\'ARENE') + expect(symbolCheckedChangedEvt.ruleKey).to.be.eq('6') + expect(symbolCheckedChangedEvt.checked).to.be.true + expect(layerSymbolCheckedChangedEvt).to.have.length(1) + expect(layerSymbolCheckedChangedEvt[0].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[0].title).to.be.eq('PRES D\'ARENE') + expect(layerSymbolCheckedChangedEvt[0].ruleKey).to.be.eq('6') + expect(layerSymbolCheckedChangedEvt[0].checked).to.be.true + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(rootLayerSymbolCheckedChangedEvt).to.have.length(1) + expect(rootLayerSymbolCheckedChangedEvt[0]).to.be.deep.eq(layerSymbolCheckedChangedEvt[0]) + expect(rootLayerVisibilityChangedEvt).to.have.length(0) + + // Reset + rootLayerSymbolCheckedChangedEvt = []; + rootLayerVisibilityChangedEvt = []; + layerSymbolCheckedChangedEvt = []; + layerVisibilityChangedEvt = []; + symbolCheckedChangedEvt = null; + + // Check layer visibility changed with symbols checked changed + // Rule 0 + quartiers.symbology.children[0].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(1) + expect(layerSymbolCheckedChangedEvt[0].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[0].ruleKey).to.be.eq('0') + expect(layerSymbolCheckedChangedEvt[0].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(rootLayerSymbolCheckedChangedEvt).to.have.length(1) + expect(rootLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(rootLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + + // Rule 1 + quartiers.symbology.children[1].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(2) + expect(layerSymbolCheckedChangedEvt[1].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[1].ruleKey).to.be.eq('1') + expect(layerSymbolCheckedChangedEvt[1].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(rootLayerSymbolCheckedChangedEvt).to.have.length(2) + expect(rootLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(rootLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + + // Rule 2 + quartiers.symbology.children[2].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(3) + expect(layerSymbolCheckedChangedEvt[2].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[2].ruleKey).to.be.eq('2') + expect(layerSymbolCheckedChangedEvt[2].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(rootLayerSymbolCheckedChangedEvt).to.have.length(3) + expect(rootLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(rootLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + + // Rule 3 + quartiers.symbology.children[3].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(4) + expect(layerSymbolCheckedChangedEvt[3].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[3].ruleKey).to.be.eq('3') + expect(layerSymbolCheckedChangedEvt[3].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(rootLayerSymbolCheckedChangedEvt).to.have.length(4) + expect(rootLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(rootLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + + // Rule 4 + quartiers.symbology.children[4].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(5) + expect(layerSymbolCheckedChangedEvt[4].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[4].ruleKey).to.be.eq('4') + expect(layerSymbolCheckedChangedEvt[4].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(rootLayerSymbolCheckedChangedEvt).to.have.length(5) + expect(rootLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(rootLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + + // Rule 5 + quartiers.symbology.children[5].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(6) + expect(layerSymbolCheckedChangedEvt[5].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[5].ruleKey).to.be.eq('5') + expect(layerSymbolCheckedChangedEvt[5].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(rootLayerSymbolCheckedChangedEvt).to.have.length(6) + expect(rootLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(rootLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + + // Rule 6 + quartiers.symbology.children[6].checked = false; + expect(symbolCheckedChangedEvt).to.not.be.null + expect(symbolCheckedChangedEvt.ruleKey).to.be.eq('6') + expect(symbolCheckedChangedEvt.checked).to.be.false + expect(layerSymbolCheckedChangedEvt).to.have.length(7) + expect(layerSymbolCheckedChangedEvt[6].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[6].ruleKey).to.be.eq('6') + expect(layerSymbolCheckedChangedEvt[6].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(rootLayerSymbolCheckedChangedEvt).to.have.length(7) + expect(rootLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(rootLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + + // Reset + symbolCheckedChangedEvt = null; + + // Rule 7 + quartiers.symbology.children[7].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(8) + expect(layerSymbolCheckedChangedEvt[7].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[7].ruleKey).to.be.eq('7') + expect(layerSymbolCheckedChangedEvt[7].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(1) + expect(layerVisibilityChangedEvt[0].name).to.be.eq('Quartiers') + expect(layerVisibilityChangedEvt[0].visibility).to.be.false + expect(rootLayerSymbolCheckedChangedEvt).to.have.length(8) + expect(rootLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(rootLayerVisibilityChangedEvt).to.have.length(1) + expect(rootLayerVisibilityChangedEvt).to.be.deep.eq(layerVisibilityChangedEvt) + expect(quartiers.visibility).to.be.false + + // Rule 6 + quartiers.symbology.children[6].checked = true; + expect(symbolCheckedChangedEvt).to.not.be.null + expect(symbolCheckedChangedEvt.ruleKey).to.be.eq('6') + expect(symbolCheckedChangedEvt.checked).to.be.true + expect(layerSymbolCheckedChangedEvt).to.have.length(9) + expect(layerSymbolCheckedChangedEvt[8].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[8].ruleKey).to.be.eq('6') + expect(layerSymbolCheckedChangedEvt[8].checked).to.be.true + expect(layerVisibilityChangedEvt).to.have.length(2) + expect(layerVisibilityChangedEvt[1].name).to.be.eq('Quartiers') + expect(layerVisibilityChangedEvt[1].visibility).to.be.true + expect(rootLayerSymbolCheckedChangedEvt).to.have.length(9) + expect(rootLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(rootLayerVisibilityChangedEvt).to.have.length(2) + expect(rootLayerVisibilityChangedEvt).to.be.deep.eq(layerVisibilityChangedEvt) + expect(quartiers.visibility).to.be.true }) }) diff --git a/tests/js-units/node/state/maplayer.test.js b/tests/js-units/node/state/maplayer.test.js index 0483c4d9f1..eb1ec877da 100644 --- a/tests/js-units/node/state/maplayer.test.js +++ b/tests/js-units/node/state/maplayer.test.js @@ -703,18 +703,26 @@ describe('MapGroupState', function () { }) // Checked all rules and events - let rootLayerSymbolCheckedChangedEvt = null; - let layerSymbolCheckedChangedEvt = null; + let rootLayerSymbolCheckedChangedEvt = []; + let rootLayerVisibilityChangedEvt = []; + let layerSymbolCheckedChangedEvt = []; + let layerVisibilityChangedEvt = []; let symbolCheckedChangedEvt = null; quartiers.symbology.children[6].addListener(evt => { symbolCheckedChangedEvt = evt }, 'symbol.checked.changed'); quartiers.addListener(evt => { - layerSymbolCheckedChangedEvt = evt + layerSymbolCheckedChangedEvt.push(evt) }, 'layer.symbol.checked.changed'); + quartiers.addListener(evt => { + layerVisibilityChangedEvt.push(evt) + }, 'layer.visibility.changed'); root.addListener(evt => { - rootLayerSymbolCheckedChangedEvt = evt + rootLayerSymbolCheckedChangedEvt.push(evt) }, 'layer.symbol.checked.changed'); + root.addListener(evt => { + rootLayerVisibilityChangedEvt.push(evt) + }, 'layer.visibility.changed'); quartiers.symbology.children[6].checked = true; expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ 'LAYERS': 'Quartiers', @@ -726,13 +734,217 @@ describe('MapGroupState', function () { expect(symbolCheckedChangedEvt.title).to.be.eq('PRES D\'ARENE') expect(symbolCheckedChangedEvt.ruleKey).to.be.eq('6') expect(symbolCheckedChangedEvt.checked).to.be.true - expect(layerSymbolCheckedChangedEvt).to.not.be.null - expect(layerSymbolCheckedChangedEvt.name).to.be.eq('Quartiers') - expect(layerSymbolCheckedChangedEvt.title).to.be.eq('PRES D\'ARENE') - expect(layerSymbolCheckedChangedEvt.ruleKey).to.be.eq('6') - expect(layerSymbolCheckedChangedEvt.checked).to.be.true - expect(rootLayerSymbolCheckedChangedEvt).to.not.be.null - expect(rootLayerSymbolCheckedChangedEvt).to.be.eq(layerSymbolCheckedChangedEvt) + expect(layerSymbolCheckedChangedEvt).to.have.length(1) + expect(layerSymbolCheckedChangedEvt[0].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[0].title).to.be.eq('PRES D\'ARENE') + expect(layerSymbolCheckedChangedEvt[0].ruleKey).to.be.eq('6') + expect(layerSymbolCheckedChangedEvt[0].checked).to.be.true + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(rootLayerSymbolCheckedChangedEvt).to.have.length(1) + expect(rootLayerSymbolCheckedChangedEvt[0]).to.be.deep.eq(layerSymbolCheckedChangedEvt[0]) + expect(rootLayerVisibilityChangedEvt).to.have.length(0) + + // Reset + rootLayerSymbolCheckedChangedEvt = []; + rootLayerVisibilityChangedEvt = []; + layerSymbolCheckedChangedEvt = []; + layerVisibilityChangedEvt = []; + symbolCheckedChangedEvt = null; + + // Check layer visibility changed with symbols checked changed + // Rule 0 + quartiers.symbology.children[0].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(1) + expect(layerSymbolCheckedChangedEvt[0].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[0].ruleKey).to.be.eq('0') + expect(layerSymbolCheckedChangedEvt[0].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(rootLayerSymbolCheckedChangedEvt).to.have.length(1) + expect(rootLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(rootLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'Quartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'LEGEND_ON': 'Quartiers:1,2,3,4,5,6,7', + 'LEGEND_OFF': 'Quartiers:0', + 'DPI': 96 + }) + + // Rule 1 + quartiers.symbology.children[1].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(2) + expect(layerSymbolCheckedChangedEvt[1].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[1].ruleKey).to.be.eq('1') + expect(layerSymbolCheckedChangedEvt[1].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(rootLayerSymbolCheckedChangedEvt).to.have.length(2) + expect(rootLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(rootLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'Quartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'LEGEND_ON': 'Quartiers:2,3,4,5,6,7', + 'LEGEND_OFF': 'Quartiers:0,1', + 'DPI': 96 + }) + + // Rule 2 + quartiers.symbology.children[2].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(3) + expect(layerSymbolCheckedChangedEvt[2].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[2].ruleKey).to.be.eq('2') + expect(layerSymbolCheckedChangedEvt[2].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(rootLayerSymbolCheckedChangedEvt).to.have.length(3) + expect(rootLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(rootLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'Quartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'LEGEND_ON': 'Quartiers:3,4,5,6,7', + 'LEGEND_OFF': 'Quartiers:0,1,2', + 'DPI': 96 + }) + + // Rule 3 + quartiers.symbology.children[3].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(4) + expect(layerSymbolCheckedChangedEvt[3].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[3].ruleKey).to.be.eq('3') + expect(layerSymbolCheckedChangedEvt[3].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(rootLayerSymbolCheckedChangedEvt).to.have.length(4) + expect(rootLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(rootLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'Quartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'LEGEND_ON': 'Quartiers:4,5,6,7', + 'LEGEND_OFF': 'Quartiers:0,1,2,3', + 'DPI': 96 + }) + + // Rule 4 + quartiers.symbology.children[4].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(5) + expect(layerSymbolCheckedChangedEvt[4].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[4].ruleKey).to.be.eq('4') + expect(layerSymbolCheckedChangedEvt[4].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(rootLayerSymbolCheckedChangedEvt).to.have.length(5) + expect(rootLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(rootLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'Quartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'LEGEND_ON': 'Quartiers:5,6,7', + 'LEGEND_OFF': 'Quartiers:0,1,2,3,4', + 'DPI': 96 + }) + + // Rule 5 + quartiers.symbology.children[5].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(6) + expect(layerSymbolCheckedChangedEvt[5].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[5].ruleKey).to.be.eq('5') + expect(layerSymbolCheckedChangedEvt[5].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(rootLayerSymbolCheckedChangedEvt).to.have.length(6) + expect(rootLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(rootLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'Quartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'LEGEND_ON': 'Quartiers:6,7', + 'LEGEND_OFF': 'Quartiers:0,1,2,3,4,5', + 'DPI': 96 + }) + + // Rule 6 + quartiers.symbology.children[6].checked = false; + expect(symbolCheckedChangedEvt).to.not.be.null + expect(symbolCheckedChangedEvt.ruleKey).to.be.eq('6') + expect(symbolCheckedChangedEvt.checked).to.be.false + expect(layerSymbolCheckedChangedEvt).to.have.length(7) + expect(layerSymbolCheckedChangedEvt[6].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[6].ruleKey).to.be.eq('6') + expect(layerSymbolCheckedChangedEvt[6].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(0) + expect(rootLayerSymbolCheckedChangedEvt).to.have.length(7) + expect(rootLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(rootLayerVisibilityChangedEvt).to.have.length(0) + expect(quartiers.visibility).to.be.true + expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'Quartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'LEGEND_ON': 'Quartiers:7', + 'LEGEND_OFF': 'Quartiers:0,1,2,3,4,5,6', + 'DPI': 96 + }) + + // Reset + symbolCheckedChangedEvt = null + + // Rule 7 + quartiers.symbology.children[7].checked = false; + expect(symbolCheckedChangedEvt).to.be.null + expect(layerSymbolCheckedChangedEvt).to.have.length(8) + expect(layerSymbolCheckedChangedEvt[7].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[7].ruleKey).to.be.eq('7') + expect(layerSymbolCheckedChangedEvt[7].checked).to.be.false + expect(layerVisibilityChangedEvt).to.have.length(1) + expect(layerVisibilityChangedEvt[0].name).to.be.eq('Quartiers') + expect(layerVisibilityChangedEvt[0].visibility).to.be.false + expect(rootLayerSymbolCheckedChangedEvt).to.have.length(8) + expect(rootLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(rootLayerVisibilityChangedEvt).to.have.length(1) + expect(rootLayerVisibilityChangedEvt).to.be.deep.eq(layerVisibilityChangedEvt) + expect(quartiers.visibility).to.be.false + + // Rule 6 + quartiers.symbology.children[6].checked = true; + expect(symbolCheckedChangedEvt).to.not.be.null + expect(symbolCheckedChangedEvt.ruleKey).to.be.eq('6') + expect(symbolCheckedChangedEvt.checked).to.be.true + expect(layerSymbolCheckedChangedEvt).to.have.length(9) + expect(layerSymbolCheckedChangedEvt[8].name).to.be.eq('Quartiers') + expect(layerSymbolCheckedChangedEvt[8].ruleKey).to.be.eq('6') + expect(layerSymbolCheckedChangedEvt[8].checked).to.be.true + expect(layerVisibilityChangedEvt).to.have.length(2) + expect(layerVisibilityChangedEvt[1].name).to.be.eq('Quartiers') + expect(layerVisibilityChangedEvt[1].visibility).to.be.true + expect(rootLayerSymbolCheckedChangedEvt).to.have.length(9) + expect(rootLayerSymbolCheckedChangedEvt).to.be.deep.eq(layerSymbolCheckedChangedEvt) + expect(rootLayerVisibilityChangedEvt).to.have.length(2) + expect(rootLayerVisibilityChangedEvt).to.be.deep.eq(layerVisibilityChangedEvt) + expect(quartiers.visibility).to.be.true + expect(quartiers.wmsParameters).to.be.an('object').that.deep.equal({ + 'LAYERS': 'Quartiers', + 'STYLES': 'default', + 'FORMAT': 'image/png', + 'LEGEND_ON': 'Quartiers:6', + 'LEGEND_OFF': 'Quartiers:0,1,2,3,4,5,7', + 'DPI': 96 + }) }) it('Selection & token', function () { diff --git a/tests/js-units/node/state/symbology.test.js b/tests/js-units/node/state/symbology.test.js index 227c421d4f..d45acc23a7 100644 --- a/tests/js-units/node/state/symbology.test.js +++ b/tests/js-units/node/state/symbology.test.js @@ -1,7 +1,9 @@ import { expect } from 'chai'; +import { readFileSync } from 'fs'; + import { ValidationError } from '../../../../assets/src/modules/Errors.js'; -import { base64png, base64pngNullData, BaseIconSymbology, LayerIconSymbology, SymbolIconSymbology, BaseSymbolsSymbology, LayerSymbolsSymbology, LayerGroupSymbology, buildLayerSymbology } from '../../../../assets/src/modules/state/Symbology.js'; +import { base64png, base64pngNullData, BaseIconSymbology, LayerIconSymbology, SymbolIconSymbology, SymbolRuleSymbology, BaseSymbolsSymbology, LayerSymbolsSymbology, LayerGroupSymbology, buildLayerSymbology } from '../../../../assets/src/modules/state/Symbology.js'; describe('BaseIconSymbology', function () { it('Simple', function () { @@ -89,14 +91,30 @@ describe('SymbolIconSymbology', function () { "ruleKey":"0", "checked":true }) - expect(icon).to.be.instanceOf(BaseIconSymbology) - expect(icon).to.be.instanceOf(SymbolIconSymbology) + expect(icon) + .to.be.instanceOf(BaseIconSymbology) + .that.be.instanceOf(SymbolIconSymbology) expect(icon.icon).to.have.string(base64png) expect(icon.title).to.be.eq('category 1') expect(icon.ruleKey).to.be.eq('0') expect(icon.checked).to.be.true - expect(icon.minScaleDenominator).to.be.eq(-1) - expect(icon.maxScaleDenominator).to.be.eq(-1) + }) + + it('Null data icon', function () { + const icon = new SymbolIconSymbology({ + "title": "1:25000", + "ruleKey": "{1a0c9345-0ffd-4743-bf78-82ca39f64d40}", + "checked": true, + "parentRuleKey": "{a5359e9e-eecc-437d-a636-38237822ea81}" + }) + expect(icon) + .to.be.instanceOf(BaseIconSymbology) + .that.be.instanceOf(SymbolIconSymbology) + expect(icon.icon).to.have.string(base64png) + expect(icon.icon).to.have.string(base64pngNullData) + expect(icon.title).to.be.eq('1:25000') + expect(icon.ruleKey).to.be.eq('{1a0c9345-0ffd-4743-bf78-82ca39f64d40}') + expect(icon.checked).to.be.true }) it('Event', function () { @@ -133,6 +151,83 @@ describe('SymbolIconSymbology', function () { }) }) +describe('SymbolRuleSymbology', function () { + it('Valid', function () { + const icon = new SymbolRuleSymbology({ + "icon":"iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAU0lEQVQ4jWNgGAV0A4z4JJWVlf8j8+\/evYtTPQs+Q9YelkMRC7Zl+I\/LMKyC2AxBGPYIq8uYcLmIVDBEDLp79y5jsO0jkgwiKfphlpBkwyigPgAATTcaN5pMVDUAAAAASUVORK5CYII=", + "title":"category 1", + "ruleKey":"0", + "checked":true + }) + expect(icon) + .to.be.instanceOf(BaseIconSymbology) + .that.be.instanceOf(SymbolIconSymbology) + .that.be.instanceOf(SymbolRuleSymbology) + expect(icon.icon).to.have.string(base64png) + expect(icon.title).to.be.eq('category 1') + expect(icon.ruleKey).to.be.eq('0') + expect(icon.checked).to.be.true + expect(icon.minScaleDenominator).to.be.eq(-1) + expect(icon.maxScaleDenominator).to.be.eq(-1) + expect(icon.parentRuleKey).to.be.eq('') + }) + + it('Null data icon', function () { + const icon = new SymbolRuleSymbology({ + "title": "1:25000", + "ruleKey": "{1a0c9345-0ffd-4743-bf78-82ca39f64d40}", + "checked": true, + "parentRuleKey": "{a5359e9e-eecc-437d-a636-38237822ea81}" + }) + expect(icon) + .to.be.instanceOf(BaseIconSymbology) + .that.be.instanceOf(SymbolIconSymbology) + .that.be.instanceOf(SymbolRuleSymbology) + expect(icon.icon) + .to.have.string(base64png) + .that.have.string(base64pngNullData) + expect(icon.title).to.be.eq('1:25000') + expect(icon.ruleKey).to.be.eq('{1a0c9345-0ffd-4743-bf78-82ca39f64d40}') + expect(icon.checked).to.be.true + expect(icon.minScaleDenominator).to.be.eq(-1) + expect(icon.maxScaleDenominator).to.be.eq(-1) + expect(icon.parentRuleKey).to.be.eq('{a5359e9e-eecc-437d-a636-38237822ea81}') + }) + + it('Event', function () { + it('Valid', function () { + const icon = new SymbolRuleSymbology({ + "icon":"iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAU0lEQVQ4jWNgGAV0A4z4JJWVlf8j8+\/evYtTPQs+Q9YelkMRC7Zl+I\/LMKyC2AxBGPYIq8uYcLmIVDBEDLp79y5jsO0jkgwiKfphlpBkwyigPgAATTcaN5pMVDUAAAAASUVORK5CYII=", + "title":"category 1", + "ruleKey":"0", + "checked":true + }) + expect(icon).to.be.instanceOf(SymbolRuleSymbology) + let symbologyChangedEvt = null; + icon.addListener(evt => { + symbologyChangedEvt = evt + }, 'symbol.checked.changed'); + expect(symbologyChangedEvt).to.not.be.null + expect(symbologyChangedEvt.title).to.be.eq('category 1') + expect(symbologyChangedEvt.ruleKey).to.be.eq('0') + expect(symbologyChangedEvt.checked).to.be.true + }) + }) + + it('Failing required properties', function () { + try { + new SymbolRuleSymbology({ + "icon":"iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAU0lEQVQ4jWNgGAV0A4z4JJWVlf8j8+\/evYtTPQs+Q9YelkMRC7Zl+I\/LMKyC2AxBGPYIq8uYcLmIVDBEDLp79y5jsO0jkgwiKfphlpBkwyigPgAATTcaN5pMVDUAAAAASUVORK5CYII=", + "title":"category 1", + }) + } catch (error) { + expect(error.name).to.be.eq('ValidationError') + expect(error.message).to.be.eq('The cfg object has not enough properties compared to required!\n- The cfg properties: icon,title\n- The required properties: icon,title,ruleKey,checked') + expect(error).to.be.instanceOf(ValidationError) + } + }) +}) + describe('BaseSymbolsSymbology', function () { it('Valid', function () { const symbols = new BaseSymbolsSymbology({ @@ -176,7 +271,7 @@ describe('BaseSymbolsSymbology', function () { }) describe('LayerSymbolsSymbology', function () { - it('Valid', function () { + it('categorizedSymbol', function () { const symbology = new LayerSymbolsSymbology({ "symbols":[{ "icon":"iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAU0lEQVQ4jWNgGAV0A4z4JJWVlf8j8+\/evYtTPQs+Q9YelkMRC7Zl+I\/LMKyC2AxBGPYIq8uYcLmIVDBEDLp79y5jsO0jkgwiKfphlpBkwyigPgAATTcaN5pMVDUAAAAASUVORK5CYII=", @@ -197,16 +292,251 @@ describe('LayerSymbolsSymbology', function () { expect(symbology).to.be.instanceOf(LayerSymbolsSymbology) expect(symbology.title).to.be.eq('layer_legend_categorized') expect(symbology.name).to.be.eq('layer_legend_categorized') + expect(symbology.legendOn).to.be.true expect(symbology.childrenCount).to.be.eq(2) expect(symbology.children).to.be.an('array').that.have.lengthOf(2) const symbologyChildren = symbology.children - expect(symbologyChildren[0]).to.be.instanceOf(BaseIconSymbology).that.be.instanceOf(SymbolIconSymbology) - expect(symbologyChildren[1]).to.be.instanceOf(BaseIconSymbology).that.be.instanceOf(SymbolIconSymbology) + expect(symbologyChildren[0]) + .to.be.instanceOf(BaseIconSymbology) + .that.be.instanceOf(SymbolIconSymbology) + .that.not.be.instanceOf(SymbolRuleSymbology) + expect(symbologyChildren[1]) + .to.be.instanceOf(BaseIconSymbology) + .that.be.instanceOf(SymbolIconSymbology) + .that.not.be.instanceOf(SymbolRuleSymbology) const symbologyGetChildren = symbology.getChildren() expect(symbologyGetChildren.next().value).to.be.instanceOf(SymbolIconSymbology).that.be.eq(symbologyChildren[0]) expect(symbologyGetChildren.next().value).to.be.instanceOf(SymbolIconSymbology).that.be.eq(symbologyChildren[1]) + expect(symbologyGetChildren.next().value).to.be.undefined + + expect(symbology.wmsParameters('layer_legend_categorized')).to.be.an('object').that.be.deep.eq({}) + symbologyChildren[0].checked = false + expect(symbology.legendOn).to.be.true + expect(symbology.wmsParameters('layer_legend_categorized')).to.be.an('object').that.be.deep.eq({ + "LEGEND_ON": "layer_legend_categorized:1", + "LEGEND_OFF": "layer_legend_categorized:0" + }) + symbologyChildren[1].checked = false + expect(symbology.legendOn).to.be.false + expect(symbology.wmsParameters('layer_legend_categorized')).to.be.an('object').that.be.deep.eq({ + "LEGEND_ON": "layer_legend_categorized:", + "LEGEND_OFF": "layer_legend_categorized:0,1" + }) + symbologyChildren[0].checked = true + expect(symbology.legendOn).to.be.true + expect(symbology.wmsParameters('layer_legend_categorized')).to.be.an('object').that.be.deep.eq({ + "LEGEND_ON": "layer_legend_categorized:0", + "LEGEND_OFF": "layer_legend_categorized:1" + }) + symbologyChildren[1].checked = true + expect(symbology.legendOn).to.be.true + expect(symbology.wmsParameters('layer_legend_categorized')).to.be.an('object').that.be.deep.eq({}) + }) + + it('RuleRenderer', function () { + const legend = JSON.parse(readFileSync('./data/quickosm-road-legend.json', 'utf8')); + expect(legend).to.not.be.undefined + expect(legend.nodes).to.be.an('array').that.have.length(1) + + const symbology = new LayerSymbolsSymbology(legend.nodes[0]) + expect(symbology).to.be.instanceOf(BaseSymbolsSymbology) + expect(symbology).to.be.instanceOf(LayerSymbolsSymbology) + expect(symbology.title).to.be.eq('road') + expect(symbology.name).to.be.eq('road') + expect(symbology.legendOn).to.be.true + expect(symbology.childrenCount).to.be.eq(3) + expect(symbology.children).to.be.an('array').that.have.length(3) + + const symbologyChildren = symbology.children + expect(symbologyChildren[0]) + .to.be.instanceOf(BaseIconSymbology) + .that.be.instanceOf(SymbolIconSymbology) + .that.be.instanceOf(SymbolRuleSymbology) + expect(symbologyChildren[0].title).to.be.eq('1:25000') + expect(symbologyChildren[0].minScaleDenominator).to.be.eq(1) + expect(symbologyChildren[0].maxScaleDenominator).to.be.eq(25000) + expect(symbologyChildren[0].checked).to.be.true + expect(symbologyChildren[0].legendOn).to.be.true + expect(symbologyChildren[0].childrenCount).to.be.eq(10) + expect(symbologyChildren[0].children).to.be.an('array').that.have.length(10) + const symbologyChildrenFirstChildren = symbologyChildren[0].children + expect(symbologyChildrenFirstChildren[0]) + .to.be.instanceOf(BaseIconSymbology) + .that.be.instanceOf(SymbolIconSymbology) + .that.be.instanceOf(SymbolRuleSymbology) + expect(symbologyChildrenFirstChildren[0].title).to.be.eq('Motorway Link') + expect(symbologyChildrenFirstChildren[0].minScaleDenominator).to.be.eq(-1) + expect(symbologyChildrenFirstChildren[0].maxScaleDenominator).to.be.eq(-1) + expect(symbologyChildrenFirstChildren[0].checked).to.be.true + expect(symbologyChildrenFirstChildren[0].parentRule).to.not.be.null + expect(symbologyChildrenFirstChildren[0].parentRule.legendOn).to.be.true + expect(symbologyChildrenFirstChildren[0].legendOn).to.be.true + expect(symbologyChildrenFirstChildren[0].childrenCount).to.be.eq(0) + expect(symbologyChildrenFirstChildren[0].children).to.be.an('array').that.have.length(0) + expect(symbologyChildren[1]) + .to.be.instanceOf(BaseIconSymbology) + .that.be.instanceOf(SymbolIconSymbology) + .that.be.instanceOf(SymbolRuleSymbology) + expect(symbologyChildren[1].title).to.be.eq('25k to 50k') + expect(symbologyChildren[1].minScaleDenominator).to.be.eq(25001) + expect(symbologyChildren[1].maxScaleDenominator).to.be.eq(50000) + expect(symbologyChildren[1].checked).to.be.true + expect(symbologyChildren[1].legendOn).to.be.true + expect(symbologyChildren[1].childrenCount).to.be.eq(1) + expect(symbologyChildren[1].children).to.be.an('array').that.have.length(1) + expect(symbologyChildren[2]) + .to.be.instanceOf(BaseIconSymbology) + .that.be.instanceOf(SymbolIconSymbology) + .that.be.instanceOf(SymbolRuleSymbology) + expect(symbologyChildren[2].title).to.be.eq('50k +') + expect(symbologyChildren[2].minScaleDenominator).to.be.eq(50001) + expect(symbologyChildren[2].maxScaleDenominator).to.be.eq(10000000) + expect(symbologyChildren[2].checked).to.be.true + expect(symbologyChildren[2].legendOn).to.be.true + expect(symbologyChildren[2].childrenCount).to.be.eq(3) + expect(symbologyChildren[2].children).to.be.an('array').that.have.length(3) + + const symbologyGetChildren = symbology.getChildren() + expect(symbologyGetChildren.next().value).to.be.instanceOf(SymbolIconSymbology).that.be.eq(symbologyChildren[0]) + expect(symbologyGetChildren.next().value).to.be.instanceOf(SymbolIconSymbology).that.be.eq(symbologyChildren[1]) + expect(symbologyGetChildren.next().value).to.be.instanceOf(SymbolIconSymbology).that.be.eq(symbologyChildren[2]) + expect(symbologyGetChildren.next().value).to.be.undefined + + expect(symbology.wmsParameters('road')).to.be.an('object').that.be.deep.eq({}) + symbologyChildren[0].checked = false + expect(symbologyChildren[0].legendOn).to.be.false + expect(symbologyChildrenFirstChildren[0].legendOn).to.be.false + expect(symbologyChildren[1].legendOn).to.be.true + expect(symbologyChildren[2].legendOn).to.be.true + expect(symbology.legendOn).to.be.true + expect(symbology.wmsParameters('road')).to.be.an('object').that.be.deep.eq({ + "LEGEND_ON": "road:" + [ + "{1be63a51-ccb6-4c5c-acdf-fdee5f8408c1}", + "{b3334f5f-daaf-4dc2-a2dc-f5f8485a1b37}", + "{1be63a51-ccb6-4c5c-acdf-fdee5f8408c1}", + "{97c219cb-9b1a-4a9d-bba5-cfe3006fe48a}", + "{2df87245-1aca-463a-a8eb-a5f2ea287a44}", + "{1be63a51-ccb6-4c5c-acdf-fdee5f8408c1}", + ].join(','), + "LEGEND_OFF": "road:" + [ + "{1a0c9345-0ffd-4743-bf78-82ca39f64d40}", + "{a9fac601-7bc7-4150-9783-19d7827b2ef8}", + "{e2c3dbec-7274-4149-8b0b-959b2e758b9a}", + "{78db6f50-70cc-417d-995d-97ad897bf52b}", + "{26f18044-95a7-4170-9ce3-0137ce4a2232}", + "{f215859b-f963-4872-8f4b-b2e39e5f0c35}", + "{aac3fe77-b7ff-4c47-8f28-c33de0dc4b2b}", + "{960d07d3-ac1a-40c8-8f2e-1b499f3ccafc}", + "{303a360c-638b-4c9f-adee-eff33d3e95f1}", + "{c63b61f8-f9e5-4a57-9231-9001ffd07bad}", + "{245c23be-e45f-4f80-9ea4-f1676315f178}", + ].join(',') + }) + + symbologyChildren[0].checked = true + expect(symbologyChildren[0].legendOn).to.be.true + expect(symbologyChildrenFirstChildren[0].legendOn).to.be.true + expect(symbologyChildren[1].legendOn).to.be.true + expect(symbologyChildren[2].legendOn).to.be.true + expect(symbology.legendOn).to.be.true + expect(symbology.wmsParameters('road')).to.be.an('object').that.be.deep.eq({}) + + symbologyChildrenFirstChildren[0].checked = false + expect(symbologyChildren[0].legendOn).to.be.true + expect(symbologyChildrenFirstChildren[0].legendOn).to.be.false + expect(symbologyChildren[1].legendOn).to.be.true + expect(symbologyChildren[2].legendOn).to.be.true + expect(symbology.legendOn).to.be.true + expect(symbology.wmsParameters('road')) + .to.be.an('object') + .that.have.all.keys(["LEGEND_ON", "LEGEND_OFF"]) + const CheckForAll = bits => string => bits.every(bit => string.includes(bit)); + expect(symbology.wmsParameters('road').LEGEND_ON).to.satisfy(CheckForAll([ + "road:", + "{1a0c9345-0ffd-4743-bf78-82ca39f64d40}", + "{e2c3dbec-7274-4149-8b0b-959b2e758b9a}", + "{78db6f50-70cc-417d-995d-97ad897bf52b}", + "{26f18044-95a7-4170-9ce3-0137ce4a2232}", + "{f215859b-f963-4872-8f4b-b2e39e5f0c35}", + "{aac3fe77-b7ff-4c47-8f28-c33de0dc4b2b}", + "{960d07d3-ac1a-40c8-8f2e-1b499f3ccafc}", + "{303a360c-638b-4c9f-adee-eff33d3e95f1}", + "{c63b61f8-f9e5-4a57-9231-9001ffd07bad}", + "{245c23be-e45f-4f80-9ea4-f1676315f178}", + "{1be63a51-ccb6-4c5c-acdf-fdee5f8408c1}", + "{b3334f5f-daaf-4dc2-a2dc-f5f8485a1b37}", + "{1be63a51-ccb6-4c5c-acdf-fdee5f8408c1}", + "{97c219cb-9b1a-4a9d-bba5-cfe3006fe48a}", + "{2df87245-1aca-463a-a8eb-a5f2ea287a44}", + "{1be63a51-ccb6-4c5c-acdf-fdee5f8408c1}", + ])).and.to.not.contains("{a9fac601-7bc7-4150-9783-19d7827b2ef8}") + expect(symbology.wmsParameters('road').LEGEND_OFF).to.be.eq("road:" + [ + "{a9fac601-7bc7-4150-9783-19d7827b2ef8}", + ].join(',') + ) + + symbologyChildren[0].checked = false + symbologyChildren[1].checked = false + symbologyChildren[2].checked = false + expect(symbologyChildren[0].legendOn).to.be.false + expect(symbologyChildrenFirstChildren[0].legendOn).to.be.false + expect(symbologyChildren[1].legendOn).to.be.false + expect(symbologyChildren[2].legendOn).to.be.false + expect(symbology.legendOn).to.be.false + expect(symbology.wmsParameters('road').LEGEND_ON).to.be.eq("road:") + expect(symbology.wmsParameters('road').LEGEND_OFF).to.satisfy(CheckForAll([ + "road:", + "{1a0c9345-0ffd-4743-bf78-82ca39f64d40}", + "{a9fac601-7bc7-4150-9783-19d7827b2ef8}", + "{e2c3dbec-7274-4149-8b0b-959b2e758b9a}", + "{78db6f50-70cc-417d-995d-97ad897bf52b}", + "{26f18044-95a7-4170-9ce3-0137ce4a2232}", + "{f215859b-f963-4872-8f4b-b2e39e5f0c35}", + "{aac3fe77-b7ff-4c47-8f28-c33de0dc4b2b}", + "{960d07d3-ac1a-40c8-8f2e-1b499f3ccafc}", + "{303a360c-638b-4c9f-adee-eff33d3e95f1}", + "{c63b61f8-f9e5-4a57-9231-9001ffd07bad}", + "{245c23be-e45f-4f80-9ea4-f1676315f178}", + "{1be63a51-ccb6-4c5c-acdf-fdee5f8408c1}", + "{b3334f5f-daaf-4dc2-a2dc-f5f8485a1b37}", + "{1be63a51-ccb6-4c5c-acdf-fdee5f8408c1}", + "{97c219cb-9b1a-4a9d-bba5-cfe3006fe48a}", + "{2df87245-1aca-463a-a8eb-a5f2ea287a44}", + "{1be63a51-ccb6-4c5c-acdf-fdee5f8408c1}", + ])) + + symbologyChildren[0].checked = true + expect(symbologyChildren[0].legendOn).to.be.true + expect(symbologyChildrenFirstChildren[0].legendOn).to.be.false + expect(symbologyChildren[1].legendOn).to.be.false + expect(symbologyChildren[2].legendOn).to.be.false + expect(symbology.legendOn).to.be.true + expect(symbology.wmsParameters('road').LEGEND_OFF).to.satisfy(CheckForAll([ + "road:", + "{a9fac601-7bc7-4150-9783-19d7827b2ef8}", + "{1be63a51-ccb6-4c5c-acdf-fdee5f8408c1}", + "{b3334f5f-daaf-4dc2-a2dc-f5f8485a1b37}", + "{1be63a51-ccb6-4c5c-acdf-fdee5f8408c1}", + "{97c219cb-9b1a-4a9d-bba5-cfe3006fe48a}", + "{2df87245-1aca-463a-a8eb-a5f2ea287a44}", + "{1be63a51-ccb6-4c5c-acdf-fdee5f8408c1}", + ]), symbology.wmsParameters('road').LEGEND_OFF) + expect(symbology.wmsParameters('road').LEGEND_ON).to.satisfy(CheckForAll([ + "road:", + "{1a0c9345-0ffd-4743-bf78-82ca39f64d40}", + "{e2c3dbec-7274-4149-8b0b-959b2e758b9a}", + "{78db6f50-70cc-417d-995d-97ad897bf52b}", + "{26f18044-95a7-4170-9ce3-0137ce4a2232}", + "{f215859b-f963-4872-8f4b-b2e39e5f0c35}", + "{aac3fe77-b7ff-4c47-8f28-c33de0dc4b2b}", + "{960d07d3-ac1a-40c8-8f2e-1b499f3ccafc}", + "{303a360c-638b-4c9f-adee-eff33d3e95f1}", + "{c63b61f8-f9e5-4a57-9231-9001ffd07bad}", + "{245c23be-e45f-4f80-9ea4-f1676315f178}", + ]), symbology.wmsParameters('road').LEGEND_ON) + .and.to.not.contains("{a9fac601-7bc7-4150-9783-19d7827b2ef8}") }) it('Failing required properties', function () {