feat(device-manager): add standalone project workspace
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
|
||||
import {
|
||||
createDeviceCoreClient,
|
||||
createLocalPreviewDeviceCore,
|
||||
} from "./device-core-client.mjs";
|
||||
|
||||
const token = "device-core-test-token-that-is-never-exposed";
|
||||
const actor = Object.freeze({
|
||||
userRef: "user:device-admin",
|
||||
hubRole: "admin",
|
||||
groupRefs: ["group:device-engineers"],
|
||||
ownerScopes: [{ scopeKind: "personal", ownerRef: "user:device-admin" }],
|
||||
});
|
||||
|
||||
test("Device Core client creates trusted actor headers and keeps its token server-side", async () => {
|
||||
const calls = [];
|
||||
const client = createDeviceCoreClient({
|
||||
baseUrl: "http://device-control-core:3210",
|
||||
token,
|
||||
fetchImpl: async (url, init) => {
|
||||
calls.push({ url: String(url), init });
|
||||
return jsonResponse(200, { ok: true, projects: [] });
|
||||
},
|
||||
});
|
||||
|
||||
assert.deepEqual(await client.listProjects(actor), []);
|
||||
assert.equal(calls.length, 1);
|
||||
assert.equal(calls[0].init.headers.Authorization, `Bearer ${token}`);
|
||||
assert.equal(calls[0].init.headers["X-NODEDC-User-Ref"], actor.userRef);
|
||||
assert.equal(calls[0].init.headers["X-NODEDC-Hub-Role"], "admin");
|
||||
assert.equal(calls[0].init.headers["X-NODEDC-Group-Refs"], "group:device-engineers");
|
||||
assert.equal(
|
||||
calls[0].init.headers["X-NODEDC-Owner-Scopes"],
|
||||
"personal=user:device-admin",
|
||||
);
|
||||
assert.equal(JSON.stringify(await client.listProjects(actor)).includes(token), false);
|
||||
});
|
||||
|
||||
test("Device Core client accepts only canonical commands and entity refs", async () => {
|
||||
const client = createDeviceCoreClient({
|
||||
baseUrl: "http://127.0.0.1:3210",
|
||||
token,
|
||||
fetchImpl: async () => jsonResponse(200, { ok: true, replayed: false, result: {} }),
|
||||
});
|
||||
|
||||
await assert.rejects(
|
||||
client.execute("raw:proxy", actor, {}, "device-manager-12345678"),
|
||||
/device_manager_command_invalid/,
|
||||
);
|
||||
await assert.rejects(
|
||||
client.getWorkspace(actor, "project:not-a-uuid"),
|
||||
/device_project_ref_invalid/,
|
||||
);
|
||||
await assert.rejects(
|
||||
client.execute("projects:ensure", actor, {}, "short"),
|
||||
/device_idempotency_key_invalid/,
|
||||
);
|
||||
});
|
||||
|
||||
test("local preview is empty and creates resources only through canonical commands", async () => {
|
||||
const client = createLocalPreviewDeviceCore();
|
||||
assert.deepEqual(await client.listProjects(actor), []);
|
||||
|
||||
const owner = await client.execute("owner-scopes:ensure", actor, {
|
||||
scopeKind: "personal",
|
||||
ownerRef: actor.userRef,
|
||||
displayName: "Device Admin",
|
||||
});
|
||||
assert.equal(owner.result.created, true);
|
||||
|
||||
const created = await client.execute("projects:ensure", actor, {
|
||||
scopeKind: "personal",
|
||||
ownerRef: actor.userRef,
|
||||
projectKey: "sandbox",
|
||||
name: "Device sandbox",
|
||||
description: null,
|
||||
});
|
||||
assert.equal(created.result.created, true);
|
||||
const projectRef = created.result.project.projectRef;
|
||||
|
||||
await client.execute("collections:ensure", actor, {
|
||||
projectRef,
|
||||
collectionKey: "field-devices",
|
||||
name: "Field devices",
|
||||
description: null,
|
||||
});
|
||||
|
||||
const projects = await client.listProjects(actor);
|
||||
assert.equal(projects.length, 1);
|
||||
assert.equal(projects[0].counts.collections, 1);
|
||||
const workspace = await client.getWorkspace(actor, projectRef);
|
||||
assert.equal(workspace.collections[0].collectionKey, "field-devices");
|
||||
assert.deepEqual(workspace.devices, []);
|
||||
});
|
||||
|
||||
function jsonResponse(status, body) {
|
||||
return new Response(JSON.stringify(body), {
|
||||
status,
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user