App-Netdisco
view release on metacpan or search on metacpan
xt/js/netmap-autosave.test.js view on Meta::CPAN
path.join(repoRoot, 'share', 'views', 'js', 'netmap.js'), 'utf8');
const deviceJs = () => fs.readFileSync(
path.join(repoRoot, 'share', 'views', 'js', 'device.js'), 'utf8');
// balanced to the handler's own closing paren, so an assertion cannot pass by
// matching text that belongs to a different handler. A line-indent heuristic
// was tried first and cut the onEngineStop body at its own fg.graphData() call.
const handlerBody = (src, name) => {
const at = src.indexOf('.' + name + '(');
assert.notEqual(at, -1, `netmap.js must register ${name}`);
const open = src.indexOf('(', at);
let depth = 0;
for (let i = open; i < src.length; i++) {
if (src[i] === '(') { depth++ }
else if (src[i] === ')') { depth--; if (depth === 0) { return src.slice(open, i + 1) } }
}
assert.fail(`unbalanced parentheses after ${name} in netmap.js`);
};
describe('netmap autosave', () => {
test('engineTick__while_the_simulation_runs__increments_a_counter', () => {
const body = handlerBody(netmapJs(), 'onEngineTick');
assert.match(
body,
/\+\+/,
'the tick handler must count, or there is no way to tell a settle from an engine ' +
'stop that ran nothing, and force-graph produces one of those per drag event. ' +
'Count inside the existing handler: onEngineTick is a setter, so registering a ' +
'second one would silently replace the spinner reset'
);
});
test('engineStop__having_run_no_ticks__does_not_post_the_map', () => {
const body = handlerBody(netmapJs(), 'onEngineStop');
assert.match(
body,
/saveMapPositions/,
'the settle after the first layout is still what saves it'
);
assert.match(
body,
/ticks[\s\S]{0,300}?saveMapPositions/i,
'the save in onEngineStop must be guarded by the tick count, or every drag event ' +
'posts the whole map again'
);
});
test('nodeDragEnd__with_autosave_on__posts_the_map_once', () => {
const body = handlerBody(netmapJs(), 'onNodeDragEnd');
assert.match(
body,
/saveMapPositions/,
'the engine stop after a drag runs no ticks, so without a save here a node the ' +
'user moved by hand is never persisted, which the renderer this replaced did ' +
'do'
);
});
});
describe('netmap autosave toggle', () => {
// Nothing re-fetches the netmap fragment when the toggle is clicked, so a
// value baked in at render time cannot follow it.
test('autosaveOn__after_the_sidebar_toggle__is_read_live_not_baked_at_render', () => {
const src = netmapJs();
assert.doesNotMatch(
src,
/autosaveOn\s*=\s*\('\[%/,
'autosave must not be baked from a template param: the toggle changes the ' +
'checkbox without re-rendering this fragment, so a baked value cannot follow it'
);
assert.match(
src,
/getElementById\(\s*'nd_autosave'\s*\)/,
'the autosave state must be read from the sidebar checkbox, the same way ' +
'showips and showspeed already are in this file'
);
});
});
describe('netmap manual save', () => {
test('saveMapPositions__called_by_the_button_with_autosave_off__announces', () => {
const src = netmapJs();
const at = src.indexOf('saveMapPositions = function');
assert.notEqual(at, -1, 'netmap.js must define saveMapPositions');
const body = src.slice(at, src.indexOf('\n };', at));
assert.match(
body,
/toastr\.success/,
'a manual save has nothing else to confirm it happened, so it must say so'
);
assert.match(
body,
/if\s*\([^)]*!\s*autosaveOn[^)]*\)[\s\S]{0,120}?toastr\.success/,
'the toast must be suppressed when autosave is on, or the map announces itself ' +
'at every settle and every drag'
);
assert.match(
body,
/function\s*\(\s*\w+\s*\)/,
'saveMapPositions must take the caller\'s intent as an argument: the autosave ' +
'calls and the button call are otherwise indistinguishable from inside it'
);
});
test('saveButton__on_click__tells_saveMapPositions_it_was_the_user', () => {
const src = deviceJs();
const at = src.indexOf("'#nd_netmap-save'");
assert.notEqual(at, -1, 'device.js must bind the netmap Save button');
const handler = src.slice(at, at + 260);
assert.match(
handler,
/saveMapPositions\(\s*\w+/,
'the button must pass an argument, or netmap.js cannot tell a click from the ' +
'saves autosave makes on its own'
);
});
});
( run in 0.837 second using v1.01-cache-2.11-cpan-b16cb0d3907 )