├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── babel.config.json ├── jestconfig.json ├── manifest.yml ├── package-lock.json ├── package.json └── src ├── index.js ├── tests ├── index.test.js └── utils.test.js └── utils.js /.gitignore: -------------------------------------------------------------------------------- 1 | coverage 2 | node_modules 3 | index.js 4 | .coveralls.yml 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 10 4 | after_success: npm run test:coverage 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### [1.1.4](https://github.com/soofka/netlify-plugin-chromium/compare/v1.1.3...v1.1.4) (2020-06-11) 6 | 7 | 8 | ### Bug Fixes 9 | 10 | * switched default value of setChromePathInEnv parameter to true (as per README) ([7e9f6df](https://github.com/soofka/netlify-plugin-chromium/commit/7e9f6df41f84c8a6efec9c09bf5475eab8bb5236)) 11 | 12 | ### [1.1.3](https://github.com/soofka/netlify-plugin-chromium/compare/v1.1.2...v1.1.3) (2020-06-11) 13 | 14 | 15 | ### Bug Fixes 16 | 17 | * brought back Travis CI ([5a93402](https://github.com/soofka/netlify-plugin-chromium/commit/5a9340243a18eb52fe35f2282890955381adf040)) 18 | 19 | ### [1.1.2](https://github.com/soofka/netlify-plugin-chromium/compare/v1.1.1...v1.1.2) (2020-06-11) 20 | 21 | 22 | ### Bug Fixes 23 | 24 | * added manifest.yml file properly ([d85cd3e](https://github.com/soofka/netlify-plugin-chromium/commit/d85cd3ef03c75ed2cd0641d03c4b6543d39a84ec)) 25 | 26 | ### [1.1.1](https://github.com/soofka/netlify-plugin-chromium/compare/v1.1.0...v1.1.1) (2020-04-30) 27 | 28 | 29 | ### Bug Fixes 30 | 31 | * switched to appropriate Netlify task runner to run Chromium installation ([481bb67](https://github.com/soofka/netlify-plugin-chromium/commit/481bb67e21871187c4e408a8beb68e253cd9a54c)) 32 | 33 | ## [1.1.0](https://github.com/soofka/netlify-plugin-chromium/compare/v1.0.1...v1.1.0) (2020-04-30) 34 | 35 | 36 | ### Features 37 | 38 | * added support for yarn, improved performance and cross-platform compatibility ([c320327](https://github.com/soofka/netlify-plugin-chromium/commit/c3203276f9d919aff8116427177ad2cc6921bd0c)) 39 | 40 | ### [1.0.1](https://github.com/soofka/netlify-plugin-chromium/compare/v1.0.0...v1.0.1) (2020-04-29) 41 | 42 | 43 | ### Bug Fixes 44 | 45 | * updated manifest snapshot test ([22ffbf1](https://github.com/soofka/netlify-plugin-chromium/commit/22ffbf14a19ce158c3d2033e769e57143dba1592)) 46 | 47 | ## [1.0.0](https://github.com/soofka/netlify-plugin-chromium/compare/v0.0.4...v1.0.0) (2020-04-29) 48 | 49 | 50 | ### Bug Fixes 51 | 52 | * battle tested the package, fixed remaining minor issues, prepared for release ([abb33dd](https://github.com/soofka/netlify-plugin-chromium/commit/abb33ddea450a8180a60c3995afb5c119b6b99bc)) 53 | 54 | ### [0.0.4](https://github.com/soofka/netlify-plugin-chromium/compare/v0.0.3...v0.0.4) (2020-04-29) 55 | 56 | 57 | ### Bug Fixes 58 | 59 | * added correct entry point in package.json file ([a3bc1d4](https://github.com/soofka/netlify-plugin-chromium/commit/a3bc1d4a05acfb8ec174ada130af85f5ea0d0ee5)) 60 | 61 | ### [0.0.3](https://github.com/soofka/netlify-plugin-chromium/compare/v0.0.2...v0.0.3) (2020-04-29) 62 | 63 | 64 | ### Bug Fixes 65 | 66 | * bundled plugin into single output file as required by Netlify ([c2811e5](https://github.com/soofka/netlify-plugin-chromium/commit/c2811e5bed8a8d83e760e53992a06f32d7d6747d)) 67 | 68 | ### 0.0.2 (2020-04-29) 69 | 70 | 71 | ### Features 72 | 73 | * added basic implementation of the functionality, documentation and unit tests coverage ([6017bd9](https://github.com/soofka/netlify-plugin-chromium/commit/6017bd9f1ba6aab39cfae87d4625d9f64cf2b227)) 74 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 soofka 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Netlify Plugin Chromium 2 | 3 | ## 2024 update 4 | 5 | **As of 2024, this repository is no longer maintained.** 6 | 7 | [![Build Status](https://travis-ci.org/soofka/netlify-plugin-chromium.svg?branch=master)](https://travis-ci.org/soofka/netlify-plugin-chromium) 8 | [![Coverage Status](https://coveralls.io/repos/soofka/netlify-plugin-chromium/badge.svg?branch=master)](https://coveralls.io/r/soofka/netlify-plugin-chromium?branch=master) 9 | [![Known Vulnerabilities](https://snyk.io/test/github/soofka/netlify-plugin-chromium/badge.svg?branch=master)](https://snyk.io/test/github/soofka/netlify-plugin-chromium?branch=master) 10 | [![NPM version](https://img.shields.io/npm/v/netlify-plugin-chromium.svg)](https://www.npmjs.com/package/netlify-plugin-chromium) 11 | 12 | 🤖 [Netlify Build Plugin](https://docs.netlify.com/configure-builds/build-plugins/) for adding [Chromium](https://github.com/dtolstyi/node-chromium) to [Netlify](https://www.netlify.com) CI/CD pipeline. 13 | 14 | ## About 15 | 16 | 17 | 18 | This is [Netlify Build Plugin](https://docs.netlify.com/configure-builds/build-plugins/). It is meant to be used in projects connected to [Netlify](https://www.netlify.com) CI/CD pipeline. Netlify Build Plugins are currently opt-in BETA feature. Learn how to enable them for your project [here](https://docs.netlify.com/configure-builds/build-plugins/#enable-build-plugins-beta). 19 | 20 | This plugin hooks into installation stage of the build process and extends it with additional step which checks if Chromium is installed and installs Chromium binaries if needed. The latest suitable build of Chromium for your platform will be installed with the help of [chromium npm package](https://www.npmjs.com/package/chromium). Installation typically takes around 20-30 seconds. 21 | 22 | 23 | 24 | ⚠️ **Important**: By default, this plugin modifies value of environment variable `CHROME_PATH`. [Read more »](#modification-of-environment-variables) 25 | 26 | ## Usage 27 | 28 | ### Installation 29 | 30 | First, install this [package from NPM](https://www.npmjs.com/package/chromium) as a dependency in your project: 31 | 32 | ```shell 33 | npm install --save-dev netlify-plugin-chromium 34 | ``` 35 | 36 | _(Alternatively, download its [source code from GitHub](https://github.com/soofka/netlify-plugin-chromium).)_ 37 | 38 | Then, add it to your [Netlify configuration file](https://docs.netlify.com/configure-builds/file-based-configuration): 39 | 40 | ```yaml 41 | plugins: 42 | - package: netlify-plugin-chromium 43 | ``` 44 | 45 | ### Configuration 46 | 47 | #### Options 48 | 49 | | Name | Type | Description | Default value | 50 | | -------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------- | 51 | | `packageManager` | `npm` \| `yarn` | Package manager to install Chromium with; `npm` or `yarn`. | `npm` | 52 | | `setChromePathInEnv` | boolean | If true, sets value of environment variable `CHROME_PATH` to location of local copy of Chromium binaries. This change is required by many tools relying on Chromium to be able to find it and launch it successfully (such as Lighthouse). | `true` | 53 | | `failBuildOnError` | boolean | If true and Chromium installation finished with failure, whole build will fail. Otherwise, only this plugin fails and the rest of the build proceeds as usual. | `false` | 54 | 55 | #### Example 56 | 57 | ```yaml 58 | plugins: 59 | - package: netlify-plugin-chromium 60 | inputs: 61 | packageManager: yarn 62 | setChromePathInEnv: false 63 | failBuildOnError: true 64 | ``` 65 | 66 | ### Output 67 | 68 | This plugin will generate output in your build logs similar to this: 69 | 70 | ```shell 71 | 10:50:12 PM: ┌────────────────────────────────────────────────────┐ 72 | 10:50:12 PM: │ 1. onPreBuild command from netlify-plugin-chromium │ 73 | 10:50:12 PM: └────────────────────────────────────────────────────┘ 74 | 10:50:12 PM: ​ 75 | 10:50:12 PM: [NetlifyChromiumPlugin]: Installing Chromium with settings: {"packageManager":"npm","setChromePathInEnv":true,"failBuildOnError":false} 76 | 10:50:12 PM: [NetlifyChromiumPlugin]: Chromium is not available, attempting to download 77 | 10:50:27 PM: > chromium@2.1.2 postinstall /opt/build/repo/node_modules/chromium 78 | 10:50:27 PM: > node install.js 79 | 10:50:27 PM: Step 1. Retrieving Chromium latest revision number 80 | 10:50:27 PM: Step 2. Downloading Chromium (this might take a while). Revision number: 764388 81 | 10:50:29 PM: Step 3. Setting up Chromium binaries 82 | 10:50:36 PM: Process is successfully finished 83 | 10:50:39 PM: + chromium@2.1.2 84 | 10:50:39 PM: added 10 packages from 9 contributors and audited 255724 packages in 26.368s 85 | 10:50:40 PM: 53 packages are looking for funding 86 | 10:50:40 PM: run `npm fund` for details 87 | 10:50:40 PM: found 0 vulnerabilities 88 | 10:50:40 PM: [NetlifyChromiumPlugin]: Setting environment variable CHROME_PATH to /opt/build/repo/node_modules/chromium/lib/chromium/chrome-linux/chrome 89 | 10:50:40 PM: [NetlifyChromiumPlugin]: Chromium installation finished with SUCCESS (path: /opt/build/repo/node_modules/chromium/lib/chromium/chrome-linux/chrome) 90 | 10:50:40 PM: ​ 91 | 10:50:40 PM: (netlify-plugin-chromium onPreBuild completed in 28.4s) 92 | ``` 93 | 94 | ### Modification of environment variables 95 | 96 | By default, this plugin sets value of environment variable `CHROME_PATH` to location of local copy of Chromium binaries. This change is required by many tools relying on Chromium to be able to find it and launch it successfully (such as Lighthouse). However, you can opt out of this change by setting `setChromePathInEnv` parameter to `false`. 97 | 98 | _(In that case it is likely that you'd like to set this variable by yourself. Path to Chromium is exposed in build logs. Chromium is installed separately with each build, but typically it should be at the same location. You can take it from build logs, set it manually, disable `setChromePathInEnv` parameter, re-run the build, and expect it to work properly.)_ 99 | 100 | ### Usage examples 101 | 102 | - [coronavirus-tracker](https://github.com/soofka/coronavirus-tracker) uses this plugin to automatically run [Lighthouse CI](https://github.com/GoogleChrome/lighthouse-ci) tests for each build. 103 | 104 | ## TODO 105 | 106 | - write functional tests with `ChromeLauncher` (especially `getInstallations` method) 107 | -------------------------------------------------------------------------------- /babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "node": "current" 8 | } 9 | } 10 | ] 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /jestconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "moduleDirectories": [ 3 | "node_modules", 4 | "src" 5 | ], 6 | "moduleFileExtensions": [ 7 | "js" 8 | ], 9 | "collectCoverageFrom": [ 10 | "src/**/*.js" 11 | ], 12 | "coveragePathIgnorePatterns": [ 13 | "node_modules", 14 | "tests" 15 | ], 16 | "coverageReporters": [ 17 | "html", 18 | "text", 19 | "text-lcov" 20 | ], 21 | "coverageThreshold": { 22 | "global": { 23 | "branches": 80, 24 | "functions": 30, 25 | "lines": 80, 26 | "statements": 80 27 | } 28 | }, 29 | "transform": { 30 | "^.+\\.js$": "babel-jest" 31 | }, 32 | "testRegex": "tests/.*\\.test\\.js$", 33 | "testURL": "http://localhost" 34 | } 35 | -------------------------------------------------------------------------------- /manifest.yml: -------------------------------------------------------------------------------- 1 | name: netlify-plugin-chromium 2 | inputs: 3 | - name: packageManager 4 | description: Package manager to install Chromium with; npm or yarn. 5 | default: npm 6 | - name: setChromePathInEnv 7 | description: If true, sets value of environment variable CHROME_PATH to location of local copy of Chromium binaries. This change is required by many tools relying on Chromium to be able to find it and launch it successfully (such as Lighthouse). 8 | default: true 9 | - name: failBuildOnError 10 | description: If true and Chromium installation finished with failure, whole build will fail. Otherwise, only this plugin fails and the rest of the build proceeds as usual. 11 | default: false 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "netlify-plugin-chromium", 3 | "version": "1.1.4", 4 | "description": "Netlify Build Plugin for adding Chromium to Netlify CI/CD pipeline", 5 | "keywords": [ 6 | "netlify", 7 | "plugin", 8 | "netlify-plugin", 9 | "netlify plugin", 10 | "netlify build plugin", 11 | "chrome", 12 | "netlify chrome plugin", 13 | "netlify chrome build plugin", 14 | "chromium", 15 | "netlify chromium plugin", 16 | "netlify chromium build plugin" 17 | ], 18 | "author": "Jakub Sowiński (https://jakubsowinski.com)", 19 | "license": "MIT", 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/soofka/netlify-plugin-chromium.git" 23 | }, 24 | "bugs": { 25 | "url": "https://github.com/soofka/netlify-plugin-chromium/issues" 26 | }, 27 | "homepage": "https://github.com/soofka/netlify-plugin-chromium#readme", 28 | "main": "index.js", 29 | "files": [ 30 | "index.js", 31 | "manifest.yml" 32 | ], 33 | "scripts": { 34 | "build": "rimraf index.js && rollup src/index.js --file index.js --format cjs", 35 | "test": "jest --config jestconfig.json", 36 | "test:coverage": "npm run test -- --coverage | coveralls", 37 | "release": "standard-version", 38 | "prepublishOnly": "npm run test && npm run build" 39 | }, 40 | "devDependencies": { 41 | "@babel/core": "^7.9.0", 42 | "@babel/preset-env": "^7.9.5", 43 | "babel-jest": "^25.5.1", 44 | "coveralls": "^3.1.0", 45 | "jest": "^25.5.0", 46 | "rimraf": "^3.0.2", 47 | "rollup": "^2.7.3", 48 | "standard-version": "^8.0.1", 49 | "yamljs": "^0.3.0" 50 | }, 51 | "dependencies": {} 52 | } 53 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import { 2 | log, 3 | getChromiumPath, 4 | installChromium, 5 | } from './utils' 6 | 7 | const NetlifyChromiumPlugin = { 8 | onPreBuild: async ({ inputs, utils }) => { 9 | log(`Installing Chromium with settings: ${JSON.stringify(inputs)}`); 10 | 11 | try { 12 | let chromiumPath; 13 | 14 | try { 15 | chromiumPath = getChromiumPath(); 16 | } catch(requireError) { 17 | log('Chromium is not available, attempting to download'); 18 | 19 | await installChromium(utils.run.command, inputs.packageManager); 20 | chromiumPath = getChromiumPath(); 21 | } 22 | 23 | if (inputs.setChromePathInEnv) { 24 | log(`Setting environmental variable CHROME_PATH to ${chromiumPath}`); 25 | process.env.CHROME_PATH = chromiumPath; 26 | } 27 | 28 | log(`Chromium installation finished with SUCCESS (path: ${chromiumPath})`); 29 | } catch(error) { 30 | log('Chromium installation finished with FAILURE', error); 31 | 32 | const failFunc = inputs.failBuildOnError ? utils.build.failBuild : utils.build.failPlugin; 33 | failFunc('Error during Chromium installation', { error }); 34 | } 35 | }, 36 | }; 37 | 38 | export default NetlifyChromiumPlugin; 39 | -------------------------------------------------------------------------------- /src/tests/index.test.js: -------------------------------------------------------------------------------- 1 | import { 2 | log, 3 | getChromiumPath, 4 | installChromium, 5 | } from '../utils'; 6 | jest.mock('../utils'); 7 | 8 | import NetlifyChromiumPlugin from '../index'; 9 | 10 | describe('NetlifyChromiumPlugin', () => { 11 | const mockError = new Error('MOCK_ERROR'); 12 | 13 | const initialChromiumPath = process.env.CHROME_PATH; 14 | const mockChromiumPath = 'MOCK_CHROMIUM_PATH'; 15 | 16 | const mockInputs = { 17 | mockPackageManager: 'MOCK_PACKAGE_MANAGER', 18 | }; 19 | 20 | const mockUtils = { 21 | run: { 22 | command: jest.fn(), 23 | }, 24 | build: { 25 | failBuild: jest.fn(), 26 | failPlugin: jest.fn(), 27 | } 28 | } 29 | 30 | beforeEach(() => { 31 | log.mockClear(); 32 | getChromiumPath.mockClear(); 33 | installChromium.mockClear(); 34 | 35 | mockUtils.run.command.mockClear(); 36 | mockUtils.build.failBuild.mockClear(); 37 | mockUtils.build.failPlugin.mockClear(); 38 | 39 | process.env.CHROME_PATH = initialChromiumPath; 40 | }); 41 | 42 | it('exists', () => { 43 | expect(NetlifyChromiumPlugin).toBeDefined(); 44 | }); 45 | 46 | it('hooks into installation stage of build process', () => { 47 | expect(NetlifyChromiumPlugin.onPreBuild).toBeDefined(); 48 | expect(typeof NetlifyChromiumPlugin.onPreBuild).toEqual('function'); 49 | }); 50 | 51 | describe('if Chromium is initially installed', () => { 52 | 53 | beforeEach(() => { 54 | getChromiumPath.mockImplementation(() => mockChromiumPath); 55 | }); 56 | 57 | it('does not attempt to install Chromium', async () => { 58 | await NetlifyChromiumPlugin.onPreBuild({ inputs: {} }); 59 | 60 | expect(getChromiumPath).toBeCalledTimes(1); 61 | expect(installChromium).toBeCalledTimes(0); 62 | }); 63 | 64 | describe('if setChromePathInEnv is true', () => { 65 | 66 | const mockLocalInputs = { 67 | setChromePathInEnv: true, 68 | ...mockInputs, 69 | }; 70 | 71 | it('sets CHROME_PATH environmental variable to Chromium path', async () => { 72 | await NetlifyChromiumPlugin.onPreBuild({ 73 | inputs: mockLocalInputs, 74 | }); 75 | 76 | expect(process.env.CHROME_PATH).toEqual(mockChromiumPath); 77 | }); 78 | 79 | it('logs all messages', async () => { 80 | await NetlifyChromiumPlugin.onPreBuild({ 81 | inputs: mockLocalInputs, 82 | }); 83 | 84 | expect(log.mock.calls).toEqual([ 85 | [`Installing Chromium with settings: ${JSON.stringify(mockLocalInputs)}`], 86 | [`Setting environmental variable CHROME_PATH to ${mockChromiumPath}`], 87 | [`Chromium installation finished with SUCCESS (path: ${mockChromiumPath})`], 88 | ]); 89 | }); 90 | 91 | }); 92 | 93 | describe('if setChromePathInEnv is false', () => { 94 | 95 | const mockLocalInputs = { 96 | setChromePathInEnv: false, 97 | ...mockInputs, 98 | }; 99 | 100 | it('does not set CHROME_PATH environmental variable', async () => { 101 | await NetlifyChromiumPlugin.onPreBuild({ 102 | inputs: mockLocalInputs, 103 | }); 104 | 105 | expect(process.env.CHROME_PATH).toEqual(`${initialChromiumPath}`); 106 | }); 107 | 108 | it('logs all messages', async () => { 109 | await NetlifyChromiumPlugin.onPreBuild({ 110 | inputs: mockLocalInputs, 111 | }); 112 | 113 | expect(log.mock.calls).toEqual([ 114 | [`Installing Chromium with settings: ${JSON.stringify(mockLocalInputs)}`], 115 | [`Chromium installation finished with SUCCESS (path: ${mockChromiumPath})`], 116 | ]); 117 | }); 118 | 119 | }); 120 | 121 | }); 122 | 123 | describe('if Chromium is initially not installed', () => { 124 | 125 | describe('if Chromium is available for download', () => { 126 | 127 | beforeEach(() => { 128 | getChromiumPath 129 | .mockImplementationOnce(() => { throw mockError; }) 130 | .mockImplementationOnce(() => mockChromiumPath); 131 | }); 132 | 133 | it('attempts to install Chromium', async () => { 134 | await NetlifyChromiumPlugin.onPreBuild({ 135 | inputs: mockInputs, 136 | utils: mockUtils, 137 | }); 138 | 139 | expect(getChromiumPath).toBeCalledTimes(2); 140 | expect(installChromium).toBeCalledTimes(1); 141 | expect(installChromium).toBeCalledWith(mockUtils.run.command, mockInputs.packageManager); 142 | }); 143 | 144 | describe('if setChromePathInEnv is true', () => { 145 | 146 | const mockLocalInputs = { 147 | setChromePathInEnv: true, 148 | ...mockInputs, 149 | }; 150 | 151 | it('sets CHROME_PATH environmental variable to Chromium path', async () => { 152 | await NetlifyChromiumPlugin.onPreBuild({ 153 | inputs: mockLocalInputs, 154 | utils: mockUtils, 155 | }); 156 | 157 | expect(process.env.CHROME_PATH).toEqual(mockChromiumPath); 158 | }); 159 | 160 | it('logs all messages', async () => { 161 | await NetlifyChromiumPlugin.onPreBuild({ 162 | inputs: mockLocalInputs, 163 | utils: mockUtils, 164 | }); 165 | 166 | expect(log.mock.calls).toEqual([ 167 | [`Installing Chromium with settings: ${JSON.stringify(mockLocalInputs)}`], 168 | ['Chromium is not available, attempting to download'], 169 | [`Setting environmental variable CHROME_PATH to ${mockChromiumPath}`], 170 | [`Chromium installation finished with SUCCESS (path: ${mockChromiumPath})`], 171 | ]); 172 | }); 173 | 174 | }); 175 | 176 | describe('if setChromePathInEnv is false', () => { 177 | 178 | const mockLocalInputs = { 179 | setChromePathInEnv: false, 180 | ...mockInputs, 181 | }; 182 | 183 | it('does not set CHROME_PATH environmental variable', async () => { 184 | await NetlifyChromiumPlugin.onPreBuild({ 185 | inputs: mockLocalInputs, 186 | utils: mockUtils, 187 | }); 188 | 189 | expect(process.env.CHROME_PATH).toEqual(`${initialChromiumPath}`); 190 | }); 191 | 192 | it('logs all messages', async () => { 193 | await NetlifyChromiumPlugin.onPreBuild({ 194 | inputs: mockLocalInputs, 195 | utils: mockUtils, 196 | }); 197 | 198 | expect(log.mock.calls).toEqual([ 199 | [`Installing Chromium with settings: ${JSON.stringify(mockLocalInputs)}`], 200 | ['Chromium is not available, attempting to download'], 201 | [`Chromium installation finished with SUCCESS (path: ${mockChromiumPath})`], 202 | ]); 203 | }); 204 | 205 | }); 206 | 207 | }); 208 | 209 | describe('if Chromium is not available for download', () => { 210 | 211 | beforeEach(() => { 212 | getChromiumPath.mockImplementation(() => { throw mockError; }); 213 | }); 214 | 215 | it('attempts to install Chromium', async () => { 216 | await NetlifyChromiumPlugin.onPreBuild({ 217 | inputs: mockInputs, 218 | utils: mockUtils, 219 | }); 220 | 221 | expect(getChromiumPath).toBeCalledTimes(2); 222 | expect(installChromium).toBeCalledTimes(1); 223 | expect(installChromium).toBeCalledWith(mockUtils.run.command, mockInputs.packageManager); 224 | }); 225 | 226 | it('does not set CHROME_PATH environmental variable', async () => { 227 | await NetlifyChromiumPlugin.onPreBuild({ 228 | inputs: mockInputs, 229 | utils: mockUtils, 230 | }); 231 | 232 | expect(process.env.CHROME_PATH).toEqual(`${initialChromiumPath}`); 233 | }); 234 | 235 | describe('if failBuildOnError is true', () => { 236 | 237 | const mockLocalInputs = { 238 | failBuildOnError: true, 239 | ...mockInputs, 240 | }; 241 | 242 | it('fails build', async () => { 243 | await NetlifyChromiumPlugin.onPreBuild({ 244 | inputs: mockLocalInputs, 245 | utils: mockUtils, 246 | }); 247 | 248 | expect(mockUtils.build.failPlugin).toBeCalledTimes(0); 249 | expect(mockUtils.build.failBuild).toBeCalledTimes(1); 250 | expect(mockUtils.build.failBuild).toBeCalledWith('Error during Chromium installation', { error: mockError }); 251 | }); 252 | 253 | it('logs all messages', async () => { 254 | await NetlifyChromiumPlugin.onPreBuild({ 255 | inputs: mockLocalInputs, 256 | utils: mockUtils, 257 | }); 258 | 259 | expect(log.mock.calls).toEqual([ 260 | [`Installing Chromium with settings: ${JSON.stringify(mockLocalInputs)}`], 261 | ['Chromium is not available, attempting to download'], 262 | ['Chromium installation finished with FAILURE', mockError], 263 | ]); 264 | }); 265 | 266 | }); 267 | 268 | describe('if failBuildOnError is false', () => { 269 | 270 | const mockLocalInputs = { 271 | failBuildOnError: false, 272 | ...mockInputs, 273 | }; 274 | 275 | it('does not build', async () => { 276 | await NetlifyChromiumPlugin.onPreBuild({ 277 | inputs: mockLocalInputs, 278 | utils: mockUtils, 279 | }); 280 | 281 | expect(mockUtils.build.failBuild).toBeCalledTimes(0); 282 | expect(mockUtils.build.failPlugin).toBeCalledTimes(1); 283 | expect(mockUtils.build.failPlugin).toBeCalledWith('Error during Chromium installation', { error: mockError }); 284 | }); 285 | 286 | it('logs all messages', async () => { 287 | await NetlifyChromiumPlugin.onPreBuild({ 288 | inputs: mockLocalInputs, 289 | utils: mockUtils, 290 | }); 291 | 292 | expect(log.mock.calls).toEqual([ 293 | [`Installing Chromium with settings: ${JSON.stringify(mockLocalInputs)}`], 294 | ['Chromium is not available, attempting to download'], 295 | ['Chromium installation finished with FAILURE', mockError], 296 | ]); 297 | }); 298 | 299 | }); 300 | 301 | }); 302 | 303 | }); 304 | 305 | }); 306 | -------------------------------------------------------------------------------- /src/tests/utils.test.js: -------------------------------------------------------------------------------- 1 | import { 2 | log, 3 | getChromiumPath, 4 | installChromium, 5 | } from '../utils'; 6 | 7 | describe('NetlifyChromiumPlugin utils', () => { 8 | 9 | describe('log', () => { 10 | 11 | it('exists and is exported', () => { 12 | expect(log).toBeDefined(); 13 | expect(typeof log).toEqual('function'); 14 | }); 15 | 16 | it('logs message to console', () => { 17 | const mockMessage = 'MOCK_MESSAGE'; 18 | global.console.log = jest.fn(); 19 | 20 | log(mockMessage); 21 | 22 | expect(global.console.log).toBeCalledTimes(1); 23 | expect(global.console.log).toBeCalledWith(`[NetlifyChromiumPlugin]: ${mockMessage}`); 24 | }) 25 | 26 | }); 27 | 28 | describe('getChromiumPath', () => { 29 | 30 | it('exists and is exported', () => { 31 | expect(getChromiumPath).toBeDefined(); 32 | expect(typeof getChromiumPath).toEqual('function'); 33 | }); 34 | 35 | }); 36 | 37 | describe('installChromium', () => { 38 | 39 | it('exists and is exported', () => { 40 | expect(installChromium).toBeDefined(); 41 | expect(typeof installChromium).toEqual('function'); 42 | }); 43 | 44 | describe('in case of unsupported package manager', () => { 45 | const mockPackageManager = 'MOCK_PACKAGE_MANAGER'; 46 | 47 | it('throws error', async () => { 48 | await expect(installChromium(null, mockPackageManager)).rejects.toThrow( 49 | new Error(`Invalid package manager: ${mockPackageManager} (available package managers: npm, yarn)`), 50 | ); 51 | }); 52 | 53 | }); 54 | 55 | describe('in case of supported package manager', () => { 56 | const mockRunTask = jest.fn(); 57 | 58 | beforeEach(() => { 59 | mockRunTask.mockClear(); 60 | }); 61 | 62 | it('if npm, installs Chromium with npm install', () => { 63 | expect(async () => await installChromium(mockRunTask, 'npm')).not.toThrow(); 64 | expect(mockRunTask).toBeCalledTimes(1); 65 | expect(mockRunTask).toBeCalledWith('npm install chromium'); 66 | }); 67 | 68 | 69 | it('if yarn, installs Chromium with yarn add', () => { 70 | expect(async () => await installChromium(mockRunTask, 'yarn')).not.toThrow(); 71 | expect(mockRunTask).toBeCalledTimes(1); 72 | expect(mockRunTask).toBeCalledWith('yarn add chromium'); 73 | }); 74 | 75 | }); 76 | 77 | }); 78 | 79 | }); -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | const PACKAGE_NAME = 'chromium'; 2 | const PACKAGE_MANAGERS = [ 3 | { 4 | name: 'npm', 5 | installCommand: 'install', 6 | }, 7 | { 8 | name: 'yarn', 9 | installCommand: 'add', 10 | }, 11 | ]; 12 | 13 | export const log = (message) => console.log(`[NetlifyChromiumPlugin]: ${message}`); 14 | 15 | export const getChromiumPath = () => { 16 | try { 17 | delete require.cache[require.resolve(PACKAGE_NAME)]; 18 | } catch(error) {} 19 | 20 | const { path } = require(PACKAGE_NAME); 21 | return path; 22 | }; 23 | 24 | export const installChromium = async (runTask, packageManagerName) => { 25 | const packageManager = PACKAGE_MANAGERS.find((packageManager) => packageManager.name === packageManagerName); 26 | 27 | if (!packageManager) { 28 | throw new Error(`Invalid package manager: ${packageManagerName} (available package managers: ${PACKAGE_MANAGERS.map((packageManager) => packageManager.name).join(', ')})`); 29 | } 30 | 31 | const installCommand = `${packageManager.name} ${packageManager.installCommand} ${PACKAGE_NAME}`; 32 | await runTask(installCommand); 33 | }; 34 | --------------------------------------------------------------------------------