Skip to content

Commit

Permalink
Merge pull request #52 from esnet/feature-requests
Browse files Browse the repository at this point in the history
Feature requests: Traffic Matching by Node and Sidebar Toggle in full-URL-configuration mode
  • Loading branch information
jkafader-esnet authored Dec 19, 2024
2 parents c860fbc + 5abc0ae commit 2de4b08
Show file tree
Hide file tree
Showing 10 changed files with 251 additions and 27 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
run: yarn build

- name: Test components
run: make test:component
run: make test-component

- name: Install E2E dependencies
run: |
Expand All @@ -57,7 +57,7 @@ jobs:
- name: E2E testing
run: |
make test:e2e
make test-e2e
- name: Check for backend
id: check-for-backend
Expand Down
3 changes: 2 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ yarn-error.log
.vitest
playwright-report
.auth
test-results
test-results
test/dist
31 changes: 10 additions & 21 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,7 @@ prod:
make build

.PHONY: build
build:
yarn test
yarn test:react
@echo "Waiting for container to spin up..."
@sleep $(SPINUP_SLEEP_T)
@echo "Starting E2E Tests..."
yarn e2e
build: test
yarn build
yarn sign "--rootUrls" https://dashboard.stardust.es.net/,https://gf.gc1.dev-stage.stardust.es.net/
yarn run "build_dts"
Expand All @@ -47,32 +41,27 @@ compose:
# get instances info
sleep 2
docker inspect $(CONTAINER_NAME) > $(PROJECT_DIR)/e2e/grafana-docker.json

.PHONY: test
test: compose
@echo "Starting component tests..."
yarn test
yarn test:react
@echo "Waiting for container to spin up..."
@sleep $(SPINUP_SLEEP_T)
@echo "Starting E2E Tests..."
yarn e2e
test: compose test-component test-e2e

.PHONY: test\:component
test\:component:
.PHONY: test-component
test-component:
@echo "Starting component tests..."
yarn test
yarn test:react
rm -R test/dist/*

.PHONY: test\:e2e
test\:e2e: compose
.PHONY: test-e2e
test-e2e: compose
# run e2e tests
@echo "Waiting for container to spin up..."
@sleep $(SPINUP_SLEEP_T)
@echo "Starting E2E Tests..."
yarn run e2e

.PHONY: test\:ui
test\:ui: compose
.PHONY: test-ui
test-ui: compose
# run e2e tests, but with ui
@echo "Starting E2E tests in Playwright UI..."
yarn run e2e:ui
Expand Down
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ <h1>Embedded Map Demonstration page</h1>
<a href='?'>Edit Mode Off</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

<a href="/autodetect.html">Autodetect Demo</a>
<a href="/node_matching.html">Node Traffic-matching Demo</a>
</td>
<tr>
<td colspan='2' style='width:80%;'>
Expand Down
162 changes: 162 additions & 0 deletions node_matching.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
<html>
<head>
<title>Embedded Map Demonstration Page</title>
<script type="module">
import "./src/components/MapCanvas.component.js";
</script>


</head>
<body>
<table style="width:100%;">
<tr>
<th colspan="3">
<h1>Demonstration Page: Traffic Matching by Node Only</h1>
</th>
<tr>
<td style="width:20%">
<a href="/">Main Demonstration Page</a>&nbsp;&nbsp;
</td>
<tr>
<td colspan="2" style="width:80%;">
<div id="mapContainer">
<esnet-map-canvas id="mapCanvas" height="400">
</esnet-map-canvas>
</div>
</td>
</tr>
<tr>
<td style="width:40%">Map Data</td>
<td style="width:40%">Map Options</td>
<td style="width:20%"></td>
</tr>
<tr>
<td id="mapDataContainer">
<textarea id="trafficText" style="height:300px; width:100%;">
</textarea>
</td>
<td id="mapToplogyContainer">
<textarea id="topologyText" style="height:300px; width:100%">
</textarea>
</td>
<td id="mapOptionsContainer">
<textarea id="optionsText" style="height:300px; width:100%;">
</textarea>
</td>
</tr>
</table>

<script type="module">
import { sanitizeTopology } from "./src/components/lib/topologyTools.js"
import { signals } from "./src/signals.js"
var parsedData = {};
var lavender = "rgb(202, 149, 229)";
var options = {
"initialViewStrategy": "viewport",
"showSidebar": true,
"showViewControls": true,
"enableEdgeAnimation": true,
"enableNodeAnimation": true,
"enableScrolling": true,
"enableEditing": true,
"background":"#EDEDED",
"multiLayerNodeSnap": false,
"topologySource": "json",
"viewport": {
"top": 33,
"left": -141,
"bottom": 43,
"right": -41,
"center": {
"lat":38.68,
"lng":-96.96,
},
"zoom":3.5
},
"tileset": {
// global options
// this string corresponds to options in RenderMap.js
"geographic":"esri.shaded",
// this string (or null) corresponds to options in RenderMap.js
"boundaries":null,
// this string (or null) corresponds to options in RenderMap.js
"labels": null,
},
"layers": [
{
// layer 1 rendering options
"visible":true,
"color": lavender,
"endpointId":"names",
"nodeWidth":4,
"edgeWidth":2,
"pathOffset":2,
"srcField": "src_name",
"dstField": "dst_name",
"inboundValueField": "in_bits",
"outboundValueField": "out_bits",
"name":"Nodes Only",
"legend":true,
"nodeThresholds": [{"value": 0, "color": "#E04040"}, {"value": 200000000, "color": "#5bb436"}]
},
]
};
var traffic = [
{"src_latitude":39,"src_longitude":-98,"src_name":"NodeA","in_bits": 16000000, "out_bits": 160000000},
{"src_latitude":42,"src_longitude":-102,"src_name":"NodeB","in_bits": 320000000, "out_bits": 32000000},
];
var topology = [{
"edges": [],
"nodes": [
{ "name": "NodeA", "coordinate": [39, -98], "meta": {
"svg": "<g><circle r='15' /><text x='20' y='4' stroke='none' fill='black'>NodeA</text></g>"
}
},
{ "name": "NodeB", "coordinate": [42, -102], "meta": {
"svg": "<g><circle r='15' /><text x='20' y='4' stroke='none' fill='black'>NodeB</text></g>"
}
}
]
}];
var canvas = document.getElementById("mapCanvas");
var optionsElem = document.getElementById("optionsText");
var topologyElem = document.getElementById("topologyText");
var trafficElem = document.getElementById("trafficText");

console.log("Available signals:", signals);

const receiveOptionsUpdates = function(options){
optionsElem.value = JSON.stringify(options, null, " ");
}
const receiveTrafficUpdates = function(traffic){
trafficElem.value = JSON.stringify(traffic, null, " ");
}
const receiveTopologyUpdates = function(topology){
var cleanTopology = [];
for(var i=0; i<3; i++){
if(topology[i]){
cleanTopology[i] = sanitizeTopology(topology[i]);
}
}
topologyElem.value = JSON.stringify(cleanTopology, null, " ");
}
canvas.listen(signals.TRAFFIC_UPDATED, receiveTrafficUpdates);
canvas.listen(signals.TOPOLOGY_UPDATED, receiveTopologyUpdates);
canvas.listen(signals.OPTIONS_UPDATED, receiveOptionsUpdates);

canvas.setTopology(topology);
canvas.setOptions(options);
canvas.setTraffic(traffic);

trafficElem.onchange = function(event){
canvas.setTraffic(JSON.parse(event.target.value));
}

optionsElem.onchange = function(event){
canvas.setOptions(JSON.parse(event.target.value));
}


</script>
</body>
</html>
7 changes: 7 additions & 0 deletions src/components/MapCanvas.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ export class MapCanvas extends BindableHTMLElement {
"enableNodeAnimation": "masked",
"enableScrolling": "masked",
"showViewControls": "masked",
"showSidebar": "masked",
"thresholds": "masked",
"multiLayerNodeSnap": "masked",
"configurationUrl": "masked",
Expand Down Expand Up @@ -472,6 +473,12 @@ export class MapCanvas extends BindableHTMLElement {
}
// set the traffic sample by single-point match if no match yet. Use forward directionality
if(!targetEdge){ targetEdge = layerTopology.edges[edgeHash[singleIdSelector]] }
// if there's no matching edge, we won't find one.
// still, we must check for the case that we can match this datapoint to a node.
if(!targetEdge && nodeHash.hasOwnProperty(singleIdSelector)){
// in this case, create a dummy edge so we can still do node traffic accounting.
targetEdge = { nodeA: singleIdSelector }
}
// if no match at all, don't mark up this edge with match data.
if(!targetEdge){ return }
targetEdge.azValue = row[values.in];
Expand Down
2 changes: 1 addition & 1 deletion src/components/SideBar.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class SideBar extends BindableHTMLElement {
render() {
if (!this.shadow) {
this.shadow = document.createElement("div");
this.shadow.setAttribute("class", "tight-form-func");
this.shadow.setAttribute("class", "tight-form-func esmap-sidebar");
this.shadow.id = "sidebar-"+this.instanceId;
this.append(this.shadow);
}
Expand Down
8 changes: 7 additions & 1 deletion src/components/lib/pubsub.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,13 @@ const doPublish = function(topic, eventData, messageBus) {
console.debug("publishing event on topic", topic, scopeMessage);
}
var accessor = `${messageBus.instanceId}.lastEvents.${topic}`;
localStorage.setItem(accessor, JSON.stringify(eventData));
try {
localStorage.setItem(accessor, JSON.stringify(eventData));
} catch(e) {
console.error(e);
console.log("received error saving to localStorage. clearing localStorage.");
localStorage.clear();
}
var subscriberData = messageBus.topics[topic];
if (!subscriberData) return;
var subscribers = Object.values(subscriberData);
Expand Down
1 change: 0 additions & 1 deletion src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,6 @@ const options = {
name: 'Show Map Sidebar',
description: 'Show sidebar. If hidden, tooltips will appear on hover.',
category: "View Options",
showIf: { "topologySource": ["autodetect", "json", "layerurls"] },
defaultValue: true,
},

Expand Down
59 changes: 59 additions & 0 deletions test/module.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1697,4 +1697,63 @@ describe( "Class MapCanvas", () => {
let node = canvas.querySelector(".node");
expect(node).toBeTruthy();
})
it("should allow users to show and hide the sidebar even when loading the full configuration from a url", ()=>{
let canvas = document.querySelector("esnet-map-canvas");
let newOptions = JSON.parse(JSON.stringify(canvas.options));

// this data url is a valid base-64 encoded terranova-style response.
let targetUrl = "data:text/plain;charset=utf-8;base64,ew0KICAiaW5pdGlhbFZpZXdTdHJhdGVneSI6ICJzdGF0aWMiLA0KICAibGF0aXR1ZGVWYXIiOiBudWxsLA0KICAibG9uZ2l0dWRlVmFyIjogbnVsbCwNCiAgInZpZXdwb3J0Ijogew0KICAgICJjZW50ZXIiOiB7DQogICAgICAibGF0IjogMzguOTU5LA0KICAgICAgImxuZyI6IC05Ny45OTgNCiAgICB9LA0KICAgICJ0b3AiOiBudWxsLA0KICAgICJsZWZ0IjogbnVsbCwNCiAgICAiYm90dG9tIjogbnVsbCwNCiAgICAicmlnaHQiOiBudWxsLA0KICAgICJ6b29tIjogNA0KICB9LA0KICAiYmFja2dyb3VuZCI6ICIjREREREREIiwNCiAgInRpbGVzZXQiOiB7DQogICAgImdlb2dyYXBoaWMiOiAiYXJjZ2lzIiwNCiAgICAiYm91bmRhcmllcyI6IG51bGwsDQogICAgImxhYmVscyI6IG51bGwNCiAgfSwNCiAgImVkaXRNb2RlIjogZmFsc2UsDQogICJzaG93U2lkZWJhciI6IGZhbHNlLA0KICAic2hvd1ZpZXdDb250cm9scyI6IHRydWUsDQogICJzaG93TGVnZW5kIjogZmFsc2UsDQogICJsZWdlbmRDb2x1bW5MZW5ndGgiOiAzLA0KICAibGVnZW5kUG9zaXRpb24iOiAiYm90dG9tTGVmdCIsDQogICJsZWdlbmREZWZhdWx0QmVoYXZpb3IiOiAibWluaW1pemVkIiwNCiAgImVuYWJsZVNjcm9sbGluZyI6IHRydWUsDQogICJlbmFibGVFZGl0aW5nIjogdHJ1ZSwNCiAgImVuYWJsZU5vZGVBbmltYXRpb24iOiB0cnVlLA0KICAiZW5hYmxlRWRnZUFuaW1hdGlvbiI6IHRydWUsDQogICJ0aHJlc2hvbGRzIjogW10sDQogICJ6SW5kZXhCYXNlIjogMTAsDQogICJsYXllcnMiOiBbDQogICAgew0KICAgICAgInZpc2libGUiOiB0cnVlLA0KICAgICAgIm5hbWUiOiAiTGF5ZXIgMSIsDQogICAgICAiY29sb3IiOiAiI0FBQUFGRiIsDQogICAgICAiZWRnZVdpZHRoIjogMi41LA0KICAgICAgInBhdGhPZmZzZXQiOiAxLjc1LA0KICAgICAgIm5vZGVXaWR0aCI6IDYuNSwNCiAgICAgICJqc29uRnJvbVVybCI6IGZhbHNlLA0KICAgICAgIm1hcGpzb24iOiAieyJub2RlcyI6W3sibmFtZSI6IkIiLCJjb2xvciI6IiNBQUFBRkYiLCJtZXRhIjp7ImRpc3BsYXlfbmFtZSI6IiIsInN2ZyI6IjxzdmcgeT1cIi01XCIgeD1cIi01XCIgd2lkdGg9XCIxMFwiIGhlaWdodD1cIjEwXCIgdmlld0JveD1cIi01LjUgLTUuNSAxMSAxMVwiPjxjaXJjbGUgcj1cIjVcIj48L2NpcmNsZT48L3N2Zz48dGV4dCBzdHlsZT1cImZvbnQtc2l6ZToxMnB4OyBmaWx0ZXI6IGRyb3Atc2hhZG93KDBweCAwcHggMXB4IHJnYmEoMjU1LDI1NSwyNTUsMS4wKSk7XCIgc3Ryb2tlPVwibm9uZVwiIGZpbGw9XCIjMTExMTExXCIgeT1cIjNcIiB4PVwiLTE4XCI+QjwvdGV4dD4iLCJ0ZW1wbGF0ZSI6IiJ9LCJjb29yZGluYXRlIjpbNDQuMDg4LC0xMDguNjMzXSwiY2hpbGRyZW4iOltdLCJzb3J0IjowLCJwYXJlbnRzIjpbXX0seyJuYW1lIjoiQSIsImNvbG9yIjoiI0FBQUFGRiIsIm1ldGEiOnsiZGlzcGxheV9uYW1lIjoiIiwic3ZnIjoiPHN2ZyB5PVwiLTVcIiB4PVwiLTVcIiB3aWR0aD1cIjEwXCIgaGVpZ2h0PVwiMTBcIiB2aWV3Qm94PVwiLTUuNSAtNS41IDExIDExXCI+PGNpcmNsZSByPVwiNVwiPjwvY2lyY2xlPjwvc3ZnPjx0ZXh0IHN0eWxlPVwiZm9udC1zaXplOjEycHg7IGZpbHRlcjogZHJvcC1zaGFkb3coMHB4IDBweCAxcHggcmdiYSgyNTUsMjU1LDI1NSwxLjApKTtcIiBzdHJva2U9XCJub25lXCIgZmlsbD1cIiMxMTExMTFcIiB5PVwiM1wiIHg9XCI4XCI+QTwvdGV4dD4iLCJ0ZW1wbGF0ZSI6IiJ9LCJjb29yZGluYXRlIjpbNDMuODM1LC05Mi44MTNdLCJjaGlsZHJlbiI6W10sInNvcnQiOjAsInBhcmVudHMiOltdfSx7Im5hbWUiOiJDIiwiY29sb3IiOiIjQUFBQUZGIiwibWV0YSI6eyJkaXNwbGF5X25hbWUiOiIiLCJzdmciOiI8c3ZnIHk9XCItNVwiIHg9XCItNVwiIHdpZHRoPVwiMTBcIiBoZWlnaHQ9XCIxMFwiIHZpZXdCb3g9XCItNS41IC01LjUgMTEgMTFcIj48Y2lyY2xlIHI9XCI1XCI+PC9jaXJjbGU+PC9zdmc+PHRleHQgc3R5bGU9XCJmb250LXNpemU6MTJweDsgZmlsdGVyOiBkcm9wLXNoYWRvdygwcHggMHB4IDFweCByZ2JhKDI1NSwyNTUsMjU1LDEuMCkpO1wiIHN0cm9rZT1cIm5vbmVcIiBmaWxsPVwiIzExMTExMVwiIHk9XCIzXCIgeD1cIjhcIj5DPC90ZXh0PiIsInRlbXBsYXRlIjoiIn0sImNvb3JkaW5hdGUiOlszNC40NTIsLTEwMC4xOTVdLCJjaGlsZHJlbiI6W10sInNvcnQiOjAsInBhcmVudHMiOltdfV0sImVkZ2VzIjpbeyJuYW1lIjoiQS0tQiIsIm1ldGEiOnsiZW5kcG9pbnRfaWRlbnRpZmllcnMiOnsibmFtZXMiOlsiQSIsIkIiXX19LCJsYXllciI6IjAiLCJhekNvbG9yIjoiI0FBQUFGRiIsInphQ29sb3IiOiIjQUFBQUZGIiwiY29vcmRpbmF0ZXMiOltbNDMuODM0NTI2NzgyMjM2ODQsLTkyLjgxMjUwMDAwMDAwMDAxXSxbNDQuMDg3NTg1MDI4MjQ1MTgsLTEwOC42MzI4MTI1MDAwMDAwMV1dLCJjaGlsZHJlbiI6W10sIm5vZGVBIjoiQSIsIm5vZGVaIjoiQiIsInBvaW50cyI6W1s2MDMsMjQxXSxbNjkzLDI0M11dLCJyZWplY3RlZCI6MCwiY29udHJvbFBvaW50UGF0aCI6Ik02OTMsMjQzTDYwMywyNDEiLCJhelBhdGgiOiJNNjkyLjk3Nzc4MzI2MjcxNDksMjQzLjk5OTc1MzE3NzgzMTYyTDYwMi45NjY2Nzk2OTE1OTQ0LDI0MS45OTk0NDQ3MjQzNTgzNyIsInphUGF0aCI6Ik02MDMuMDIyMjE2NzM3Mjg1MSwyNDAuMDAwMjQ2ODIyMTY4MzhMNjkzLjAzMzMyMDMwODQwNTYsMjQyLjAwMDU1NTI3NTY0MTYzIiwic29ydCI6MX0seyJuYW1lIjoiQS0tQyIsIm1ldGEiOnsiZW5kcG9pbnRfaWRlbnRpZmllcnMiOnsibmFtZXMiOlsiQSIsIkMiXX19LCJsYXllciI6IjAiLCJhekNvbG9yIjoiI0FBQUFGRiIsInphQ29sb3IiOiIjQUFBQUZGIiwiY29vcmRpbmF0ZXMiOltbNDMuODM0NTI2NzgyMjM2ODQsLTkyLjgxMjUwMDAwMDAwMDAxXSxbMzQuNDUyMjE4NDcyODI2NTY2LC0xMDAuMTk1MzEyNTAwMDAwMDFdXSwiY2hpbGRyZW4iOltdLCJub2RlQSI6IkEiLCJub2RlWiI6IkMiLCJwb2ludHMiOltbNjUxLDMxMl0sWzY5MywyNDNdXSwicmVqZWN0ZWQiOjAsImNvbnRyb2xQb2ludFBhdGgiOiJNNjkzLDI0M0w2NTEsMzEyIiwiYXpQYXRoIjoiTTY5My44NTQxOTg1NTU2MTQ0LDI0My41MTk5NDY5NDY4OTU3NEw2NTEuODQ3Njk2ODE4ODgzMywzMTIuNTMwNDgxMDExMjEwODQiLCJ6YVBhdGgiOiJNNjUwLjE0NTgwMTQ0NDM4NTYsMzExLjQ4MDA1MzA1MzEwNDI2TDY5Mi4xNTIzMDMxODExMTY3LDI0Mi40Njk1MTg5ODg3ODkxMyIsInNvcnQiOjF9LHsibmFtZSI6IkItLUMiLCJtZXRhIjp7ImVuZHBvaW50X2lkZW50aWZpZXJzIjp7Im5hbWVzIjpbIkIiLCJDIl19fSwibGF5ZXIiOiIwIiwiYXpDb2xvciI6IiNBQUFBRkYiLCJ6YUNvbG9yIjoiI0FBQUFGRiIsImNvb3JkaW5hdGVzIjpbWzQ0LjA4NzU4NTAyODI0NTE4LC0xMDguNjMyODEyNTAwMDAwMDFdLFszNC40NTIyMTg0NzI4MjY1NjYsLTEwMC4xOTUzMTI1MDAwMDAwMV1dLCJjaGlsZHJlbiI6W10sIm5vZGVBIjoiQiIsIm5vZGVaIjoiQyIsInBvaW50cyI6W1s2NTEsMzEyXSxbNjAzLDI0MV1dLCJyZWplY3RlZCI6MCwiY29udHJvbFBvaW50UGF0aCI6Ik02MDMsMjQxTDY1MSwzMTIiLCJhelBhdGgiOiJNNjAzLjgyODQ0MjY0ODk1MDcsMjQwLjQzOTkyNjA5NjQ4NDA0TDY1MS44MzQ5MjA4NzI3NDUzLDMxMS40NDk2MzAwMDA1ODY3IiwiemFQYXRoIjoiTTY1MC4xNzE1NTczNTEwNDkzLDMxMi41NjAwNzM5MDM1MTU5Nkw2MDIuMTY1MDc5MTI3MjU0NywyNDEuNTUwMzY5OTk5NDEzMyIsInNvcnQiOjF9XSwibGF5ZXIiOiJ0YWlsIiwibmFtZSI6Ik51bGwgRGF0YXNldCIsInBhdGhMYXlvdXQiOnsidHlwZSI6ImN1cnZlQ2FyZGluYWwiLCJ0ZW5zaW9uIjowLjZ9fSIsDQogICAgICAibWFwanNvblVybCI6ICJodHRwczovL3RlcnJhbm92YS1pbnRlcm5hbC5lcy5uZXQvdGVycmFub3ZhL2FwaS92MS9vdXRwdXQvZGF0YXNldC9MbGtkQ3VZL2dlb2dyYXBoaWMvbGl2ZS8/dGVtcGxhdGU9WGNqNmV5WCIsDQogICAgICAiZW5kcG9pbnRJZCI6ICJuYW1lcyIsDQogICAgICAiaW5ib3VuZFZhbHVlRmllbGQiOiAiYXRveiIsDQogICAgICAib3V0Ym91bmRWYWx1ZUZpZWxkIjogInp0b2EiLA0KICAgICAgInNyY0ZpZWxkIjogInNyYyIsDQogICAgICAiZHN0RmllbGQiOiAiZHN0IiwNCiAgICAgICJsZWdlbmQiOiB0cnVlLA0KICAgICAgIm5vZGVIaWdobGlnaHQiOiAiI0FBRkZBQSINCiAgICB9DQogIF0NCn0=";

newOptions.configurationUrl = targetUrl;
newOptions.showSidebar = true;

canvas.setOptions(newOptions);

let node = canvas.querySelector(".esmap-sidebar");
expect(node).toBeTruthy();

newOptions = JSON.parse(JSON.stringify(canvas.options));
newOptions.showSidebar = false;

canvas.setOptions(newOptions);

node = canvas.querySelector(".esmap-sidebar");
expect(node).not.toBeTruthy();
});
it("should color nodes when there's a matching edge datapoint, even without a matching edge", ()=>{
let canvas = document.querySelector("esnet-map-canvas");
let newOptions = JSON.parse(JSON.stringify(canvas.options));

newOptions.layers[0].nodeThresholds = [{"value": 0, "color": "#E04040"}, {"value": 200000000, "color": "#5bb436"}]
let traffic = [
{"src_latitude":39,"src_longitude":-98,"src_name":"NodeA","in_bits": 16000000, "out_bits": 160000000},
{"src_latitude":42,"src_longitude":-102,"src_name":"NodeB","in_bits": 320000000, "out_bits": 32000000},
];
let topology = [{
"edges": [],
"nodes": [
{ "name": "NodeA", "coordinate": [39, -98], "meta": {
"svg": "<g><circle r='15' /><text x='20' y='4' stroke='none' fill='black'>NodeA</text></g>"
}
},
{ "name": "NodeB", "coordinate": [42, -102], "meta": {
"svg": "<g><circle r='15' /><text x='20' y='4' stroke='none' fill='black'>NodeB</text></g>"
}
}
]
}];

canvas.setOptions(newOptions);
canvas.setTopology(topology);
canvas.setTraffic(traffic);

let nodeA = canvas.querySelector(".node-NodeA circle");
expect(nodeA).toBeTruthy();
let style = getComputedStyle(nodeA);
expect(style.fill).toEqual("rgb(224, 64, 64)");
let nodeB = canvas.querySelector(".node-NodeB circle");
expect(nodeB).toBeTruthy();
style = getComputedStyle(nodeB);
expect(style.fill).toEqual("rgb(91, 180, 54)")
})
} );

0 comments on commit 2de4b08

Please sign in to comment.