From c9248c32f57fb55237da4b65f10dc1e1aac85d2f Mon Sep 17 00:00:00 2001 From: Jarek Radosz Date: Sun, 16 Jun 2019 19:15:42 +0200 Subject: [PATCH 1/4] Deduplicate error messages --- addon-test-support/index.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/addon-test-support/index.js b/addon-test-support/index.js index a29e5b58..c1723005 100644 --- a/addon-test-support/index.js +++ b/addon-test-support/index.js @@ -50,17 +50,19 @@ let fetchFromEmberCli = async function(url, headers) { response = await fetch(endpoint); } catch (e) { if (e.message && e.message.match(/^Mirage:/)) { - error = `Ember CLI FastBoot Testing: It looks like Mirage is intercepting ember-cli-fastboot-testing's attempt to render ${url}. Please disable Mirage when running FastBoot tests.`; + error = `It looks like Mirage is intercepting ember-cli-fastboot-testing's attempt to render ${url}. Please disable Mirage when running FastBoot tests.`; } else { - error = `Ember CLI FastBoot Testing: We were unable to render ${url}. Is your test suite blocking or intercepting HTTP requests? Error: ${e.message ? e.message : e}.` + error = `We were unable to render ${url}. Is your test suite blocking or intercepting HTTP requests? Error: ${e.message ? e.message : e}.` } } if (response && response.headers && response.headers.get && response.headers.get('x-fastboot-testing') !== 'true') { - error = `Ember CLI FastBoot Testing: We were unable to render ${url}. Is your test suite blocking or intercepting HTTP requests?`; + error = `We were unable to render ${url}. Is your test suite blocking or intercepting HTTP requests?`; } if (error) { + error = `Ember CLI FastBoot Testing: ${error}`; + // eslint-disable-next-line no-console console.error(error); throw new Error(error); From b7a898db8fee373b23d7e8075dd2e65aded0b108 Mon Sep 17 00:00:00 2001 From: Jarek Radosz Date: Sun, 16 Jun 2019 19:28:47 +0200 Subject: [PATCH 2/4] Add the nock proxy --- addon-test-support/index.js | 30 ++++++++ index.js | 51 +++++++++++++- package.json | 1 + tests/fastboot/network-mocking-test.js | 4 +- tests/fastboot/nock-proxy-test.js | 95 ++++++++++++++++++++++++++ yarn.lock | 5 ++ 6 files changed, 183 insertions(+), 3 deletions(-) create mode 100644 tests/fastboot/nock-proxy-test.js diff --git a/addon-test-support/index.js b/addon-test-support/index.js index c1723005..85168c54 100644 --- a/addon-test-support/index.js +++ b/addon-test-support/index.js @@ -2,6 +2,7 @@ import { fetch } from 'whatwg-fetch'; import { setupContext, teardownContext } from '@ember/test-helpers'; import { mockServer } from './-private/mock-server'; import param from 'jquery-param'; +import * as Comlink from 'comlink'; export function setup(hooks) { hooks.beforeEach(async function() { @@ -39,6 +40,35 @@ export async function visit(url, options = {}) { export { mockServer }; +export const nock = Comlink.wrapChain({ + listeners: [], + + async postMessage(message) { + let response = await fetch('/__nock-proxy', { + method: 'post', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(message), + }); + + let result = await response.json(); + + for (let listener of this.listeners) { + listener({ data: result }); + } + }, + + addEventListener(type, listener) { + this.listeners.push(listener); + }, + + removeEventListener(type, listener) { + let index = this.listeners.indexOf(listener); + this.listeners.splice(index, 1); + }, +}); + // private let fetchFromEmberCli = async function(url, headers) { diff --git a/index.js b/index.js index 382f1a8a..80f9b4ea 100644 --- a/index.js +++ b/index.js @@ -4,7 +4,46 @@ let FastBoot = require('fastboot'); let url = require('url'); let resolve = require('resolve'); let nock = require('nock'); -let bodyParser = require('body-parser') +let bodyParser = require('body-parser'); +let Comlink = require('comlink'); + +let nockInterface = { + listeners: [], + lastMessage: null, + + dispatchEvent(message) { + let listener = this.listeners[0]; + return listener({ data: message }); + }, + + postMessage(message) { + this.lastMessage = message; + }, + + addEventListener(type, listener) { + this.listeners.push(listener); + }, + + removeEventListener(type, listener) { + let index = this.listeners.indexOf(listener); + this.listeners.splice(index, 1); + }, +} + +Comlink.expose(nock, nockInterface); + +let getCircularReplacer = () => { + let seen = new WeakSet(); + return (key, value) => { + if (typeof value === "object" && value !== null) { + if (seen.has(value)) { + return; + } + seen.add(value); + } + return value; + }; +} module.exports = { name: 'ember-cli-fastboot-testing', @@ -41,6 +80,16 @@ module.exports = { }, _fastbootRenderingMiddleware(app) { + app.post('/__nock-proxy', bodyParser.json(), (req, res) => { + nockInterface.dispatchEvent(req.body).then(() => { + let body = JSON.stringify( + nockInterface.lastMessage, + getCircularReplacer() + ); + + res.send(body); + }); + }); app.post('/__mock-request', bodyParser.json({ limit: '50mb' }), (req, res) => { let mock = nock(req.headers.origin) diff --git a/package.json b/package.json index 7fc4f388..9fecf27e 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ }, "dependencies": { "body-parser": "^1.18.3", + "comlink": "^4.0.1", "ember-auto-import": "^1.2.15", "ember-cli-babel": "^6.6.0", "fastboot": "^1.2.1", diff --git a/tests/fastboot/network-mocking-test.js b/tests/fastboot/network-mocking-test.js index e7978179..45b28c31 100644 --- a/tests/fastboot/network-mocking-test.js +++ b/tests/fastboot/network-mocking-test.js @@ -69,7 +69,7 @@ module('Fastboot | network mocking', function(hooks) { test('it can mock a get request', async function(assert) { await mockServer.get('/api/notes', [ - { id: 1, title: 'get note'}, + { id: 1, title: 'get note' }, ]); await visit('/examples/network/other/get-request'); @@ -79,7 +79,7 @@ module('Fastboot | network mocking', function(hooks) { test('it can mock a post request', async function(assert) { await mockServer.post('/api/notes', [ - { id: 1, title: 'post note'}, + { id: 1, title: 'post note' }, ]); await visit('/examples/network/other/post-request'); diff --git a/tests/fastboot/nock-proxy-test.js b/tests/fastboot/nock-proxy-test.js new file mode 100644 index 00000000..94159cf7 --- /dev/null +++ b/tests/fastboot/nock-proxy-test.js @@ -0,0 +1,95 @@ +import { module, test } from 'qunit'; +import { setup, visit, nock } from 'ember-cli-fastboot-testing/test-support'; + +module('Fastboot | nock proxy', function(hooks) { + setup(hooks); + + test('it will not change an endpoint that already exists', async function(assert) { + await visit('/examples/network/other/echo?message=hello%20world'); + assert.dom('[data-test-id="echo"]').hasText("hello world"); + }); + + test('it can mock an array of models', async function(assert) { + await nock('http://localhost:7357') + .intercept('/api/notes', 'GET') + .reply(200, { + data: [ + { + type: 'note', + id: '1', + attributes: { + title: 'test note' + } + }, + { + type: 'note', + id: '2', + attributes: { + title: 'test 2' + } + } + ] + }); + + await visit('/examples/network/notes'); + + assert.dom('[data-test-id="title-1"]').hasText("test note") + assert.dom('[data-test-id="title-2"]').hasText("test 2") + }); + + test('it can mock a single model', async function(assert) { + await nock('http://localhost:7357') + .intercept('/api/notes/1', 'GET') + .reply(200, { + data: { + type: "notes", + id: "1", + attributes: { + title: 'test note' + } + } + }); + + await visit('/examples/network/notes/1'); + + assert.dom('[data-test-id="title"]').hasText("test note"); + }); + + test('it can mock 404s', async function(assert) { + await nock('http://localhost:7357') + .intercept('/api/notes/1', 'GET') + .reply(404, { + errors: [ + { title: "Not found" } + ] + }); + + await visit('/examples/network/notes/1'); + + assert.dom().includesText('Ember Data Request GET /api/notes/1 returned a 404'); + }); + + test('it can mock a get request', async function(assert) { + await nock('http://localhost:7357') + .intercept('/api/notes', 'GET') + .reply(200, [ + { id: 1, title: 'get note' }, + ]); + + await visit('/examples/network/other/get-request'); + + assert.dom('[data-test-id="title-1"]').hasText("get note") + }); + + test('it can mock a post request', async function(assert) { + await nock('http://localhost:7357') + .intercept('/api/notes', 'POST') + .reply(200, [ + { id: 1, title: 'post note' }, + ]); + + await visit('/examples/network/other/post-request'); + + assert.dom('[data-test-id="title-1"]').hasText("post note") + }); +}); diff --git a/yarn.lock b/yarn.lock index d1f92208..336535b0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3663,6 +3663,11 @@ combined-stream@~0.0.4: dependencies: delayed-stream "0.0.5" +comlink@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/comlink/-/comlink-4.0.1.tgz#b20d0fca012ef80cf7eae89b76e4b43b2a1a0e6d" + integrity sha512-xEI50m6xEff5aZ29Epd+eNP+Plq2xTcUXGDJeWNqptudNB0hr59NV2KIi1xz6igb/Y2azKKSAj4ehI3wgGbREw== + commander@2.12.2: version "2.12.2" resolved "https://registry.yarnpkg.com/commander/-/commander-2.12.2.tgz#0f5946c427ed9ec0d91a46bb9def53e54650e555" From 0aaa6a9810129b68abd73730cf70790299aefa97 Mon Sep 17 00:00:00 2001 From: Jarek Radosz Date: Fri, 21 Jun 2019 22:18:44 +0200 Subject: [PATCH 3/4] Use WIP comlink version with wrapChain --- package.json | 3 ++- yarn.lock | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 9fecf27e..ea6b8d2a 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ }, "scripts": { "build": "ember build", + "install": "cd node_modules/comlink && npm install && npm run build", "lint:js": "eslint .", "start": "ember serve", "test": "ember test", @@ -22,7 +23,7 @@ }, "dependencies": { "body-parser": "^1.18.3", - "comlink": "^4.0.1", + "comlink": "CvX/comlink#wrap-chain", "ember-auto-import": "^1.2.15", "ember-cli-babel": "^6.6.0", "fastboot": "^1.2.1", diff --git a/yarn.lock b/yarn.lock index 336535b0..06d81ae3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3663,10 +3663,9 @@ combined-stream@~0.0.4: dependencies: delayed-stream "0.0.5" -comlink@^4.0.1: +comlink@CvX/comlink#wrap-chain: version "4.0.1" - resolved "https://registry.yarnpkg.com/comlink/-/comlink-4.0.1.tgz#b20d0fca012ef80cf7eae89b76e4b43b2a1a0e6d" - integrity sha512-xEI50m6xEff5aZ29Epd+eNP+Plq2xTcUXGDJeWNqptudNB0hr59NV2KIi1xz6igb/Y2azKKSAj4ehI3wgGbREw== + resolved "https://codeload.github.com/CvX/comlink/tar.gz/f7913e3a02905389eeee4fda441356f3dbb19688" commander@2.12.2: version "2.12.2" From 38dba06c4246d7078f85dddd771bdc0070d3dc15 Mon Sep 17 00:00:00 2001 From: Jarek Radosz Date: Tue, 25 Jun 2019 01:51:23 +0200 Subject: [PATCH 4/4] Increase the bodyParser memory limit --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 80f9b4ea..b4feea4a 100644 --- a/index.js +++ b/index.js @@ -80,7 +80,7 @@ module.exports = { }, _fastbootRenderingMiddleware(app) { - app.post('/__nock-proxy', bodyParser.json(), (req, res) => { + app.post('/__nock-proxy', bodyParser.json({ limit: '50mb' }), (req, res) => { nockInterface.dispatchEvent(req.body).then(() => { let body = JSON.stringify( nockInterface.lastMessage,