From adeb92e1e37551a6cbf3063942d6c2c7efbdff10 Mon Sep 17 00:00:00 2001 From: Islam ElHakmi Date: Thu, 2 Apr 2020 14:58:23 +0200 Subject: [PATCH] feat: allow open option to accept an object (#2492) * feat: allow open option to accept object * test: update snapshot * test: spread argv * test: remove error checks & use toBeCalledWith instead * test: return logMock error checks * test: remove unnecessary lines * test: update success & failure types for open option --- lib/options.json | 5 +- lib/utils/runOpen.js | 3 + test/options.test.js | 4 +- .../__snapshots__/createConfig.test.js.snap | 23 ++++- test/server/utils/createConfig.test.js | 16 +++- test/server/utils/runOpen.test.js | 96 +++++++++++++++++++ 6 files changed, 142 insertions(+), 5 deletions(-) diff --git a/lib/options.json b/lib/options.json index ab67fdd5d3..43c8d30b94 100644 --- a/lib/options.json +++ b/lib/options.json @@ -219,6 +219,9 @@ }, { "type": "boolean" + }, + { + "type": "object" } ] }, @@ -460,7 +463,7 @@ "mimeTypes": "should be {Object} (https://webpack.js.org/configuration/dev-server/#devservermimetypes-)", "noInfo": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devservernoinfo-)", "onListening": "should be {Function} (https://webpack.js.org/configuration/dev-server/#onlistening)", - "open": "should be {String|Boolean} (https://webpack.js.org/configuration/dev-server/#devserveropen)", + "open": "should be {String|Boolean|Object} (https://webpack.js.org/configuration/dev-server/#devserveropen)", "openPage": "should be {String|Array} (https://webpack.js.org/configuration/dev-server/#devserveropenpage)", "overlay": "should be {Boolean|Object} (https://webpack.js.org/configuration/dev-server/#devserveroverlay)", "pfx": "should be {String|Buffer} (https://webpack.js.org/configuration/dev-server/#devserverpfx)", diff --git a/lib/utils/runOpen.js b/lib/utils/runOpen.js index 0b42eff54d..0fe1eb6895 100644 --- a/lib/utils/runOpen.js +++ b/lib/utils/runOpen.js @@ -11,6 +11,9 @@ function runOpen(uri, options, log) { if (typeof options.open === 'string') { openOptions = Object.assign({}, openOptions, { app: options.open }); openOptionValue = `: "${options.open}"`; + } else if (typeof options.open === 'object') { + openOptions = options.open; + openOptionValue = `: "${JSON.stringify(options.open)}"`; } const pages = diff --git a/test/options.test.js b/test/options.test.js index 409dc07bec..26b198b41d 100644 --- a/test/options.test.js +++ b/test/options.test.js @@ -262,8 +262,8 @@ describe('options', () => { failure: [''], }, open: { - success: [true, ''], - failure: [{}], + success: [true, '', {}], + failure: [[]], }, openPage: { success: [''], diff --git a/test/server/utils/__snapshots__/createConfig.test.js.snap b/test/server/utils/__snapshots__/createConfig.test.js.snap index dd2215151b..7fde2cf238 100644 --- a/test/server/utils/__snapshots__/createConfig.test.js.snap +++ b/test/server/utils/__snapshots__/createConfig.test.js.snap @@ -802,7 +802,28 @@ Object { } `; -exports[`createConfig open option (browser) 1`] = ` +exports[`createConfig open option (object) 1`] = ` +Object { + "hot": true, + "hotOnly": false, + "noInfo": true, + "open": Object { + "app": Array [ + "Google Chrome", + "--incognito", + ], + }, + "openPage": "", + "port": 8080, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, +} +`; + +exports[`createConfig open option (string) 1`] = ` Object { "hot": true, "hotOnly": false, diff --git a/test/server/utils/createConfig.test.js b/test/server/utils/createConfig.test.js index 746b7dba64..7734250737 100644 --- a/test/server/utils/createConfig.test.js +++ b/test/server/utils/createConfig.test.js @@ -855,7 +855,7 @@ describe('createConfig', () => { expect(config).toMatchSnapshot(); }); - it('open option (browser)', () => { + it('open option (string)', () => { const config = createConfig( webpackConfig, Object.assign({}, argv, { open: 'Google Chrome' }), @@ -865,6 +865,20 @@ describe('createConfig', () => { expect(config).toMatchSnapshot(); }); + it('open option (object)', () => { + const config = createConfig( + webpackConfig, + { + ...argv, + open: { + app: ['Google Chrome', '--incognito'], + }, + }, + { port: 8080 } + ); + expect(config).toMatchSnapshot(); + }); + it('openPage option', () => { const config = createConfig( webpackConfig, diff --git a/test/server/utils/runOpen.test.js b/test/server/utils/runOpen.test.js index 80fe358512..50b9d37575 100644 --- a/test/server/utils/runOpen.test.js +++ b/test/server/utils/runOpen.test.js @@ -17,6 +17,8 @@ describe('runOpen util', () => { it('on specify URL', () => { return runOpen('https://example.com', {}, console).then(() => { + expect(opn).toBeCalledWith('https://example.com', { wait: false }); + expect(opn.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com", @@ -34,6 +36,10 @@ describe('runOpen util', () => { { openPage: '/index.html' }, console ).then(() => { + expect(opn).toBeCalledWith('https://example.com/index.html', { + wait: false, + }); + expect(opn.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com/index.html", @@ -51,6 +57,10 @@ describe('runOpen util', () => { { openPage: ['/index.html'] }, console ).then(() => { + expect(opn).toBeCalledWith('https://example.com/index.html', { + wait: false, + }); + expect(opn.mock.calls[0]).toMatchSnapshot(); }); }); @@ -61,6 +71,13 @@ describe('runOpen util', () => { { openPage: ['/index.html', '/index2.html'] }, console ).then(() => { + expect(opn).toBeCalledWith('https://example.com/index.html', { + wait: false, + }); + expect(opn).toBeCalledWith('https://example.com/index2.html', { + wait: false, + }); + expect(opn.mock.calls[0]).toMatchSnapshot(); expect(opn.mock.calls[1]).toMatchSnapshot(); }); @@ -72,6 +89,11 @@ describe('runOpen util', () => { { open: 'Google Chrome' }, console ).then(() => { + expect(opn).toBeCalledWith('https://example.com', { + app: 'Google Chrome', + wait: false, + }); + expect(opn.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com", @@ -90,6 +112,11 @@ describe('runOpen util', () => { { open: 'Google Chrome', openPage: '/index.html' }, console ).then(() => { + expect(opn).toBeCalledWith('https://example.com/index.html', { + app: 'Google Chrome', + wait: false, + }); + expect(opn.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com/index.html", @@ -108,6 +135,11 @@ describe('runOpen util', () => { { open: 'Google Chrome', openPage: 'https://example2.com' }, console ).then(() => { + expect(opn).toBeCalledWith('https://example2.com', { + app: 'Google Chrome', + wait: false, + }); + expect(opn.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example2.com", @@ -126,6 +158,10 @@ describe('runOpen util', () => { { open: 'Google Chrome', openPage: 'http://example2.com' }, console ).then(() => { + expect(opn).toBeCalledWith('http://example2.com', { + app: 'Google Chrome', + wait: false, + }); expect(opn.mock.calls[0]).toMatchInlineSnapshot(` Array [ "http://example2.com", @@ -148,6 +184,14 @@ describe('runOpen util', () => { }, console ).then(() => { + expect(opn).toBeCalledWith('https://example2.com', { + app: 'Google Chrome', + wait: false, + }); + expect(opn).toBeCalledWith('https://example3.com', { + app: 'Google Chrome', + wait: false, + }); expect(opn.mock.calls[0]).toMatchSnapshot(); expect(opn.mock.calls[1]).toMatchSnapshot(); }); @@ -162,6 +206,15 @@ describe('runOpen util', () => { }, console ).then(() => { + expect(opn).toBeCalledWith('https://example.com/index.html', { + app: 'Google Chrome', + wait: false, + }); + expect(opn).toBeCalledWith('https://example2.com', { + app: 'Google Chrome', + wait: false, + }); + expect(opn.mock.calls[0]).toMatchSnapshot(); expect(opn.mock.calls[1]).toMatchSnapshot(); }); @@ -183,6 +236,8 @@ describe('runOpen util', () => { expect(logMock.warn.mock.calls[0][0]).toMatchInlineSnapshot( `"Unable to open \\"https://example.com\\" in browser. If you are running in a headless environment, please do not use the --open flag"` ); + expect(opn).toBeCalledWith('https://example.com', { wait: false }); + expect(opn.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com", @@ -203,6 +258,10 @@ describe('runOpen util', () => { expect(logMock.warn.mock.calls[0][0]).toMatchInlineSnapshot( `"Unable to open \\"https://example.com/index.html\\" in browser. If you are running in a headless environment, please do not use the --open flag"` ); + expect(opn).toBeCalledWith('https://example.com/index.html', { + wait: false, + }); + expect(opn.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com/index.html", @@ -223,6 +282,11 @@ describe('runOpen util', () => { expect(logMock.warn.mock.calls[0][0]).toMatchInlineSnapshot( `"Unable to open \\"https://example.com\\" in browser: \\"Google Chrome\\". If you are running in a headless environment, please do not use the --open flag"` ); + expect(opn).toBeCalledWith('https://example.com', { + app: 'Google Chrome', + wait: false, + }); + expect(opn.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com", @@ -244,6 +308,11 @@ describe('runOpen util', () => { expect(logMock.warn.mock.calls[0][0]).toMatchInlineSnapshot( `"Unable to open \\"https://example.com/index.html\\" in browser: \\"Google Chrome\\". If you are running in a headless environment, please do not use the --open flag"` ); + expect(opn).toBeCalledWith('https://example.com/index.html', { + app: 'Google Chrome', + wait: false, + }); + expect(opn.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com/index.html", @@ -255,5 +324,32 @@ describe('runOpen util', () => { `); }); }); + + it('on specify URL with page in Google Chrome incognito mode and log error ', () => { + return runOpen( + 'https://example.com', + { + open: { app: ['Google Chrome', '--incognito'] }, + openPage: '/index.html', + }, + logMock + ).then(() => { + expect(opn).toBeCalledWith('https://example.com/index.html', { + app: ['Google Chrome', '--incognito'], + }); + + expect(opn.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "https://example.com/index.html", + Object { + "app": Array [ + "Google Chrome", + "--incognito", + ], + }, + ] + `); + }); + }); }); });