import { assert } from "chai"; import { Types } from "mongoose"; import { describe, it, beforeEach, afterEach } from "node:test"; import * as m from "../index"; import * as config from "./config"; describe("DroneConnection", function() { let models: m.BackendModels, mongoose: m.MongooseModule; let departmentId: Types.ObjectId; beforeEach(async function() { const c = await m.connect(config.url); models = c.models; mongoose = c.mongoose; departmentId = new mongoose.Types.ObjectId(); await models.DroneConnection.syncIndexes(); }); afterEach(async function() { await models.DroneConnection.deleteMany({}); await mongoose.disconnect(); }); it("is saved and reads back every field", async function() { const sut = await new models.DroneConnection({ departmentId, provider: "skydio", active: true, label: "Skydio HQ", authToken: { iv: "iv-token", encryptedData: "enc-token" }, authSecret: { iv: "iv-secret", encryptedData: "enc-secret" }, options: { drones: "listed", serials: ["SN-1", "SN-2"], }, }).save(); assert.isNotNull(sut._id); assert.equal(sut.departmentId.toString(), departmentId.toString()); assert.equal(sut.provider, "skydio"); assert.isTrue(sut.active); assert.equal(sut.label, "Skydio HQ"); assert.equal(sut.authToken.iv, "iv-token"); assert.equal(sut.authToken.encryptedData, "enc-token"); assert.equal(sut.authSecret.iv, "iv-secret"); assert.equal(sut.authSecret.encryptedData, "enc-secret"); assert.equal(sut.options?.drones, "listed"); assert.deepEqual(sut.options?.serials, ["SN-1", "SN-2"]); assert.instanceOf(sut.modified, Date); }); it("leaves options undefined when none are given", async function() { const sut = await new models.DroneConnection({ departmentId, provider: "skydio", label: "No options", authToken: { iv: "iv", encryptedData: "t" }, authSecret: { iv: "iv", encryptedData: "s" }, }).save(); assert.isUndefined(sut.options); }); for (const provider of Object.values(m.DroneProvider)) { it(`saves the ${provider} provider`, async function() { const sut = await new models.DroneConnection({ departmentId, provider, label: `${provider} fleet`, }).save(); const loaded = await models.DroneConnection.findOne({ _id: sut._id }); assert.equal(loaded?.provider, provider); }); } it("rejects an unknown provider", async function() { let thrownError: unknown = null; try { await new models.DroneConnection({ departmentId, provider: "bogus", label: "Bad provider", }).save(); } catch (e) { thrownError = e; } assert.isNotNull(thrownError, "expected an unknown provider to be rejected"); assert.include(String((thrownError as Error).message), "provider"); }); it("rejects an unknown options.drones value", async function() { let thrownError: unknown = null; try { await new models.DroneConnection({ departmentId, provider: "skydio", label: "Bad options", options: { drones: "list", serials: [], }, }).save(); } catch (e) { thrownError = e; } assert.isNotNull(thrownError, "expected an unknown options.drones value to be rejected"); assert.include(String((thrownError as Error).message), "options.drones"); }); it("stores no timestamp field outside the schema", async function() { await new models.DroneConnection({ departmentId, provider: "skydio", label: "Raw read", }).save(); const raw = await models.DroneConnection.collection.findOne({ departmentId }); assert.isNotNull(raw); assert.notProperty(raw, "createdAt"); assert.notProperty(raw, "updatedAt"); assert.property(raw, "modified"); }); it("advances modified on findOneAndUpdate", async function() { const staleDate = new Date("2020-01-02T03:04:05.000Z"); await new models.DroneConnection({ departmentId, provider: "skydio", label: "Stale", }).save(); await models.DroneConnection.collection.updateOne({ departmentId, }, { $set: { modified: staleDate, }, }); const updated = await models.DroneConnection.findOneAndUpdate({ departmentId, }, { $set: { active: true, }, }, { new: true, }); assert.isNotNull(updated); assert.isTrue(updated!.modified > staleDate, "expected modified to advance"); }); it("enforces a unique (departmentId, provider, label) index", async function() { await new models.DroneConnection({ departmentId, provider: "skydio", label: "Skydio HQ", }).save(); let thrownError: unknown = null; try { await new models.DroneConnection({ departmentId, provider: "skydio", label: "Skydio HQ", }).save(); } catch (e) { thrownError = e; } assert.isNotNull(thrownError, "expected a duplicate (departmentId, label) to be rejected"); assert.equal((thrownError as { code?: number }).code, 11000); assert.include(String((thrownError as Error).message), "E11000"); }); it("rejects a provider whose case does not match", async function() { let thrownError: unknown = null; try { await new models.DroneConnection({ departmentId, provider: "BRINC", label: "Wrong case", }).save(); } catch (e) { thrownError = e; } assert.isNotNull(thrownError, "expected an upper-case provider to be rejected"); assert.include(String((thrownError as Error).message), "provider"); }); it("allows one label across different providers in a department", async function() { for (const provider of Object.values(m.DroneProvider)) { const sut = await new models.DroneConnection({ departmentId, provider, label: "Fleet A", }).save(); assert.equal(sut.provider, provider); } const stored = await models.DroneConnection.find({ departmentId, label: "Fleet A" }); assert.equal(stored.length, Object.values(m.DroneProvider).length); }); });