From 11a0d234803c6efd1413f5bd766e0078d05e2d13 Mon Sep 17 00:00:00 2001 From: Emil Bay Date: Thu, 10 Nov 2016 13:30:31 +1030 Subject: [PATCH 1/4] Pass opts to live reload server helper --- test/helpers/listen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/helpers/listen.js b/test/helpers/listen.js index 86860ad..6f0a1a2 100644 --- a/test/helpers/listen.js +++ b/test/helpers/listen.js @@ -6,7 +6,7 @@ export default function listen (opts) { opts = opts || {}; return function _listen (done) { - this.app = new Server(); + this.app = new Server(opts); const srv = this.server = this.app.server; const ctx = this; this.server.listen(err => { From c59f073f162949d549026aac60b978e74d35e3fd Mon Sep 17 00:00:00 2001 From: Emil Bay Date: Thu, 10 Nov 2016 13:31:07 +1030 Subject: [PATCH 2/4] Allow livereload option to be (fn -> stream) --- lib/server.js | 14 +++- test/server-custom-livereload.js | 120 +++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 test/server-custom-livereload.js diff --git a/lib/server.js b/lib/server.js index 1239744..390e1e2 100644 --- a/lib/server.js +++ b/lib/server.js @@ -13,13 +13,23 @@ const debug = require('debug')('tinylr:server'); const CONTENT_TYPE = 'content-type'; const FORM_TYPE = 'application/x-www-form-urlencoded'; +function wrapStream (path) { + return function () { + return fs.createReadStream(path); + }; +} + class Server extends events.EventEmitter { constructor (options = {}) { super(); this.options = options; - options.livereload = options.livereload || require.resolve('livereload-js/dist/livereload.js'); + options.livereload = typeof options.livereload === 'string' + ? wrapStream(options.livereload) + : typeof options.livereload === 'function' + ? options.livereload + : wrapStream(require.resolve('livereload-js/dist/livereload.js')); // todo: change falsy check to allow 0 for random port options.port = parseInt(options.port || 35729, 10); @@ -214,7 +224,7 @@ class Server extends events.EventEmitter { livereload (req, res) { res.setHeader('Content-Type', 'application/javascript'); - fs.createReadStream(this.options.livereload).pipe(res); + this.options.livereload().pipe(res); } changed (req, res) { diff --git a/test/server-custom-livereload.js b/test/server-custom-livereload.js new file mode 100644 index 0000000..29c5517 --- /dev/null +++ b/test/server-custom-livereload.js @@ -0,0 +1,120 @@ +import request from 'supertest'; +import assert from 'assert'; +import listen from './helpers/listen'; +import {PassThrough} from 'stream'; + +describe('tiny-lr', () => { + before(listen({ + livereload: function () { + const s = new PassThrough(); + + s.end('// custom live-reload'); + + return s; + } + })); + + describe('GET /', () => { + it('respond with nothing, but respond', function (done) { + request(this.server) + .get('/') + .expect('Content-Type', /json/) + .expect(/\{"tinylr":"Welcome","version":"[\d].[\d].[\d]+"\}/) + .expect(200, done); + }); + + it('unknown route respond with proper 404 and error message', function (done) { + request(this.server) + .get('/whatev') + .expect('Content-Type', /json/) + .expect('{"error":"not_found","reason":"no such route"}') + .expect(404, done); + }); + }); + + describe('GET /changed', () => { + it('with no clients, no files', function (done) { + request(this.server) + .get('/changed') + .expect('Content-Type', /json/) + .expect(/"clients":\[\]/) + .expect(/"files":\[\]/) + .expect(200, done); + }); + + it('with no clients, some files', function (done) { + request(this.server) + .get('/changed?files=gonna.css,test.css,it.css') + .expect('Content-Type', /json/) + .expect('{"clients":[],"files":["gonna.css","test.css","it.css"]}') + .expect(200, done); + }); + }); + + describe('POST /changed', () => { + it('with no clients, no files', function (done) { + request(this.server) + .post('/changed') + .expect('Content-Type', /json/) + .expect(/"clients":\[\]/) + .expect(/"files":\[\]/) + .expect(200, done); + }); + + it('with no clients, some files', function (done) { + const data = { clients: [], files: ['cat.css', 'sed.css', 'ack.js'] }; + + request(this.server) + .post('/changed') + // .type('json') + .send({ files: data.files }) + .expect('Content-Type', /json/) + .expect(JSON.stringify(data)) + .expect(200, done); + }); + }); + + describe('POST /alert', () => { + it('with no clients, no message', function (done) { + const data = { clients: [] }; + request(this.server) + .post('/alert') + .expect('Content-Type', /json/) + .expect(JSON.stringify(data)) + .expect(200, done); + }); + + it('with no clients, some message', function (done) { + const message = 'Hello Client!'; + const data = { clients: [], message: message }; + request(this.server) + .post('/alert') + .send({ message: message }) + .expect('Content-Type', /json/) + .expect(JSON.stringify(data)) + .expect(200, done); + }); + }); + + describe('GET /livereload.js', () => { + it('respond with livereload script', function (done) { + request(this.server) + .get('/livereload.js') + .expect('// custom live-reload') + .expect(200, done); + }); + }); + + describe('GET /kill', () => { + it('shutdown the server', function (done) { + const srv = this.server; + request(srv) + .get('/kill') + .expect(200, err => { + if (err) return done(err); + assert.ok(!srv._handle); + done(); + }); + }); + }); +}); From 312c90de345132826633cde30b2609bbb2a83ad1 Mon Sep 17 00:00:00 2001 From: Emil Bay Date: Mon, 20 Feb 2017 19:07:53 +0100 Subject: [PATCH 3/4] Factor out shared tests --- test/helpers/test-http-api.js | 99 ++++++++++++++++++++++++++++++++ test/server-custom-livereload.js | 99 +------------------------------- test/server.js | 99 +------------------------------- 3 files changed, 105 insertions(+), 192 deletions(-) create mode 100644 test/helpers/test-http-api.js diff --git a/test/helpers/test-http-api.js b/test/helpers/test-http-api.js new file mode 100644 index 0000000..32c9fa0 --- /dev/null +++ b/test/helpers/test-http-api.js @@ -0,0 +1,99 @@ +import request from 'supertest'; +import assert from 'assert'; + +export default function testHttpApi () { + describe('GET /', () => { + it('respond with nothing, but respond', function (done) { + request(this.server) + .get('/') + .expect('Content-Type', /json/) + .expect(/\{"tinylr":"Welcome","version":"[\d].[\d].[\d]+"\}/) + .expect(200, done); + }); + + it('unknown route respond with proper 404 and error message', function (done) { + request(this.server) + .get('/whatev') + .expect('Content-Type', /json/) + .expect('{"error":"not_found","reason":"no such route"}') + .expect(404, done); + }); + }); + + describe('GET /changed', () => { + it('with no clients, no files', function (done) { + request(this.server) + .get('/changed') + .expect('Content-Type', /json/) + .expect(/"clients":\[\]/) + .expect(/"files":\[\]/) + .expect(200, done); + }); + + it('with no clients, some files', function (done) { + request(this.server) + .get('/changed?files=gonna.css,test.css,it.css') + .expect('Content-Type', /json/) + .expect('{"clients":[],"files":["gonna.css","test.css","it.css"]}') + .expect(200, done); + }); + }); + + describe('POST /changed', () => { + it('with no clients, no files', function (done) { + request(this.server) + .post('/changed') + .expect('Content-Type', /json/) + .expect(/"clients":\[\]/) + .expect(/"files":\[\]/) + .expect(200, done); + }); + + it('with no clients, some files', function (done) { + const data = { clients: [], files: ['cat.css', 'sed.css', 'ack.js'] }; + + request(this.server) + .post('/changed') + // .type('json') + .send({ files: data.files }) + .expect('Content-Type', /json/) + .expect(JSON.stringify(data)) + .expect(200, done); + }); + }); + + describe('POST /alert', () => { + it('with no clients, no message', function (done) { + const data = { clients: [] }; + request(this.server) + .post('/alert') + .expect('Content-Type', /json/) + .expect(JSON.stringify(data)) + .expect(200, done); + }); + + it('with no clients, some message', function (done) { + const message = 'Hello Client!'; + const data = { clients: [], message: message }; + request(this.server) + .post('/alert') + .send({ message: message }) + .expect('Content-Type', /json/) + .expect(JSON.stringify(data)) + .expect(200, done); + }); + }); + + describe('GET /kill', () => { + it('shutdown the server', function (done) { + const srv = this.server; + request(srv) + .get('/kill') + .expect(200, err => { + if (err) return done(err); + assert.ok(!srv._handle); + done(); + }); + }); + }); +} diff --git a/test/server-custom-livereload.js b/test/server-custom-livereload.js index 29c5517..72103b5 100644 --- a/test/server-custom-livereload.js +++ b/test/server-custom-livereload.js @@ -1,7 +1,7 @@ -import request from 'supertest'; -import assert from 'assert'; import listen from './helpers/listen'; +import request from 'supertest'; import {PassThrough} from 'stream'; +import testHttpApi from './helpers/test-http-api'; describe('tiny-lr', () => { before(listen({ @@ -14,87 +14,7 @@ describe('tiny-lr', () => { } })); - describe('GET /', () => { - it('respond with nothing, but respond', function (done) { - request(this.server) - .get('/') - .expect('Content-Type', /json/) - .expect(/\{"tinylr":"Welcome","version":"[\d].[\d].[\d]+"\}/) - .expect(200, done); - }); - - it('unknown route respond with proper 404 and error message', function (done) { - request(this.server) - .get('/whatev') - .expect('Content-Type', /json/) - .expect('{"error":"not_found","reason":"no such route"}') - .expect(404, done); - }); - }); - - describe('GET /changed', () => { - it('with no clients, no files', function (done) { - request(this.server) - .get('/changed') - .expect('Content-Type', /json/) - .expect(/"clients":\[\]/) - .expect(/"files":\[\]/) - .expect(200, done); - }); - - it('with no clients, some files', function (done) { - request(this.server) - .get('/changed?files=gonna.css,test.css,it.css') - .expect('Content-Type', /json/) - .expect('{"clients":[],"files":["gonna.css","test.css","it.css"]}') - .expect(200, done); - }); - }); - - describe('POST /changed', () => { - it('with no clients, no files', function (done) { - request(this.server) - .post('/changed') - .expect('Content-Type', /json/) - .expect(/"clients":\[\]/) - .expect(/"files":\[\]/) - .expect(200, done); - }); - - it('with no clients, some files', function (done) { - const data = { clients: [], files: ['cat.css', 'sed.css', 'ack.js'] }; - - request(this.server) - .post('/changed') - // .type('json') - .send({ files: data.files }) - .expect('Content-Type', /json/) - .expect(JSON.stringify(data)) - .expect(200, done); - }); - }); - - describe('POST /alert', () => { - it('with no clients, no message', function (done) { - const data = { clients: [] }; - request(this.server) - .post('/alert') - .expect('Content-Type', /json/) - .expect(JSON.stringify(data)) - .expect(200, done); - }); - - it('with no clients, some message', function (done) { - const message = 'Hello Client!'; - const data = { clients: [], message: message }; - request(this.server) - .post('/alert') - .send({ message: message }) - .expect('Content-Type', /json/) - .expect(JSON.stringify(data)) - .expect(200, done); - }); - }); + testHttpApi(this); describe('GET /livereload.js', () => { it('respond with livereload script', function (done) { @@ -104,17 +24,4 @@ describe('tiny-lr', () => { .expect(200, done); }); }); - - describe('GET /kill', () => { - it('shutdown the server', function (done) { - const srv = this.server; - request(srv) - .get('/kill') - .expect(200, err => { - if (err) return done(err); - assert.ok(!srv._handle); - done(); - }); - }); - }); }); diff --git a/test/server.js b/test/server.js index 31aa946..2952ffe 100644 --- a/test/server.js +++ b/test/server.js @@ -1,91 +1,11 @@ -import request from 'supertest'; -import assert from 'assert'; import listen from './helpers/listen'; +import request from 'supertest'; +import testHttpApi from './helpers/test-http-api'; describe('tiny-lr', () => { before(listen()); - describe('GET /', () => { - it('respond with nothing, but respond', function (done) { - request(this.server) - .get('/') - .expect('Content-Type', /json/) - .expect(/\{"tinylr":"Welcome","version":"[\d].[\d].[\d]+"\}/) - .expect(200, done); - }); - - it('unknown route respond with proper 404 and error message', function (done) { - request(this.server) - .get('/whatev') - .expect('Content-Type', /json/) - .expect('{"error":"not_found","reason":"no such route"}') - .expect(404, done); - }); - }); - - describe('GET /changed', () => { - it('with no clients, no files', function (done) { - request(this.server) - .get('/changed') - .expect('Content-Type', /json/) - .expect(/"clients":\[\]/) - .expect(/"files":\[\]/) - .expect(200, done); - }); - - it('with no clients, some files', function (done) { - request(this.server) - .get('/changed?files=gonna.css,test.css,it.css') - .expect('Content-Type', /json/) - .expect('{"clients":[],"files":["gonna.css","test.css","it.css"]}') - .expect(200, done); - }); - }); - - describe('POST /changed', () => { - it('with no clients, no files', function (done) { - request(this.server) - .post('/changed') - .expect('Content-Type', /json/) - .expect(/"clients":\[\]/) - .expect(/"files":\[\]/) - .expect(200, done); - }); - - it('with no clients, some files', function (done) { - const data = { clients: [], files: ['cat.css', 'sed.css', 'ack.js'] }; - - request(this.server) - .post('/changed') - // .type('json') - .send({ files: data.files }) - .expect('Content-Type', /json/) - .expect(JSON.stringify(data)) - .expect(200, done); - }); - }); - - describe('POST /alert', () => { - it('with no clients, no message', function (done) { - const data = { clients: [] }; - request(this.server) - .post('/alert') - .expect('Content-Type', /json/) - .expect(JSON.stringify(data)) - .expect(200, done); - }); - - it('with no clients, some message', function (done) { - const message = 'Hello Client!'; - const data = { clients: [], message: message }; - request(this.server) - .post('/alert') - .send({ message: message }) - .expect('Content-Type', /json/) - .expect(JSON.stringify(data)) - .expect(200, done); - }); - }); + testHttpApi(this); describe('GET /livereload.js', () => { it('respond with livereload script', function (done) { @@ -95,17 +15,4 @@ describe('tiny-lr', () => { .expect(200, done); }); }); - - describe('GET /kill', () => { - it('shutdown the server', function (done) { - const srv = this.server; - request(srv) - .get('/kill') - .expect(200, err => { - if (err) return done(err); - assert.ok(!srv._handle); - done(); - }); - }); - }); }); From ab0c253408e6f94b0c487258a8c39872931e67da Mon Sep 17 00:00:00 2001 From: Emil Bay Date: Mon, 20 Feb 2017 19:08:07 +0100 Subject: [PATCH 4/4] Fix ternary style --- lib/server.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/server.js b/lib/server.js index 390e1e2..a99d9bc 100644 --- a/lib/server.js +++ b/lib/server.js @@ -25,11 +25,9 @@ class Server extends events.EventEmitter { this.options = options; - options.livereload = typeof options.livereload === 'string' - ? wrapStream(options.livereload) - : typeof options.livereload === 'function' - ? options.livereload - : wrapStream(require.resolve('livereload-js/dist/livereload.js')); + options.livereload = typeof options.livereload === 'string' ? wrapStream(options.livereload) + : typeof options.livereload === 'function' ? options.livereload + : wrapStream(require.resolve('livereload-js/dist/livereload.js')); // todo: change falsy check to allow 0 for random port options.port = parseInt(options.port || 35729, 10);