App-Netdisco
view release on metacpan or search on metacpan
xt/js/request-helper.test.js view on Meta::CPAN
// The routes these helpers reach are declared with Dancer's ajax keyword,
// which skips the route entirely without the XMLHttpRequest header. fetch
// sends nothing on its own, so the assertion below is what stands between a
// call through this helper and a button that answers 404.
const test = require('node:test');
const assert = require('node:assert');
const fs = require('node:fs');
const path = require('node:path');
const vm = require('node:vm');
const SRC = path.join(__dirname, '..', '..', 'share', 'public', 'javascripts',
'netdisco-request.js');
function load(fetchStub) {
const window = { location: { origin: 'http://example.net' } };
const context = {
window,
document: { querySelectorAll: () => [] },
fetch: fetchStub,
URLSearchParams,
console,
};
context.globalThis = context;
vm.createContext(context);
vm.runInContext(fs.readFileSync(SRC, 'utf8'), context);
return window.ndRequest;
}
// These stand in for real form elements, which answer :disabled through
// Element.matches. The default here mirrors an element's own disabled
// property; a test proving the fieldset case overrides it directly.
function field(props) {
return Object.assign({
matches: function (sel) { return sel === ':disabled' && !!this.disabled; },
}, props);
}
test('post__sending_a_body__carries_the_XMLHttpRequest_header', async () => {
let seen = null;
const ndRequest = load((url, init) => { seen = { url, init }; return Promise.resolve({ ok: true, status: 200 }); });
await ndRequest.post('/ajax/portcontrol', new URLSearchParams({ device: '192.0.2.1' }));
assert.equal(seen.url, '/ajax/portcontrol');
assert.equal(seen.init.method, 'POST');
assert.equal(seen.init.headers['X-Requested-With'], 'XMLHttpRequest');
assert.match(seen.init.headers['Content-Type'], /application\/x-www-form-urlencoded/);
assert.equal(seen.init.credentials, 'same-origin');
assert.equal(String(seen.init.body), 'device=192.0.2.1');
});
test('post__a_server_error__resolves_so_the_caller_can_read_the_status', async () => {
const ndRequest = load(() => Promise.resolve({ ok: false, status: 500 }));
const res = await ndRequest.post('/ajax/portcontrol', new URLSearchParams());
assert.equal(res.status, 500, 'fetch does not reject on 5xx and the helper must not hide that');
});
test('fields__over_a_row_of_inputs__skips_an_unchecked_box_and_a_nameless_field', () => {
const ndRequest = load(() => Promise.resolve({ ok: true }));
const row = {
querySelectorAll: () => ([
field({ name: 'port', value: 'Gi0/1', type: 'text' }),
field({ name: 'up', value: 'on', type: 'checkbox', checked: false }),
field({ name: 'down', value: 'on', type: 'checkbox', checked: true }),
field({ name: '', value: 'ignored', type: 'text' }),
]),
};
assert.equal(String(ndRequest.fields(row, 'input')), 'port=Gi0%2F1&down=on');
});
test('fields__a_multiple_select_with_two_chosen_options__contributes_one_pair_per_option', () => {
const ndRequest = load(() => Promise.resolve({ ok: true }));
const row = {
querySelectorAll: () => ([
field({
name: 'vendor',
type: 'select-multiple',
selectedOptions: [{ value: 'cisco' }, { value: 'juniper' }],
}),
]),
};
assert.equal(String(ndRequest.fields(row, 'select')), 'vendor=cisco&vendor=juniper');
});
test('fields__a_disabled_field__contributes_nothing_while_its_neighbor_does', () => {
const ndRequest = load(() => Promise.resolve({ ok: true }));
const row = {
querySelectorAll: () => ([
field({ name: 'token_acl', value: 'stale', type: 'select-one', disabled: true }),
field({ name: 'other', value: 'ok', type: 'text', disabled: false }),
]),
};
assert.equal(String(ndRequest.fields(row, 'select, input')), 'other=ok');
});
// A field's own disabled property stays false when a surrounding fieldset is
// what disables it; :disabled answers true either way, which is why the
// serializer tests that rather than the property.
test('fields__a_field_disabled_only_by_its_fieldset__contributes_nothing', () => {
const ndRequest = load(() => Promise.resolve({ ok: true }));
const row = {
querySelectorAll: () => ([
{ name: 'reason', value: 'stale', type: 'select-one', disabled: false, matches: (sel) => sel === ':disabled' },
field({ name: 'other', value: 'ok', type: 'text' }),
]),
};
assert.equal(String(ndRequest.fields(row, 'select, input')), 'other=ok');
});
( run in 1.864 second using v1.01-cache-2.11-cpan-007c89162af )