Skip to content

Commit

Permalink
TERR-53
Browse files Browse the repository at this point in the history
- added reporters to karma config
- refactored santize functions into utils module
- narrowed scope of coverage testing to non-d3, non-leaflet, non-pubsub code
- corrected imports of santize functions
- refactored render function to use resolvePath
- removed resolveObjPath fn from templates module
- removed topologyTools module
- added some jsdoc inlinedocs for utils module
- refactored util fn name from getUrlSearchParams to getUrlQueryParams
  • Loading branch information
sanchezelton committed Aug 23, 2024
1 parent 04963b9 commit 46a1b5b
Show file tree
Hide file tree
Showing 8 changed files with 400 additions and 66 deletions.
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
</script>

<script type="module">
import { sanitizeTopology } from "./src/components/lib/topologyTools.js"
import { sanitizeTopology } from "./src/components/lib/utils.js"
var parsedData = {};
var lavender = "rgb(202, 149, 229)"
var topology = [
Expand Down
19 changes: 14 additions & 5 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module.exports = function( config ) {
config.set( {
frameworks: [
"mocha",
"should",
"should"
],

files: [
Expand All @@ -20,16 +20,25 @@ module.exports = function( config ) {
exclude: [
"src/components/lib/leaflet.js",
"src/components/lib/dataParser.js",
"src/components/old/*"
],

browsers: ["ChromeHeadless"],

singleRun: false,

preprocessors: {
'**/*.js': ['coverage'],
'**/*.ts': ['coverage']
}
'src/components/lib/!(d3\.min|leaflet\.esm|leaflet|pubsub).js': ['coverage'],
'src/components/lib/leaflet.global.js': ['coverage'],
'src/components/hoc/*.tsx': ['coverage'],
'src/components/css/*.js': ['coverage'],
'src/components/*.tsx': ['coverage'],
'src/components/*.js': ['coverage'],
'src/*.tsx': ['coverage'],
'src/*.ts': ['coverage'],
'src/*.js': ['coverage'],
},

// coverage reporter generates the coverage
reporters: ['progress', 'coverage'],
} );
};
2 changes: 1 addition & 1 deletion src/MapPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { Component } from 'react';
import { PanelProps, createTheme, DataFrameView, getValueFormat, EventBus, GrafanaTheme2 } from '@grafana/data';
import { MapOptions } from './types';
import { parseData } from './components/lib/dataParser';
import { sanitizeTopology } from './components/lib/topologyTools';
import { sanitizeTopology } from './components/lib/utils';
import './components/MapCanvas.component.js';
import { PubSub } from './components/lib/pubsub.js';
import { locationService } from '@grafana/runtime';
Expand Down
2 changes: 1 addition & 1 deletion src/components/MapCanvas.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export class MapCanvas extends BindableHTMLElement {
}
this.maybeFetchOptions();

const params = utils.getUrlSearchParams();
const params = utils.getUrlQueryParams();
if (
params.editPanel === null ||
params.editPanel === undefined ||
Expand Down
12 changes: 3 additions & 9 deletions src/components/lib/templates.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
const TEMPLATE_REGEX = /\${[^{]+}/g;

// copied from Matt Browne's answer https://stackoverflow.com/questions/29182244/convert-a-string-to-a-template-string
// functions renamed slightly for readability
import { resolvePath } from './utils.js';

//get the specified property or nested property of an object
function resolveObjPath(path, obj, fallback = '') {
return path.split('.').reduce((res, key) => res[key] || fallback, obj);
}
const TEMPLATE_REGEX = /\${[^{]+}/g;

export function render(template, variables, fallback) {
return template.replace(TEMPLATE_REGEX, (match) => {
const path = match.slice(2, -1).trim();
return resolveObjPath(path, variables, fallback);
return resolvePath(path, variables, fallback);
});
}
42 changes: 0 additions & 42 deletions src/components/lib/topologyTools.js

This file was deleted.

109 changes: 103 additions & 6 deletions src/components/lib/utils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
export const LAYER_LIMIT = 3;

export function getUrlSearchParams() {
/**
* Defines delimiters for object prop paths when using resolvePath and setPath.
* @var {RegExp}
*/
const PATH_DELIMITER_REGEXP = /[\.\[\]\'\"]/;

/**
* Retrives query parameters in the URL from the browser's location as an
* object with key-value pairs matching those of the URL parameters, with
* any URL encoded characters decoded.
*
* @returns {{[queryKey: string]: any}]
*/
export function getUrlQueryParams() {
const search = window.location.search.substring(1);
const searchParamsSegments = search.split('&');
let params = {};
Expand All @@ -24,6 +37,9 @@ export function getUrlSearchParams() {
return params;
}

/**
* Schema for a topology.
*/
const schema = {
type: 'object',
properties: {
Expand Down Expand Up @@ -58,7 +74,12 @@ const schema = {
additionalProperties: true,
};

// helper function for JSON validation: works on arrays
/**
* helper function for JSON validation: works on arrays
*
* @param {} itemSchema
* @param {} data
*/
const validateArray = function(itemSchema, data){
var output = { 'valid': true, errorDetails: {} }
for(var i=0; i<data.length; i++){
Expand All @@ -73,6 +94,15 @@ const validateArray = function(itemSchema, data){
}

// main JSON validation function: heavily recursive
/**
* Validates a given object against a provided JSON schema.
*
* @param {any} schema
* @param {any} data
* @returns {{ valid: boolean, errorDetails: string }}} An object with a prop valid set to true if validation passes.
* A prop errorDetails contains an empty string if passing, otherwise
* it contains the reason for validation failure.
*/
const validate = function(schema, data){
// do type check
var output = { "valid": true, "errorDetails": "" }
Expand Down Expand Up @@ -122,6 +152,14 @@ const validate = function(schema, data){
return output;
}

/**
* Returns a tuple, of which the first element is true if data passes validation for a JSON schema,
* false otherwise. A false value will replace the second element (which defaults to simply a string 'valid' upon
* validation passing), to information regarding the error.
*
* @param {any} data The data to validate
* @returns {[boolean, any]}
*/
export function testJsonSchema(data) {
const {valid, errorDetails} = validate(schema, data);
if (valid) {
Expand All @@ -131,16 +169,32 @@ export function testJsonSchema(data) {
}
}

/**
* Gets the specified property or nested property of an object
*
* @param {object} object The object from which to get the value using path
* @param {string} path The specified or nested property from which to get the value in object
* @param {null|any} defaultValue Optional. The default value to return in the case that the specified or nested property
* is not defined. Defaults to null.
* @returns {any} The value of the specified or nested property given path upon object.
*/
export function resolvePath(object, path, defaultValue=null){
return path
.split(/[\.\[\]\'\"]/)
.split(PATH_DELIMITER_REGEXP)
.filter(p => p) // remove empty splits
.reduce((o, p) => o ? o[p] : defaultValue, object)
}

/**
* Sets a newValue upon the specified property or nested property of an object
*
* @param {object} object The object in which to set a new value using path
* @param {string} path The specified or nested property at which to set the value
* @param {any} newValue The value to set at path within object.
*/
export function setPath(object, path, newValue){
let splitPath = path
.split(/[\.\[\]\'\"]/)
.split(PATH_DELIMITER_REGEXP)
.filter(p => p)
let o = object;
let lastItem = splitPath.pop();
Expand All @@ -152,7 +206,7 @@ export function setPath(object, path, newValue){

try {
const Utils = {
getUrlSearchParams,
getUrlQueryParams,
schema,
validateArray,
validate,
Expand All @@ -164,4 +218,47 @@ try {
module.exports.Utils = Utils;
exports.Utils = Utils;
} catch (e) {
}
}

export function sanitizeNode(node){
let output = {
name: node.name,
meta: node.meta,
coordinate: node.coordinate,
};
if(node.children && node.children.length > 0){
output["children"] = node.children;
}
return output;
};

export function sanitizeEdge(edge){
return {
name: edge.name,
meta: edge.meta,
coordinates: edge.coordinates,
children: edge.children,
};
};

export function sanitizeTopology(layerData) {
return {
name: layerData.name,
layer: layerData.layer,
pathLayout: layerData.pathLayout,
edges:
(layerData.edges &&
layerData.edges.reduce((output, edge) => {
output.push(sanitizeEdge(edge));
return output;
}, [])) ||
[],
nodes:
(layerData.nodes &&
layerData.nodes.reduce((output, node) => {
output.push(sanitizeNode(node));
return output;
}, [])) ||
[],
};
};
Loading

0 comments on commit 46a1b5b

Please sign in to comment.