238 lines
7.3 KiB
JavaScript
238 lines
7.3 KiB
JavaScript
const expect = require("chai").expect;
|
|
const { CloudEvent } = require("../index.js");
|
|
const { v4: uuidv4 } = require("uuid");
|
|
const { asBase64 } = require("../lib/bindings/http/validation/fun.js");
|
|
const ValidationError = require("../lib/bindings/http/validation/validation_error.js");
|
|
const {
|
|
SPEC_V1
|
|
} = require("../lib/bindings/http/constants.js");
|
|
|
|
const id = uuidv4();
|
|
const type = "com.github.pull.create";
|
|
const source = "urn:event:from:myapi/resource/123";
|
|
const time = new Date();
|
|
const dataSchema = "http://example.com/registry/myschema.json";
|
|
const dataContentType = "application/json";
|
|
const data = {
|
|
much: "wow"
|
|
};
|
|
const subject = "subject-x0";
|
|
|
|
const cloudevent = new CloudEvent({
|
|
specversion: SPEC_V1,
|
|
id,
|
|
source,
|
|
type,
|
|
dataContentType,
|
|
dataSchema,
|
|
subject,
|
|
time,
|
|
data
|
|
});
|
|
|
|
describe("CloudEvents Spec v1.0", () => {
|
|
describe("REQUIRED Attributes", () => {
|
|
it("Should have 'id'", () => {
|
|
expect(cloudevent.id).to.equal(id);
|
|
});
|
|
|
|
it("Should have 'source'", () => {
|
|
expect(cloudevent.source).to.equal(source);
|
|
});
|
|
|
|
it("Should have 'specversion'", () => {
|
|
expect(cloudevent.specversion).to.equal("1.0");
|
|
});
|
|
|
|
it("Should have 'type'", () => {
|
|
expect(cloudevent.type).to.equal(type);
|
|
});
|
|
});
|
|
|
|
describe("OPTIONAL Attributes", () => {
|
|
it("Should have 'datacontenttype'", () => {
|
|
expect(cloudevent.dataContentType).to.equal(dataContentType);
|
|
});
|
|
|
|
it("Should have 'dataschema'", () => {
|
|
expect(cloudevent.dataSchema).to.equal(dataSchema);
|
|
});
|
|
|
|
it("Should have 'subject'", () => {
|
|
expect(cloudevent.subject).to.equal(subject);
|
|
});
|
|
|
|
it("Should have 'time'", () => {
|
|
expect(cloudevent.time).to.equal(time.toISOString());
|
|
});
|
|
});
|
|
|
|
describe("Extensions Constraints", () => {
|
|
it("should be ok when type is 'boolean'", () => {
|
|
cloudevent.addExtension("ext-boolean", true);
|
|
expect(cloudevent.spec.payload["ext-boolean"])
|
|
.to.equal(true);
|
|
});
|
|
|
|
it("should be ok when type is 'integer'", () => {
|
|
cloudevent.addExtension("ext-integer", 2019);
|
|
expect(cloudevent.spec.payload["ext-integer"])
|
|
.to.equal(2019);
|
|
});
|
|
|
|
it("should be ok when type is 'string'", () => {
|
|
cloudevent.addExtension("ext-string", "an-string");
|
|
expect(cloudevent.spec.payload["ext-string"])
|
|
.to.equal("an-string");
|
|
});
|
|
|
|
it("should be ok when type is 'Uint32Array' for 'Binary'", () => {
|
|
const myBinary = new Uint32Array(2019);
|
|
cloudevent.addExtension("ext-binary", myBinary);
|
|
expect(cloudevent.spec.payload["ext-binary"])
|
|
.to.equal(myBinary);
|
|
});
|
|
|
|
// URI
|
|
|
|
it("should be ok when type is 'Date' for 'Timestamp'", () => {
|
|
const myDate = new Date();
|
|
cloudevent.addExtension("ext-date", myDate);
|
|
expect(cloudevent.spec.payload["ext-date"])
|
|
.to.equal(myDate);
|
|
});
|
|
|
|
it("Should have the 'extension1'", () => {
|
|
cloudevent.addExtension("extension1", "value1");
|
|
expect(cloudevent.spec.payload.extension1)
|
|
.to.equal("value1");
|
|
});
|
|
|
|
it("should throw an error when use a reserved name as extension", () => {
|
|
expect(cloudevent.addExtension.bind(cloudevent, "id"))
|
|
.to.throw(ValidationError, "Reserved attribute name: 'id'");
|
|
});
|
|
|
|
it("should throw an error when use an invalid type", () => {
|
|
expect(cloudevent
|
|
.addExtension.bind(cloudevent, "invalid-val", { cool: "nice" }))
|
|
.to.throw(ValidationError, "Invalid type of extension value");
|
|
});
|
|
});
|
|
|
|
describe("The Constraints check", () => {
|
|
describe("'id'", () => {
|
|
it("should throw an error when is absent", () => {
|
|
delete cloudevent.spec.payload.id;
|
|
expect(cloudevent.format.bind(cloudevent))
|
|
.to
|
|
.throw(ValidationError, "invalid payload");
|
|
cloudevent.spec.payload.id = id;
|
|
});
|
|
|
|
it("should throw an error when is empty", () => {
|
|
cloudevent.spec.payload.id = "";
|
|
expect(cloudevent.format.bind(cloudevent))
|
|
.to.throw(ValidationError, "invalid payload");
|
|
cloudevent.spec.payload.id = id;
|
|
});
|
|
});
|
|
|
|
describe("'source'", () => {
|
|
it("should throw an error when is absent", () => {
|
|
delete cloudevent.spec.payload.source;
|
|
expect(cloudevent.format.bind(cloudevent))
|
|
.to.throw(ValidationError, "invalid payload");
|
|
cloudevent.spec.payload.source = source;
|
|
});
|
|
});
|
|
|
|
describe("'specversion'", () => {
|
|
it("should throw an error when is absent", () => {
|
|
delete cloudevent.spec.payload.specversion;
|
|
expect(cloudevent.format.bind(cloudevent))
|
|
.to.throw(ValidationError, "invalid payload");
|
|
cloudevent.spec.payload.specversion = "1.0";
|
|
});
|
|
|
|
it("should throw an error when is empty", () => {
|
|
cloudevent.spec.payload.specversion = "";
|
|
expect(cloudevent.format.bind(cloudevent))
|
|
.to.throw(ValidationError, "invalid payload");
|
|
cloudevent.spec.payload.specversion = "1.0";
|
|
});
|
|
});
|
|
|
|
describe("'type'", () => {
|
|
it("should throw an error when is absent", () => {
|
|
delete cloudevent.spec.payload.type;
|
|
expect(cloudevent.format.bind(cloudevent))
|
|
.to.throw(ValidationError, "invalid payload");
|
|
cloudevent.spec.payload.type = type;
|
|
});
|
|
|
|
it("should throw an error when is an empty string", () => {
|
|
cloudevent.type = "";
|
|
expect(cloudevent.format.bind(cloudevent))
|
|
.to.throw(ValidationError, "invalid payload");
|
|
cloudevent.type = type;
|
|
});
|
|
|
|
it("must be a non-empty string", () => {
|
|
cloudevent.type = type;
|
|
expect(cloudevent.spec.payload.type).to.equal(type);
|
|
});
|
|
});
|
|
|
|
describe("'subject'", () => {
|
|
it("should throw an error when is an empty string", () => {
|
|
cloudevent.subject = "";
|
|
expect(cloudevent.format.bind(cloudevent))
|
|
.to.throw(ValidationError, "invalid payload");
|
|
cloudevent.subject = type;
|
|
});
|
|
});
|
|
|
|
describe("'time'", () => {
|
|
it("must adhere to the format specified in RFC 3339", () => {
|
|
cloudevent.time = time;
|
|
expect(cloudevent.format().time).to.equal(time.toISOString());
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("Event data constraints", () => {
|
|
it("Should have 'data'", () => {
|
|
expect(cloudevent.data).to.deep.equal(data);
|
|
});
|
|
|
|
it("should maintain the type of data when no data content type", () => {
|
|
delete cloudevent.spec.payload.datacontenttype;
|
|
cloudevent.data = JSON.stringify(data);
|
|
|
|
expect(typeof cloudevent.data).to.equal("string");
|
|
cloudevent.dataContentType = dataContentType;
|
|
});
|
|
|
|
it("should convert data with stringified json to a json object", () => {
|
|
cloudevent.dataContentType = dataContentType;
|
|
cloudevent.data = JSON.stringify(data);
|
|
expect(cloudevent.data).to.deep.equal(data);
|
|
});
|
|
|
|
it("should be ok when type is 'Uint32Array' for 'Binary'", () => {
|
|
const dataString = ")(*~^my data for ce#@#$%";
|
|
|
|
const dataBinary = Uint32Array.from(dataString, (c) => c.codePointAt(0));
|
|
const expected = asBase64(dataBinary);
|
|
const olddct = cloudevent.dataContentType;
|
|
|
|
cloudevent.dataContentType = "text/plain";
|
|
cloudevent.data = dataBinary;
|
|
expect(cloudevent.data).to.deep.equal(expected);
|
|
|
|
cloudevent.dataContentType = olddct;
|
|
});
|
|
});
|
|
});
|