'use strict'; const test = require('node:test'); const assert = require('node:assert/strict'); const DashboardApi = require('../../src/specificClass.js'); const { registerChild } = require('../../src/commands/handlers.js'); // Minimal fetch double. `routes` maps `${method} ${pathname}` to a response // descriptor { ok, status, body }. Records every call for assertions. function makeFetch(routes) { const calls = []; const fetchImpl = async (url, opts = {}) => { const method = opts.method || 'GET'; const { pathname } = new URL(url); calls.push({ method, pathname, body: opts.body }); const r = routes[`${method} ${pathname}`]; if (!r) return { ok: false, status: 404, json: async () => ({ message: 'not found' }) }; if (typeof r === 'function') return r(); return { ok: r.ok ?? true, status: r.status ?? 200, json: async () => r.body }; }; fetchImpl.calls = calls; return fetchImpl; } function api(grafanaConnector) { return new DashboardApi({ grafanaConnector }); } test('no folderTitle → returns configured folderUid without any fetch (legacy path)', async () => { const a = api({ folderUid: 'pinned-uid' }); const fetchImpl = makeFetch({}); const uid = await a.resolveFolderUid({ fetchImpl }); assert.equal(uid, 'pinned-uid'); assert.equal(fetchImpl.calls.length, 0, 'must not call Grafana when no folderTitle is set'); }); test('folderTitle matches an existing folder (case-insensitive) → returns its uid', async () => { const a = api({ folderTitle: 'EVOLV' }); const fetchImpl = makeFetch({ 'GET /api/folders': { body: [{ title: 'Other', uid: 'x' }, { title: 'evolv', uid: 'bfncls6af0b9cb' }] }, }); const uid = await a.resolveFolderUid({ fetchImpl }); assert.equal(uid, 'bfncls6af0b9cb'); assert.equal(fetchImpl.calls.filter((c) => c.method === 'POST').length, 0, 'must not create when found'); }); test('resolution is cached → second call makes no further fetch', async () => { const a = api({ folderTitle: 'EVOLV' }); const fetchImpl = makeFetch({ 'GET /api/folders': { body: [{ title: 'EVOLV', uid: 'u1' }] } }); await a.resolveFolderUid({ fetchImpl }); await a.resolveFolderUid({ fetchImpl }); assert.equal(fetchImpl.calls.length, 1, 'second resolve should hit the cache'); }); test('folder absent → creates it by name and returns the new uid', async () => { const a = api({ folderTitle: 'EVOLV' }); const fetchImpl = makeFetch({ 'GET /api/folders': { body: [{ title: 'Other', uid: 'x' }] }, 'POST /api/folders': { status: 200, body: { uid: 'created-uid', title: 'EVOLV' } }, }); const uid = await a.resolveFolderUid({ fetchImpl }); assert.equal(uid, 'created-uid'); const post = fetchImpl.calls.find((c) => c.method === 'POST'); assert.equal(JSON.parse(post.body).title, 'EVOLV'); }); test('fetch throws → falls back to configured folderUid (never worse than pinned)', async () => { const a = api({ folderTitle: 'EVOLV', folderUid: 'fallback-uid' }); const fetchImpl = async () => { throw new Error('ECONNREFUSED'); }; const uid = await a.resolveFolderUid({ fetchImpl }); assert.equal(uid, 'fallback-uid'); }); test('no fetch implementation available → falls back to configured folderUid', async () => { const a = api({ folderTitle: 'EVOLV', folderUid: 'fallback-uid' }); // Pass an explicit non-function (not undefined, which would trigger the // globalThis.fetch default) to exercise the "no fetch available" branch. const uid = await a.resolveFolderUid({ fetchImpl: null }); assert.equal(uid, 'fallback-uid'); }); test('emit path stamps the resolved folderUid onto every upsert payload', async () => { const a = api({ folderTitle: 'EVOLV' }); // Force a deterministic resolution without standing up fetch. a.resolveFolderUid = async () => 'resolved-folder-uid'; const childSource = { config: { general: { id: 'm1', name: 'Level' }, functionality: { softwareType: 'measurement' } }, }; const sent = []; const ctx = { node: { id: 'dapi' }, send: (m) => sent.push(m) }; await registerChild(a, { payload: childSource }, ctx); assert.ok(sent.length >= 1, 'should emit at least one create'); for (const m of sent) { assert.equal(m.topic, 'create'); assert.equal(m.payload.folderUid, 'resolved-folder-uid'); } });