Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature requests: Traffic Matching by Node and Sidebar Toggle in full-URL-configuration mode #52

Merged
merged 2 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)")
})
} );
Loading