Skip to content

Commit

Permalink
changed: manage browser instances to improve performance of tests and…
Browse files Browse the repository at this point in the history
… using this library as a JS module
  • Loading branch information
MartijnR committed Jul 10, 2023
1 parent 8cbf992 commit 5ce33ec
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 60 deletions.
1 change: 0 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
"jsdoc/check-param-names": 1,
"jsdoc/check-tag-names": 1,
"jsdoc/check-types": 1,
"jsdoc/newline-after-description": ["warn", "always"],
"jsdoc/no-undefined-types": 1,
"jsdoc/require-description": 0,
"jsdoc/require-description-complete-sentence": 0,
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).

##### Changed
- Updated dependencies.
- Improved performance of tests and using this library as a JS module

[2.1.2] - 2023-03-01
--------------------------
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"main": "src/validator.js",
"bin": "./validate",
"scripts": {
"test": "mocha test/spec/*.spec.js --exit --timeout 9000 && npm run style-check",
"test": "mocha test/spec/*.spec.js --exit --timeout 6000 && npm run style-check",
"build-docs": "rimraf docs && ./node_modules/.bin/jsdoc -c jsdoc.config.js",
"prepare": "rollup --config && rollup --config rollup.utils.config.mjs",
"style-fix": "eslint *.js src/**/*.js test/**/*.js --fix",
Expand Down
43 changes: 43 additions & 0 deletions src/headless-browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const puppeteer = require( 'puppeteer' );

/**
* This class approach makes it easy to open multiple browser instances with
* different arguments in case that is ever required.
*/
class BrowserHandler {
constructor() {
const launchBrowser = async() => {
this.browser = false;
this.browser = await puppeteer.launch( {
headless: 'new',
devtools: false
} );
this.browser.on( 'disconnected', launchBrowser );
};

this.exit = ()=>{
this.browser.off( 'disconnected', launchBrowser );
this.browser.close();
};

( async() => {
await launchBrowser();
} )();
}
}

const getBrowser = ( handler ) =>
new Promise( ( resolve ) => {
const browserCheck = setInterval( () => {
if ( handler.browser !== false ) {
clearInterval( browserCheck );
resolve( handler.browser );
}
}, 100 );
} );

const closeBrowser = ( handler ) => {
return handler.exit();
};

module.exports = { BrowserHandler, getBrowser, closeBrowser };
6 changes: 4 additions & 2 deletions src/validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
'use strict';

const { XForm } = require( './xform' );
const { BrowserHandler } = require( './headless-browser' );
/**
* @constant
* @static
Expand All @@ -30,18 +31,19 @@ const { version } = require( '../package' );
*
* @static
* @param {string} xformStr - XForm content.
* @param browserHandler
* @param {ValidationOptions} [options] - Validation options.
* @return {ValidateResult} validation results.
*/
const validate = async( xformStr, options = {} ) => {
const validate = async( xformStr, browserHandler = new BrowserHandler(), options = {} ) => {
const start = Date.now();
let warnings = [];
let errors = [];
let result = {};
let xform;

try {
xform = new XForm( xformStr, options );
xform = new XForm( xformStr, browserHandler, options );
} catch ( e ) {
errors.push( e );
}
Expand Down
17 changes: 9 additions & 8 deletions src/xform.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
global.IntersectionObserver = function(){};
const utils = require( '../build/utils-cjs-bundle' );
const { JSDOM } = require( 'jsdom' );
const puppeteer = require( 'puppeteer' );
const { BrowserHandler, getBrowser } = require( './headless-browser' );
const libxslt = require( 'libxslt' );
const libxmljs = libxslt.libxmljs;
const path = require( 'path' );
const sheets = require( 'enketo-transformer' ).sheets;
const xslModelSheet = libxslt.parse( sheets.xslModel );
const appearanceRules = require( './appearances' );


/**
* @typedef Result
* @property {Array<string>} warnings - List of warnings.
Expand All @@ -24,9 +25,10 @@ class XForm {
* @constructs
*
* @param {string} xformStr - XForm content.
* @param browserHandler
* @param {module:validator~ValidateResult} [options] - Validation options.
*/
constructor( xformStr, options = {} ) {
constructor( xformStr, browserHandler = new BrowserHandler(), options = {} ) {
this.options = options;
if ( !xformStr || !xformStr.trim() ) {
throw 'Empty form.';
Expand All @@ -35,8 +37,9 @@ class XForm {

const dom = this._getDom();
this.doc = dom.window.document;
this.loadBrowserPage = puppeteer.launch( { headless: 'new', devtools: false } )
.then( browser => {

this.loadBrowserPage = getBrowser( browserHandler )
.then( browser =>{
this.browser = browser;

return browser.newPage();
Expand Down Expand Up @@ -167,10 +170,8 @@ class XForm {
}

exit(){
if ( this.browser ){

return this.browser.close();
}
return this.loadBrowserPage
.then( page => page.close() );
}

/**
Expand Down
Loading

0 comments on commit 5ce33ec

Please sign in to comment.