From e1f26f8ab5f9c21cc2edfe98d21ac276bdc3d596 Mon Sep 17 00:00:00 2001 From: Lance Ball Date: Tue, 5 May 2020 17:03:09 -0400 Subject: [PATCH 1/3] feat(unmarshaller)!: remove asynchronous 0.3 unmarshaller API This commit removes the unnecessary use of Promises in the 0.3 unmarshaller. There was actually no asynchronous activity happening in that function, so there was no need to deal with Promises, and as a result testing was made much more difficult. Fixes: https://github.com/cloudevents/sdk-javascript/pull/95 Signed-off-by: Lance Ball --- lib/bindings/http/unmarshaller.js | 34 +++--- test/bindings/http/unmarshaller_0_3_tests.js | 113 +++++++++---------- 2 files changed, 69 insertions(+), 78 deletions(-) diff --git a/lib/bindings/http/unmarshaller.js b/lib/bindings/http/unmarshaller.js index 4476f25a..99688c39 100644 --- a/lib/bindings/http/unmarshaller.js +++ b/lib/bindings/http/unmarshaller.js @@ -45,27 +45,25 @@ class Unmarshaller { } unmarshall(payload, headers) { - return new Promise((resolve, reject) => { - if (!payload) { - return reject(new TypeError("payload is null or undefined")); - } - if (!headers) { - return reject(new TypeError("headers is null or undefined")); - } + if (!payload) { + throw new TypeError("payload is null or undefined"); + } + if (!headers) { + throw new TypeError("headers is null or undefined"); + } - // Validation level 1 - const sanityHeaders = Commons.sanityAndClone(headers); - if (!sanityHeaders[Constants.HEADER_CONTENT_TYPE]) { - throw new TypeError("content-type header not found"); - } + // Validation level 1 + const sanityHeaders = Commons.sanityAndClone(headers); + if (!sanityHeaders[Constants.HEADER_CONTENT_TYPE]) { + throw new TypeError("content-type header not found"); + } - // Resolve the binding - const bindingName = resolveBindingName(payload, sanityHeaders); - const cloudevent = this.receiverByBinding[bindingName] - .parse(payload, sanityHeaders); + // Resolve the binding + const bindingName = resolveBindingName(payload, sanityHeaders); + const cloudevent = this.receiverByBinding[bindingName] + .parse(payload, sanityHeaders); - resolve(cloudevent); - }); + return cloudevent; } } diff --git a/test/bindings/http/unmarshaller_0_3_tests.js b/test/bindings/http/unmarshaller_0_3_tests.js index 6bc3deb6..7eaa44f2 100644 --- a/test/bindings/http/unmarshaller_0_3_tests.js +++ b/test/bindings/http/unmarshaller_0_3_tests.js @@ -26,10 +26,11 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { const 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")); + try { + un.unmarshall(payload); + } catch (err) { + expect(err.message).to.equal("payload is null or undefined"); + } }); it("Throw error when headers is null", () => { @@ -39,10 +40,11 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { const 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")); + try { + un.unmarshall(payload, headers); + } catch (err) { + expect(err.message).to.equal("headers is null or undefined"); + } }); it("Throw error when there is no content-type header", () => { @@ -52,10 +54,11 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { const 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")); + try { + un.unmarshall(payload, headers); + } catch (err) { + expect(err.message).to.equal("content-type header not found"); + } }); it("Throw error when content-type is not allowed", () => { @@ -67,10 +70,11 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { const 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")); + try { + un.unmarshall(payload, headers); + } catch (err) { + expect(err.message).to.equal("content type not allowed"); + } }); describe("Structured", () => { @@ -83,10 +87,11 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { const 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")); + try { + un.unmarshall(payload, headers); + } catch (err) { + expect(err.message).to.equal("structured+type not allowed"); + } }); it("Throw error when the event does not follow the spec 0.3", () => { @@ -108,10 +113,11 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { const un = new Unmarshaller(); // act and assert - un.unmarshall(payload, headers) - .then(() => { throw new Error("failed"); }) - .catch((err) => - expect(err.message).to.equal("invalid payload")); + try { + un.unmarshall(payload, headers); + } catch (err) { + expect(err.message).to.equal("invalid payload"); + } }); it("Should accept event that follow the spec 0.3", () => { @@ -134,13 +140,8 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { const un = new Unmarshaller(); // act and assert - return un.unmarshall(payload, headers) - .then((actual) => - expect(actual).to.be.an("object")) - .catch((err) => { - console.error(err); - throw err; - }); + const event = un.unmarshall(payload, headers); + expect(event instanceof CloudEvent).to.equal(true); }); it("Should parse 'data' stringfied json to json object", () => { @@ -163,14 +164,8 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { const un = new Unmarshaller(); // act and assert - return un.unmarshall(payload, headers) - .then((actual) => { - expect(actual.getData()).to.deep.equal(data); - }) - .catch((err) => { - console.error(err); - throw err; - }); + const event = un.unmarshall(payload, headers); + expect(event.getData()).to.deep.equal(data); }); }); @@ -193,10 +188,11 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { const 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")); + try { + un.unmarshall(payload, attributes); + } catch (err) { + expect(err.message).to.equal("content type not allowed"); + } }); it("Throw error when the event does not follow the spec 0.3", () => { @@ -217,10 +213,11 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { const un = new Unmarshaller(); // act and assert - un.unmarshall(payload, attributes) - .then(() => { throw new Error("failed"); }) - .catch((err) => - expect(err.message).to.not.empty); + try { + un.unmarshall(payload, attributes); + } catch (err) { + expect(err.message).to.equal("header 'ce-specversion' not found"); + } }); it("No error when all attributes are in place", () => { @@ -241,8 +238,8 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { const un = new Unmarshaller(); // act and assert - un.unmarshall(payload, attributes) - .then((actual) => expect(actual).to.be.an("object")); + const event = un.unmarshall(payload, attributes); + expect(event instanceof CloudEvent).to.equal(true); }); it("Throw error when 'ce-datacontentencoding' is not allowed", () => { @@ -263,11 +260,11 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { const un = new Unmarshaller(); // act and assert - return un.unmarshall(payload, attributes) - .then(() => { throw new Error("failed"); }) - .catch((err) => { - expect(err.message).to.equal("unsupported datacontentencoding"); - }); + try { + un.unmarshall(payload, attributes); + } catch (err) { + expect(err.message).to.equal("unsupported datacontentencoding"); + } }); it("No error when 'ce-datacontentencoding' is base64", () => { @@ -291,12 +288,8 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { const un = new Unmarshaller(); // act and assert - return un.unmarshall(payload, attributes) - .then((actual) => expect(actual.getData()).to.deep.equal(expected)) - .catch((err) => { - console.error(err); - throw err; - }); + const event = un.unmarshall(payload, attributes); + expect(event.getData()).to.deep.equal(expected); }); }); }); From a524e5e5cf26f11dc9b4354d6b5c514f25cbfa0b Mon Sep 17 00:00:00 2001 From: Lance Ball Date: Wed, 6 May 2020 19:07:54 -0400 Subject: [PATCH 2/3] test: clean up unmarshalling tests for failure cases Signed-off-by: Lance Ball --- test/bindings/http/unmarshaller_0_3_tests.js | 130 ++++--------------- 1 file changed, 25 insertions(+), 105 deletions(-) diff --git a/test/bindings/http/unmarshaller_0_3_tests.js b/test/bindings/http/unmarshaller_0_3_tests.js index 7eaa44f2..4571f47e 100644 --- a/test/bindings/http/unmarshaller_0_3_tests.js +++ b/test/bindings/http/unmarshaller_0_3_tests.js @@ -10,7 +10,8 @@ const schemaurl = "http://cloudevents.io/schema.json"; const subject = "subject.ext"; const { BINARY_HEADERS_03, - HEADER_CONTENT_TYPE + HEADER_CONTENT_TYPE, + SPEC_V03 } = require("../../../lib/bindings/http/constants.js"); const ceContentType = "application/json"; @@ -19,127 +20,73 @@ const data = { foo: "bar" }; +const un = new Unmarshaller(); + describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { it("Throw error when payload is null", () => { - // setup - const payload = null; - const un = new Unmarshaller(); - - // act and assert - try { - un.unmarshall(payload); - } catch (err) { - expect(err.message).to.equal("payload is null or undefined"); - } + expect(() => un.unmarshall(null)).to.throw("payload is null or undefined"); }); it("Throw error when headers is null", () => { - // setup - const payload = {}; - const headers = null; - const un = new Unmarshaller(); - - // act and assert - try { - un.unmarshall(payload, headers); - } catch (err) { - expect(err.message).to.equal("headers is null or undefined"); - } + expect(() => un.unmarshall({})).to.throw("headers is null or undefined"); + expect(() => un.unmarshall({}, null)).to + .throw("headers is null or undefined"); }); it("Throw error when there is no content-type header", () => { - // setup - const payload = {}; - const headers = {}; - const un = new Unmarshaller(); - - // act and assert - try { - un.unmarshall(payload, headers); - } catch (err) { - expect(err.message).to.equal("content-type header not found"); - } + expect(() => un.unmarshall({}, {})).to + .throw("content-type header not found"); }); it("Throw error when content-type is not allowed", () => { - // setup - const payload = {}; const headers = { "content-type": "text/xml" }; - const un = new Unmarshaller(); - - // act and assert - try { - un.unmarshall(payload, headers); - } catch (err) { - expect(err.message).to.equal("content type not allowed"); - } + expect(() => un.unmarshall({}, headers)).to + .throw("content type not allowed"); }); describe("Structured", () => { it("Throw error when has not allowed mime", () => { // setup - const payload = {}; const headers = { "content-type": "application/cloudevents+zip" }; - const un = new Unmarshaller(); // act and assert - try { - un.unmarshall(payload, headers); - } catch (err) { - expect(err.message).to.equal("structured+type not allowed"); - } + expect(() => un.unmarshall({}, headers)).to + .throw("structured+type not allowed"); }); it("Throw error when the event does not follow the spec 0.3", () => { - // setup const payload = - new v03.CloudEvent(v03.Spec) - .type(type) - .source(source) - .dataContentType(ceContentType) + new CloudEvent(v03.Spec) .time(now) - .schemaurl(schemaurl) - .data(data) .toString(); const headers = { "content-type": "application/cloudevents+json" }; - const un = new Unmarshaller(); - - // act and assert - try { - un.unmarshall(payload, headers); - } catch (err) { - expect(err.message).to.equal("invalid payload"); - } + expect(() => un.unmarshall(payload, headers)).to + .throw(TypeError); }); it("Should accept event that follow the spec 0.3", () => { - // setup const payload = new CloudEvent(v03.Spec) .type(type) + .data(data) .source(source) .dataContentType(ceContentType) .time(now) .schemaurl(schemaurl) .subject(subject) - .data(data) - .toString(); + .format(); const headers = { "content-type": "application/cloudevents+json" }; - - const un = new Unmarshaller(); - - // act and assert const event = un.unmarshall(payload, headers); expect(event instanceof CloudEvent).to.equal(true); }); @@ -161,9 +108,6 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { "content-type": "application/cloudevents+json" }; - const un = new Unmarshaller(); - - // act and assert const event = un.unmarshall(payload, headers); expect(event.getData()).to.deep.equal(data); }); @@ -185,14 +129,8 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { [HEADER_CONTENT_TYPE]: "text/html" }; - const un = new Unmarshaller(); - - // act and assert - try { - un.unmarshall(payload, attributes); - } catch (err) { - expect(err.message).to.equal("content type not allowed"); - } + expect(() => un.unmarshall(payload, attributes)).to + .throw("content type not allowed"); }); it("Throw error when the event does not follow the spec 0.3", () => { @@ -210,14 +148,8 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { [HEADER_CONTENT_TYPE]: "application/json" }; - const un = new Unmarshaller(); - - // act and assert - try { - un.unmarshall(payload, attributes); - } catch (err) { - expect(err.message).to.equal("header 'ce-specversion' not found"); - } + expect(() => un.unmarshall(payload, attributes)).to + .throw("header 'ce-specversion' not found"); }); it("No error when all attributes are in place", () => { @@ -235,9 +167,6 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { [HEADER_CONTENT_TYPE]: "application/json" }; - const un = new Unmarshaller(); - - // act and assert const event = un.unmarshall(payload, attributes); expect(event instanceof CloudEvent).to.equal(true); }); @@ -257,14 +186,8 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { [BINARY_HEADERS_03.CONTENT_ENCONDING]: "binary" }; - const un = new Unmarshaller(); - - // act and assert - try { - un.unmarshall(payload, attributes); - } catch (err) { - expect(err.message).to.equal("unsupported datacontentencoding"); - } + expect(() => un.unmarshall(payload, attributes)).to + .throw("unsupported datacontentencoding"); }); it("No error when 'ce-datacontentencoding' is base64", () => { @@ -285,9 +208,6 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { [BINARY_HEADERS_03.CONTENT_ENCONDING]: "base64" }; - const un = new Unmarshaller(); - - // act and assert const event = un.unmarshall(payload, attributes); expect(event.getData()).to.deep.equal(expected); }); From 96dfd019bb54059d8b8e4e6d0179becc6a26daff Mon Sep 17 00:00:00 2001 From: Lance Ball Date: Wed, 6 May 2020 19:09:53 -0400 Subject: [PATCH 3/3] squash: remove unused variable Signed-off-by: Lance Ball --- test/bindings/http/unmarshaller_0_3_tests.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/bindings/http/unmarshaller_0_3_tests.js b/test/bindings/http/unmarshaller_0_3_tests.js index 4571f47e..e7e2127d 100644 --- a/test/bindings/http/unmarshaller_0_3_tests.js +++ b/test/bindings/http/unmarshaller_0_3_tests.js @@ -10,8 +10,7 @@ const schemaurl = "http://cloudevents.io/schema.json"; const subject = "subject.ext"; const { BINARY_HEADERS_03, - HEADER_CONTENT_TYPE, - SPEC_V03 + HEADER_CONTENT_TYPE } = require("../../../lib/bindings/http/constants.js"); const ceContentType = "application/json";