src,fix: drop support for v0.2 and clean up contenttype

This commit removes support for the v0.2 specification. It also removes the
`contenttype` attribute from the `CloudEvent` object. While the HTTP protocol
binding specifies that in binary mode, the `datacontenttype` attribute should
map to the HTTP Content-Type header, that doesn't mean that the `CloudEvent`
object should have a `contenttype` property.

Fixes: https://github.com/cloudevents/sdk-javascript/issues/61
Fixes: https://github.com/cloudevents/sdk-javascript/issues/66

Signed-off-by: Lance Ball <lball@redhat.com>
This commit is contained in:
Lance Ball 2020-04-27 15:50:05 -04:00 committed by Fabio José
parent 1a4bdce192
commit 5110ad4c67
35 changed files with 220 additions and 2511 deletions

View File

@ -33,7 +33,7 @@ To see working examples, point to [examples](./examples).
## :newspaper: Newsletter :newspaper:
> all the API developed before, for 0.1, 0.2 and 0.3, works as the same.
> all the API developed before, for 0.1 and 0.3, works as the same.
Checkout the new expressive additions.
@ -91,21 +91,21 @@ These are the supported specifications by this version.
| **Specifications** | v0.1 | v0.2 | v0.3 | **v1.0** |
|---------------------------------------|------|------|------|----------|
| CloudEvents | yes | yes | yes | yes |
| HTTP Transport Binding - Structured | yes | yes | yes | yes |
| HTTP Transport Binding - Binary | yes | yes | yes | yes |
| JSON Event Format | yes | yes | yes | yes |
| CloudEvents | no | no | yes | yes |
| HTTP Transport Binding - Structured | no | no | yes | yes |
| HTTP Transport Binding - Binary | no | no | yes | yes |
| JSON Event Format | no | no | yes | yes |
### What we can do
| **What** | v0.1 | v0.2 | v0.3 | **v1.0** |
|-------------------------------------|--------|------|------|----------|
| Create events | yes | yes | yes | yes |
| Emit Structured events over HTTP | yes | yes | yes | yes |
| Emit Binary events over HTTP | yes | yes | yes | yes |
| JSON Event Format | yes | yes | yes | yes |
| Receive Structured events over HTTP | **no** | yes | yes | yes |
| Receive Binary events over HTTP | **no** | yes | yes | yes |
| Create events | no | no | yes | yes |
| Emit Structured events over HTTP | no | no | yes | yes |
| Emit Binary events over HTTP | no | no | yes | yes |
| JSON Event Format | no | no | yes | yes |
| Receive Structured events over HTTP | **no** | no | yes | yes |
| Receive Binary events over HTTP | **no** | no | yes | yes |
## How to use

View File

@ -161,61 +161,3 @@ __A Batch One__
TODO
## Spec v0.2
### How To Post an Event
__A Structured One__
> Payload [example](../payload/v02/structured-event-0.json)
```bash
curl -X POST \
-d'@../payload/v02/structured-event-0.json' \
-H'Content-Type:application/cloudevents+json' \
http://localhost:3000/v02
```
__A Structured One with Extension__
> Payload [example](../payload/v02/structured-event-1.json)
```bash
curl -X POST \
-d'@../payload/v02/structured-event-1.json' \
-H'Content-Type:application/cloudevents+json' \
http://localhost:3000/v02
```
__A Binary One__
```bash
curl -X POST \
-d'@../payload/data-0.json' \
-H'Content-Type:application/json' \
-H'ce-specversion:0.2' \
-H'ce-type:com.github.pull.create' \
-H'ce-source:https://github.com/cloudevents/spec/pull/123' \
-H'ce-id:45c83279-c8a1-4db6-a703-b3768db93887' \
-H'ce-time:2019-06-21T17:31:00Z' \
http://localhost:3000/v02
```
__A Binary One with Extension__
```bash
curl -X POST \
-d'@../payload/data-0.json' \
-H'Content-Type:application/json' \
-H'ce-specversion:0.2' \
-H'ce-type:com.github.pull.create' \
-H'ce-source:https://github.com/cloudevents/spec/pull/123' \
-H'ce-id:45c83279-c8a1-4db6-a703-b3768db93887' \
-H'ce-time:2019-06-21T17:31:00Z' \
-H'ce-my-extension:extension value' \
http://localhost:3000/v02
```
__A Batch One__
TODO

View File

@ -6,9 +6,6 @@ const app = express();
const v03 = require("cloudevents-sdk/v03");
const unmarshaller03 = new v03.HTTPUnmarshaller();
const v02 = require("cloudevents-sdk/v02");
const unmarshaller02 = new v02.HTTPUnmarshaller();
const v1 = require("cloudevents-sdk/v1");
const structured1 = new v1.StructuredHTTPReceiver();
const binary1 = new v1.BinaryHTTPReceiver();
@ -88,27 +85,6 @@ app.post("/v03", function(req, res) {
});
});
app.post("/v02", function(req, res) {
console.log(req.headers);
console.log(req.body);
unmarshaller02.unmarshall(req.body, req.headers)
.then((cloudevent) => {
// pretty print
console.log("Accepted event:");
console.log(JSON.stringify(cloudevent.format(), null, 2));
res.status(201)
.json(cloudevent.format());
})
.catch((err) => {
console.error(err);
res.status(415)
.header("Content-Type", "application/json")
.send(JSON.stringify(err));
});
});
app.listen(3000, function() {
console.log("Example app listening on port 3000!");
});

View File

@ -1,11 +0,0 @@
{
"specversion":"0.2",
"type":"com.github.pull.create",
"source":"https://github.com/cloudevents/spec/pull/123",
"id":"45c83279-c8a1-4db6-a703-b3768db93887",
"time":"2019-06-21T17:31:00Z",
"contenttype":"application/json",
"data":{
"much":"wow"
}
}

View File

@ -1,14 +0,0 @@
{
"specversion":"0.2",
"type":"com.github.pull.create",
"source":"https://github.com/cloudevents/spec/pull/123",
"id":"45c83279-c8a1-4db6-a703-b3768db93887",
"time":"2019-06-21T17:31:00Z",
"contenttype":"application/json",
"data":{
"much":"wow"
},
"my-extension" : {
"some" : "thing"
}
}

View File

@ -1,81 +0,0 @@
{
"$ref": "#/definitions/event",
"definitions": {
"specversion": {
"type": "string",
"minLength": 1,
"const": "0.2"
},
"contenttype": {
"type": "string"
},
"data": {
"type": [
"object",
"string"
]
},
"event": {
"properties": {
"specversion": {
"$ref": "#/definitions/specversion"
},
"contenttype": {
"$ref": "#/definitions/contenttype"
},
"data": {
"$ref": "#/definitions/data"
},
"id": {
"$ref": "#/definitions/id"
},
"time": {
"$ref": "#/definitions/time"
},
"schemaurl": {
"$ref": "#/definitions/schemaurl"
},
"type": {
"$ref": "#/definitions/type"
},
"extensions": {
"$ref": "#/definitions/extensions"
},
"source": {
"$ref": "#/definitions/source"
}
},
"required": [
"specversion",
"id",
"type",
"source"
],
"type": "object"
},
"id": {
"type": "string",
"minLength": 1
},
"time": {
"format": "date-time",
"type": "string"
},
"schemaurl": {
"type": "string",
"format": "uri"
},
"type": {
"type": "string",
"minLength": 1
},
"extensions": {
"type": "object"
},
"source": {
"format": "uri-reference",
"type": "string"
}
},
"type": "object"
}

View File

@ -1,3 +0,0 @@
var Unmarshaller = require("../../lib/bindings/http/unmarshaller_0_2.js");
module.exports = Unmarshaller;

View File

@ -3,7 +3,6 @@ module.exports = {
HEADERS: "headers",
CHARSET_DEFAULT: "utf-8",
SPEC_V02: "0.2",
SPEC_V03: "0.3",
SPEC_V1: "1.0",
@ -23,26 +22,6 @@ module.exports = {
DEFAULT_CONTENT_TYPE: "application/json; charset=utf-8",
DEFAULT_CE_CONTENT_TYPE: "application/cloudevents+json; charset=utf-8",
BINARY_HEADERS_02: {
TYPE: "ce-type",
SPEC_VERSION: "ce-specversion",
SOURCE: "ce-source",
ID: "ce-id",
TIME: "ce-time",
SCHEMA_URL: "ce-schemaurl",
EXTENSIONS_PREFIX: "ce-"
},
STRUCTURED_ATTRS_02: {
TYPE: "type",
SPEC_VERSION: "specversion",
SOURCE: "source",
ID: "id",
TIME: "time",
SCHEMA_URL: "schemaurl",
CONTENT_TYPE: "contenttype",
DATA: "data"
},
BINARY_HEADERS_03: {
TYPE: "ce-type",
SPEC_VERSION: "ce-specversion",

View File

@ -1,91 +0,0 @@
const axios = require("axios");
const Constants = require("./constants.js");
const headerByGetter = {};
headerByGetter.getContenttype = {
name: Constants.HEADER_CONTENT_TYPE,
parser: (v) => v
};
headerByGetter.getType = {
name: "CE-EventType",
parser: (v) => v
};
headerByGetter.getSpecversion = {
name: "CE-CloudEventsVersion",
parser: (v) => v
};
headerByGetter.getSource = {
name: "CE-Source",
parser: (v) => v
};
headerByGetter.getId = {
name: "CE-EventID",
parser: (v) => v
};
headerByGetter.getEventTypeVersion = {
name: "CE-EventTypeVersion",
parser: (v) => v
};
headerByGetter.getTime = {
name: "CE-EventTime",
parser: (v) => v
};
headerByGetter.getSchemaurl = {
name: "CE-SchemaURL",
parser: (v) => v
};
function HTTPBinary(configuration) {
this.config = JSON.parse(JSON.stringify(configuration));
if (!this.config.headers) {
this.config.headers = {};
}
this.config.headers[Constants.HEADER_CONTENT_TYPE] =
`${Constants.MIME_JSON}; charset=${Constants.CHARSET_DEFAULT}`;
}
HTTPBinary.prototype.emit = function(cloudevent) {
// Create new request object
const _config = JSON.parse(JSON.stringify(this.config));
// Always set stuff in _config
const _headers = _config.headers;
Object.keys(headerByGetter)
.filter((getter) => cloudevent[getter]())
.forEach((getter) => {
const header = headerByGetter[getter];
_headers[header.name] =
header.parser(
cloudevent[getter]()
);
});
// Set the cloudevent payload
_config.data = cloudevent.format().data;
// EXTENSION CONTEXT ATTRIBUTES
const exts = cloudevent.getExtensions();
Object.keys(exts)
.filter((ext) => Object.hasOwnProperty.call(exts, ext))
.forEach((ext) => {
const capsExt = ext.charAt(0).toUpperCase() + ext.slice(1);
_headers[`CE-X-${capsExt}`] = exts[ext];
});
// Return the Promise
return axios.request(_config);
};
module.exports = HTTPBinary;

View File

@ -1,56 +0,0 @@
const BinaryHTTPEmitter = require("./emitter_binary.js");
const Constants = require("./constants.js");
const headerByGetter = {};
headerByGetter.getContenttype = {
name: Constants.HEADER_CONTENT_TYPE,
parser: (v) => v
};
headerByGetter.getType = {
name: Constants.BINARY_HEADERS_02.TYPE,
parser: (v) => v
};
headerByGetter.getSpecversion = {
name: Constants.BINARY_HEADERS_02.SPEC_VERSION,
parser: (v) => v
};
headerByGetter.getSource = {
name: Constants.BINARY_HEADERS_02.SOURCE,
parser: (v) => v
};
headerByGetter.getId = {
name: Constants.BINARY_HEADERS_02.ID,
parser: (v) => v
};
headerByGetter.getTime = {
name: Constants.BINARY_HEADERS_02.TIME,
parser: (v) => v
};
headerByGetter.getSchemaurl = {
name: Constants.BINARY_HEADERS_02.SCHEMA_URL,
parser: (v) => v
};
function HTTPBinary02(configuration) {
this.emitter = new BinaryHTTPEmitter(
configuration,
headerByGetter,
Constants.BINARY_HEADERS_02.EXTENSIONS_PREFIX
);
}
HTTPBinary02.prototype.emit = function(cloudevent) {
return this.emitter.emit(cloudevent);
};
module.exports = {
HTTPBinary02
};

View File

@ -1,27 +0,0 @@
const axios = require("axios");
const Constants = require("./constants.js");
function HTTPStructured(configuration) {
this.config = JSON.parse(JSON.stringify(configuration));
if (!this.config.headers) {
this.config.headers = {};
}
this.config.headers[Constants.HEADER_CONTENT_TYPE] =
`${Constants.MIME_CE_JSON}; charset=${Constants.CHARSET_DEFAULT}`;
}
HTTPStructured.prototype.emit = function(cloudevent) {
// Create new request object
const _config = JSON.parse(JSON.stringify(this.config));
// Set the cloudevent payload
_config.data = cloudevent.format();
// Return the Promise
return axios.request(_config);
};
module.exports = HTTPStructured;

View File

@ -1,11 +0,0 @@
const StructuredHTTPEmitter = require("./emitter_structured.js");
function HTTPStructured(configuration) {
this.emitter = new StructuredHTTPEmitter(configuration);
}
HTTPStructured.prototype.emit = function(cloudevent) {
return this.emitter.emit(cloudevent);
};
module.exports = HTTPStructured;

View File

@ -1,79 +0,0 @@
const Constants = require("./constants.js");
const Spec02 = require("../../specs/spec_0_2.js");
const JSONParser = require("../../formats/json/parser.js");
const BinaryHTTPReceiver = require("./receiver_binary.js");
const parserByType = {};
parserByType[Constants.MIME_JSON] = new JSONParser();
parserByType[Constants.MIME_OCTET_STREAM] = {
parse(payload) { return payload; }
};
const parsersByEncoding = {};
parsersByEncoding.null = parserByType;
parsersByEncoding[undefined] = parserByType;
const allowedContentTypes = [];
allowedContentTypes.push(Constants.MIME_JSON);
allowedContentTypes.push(Constants.MIME_OCTET_STREAM);
const requiredHeaders = [];
requiredHeaders.push(Constants.BINARY_HEADERS_02.TYPE);
requiredHeaders.push(Constants.BINARY_HEADERS_02.SPEC_VERSION);
requiredHeaders.push(Constants.BINARY_HEADERS_02.SOURCE);
requiredHeaders.push(Constants.BINARY_HEADERS_02.ID);
const setterByHeader = {};
setterByHeader[Constants.BINARY_HEADERS_02.TYPE] = {
name: "type",
parser: (v) => v
};
setterByHeader[Constants.BINARY_HEADERS_02.SPEC_VERSION] = {
name: "specversion",
parser: () => "0.2"
};
setterByHeader[Constants.BINARY_HEADERS_02.SOURCE] = {
name: "source",
parser: (v) => v
};
setterByHeader[Constants.BINARY_HEADERS_02.ID] = {
name: "id",
parser: (v) => v
};
setterByHeader[Constants.BINARY_HEADERS_02.TIME] = {
name: "time",
parser: (v) => new Date(Date.parse(v))
};
setterByHeader[Constants.BINARY_HEADERS_02.SCHEMA_URL] = {
name: "schemaurl",
parser: (v) => v
};
setterByHeader[Constants.HEADER_CONTENT_TYPE] = {
name: "contenttype",
parser: (v) => v
};
// Leaving this in place for now. TODO: fixme
// eslint-disable-next-line
function Receiver(configuration) {
this.receiver = new BinaryHTTPReceiver(
parsersByEncoding,
setterByHeader,
allowedContentTypes,
requiredHeaders,
Spec02,
Constants.SPEC_V02,
Constants.BINARY_HEADERS_02.EXTENSIONS_PREFIX
);
}
Receiver.prototype.check = function(payload, headers) {
this.receiver.check(payload, headers);
};
Receiver.prototype.parse = function(payload, headers) {
return this.receiver.parse(payload, headers);
};
module.exports = Receiver;

View File

@ -1,69 +0,0 @@
const Constants = require("./constants.js");
const Spec02 = require("../../specs/spec_0_2.js");
const JSONParser = require("../../formats/json/parser.js");
const StructuredHTTPReceiver = require("./receiver_structured.js");
const jsonParserSpec02 = new JSONParser();
const parserByMime = {};
parserByMime[Constants.MIME_JSON] = jsonParserSpec02;
parserByMime[Constants.MIME_CE_JSON] = jsonParserSpec02;
const allowedContentTypes = [];
allowedContentTypes.push(Constants.MIME_CE_JSON);
const setterByAttribute = {};
setterByAttribute[Constants.STRUCTURED_ATTRS_02.TYPE] = {
name: "type",
parser: (v) => v
};
setterByAttribute[Constants.STRUCTURED_ATTRS_02.SPEC_VERSION] = {
name: "specversion",
parser: (v) => v
};
setterByAttribute[Constants.STRUCTURED_ATTRS_02.SOURCE] = {
name: "source",
parser: (v) => v
};
setterByAttribute[Constants.STRUCTURED_ATTRS_02.ID] = {
name: "id",
parser: (v) => v
};
setterByAttribute[Constants.STRUCTURED_ATTRS_02.TIME] = {
name: "time",
parser: (v) => new Date(Date.parse(v))
};
setterByAttribute[Constants.STRUCTURED_ATTRS_02.SCHEMA_URL] = {
name: "schemaurl",
parser: (v) => v
};
setterByAttribute[Constants.STRUCTURED_ATTRS_02.CONTENT_TYPE] = {
name: "contenttype",
parser: (v) => v
};
setterByAttribute[Constants.STRUCTURED_ATTRS_02.DATA] = {
name: "data",
parser: (v) => v
};
// Leaving this in place for now. TODO: fixme
// eslint-disable-next-line
function Receiver(configuration) {
this.receiver = new StructuredHTTPReceiver(
parserByMime,
setterByAttribute,
allowedContentTypes,
Spec02
);
}
Receiver.prototype.check = function(payload, headers) {
this.receiver.check(payload, headers);
};
Receiver.prototype.parse = function(payload, headers) {
return this.receiver.parse(payload, headers);
};
module.exports = Receiver;

View File

@ -1,19 +0,0 @@
const GenericUnmarshaller = require("./unmarshaller.js");
const StructuredReceiver = require("./receiver_structured_0_2.js");
const BinaryReceiver = require("./receiver_binary_0_2.js");
const RECEIVER_BY_BINDING = {
structured: new StructuredReceiver(),
binary: new BinaryReceiver()
};
const Unmarshaller = function() {
this.unmarshaller = new GenericUnmarshaller(RECEIVER_BY_BINDING);
};
Unmarshaller.prototype.unmarshall = function(payload, headers) {
return this.unmarshaller.unmarshall(payload, headers);
};
module.exports = Unmarshaller;

View File

@ -1,10 +1,5 @@
const Spec01 = require("./specs/spec_0_1.js");
const Spec02 = require("./specs/spec_0_2.js");
const JSONFormatter01 = require("./formats/json/formatter.js");
const HTTPStructured01 = require("./bindings/http/emitter_structured_0_1.js");
const HTTPStructured02 = require("./bindings/http/emitter_structured_0_2.js");
const HTTPBinary01 = require("./bindings/http/emitter_binary_0_1.js");
const { HTTPBinary02 } = require("./bindings/http/emitter_binary_0_2.js");
const Spec = require("./specs/spec_1.js");
const Formatter = require("./formats/json/formatter.js");
/*
* Class created using the Builder Design Pattern.
@ -12,8 +7,8 @@ const { HTTPBinary02 } = require("./bindings/http/emitter_binary_0_2.js");
* https://en.wikipedia.org/wiki/Builder_pattern
*/
function Cloudevent(_spec, _formatter) {
this.spec = (_spec) ? new _spec(Cloudevent) : new Spec01(Cloudevent);
this.formatter = (_formatter) || new JSONFormatter01();
this.spec = (_spec) ? new _spec(Cloudevent) : new Spec(Cloudevent);
this.formatter = (_formatter) ? new _formatter() : new Formatter();
// The map of extensions
this.extensions = {};
@ -90,13 +85,13 @@ Cloudevent.prototype.getSchemaurl = function() {
return this.spec.getSchemaurl();
};
Cloudevent.prototype.contenttype = function(_contenttype) {
this.spec.contenttype(_contenttype);
Cloudevent.prototype.dataContenttype = function(_contenttype) {
this.spec.dataContenttype(_contenttype);
return this;
};
Cloudevent.prototype.getContenttype = function() {
return this.spec.getContenttype();
Cloudevent.prototype.getDataContenttype = function() {
return this.spec.getDataContenttype();
};
Cloudevent.prototype.data = function(_data) {
@ -121,28 +116,12 @@ Cloudevent.prototype.getExtensions = function() {
return this.extensions;
};
/*
* Export the specs
*/
Cloudevent.specs = {
0.1: Spec01,
0.2: Spec02
};
/*
* Export the formats
*/
Cloudevent.formats = {
json: JSONFormatter01,
"json0.1": JSONFormatter01
};
Cloudevent.bindings = {
"http-structured": HTTPStructured01,
"http-structured0.1": HTTPStructured01,
"http-structured0.2": HTTPStructured02,
"http-binary0.1": HTTPBinary01,
"http-binary0.2": HTTPBinary02
json: Formatter,
"json0.1": Formatter
};
module.exports = Cloudevent;

View File

@ -1,121 +0,0 @@
const uuid = require("uuid/v4");
function Spec01(_caller) {
this.payload = {
cloudEventsVersion: "0.1",
eventID: uuid()
};
/*
* Used to inject backward compatibility functions or attributes.
*/
this.caller = _caller;
/*
* Inject the method to set the version related to data attribute.
*/
this.caller.prototype.eventTypeVersion = function(_version) {
return this.spec.eventTypeVersion(_version);
};
this.caller.prototype.getEventTypeVersion = function() {
return this.spec.getEventTypeVersion();
};
}
/*
* Check the constraints.
*
* throw an error if do not pass.
*/
Spec01.prototype.check = function() {
if (!this.payload.eventType) {
throw new TypeError("'eventType' is invalid");
}
};
Spec01.prototype.type = function(_type) {
this.payload.eventType = _type;
return this;
};
Spec01.prototype.getType = function() {
return this.payload.eventType;
};
Spec01.prototype.getSpecversion = function() {
return this.payload.cloudEventsVersion;
};
Spec01.prototype.eventTypeVersion = function(version) {
this.payload.eventTypeVersion = version;
return this;
};
Spec01.prototype.getEventTypeVersion = function() {
return this.payload.eventTypeVersion;
};
Spec01.prototype.source = function(_source) {
this.payload.source = _source;
return this;
};
Spec01.prototype.getSource = function() {
return this.payload.source;
};
Spec01.prototype.id = function(_id) {
this.payload.eventID = _id;
return this;
};
Spec01.prototype.getId = function() {
return this.payload.eventID;
};
Spec01.prototype.time = function(_time) {
this.payload.eventTime = _time.toISOString();
return this;
};
Spec01.prototype.getTime = function() {
return this.payload.eventTime;
};
Spec01.prototype.schemaurl = function(_schemaurl) {
this.payload.schemaURL = _schemaurl;
return this;
};
Spec01.prototype.getSchemaurl = function() {
return this.payload.schemaURL;
};
Spec01.prototype.contenttype = function(_contenttype) {
this.payload.contentType = _contenttype;
return this;
};
Spec01.prototype.getContenttype = function() {
return this.payload.contentType;
};
Spec01.prototype.data = function(_data) {
this.payload.data = _data;
return this;
};
Spec01.prototype.getData = function() {
return this.payload.data;
};
Spec01.prototype.addExtension = function(key, value) {
if (!this.payload.extensions) {
this.payload.extensions = {};
}
this.payload.extensions[key] = value;
return this;
};
module.exports = Spec01;

View File

@ -1,130 +0,0 @@
const uuid = require("uuid/v4");
const Ajv = require("ajv");
// Reserved attributes names
const reserved = {
type: "type",
specversion: "specversion",
source: "source",
id: "id",
time: "time",
schemaurl: "schemaurl",
contenttype: "contenttype",
data: "data"
};
const schema = require("../../ext/spec_0_2.json");
const ajv = new Ajv({
// validate all keywords in the schemas with $ref
extendRefs: true
});
const validate = ajv.compile(schema);
function Spec02() {
this.payload = {
specversion: "0.2",
id: uuid()
};
}
/*
* Check the spec constraints
*/
Spec02.prototype.check = function(ce) {
var toCheck = ce;
if (!toCheck) {
toCheck = this.payload;
}
const valid = validate(toCheck);
if (!valid) {
const err = new TypeError("invalid payload");
err.errors = validate.errors;
throw err;
}
};
Spec02.prototype.type = function(_type) {
this.payload.type = _type;
return this;
};
Spec02.prototype.getType = function() {
return this.payload.type;
};
Spec02.prototype.specversion = function() {
// does not set! This is right
return this;
};
Spec02.prototype.getSpecversion = function() {
return this.payload.specversion;
};
Spec02.prototype.source = function(_source) {
this.payload.source = _source;
return this;
};
Spec02.prototype.getSource = function() {
return this.payload.source;
};
Spec02.prototype.id = function(_id) {
this.payload.id = _id;
return this;
};
Spec02.prototype.getId = function() {
return this.payload.id;
};
Spec02.prototype.time = function(_time) {
this.payload.time = _time.toISOString();
return this;
};
Spec02.prototype.getTime = function() {
return this.payload.time;
};
Spec02.prototype.schemaurl = function(_schemaurl) {
this.payload.schemaurl = _schemaurl;
return this;
};
Spec02.prototype.getSchemaurl = function() {
return this.payload.schemaurl;
};
Spec02.prototype.contenttype = function(_contenttype) {
this.payload.contenttype = _contenttype;
return this;
};
Spec02.prototype.getContenttype = function() {
return this.payload.contenttype;
};
Spec02.prototype.data = function(_data) {
this.payload.data = _data;
return this;
};
Spec02.prototype.getData = function() {
return this.payload.data;
};
Spec02.prototype.addExtension = function(key, value) {
if (!Object.prototype.hasOwnProperty.call(reserved, key)) {
this.payload[key] = value;
} else {
throw new TypeError(`Reserved attribute name: '${key}'`);
}
return this;
};
module.exports = Spec02;

View File

@ -168,15 +168,6 @@ Spec03.prototype.getDataContentEncoding = function() {
return this.payload.datacontentencoding;
};
// maps to datacontenttype
Spec03.prototype.contenttype = function(_contenttype) {
this.payload.datacontenttype = _contenttype;
return this;
};
Spec03.prototype.getContenttype = function() {
return this.payload.datacontenttype;
};
Spec03.prototype.dataContentType = function(_contenttype) {
this.payload.datacontenttype = _contenttype;
return this;

View File

@ -1,428 +0,0 @@
var expect = require("chai").expect;
var HTTPBinaryReceiver02 =
require("../../../lib/bindings/http/receiver_binary_0_2.js");
var receiver = new HTTPBinaryReceiver02();
describe("HTTP Transport Binding Binary Receiver for CloudEvents v0.2", () => {
describe("Check", () => {
it("Throw error when payload arg is null or undefined", () => {
// setup
var payload = null;
var attributes = {};
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("payload is null or undefined");
});
it("Throw error when attributes arg is null or undefined", () => {
// setup
var payload = {};
var attributes = null;
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("attributes is null or undefined");
});
it("Throw error when payload is not an object or string", () => {
// setup
var payload = 1.2;
var attributes = {};
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("payload must be an object or a string");
});
it("Throw error when headers has no 'ce-type'", () => {
// setup
var payload = {};
var attributes = {
"ce-specversion": "specversion",
"ce-source": "source",
"ce-id": "id",
"Content-Type": "application/json"
};
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("header 'ce-type' not found");
});
it("Throw error when headers has no 'ce-specversion'", () => {
// setup
var payload = {};
var attributes = {
"ce-type": "type",
"ce-source": "source",
"ce-id": "id",
"Content-Type": "application/json"
};
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("header 'ce-specversion' not found");
});
it("Throw error when headers has no 'ce-source'", () => {
// setup
var payload = {};
var attributes = {
"ce-type": "type",
"ce-specversion": "specversion",
"ce-id": "id",
"Content-Type": "application/json"
};
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("header 'ce-source' not found");
});
it("Throw error when headers has no 'ce-id'", () => {
// setup
var payload = {};
var attributes = {
"ce-type": "type",
"ce-specversion": "specversion",
"ce-source": "source",
"Content-Type": "application/json"
};
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("header 'ce-id' not found");
});
it("Throw error when spec is not 0.2", () => {
// setup
var payload = {};
var attributes = {
"ce-type": "type",
"ce-specversion": "specversion",
"ce-source": "source",
"ce-id": "id",
"Content-Type": "application/json"
};
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("invalid spec version");
});
it("Throw error when the content-type is invalid", () => {
// setup
var payload = {};
var attributes = {
"ce-type": "type",
"ce-specversion": "specversion",
"ce-source": "source",
"ce-id": "id",
"Content-Type": "text/html"
};
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("invalid content type");
});
it("No error when all required headers are in place", () => {
// setup
var payload = {};
var attributes = {
"ce-type": "type",
"ce-specversion": "0.2",
"ce-source": "source",
"ce-id": "id",
"Content-Type": "application/json"
};
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.not.throw();
});
});
describe("Parse", () => {
it("Cloudevent contains 'type'", () => {
// setup
var payload = {
data: "dataString"
};
var attributes = {
"ce-type": "type",
"ce-specversion": "0.2",
"ce-source": "source",
"ce-id": "id",
"ce-time": "2019-06-16T11:42:00Z",
"ce-schemaurl": "http://schema.registry/v1",
"Content-Type": "application/json"
};
// act
var actual = receiver.parse(payload, attributes);
// assert
expect(actual.getType())
.to.equal("type");
});
it("Cloudevent contains 'specversion'", () => {
// setup
var payload = {
data: "dataString"
};
var attributes = {
"ce-type": "type",
"ce-specversion": "0.2",
"ce-source": "source",
"ce-id": "id",
"ce-time": "2019-06-16T11:42:00Z",
"ce-schemaurl": "http://schema.registry/v1",
"Content-Type": "application/json"
};
// act
var actual = receiver.parse(payload, attributes);
// assert
expect(actual.getSpecversion())
.to.equal("0.2");
});
it("Cloudevent contains 'source'", () => {
// setup
var payload = {
data: "dataString"
};
var attributes = {
"ce-type": "type",
"ce-specversion": "0.2",
"ce-source": "/source",
"ce-id": "id",
"ce-time": "2019-06-16T11:42:00Z",
"ce-schemaurl": "http://schema.registry/v1",
"Content-Type": "application/json"
};
// act
var actual = receiver.parse(payload, attributes);
// assert
expect(actual.getSource())
.to.equal("/source");
});
it("Cloudevent contains 'id'", () => {
// setup
var payload = {
data: "dataString"
};
var attributes = {
"ce-type": "type",
"ce-specversion": "0.2",
"ce-source": "/source",
"ce-id": "id",
"ce-time": "2019-06-16T11:42:00Z",
"ce-schemaurl": "http://schema.registry/v1",
"Content-Type": "application/json"
};
// act
var actual = receiver.parse(payload, attributes);
// assert
expect(actual.getId())
.to.equal("id");
});
it("Cloudevent contains 'time'", () => {
// setup
var payload = {
data: "dataString"
};
var attributes = {
"ce-type": "type",
"ce-specversion": "0.2",
"ce-source": "/source",
"ce-id": "id",
"ce-time": "2019-06-16T11:42:00.000Z",
"ce-schemaurl": "http://schema.registry/v1",
"Content-Type": "application/json"
};
// act
var actual = receiver.parse(payload, attributes);
// assert
expect(actual.getTime())
.to.equal("2019-06-16T11:42:00.000Z");
});
it("Cloudevent contains 'schemaurl'", () => {
// setup
var payload = {
data: "dataString"
};
var attributes = {
"ce-type": "type",
"ce-specversion": "0.2",
"ce-source": "/source",
"ce-id": "id",
"ce-time": "2019-06-16T11:42:00Z",
"ce-schemaurl": "http://schema.registry/v1",
"Content-Type": "application/json"
};
// act
var actual = receiver.parse(payload, attributes);
// assert
expect(actual.getSchemaurl())
.to.equal("http://schema.registry/v1");
});
it("Cloudevent contains 'contenttype' (application/json)", () => {
// setup
var payload = {
data: "dataString"
};
var attributes = {
"ce-type": "type",
"ce-specversion": "0.2",
"ce-source": "/source",
"ce-id": "id",
"ce-time": "2019-06-16T11:42:00Z",
"ce-schemaurl": "http://schema.registry/v1",
"Content-Type": "application/json"
};
// act
var actual = receiver.parse(payload, attributes);
// assert
expect(actual.getContenttype())
.to.equal("application/json");
});
it("Cloudevent contains 'contenttype' (application/octet-stream)", () => {
// setup
var payload = "The payload is binary data";
var attributes = {
"ce-type": "type",
"ce-specversion": "0.2",
"ce-source": "/source",
"ce-id": "id",
"ce-time": "2019-06-16T11:42:00Z",
"ce-schemaurl": "http://schema.registry/v1",
"Content-Type": "application/octet-stream"
};
// act
var actual = receiver.parse(payload, attributes);
// assert
expect(actual.getContenttype())
.to.equal("application/octet-stream");
});
it("Cloudevent contains 'data' (application/json)", () => {
// setup
var payload = {
data: "dataString"
};
var attributes = {
"ce-type": "type",
"ce-specversion": "0.2",
"ce-source": "/source",
"ce-id": "id",
"ce-time": "2019-06-16T11:42:00Z",
"ce-schemaurl": "http://schema.registry/v1",
"Content-Type": "application/json"
};
// act
var actual = receiver.parse(payload, attributes);
// assert
expect(actual.getData())
.to.deep.equal(payload);
});
it("Cloudevent contains 'data' (application/octet-stream)", () => {
// setup
var payload = "The payload is binary data";
var attributes = {
"ce-type": "type",
"ce-specversion": "0.2",
"ce-source": "/source",
"ce-id": "id",
"ce-time": "2019-06-16T11:42:00Z",
"ce-schemaurl": "http://schema.registry/v1",
"Content-Type": "application/octet-stream"
};
// act
var actual = receiver.parse(payload, attributes);
// assert
expect(actual.getData())
.to.deep.equal(payload);
});
it("No error when all attributes are in place", () => {
// setup
var payload = {
data: "dataString"
};
var attributes = {
"ce-type": "type",
"ce-specversion": "0.2",
"ce-source": "source",
"ce-id": "id",
"ce-time": "2019-06-16T11:42:00Z",
"ce-schemaurl": "http://schema.registry/v1",
"Content-Type": "application/json"
};
// act
var actual = receiver.parse(payload, attributes);
// assert
expect(actual)
.to.be.an("object");
expect(actual)
.to.have.property("format");
});
it("Should accept 'extension1'", () => {
// setup
var extension1 = "mycuston-ext1";
var payload = {
data: "dataString"
};
var attributes = {
"ce-type": "type",
"ce-specversion": "0.2",
"ce-source": "source",
"ce-id": "id",
"ce-time": "2019-06-16T11:42:00Z",
"ce-schemaurl": "http://schema.registry/v1",
"Content-Type": "application/json",
"ce-extension1": extension1
};
// act
var actual = receiver.parse(payload, attributes);
var actualExtensions = actual.getExtensions();
// assert
expect(actualExtensions.extension1)
.to.equal(extension1);
});
});
});

View File

@ -285,7 +285,7 @@ describe("HTTP Transport Binding Binary Receiver for CloudEvents v0.3", () => {
.to.equal("http://schema.registry/v1");
});
it("Cloudevent contains 'contenttype' (application/json)", () => {
it("Cloudevent contains 'datacontenttype' (application/json)", () => {
// setup
var payload = {
data: "dataString"
@ -304,30 +304,31 @@ describe("HTTP Transport Binding Binary Receiver for CloudEvents v0.3", () => {
var actual = receiver.parse(payload, attributes);
// assert
expect(actual.getContenttype())
expect(actual.getDataContentType())
.to.equal("application/json");
});
it("Cloudevent contains 'contenttype' (application/octet-stream)", () => {
it("Cloudevent contains 'datacontenttype' (application/octet-stream)",
() => {
// setup
var payload = "The payload is binary data";
var attributes = {
"ce-type": "type",
"ce-specversion": "0.3",
"ce-source": "/source",
"ce-id": "id",
"ce-time": "2019-06-16T11:42:00Z",
"ce-schemaurl": "http://schema.registry/v1",
"Content-Type": "application/octet-stream"
};
var payload = "The payload is binary data";
var attributes = {
"ce-type": "type",
"ce-specversion": "0.3",
"ce-source": "/source",
"ce-id": "id",
"ce-time": "2019-06-16T11:42:00Z",
"ce-schemaurl": "http://schema.registry/v1",
"Content-Type": "application/octet-stream"
};
// act
var actual = receiver.parse(payload, attributes);
// act
var actual = receiver.parse(payload, attributes);
// assert
expect(actual.getContenttype())
.to.equal("application/octet-stream");
});
// assert
expect(actual.getDataContentType())
.to.equal("application/octet-stream");
});
it("Cloudevent contains 'data' (application/json)", () => {
// setup

View File

@ -1,158 +0,0 @@
var expect = require("chai").expect;
var Cloudevent = require("../../../index.js");
var HTTPStructuredReceiver02 =
require("../../../lib/bindings/http/receiver_structured_0_2.js");
var receiver = new HTTPStructuredReceiver02();
const type = "com.github.pull.create";
const source = "urn:event:from:myapi/resourse/123";
const now = new Date();
const schemaurl = "http://cloudevents.io/schema.json";
const ceContentType = "application/json";
const data = {
foo: "bar"
};
describe("HTTP Transport Binding Structured Receiver for CloudEvents v0.2",
() => {
describe("Check", () => {
it("Throw error when payload arg is null or undefined", () => {
// setup
var payload = null;
var attributes = {};
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("payload is null or undefined");
});
it("Throw error when attributes arg is null or undefined", () => {
// setup
var payload = {};
var attributes = null;
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("attributes is null or undefined");
});
it("Throw error when payload is not an object or string", () => {
// setup
var payload = 1.0;
var attributes = {};
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("payload must be an object or string");
});
it("Throw error when the content-type is invalid", () => {
// setup
var payload = {};
var attributes = {
"Content-Type": "text/html"
};
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("invalid content type");
});
it("No error when all required stuff are in place", () => {
// setup
var payload = {};
var attributes = {
"Content-Type": "application/cloudevents+json"
};
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.not.throw();
});
});
describe("Parse", () => {
it("Throw error when the event does not follow the spec 0.2", () => {
// setup
var payload =
new Cloudevent()
.type(type)
.source(source)
.contenttype(ceContentType)
.time(now)
.schemaurl(schemaurl)
.data(data)
.toString();
var headers = {
"Content-Type": "application/cloudevents+json"
};
// act and assert
expect(receiver.parse.bind(receiver, payload, headers))
.to.throw("invalid payload");
});
it("Should accept event that follow the spec 0.2", () => {
// setup
var id = "id-x0dk";
var payload =
new Cloudevent(Cloudevent.specs["0.2"])
.type(type)
.source(source)
.id(id)
.contenttype(ceContentType)
.time(now)
.schemaurl(schemaurl)
.data(data)
.toString();
var headers = {
"content-type": "application/cloudevents+json"
};
// act
var actual = receiver.parse(payload, headers);
// assert
expect(actual)
.to.be.an("object");
expect(actual)
.to.have.property("format");
expect(actual.getId())
.to.equals(id);
});
it("Should accept 'extension1'", () => {
// setup
var extension1 = "mycuston-ext1";
var payload =
new Cloudevent(Cloudevent.specs["0.2"])
.type(type)
.source(source)
.contenttype(ceContentType)
.time(now)
.schemaurl(schemaurl)
.data(data)
.addExtension("extension1", extension1)
.toString();
var headers = {
"content-type": "application/cloudevents+json"
};
// act
var actual = receiver.parse(payload, headers);
var actualExtensions = actual.getExtensions();
// assert
expect(actualExtensions.extension1)
.to.equal(extension1);
});
});
});

View File

@ -1,6 +1,5 @@
var expect = require("chai").expect;
var v03 = require("../../../v03/index.js");
var Cloudevent = require("../../../index.js");
var HTTPStructuredReceiver =
require("../../../lib/bindings/http/receiver_structured_0_3.js");
@ -23,186 +22,198 @@ const ext1Value = "foobar";
const ext2Name = "extension2";
const ext2Value = "acme";
describe("HTTP Transport Binding Structured Receiver for CloudEvents v0.3",
() => {
describe("Check", () => {
it("Throw error when payload arg is null or undefined", () => {
describe("HTTP Transport Binding Structured Receiver CloudEvents v0.3", () => {
describe("Check", () => {
it("Throw error when payload arg is null or undefined", () => {
// setup
var payload = null;
var attributes = {};
var payload = null;
var attributes = {};
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("payload is null or undefined");
});
it("Throw error when attributes arg is null or undefined", () => {
// setup
var payload = {};
var attributes = null;
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("attributes is null or undefined");
});
it("Throw error when payload is not an object or string", () => {
// setup
var payload = 1.0;
var attributes = {};
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("payload must be an object or string");
});
it("Throw error when the content-type is invalid", () => {
// setup
var payload = {};
var attributes = {
"Content-Type": "text/html"
};
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("invalid content type");
});
it("Throw error data content encoding is base64, but 'data' is not",
() => {
// setup
const payload = v03.event()
.type(type)
.source(source)
.dataContentType("text/plain")
.dataContentEncoding("base64")
.time(now)
.schemaurl(schemaurl)
.data("No base 64 value")
.addExtension(ext1Name, ext1Value)
.addExtension(ext2Name, ext2Value)
.toString();
const attributes = {
"Content-Type": "application/cloudevents+json"
};
// act and assert
expect(receiver.parse.bind(receiver, payload, attributes))
.to.throw("invalid payload");
});
it("No error when all required stuff are in place", () => {
// setup
var payload = {};
var attributes = {
"Content-Type": "application/cloudevents+json"
};
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.not.throw();
});
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("payload is null or undefined");
});
describe("Parse", () => {
it("Throw error when the event does not follow the spec", () => {
it("Throw error when attributes arg is null or undefined", () => {
// setup
var payload =
new Cloudevent()
var payload = {};
var attributes = null;
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("attributes is null or undefined");
});
it("Throw error when payload is not an object or string", () => {
// setup
var payload = 1.0;
var attributes = {};
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("payload must be an object or string");
});
it("Throw error when the content-type is invalid", () => {
// setup
var payload = {};
var attributes = {
"Content-Type": "text/html"
};
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.throw("invalid content type");
});
it("Throw error data content encoding is base64, but 'data' is not",
() => {
// setup
const payload = v03.event()
.type(type)
.source(source)
.contenttype(ceContentType)
.dataContentType("text/plain")
.dataContentEncoding("base64")
.time(now)
.schemaurl(schemaurl)
.data(data)
.data("No base 64 value")
.addExtension(ext1Name, ext1Value)
.addExtension(ext2Name, ext2Value)
.toString();
var headers = {
const attributes = {
"Content-Type": "application/cloudevents+json"
};
// act and assert
expect(receiver.parse.bind(receiver, payload, headers))
expect(receiver.parse.bind(receiver, payload, attributes))
.to.throw("invalid payload");
});
it("Should accept event that follows the spec", () => {
it("No error when all required stuff are in place", () => {
// setup
var id = "id-x0dk";
var payload = v03.event()
.type(type)
.source(source)
.id(id)
.contenttype(ceContentType)
.time(now)
.schemaurl(schemaurl)
.data(data)
.toString();
var headers = {
"content-type": "application/cloudevents+json"
};
var payload = {};
var attributes = {
"Content-Type": "application/cloudevents+json"
};
// act
var actual = receiver.parse(payload, headers);
// assert
expect(actual)
.to.be.an("object");
expect(actual)
.to.have.property("format");
expect(actual.getId())
.to.equals(id);
});
it("Should accept 'extension1'", () => {
// setup
var extension1 = "mycuston-ext1";
var payload = v03.event()
.type(type)
.source(source)
.contenttype(ceContentType)
.time(now)
.schemaurl(schemaurl)
.data(data)
.addExtension("extension1", extension1)
.toString();
var headers = {
"content-type": "application/cloudevents+json"
};
// act
var actual = receiver.parse(payload, headers);
var actualExtensions = actual.getExtensions();
// assert
expect(actualExtensions.extension1)
.to.equal(extension1);
});
it("Should parse 'data' stringfied json to json object", () => {
// setup
var payload = v03.event()
.type(type)
.source(source)
.contenttype(ceContentType)
.time(now)
.schemaurl(schemaurl)
.data(JSON.stringify(data))
.toString();
var headers = {
"content-type": "application/cloudevents+json"
};
// act
var actual = receiver.parse(payload, headers);
// assert
expect(actual.getData()).to.deep.equal(data);
});
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.not.throw();
});
});
describe("Parse", () => {
it("Throw error when the event does not follow the spec", () => {
// setup
var payload = {};
var attributes = {
"Content-Type": "application/cloudevents+json"
};
// act and assert
expect(receiver.check.bind(receiver, payload, attributes))
.to.not.throw();
});
});
describe("Parse", () => {
it("Throw error when the event does not follow the spec", () => {
// setup
var payload =
v03.event()
.type(type)
.source(source)
.time(now)
.schemaurl(schemaurl)
.data(data)
.toString();
var headers = {
"Content-Type": "application/cloudevents+xml"
};
// act and assert
expect(receiver.parse.bind(receiver, payload, headers))
.to.throw("invalid content type");
});
it("Should accept event that follows the spec", () => {
// setup
var id = "id-x0dk";
var payload = v03.event()
.type(type)
.source(source)
.id(id)
.dataContentType(ceContentType)
.time(now)
.schemaurl(schemaurl)
.data(data)
.toString();
var headers = {
"content-type": "application/cloudevents+json"
};
// act
var actual = receiver.parse(payload, headers);
// assert
expect(actual)
.to.be.an("object");
expect(actual)
.to.have.property("format");
expect(actual.getId())
.to.equals(id);
});
it("Should accept 'extension1'", () => {
// setup
var extension1 = "mycuston-ext1";
var payload = v03.event()
.type(type)
.source(source)
.dataContentType(ceContentType)
.time(now)
.schemaurl(schemaurl)
.data(data)
.addExtension("extension1", extension1)
.toString();
var headers = {
"content-type": "application/cloudevents+json"
};
// act
var actual = receiver.parse(payload, headers);
var actualExtensions = actual.getExtensions();
// assert
expect(actualExtensions.extension1)
.to.equal(extension1);
});
it("Should parse 'data' stringfied json to json object", () => {
// setup
var payload = v03.event()
.type(type)
.source(source)
.dataContentType(ceContentType)
.time(now)
.schemaurl(schemaurl)
.data(JSON.stringify(data))
.toString();
var headers = {
"content-type": "application/cloudevents+json"
};
// act
var actual = receiver.parse(payload, headers);
// assert
expect(actual.getData()).to.deep.equal(data);
});
});
});

View File

@ -90,12 +90,12 @@ describe("HTTP Transport Binding Structured Receiver for CloudEvents v1.0",
.toString();
var headers = {
"Content-Type": "application/cloudevents+json"
"Content-Type": "application/cloudevents+xml"
};
// act and assert
expect(receiver.parse.bind(receiver, payload, headers))
.to.throw("invalid payload");
.to.throw("invalid content type");
});
it("Should accept event that follows the spec", () => {

View File

@ -1,207 +0,0 @@
var expect = require("chai").expect;
var Unmarshaller = require("../../../http/unmarshaller/v02.js");
var Cloudevent = require("../../../index.js");
const type = "com.github.pull.create";
const source = "urn:event:from:myapi/resourse/123";
const now = new Date();
const schemaurl = "http://cloudevents.io/schema.json";
const ceContentType = "application/json";
const data = {
foo: "bar"
};
describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.2", () => {
it("Throw error when payload is null", () => {
// setup
var payload = null;
var un = new Unmarshaller();
// act and assert
return un.unmarshall(payload)
.then(() => { throw new Error("failed"); })
.catch((err) =>
expect(err.message).to.equal("payload is null or undefined"));
});
it("Throw error when headers is null", () => {
// setup
var payload = {};
var headers = null;
var un = new Unmarshaller();
// act and assert
return un.unmarshall(payload, headers)
.then(() => { throw new Error("failed"); })
.catch((err) =>
expect(err.message).to.equal("headers is null or undefined"));
});
it("Throw error when there is no content-type header", () => {
// setup
var payload = {};
var headers = {};
var un = new Unmarshaller();
// act and assert
un.unmarshall(payload, headers)
.then(() => { throw new Error("failed"); })
.catch((err) =>
expect(err.message).to.equal("content-type header not found"));
});
it("Throw error when content-type is not allowed", () => {
// setup
var payload = {};
var headers = {
"content-type": "text/xml"
};
var un = new Unmarshaller();
// act and assert
un.unmarshall(payload, headers)
.then(() => { throw new Error("failed"); })
.catch((err) =>
expect(err.message).to.equal("content type not allowed"));
});
describe("Structured", () => {
it("Throw error when has not allowed mime", () => {
// setup
var payload = {};
var headers = {
"content-type": "application/cloudevents+zip"
};
var un = new Unmarshaller();
// act and assert
un.unmarshall(payload, headers)
.then(() => { throw new Error("failed"); })
.catch((err) =>
expect(err.message).to.equal("structured+type not allowed"));
});
it("Throw error when the event does not follow the spec 0.2", () => {
// setup
var payload =
new Cloudevent()
.type(type)
.source(source)
.contenttype(ceContentType)
.time(now)
.schemaurl(schemaurl)
.data(data)
.toString();
var headers = {
"content-type": "application/cloudevents+json"
};
var un = new Unmarshaller();
// act and assert
un.unmarshall(payload, headers)
.then(() => { throw new Error("failed"); })
.catch((err) =>
expect(err.message).to.equal("invalid payload"));
});
it("Should accept event that follow the spec 0.2", () => {
// setup
var payload =
new Cloudevent(Cloudevent.specs["0.2"])
.type(type)
.source(source)
.contenttype(ceContentType)
.time(now)
.schemaurl(schemaurl)
.data(data)
.toString();
var headers = {
"content-type": "application/cloudevents+json"
};
var un = new Unmarshaller();
// act and assert
un.unmarshall(payload, headers)
.then((actual) =>
expect(actual).to.be.an("object"));
});
});
describe("Binary", () => {
it("Throw error when has not allowed mime", () => {
// setup
var payload = {
data: "dataString"
};
var attributes = {
"ce-type": "type",
"ce-specversion": "0.2",
"ce-source": "source",
"ce-id": "id",
"ce-time": "2019-06-16T11:42:00Z",
"ce-schemaurl": "http://schema.registry/v1",
"Content-Type": "text/html"
};
var un = new Unmarshaller();
// act and assert
un.unmarshall(payload, attributes)
.then(() => { throw new Error("failed"); })
.catch((err) =>
expect(err.message).to.equal("content type not allowed"));
});
it("Throw error when the event does not follow the spec 0.2", () => {
// setup
var payload = {
data: "dataString"
};
var attributes = {
"ce-type": "type",
"CE-CloudEventsVersion": "0.1",
"ce-source": "source",
"ce-id": "id",
"ce-time": "2019-06-16T11:42:00Z",
"ce-schemaurl": "http://schema.registry/v1",
"Content-Type": "application/json"
};
var un = new Unmarshaller();
// act and assert
un.unmarshall(payload, attributes)
.then(() => { throw new Error("failed"); })
.catch((err) =>
expect(err.message).to.not.empty);
});
it("No error when all attributes are in place", () => {
// setup
var payload = {
data: "dataString"
};
var attributes = {
"ce-type": "type",
"ce-specversion": "0.2",
"ce-source": "source",
"ce-id": "id",
"ce-time": "2019-06-16T11:42:00Z",
"ce-schemaurl": "http://schema.registry/v1",
"Content-Type": "application/json"
};
var un = new Unmarshaller();
// act and assert
un.unmarshall(payload, attributes)
.then((actual) => expect(actual).to.be.an("object"));
});
});
});

View File

@ -87,10 +87,10 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => {
it("Throw error when the event does not follow the spec 0.3", () => {
// setup
var payload =
new Cloudevent()
new v03.CloudEvent(v03.Spec)
.type(type)
.source(source)
.contenttype(ceContentType)
.dataContentType(ceContentType)
.time(now)
.schemaurl(schemaurl)
.data(data)

View File

@ -1,114 +0,0 @@
var expect = require("chai").expect;
var Cloudevent = require("../index.js");
const type = "com.github.pull.create01";
const source = "urn:event:from:myapi/resourse/01";
const time = new Date();
const schemaurl = "http://example.com/registry/v01/myschema.json";
const contenttype = "application/json";
const data = {};
var cloudevent = new Cloudevent()
.type(type)
.source(source);
describe("CloudEvents Spec 0.1 - JavaScript SDK", () => {
describe("Object properties", () => {
describe("Attribute getters", () => {
it("returns 'type'", () => {
expect(cloudevent.getType()).to.equal(type);
});
it("returns 'source'", () => {
expect(cloudevent.getSource()).to.equal(source);
});
});
});
describe("JSON Format", () => {
describe("Required context attributes", () => {
it("requires 'eventType'", () => {
expect(cloudevent.format()).to.have.property("eventType");
});
it("requires 'eventTypeVersion'", () => {
cloudevent.eventTypeVersion("1.0");
expect(cloudevent.format()).to.have.property("eventTypeVersion");
});
it("requires 'cloudEventsVersion'", () => {
expect(cloudevent.format()).to.have.property("cloudEventsVersion");
});
it("requires 'source'", () => {
expect(cloudevent.format()).to.have.property("source");
});
it("requires 'eventID'", () => {
expect(cloudevent.format()).to.have.property("eventID");
});
});
describe("Optional context attributes", () => {
it("contains 'eventTime'", () => {
cloudevent.time(time);
expect(cloudevent.format()).to.have.property("eventTime");
});
it("contains 'schemaURL'", () => {
cloudevent.schemaurl(schemaurl);
expect(cloudevent.format()).to.have.property("schemaURL");
});
it("contains 'contentType'", () => {
cloudevent.contenttype(contenttype);
expect(cloudevent.format()).to.have.property("contentType");
});
it("contains 'data'", () => {
cloudevent.data(data);
expect(cloudevent.format()).to.have.property("data");
});
it("contains 'extensions'", () => {
cloudevent.addExtension("foo", "value");
expect(cloudevent.format()).to.have.property("extensions");
});
it("'extensions' should have 'bar' extension", () => {
cloudevent.addExtension("bar", "value");
expect(cloudevent.format().extensions)
.to.have.property("foo");
});
});
describe("The Constraints check", () => {
describe("'eventType'", () => {
it("should throw an error when is an empty string", () => {
cloudevent.type("");
expect(cloudevent.format.bind(cloudevent))
.to
.throw("'eventType' is invalid");
});
it("must be a non-empty string", () => {
cloudevent.type(type);
cloudevent.format();
});
it("should be prefixed with a reverse-DNS name", () => {
// TODO how to assert it?
});
});
// TODO another attributes . . .
describe("'eventTime'", () => {
it("must adhere to the format specified in RFC 3339", () => {
cloudevent.time(time);
expect(cloudevent.format().eventTime).to.equal(time.toISOString());
});
});
});
});
});

View File

@ -1,168 +0,0 @@
var expect = require("chai").expect;
var Cloudevent = require("../index.js");
const type = "com.github.pull.create";
const source = "urn:event:from:myapi/resourse/123";
const time = new Date();
const schemaurl = "http://example.com/registry/myschema.json";
const contenttype = "application/json";
const data = {};
var cloudevent =
new Cloudevent(Cloudevent.specs["0.2"])
.type(type)
.source(source);
describe("CloudEvents Spec 0.2 - JavaScript SDK", () => {
describe("Object properties", () => {
describe("Attribute getters", () => {
it("returns 'type'", () => {
expect(cloudevent.getType()).to.equal(type);
});
it("returns 'source'", () => {
expect(cloudevent.getSource()).to.equal(source);
});
});
});
describe("JSON Format", () => {
describe("Required context attributes", () => {
it("requires 'type'", () => {
expect(cloudevent.format()).to.have.property("type");
});
it("requires 'specversion'", () => {
expect(cloudevent.format()).to.have.property("specversion");
});
it("should throw an error when mandatory attribute is absent", () => {
delete cloudevent.spec.payload.source;
expect(cloudevent.format.bind(cloudevent))
.to
.throw("invalid payload");
cloudevent.spec.payload.source = source;
});
it("requires 'source'", () => {
expect(cloudevent.format()).to.have.property("source");
});
it("requires 'id'", () => {
expect(cloudevent.format()).to.have.property("id");
});
});
describe("Optional context attributes", () => {
it("contains 'time'", () => {
cloudevent.time(time);
expect(cloudevent.format()).to.have.property("time");
});
it("contains 'schemaurl'", () => {
cloudevent.schemaurl(schemaurl);
expect(cloudevent.format()).to.have.property("schemaurl");
});
it("should throw an error when 'schemaurl' is not an URI", () => {
cloudevent.spec.payload.schemaurl = "KKKKKK";
expect(cloudevent.format.bind(cloudevent))
.to
.throw("invalid payload");
cloudevent.spec.payload.schemaurl = schemaurl;
});
it("contains 'contenttype'", () => {
cloudevent.contenttype(contenttype);
expect(cloudevent.format()).to.have.property("contenttype");
});
it("contains 'data'", () => {
cloudevent.data(data);
expect(cloudevent.format()).to.have.property("data");
});
it("contains 'extension1'", () => {
cloudevent.addExtension("extension1", "value1");
expect(cloudevent.format()).to.have.property("extension1");
});
it("'extension2' should have value equals to 'value1'", () => {
cloudevent.addExtension("extension2", "value2");
expect(cloudevent.format().extension2).to.equal("value2");
});
it("should throw an error when employ reserved name as extension", () => {
var cevt =
new Cloudevent(Cloudevent.specs["0.2"])
.type(type)
.source(source);
expect(cevt.addExtension.bind(cevt, "id"))
.to
.throw("Reserved attribute name: 'id'");
});
});
describe("The Constraints check", () => {
describe("'type'", () => {
it("should throw an error when is an empty string", () => {
cloudevent.type("");
expect(cloudevent.format.bind(cloudevent))
.to
.throw("invalid payload");
});
it("must be a non-empty string", () => {
cloudevent.type(type);
cloudevent.format();
});
it("should be prefixed with a reverse-DNS name", () => {
// TODO how to assert it?
});
});
describe("'specversion'", () => {
it("compliant event producers must use a value of '0.2'", () => {
expect(cloudevent.format().specversion).to.equal("0.2");
});
it("should throw an error when is an empty string", () => {
cloudevent.spec.payload.specversion = "";
expect(cloudevent.format.bind(cloudevent))
.to
.throw("invalid payload");
cloudevent.spec.payload.specversion = "0.2";
});
it("should throw an error when the value is not '0.2'", () => {
cloudevent.spec.payload.specversion = "0.4";
expect(cloudevent.format.bind(cloudevent))
.to
.throw("invalid payload");
cloudevent.spec.payload.specversion = "0.2";
});
});
describe("'id'", () => {
it("should throw an error when is an empty string", () => {
cloudevent.id("");
expect(cloudevent.format.bind(cloudevent))
.to
.throw("invalid payload");
});
it("must be a non-empty string", () => {
cloudevent.id("my.id-0x0090");
cloudevent.format();
});
});
describe("'time'", () => {
it("must adhere to the format specified in RFC 3339", () => {
cloudevent.time(time);
expect(cloudevent.format().time).to.equal(time.toISOString());
});
});
});
});
});

View File

@ -1,17 +1,5 @@
var expect = require("chai").expect;
var Parser = require("../../../lib/formats/json/parser.js");
var Cloudevent = require("../../../index.js");
const type = "com.github.pull.create";
const source = "urn:event:from:myapi/resourse/123";
const now = new Date();
const schemaurl = "http://cloudevents.io/schema.json";
const ceContentType = "application/json";
const data = {
foo: "bar"
};
describe("JSON Event Format Parser", () => {
it("Throw error when payload is an integer", () => {
@ -63,28 +51,6 @@ describe("JSON Event Format Parser", () => {
.to.throw("Unexpected token g in JSON at position 0");
});
it("Must accept the CloudEvent spec 0.2 as JSON", () => {
// setup
var payload =
new Cloudevent(Cloudevent.specs["0.2"])
.type(type)
.source(source)
.contenttype(ceContentType)
.time(now)
.schemaurl(schemaurl)
.data(data)
.toString();
var parser = new Parser();
// act
var actual = parser.parse(payload);
// assert
expect(actual)
.to.be.an("object");
});
it("Must accept when the payload is a string well formed as JSON", () => {
// setup
var payload = "{\"much\" : \"wow\"}";

View File

@ -1,145 +0,0 @@
var expect = require("chai").expect;
var Cloudevent = require("../index.js");
var nock = require("nock");
const type = "com.github.pull.create";
const source = "urn:event:from:myapi/resourse/123";
const webhook = "https://cloudevents.io/webhook";
const contentType = "application/cloudevents+json; charset=utf-8";
const now = new Date();
const schemaurl = "http://cloudevents.io/schema.json";
const ceContentType = "application/json";
const data = {
foo: "bar"
};
const ext1Name = "extension1";
const ext1Value = "foobar";
const ext2Name = "extension2";
const ext2Value = "acme";
const Structured01 = Cloudevent.bindings["http-structured0.1"];
const Binary01 = Cloudevent.bindings["http-binary0.1"];
var cloudevent =
new Cloudevent()
.type(type)
.source(source)
.contenttype(ceContentType)
.time(now)
.schemaurl(schemaurl)
.data(data)
.addExtension(ext1Name, ext1Value)
.addExtension(ext2Name, ext2Value);
cloudevent.eventTypeVersion("1.0.0");
var httpcfg = {
method: "POST",
url: `${webhook}/json`
};
var httpstructured01 = new Structured01(httpcfg);
var httpbinary01 = new Binary01(httpcfg);
describe("HTTP Transport Binding - Version 0.1", () => {
beforeEach(() => {
// Mocking the webhook
nock(webhook)
.post("/json")
.reply(201, { status: "accepted" });
});
describe("Structured", () => {
describe("JSON Format", () => {
it(`requires '${contentType}' Content-Type in the header`,
() => httpstructured01.emit(cloudevent)
.then((response) => {
expect(response.config.headers["Content-Type"])
.to.equal(contentType);
}));
it("the request payload should be correct",
() => httpstructured01.emit(cloudevent)
.then((response) => {
expect(JSON.parse(response.config.data))
.to.deep.equal(cloudevent.format());
}));
});
});
describe("Binary", () => {
describe("JSON Format", () => {
it(`requires '${cloudevent.getContenttype()}' Content-Type in the header`,
() => httpbinary01.emit(cloudevent)
.then((response) => {
expect(response.config.headers["Content-Type"])
.to.equal(cloudevent.getContenttype());
}));
it("the request payload should be correct",
() => httpbinary01.emit(cloudevent)
.then((response) => {
expect(JSON.parse(response.config.data))
.to.deep.equal(cloudevent.getData());
}));
it("HTTP Header contains 'CE-EventType'",
() => httpbinary01.emit(cloudevent)
.then((response) => {
expect(response.config.headers)
.to.have.property("CE-EventType");
}));
it("HTTP Header contains 'CE-EventTypeVersion'",
() => httpbinary01.emit(cloudevent)
.then((response) => {
expect(response.config.headers)
.to.have.property("CE-EventTypeVersion");
}));
it("HTTP Header contains 'CE-CloudEventsVersion'",
() => httpbinary01.emit(cloudevent)
.then((response) => {
expect(response.config.headers)
.to.have.property("CE-CloudEventsVersion");
}));
it("HTTP Header contains 'CE-Source'", () => httpbinary01.emit(cloudevent)
.then((response) => {
expect(response.config.headers)
.to.have.property("CE-Source");
}));
it("HTTP Header contains 'CE-EventID'",
() => httpbinary01.emit(cloudevent)
.then((response) => {
expect(response.config.headers)
.to.have.property("CE-EventID");
}));
it("HTTP Header contains 'CE-EventTime'",
() => httpbinary01.emit(cloudevent)
.then((response) => {
expect(response.config.headers)
.to.have.property("CE-EventTime");
}));
it("HTTP Header contains 'CE-SchemaURL'",
() => httpbinary01.emit(cloudevent)
.then((response) => {
expect(response.config.headers)
.to.have.property("CE-SchemaURL");
}));
it("HTTP Header contains 'CE-X-Extension1' as extension",
() => httpbinary01.emit(cloudevent)
.then((response) => {
expect(response.config.headers)
.to.have.property("CE-X-Extension1");
}));
});
});
});

View File

@ -1,140 +0,0 @@
var expect = require("chai").expect;
var Cloudevent = require("../index.js");
var nock = require("nock");
const type = "com.github.pull.create";
const source = "urn:event:from:myapi/resourse/123";
const webhook = "https://cloudevents.io/webhook";
const contentType = "application/cloudevents+json; charset=utf-8";
const now = new Date();
const schemaurl = "http://cloudevents.io/schema.json";
const ceContentType = "application/json";
const data = {
foo: "bar"
};
const ext1Name = "extension1";
const ext1Value = "foobar";
const ext2Name = "extension2";
const ext2Value = "acme";
const Structured02 = Cloudevent.bindings["http-structured0.2"];
const Binary02 = Cloudevent.bindings["http-binary0.2"];
var cloudevent =
new Cloudevent()
.type(type)
.source(source)
.contenttype(ceContentType)
.time(now)
.schemaurl(schemaurl)
.data(data)
.addExtension(ext1Name, ext1Value)
.addExtension(ext2Name, ext2Value);
var httpcfg = {
method: "POST",
url: `${webhook}/json`
};
var httpstructured02 = new Structured02(httpcfg);
var httpbinary02 = new Binary02(httpcfg);
describe("HTTP Transport Binding - Version 0.2", () => {
beforeEach(() => {
// Mocking the webhook
nock(webhook)
.post("/json")
.reply(201, { status: "accepted" });
});
describe("Structured", () => {
describe("JSON Format", () => {
it(`requires '${contentType}' Content-Type in the header`,
() => httpstructured02.emit(cloudevent)
.then((response) => {
expect(response.config.headers["Content-Type"])
.to.equal(contentType);
}));
it("the request payload should be correct",
() => httpstructured02.emit(cloudevent)
.then((response) => {
expect(JSON.parse(response.config.data))
.to.deep.equal(cloudevent.format());
}));
});
});
describe("Binary", () => {
describe("JSON Format", () => {
it(`requires ${cloudevent.getContenttype()} Content-Type in the header`,
() => httpbinary02.emit(cloudevent)
.then((response) => {
expect(response.config.headers["Content-Type"])
.to.equal(cloudevent.getContenttype());
}));
it("the request payload should be correct",
() => httpbinary02.emit(cloudevent)
.then((response) => {
expect(JSON.parse(response.config.data))
.to.deep.equal(cloudevent.getData());
}));
it("HTTP Header contains 'ce-type'", () => httpbinary02.emit(cloudevent)
.then((response) => {
expect(response.config.headers)
.to.have.property("ce-type");
}));
it("HTTP Header contains 'ce-specversion'",
() => httpbinary02.emit(cloudevent)
.then((response) => {
expect(response.config.headers)
.to.have.property("ce-specversion");
}));
it("HTTP Header contains 'ce-source'", () => httpbinary02.emit(cloudevent)
.then((response) => {
expect(response.config.headers)
.to.have.property("ce-source");
}));
it("HTTP Header contains 'ce-id'", () => httpbinary02.emit(cloudevent)
.then((response) => {
expect(response.config.headers)
.to.have.property("ce-id");
}));
it("HTTP Header contains 'ce-time'", () => httpbinary02.emit(cloudevent)
.then((response) => {
expect(response.config.headers)
.to.have.property("ce-time");
}));
it("HTTP Header contains 'ce-schemaurl'",
() => httpbinary02.emit(cloudevent)
.then((response) => {
expect(response.config.headers)
.to.have.property("ce-schemaurl");
}));
it(`HTTP Header contains 'ce-${ext1Name}'`,
() => httpbinary02.emit(cloudevent)
.then((response) => {
expect(response.config.headers)
.to.have.property(`ce-${ext1Name}`);
}));
it(`HTTP Header contains 'ce-${ext2Name}'`,
() => httpbinary02.emit(cloudevent)
.then((response) => {
expect(response.config.headers)
.to.have.property(`ce-${ext2Name}`);
}));
});
});
});

View File

@ -1,43 +1,8 @@
const expect = require("chai").expect;
const v02 = require("../v02/index.js");
const v03 = require("../v03/index.js");
const v1 = require("../v1/index.js");
describe("The SDK Requirements", () => {
describe("v0.2", () => {
it("should create an event using the right spec version", () => {
expect(v02.event().spec.payload.specversion).to.equal("0.2");
});
it("should exports 'Spec'", () => {
expect(v02).to.have.property("Spec");
});
it("should exports 'StructuredHTTPEmitter'", () => {
expect(v02).to.have.property("StructuredHTTPEmitter");
});
it("should exports 'StructuredHTTPReceiver'", () => {
expect(v02).to.have.property("StructuredHTTPReceiver");
});
it("should exports 'BinaryHTTPEmitter'", () => {
expect(v02).to.have.property("BinaryHTTPEmitter");
});
it("should exports 'BinaryHTTPReceiver'", () => {
expect(v02).to.have.property("BinaryHTTPReceiver");
});
it("should exports 'HTTPUnmarshaller'", () => {
expect(v02).to.have.property("HTTPUnmarshaller");
});
it("should exports 'event'", () => {
expect(v02).to.have.property("event");
});
});
describe("v0.3", () => {
it("should create an event using the right spec version", () => {
expect(v03.event().spec.payload.specversion).to.equal("0.3");

View File

@ -57,12 +57,6 @@ describe("CloudEvents Spec v0.3", () => {
expect(cloudevent.getDataContentType()).to.equal(dataContentType);
});
it("contenttype() method should maps to 'datacontenttype'", () => {
cloudevent.contenttype("text/xml");
expect(cloudevent.spec.payload.datacontenttype).to.equal("text/xml");
cloudevent.contenttype(dataContentType);
});
it("Should have 'schemaurl'", () => {
expect(cloudevent.getSchemaurl()).to.equal(schemaurl);
});

View File

@ -1,25 +0,0 @@
const Cloudevent = require("../lib/cloudevent.js");
const Spec = require("../lib/specs/spec_0_2.js");
const StructuredHTTPEmitter =
require("../lib/bindings/http/emitter_structured_0_2.js");
const { HTTPBinary02 } = require("../lib/bindings/http/emitter_binary_0_2.js");
const StructuredHTTPReceiver =
require("../lib/bindings/http/receiver_structured_0_2.js");
const BinaryHTTPReceiver =
require("../lib/bindings/http/receiver_binary_0_2.js");
const HTTPUnmarshaller = require("../lib/bindings/http/unmarshaller_0_2.js");
function event() {
return new Cloudevent(Spec);
}
module.exports = {
Spec,
StructuredHTTPEmitter,
StructuredHTTPReceiver,
BinaryHTTPEmitter: HTTPBinary02,
BinaryHTTPReceiver,
HTTPUnmarshaller,
event
};

View File

@ -23,5 +23,7 @@ module.exports = {
BinaryHTTPEmitter,
BinaryHTTPReceiver,
HTTPUnmarshaller,
Cloudevent,
CloudEvent: Cloudevent,
event
};