359 lines
14 KiB
TypeScript
359 lines
14 KiB
TypeScript
import { DeltaV1, DeltaV2 } from "../src/delta";
|
|
import {
|
|
InvalidDeltaFormatError,
|
|
MissingRequiredFieldError,
|
|
InvalidPointerError,
|
|
validateDeltaNetworkImageV1,
|
|
validateDeltaNetworkImageV2
|
|
} from "../src/delta-validation";
|
|
|
|
describe("Delta Validation", () => {
|
|
describe("Invalid Delta Formats", () => {
|
|
describe("DeltaV1 validation", () => {
|
|
it("should throw error for non-object delta", () => {
|
|
expect(() => validateDeltaNetworkImageV1(null)).toThrow(InvalidDeltaFormatError);
|
|
expect(() => validateDeltaNetworkImageV1("string")).toThrow(InvalidDeltaFormatError);
|
|
expect(() => validateDeltaNetworkImageV1(123)).toThrow(InvalidDeltaFormatError);
|
|
expect(() => validateDeltaNetworkImageV1([])).toThrow(InvalidDeltaFormatError);
|
|
});
|
|
|
|
it("should throw error for invalid ID types", () => {
|
|
const invalidDeltas = [
|
|
{ id: null, timeCreated: 123, host: "host", creator: "creator", pointers: [] },
|
|
{ id: 123, timeCreated: 123, host: "host", creator: "creator", pointers: [] },
|
|
{ id: "", timeCreated: 123, host: "host", creator: "creator", pointers: [] },
|
|
{ id: {}, timeCreated: 123, host: "host", creator: "creator", pointers: [] }
|
|
];
|
|
|
|
invalidDeltas.forEach(delta => {
|
|
expect(() => validateDeltaNetworkImageV1(delta)).toThrow(InvalidDeltaFormatError);
|
|
});
|
|
});
|
|
|
|
it("should throw error for invalid timestamp", () => {
|
|
const invalidDeltas = [
|
|
{ id: "id", timeCreated: "123", host: "host", creator: "creator", pointers: [] },
|
|
{ id: "id", timeCreated: -123, host: "host", creator: "creator", pointers: [] },
|
|
{ id: "id", timeCreated: 0, host: "host", creator: "creator", pointers: [] },
|
|
{ id: "id", timeCreated: null, host: "host", creator: "creator", pointers: [] }
|
|
];
|
|
|
|
invalidDeltas.forEach(delta => {
|
|
expect(() => validateDeltaNetworkImageV1(delta)).toThrow(InvalidDeltaFormatError);
|
|
});
|
|
});
|
|
|
|
it("should throw error for invalid host/creator", () => {
|
|
const invalidDeltas = [
|
|
{ id: "id", timeCreated: 123, host: null, creator: "creator", pointers: [] },
|
|
{ id: "id", timeCreated: 123, host: "", creator: "creator", pointers: [] },
|
|
{ id: "id", timeCreated: 123, host: 123, creator: "creator", pointers: [] },
|
|
{ id: "id", timeCreated: 123, host: "host", creator: null, pointers: [] },
|
|
{ id: "id", timeCreated: 123, host: "host", creator: "", pointers: [] },
|
|
{ id: "id", timeCreated: 123, host: "host", creator: 123, pointers: [] }
|
|
];
|
|
|
|
invalidDeltas.forEach(delta => {
|
|
expect(() => validateDeltaNetworkImageV1(delta)).toThrow(InvalidDeltaFormatError);
|
|
});
|
|
});
|
|
|
|
it("should throw error for non-array pointers", () => {
|
|
const invalidDeltas = [
|
|
{ id: "id", timeCreated: 123, host: "host", creator: "creator", pointers: null },
|
|
{ id: "id", timeCreated: 123, host: "host", creator: "creator", pointers: {} },
|
|
{ id: "id", timeCreated: 123, host: "host", creator: "creator", pointers: "pointers" },
|
|
{ id: "id", timeCreated: 123, host: "host", creator: "creator", pointers: 123 }
|
|
];
|
|
|
|
invalidDeltas.forEach(delta => {
|
|
expect(() => validateDeltaNetworkImageV1(delta)).toThrow(InvalidDeltaFormatError);
|
|
});
|
|
});
|
|
|
|
it("should throw error for empty pointers array", () => {
|
|
const delta = { id: "id", timeCreated: 123, host: "host", creator: "creator", pointers: [] };
|
|
expect(() => validateDeltaNetworkImageV1(delta)).toThrow(InvalidDeltaFormatError);
|
|
});
|
|
|
|
it("should throw error for invalid pointer structure", () => {
|
|
const invalidPointers = [
|
|
[null],
|
|
["string"],
|
|
[123],
|
|
[{ localContext: null, target: "target" }],
|
|
[{ localContext: "", target: "target" }],
|
|
[{ localContext: 123, target: "target" }],
|
|
[{ localContext: "context", target: undefined }],
|
|
[{ localContext: "context", target: {} }],
|
|
[{ localContext: "context", target: [] }]
|
|
];
|
|
|
|
invalidPointers.forEach(pointers => {
|
|
const delta = { id: "id", timeCreated: 123, host: "host", creator: "creator", pointers };
|
|
expect(() => validateDeltaNetworkImageV1(delta)).toThrow(InvalidPointerError);
|
|
});
|
|
});
|
|
|
|
it("should throw error for invalid targetContext", () => {
|
|
const invalidPointers = [
|
|
[{ localContext: "context", target: "target", targetContext: null }],
|
|
[{ localContext: "context", target: "target", targetContext: "" }],
|
|
[{ localContext: "context", target: "target", targetContext: 123 }],
|
|
[{ localContext: "context", target: "target", targetContext: {} }]
|
|
];
|
|
|
|
invalidPointers.forEach(pointers => {
|
|
const delta = { id: "id", timeCreated: 123, host: "host", creator: "creator", pointers };
|
|
expect(() => validateDeltaNetworkImageV1(delta)).toThrow(InvalidPointerError);
|
|
});
|
|
});
|
|
|
|
it("should throw error for pointer consistency violation", () => {
|
|
// If targetContext exists, target must be a string (reference)
|
|
const pointers = [{ localContext: "context", target: 123, targetContext: "property" }];
|
|
const delta = { id: "id", timeCreated: 123, host: "host", creator: "creator", pointers };
|
|
expect(() => validateDeltaNetworkImageV1(delta)).toThrow(InvalidPointerError);
|
|
});
|
|
});
|
|
|
|
describe("DeltaV2 validation", () => {
|
|
it("should throw error for non-object delta", () => {
|
|
expect(() => validateDeltaNetworkImageV2(null)).toThrow(InvalidDeltaFormatError);
|
|
expect(() => validateDeltaNetworkImageV2("string")).toThrow(InvalidDeltaFormatError);
|
|
expect(() => validateDeltaNetworkImageV2(123)).toThrow(InvalidDeltaFormatError);
|
|
expect(() => validateDeltaNetworkImageV2([])).toThrow(InvalidDeltaFormatError);
|
|
});
|
|
|
|
it("should throw error for invalid pointers object", () => {
|
|
const invalidDeltas = [
|
|
{ id: "id", timeCreated: 123, host: "host", creator: "creator", pointers: null },
|
|
{ id: "id", timeCreated: 123, host: "host", creator: "creator", pointers: [] },
|
|
{ id: "id", timeCreated: 123, host: "host", creator: "creator", pointers: "pointers" },
|
|
{ id: "id", timeCreated: 123, host: "host", creator: "creator", pointers: 123 }
|
|
];
|
|
|
|
invalidDeltas.forEach(delta => {
|
|
expect(() => validateDeltaNetworkImageV2(delta)).toThrow(InvalidDeltaFormatError);
|
|
});
|
|
});
|
|
|
|
it("should throw error for empty pointers object", () => {
|
|
const delta = { id: "id", timeCreated: 123, host: "host", creator: "creator", pointers: {} };
|
|
expect(() => validateDeltaNetworkImageV2(delta)).toThrow(InvalidDeltaFormatError);
|
|
});
|
|
|
|
it("should throw error for invalid pointer keys", () => {
|
|
const invalidPointers = [
|
|
{ "": "value" }
|
|
];
|
|
|
|
invalidPointers.forEach(pointers => {
|
|
const delta = { id: "id", timeCreated: 123, host: "host", creator: "creator", pointers };
|
|
expect(() => validateDeltaNetworkImageV2(delta)).toThrow(InvalidPointerError);
|
|
});
|
|
});
|
|
|
|
it("should throw error for invalid pointer values", () => {
|
|
const invalidPointers = [
|
|
{ key: undefined },
|
|
{ key: [] },
|
|
{ key: true },
|
|
{ key: false }
|
|
];
|
|
|
|
invalidPointers.forEach(pointers => {
|
|
const delta = { id: "id", timeCreated: 123, host: "host", creator: "creator", pointers };
|
|
expect(() => validateDeltaNetworkImageV2(delta)).toThrow(InvalidPointerError);
|
|
});
|
|
});
|
|
|
|
it("should throw error for invalid reference format", () => {
|
|
const invalidReferences = [
|
|
{ key: {} }, // Empty reference
|
|
{ key: { ref1: "val1", ref2: "val2" } }, // Multiple keys
|
|
{ key: { "": "value" } }, // Empty key
|
|
{ key: { ref: "" } }, // Empty value
|
|
{ key: { ref: 123 } }, // Non-string value
|
|
{ key: { ref: null } } // Null value
|
|
];
|
|
|
|
invalidReferences.forEach(pointers => {
|
|
const delta = { id: "id", timeCreated: 123, host: "host", creator: "creator", pointers };
|
|
expect(() => validateDeltaNetworkImageV2(delta)).toThrow(InvalidPointerError);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("Missing Required Fields", () => {
|
|
describe("DeltaV1", () => {
|
|
it("should throw MissingRequiredFieldError for missing id", () => {
|
|
const delta = { timeCreated: 123, host: "host", creator: "creator", pointers: [] };
|
|
expect(() => validateDeltaNetworkImageV1(delta)).toThrow(MissingRequiredFieldError);
|
|
expect(() => validateDeltaNetworkImageV1(delta)).toThrow(/id/);
|
|
});
|
|
|
|
it("should throw MissingRequiredFieldError for missing timeCreated", () => {
|
|
const delta = { id: "id", host: "host", creator: "creator", pointers: [] };
|
|
expect(() => validateDeltaNetworkImageV1(delta)).toThrow(MissingRequiredFieldError);
|
|
expect(() => validateDeltaNetworkImageV1(delta)).toThrow(/timeCreated/);
|
|
});
|
|
|
|
it("should throw MissingRequiredFieldError for missing host", () => {
|
|
const delta = { id: "id", timeCreated: 123, creator: "creator", pointers: [] };
|
|
expect(() => validateDeltaNetworkImageV1(delta)).toThrow(MissingRequiredFieldError);
|
|
expect(() => validateDeltaNetworkImageV1(delta)).toThrow(/host/);
|
|
});
|
|
|
|
it("should throw MissingRequiredFieldError for missing creator", () => {
|
|
const delta = { id: "id", timeCreated: 123, host: "host", pointers: [] };
|
|
expect(() => validateDeltaNetworkImageV1(delta)).toThrow(MissingRequiredFieldError);
|
|
expect(() => validateDeltaNetworkImageV1(delta)).toThrow(/creator/);
|
|
});
|
|
|
|
it("should throw MissingRequiredFieldError for missing pointers", () => {
|
|
const delta = { id: "id", timeCreated: 123, host: "host", creator: "creator" };
|
|
expect(() => validateDeltaNetworkImageV1(delta)).toThrow(MissingRequiredFieldError);
|
|
expect(() => validateDeltaNetworkImageV1(delta)).toThrow(/pointers/);
|
|
});
|
|
});
|
|
|
|
describe("DeltaV2", () => {
|
|
it("should throw MissingRequiredFieldError for all missing fields", () => {
|
|
const requiredFields = ["id", "timeCreated", "host", "creator", "pointers"];
|
|
|
|
requiredFields.forEach(field => {
|
|
const delta: Record<string, unknown> = {
|
|
id: "id",
|
|
timeCreated: 123,
|
|
host: "host",
|
|
creator: "creator",
|
|
pointers: { key: "value" }
|
|
};
|
|
delete delta[field];
|
|
|
|
expect(() => validateDeltaNetworkImageV2(delta)).toThrow(MissingRequiredFieldError);
|
|
expect(() => validateDeltaNetworkImageV2(delta)).toThrow(new RegExp(field));
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("Valid Delta Formats", () => {
|
|
it("should accept valid DeltaV1", () => {
|
|
const validDeltas = [
|
|
{
|
|
id: "uuid-123",
|
|
timeCreated: 123456789,
|
|
host: "host1",
|
|
creator: "creator1",
|
|
pointers: [{ localContext: "name", target: "Alice" }]
|
|
},
|
|
{
|
|
id: "uuid-456",
|
|
timeCreated: 987654321,
|
|
host: "host2",
|
|
creator: "creator2",
|
|
pointers: [
|
|
{ localContext: "name", target: "Bob" },
|
|
{ localContext: "age", target: 25 },
|
|
{ localContext: "active", target: null }
|
|
]
|
|
},
|
|
{
|
|
id: "uuid-789",
|
|
timeCreated: 111111111,
|
|
host: "host3",
|
|
creator: "creator3",
|
|
pointers: [{ localContext: "friend", target: "user123", targetContext: "friendOf" }]
|
|
}
|
|
];
|
|
|
|
validDeltas.forEach(delta => {
|
|
expect(() => validateDeltaNetworkImageV1(delta)).not.toThrow();
|
|
});
|
|
});
|
|
|
|
it("should accept valid DeltaV2", () => {
|
|
const validDeltas = [
|
|
{
|
|
id: "uuid-123",
|
|
timeCreated: 123456789,
|
|
host: "host1",
|
|
creator: "creator1",
|
|
pointers: { name: "Alice" }
|
|
},
|
|
{
|
|
id: "uuid-456",
|
|
timeCreated: 987654321,
|
|
host: "host2",
|
|
creator: "creator2",
|
|
pointers: {
|
|
name: "Bob",
|
|
age: 25,
|
|
active: null
|
|
}
|
|
},
|
|
{
|
|
id: "uuid-789",
|
|
timeCreated: 111111111,
|
|
host: "host3",
|
|
creator: "creator3",
|
|
pointers: { friend: { user123: "friendOf" } }
|
|
}
|
|
];
|
|
|
|
validDeltas.forEach(delta => {
|
|
expect(() => validateDeltaNetworkImageV2(delta)).not.toThrow();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("Delta class integration", () => {
|
|
it("should validate when creating DeltaV1 from network image", () => {
|
|
const invalidDelta = {
|
|
id: "id",
|
|
timeCreated: "not-a-number",
|
|
host: "host",
|
|
creator: "creator",
|
|
pointers: [{ localContext: "name", target: "value" }]
|
|
};
|
|
|
|
expect(() => DeltaV1.fromNetworkImage(invalidDelta as never)).toThrow(InvalidDeltaFormatError);
|
|
});
|
|
|
|
it("should validate when creating DeltaV2 from network image", () => {
|
|
const invalidDelta = {
|
|
id: "id",
|
|
timeCreated: 123,
|
|
host: "",
|
|
creator: "creator",
|
|
pointers: { name: "value" }
|
|
};
|
|
|
|
expect(() => DeltaV2.fromNetworkImage(invalidDelta as never)).toThrow(InvalidDeltaFormatError);
|
|
});
|
|
|
|
it("should accept valid network images", () => {
|
|
const validV1 = {
|
|
id: "uuid-123",
|
|
timeCreated: 123456789,
|
|
host: "host1",
|
|
creator: "creator1",
|
|
pointers: [{ localContext: "name", target: "Alice" }]
|
|
};
|
|
|
|
const validV2 = {
|
|
id: "uuid-456",
|
|
timeCreated: 987654321,
|
|
host: "host2",
|
|
creator: "creator2",
|
|
pointers: { name: "Bob" }
|
|
};
|
|
|
|
expect(() => DeltaV1.fromNetworkImage(validV1)).not.toThrow();
|
|
expect(() => DeltaV2.fromNetworkImage(validV2)).not.toThrow();
|
|
});
|
|
});
|
|
}); |