From 78f1a60e92914d4804bcb7ad609ee46ce32fcac8 Mon Sep 17 00:00:00 2001 From: Marc Nuri Date: Sun, 11 Sep 2022 10:54:08 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20help=20uses=20bundled=20pr?= =?UTF-8?q?eload=20script?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc Nuri --- .eslintrc | 3 +- ...wser-help.test.js => help.browser.test.js} | 24 +++--- src/help/__tests/index.test.js | 27 ------- src/help/__tests/preload.test.js | 74 +++++++++++-------- src/help/docs.browser.val-loader.js | 39 ++++++++++ .../{browser-help.css => help.browser.css} | 0 src/help/{browser-help.js => help.browser.js} | 0 src/help/index.html | 4 +- src/help/index.js | 24 +----- src/help/preload.js | 17 +++-- webpack.js | 4 +- 11 files changed, 110 insertions(+), 106 deletions(-) rename src/help/__tests/{browser-help.test.js => help.browser.test.js} (72%) create mode 100644 src/help/docs.browser.val-loader.js rename src/help/{browser-help.css => help.browser.css} (100%) rename src/help/{browser-help.js => help.browser.js} (100%) diff --git a/.eslintrc b/.eslintrc index 8a78622b..abfa58a2 100644 --- a/.eslintrc +++ b/.eslintrc @@ -14,7 +14,8 @@ "experimentalObjectRestSpread": true, "destructuring": true, "spread": true - } + }, + "sourceType": "module" }, "rules": { // Possible Errors diff --git a/src/help/__tests/browser-help.test.js b/src/help/__tests/help.browser.test.js similarity index 72% rename from src/help/__tests/browser-help.test.js rename to src/help/__tests/help.browser.test.js index 6003b7fb..b465f7b2 100644 --- a/src/help/__tests/browser-help.test.js +++ b/src/help/__tests/help.browser.test.js @@ -25,31 +25,25 @@ const mockDOM = () => { describe('Help in Browser test suite', () => { let mockIpcRenderer; beforeEach(() => { + require('../../../bundles/help.preload'); mockIpcRenderer = { send: jest.fn() }; - window.preact = require('preact'); - window.html = require('htm').bind(window.preact.h); - window.TopBar = require('../../components').topBar(window.html); - window.APP_EVENTS = {closeDialog: 'close the dialog'}; - window.ELECTRONIM_VERSION = '1.33.7'; - window.docs = { - 'Setup.md': 'Setup guide', - 'Keyboard-shortcuts.md': 'Keyboard shortcuts', - 'Troubleshooting.md': 'Troubleshooting' - }; - window.ipcRenderer = mockIpcRenderer; mockDOM(); + window.ipcRenderer = mockIpcRenderer; + window.ELECTRONIM_VERSION = '1.33.7'; jest.isolateModules(() => { - require('../browser-help'); + require('../help.browser'); }); }); test('render, should render all documents', () => { // Then expect(document.querySelector('.toc-container').innerHTML) .toMatch(/Table of Contents/); - expect(document.querySelector('.documents-container').innerHTML) - .toMatch(/Setup guide.+Keyboard shortcuts.+Troubleshooting/); + const documentsContent = document.querySelector('.documents-container').innerHTML; + expect(documentsContent).toContain('

Setup

'); + expect(documentsContent).toContain('

Keyboard Shortcuts

'); + expect(documentsContent).toContain('

Troubleshooting

'); }); test('render, should show version in footer', () => { // Then @@ -62,7 +56,7 @@ describe('Help in Browser test suite', () => { fireEvent.click(document.querySelector('.button.is-link.is-light')); // Then expect(mockIpcRenderer.send).toHaveBeenCalledTimes(1); - expect(mockIpcRenderer.send).toHaveBeenCalledWith('close the dialog'); + expect(mockIpcRenderer.send).toHaveBeenCalledWith('closeDialog'); }); }); }); diff --git a/src/help/__tests/index.test.js b/src/help/__tests/index.test.js index 4590d595..3ebc2c49 100644 --- a/src/help/__tests/index.test.js +++ b/src/help/__tests/index.test.js @@ -13,8 +13,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -const path = require('path'); -const DOCS_DIR = path.resolve(__dirname, '../../../docs'); describe('Help module test suite', () => { let mockBrowserView; let help; @@ -28,31 +26,6 @@ describe('Help module test suite', () => { })); help = require('../'); }); - describe('fixRelativeUrls', () => { - test('Combination of absolute and relative paths', () => { - // Given - const input = ` - - - - `; - // When - const result = help.fixRelativeUrls(input); - // Then - expect(result).toBe(` - - - - `); - }); - }); - test('loadDocs, should load object with documentation', () => { - // When - const docs = help.loadDocs(); - // Then - expect(Object.keys(docs)).toContain('Setup.md'); - expect(docs['Setup.md']).toMatch(/There are several options available/i); - }); test('openHelpDialog, should open dialog and add event listeners', () => { // Given mockBrowserView.setBounds = jest.fn(); diff --git a/src/help/__tests/preload.test.js b/src/help/__tests/preload.test.js index 7e9a14df..49753135 100644 --- a/src/help/__tests/preload.test.js +++ b/src/help/__tests/preload.test.js @@ -16,41 +16,51 @@ const {waitFor} = require('@testing-library/dom'); describe('Help Module preload test suite', () => { - let mockHelp; beforeEach(() => { - mockHelp = {loadDocs: jest.fn()}; jest.resetModules(); - jest.mock('../../main/preload', () => { - global.mainPreloadLoaded = true; - }); - jest.mock('../', () => mockHelp); - }); - test('preload', () => { - // When - require('../preload'); - // Then - expect(global.mainPreloadLoaded).toBe(true); - expect(mockHelp.loadDocs).toHaveBeenCalledTimes(1); - }); - test('bulma is loaded', async () => { - // When - require('../preload'); - window.document.body.innerHTML = '
'; - // Then - await waitFor(() => expect(document.querySelector('link[href*="bulma"]')).not.toBeNull()); }); - test('fontawesome is loaded', async () => { - // When - require('../preload'); - window.document.body.innerHTML = '
'; - // Then - await waitFor(() => expect(document.querySelector('link[href*="fontawesome"]')).not.toBeNull()); + describe('preload (just for coverage and sanity, see bundle tests)', () => { + beforeEach(() => { + jest.mock('../help.browser.css', () => {}); + jest.mock('!val-loader!./docs.browser.val-loader', () => ({ + docs: {} + }), {virtual: true}); + window.APP_EVENTS = {}; + window.ELECTRONIM_VERSION = '1.33.7'; + require('../preload'); + }); + test('adds required libraries', () => { + expect(window.ELECTRONIM_VERSION).toEqual('1.33.7'); + }); }); - test('browser-help is loaded', async () => { - // When - require('../preload'); - window.document.body.innerHTML = '
'; - // Then - await waitFor(() => expect(document.querySelector('link[href*="browser-help"]')).not.toBeNull()); + describe('preload.bundle', () => { + beforeEach(() => { + require('../../../bundles/help.preload'); + }); + test('loads styles in order', async () => { + // When + document.body.append(document.createElement('div')); + // Then + await waitFor(() => expect(document.head.children.length).toBeGreaterThan(0)); + const styles = Array.from(document.querySelectorAll('style')); + expect(styles).toHaveLength(1); + expect(styles[0].innerHTML).toContain('.help-root {'); + }); + test('adds required libraries', () => { + expect(window.ELECTRONIM_VERSION).toEqual('0.0.0'); + expect(window.preact).not.toBeUndefined(); + expect(window.preactHooks).not.toBeUndefined(); + expect(window.html).not.toBeUndefined(); + expect(window.TopBar).not.toBeUndefined(); + }); + test('loads document contents with valid asset URLs', () => { + expect(window.docs).toEqual(expect.objectContaining({ + 'Keyboard-shortcuts.md': expect.stringMatching(/

Keyboard Shortcuts/i), + 'Roadmap.md': expect.any(String), + 'Screenshots.md': expect.stringContaining('Main'), + 'Setup.md': expect.stringMatching(/There are several options available/i), + 'Troubleshooting.md': expect.any(String) + })); + }); }); }); diff --git a/src/help/docs.browser.val-loader.js b/src/help/docs.browser.val-loader.js new file mode 100644 index 00000000..2df7f374 --- /dev/null +++ b/src/help/docs.browser.val-loader.js @@ -0,0 +1,39 @@ +/* + Copyright 2019 Marc Nuri San Felix + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ +const fs = require('fs'); +const path = require('path'); +const md = require('markdown-it')({html: true, xhtmlOut: true}); // NOSONAR + +const DOCS_DIR = path.resolve(__dirname, '..', '..', 'docs'); +// Should be a relative path from the src/help directory (or wherever index.html is located) +const DOCS_DIR_RELATIVE = '../../docs'; + +const fixRelativeUrls = s => s.replace( + /((src|href)\s*?=\s*?['"](?!http))([^'"]+)(['"])/gi, + `$1${DOCS_DIR_RELATIVE}/$3$4` +); + +const loadDocs = () => fs.readdirSync(DOCS_DIR) + .filter(fileName => fileName.endsWith('.md')) + .reduce((acc, fileName) => { + acc[fileName] = fixRelativeUrls(md.render(fs.readFileSync(path.resolve(DOCS_DIR, fileName), 'utf8'))); + return acc; + }, {}); + +module.exports = () => ({ + cacheable: true, + code: `module.exports = {docs: ${JSON.stringify(loadDocs())}};` +}); diff --git a/src/help/browser-help.css b/src/help/help.browser.css similarity index 100% rename from src/help/browser-help.css rename to src/help/help.browser.css diff --git a/src/help/browser-help.js b/src/help/help.browser.js similarity index 100% rename from src/help/browser-help.js rename to src/help/help.browser.js diff --git a/src/help/index.html b/src/help/index.html index 15a4e480..da82c99c 100644 --- a/src/help/index.html +++ b/src/help/index.html @@ -23,6 +23,8 @@
- + + + diff --git a/src/help/index.js b/src/help/index.js index dfff22db..13602c75 100644 --- a/src/help/index.js +++ b/src/help/index.js @@ -14,36 +14,18 @@ limitations under the License. */ const {BrowserView} = require('electron'); -const fs = require('fs'); const path = require('path'); -const md = require('markdown-it')({html: true, xhtmlOut: true}); const {handleRedirect} = require('../tab-manager/redirect'); const {showDialog} = require('../browser-window'); -const DOCS_DIR = path.resolve(__dirname, '../../docs'); - const webPreferences = { contextIsolation: false, nativeWindowOpen: true, nodeIntegration: false, - sandbox: false, - preload: path.resolve(__dirname, 'preload.js') + sandbox: true, + preload: path.resolve(__dirname, '..', '..', 'bundles', 'help.preload.js') }; -// Visible for testing -const fixRelativeUrls = s => s.replace( - /((src|href)\s*?=\s*?['"](?!http))([^'"]+)(['"])/gi, - `$1${DOCS_DIR}/$3$4` -); - -const loadDocs = () => fs.readdirSync(DOCS_DIR) - .filter(fileName => fileName.endsWith('.md')) - .reduce((acc, fileName) => { - acc[fileName] = fixRelativeUrls(md.render(fs.readFileSync(path.resolve(DOCS_DIR, fileName), 'utf8'))); - return acc; - }, {}); - - const openHelpDialog = mainWindow => () => { const helpView = new BrowserView({webPreferences}); helpView.webContents.loadURL(`file://${__dirname}/index.html`); @@ -53,4 +35,4 @@ const openHelpDialog = mainWindow => () => { showDialog(mainWindow, helpView); }; -module.exports = {fixRelativeUrls, openHelpDialog, loadDocs}; +module.exports = {openHelpDialog}; diff --git a/src/help/preload.js b/src/help/preload.js index 58670ef6..49319cce 100644 --- a/src/help/preload.js +++ b/src/help/preload.js @@ -13,16 +13,19 @@ See the License for the specific language governing permissions and limitations under the License. */ -require('../main/preload'); -const components = require('../components'); +/* eslint-disable no-undef */ +const {ipcRenderer} = require('electron'); +const {docs} = require('!val-loader!./docs.browser.val-loader'); +const {topBar} = require('../components/top-bar'); -components.bulma(); -components.fontAwesome(); -components.addStylesheet('./browser-help.css'); +require('./help.browser.css'); +window.ipcRenderer = ipcRenderer; +window.APP_EVENTS = APP_EVENTS; +window.ELECTRONIM_VERSION = ELECTRONIM_VERSION; window.preact = require('preact'); window.preactHooks = require('preact/hooks'); window.html = require('htm').bind(window.preact.h); -window.TopBar = components.topBar(window.html); +window.TopBar = topBar(window.html); -window.docs = require('./').loadDocs(); +window.docs = docs; diff --git a/webpack.js b/webpack.js index cff8c86b..0314d113 100755 --- a/webpack.js +++ b/webpack.js @@ -25,7 +25,7 @@ const {APP_EVENTS, ELECTRONIM_VERSION} = require('./src/constants'); const BUNDLES_DIR = 'bundles'; const ENTRIES = [ // 'chrome-tabs', - // 'help', + 'help' // 'main', // 'settings', // 'tab-manager' @@ -72,7 +72,7 @@ const bundle = webpack({ // eslint-disable-next-line prefer-const let observer; const callback = () => { - if (document.head) { + if (document && document.head) { document.head.append(element); observer.disconnect(); }