Merged PI
authorMartin Taal <martin.taal@openbravo.com>
Tue, 19 Nov 2019 17:40:39 +0100
changeset 36837 0b8a0558c384
parent 36836 6e96d33a5642 (current diff)
parent 36814 5a1554f3b7a1 (diff)
child 36838 d61d2d53638f
Merged PI
lib/runtime/quartz-1.6.2.jar
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/test/ob-navbar-test.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/test/ob-property-store-test.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/test/ob-ui-test.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/test/ob-utilities-date-test.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/test/ob-utilities-number-test.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/test/ob-utilities-valid-url-test.js
modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/TestComponent.java
modules/org.openbravo.client.kernel/web/org.openbravo.client.kernel/ui-test-suite/index.html
modules/org.openbravo.client.kernel/web/org.openbravo.client.kernel/ui-test-suite/qunit/qunit.css
modules/org.openbravo.client.kernel/web/org.openbravo.client.kernel/ui-test-suite/qunit/qunit.js
modules/org.openbravo.client.myob/web/org.openbravo.client.myob/js/test/ob-myopenbravo-test.js
src-test/src/org/openbravo/test/scheduling/ProcessSchedulingTest.java
src/org/openbravo/scheduling/Trigger_data.xsql
--- a/.eslintignore	Mon Nov 18 16:08:25 2019 +0100
+++ b/.eslintignore	Tue Nov 19 17:40:39 2019 +0100
@@ -1,4 +1,3 @@
-qunit/
 docs/
 LAB*.js
 benchmark/
--- a/.eslintrc.json	Mon Nov 18 16:08:25 2019 +0100
+++ b/.eslintrc.json	Tue Nov 19 17:40:39 2019 +0100
@@ -1,27 +1,35 @@
 {
+  "root": true,
   "env": {
     "browser": true,
-    "es6": true
+    "es6": true,
+    "jest": true
   },
+  "plugins": ["prettier", "jest"],
   "extends": [
     "eslint:recommended",
-    "prettier"
+    "plugin:jest/recommended",
+    "plugin:jest/style",
+    "plugin:prettier/recommended"
   ],
   "parserOptions": {
-    "ecmaVersion": 6
+    "ecmaVersion": 9
   },
   "globals": {
-    "OB": "writeable",
-    "Backbone": "readable",
-    "_": "readable",
-    "isc": "readable",
-    "BigDecimal": "readable"
+    "OB": "writable",
+    "Backbone": "readonly",
+    "_": "readonly",
+    "isc": "readonly",
+    "BigDecimal": "readonly"
   },
   "rules": {
     "eqeqeq": ["warn", "smart"],
-    "no-unused-vars": ["warn", {
-      "args": "none"
-    }],
+    "no-unused-vars": [
+      "warn",
+      {
+        "args": "none"
+      }
+    ],
     "no-console": ["warn"],
     "no-useless-escape": ["warn"]
   }
--- a/.gitignore	Mon Nov 18 16:08:25 2019 +0100
+++ b/.gitignore	Tue Nov 19 17:40:39 2019 +0100
@@ -46,6 +46,7 @@
 sources
 scripts
 node_modules
+test-reports
 
 # ignore all modules 
 # except those ones included in OB3 distribution
--- a/.hgignore	Mon Nov 18 16:08:25 2019 +0100
+++ b/.hgignore	Tue Nov 19 17:40:39 2019 +0100
@@ -48,3 +48,4 @@
 sources
 scripts
 node_modules
+test-reports
--- a/.hgsigs	Mon Nov 18 16:08:25 2019 +0100
+++ b/.hgsigs	Tue Nov 19 17:40:39 2019 +0100
@@ -253,3 +253,4 @@
 3e6de99a50604bf1817e3e509dd1b26a9dddd96a 0 iF0EABECAB0WIQQwlWrRXxlUdnEi7O8Jf+gZ/7aqQwUCXY3hHQAKCRAJf+gZ/7aqQ3WjAJ4ydw4yhZFc757DHRiA0HfyWDMl5wCeLtYUOMAdlCKOOzf5pGGoWJM/7fU=
 141ce2831a2318a095a2db263f1dc041ae31f850 0 iFwEABECAB0WIQQwlWrRXxlUdnEi7O8Jf+gZ/7aqQwUCXVzM7wAKCRAJf+gZ/7aqQwUGAJjl80f+aW3QMjFZsDptNJM/oeYSAJ9Slfrt5/iIZ8XTC0t8rnNbdb9Ihg==
 ba61eb73dbd816a69f6d060cf92ec944420e8fb7 0 iF0EABECAB0WIQQwlWrRXxlUdnEi7O8Jf+gZ/7aqQwUCXY3/bwAKCRAJf+gZ/7aqQ1anAKD2x0q55rTlHOeJge+5FUmbQ4AUvQCcDd/NTdSk9mgwLR1m9x22vviyuo8=
+240f11a1fce7839acf3bbcddf77b0fb2bd19e412 0 iF0EABECAB0WIQQwlWrRXxlUdnEi7O8Jf+gZ/7aqQwUCXcPl8AAKCRAJf+gZ/7aqQ1tlAKClM8vlvhtTPeDUjzdPZjvI9/1EGACgqDQ1HV9CpWVokqZboYfIJJ7e7E0=
--- a/.hgtags	Mon Nov 18 16:08:25 2019 +0100
+++ b/.hgtags	Tue Nov 19 17:40:39 2019 +0100
@@ -264,3 +264,4 @@
 9a99482178d152b245851b965ee71ebb7471f79c 3.0PR19Q2.3
 bda45dd2e1704d61971095da67836a3b2894e73d 3.0PR19Q3
 921035308d3805140861f213b50b10ea056775cc 3.0PR19Q3.1
+fbeebc51d2541bb995b6caddf559ad25dddcbf62 3.0PR19Q3.2
--- a/.prettierignore	Mon Nov 18 16:08:25 2019 +0100
+++ b/.prettierignore	Tue Nov 19 17:40:39 2019 +0100
@@ -1,4 +1,3 @@
-qunit/
 docs/
 LAB*.js
 benchmark/
--- a/legal/Licensing.txt	Mon Nov 18 16:08:25 2019 +0100
+++ b/legal/Licensing.txt	Tue Nov 19 17:40:39 2019 +0100
@@ -105,7 +105,7 @@
 # log4j-web-2.11.1.jar
 # log4j-slf4j-impl-2.11.1.jar
 # log4j-1.2-api-2.11.1.jar
-# quartz-1.6.2.jar
+# quartz-2.3.1.jar
 # servlet-api.jar 
 # tika-core-0.9.jar
 # wstx-asl-3.0.2.jar
@@ -286,11 +286,6 @@
 Modified by John-David Dalton <http://allyoucanleet.com/>
 Available under MIT license <http://mths.be/mit>
 
-# qunit.js
-http://docs.jquery.com/QUnit
-Copyright (c) 2011 John Resig, Jörn Zaefferer
-Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses.
-
 # web/org.openbravo.client.kernel/docs
 Beautiful documentation, dynamically generated from source code in the browser.
 From the code-illuminated project at: http://code.google.com/p/code-illuminated/, under the MPL 1.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lerna.json	Tue Nov 19 17:40:39 2019 +0100
@@ -0,0 +1,5 @@
+{
+  "version": "1.0.0",
+  "npmClient": "npm",
+  "packages": ["modules/*"]
+}
Binary file lib/runtime/quartz-1.6.2.jar has changed
Binary file lib/runtime/quartz-2.3.1.jar has changed
--- a/modules/org.openbravo.advpaymentmngt/web/org.openbravo.advpaymentmngt/js/ob-aprm-addPayment.js	Mon Nov 18 16:08:25 2019 +0100
+++ b/modules/org.openbravo.advpaymentmngt/web/org.openbravo.advpaymentmngt/js/ob-aprm-addPayment.js	Tue Nov 19 17:40:39 2019 +0100
@@ -405,9 +405,19 @@
   } else {
     OB.APRM.AddPayment.updateInvOrderTotal(this.view.theForm, grid);
   }
+  OB.APRM.AddPayment.refreshEditedSelectedRecordsInGrid(grid);
   OB.APRM.AddPayment.tryToUpdateActualExpected(this.view.theForm);
 };
 
+OB.APRM.AddPayment.refreshEditedSelectedRecordsInGrid = function(grid) {
+  var editedSelectedRecords = grid.editedSelectedRecords;
+  if (editedSelectedRecords && editedSelectedRecords.length > 0) {
+    editedSelectedRecords.forEach(function(record) {
+      OB.APRM.AddPayment.doSelectionChanged(record, true, grid.view);
+    });
+  }
+};
+
 OB.APRM.AddPayment.glitemsOnLoadGrid = function(grid) {
   if (!grid.isReady) {
     // If Gl Items Grid contains records when first opened then section is uncollapsed
@@ -955,11 +965,13 @@
       }
     }
     if (bslamount.compareTo(BigDecimal.prototype.ZERO) !== 0) {
-      if (actpayment.compareTo(BigDecimal.prototype.ZERO) === 0) {
-        actpayment = actpayment.add(bslamount.abs());
-        actualPayment.setValue(Number(actpayment));
-      } else if (actpayment.compareTo(bslamount.abs()) < 0) {
-        actpayment = bslamount.abs();
+      var bslAmountConverted = OB.APRM.AddPayment.getConvertedAmount(
+        form,
+        bslamount,
+        false
+      );
+      if (actpayment.compareTo(bslAmountConverted.abs()) <= 0) {
+        actpayment = bslAmountConverted.abs();
         actualPayment.setValue(Number(actpayment));
       }
     }
@@ -971,6 +983,28 @@
   form.redraw();
 };
 
+OB.APRM.AddPayment.getConvertedAmount = function(
+  form,
+  amount,
+  directConversion
+) {
+  var currencyPrecision = form.getItem('StdPrecision').getValue();
+  var exchangeRate = new BigDecimal(
+    String(form.getItem('conversion_rate').getValue() || 1)
+  );
+  if (directConversion) {
+    return amount
+      .multiply(exchangeRate)
+      .setScale(currencyPrecision, BigDecimal.prototype.ROUND_HALF_UP);
+  } else {
+    return amount.divide(
+      exchangeRate,
+      currencyPrecision,
+      BigDecimal.prototype.ROUND_HALF_UP
+    );
+  }
+};
+
 OB.APRM.AddPayment.removeRecordClick = function(rowNum, record) {
   this.Super('removeRecordClick', rowNum, record);
 
@@ -1219,23 +1253,18 @@
   form,
   recalcExchangeRate
 ) {
-  var exchangeRate = form.getItem('conversion_rate').getValue(),
-    actualConverted = form.getItem('converted_amount').getValue(),
-    actualPayment = new BigDecimal(
+  var actualPayment = new BigDecimal(
       String(form.getItem('actual_payment').getValue() || 0)
     ),
     actualConvertedItem = form.getItem('converted_amount'),
     exchangeRateItem = form.getItem('conversion_rate'),
     newConvertedAmount = BigDecimal.prototype.ZERO,
-    newExchangeRate = BigDecimal.prototype.ONE,
-    currencyPrecision = form.getItem('StdPrecision').getValue();
+    newExchangeRate = BigDecimal.prototype.ONE;
 
-  if (!actualConverted && !exchangeRate) {
-    return;
-  }
-
-  exchangeRate = new BigDecimal(String(exchangeRate || 1));
-  actualConverted = new BigDecimal(String(actualConverted || 0));
+  var exchangeRate = new BigDecimal(String(exchangeRateItem.getValue() || 1));
+  var actualConverted = new BigDecimal(
+    String(actualConvertedItem.getValue() || 0)
+  );
   if (!actualConverted || !exchangeRate) {
     return;
   }
@@ -1249,9 +1278,11 @@
       exchangeRateItem.setValue(Number(newExchangeRate.toString()));
     }
   } else if (exchangeRate) {
-    newConvertedAmount = actualPayment
-      .multiply(exchangeRate)
-      .setScale(currencyPrecision, BigDecimal.prototype.ROUND_HALF_UP);
+    newConvertedAmount = OB.APRM.AddPayment.getConvertedAmount(
+      form,
+      actualPayment,
+      true
+    );
     exchangeRateItem.setValue(Number(exchangeRate.toString()));
     actualConvertedItem.setValue(Number(newConvertedAmount.toString()));
   } else {
--- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/ApplicationComponentProvider.java	Mon Nov 18 16:08:25 2019 +0100
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/ApplicationComponentProvider.java	Tue Nov 19 17:40:39 2019 +0100
@@ -502,17 +502,4 @@
     obc.setMaxResults(1);
     return obc.uniqueResult() != null;
   }
-
-  @Override
-  public List<String> getTestResources() {
-    final List<String> testResources = new ArrayList<String>();
-    testResources.add("web/org.openbravo.client.application/js/test/ob-ui-test.js");
-    testResources.add("web/org.openbravo.client.application/js/test/ob-property-store-test.js");
-    testResources.add("web/org.openbravo.client.application/js/test/ob-utilities-date-test.js");
-    testResources.add("web/org.openbravo.client.application/js/test/ob-navbar-test.js");
-    testResources.add("web/org.openbravo.client.application/js/test/ob-utilities-number-test.js");
-    testResources
-        .add("web/org.openbravo.client.application/js/test/ob-utilities-valid-url-test.js");
-    return testResources;
-  }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.application/web-test/ob-utilities-date.test.js	Tue Nov 19 17:40:39 2019 +0100
@@ -0,0 +1,130 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2019 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+require('../web/org.openbravo.client.application/js/utilities/ob-utilities-date');
+
+describe('OB.Utilities.Date.*', () => {
+  describe('OB.Utilities.Date.normalizeDisplayFormat', () => {
+    it.each`
+      format                   | expected
+      ${'DD-MM-YYYY'}          | ${'%d-%m-%Y'}
+      ${'DD-MM-YY'}            | ${'%d-%m-%y'}
+      ${'dd-mm-yyyy'}          | ${'%d-%m-%Y'}
+      ${'dd-mm-yy'}            | ${'%d-%m-%y'}
+      ${'%D-%M-%Y'}            | ${'%d-%m-%Y'}
+      ${'%D-%M-%y'}            | ${'%d-%m-%y'}
+      ${'%d-%m-%Y'}            | ${'%d-%m-%Y'}
+      ${'%d-%m-%y'}            | ${'%d-%m-%y'}
+      ${'%d-%m-%Y hh:mi:ss'}   | ${'%d-%m-%Y %H:%M:%S'}
+      ${'%d-%m-%Y HH:MI:SS'}   | ${'%d-%m-%Y %H:%M:%S'}
+      ${'%d-%m-%Y HH24:mi:ss'} | ${'%d-%m-%Y %H:%M:%S'}
+      ${'%d-%m-%Y HH24:MI:SS'} | ${'%d-%m-%Y %H:%M:%S'}
+      ${'%d-%m-%Y HH:MM:SS'}   | ${'%d-%m-%Y %H:%M:%S'}
+      ${'%d-%m-%Y HH24:MM:SS'} | ${'%d-%m-%Y %H:%M:%S'}
+      ${'%d-%m-%Y %H:%M:%S'}   | ${'%d-%m-%Y %H:%M:%S'}
+      ${'%d-%m-%Y %H.%M.%S'}   | ${'%d-%m-%Y %H.%M.%S'}
+      ${'%d-%m-%Y %H:%M:%S a'} | ${'%d-%m-%Y %H:%M:%S A'}
+      ${'%d-%m-%Y %H.%M.%S a'} | ${'%d-%m-%Y %H.%M.%S A'}
+    `(
+      "Display format '$format' is normalized as '$expected'",
+      ({ format, expected }) => {
+        expect(OB.Utilities.Date.normalizeDisplayFormat(format)).toEqual(
+          expected
+        );
+      }
+    );
+  });
+
+  describe('OB.Utilities.Date.OBToJS', () => {
+    it.each`
+      date                        | format                   | expected
+      ${'31/12/2010'}             | ${'%d/%m/%Y'}            | ${new Date(2010, 11, 31, 0, 0, 0, 0)}
+      ${'31:12:2010'}             | ${'%d:%m:%Y'}            | ${new Date(2010, 11, 31, 0, 0, 0, 0)}
+      ${'31.12.2010'}             | ${'%d.%m.%Y'}            | ${new Date(2010, 11, 31, 0, 0, 0, 0)}
+      ${'31-12-2010'}             | ${'%d-%m-%Y'}            | ${new Date(2010, 11, 31, 0, 0, 0, 0)}
+      ${'12-31-2010'}             | ${'%m-%d-%Y'}            | ${new Date(2010, 11, 31, 0, 0, 0, 0)}
+      ${'2010-31-12'}             | ${'%Y-%d-%m'}            | ${new Date(2010, 11, 31, 0, 0, 0, 0)}
+      ${'2010-12-31'}             | ${'%Y-%m-%d'}            | ${new Date(2010, 11, 31, 0, 0, 0, 0)}
+      ${'01-01-0001'}             | ${'%d-%m-%Y'}            | ${createDateObjectOfFirstDayOfYear1()}
+      ${'31-12-10'}               | ${'%d-%m-%y'}            | ${new Date(2010, 11, 31, 0, 0, 0, 0)}
+      ${'12-31-10'}               | ${'%m-%d-%y'}            | ${new Date(2010, 11, 31, 0, 0, 0, 0)}
+      ${'10-31-12'}               | ${'%y-%d-%m'}            | ${new Date(2010, 11, 31, 0, 0, 0, 0)}
+      ${'10-12-31'}               | ${'%y-%m-%d'}            | ${new Date(2010, 11, 31, 0, 0, 0, 0)}
+      ${'01-01-00'}               | ${'%d-%m-%y'}            | ${new Date(2000, 0, 1, 0, 0, 0, 0)}
+      ${'01-01-01'}               | ${'%d-%m-%y'}            | ${new Date(2001, 0, 1, 0, 0, 0, 0)}
+      ${'01-01-49'}               | ${'%d-%m-%y'}            | ${new Date(2049, 0, 1, 0, 0, 0, 0)}
+      ${'01-01-50'}               | ${'%d-%m-%y'}            | ${new Date(1950, 0, 1, 0, 0, 0, 0)}
+      ${'01-01-99'}               | ${'%d-%m-%y'}            | ${new Date(1999, 0, 1, 0, 0, 0, 0)}
+      ${'31-12-2010'}             | ${'%d-%m-%Y'}            | ${new Date(2010, 11, 31, 0, 0, 0, 0)}
+      ${'31-12-2010 23:59'}       | ${'%d-%m-%Y %H:%M'}      | ${new Date(2010, 11, 31, 23, 59, 0, 0)}
+      ${'31-12-2010 23:59:58'}    | ${'%d-%m-%Y %H:%M:%S'}   | ${new Date(2010, 11, 31, 23, 59, 58, 0)}
+      ${'31-12-2010 12:59:58'}    | ${'%d-%m-%Y %H:%M:%S'}   | ${new Date(2010, 11, 31, 12, 59, 58, 0)}
+      ${'31-12-2010 00:59:58'}    | ${'%d-%m-%Y %H:%M:%S'}   | ${new Date(2010, 11, 31, 0, 59, 58, 0)}
+      ${'31-12-2010 12:59:58 PM'} | ${'%d-%m-%Y %H:%M:%S a'} | ${new Date(2010, 11, 31, 12, 59, 58, 0)}
+      ${'31-12-2010 12:59:58 AM'} | ${'%d-%m-%Y %H:%M:%S a'} | ${new Date(2010, 11, 31, 0, 59, 58, 0)}
+    `(
+      "Date '$date' is converted to Date object with value '$expected' using format '$format'",
+      ({ date, format, expected }) => {
+        expect(OB.Utilities.Date.OBToJS(date, format)).toEqual(expected);
+      }
+    );
+  });
+
+  describe('OB.Utilities.Date.JSToOB', () => {
+    it.each`
+      date                                     | format                   | expected
+      ${'BadDefinedJSDate'}                    | ${'%d-%m-%Y'}            | ${null}
+      ${new Date(2010, 11, 31, 0, 0, 0, 0)}    | ${'%d/%m/%Y'}            | ${'31/12/2010'}
+      ${new Date(2010, 11, 31, 0, 0, 0, 0)}    | ${'%d:%m:%Y'}            | ${'31:12:2010'}
+      ${new Date(2010, 11, 31, 0, 0, 0, 0)}    | ${'%d.%m.%Y'}            | ${'31.12.2010'}
+      ${new Date(2010, 11, 31, 0, 0, 0, 0)}    | ${'%d-%m-%Y'}            | ${'31-12-2010'}
+      ${new Date(2010, 11, 31, 0, 0, 0, 0)}    | ${'%m-%d-%Y'}            | ${'12-31-2010'}
+      ${new Date(2010, 11, 31, 0, 0, 0, 0)}    | ${'%Y-%d-%m'}            | ${'2010-31-12'}
+      ${new Date(2010, 11, 31, 0, 0, 0, 0)}    | ${'%Y-%m-%d'}            | ${'2010-12-31'}
+      ${createDateObjectOfFirstDayOfYear1()}   | ${'%d-%m-%Y'}            | ${'01-01-0001'}
+      ${new Date(2010, 11, 31, 0, 0, 0, 0)}    | ${'%d-%m-%y'}            | ${'31-12-10'}
+      ${new Date(2010, 11, 31, 0, 0, 0, 0)}    | ${'%m-%d-%y'}            | ${'12-31-10'}
+      ${new Date(2010, 11, 31, 0, 0, 0, 0)}    | ${'%y-%d-%m'}            | ${'10-31-12'}
+      ${new Date(2010, 11, 31, 0, 0, 0, 0)}    | ${'%y-%m-%d'}            | ${'10-12-31'}
+      ${new Date(2000, 0, 1, 0, 0, 0, 0)}      | ${'%d-%m-%y'}            | ${'01-01-00'}
+      ${new Date(2001, 0, 1, 0, 0, 0, 0)}      | ${'%d-%m-%y'}            | ${'01-01-01'}
+      ${new Date(2049, 0, 1, 0, 0, 0, 0)}      | ${'%d-%m-%y'}            | ${'01-01-49'}
+      ${new Date(1950, 0, 1, 0, 0, 0, 0)}      | ${'%d-%m-%y'}            | ${'01-01-50'}
+      ${new Date(1999, 0, 1, 0, 0, 0, 0)}      | ${'%d-%m-%y'}            | ${'01-01-99'}
+      ${new Date(1949, 0, 1, 0, 0, 0, 0)}      | ${'%d-%m-%y'}            | ${null}
+      ${new Date(2010, 11, 31, 0, 0, 0, 0)}    | ${'%d-%m-%Y'}            | ${'31-12-2010'}
+      ${new Date(2010, 11, 31, 23, 59, 0, 0)}  | ${'%d-%m-%Y %H:%M'}      | ${'31-12-2010 23:59'}
+      ${new Date(2010, 11, 31, 23, 59, 58, 0)} | ${'%d-%m-%Y %H:%M:%S'}   | ${'31-12-2010 23:59:58'}
+      ${new Date(2010, 11, 31, 12, 59, 58, 0)} | ${'%d-%m-%Y %H:%M:%S'}   | ${'31-12-2010 12:59:58'}
+      ${new Date(2010, 11, 31, 0, 59, 58, 0)}  | ${'%d-%m-%Y %H:%M:%S'}   | ${'31-12-2010 00:59:58'}
+      ${new Date(2010, 11, 31, 12, 59, 58, 0)} | ${'%d-%m-%Y %H:%M:%S a'} | ${'31-12-2010 12:59:58 PM'}
+      ${new Date(2010, 11, 31, 0, 59, 58, 0)}  | ${'%d-%m-%Y %H:%M:%S a'} | ${'31-12-2010 12:59:58 AM'}
+    `(
+      "Date with value '$date' is converted to '$expected' using format '$format'",
+      ({ date, format, expected }) => {
+        expect(OB.Utilities.Date.JSToOB(date, format)).toEqual(expected);
+      }
+    );
+  });
+
+  function createDateObjectOfFirstDayOfYear1() {
+    let date = new Date(1, 0, 1, 0, 0, 0, 0);
+    date.setFullYear('1');
+    return date;
+  }
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.application/web-test/ob-utilities-number.test.js	Tue Nov 19 17:40:39 2019 +0100
@@ -0,0 +1,157 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2019 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+OB = {
+  I18N: {
+    getLabel: jest.fn()
+  }
+};
+require('../web/org.openbravo.client.application/js/utilities/ob-utilities-number');
+require('../../org.openbravo.client.kernel/web/org.openbravo.client.kernel/js/BigDecimal-all-1.0.3');
+
+describe('OB.Utilities.Number.*', () => {
+  const decimalSeparator = '.';
+  const groupSeparator = ',';
+
+  describe('OB.Utilities.Number.ScientificToDecimal', () => {
+    it.each`
+      number              | expected
+      ${'-5E-4'}          | ${'-0.0005'}
+      ${'-5E4'}           | ${'-50000'}
+      ${'5E7'}            | ${'50000000'}
+      ${'-1.056E-5'}      | ${'-0.00001056'}
+      ${'-1.056E5'}       | ${'-105600'}
+      ${'1.056E-5'}       | ${'0.00001056'}
+      ${'1.056E5'}        | ${'105600'}
+      ${'-1.2E-5'}        | ${'-0.000012'}
+      ${'-1.2E5'}         | ${'-120000'}
+      ${'1.2E-5'}         | ${'0.000012'}
+      ${'1.2E5'}          | ${'120000'}
+      ${'-3.566E-4'}      | ${'-0.0003566'}
+      ${'1.020050045E7'}  | ${'10200500.45'}
+      ${'-1.020050045E7'} | ${'-10200500.45'}
+      ${'1.020050000E7'}  | ${'10200500.00'}
+      ${'-1.020050000E7'} | ${'-10200500.00'}
+    `('should convert $number to $expected', ({ number, expected }) => {
+      expect(
+        OB.Utilities.Number.ScientificToDecimal(number, decimalSeparator)
+      ).toEqual(expected);
+    });
+  });
+
+  describe('OB.Utilities.Number.OBMaskedToOBPlain works properly when the exponent of the scientific number ends with 0', () => {
+    it.each`
+      number          | expected
+      ${'1.12E10'}    | ${'11200000000'}
+      ${'1.12E-10'}   | ${'0.000000000112'}
+      ${'-1.0564E10'} | ${'-10564000000'}
+      ${'1.056E-5'}   | ${'0.00001056'}
+    `('should convert $number to $expected', ({ number, expected }) => {
+      expect(
+        OB.Utilities.Number.OBMaskedToOBPlain(
+          number,
+          decimalSeparator,
+          groupSeparator
+        )
+      ).toEqual(expected);
+    });
+  });
+
+  describe('OB.Utilities.Number.ScientificToDecimal works properly for the conversion of the numbers from scientific notation to decimal notation in the case of the upper case E, lower case e and if a sign is added to the exponent', () => {
+    it.each`
+      number          | expected
+      ${'1.12E10'}    | ${'11200000000'}
+      ${'-5E20'}      | ${'-500000000000000000000'}
+      ${'-1.056E10'}  | ${'-10560000000'}
+      ${'1.12E+10'}   | ${'11200000000'}
+      ${'-5E+20'}     | ${'-500000000000000000000'}
+      ${'-1.056E+10'} | ${'-10560000000'}
+      ${'1.12e10'}    | ${'11200000000'}
+      ${'-5e20'}      | ${'-500000000000000000000'}
+      ${'-1.056e10'}  | ${'-10560000000'}
+      ${'1.12e+10'}   | ${'11200000000'}
+      ${'-5e+20'}     | ${'-500000000000000000000'}
+      ${'-1.056e+10'} | ${'-10560000000'}
+    `('should convert $number to $expected', ({ number, expected }) => {
+      expect(
+        OB.Utilities.Number.ScientificToDecimal(number, decimalSeparator)
+      ).toEqual(expected);
+    });
+  });
+
+  describe('OB.Utilities.Number.ScientificToDecimal works properly with numbers with leading zeros', () => {
+    it.each`
+      numberWithZero | number
+      ${'03.4e-2'}   | ${'3.4e-2'}
+      ${'03.4e+2'}   | ${'3.4e+2'}
+      ${'03.4e2'}    | ${'3.4e2'}
+      ${'03.4E-2'}   | ${'3.4E-2'}
+      ${'03.4E+2'}   | ${'3.4E+2'}
+      ${'03.4E2'}    | ${'3.4E2'}
+    `(
+      'should return the same value for $numberWithZero and $number',
+      ({ numberWithZero, number }) => {
+        const decimalFromNumberWithLeadingZero = OB.Utilities.Number.ScientificToDecimal(
+          numberWithZero,
+          decimalSeparator
+        );
+
+        const decimalFromNumberWithNoLeadingZero = OB.Utilities.Number.ScientificToDecimal(
+          number,
+          decimalSeparator
+        );
+
+        expect(decimalFromNumberWithLeadingZero).toEqual(
+          decimalFromNumberWithNoLeadingZero
+        );
+      }
+    );
+  });
+
+  describe('OB.Utilities.Number.roundJSNumber', () => {
+    it.each`
+      number                | decimals | expected
+      ${0.145}              | ${2}     | ${0.15}
+      ${1.145}              | ${2}     | ${1.15}
+      ${10.145}             | ${2}     | ${10.15}
+      ${14.499999999999998} | ${2}     | ${14.5}
+    `(
+      'should round $number with $decimals decimals to $expected',
+      ({ number, decimals, expected }) => {
+        expect(OB.Utilities.Number.roundJSNumber(number, decimals)).toEqual(
+          expected
+        );
+      }
+    );
+  });
+
+  describe('OB.Utilities.Number.roundJSNumber works properly when the parameter is NaN', () => {
+    it.each`
+      number   | decimals | expected
+      ${'a'}   | ${2}     | ${NaN}
+      ${'12a'} | ${2}     | ${NaN}
+    `(
+      "should return $expected when rounding '$number'",
+      ({ number, decimals, expected }) => {
+        expect(OB.Utilities.Number.roundJSNumber(number, decimals)).toEqual(
+          expected
+        );
+      }
+    );
+  });
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.application/web-test/ob-utilities-validUrl.test.js	Tue Nov 19 17:40:39 2019 +0100
@@ -0,0 +1,32 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2019 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+OB = {};
+require('../web/org.openbravo.client.application/js/utilities/ob-utilities');
+
+describe('OB.Utilities.isValidUrl', () => {
+  it('should consider http://localhost as not a valid URL', () => {
+    expect(OB.Utilities.isValidURL('http://localhost')).toBeFalsy();
+  });
+
+  it('should consider http://localhost.localdomain as a valid URL', () => {
+    expect(
+      OB.Utilities.isValidURL('http://localhost.localdomain')
+    ).toBeTruthy();
+  });
+});
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-window.js	Mon Nov 18 16:08:25 2019 +0100
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-window.js	Tue Nov 19 17:40:39 2019 +0100
@@ -11,7 +11,7 @@
  * under the License.
  * The Original Code is Openbravo ERP.
  * The Initial Developer of the Original Code is Openbravo SLU
- * All portions are Copyright (C) 2010-2017 Openbravo SLU
+ * All portions are Copyright (C) 2010-2019 Openbravo SLU
  * All Rights Reserved.
  * Contributor(s):  ______________________________________.
  ************************************************************************
@@ -292,6 +292,9 @@
         ]
       });
       this.addChild(theModalMask);
+      // Always force to show popup over mask so when switching tabs before popup is shown,
+      // it still shows in front of mask. Related to issue #42178
+      thePopup.bringToFront();
     } else {
       this.addChild(thePopup);
     }
@@ -684,7 +687,8 @@
       persDefaultValue,
       views,
       currentView = this.activeView || this.view,
-      length;
+      length,
+      formPersonalizationApplied = false;
 
     // only personalize if there is a professional license
     if (!OB.Utilities.checkProfessionalLicense(null, true)) {
@@ -778,6 +782,7 @@
               this.views[i].viewForm.getDataSource()
             ) {
               this.lastViewApplied = true;
+              formPersonalizationApplied = true;
               OB.Personalization.personalizeForm(
                 personalization.forms[this.views[i].tabId],
                 this.views[i].viewForm
@@ -786,13 +791,16 @@
           }
         }
       }
-    } else {
-      if (this.view.dataLoadDelayedForDefaultSavedView) {
-        // it might happen that the load of the initial grid data was delayed because it had a
-        // default saved view, but then the default saved view is not returned by the WindowSettingsActionHandler.
-        // in that case, detect it and load the grid now
-        this.view.viewGrid.fetchData(this.view.viewGrid.getCriteria());
-      }
+    }
+    if (
+      this.view.dataLoadDelayedForDefaultSavedView &&
+      !defaultView &&
+      !formPersonalizationApplied
+    ) {
+      // it might happen that the load of the initial grid data was delayed because it had a
+      // default saved view, but then the default saved view is not returned by the WindowSettingsActionHandler.
+      // in that case, detect it and load the grid now
+      this.view.viewGrid.fetchData(this.view.viewGrid.getCriteria());
     }
 
     // restore focus as the focusitem may have been hidden now
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/test/ob-navbar-test.js	Mon Nov 18 16:08:25 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- *************************************************************************
- * The contents of this file are subject to the Openbravo  Public  License
- * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
- * Version 1.1  with a permitted attribution clause; you may not  use this
- * file except in compliance with the License. You  may  obtain  a copy of
- * the License at http://www.openbravo.com/legal/license.html
- * Software distributed under the License  is  distributed  on  an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
- * License for the specific  language  governing  rights  and  limitations
- * under the License.
- * The Original Code is Openbravo ERP.
- * The Initial Developer of the Original Code is Openbravo SLU
- * All portions are Copyright (C) 2010-2017 Openbravo SLU
- * All Rights Reserved.
- * Contributor(s):  ______________________________________.
- ************************************************************************
- */
-
-/*global QUnit */
-
-QUnit.module('org.openbravo.client.application.navigationbarcomponents');
-
-QUnit.test('Basic requirements', function() {
-  QUnit.expect(1);
-  QUnit.ok(OB.RecentUtilities, 'recent utilities defined');
-});
-
-QUnit.test('Test user info data read', function(assert) {
-  QUnit.expect(15);
-
-  QUnit.ok(OB.User.userInfo.language, 'Language present');
-  QUnit.ok(OB.User.userInfo.language.value, 'Language value present');
-  QUnit.ok(OB.User.userInfo.language.valueMap, 'Language valueMap present');
-
-  QUnit.ok(OB.User.userInfo.initialValues.role, 'Initial role value set');
-  QUnit.ok(OB.User.userInfo.initialValues.client, 'Initial client value set');
-  QUnit.ok(
-    OB.User.userInfo.initialValues.organization,
-    'Initial organization value set'
-  );
-  QUnit.ok(
-    OB.User.userInfo.initialValues.language,
-    'Initial language value set'
-  );
-
-  QUnit.ok(OB.User.userInfo.role, 'Role set');
-  QUnit.ok(OB.User.userInfo.role.value, 'Role value set');
-  QUnit.ok(OB.User.userInfo.role.valueMap, 'Role valueMap set');
-  QUnit.ok(OB.User.userInfo.role.roles, 'Role info set');
-  QUnit.ok(
-    OB.User.userInfo.role.roles.length > 0,
-    'More than one role present'
-  );
-  QUnit.ok(OB.User.userInfo.role.roles[0].id, 'Role id set');
-  QUnit.ok(
-    OB.User.userInfo.role.roles[0].organizationValueMap,
-    'Role org value map set'
-  );
-  QUnit.ok(
-    OB.User.userInfo.role.roles[0].warehouseOrgMap,
-    'Role wh value map set'
-  );
-});
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/test/ob-property-store-test.js	Mon Nov 18 16:08:25 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- *************************************************************************
- * The contents of this file are subject to the Openbravo  Public  License
- * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
- * Version 1.1  with a permitted attribution clause; you may not  use this
- * file except in compliance with the License. You  may  obtain  a copy of
- * the License at http://www.openbravo.com/legal/license.html
- * Software distributed under the License  is  distributed  on  an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
- * License for the specific  language  governing  rights  and  limitations
- * under the License.
- * The Original Code is Openbravo ERP.
- * The Initial Developer of the Original Code is Openbravo SLU
- * All portions are Copyright (C) 2010-2015 Openbravo SLU
- * All Rights Reserved.
- * Contributor(s):  ______________________________________.
- ************************************************************************
- */
-
-/*global QUnit */
-
-QUnit.module('org.openbravo.client.application');
-
-QUnit.test('Property Store Exists', function() {
-  QUnit.expect(2);
-  QUnit.ok(OB.PropertyStore, 'PropertyStore is present');
-  QUnit.ok(!OB.PropertyStore.get('abc'), 'Test property is not present (okay)');
-});
-
-QUnit.test('Set/Get Property', function() {
-  QUnit.expect(2);
-
-  var propName = 'CCU';
-  var testValue = 'testValue';
-  var propValue = OB.PropertyStore.get(propName);
-  QUnit.ok(propValue, 'CCU is present, value is ' + propValue);
-
-  OB.PropertyStore.set(propName, testValue);
-  propValue = OB.PropertyStore.get(propName);
-  QUnit.equal(propValue, testValue, 'Equal values');
-  // clear the test property
-  // with a short delay to make sure that the previous set does not interfere
-  // on the server
-  isc.Timer.setTimeout(function() {
-    OB.PropertyStore.set(propName, 'Y');
-  }, 1000);
-});
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/test/ob-ui-test.js	Mon Nov 18 16:08:25 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- *************************************************************************
- * The contents of this file are subject to the Openbravo  Public  License
- * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
- * Version 1.1  with a permitted attribution clause; you may not  use this
- * file except in compliance with the License. You  may  obtain  a copy of
- * the License at http://www.openbravo.com/legal/license.html
- * Software distributed under the License  is  distributed  on  an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
- * License for the specific  language  governing  rights  and  limitations
- * under the License.
- * The Original Code is Openbravo ERP.
- * The Initial Developer of the Original Code is Openbravo SLU
- * All portions are Copyright (C) 2010-2015 Openbravo SLU
- * All Rights Reserved.
- * Contributor(s):  ______________________________________.
- ************************************************************************
- */
-
-/*global QUnit */
-
-QUnit.module('org.openbravo.client.application');
-
-QUnit.test('Basic requirements', function() {
-  QUnit.expect(2);
-  QUnit.ok(isc, 'isc object is present');
-  QUnit.ok(document.getElementById, 'getElementById');
-});
-
-QUnit.test('Create Canvas', function() {
-  var canvasID = 'myCanvas',
-    canvas,
-    createCanvas;
-
-  QUnit.expect(3);
-
-  createCanvas = function(isc) {
-    var c = isc.Canvas.newInstance({
-      ID: canvasID,
-      width: '100%',
-      height: '100%'
-    });
-    return c;
-  };
-
-  canvas = createCanvas(isc);
-  canvas.setBackgroundColor('blue');
-
-  QUnit.ok(typeof canvas !== 'undefined', 'Canvas created');
-
-  QUnit.ok(
-    (function(c) {
-      return c.height !== 0 && c.width !== 0;
-    })(canvas),
-    'Canvas height and width are not zero'
-  );
-
-  QUnit.ok(isc.Log.getStackTrace() !== undefined, 'getStackTrace()');
-});
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/test/ob-utilities-date-test.js	Mon Nov 18 16:08:25 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,308 +0,0 @@
-/*
- *************************************************************************
- * The contents of this file are subject to the Openbravo  Public  License
- * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
- * Version 1.1  with a permitted attribution clause; you may not  use this
- * file except in compliance with the License. You  may  obtain  a copy of
- * the License at http://www.openbravo.com/legal/license.html
- * Software distributed under the License  is  distributed  on  an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
- * License for the specific  language  governing  rights  and  limitations
- * under the License.
- * The Original Code is Openbravo ERP.
- * The Initial Developer of the Original Code is Openbravo SLU
- * All portions are Copyright (C) 2010-2015 Openbravo SLU
- * All Rights Reserved.
- * Contributor(s):  ______________________________________.
- ************************************************************************
- */
-
-/*global QUnit */
-
-QUnit.module('org.openbravo.client.application');
-
-QUnit.test('OB.Utilities.Date.* functions', function() {
-  QUnit.expect(4);
-
-  var outputText = '';
-
-  QUnit.ok(
-    (function() {
-      var expectedCenturyReference = 50;
-      var successText = 'OB.Utilities.Date.centuryReference has a valid value';
-      var failureText = 'OB.Utilities.Date.centuryReference ';
-      var success = true;
-
-      if (OB.Utilities.Date.centuryReference !== expectedCenturyReference) {
-        success = false;
-      }
-
-      if (success) {
-        outputText = successText;
-      } else {
-        failureText =
-          failureText +
-          ' has a wrong value: ' +
-          OB.Utilities.Date.centuryReference +
-          ' (expected: ' +
-          expectedCenturyReference +
-          '). This could make the following tests fail.';
-        outputText = failureText;
-      }
-      return success;
-    })(),
-    outputText
-  );
-
-  QUnit.ok(
-    (function() {
-      var i;
-      var successText =
-        'OB.Utilities.Date.normalizeDisplayFormat works properly';
-      var failureText =
-        'OB.Utilities.Date.normalizeDisplayFormat failed while eval';
-      var success = true;
-      var normalizedDisplayFormat;
-      var list = [
-        ['DD-MM-YYYY', '%d-%m-%Y'],
-        ['DD-MM-YY', '%d-%m-%y'],
-        ['dd-mm-yyyy', '%d-%m-%Y'],
-        ['dd-mm-yy', '%d-%m-%y'],
-        ['%D-%M-%Y', '%d-%m-%Y'],
-        ['%D-%M-%y', '%d-%m-%y'],
-        ['%d-%m-%Y', '%d-%m-%Y'],
-        ['%d-%m-%y', '%d-%m-%y'],
-        ['%d-%m-%Y hh:mi:ss', '%d-%m-%Y %H:%M:%S'],
-        ['%d-%m-%Y HH:MI:SS', '%d-%m-%Y %H:%M:%S'],
-        ['%d-%m-%Y HH24:mi:ss', '%d-%m-%Y %H:%M:%S'],
-        ['%d-%m-%Y HH24:MI:SS', '%d-%m-%Y %H:%M:%S'],
-        ['%d-%m-%Y HH:MM:SS', '%d-%m-%Y %H:%M:%S'],
-        ['%d-%m-%Y HH24:MM:SS', '%d-%m-%Y %H:%M:%S'],
-        ['%d-%m-%Y %H:%M:%S', '%d-%m-%Y %H:%M:%S'],
-        ['%d-%m-%Y %H.%M.%S', '%d-%m-%Y %H.%M.%S'],
-        ['%d-%m-%Y %H:%M:%S a', '%d-%m-%Y %H:%M:%S A'],
-        ['%d-%m-%Y %H.%M.%S a', '%d-%m-%Y %H.%M.%S A']
-      ];
-      for (i = 0; i < list.length; i++) {
-        normalizedDisplayFormat = OB.Utilities.Date.normalizeDisplayFormat(
-          list[i][0]
-        );
-        if (normalizedDisplayFormat !== list[i][1]) {
-          success = false;
-          failureText =
-            failureText +
-            " normalizeDisplayFormat('" +
-            list[i][0] +
-            "') === '" +
-            list[i][1] +
-            "' (returned: " +
-            normalizedDisplayFormat +
-            ') &';
-        }
-      }
-      if (success) {
-        outputText = successText;
-      } else {
-        failureText = failureText.substring(0, failureText.length - 2);
-        outputText = failureText;
-      }
-      return success;
-    })(),
-    outputText
-  );
-
-  QUnit.ok(
-    (function() {
-      var i;
-      var successText = 'OB.Utilities.Date.OBToJS works properly';
-      var failureText = 'OB.Utilities.Date.OBToJS failed while eval';
-      var success = true;
-      var OBToJS;
-      var list = [
-        ['BadDefinedOBDate', '%d-%m-%Y', 'null'],
-        ['31/12/2010', '%d/%m/%Y', new Date(2010, 11, 31, 0, 0, 0, 0)],
-        ['31:12:2010', '%d:%m:%Y', new Date(2010, 11, 31, 0, 0, 0, 0)],
-        ['31.12.2010', '%d.%m.%Y', new Date(2010, 11, 31, 0, 0, 0, 0)],
-        ['31-12-2010', '%d-%m-%Y', new Date(2010, 11, 31, 0, 0, 0, 0)],
-        ['12-31-2010', '%m-%d-%Y', new Date(2010, 11, 31, 0, 0, 0, 0)],
-        ['2010-31-12', '%Y-%d-%m', new Date(2010, 11, 31, 0, 0, 0, 0)],
-        ['2010-12-31', '%Y-%m-%d', new Date(2010, 11, 31, 0, 0, 0, 0)],
-        [
-          '01-01-0001',
-          '%d-%m-%Y',
-          (function() {
-            var date = new Date(1, 0, 1, 0, 0, 0, 0);
-            date.setFullYear('1');
-            return date;
-          })()
-        ],
-        ['31-12-10', '%d-%m-%y', new Date(2010, 11, 31, 0, 0, 0, 0)],
-        ['12-31-10', '%m-%d-%y', new Date(2010, 11, 31, 0, 0, 0, 0)],
-        ['10-31-12', '%y-%d-%m', new Date(2010, 11, 31, 0, 0, 0, 0)],
-        ['10-12-31', '%y-%m-%d', new Date(2010, 11, 31, 0, 0, 0, 0)],
-        ['01-01-00', '%d-%m-%y', new Date(2000, 0, 1, 0, 0, 0, 0)],
-        ['01-01-01', '%d-%m-%y', new Date(2001, 0, 1, 0, 0, 0, 0)],
-        ['01-01-49', '%d-%m-%y', new Date(2049, 0, 1, 0, 0, 0, 0)],
-        ['01-01-50', '%d-%m-%y', new Date(1950, 0, 1, 0, 0, 0, 0)],
-        ['01-01-99', '%d-%m-%y', new Date(1999, 0, 1, 0, 0, 0, 0)],
-        ['31-12-2010', '%d-%m-%Y', new Date(2010, 11, 31, 0, 0, 0, 0)],
-        [
-          '31-12-2010 23:59',
-          '%d-%m-%Y %H:%M',
-          new Date(2010, 11, 31, 23, 59, 0, 0)
-        ],
-        [
-          '31-12-2010 23:59:58',
-          '%d-%m-%Y %H:%M:%S',
-          new Date(2010, 11, 31, 23, 59, 58, 0)
-        ],
-        [
-          '31-12-2010 12:59:58',
-          '%d-%m-%Y %H:%M:%S',
-          new Date(2010, 11, 31, 12, 59, 58, 0)
-        ],
-        [
-          '31-12-2010 00:59:58',
-          '%d-%m-%Y %H:%M:%S',
-          new Date(2010, 11, 31, 0, 59, 58, 0)
-        ],
-        [
-          '31-12-2010 12:59:58 PM',
-          '%d-%m-%Y %H:%M:%S a',
-          new Date(2010, 11, 31, 12, 59, 58, 0)
-        ],
-        [
-          '31-12-2010 12:59:58 AM',
-          '%d-%m-%Y %H:%M:%S a',
-          new Date(2010, 11, 31, 0, 59, 58, 0)
-        ]
-      ];
-      for (i = 0; i < list.length; i++) {
-        OBToJS = OB.Utilities.Date.OBToJS(list[i][0], list[i][1]);
-        if (OBToJS === null) {
-          OBToJS = 'null';
-        }
-        if (OBToJS.toString() !== list[i][2].toString()) {
-          success = false;
-          failureText =
-            failureText +
-            " OBToJS('" +
-            list[i][0] +
-            "', '" +
-            list[i][1] +
-            "') === '" +
-            list[i][2].toString() +
-            "' (returned: " +
-            OBToJS +
-            ') &';
-        }
-      }
-      if (success) {
-        outputText = successText;
-      } else {
-        failureText = failureText.substring(0, failureText.length - 2);
-        outputText = failureText;
-      }
-      return success;
-    })(),
-    outputText
-  );
-
-  QUnit.ok(
-    (function() {
-      var i;
-      var successText = 'OB.Utilities.Date.JSToOB works properly';
-      var failureText = 'OB.Utilities.Date.JSToOB failed while eval';
-      var success = true;
-      var JSToOB;
-      var list = [
-        ['BadDefinedJSDate', '%d-%m-%Y', 'null'],
-        [new Date(2010, 11, 31, 0, 0, 0, 0), '%d/%m/%Y', '31/12/2010'],
-        [new Date(2010, 11, 31, 0, 0, 0, 0), '%d:%m:%Y', '31:12:2010'],
-        [new Date(2010, 11, 31, 0, 0, 0, 0), '%d.%m.%Y', '31.12.2010'],
-        [new Date(2010, 11, 31, 0, 0, 0, 0), '%d-%m-%Y', '31-12-2010'],
-        [new Date(2010, 11, 31, 0, 0, 0, 0), '%m-%d-%Y', '12-31-2010'],
-        [new Date(2010, 11, 31, 0, 0, 0, 0), '%Y-%d-%m', '2010-31-12'],
-        [new Date(2010, 11, 31, 0, 0, 0, 0), '%Y-%m-%d', '2010-12-31'],
-        [
-          (function() {
-            var date = new Date(1, 0, 1, 0, 0, 0, 0);
-            date.setFullYear('1');
-            return date;
-          })(),
-          '%d-%m-%Y',
-          '01-01-0001'
-        ],
-        [new Date(2010, 11, 31, 0, 0, 0, 0), '%d-%m-%y', '31-12-10'],
-        [new Date(2010, 11, 31, 0, 0, 0, 0), '%m-%d-%y', '12-31-10'],
-        [new Date(2010, 11, 31, 0, 0, 0, 0), '%y-%d-%m', '10-31-12'],
-        [new Date(2010, 11, 31, 0, 0, 0, 0), '%y-%m-%d', '10-12-31'],
-        [new Date(2000, 0, 1, 0, 0, 0, 0), '%d-%m-%y', '01-01-00'],
-        [new Date(2001, 0, 1, 0, 0, 0, 0), '%d-%m-%y', '01-01-01'],
-        [new Date(2049, 0, 1, 0, 0, 0, 0), '%d-%m-%y', '01-01-49'],
-        [new Date(1950, 0, 1, 0, 0, 0, 0), '%d-%m-%y', '01-01-50'],
-        [new Date(1999, 0, 1, 0, 0, 0, 0), '%d-%m-%y', '01-01-99'],
-        [new Date(1949, 0, 1, 0, 0, 0, 0), '%d-%m-%y', 'null'],
-        [new Date(2010, 11, 31, 0, 0, 0, 0), '%d-%m-%Y', '31-12-2010'],
-        [
-          new Date(2010, 11, 31, 23, 59, 0, 0),
-          '%d-%m-%Y %H:%M',
-          '31-12-2010 23:59'
-        ],
-        [
-          new Date(2010, 11, 31, 23, 59, 58, 0),
-          '%d-%m-%Y %H:%M:%S',
-          '31-12-2010 23:59:58'
-        ],
-        [
-          new Date(2010, 11, 31, 12, 59, 58, 0),
-          '%d-%m-%Y %H:%M:%S',
-          '31-12-2010 12:59:58'
-        ],
-        [
-          new Date(2010, 11, 31, 0, 59, 58, 0),
-          '%d-%m-%Y %H:%M:%S',
-          '31-12-2010 00:59:58'
-        ],
-        [
-          new Date(2010, 11, 31, 12, 59, 58, 0),
-          '%d-%m-%Y %H:%M:%S a',
-          '31-12-2010 12:59:58 PM'
-        ],
-        [
-          new Date(2010, 11, 31, 0, 59, 58, 0),
-          '%d-%m-%Y %H:%M:%S a',
-          '31-12-2010 12:59:58 AM'
-        ]
-      ];
-      for (i = 0; i < list.length; i++) {
-        JSToOB = OB.Utilities.Date.JSToOB(list[i][0], list[i][1]);
-        if (JSToOB === null) {
-          JSToOB = 'null';
-        }
-        if (JSToOB.toString() !== list[i][2].toString()) {
-          success = false;
-          failureText =
-            failureText +
-            " JSToOB('" +
-            list[i][0] +
-            "', '" +
-            list[i][1] +
-            "') === '" +
-            list[i][2].toString() +
-            "' (returned: " +
-            JSToOB +
-            ') &';
-        }
-      }
-      if (success) {
-        outputText = successText;
-      } else {
-        failureText = failureText.substring(0, failureText.length - 2);
-        outputText = failureText;
-      }
-      return success;
-    })(),
-    outputText
-  );
-});
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/test/ob-utilities-number-test.js	Mon Nov 18 16:08:25 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,361 +0,0 @@
-/*
- *************************************************************************
- * The contents of this file are subject to the Openbravo  Public  License
- * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
- * Version 1.1  with a permitted attribution clause; you may not  use this
- * file except in compliance with the License. You  may  obtain  a copy of
- * the License at http://www.openbravo.com/legal/license.html
- * Software distributed under the License  is  distributed  on  an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
- * License for the specific  language  governing  rights  and  limitations
- * under the License.
- * The Original Code is Openbravo ERP.
- * The Initial Developer of the Original Code is Openbravo SLU
- * All portions are Copyright (C) 2015 Openbravo SLU
- * All Rights Reserved.
- * Contributor(s):  ______________________________________.
- ************************************************************************
- */
-
-/*global QUnit */
-
-QUnit.module('org.openbravo.client.application1');
-
-QUnit.test(
-  'OB.Utilities.Number. ScientificToDecimal, OBMaskedToOBPlain and roundJSNumber functions',
-  function() {
-    QUnit.expect(7);
-
-    var outputText = '';
-    var decSeparator = '.';
-    var groupSeparator = ',';
-
-    QUnit.ok(
-      (function() {
-        var i;
-        var successText =
-          'OB.Utilities.Number.ScientificToDecimal works properly';
-        var failureText =
-          'OB.Utilities.Number.ScientificToDecimal failed while eval';
-        var success = true;
-        var normalizedDisplayFormat;
-        var list = [
-          ['-5E-4', '-0.0005'],
-          ['-5E4', '-50000'],
-          ['5E7', '50000000'],
-          ['-1.056E-5', '-0.00001056'],
-          ['-1.056E5', '-105600'],
-          ['1.056E-5', '0.00001056'],
-          ['1.056E5', '105600'],
-          ['-1.2E-5', '-0.000012'],
-          ['-1.2E5', '-120000'],
-          ['1.2E-5', '0.000012'],
-          ['1.2E5', '120000'],
-          ['-3.566E-4', '-0.0003566']
-        ];
-        for (i = 0; i < list.length; i++) {
-          normalizedDisplayFormat = OB.Utilities.Number.ScientificToDecimal(
-            list[i][0],
-            decSeparator
-          );
-          if (normalizedDisplayFormat !== list[i][1]) {
-            success = false;
-            failureText =
-              failureText +
-              " normalizeDisplayFormat('" +
-              list[i][0] +
-              "') === '" +
-              list[i][1] +
-              "' (returned: " +
-              normalizedDisplayFormat +
-              ') &';
-          }
-        }
-        if (success) {
-          outputText = successText;
-        } else {
-          failureText = failureText.substring(0, failureText.length - 2);
-          outputText = failureText;
-        }
-        return success;
-      })(),
-      outputText
-    );
-
-    QUnit.ok(
-      (function() {
-        var i;
-        var successText =
-          'OB.Utilities.Number.OBMaskedToOBPlain works properly when the exponent of the scientific number ends with 0';
-        var failureText =
-          'OB.Utilities.Number.OBMaskedToOBPlain failed while eval';
-        var success = true;
-        var normalizedDisplayFormat;
-        var list = [
-          ['1.12E10', '11200000000'],
-          ['1.12E-10', '0.000000000112'],
-          ['-1.0564E10', '-10564000000'],
-          ['1.056E-5', '0.00001056']
-        ];
-        for (i = 0; i < list.length; i++) {
-          normalizedDisplayFormat = OB.Utilities.Number.OBMaskedToOBPlain(
-            list[i][0],
-            decSeparator,
-            groupSeparator
-          );
-          if (normalizedDisplayFormat !== list[i][1]) {
-            success = false;
-            failureText =
-              failureText +
-              " normalizeDisplayFormat('" +
-              list[i][0] +
-              "') === '" +
-              list[i][1] +
-              "' (returned: " +
-              normalizedDisplayFormat +
-              ') &';
-          }
-        }
-        if (success) {
-          outputText = successText;
-        } else {
-          failureText = failureText.substring(0, failureText.length - 2);
-          outputText = failureText;
-        }
-        return success;
-      })(),
-      outputText
-    );
-
-    QUnit.ok(
-      (function() {
-        var i;
-        var successText =
-          'OB.Utilities.Number.ScientificToDecimal works properly for the conversion of the numbers from scientific notation to decimal notation in the case of the upper case E, lower case e and if a sign is added to the exponent';
-        var failureText =
-          'OB.Utilities.Number.ScientificToDecimal failed while eval';
-        var success = true;
-        var normalizedDisplayFormat;
-        var list = [
-          ['1.12E10', '11200000000'],
-          ['-5E20', '-500000000000000000000'],
-          ['-1.056E10', '-10560000000'],
-          ['1.12E+10', '11200000000'],
-          ['-5E+20', '-500000000000000000000'],
-          ['-1.056E+10', '-10560000000'],
-          ['1.12e10', '11200000000'],
-          ['-5e20', '-500000000000000000000'],
-          ['-1.056e10', '-10560000000'],
-          ['1.12e+10', '11200000000'],
-          ['-5e+20', '-500000000000000000000'],
-          ['-1.056e+10', '-10560000000']
-        ];
-        for (i = 0; i < list.length; i++) {
-          normalizedDisplayFormat = OB.Utilities.Number.ScientificToDecimal(
-            list[i][0],
-            decSeparator
-          );
-          if (normalizedDisplayFormat !== list[i][1]) {
-            success = false;
-            failureText =
-              failureText +
-              " normalizeDisplayFormat('" +
-              list[i][0] +
-              "') === '" +
-              list[i][1] +
-              "' (returned: " +
-              normalizedDisplayFormat +
-              ') &';
-          }
-        }
-        if (success) {
-          outputText = successText;
-        } else {
-          failureText = failureText.substring(0, failureText.length - 2);
-          outputText = failureText;
-        }
-        return success;
-      })(),
-      outputText
-    );
-
-    QUnit.ok(
-      (function() {
-        var i;
-        var successText =
-          'OB.Utilities.Number.ScientificToDecimal works properly with numbers with leading zeros';
-        var failureText =
-          'OB.Utilities.Number.ScientificToDecimal does not work properly with numbers with leading zeros';
-        var success = true;
-        var normalizedDisplayFormat0;
-        var normalizedDisplayFormat1;
-        var list = [
-          ['03.4e-2', '3.4e-2'],
-          ['03.4e+2', '3.4e+2'],
-          ['03.4e2', '3.4e2'],
-          ['03.4E-2', '3.4E-2'],
-          ['03.4E+2', '3.4E+2'],
-          ['03.4E2', '3.4E2']
-        ];
-        for (i = 0; i < list.length; i++) {
-          normalizedDisplayFormat0 = OB.Utilities.Number.ScientificToDecimal(
-            list[i][0],
-            decSeparator
-          );
-          normalizedDisplayFormat1 = OB.Utilities.Number.ScientificToDecimal(
-            list[i][1],
-            decSeparator
-          );
-          if (normalizedDisplayFormat0 !== normalizedDisplayFormat1) {
-            success = false;
-            failureText =
-              failureText +
-              " normalizeDisplayFormat('" +
-              list[i][0] +
-              "') === '" +
-              normalizedDisplayFormat1 +
-              "' (returned: " +
-              normalizedDisplayFormat0 +
-              ') &';
-          }
-        }
-        if (success) {
-          outputText = successText;
-        } else {
-          failureText = failureText.substring(0, failureText.length - 2);
-          outputText = failureText;
-        }
-        return success;
-      })(),
-      outputText
-    );
-
-    QUnit.ok(
-      (function() {
-        var i;
-        var successText =
-          'OB.Utilities.Number.ScientificToDecimal works properly';
-        var failureText =
-          'OB.Utilities.Number.ScientificToDecimal failed while eval';
-        var success = true;
-        var normalizedDisplayFormat;
-        var list = [
-          ['1.020050045E7', '10200500.45'],
-          ['-1.020050045E7', '-10200500.45'],
-          ['1.020050000E7', '10200500.00'],
-          ['-1.020050000E7', '-10200500.00']
-        ];
-        for (i = 0; i < list.length; i++) {
-          normalizedDisplayFormat = OB.Utilities.Number.ScientificToDecimal(
-            list[i][0],
-            decSeparator
-          );
-          if (normalizedDisplayFormat !== list[i][1]) {
-            success = false;
-            failureText =
-              failureText +
-              " normalizeDisplayFormat('" +
-              list[i][0] +
-              "') === '" +
-              list[i][1] +
-              "' (returned: " +
-              normalizedDisplayFormat +
-              ') &';
-          }
-        }
-        if (success) {
-          outputText = successText;
-        } else {
-          failureText = failureText.substring(0, failureText.length - 2);
-          outputText = failureText;
-        }
-        return success;
-      })(),
-      outputText
-    );
-
-    QUnit.ok(
-      (function() {
-        var i;
-        var successText = 'OB.Utilities.Number.roundJSNumber works properly';
-        var failureText = 'OB.Utilities.Number.roundJSNumber failed while eval';
-        var success = true;
-        var normalizedDisplayFormat;
-        var list1 = [
-          [0.145, 2],
-          [1.145, 2],
-          [10.145, 2],
-          [14.499999999999998, 2]
-        ];
-        var list2 = [[0.15], [1.15], [10.15], [14.5]];
-        for (i = 0; i < list1.length; i++) {
-          normalizedDisplayFormat = OB.Utilities.Number.roundJSNumber(
-            list1[i][0],
-            list1[i][1]
-          );
-          if (normalizedDisplayFormat !== list2[i][0]) {
-            success = false;
-            failureText =
-              failureText +
-              " normalizeDisplayFormat('" +
-              'number ' +
-              list1[i][0] +
-              ' with ' +
-              list1[i][1] +
-              'decimals' +
-              "') === '" +
-              list2[i][0] +
-              "' (returned: " +
-              normalizedDisplayFormat +
-              ') &';
-          }
-        }
-        if (success) {
-          outputText = successText;
-        } else {
-          failureText = failureText.substring(0, failureText.length - 2);
-          outputText = failureText;
-        }
-        return success;
-      })(),
-      outputText
-    );
-
-    QUnit.ok(
-      (function() {
-        var i;
-        var successText =
-          'OB.Utilities.Number.roundJSNumber works properly when the parameter is NaN';
-        var failureText = 'OB.Utilities.Number.roundJSNumber failed while eval';
-        var success = true;
-        var normalizedDisplayFormat;
-        var list = [['a', 2], ['12a', 2]];
-        for (i = 0; i < list.length; i++) {
-          normalizedDisplayFormat = OB.Utilities.Number.roundJSNumber(
-            list[i][0],
-            list[i][1]
-          );
-          if (!isNaN(normalizedDisplayFormat)) {
-            success = false;
-            failureText =
-              failureText +
-              " normalizeDisplayFormat('" +
-              list[i][0] +
-              "') === '" +
-              "' (returned: " +
-              normalizedDisplayFormat +
-              ') &';
-          }
-        }
-        if (success) {
-          outputText = successText;
-        } else {
-          failureText = failureText.substring(0, failureText.length - 2);
-          outputText = failureText;
-        }
-        return success;
-      })(),
-      outputText
-    );
-  }
-);
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/test/ob-utilities-valid-url-test.js	Mon Nov 18 16:08:25 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- *************************************************************************
- * The contents of this file are subject to the Openbravo  Public  License
- * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
- * Version 1.1  with a permitted attribution clause; you may not  use this
- * file except in compliance with the License. You  may  obtain  a copy of
- * the License at http://www.openbravo.com/legal/license.html
- * Software distributed under the License  is  distributed  on  an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
- * License for the specific  language  governing  rights  and  limitations
- * under the License.
- * The Original Code is Openbravo ERP.
- * The Initial Developer of the Original Code is Openbravo SLU
- * All portions are Copyright (C) 2019 Openbravo SLU
- * All Rights Reserved.
- * Contributor(s):  ______________________________________.
- ************************************************************************
- */
-
-/*global QUnit */
-
-QUnit.module('org.openbravo.client.application');
-
-QUnit.test('OB.Utilities.isValidUrl', function() {
-  QUnit.expect(2);
-
-  QUnit.notOk(
-    OB.Utilities.isValidURL('http://localhost'),
-    'http://localhost is not a valid URL'
-  );
-  QUnit.ok(
-    OB.Utilities.isValidURL('http://localhost.localdomain'),
-    'http://localhost.localdomain is a valid URL'
-  );
-});
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-utilities-date.js	Mon Nov 18 16:08:25 2019 +0100
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-utilities-date.js	Tue Nov 19 17:40:39 2019 +0100
@@ -27,9 +27,7 @@
 // For a two-digit year display format, it establishes where is the frontier
 // between the 20th and the 21st century
 // The range is taken between 1900+centuryReference and 2100-centuryReference-1
-OB.Utilities.Date.centuryReference = 50; // Notice that change this value
-// implies that also the QUnit test
-// case should be changed
+OB.Utilities.Date.centuryReference = 50;
 // ** {{{ OB.Utilities.Date.normalizeDisplayFormat }}} **
 // Repairs the displayFormat definition (passed in as a parameter) to a value
 // expected by the rest of the system. For example mm is replaced by MM,
--- a/modules/org.openbravo.client.application/web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.application/ob-form-styles.css	Mon Nov 18 16:08:25 2019 +0100
+++ b/modules/org.openbravo.client.application/web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.application/ob-form-styles.css	Tue Nov 19 17:40:39 2019 +0100
@@ -11,7 +11,7 @@
  * under the License.
  * The Original Code is Openbravo ERP.
  * The Initial Developer of the Original Code is Openbravo SLU
- * All portions are Copyright (C) 2010-2016 Openbravo SLU
+ * All portions are Copyright (C) 2010-2019 Openbravo SLU
  * All Rights Reserved.
  * Contributor(s):  ______________________________________.
  ************************************************************************
@@ -645,7 +645,11 @@
 .OBDateChooserWeekendButtonDown,
 .OBDateChooserWeekendButtonSelected,
 .OBDateChooserWeekendButtonSelectedOver,
-.OBDateChooserWeekendButtonSelectedDown,
+.OBDateChooserWeekendButtonSelectedDown {
+  color: #4C4C4C;
+  font-weight: bold;
+}
+
 .OBDateChooserNavButton,
 .OBDateChooserNavButtonOver,
 .OBDateChooserNavButtonDown,
@@ -655,7 +659,6 @@
 .OBDateChooserNavButtonSelected,
 .OBDateChooserNavButtonSelectedOver,
 .OBDateChooserNavButtonSelectedDown {
-  font-weight: bold;
   color: #4C4C4C;
 }
 
--- a/modules/org.openbravo.client.htmlwidget/src/org/openbravo/client/htmlwidget/HTMLWidgetComponentProvider.java	Mon Nov 18 16:08:25 2019 +0100
+++ b/modules/org.openbravo.client.htmlwidget/src/org/openbravo/client/htmlwidget/HTMLWidgetComponentProvider.java	Tue Nov 19 17:40:39 2019 +0100
@@ -49,10 +49,4 @@
         createStaticResource("web/org.openbravo.client.htmlwidget/js/ob-html-widget.js", false));
     return globalResources;
   }
-
-  @Override
-  public List<String> getTestResources() {
-    final List<String> testResources = new ArrayList<String>();
-    return testResources;
-  }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.kernel/eslint-airbnb/copy-config	Tue Nov 19 17:40:39 2019 +0100
@@ -0,0 +1,27 @@
+#!/bin/bash
+# *************************************************************************
+# * The contents of this file are subject to the Openbravo  Public  License
+# * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+# * Version 1.1  with a permitted attribution clause; you may not  use this
+# * file except in compliance with the License. You  may  obtain  a copy of
+# * the License at http://www.openbravo.com/legal/license.html
+# * Software distributed under the License  is  distributed  on  an "AS IS"
+# * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+# * License for the specific  language  governing  rights  and  limitations
+# * under the License.
+# * The Original Code is Openbravo ERP.
+# * The Initial Developer of the Original Code is Openbravo SLU
+# * All portions are Copyright (C) 2019 Openbravo SLU
+# * All Rights Reserved.
+# * Contributor(s):  ______________________________________.
+# ************************************************************************
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
+
+echo "Copying .eslintrc.json with Airbnb rules to modules with web/app folder"
+for mod in modules/*; do
+  if [[ -d "${mod}/web/$(basename ${mod})/app" ]]; then
+    cp ${SCRIPT_DIR}/eslintrc-airbnb.template ${mod}/web/$(basename ${mod})/app/.eslintrc.json
+    echo "> Copied to ${mod}/app"
+  fi
+done
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.kernel/eslint-airbnb/eslintrc-airbnb.template	Tue Nov 19 17:40:39 2019 +0100
@@ -0,0 +1,3 @@
+{
+  "extends": ["airbnb-base", "plugin:prettier/recommended"]
+}
--- a/modules/org.openbravo.client.kernel/jsformatter/jsformatter	Mon Nov 18 16:08:25 2019 +0100
+++ b/modules/org.openbravo.client.kernel/jsformatter/jsformatter	Tue Nov 19 17:40:39 2019 +0100
@@ -54,7 +54,7 @@
         IGNORE_PATH="--ignore-path $(pwd)/.prettierignore"
     fi
 
-    echo "$@" | xargs -n 250 npm run jsformat -s -- ${FLAGS} ${IGNORE_PATH} || exit 1
+    echo "$@" | xargs -n 250 npm run jsformat --prefix ${OPENBRAVO_ROOT_PATH} -s -- ${FLAGS} ${IGNORE_PATH} || exit 1
 }
 
 function getPrettierIgnorePatterns {
@@ -101,7 +101,7 @@
     fi
 
     echo "Formatter check for module $(basename ${BASE})"
-    npm run jsformat -s -- ${FORMATTER_FLAGS} ${IGNORE_PATH} "${BASE}/**/*.js"
+    npm run jsformat --prefix ${OPENBRAVO_ROOT_PATH} -s -- ${FORMATTER_FLAGS} ${IGNORE_PATH} "${BASE}/**/*.js"
 }
 
 #Parse input arguments
--- a/modules/org.openbravo.client.kernel/jslint/jslint	Mon Nov 18 16:08:25 2019 +0100
+++ b/modules/org.openbravo.client.kernel/jslint/jslint	Tue Nov 19 17:40:39 2019 +0100
@@ -57,7 +57,7 @@
     # ignored files are removed using a script
     FILTERED_FILES=$(node ${SCRIPT_DIR}/filter-eslint-ignored-files.js "$@")
     if [[ -n "${FILTERED_FILES}" ]]; then
-        echo "${FILTERED_FILES}" | xargs -n 250 npm run jslint -s -- ${FLAGS} ${IGNORE_PATH} || exit 1
+        echo "${FILTERED_FILES}" | xargs -n 250 npm run --prefix ${OPENBRAVO_ROOT_PATH} jslint -s -- ${FLAGS} ${IGNORE_PATH} || exit 1
     fi
 }
 
@@ -106,7 +106,7 @@
     fi
 
     echo "Lint check for module $(basename ${BASE})"
-    npm run jslint -s -- ${LINTER_FLAGS} ${IGNORE_PATH} "${BASE}"
+    npm run jslint --prefix ${OPENBRAVO_ROOT_PATH} -s -- ${LINTER_FLAGS} ${IGNORE_PATH} "${BASE}"
 }
 
 #Parse input arguments
--- a/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/BaseComponentProvider.java	Mon Nov 18 16:08:25 2019 +0100
+++ b/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/BaseComponentProvider.java	Tue Nov 19 17:40:39 2019 +0100
@@ -95,11 +95,6 @@
     return this.getClass().getPackage().getName();
   }
 
-  @Override
-  public List<String> getTestResources() {
-    return null;
-  }
-
   protected ComponentResource createComponentResource(ComponentResourceType type, String path) {
     final ComponentResource resource = new ComponentResource();
     resource.setType(type);
--- a/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/ComponentProvider.java	Mon Nov 18 16:08:25 2019 +0100
+++ b/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/ComponentProvider.java	Tue Nov 19 17:40:39 2019 +0100
@@ -66,12 +66,6 @@
   public Module getModule();
 
   /**
-   * 
-   * @return the list of JavaScript files that implement unit tests
-   */
-  public List<String> getTestResources();
-
-  /**
    * Computes parameters to add to a link of a resource. The parameters include the version and
    * language of the user.
    * 
--- a/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/KernelComponentProvider.java	Mon Nov 18 16:08:25 2019 +0100
+++ b/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/KernelComponentProvider.java	Tue Nov 19 17:40:39 2019 +0100
@@ -65,8 +65,6 @@
           SessionDynamicResourceComponent.class);
       sessionDynamicComponent.setParameters(parameters);
       return sessionDynamicComponent;
-    } else if (componentId.equals(KernelConstants.TEST_COMPONENT_ID)) {
-      return getComponent(TestComponent.class);
     } else if (componentId.equals(KernelConstants.DOCUMENT_COMPONENT_ID)) {
       return getComponent(DocumentationComponent.class);
     }
--- a/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/KernelConstants.java	Mon Nov 18 16:08:25 2019 +0100
+++ b/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/KernelConstants.java	Tue Nov 19 17:40:39 2019 +0100
@@ -65,7 +65,6 @@
 
   public static final String STYLE_SHEET_COMPONENT_ID = "StyleSheetResources";
   public static final String RESOURCE_COMPONENT_ID = "StaticResources";
-  public static final String TEST_COMPONENT_ID = "TestResources";
   public static final String DOCUMENT_COMPONENT_ID = "DocumentResources";
   public static final String RESOURCE_CONTEXT_URL_PARAMETER = "#{contextUrl}";
 
--- a/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/TestComponent.java	Mon Nov 18 16:08:25 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- *************************************************************************
- * The contents of this file are subject to the Openbravo  Public  License
- * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
- * Version 1.1  with a permitted attribution clause; you may not  use this
- * file except in compliance with the License. You  may  obtain  a copy of
- * the License at http://www.openbravo.com/legal/license.html
- * Software distributed under the License  is  distributed  on  an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
- * License for the specific  language  governing  rights  and  limitations
- * under the License.
- * The Original Code is Openbravo ERP.
- * The Initial Developer of the Original Code is Openbravo SLU
- * All portions are Copyright (C) 2010-2015 Openbravo SLU
- * All Rights Reserved.
- * Contributor(s):  ______________________________________.
- ************************************************************************
- */
-package org.openbravo.client.kernel;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.enterprise.inject.Any;
-import javax.enterprise.inject.Instance;
-import javax.inject.Inject;
-
-import org.openbravo.model.ad.module.Module;
-
-/**
- * 
- * @author iperdomo
- * 
- */
-public class TestComponent extends BaseComponent {
-
-  @Inject
-  @Any
-  private Instance<ComponentProvider> componentProviders;
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see org.openbravo.client.kernel.BaseComponent#generate()
-   */
-  @Override
-  public String generate() {
-    final StringBuilder sb = new StringBuilder();
-    for (String resource : getTestResources()) {
-      String testResource = resource;
-      if (testResource.startsWith("/") && getContextUrl().length() > 0) {
-        testResource = getContextUrl() + testResource.substring(1);
-      } else {
-        testResource = getContextUrl() + testResource;
-      }
-      sb.append("$LAB.script(\"" + testResource + "\");\n");
-    }
-    return sb.toString();
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see org.openbravo.client.kernel.BaseComponent#getData()
-   */
-  @Override
-  public Object getData() {
-    return this;
-  }
-
-  /**
-   * Get the list of static test resources ordered by module dependency
-   * 
-   * @return all static test components to be used by the ui test suite
-   */
-  public List<String> getTestResources() {
-    final List<Module> modules = KernelUtils.getInstance().getModulesOrderedByDependency();
-    final List<String> result = new ArrayList<String>();
-    for (Module mod : modules) {
-      for (ComponentProvider provider : componentProviders) {
-        if (provider.getTestResources() == null) {
-          continue;
-        }
-        if (provider.getModule().getId().equals(mod.getId())) {
-          for (String resource : provider.getTestResources()) {
-            if (!"".equals(resource)) {
-              result.add(resource);
-            }
-          }
-        }
-      }
-    }
-    return result;
-  }
-}
--- a/modules/org.openbravo.client.kernel/web/org.openbravo.client.kernel/ui-test-suite/index.html	Mon Nov 18 16:08:25 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-        "http://www.w3.org/TR/html4/loose.dtd">
-<!--
-*************************************************************************
-* The contents of this file are subject to the Openbravo  Public  License
-* Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
-* Version 1.1  with a permitted attribution clause; you may not  use this
-* file except in compliance with the License. You  may  obtain  a copy of
-* the License at http://www.openbravo.com/legal/license.html
-* Software distributed under the License  is  distributed  on  an "AS IS"
-* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-* License for the specific  language  governing  rights  and  limitations
-* under the License.
-* The Original Code is Openbravo ERP.
-* The Initial Developer of the Original Code is Openbravo SLU
-* All portions are Copyright (C) 2010-2019 Openbravo SLU
-* All Rights Reserved.
-* Contributor(s):  ______________________________________.
-************************************************************************
--->
-<html>
-<head>
-<meta http-equiv="Expires" content="Tue, 24 Apr 1979 00:00:01 GMT">
-<meta http-equiv="Content-type" content="text/html;charset=utf-8">
-<link rel="stylesheet" href="./qunit/qunit.css" type="text/css" media="screen">
-
-
-<script type="text/javascript" src="../js/LAB.min.js"></script>
-<script type="text/javascript"  src="./qunit/qunit.js"></script>
-<script src="../js/BigDecimal-all-1.0.3.min.js"></script>
-
-<title>Openbravo - Test Suite</title>
-</head>
-<body>
-  <script>
-    var isomorphicDir='../../org.openbravo.userinterface.smartclient/isomorphic/',
-        OBTest = { testStarted: false,
-              completed: false,
-              executed: {}
-            };
-    $LAB.setGlobalDefaults({CacheBust:true});
-    
-    QUnit.done(function (details) {
-        if (OBTest.testStarted){
-          isc.Class.fireOnPause('testExecution', function(){
-            if (QUnit.config.queue.length === 0) {
-              // mark execution as completed so Selenium gets notified
-              OBTest.completed = true;
-              OBTest.failed = details.failed;
-              OBTest.passed = details.passed;
-              OBTest.total = details.total;
-              OBTest.runtime = details.runtime;
-              console.log('Tests completed',OBTest);
-            }
-          }, 1000);
-        }
-    });
-    
-    QUnit.log(function (details) {
-      var result = OBTest.executed, testCase, assertName, i;
-      
-      if (!result[details.module + ' - ' + details.name]){
-          result[details.module + ' - ' + details.name] = {};
-      }
-      
-      testCase = result[details.module + ' - ' + details.name];
-      
-      assertName = details.message;
-      testCase[assertName] = { success: details.result, runtime: details.runtime};
-      
-      if (!details.result) {
-          testCase[assertName].expected = details.expected;
-          testCase[assertName].actual = details.actual;
-          testCase[assertName].source = details.source;
-      }
-    });
-
-    function OBStartApplication() {
-      OBTest.testStarted = true;
-      $LAB.script('../../../org.openbravo.client.kernel/OBCLKER_Kernel/TestResources');
-    }
-  </script>
-  
-  <script type="text/javascript" src="../../org.openbravo.userinterface.smartclient/isomorphic/ISC_Combined.js"></script>
-  <script type="text/javascript" src="../../org.openbravo.userinterface.smartclient/isomorphic/ISC_History.js"></script>
-  
-  <script>
-  (
-    function () {
-      var requestApplication = function () {
-          // Now we have a valid session, all StaticResources can be retrieved
-          isc.RPCManager.sendRequest({actionURL:'../../../org.openbravo.client.kernel/OBCLKER_Kernel/StaticResources?_mode=3.00&_skinVersion=Default', 
-              evalResult: false,
-              callback:function (resp, data) {
-                  test('Static Resources can be requested', function () {
-                      var app = data, idx;
-                      idx = app.indexOf("src='");
-                      QUnit.ok(idx !== -1, 'Static Resources file is present');
-                      app = app.substring(idx + 5);
-                      
-                      idx = app.indexOf(".js'>");
-                      QUnit.ok(idx !== -1, 'StaticResource file is a js file');
-                      app = app.substring(0, idx + 3);
-                      
-                      if (idx !== -1) {
-                        $LAB.script(app);
-                      }
-                  });
-              }});
-      };
-        
-      // at this point we have SC, we need a sesison to get the application
-      isc.RPCManager.sendRequest({actionURL:'../../../secureApp/LoginHandler.html?user=Openbravo&password=openbravo', 
-            evalResult: true,
-            callback:function (resp, data) {
-            	QUnit.module('org.openbravo.security');
-            	QUnit.test('Login', function (){
-                QUnit.ok(data && data.showMessage === false, 'Login correct');
-                requestApplication();
-              });
-            }});
-    }
-  )();
-  </script>
-  
-  <h1 id="qunit-header">Openbravo - Test Suite</h1>
-  <h2 id="qunit-banner"></h2>
-  <div id="qunit-testrunner-toolbar"></div>
-  <h2 id="qunit-userAgent"></h2>
-  <ol id="qunit-tests"></ol>
-</body>
-</html>
\ No newline at end of file
--- a/modules/org.openbravo.client.kernel/web/org.openbravo.client.kernel/ui-test-suite/qunit/qunit.css	Mon Nov 18 16:08:25 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,291 +0,0 @@
-/*!
- * QUnit 1.18.0
- * http://qunitjs.com/
- *
- * Copyright jQuery Foundation and other contributors
- * Released under the MIT license
- * http://jquery.org/license
- *
- * Date: 2015-04-03T10:23Z
- */
-
-/** Font Family and Sizes */
-
-#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
-    font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
-}
-
-#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
-#qunit-tests { font-size: smaller; }
-
-
-/** Resets */
-
-#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
-    margin: 0;
-    padding: 0;
-}
-
-
-/** Header */
-
-#qunit-header {
-    padding: 0.5em 0 0.5em 1em;
-
-    color: #8699A4;
-    background-color: #0D3349;
-
-    font-size: 1.5em;
-    line-height: 1em;
-    font-weight: 400;
-
-    border-radius: 5px 5px 0 0;
-}
-
-#qunit-header a {
-    text-decoration: none;
-    color: #C2CCD1;
-}
-
-#qunit-header a:hover,
-#qunit-header a:focus {
-    color: #FFF;
-}
-
-#qunit-testrunner-toolbar label {
-    display: inline-block;
-    padding: 0 0.5em 0 0.1em;
-}
-
-#qunit-banner {
-    height: 5px;
-}
-
-#qunit-testrunner-toolbar {
-    padding: 0.5em 1em 0.5em 1em;
-    color: #5E740B;
-    background-color: #EEE;
-    overflow: hidden;
-}
-
-#qunit-userAgent {
-    padding: 0.5em 1em 0.5em 1em;
-    background-color: #2B81AF;
-    color: #FFF;
-    text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
-}
-
-#qunit-modulefilter-container {
-    float: right;
-    padding: 0.2em;
-}
-
-.qunit-url-config {
-    display: inline-block;
-    padding: 0.1em;
-}
-
-.qunit-filter {
-    display: block;
-    float: right;
-    margin-left: 1em;
-}
-
-/** Tests: Pass/Fail */
-
-#qunit-tests {
-    list-style-position: inside;
-}
-
-#qunit-tests li {
-    padding: 0.4em 1em 0.4em 1em;
-    border-bottom: 1px solid #FFF;
-    list-style-position: inside;
-}
-
-#qunit-tests > li {
-    display: none;
-}
-
-#qunit-tests li.running,
-#qunit-tests li.pass,
-#qunit-tests li.fail,
-#qunit-tests li.skipped {
-    display: list-item;
-}
-
-#qunit-tests.hidepass li.running,
-#qunit-tests.hidepass li.pass {
-    visibility: hidden;
-    position: absolute;
-    width:   0px;
-    height:  0px;
-    padding: 0;
-    border:  0;
-    margin:  0;
-}
-
-#qunit-tests li strong {
-    cursor: pointer;
-}
-
-#qunit-tests li.skipped strong {
-    cursor: default;
-}
-
-#qunit-tests li a {
-    padding: 0.5em;
-    color: #C2CCD1;
-    text-decoration: none;
-}
-
-#qunit-tests li p a {
-    padding: 0.25em;
-    color: #6B6464;
-}
-#qunit-tests li a:hover,
-#qunit-tests li a:focus {
-    color: #000;
-}
-
-#qunit-tests li .runtime {
-    float: right;
-    font-size: smaller;
-}
-
-.qunit-assert-list {
-    margin-top: 0.5em;
-    padding: 0.5em;
-
-    background-color: #FFF;
-
-    border-radius: 5px;
-}
-
-.qunit-collapsed {
-    display: none;
-}
-
-#qunit-tests table {
-    border-collapse: collapse;
-    margin-top: 0.2em;
-}
-
-#qunit-tests th {
-    text-align: right;
-    vertical-align: top;
-    padding: 0 0.5em 0 0;
-}
-
-#qunit-tests td {
-    vertical-align: top;
-}
-
-#qunit-tests pre {
-    margin: 0;
-    white-space: pre-wrap;
-    word-wrap: break-word;
-}
-
-#qunit-tests del {
-    background-color: #E0F2BE;
-    color: #374E0C;
-    text-decoration: none;
-}
-
-#qunit-tests ins {
-    background-color: #FFCACA;
-    color: #500;
-    text-decoration: none;
-}
-
-/*** Test Counts */
-
-#qunit-tests b.counts                       { color: #000; }
-#qunit-tests b.passed                       { color: #5E740B; }
-#qunit-tests b.failed                       { color: #710909; }
-
-#qunit-tests li li {
-    padding: 5px;
-    background-color: #FFF;
-    border-bottom: none;
-    list-style-position: inside;
-}
-
-/*** Passing Styles */
-
-#qunit-tests li li.pass {
-    color: #3C510C;
-    background-color: #FFF;
-    border-left: 10px solid #C6E746;
-}
-
-#qunit-tests .pass                          { color: #528CE0; background-color: #D2E0E6; }
-#qunit-tests .pass .test-name               { color: #366097; }
-
-#qunit-tests .pass .test-actual,
-#qunit-tests .pass .test-expected           { color: #999; }
-
-#qunit-banner.qunit-pass                    { background-color: #C6E746; }
-
-/*** Failing Styles */
-
-#qunit-tests li li.fail {
-    color: #710909;
-    background-color: #FFF;
-    border-left: 10px solid #EE5757;
-    white-space: pre;
-}
-
-#qunit-tests > li:last-child {
-    border-radius: 0 0 5px 5px;
-}
-
-#qunit-tests .fail                          { color: #000; background-color: #EE5757; }
-#qunit-tests .fail .test-name,
-#qunit-tests .fail .module-name             { color: #000; }
-
-#qunit-tests .fail .test-actual             { color: #EE5757; }
-#qunit-tests .fail .test-expected           { color: #008000; }
-
-#qunit-banner.qunit-fail                    { background-color: #EE5757; }
-
-/*** Skipped tests */
-
-#qunit-tests .skipped {
-    background-color: #EBECE9;
-}
-
-#qunit-tests .qunit-skipped-label {
-    background-color: #F4FF77;
-    display: inline-block;
-    font-style: normal;
-    color: #366097;
-    line-height: 1.8em;
-    padding: 0 0.5em;
-    margin: -0.4em 0.4em -0.4em 0;
-}
-
-/** Result */
-
-#qunit-testresult {
-    padding: 0.5em 1em 0.5em 1em;
-
-    color: #2B81AF;
-    background-color: #D2E0E6;
-
-    border-bottom: 1px solid #FFF;
-}
-#qunit-testresult .module-name {
-    font-weight: 700;
-}
-
-/** Fixture */
-
-#qunit-fixture {
-    position: absolute;
-    top: -10000px;
-    left: -10000px;
-    width: 1000px;
-    height: 1000px;
-}
--- a/modules/org.openbravo.client.kernel/web/org.openbravo.client.kernel/ui-test-suite/qunit/qunit.js	Mon Nov 18 16:08:25 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3828 +0,0 @@
-/*!
- * QUnit 1.18.0
- * http://qunitjs.com/
- *
- * Copyright jQuery Foundation and other contributors
- * Released under the MIT license
- * http://jquery.org/license
- *
- * Date: 2015-04-03T10:23Z
- */
-
-(function( window ) {
-
-var QUnit,
-	config,
-	onErrorFnPrev,
-	loggingCallbacks = {},
-	fileName = ( sourceFromStacktrace( 0 ) || "" ).replace( /(:\d+)+\)?/, "" ).replace( /.+\//, "" ),
-	toString = Object.prototype.toString,
-	hasOwn = Object.prototype.hasOwnProperty,
-	// Keep a local reference to Date (GH-283)
-	Date = window.Date,
-	now = Date.now || function() {
-		return new Date().getTime();
-	},
-	globalStartCalled = false,
-	runStarted = false,
-	setTimeout = window.setTimeout,
-	clearTimeout = window.clearTimeout,
-	defined = {
-		document: window.document !== undefined,
-		setTimeout: window.setTimeout !== undefined,
-		sessionStorage: (function() {
-			var x = "qunit-test-string";
-			try {
-				sessionStorage.setItem( x, x );
-				sessionStorage.removeItem( x );
-				return true;
-			} catch ( e ) {
-				return false;
-			}
-		}())
-	},
-	/**
-	 * Provides a normalized error string, correcting an issue
-	 * with IE 7 (and prior) where Error.prototype.toString is
-	 * not properly implemented
-	 *
-	 * Based on http://es5.github.com/#x15.11.4.4
-	 *
-	 * @param {String|Error} error
-	 * @return {String} error message
-	 */
-	errorString = function( error ) {
-		var name, message,
-			errorString = error.toString();
-		if ( errorString.substring( 0, 7 ) === "[object" ) {
-			name = error.name ? error.name.toString() : "Error";
-			message = error.message ? error.message.toString() : "";
-			if ( name && message ) {
-				return name + ": " + message;
-			} else if ( name ) {
-				return name;
-			} else if ( message ) {
-				return message;
-			} else {
-				return "Error";
-			}
-		} else {
-			return errorString;
-		}
-	},
-	/**
-	 * Makes a clone of an object using only Array or Object as base,
-	 * and copies over the own enumerable properties.
-	 *
-	 * @param {Object} obj
-	 * @return {Object} New object with only the own properties (recursively).
-	 */
-	objectValues = function( obj ) {
-		var key, val,
-			vals = QUnit.is( "array", obj ) ? [] : {};
-		for ( key in obj ) {
-			if ( hasOwn.call( obj, key ) ) {
-				val = obj[ key ];
-				vals[ key ] = val === Object( val ) ? objectValues( val ) : val;
-			}
-		}
-		return vals;
-	};
-
-QUnit = {};
-
-/**
- * Config object: Maintain internal state
- * Later exposed as QUnit.config
- * `config` initialized at top of scope
- */
-config = {
-	// The queue of tests to run
-	queue: [],
-
-	// block until document ready
-	blocking: true,
-
-	// by default, run previously failed tests first
-	// very useful in combination with "Hide passed tests" checked
-	reorder: true,
-
-	// by default, modify document.title when suite is done
-	altertitle: true,
-
-	// by default, scroll to top of the page when suite is done
-	scrolltop: true,
-
-	// when enabled, all tests must call expect()
-	requireExpects: false,
-
-	// depth up-to which object will be dumped
-	maxDepth: 5,
-
-	// add checkboxes that are persisted in the query-string
-	// when enabled, the id is set to `true` as a `QUnit.config` property
-	urlConfig: [
-		{
-			id: "hidepassed",
-			label: "Hide passed tests",
-			tooltip: "Only show tests and assertions that fail. Stored as query-strings."
-		},
-		{
-			id: "noglobals",
-			label: "Check for Globals",
-			tooltip: "Enabling this will test if any test introduces new properties on the " +
-				"`window` object. Stored as query-strings."
-		},
-		{
-			id: "notrycatch",
-			label: "No try-catch",
-			tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging " +
-				"exceptions in IE reasonable. Stored as query-strings."
-		}
-	],
-
-	// Set of all modules.
-	modules: [],
-
-	// The first unnamed module
-	currentModule: {
-		name: "",
-		tests: []
-	},
-
-	callbacks: {}
-};
-
-// Push a loose unnamed module to the modules collection
-config.modules.push( config.currentModule );
-
-// Initialize more QUnit.config and QUnit.urlParams
-(function() {
-	var i, current,
-		location = window.location || { search: "", protocol: "file:" },
-		params = location.search.slice( 1 ).split( "&" ),
-		length = params.length,
-		urlParams = {};
-
-	if ( params[ 0 ] ) {
-		for ( i = 0; i < length; i++ ) {
-			current = params[ i ].split( "=" );
-			current[ 0 ] = decodeURIComponent( current[ 0 ] );
-
-			// allow just a key to turn on a flag, e.g., test.html?noglobals
-			current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;
-			if ( urlParams[ current[ 0 ] ] ) {
-				urlParams[ current[ 0 ] ] = [].concat( urlParams[ current[ 0 ] ], current[ 1 ] );
-			} else {
-				urlParams[ current[ 0 ] ] = current[ 1 ];
-			}
-		}
-	}
-
-	if ( urlParams.filter === true ) {
-		delete urlParams.filter;
-	}
-
-	QUnit.urlParams = urlParams;
-
-	// String search anywhere in moduleName+testName
-	config.filter = urlParams.filter;
-
-	if ( urlParams.maxDepth ) {
-		config.maxDepth = parseInt( urlParams.maxDepth, 10 ) === -1 ?
-			Number.POSITIVE_INFINITY :
-			urlParams.maxDepth;
-	}
-
-	config.testId = [];
-	if ( urlParams.testId ) {
-
-		// Ensure that urlParams.testId is an array
-		urlParams.testId = decodeURIComponent( urlParams.testId ).split( "," );
-		for ( i = 0; i < urlParams.testId.length; i++ ) {
-			config.testId.push( urlParams.testId[ i ] );
-		}
-	}
-
-	// Figure out if we're running the tests from a server or not
-	QUnit.isLocal = location.protocol === "file:";
-
-	// Expose the current QUnit version
-	QUnit.version = "1.18.0";
-}());
-
-// Root QUnit object.
-// `QUnit` initialized at top of scope
-extend( QUnit, {
-
-	// call on start of module test to prepend name to all tests
-	module: function( name, testEnvironment ) {
-		var currentModule = {
-			name: name,
-			testEnvironment: testEnvironment,
-			tests: []
-		};
-
-		// DEPRECATED: handles setup/teardown functions,
-		// beforeEach and afterEach should be used instead
-		if ( testEnvironment && testEnvironment.setup ) {
-			testEnvironment.beforeEach = testEnvironment.setup;
-			delete testEnvironment.setup;
-		}
-		if ( testEnvironment && testEnvironment.teardown ) {
-			testEnvironment.afterEach = testEnvironment.teardown;
-			delete testEnvironment.teardown;
-		}
-
-		config.modules.push( currentModule );
-		config.currentModule = currentModule;
-	},
-
-	// DEPRECATED: QUnit.asyncTest() will be removed in QUnit 2.0.
-	asyncTest: function( testName, expected, callback ) {
-		if ( arguments.length === 2 ) {
-			callback = expected;
-			expected = null;
-		}
-
-		QUnit.test( testName, expected, callback, true );
-	},
-
-	test: function( testName, expected, callback, async ) {
-		var test;
-
-		if ( arguments.length === 2 ) {
-			callback = expected;
-			expected = null;
-		}
-
-		test = new Test({
-			testName: testName,
-			expected: expected,
-			async: async,
-			callback: callback
-		});
-
-		test.queue();
-	},
-
-	skip: function( testName ) {
-		var test = new Test({
-			testName: testName,
-			skip: true
-		});
-
-		test.queue();
-	},
-
-	// DEPRECATED: The functionality of QUnit.start() will be altered in QUnit 2.0.
-	// In QUnit 2.0, invoking it will ONLY affect the `QUnit.config.autostart` blocking behavior.
-	start: function( count ) {
-		var globalStartAlreadyCalled = globalStartCalled;
-
-		if ( !config.current ) {
-			globalStartCalled = true;
-
-			if ( runStarted ) {
-				throw new Error( "Called start() outside of a test context while already started" );
-			} else if ( globalStartAlreadyCalled || count > 1 ) {
-				throw new Error( "Called start() outside of a test context too many times" );
-			} else if ( config.autostart ) {
-				throw new Error( "Called start() outside of a test context when " +
-					"QUnit.config.autostart was true" );
-			} else if ( !config.pageLoaded ) {
-
-				// The page isn't completely loaded yet, so bail out and let `QUnit.load` handle it
-				config.autostart = true;
-				return;
-			}
-		} else {
-
-			// If a test is running, adjust its semaphore
-			config.current.semaphore -= count || 1;
-
-			// Don't start until equal number of stop-calls
-			if ( config.current.semaphore > 0 ) {
-				return;
-			}
-
-			// throw an Error if start is called more often than stop
-			if ( config.current.semaphore < 0 ) {
-				config.current.semaphore = 0;
-
-				QUnit.pushFailure(
-					"Called start() while already started (test's semaphore was 0 already)",
-					sourceFromStacktrace( 2 )
-				);
-				return;
-			}
-		}
-
-		resumeProcessing();
-	},
-
-	// DEPRECATED: QUnit.stop() will be removed in QUnit 2.0.
-	stop: function( count ) {
-
-		// If there isn't a test running, don't allow QUnit.stop() to be called
-		if ( !config.current ) {
-			throw new Error( "Called stop() outside of a test context" );
-		}
-
-		// If a test is running, adjust its semaphore
-		config.current.semaphore += count || 1;
-
-		pauseProcessing();
-	},
-
-	config: config,
-
-	// Safe object type checking
-	is: function( type, obj ) {
-		return QUnit.objectType( obj ) === type;
-	},
-
-	objectType: function( obj ) {
-		if ( typeof obj === "undefined" ) {
-			return "undefined";
-		}
-
-		// Consider: typeof null === object
-		if ( obj === null ) {
-			return "null";
-		}
-
-		var match = toString.call( obj ).match( /^\[object\s(.*)\]$/ ),
-			type = match && match[ 1 ] || "";
-
-		switch ( type ) {
-			case "Number":
-				if ( isNaN( obj ) ) {
-					return "nan";
-				}
-				return "number";
-			case "String":
-			case "Boolean":
-			case "Array":
-			case "Date":
-			case "RegExp":
-			case "Function":
-				return type.toLowerCase();
-		}
-		if ( typeof obj === "object" ) {
-			return "object";
-		}
-		return undefined;
-	},
-
-	extend: extend,
-
-	load: function() {
-		config.pageLoaded = true;
-
-		// Initialize the configuration options
-		extend( config, {
-			stats: { all: 0, bad: 0 },
-			moduleStats: { all: 0, bad: 0 },
-			started: 0,
-			updateRate: 1000,
-			autostart: true,
-			filter: ""
-		}, true );
-
-		config.blocking = false;
-
-		if ( config.autostart ) {
-			resumeProcessing();
-		}
-	}
-});
-
-// Register logging callbacks
-(function() {
-	var i, l, key,
-		callbacks = [ "begin", "done", "log", "testStart", "testDone",
-			"moduleStart", "moduleDone" ];
-
-	function registerLoggingCallback( key ) {
-		var loggingCallback = function( callback ) {
-			if ( QUnit.objectType( callback ) !== "function" ) {
-				throw new Error(
-					"QUnit logging methods require a callback function as their first parameters."
-				);
-			}
-
-			config.callbacks[ key ].push( callback );
-		};
-
-		// DEPRECATED: This will be removed on QUnit 2.0.0+
-		// Stores the registered functions allowing restoring
-		// at verifyLoggingCallbacks() if modified
-		loggingCallbacks[ key ] = loggingCallback;
-
-		return loggingCallback;
-	}
-
-	for ( i = 0, l = callbacks.length; i < l; i++ ) {
-		key = callbacks[ i ];
-
-		// Initialize key collection of logging callback
-		if ( QUnit.objectType( config.callbacks[ key ] ) === "undefined" ) {
-			config.callbacks[ key ] = [];
-		}
-
-		QUnit[ key ] = registerLoggingCallback( key );
-	}
-})();
-
-// `onErrorFnPrev` initialized at top of scope
-// Preserve other handlers
-onErrorFnPrev = window.onerror;
-
-// Cover uncaught exceptions
-// Returning true will suppress the default browser handler,
-// returning false will let it run.
-window.onerror = function( error, filePath, linerNr ) {
-	var ret = false;
-	if ( onErrorFnPrev ) {
-		ret = onErrorFnPrev( error, filePath, linerNr );
-	}
-
-	// Treat return value as window.onerror itself does,
-	// Only do our handling if not suppressed.
-	if ( ret !== true ) {
-		if ( QUnit.config.current ) {
-			if ( QUnit.config.current.ignoreGlobalErrors ) {
-				return true;
-			}
-			QUnit.pushFailure( error, filePath + ":" + linerNr );
-		} else {
-			QUnit.test( "global failure", extend(function() {
-				QUnit.pushFailure( error, filePath + ":" + linerNr );
-			}, { validTest: true } ) );
-		}
-		return false;
-	}
-
-	return ret;
-};
-
-function done() {
-	var runtime, passed;
-
-	config.autorun = true;
-
-	// Log the last module results
-	if ( config.previousModule ) {
-		runLoggingCallbacks( "moduleDone", {
-			name: config.previousModule.name,
-			tests: config.previousModule.tests,
-			failed: config.moduleStats.bad,
-			passed: config.moduleStats.all - config.moduleStats.bad,
-			total: config.moduleStats.all,
-			runtime: now() - config.moduleStats.started
-		});
-	}
-	delete config.previousModule;
-
-	runtime = now() - config.started;
-	passed = config.stats.all - config.stats.bad;
-
-	runLoggingCallbacks( "done", {
-		failed: config.stats.bad,
-		passed: passed,
-		total: config.stats.all,
-		runtime: runtime
-	});
-}
-
-// Doesn't support IE6 to IE9, it will return undefined on these browsers
-// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
-function extractStacktrace( e, offset ) {
-	offset = offset === undefined ? 4 : offset;
-
-	var stack, include, i;
-
-	if ( e.stack ) {
-		stack = e.stack.split( "\n" );
-		if ( /^error$/i.test( stack[ 0 ] ) ) {
-			stack.shift();
-		}
-		if ( fileName ) {
-			include = [];
-			for ( i = offset; i < stack.length; i++ ) {
-				if ( stack[ i ].indexOf( fileName ) !== -1 ) {
-					break;
-				}
-				include.push( stack[ i ] );
-			}
-			if ( include.length ) {
-				return include.join( "\n" );
-			}
-		}
-		return stack[ offset ];
-
-	// Support: Safari <=6 only
-	} else if ( e.sourceURL ) {
-
-		// exclude useless self-reference for generated Error objects
-		if ( /qunit.js$/.test( e.sourceURL ) ) {
-			return;
-		}
-
-		// for actual exceptions, this is useful
-		return e.sourceURL + ":" + e.line;
-	}
-}
-
-function sourceFromStacktrace( offset ) {
-	var error = new Error();
-
-	// Support: Safari <=7 only, IE <=10 - 11 only
-	// Not all browsers generate the `stack` property for `new Error()`, see also #636
-	if ( !error.stack ) {
-		try {
-			throw error;
-		} catch ( err ) {
-			error = err;
-		}
-	}
-
-	return extractStacktrace( error, offset );
-}
-
-function synchronize( callback, last ) {
-	if ( QUnit.objectType( callback ) === "array" ) {
-		while ( callback.length ) {
-			synchronize( callback.shift() );
-		}
-		return;
-	}
-	config.queue.push( callback );
-
-	if ( config.autorun && !config.blocking ) {
-		process( last );
-	}
-}
-
-function process( last ) {
-	function next() {
-		process( last );
-	}
-	var start = now();
-	config.depth = ( config.depth || 0 ) + 1;
-
-	while ( config.queue.length && !config.blocking ) {
-		if ( !defined.setTimeout || config.updateRate <= 0 ||
-				( ( now() - start ) < config.updateRate ) ) {
-			if ( config.current ) {
-
-				// Reset async tracking for each phase of the Test lifecycle
-				config.current.usedAsync = false;
-			}
-			config.queue.shift()();
-		} else {
-			setTimeout( next, 13 );
-			break;
-		}
-	}
-	config.depth--;
-	if ( last && !config.blocking && !config.queue.length && config.depth === 0 ) {
-		done();
-	}
-}
-
-function begin() {
-	var i, l,
-		modulesLog = [];
-
-	// If the test run hasn't officially begun yet
-	if ( !config.started ) {
-
-		// Record the time of the test run's beginning
-		config.started = now();
-
-		verifyLoggingCallbacks();
-
-		// Delete the loose unnamed module if unused.
-		if ( config.modules[ 0 ].name === "" && config.modules[ 0 ].tests.length === 0 ) {
-			config.modules.shift();
-		}
-
-		// Avoid unnecessary information by not logging modules' test environments
-		for ( i = 0, l = config.modules.length; i < l; i++ ) {
-			modulesLog.push({
-				name: config.modules[ i ].name,
-				tests: config.modules[ i ].tests
-			});
-		}
-
-		// The test run is officially beginning now
-		runLoggingCallbacks( "begin", {
-			totalTests: Test.count,
-			modules: modulesLog
-		});
-	}
-
-	config.blocking = false;
-	process( true );
-}
-
-function resumeProcessing() {
-	runStarted = true;
-
-	// A slight delay to allow this iteration of the event loop to finish (more assertions, etc.)
-	if ( defined.setTimeout ) {
-		setTimeout(function() {
-			if ( config.current && config.current.semaphore > 0 ) {
-				return;
-			}
-			if ( config.timeout ) {
-				clearTimeout( config.timeout );
-			}
-
-			begin();
-		}, 13 );
-	} else {
-		begin();
-	}
-}
-
-function pauseProcessing() {
-	config.blocking = true;
-
-	if ( config.testTimeout && defined.setTimeout ) {
-		clearTimeout( config.timeout );
-		config.timeout = setTimeout(function() {
-			if ( config.current ) {
-				config.current.semaphore = 0;
-				QUnit.pushFailure( "Test timed out", sourceFromStacktrace( 2 ) );
-			} else {
-				throw new Error( "Test timed out" );
-			}
-			resumeProcessing();
-		}, config.testTimeout );
-	}
-}
-
-function saveGlobal() {
-	config.pollution = [];
-
-	if ( config.noglobals ) {
-		for ( var key in window ) {
-			if ( hasOwn.call( window, key ) ) {
-				// in Opera sometimes DOM element ids show up here, ignore them
-				if ( /^qunit-test-output/.test( key ) ) {
-					continue;
-				}
-				config.pollution.push( key );
-			}
-		}
-	}
-}
-
-function checkPollution() {
-	var newGlobals,
-		deletedGlobals,
-		old = config.pollution;
-
-	saveGlobal();
-
-	newGlobals = diff( config.pollution, old );
-	if ( newGlobals.length > 0 ) {
-		QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join( ", " ) );
-	}
-
-	deletedGlobals = diff( old, config.pollution );
-	if ( deletedGlobals.length > 0 ) {
-		QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join( ", " ) );
-	}
-}
-
-// returns a new Array with the elements that are in a but not in b
-function diff( a, b ) {
-	var i, j,
-		result = a.slice();
-
-	for ( i = 0; i < result.length; i++ ) {
-		for ( j = 0; j < b.length; j++ ) {
-			if ( result[ i ] === b[ j ] ) {
-				result.splice( i, 1 );
-				i--;
-				break;
-			}
-		}
-	}
-	return result;
-}
-
-function extend( a, b, undefOnly ) {
-	for ( var prop in b ) {
-		if ( hasOwn.call( b, prop ) ) {
-
-			// Avoid "Member not found" error in IE8 caused by messing with window.constructor
-			if ( !( prop === "constructor" && a === window ) ) {
-				if ( b[ prop ] === undefined ) {
-					delete a[ prop ];
-				} else if ( !( undefOnly && typeof a[ prop ] !== "undefined" ) ) {
-					a[ prop ] = b[ prop ];
-				}
-			}
-		}
-	}
-
-	return a;
-}
-
-function runLoggingCallbacks( key, args ) {
-	var i, l, callbacks;
-
-	callbacks = config.callbacks[ key ];
-	for ( i = 0, l = callbacks.length; i < l; i++ ) {
-		callbacks[ i ]( args );
-	}
-}
-
-// DEPRECATED: This will be removed on 2.0.0+
-// This function verifies if the loggingCallbacks were modified by the user
-// If so, it will restore it, assign the given callback and print a console warning
-function verifyLoggingCallbacks() {
-	var loggingCallback, userCallback;
-
-	for ( loggingCallback in loggingCallbacks ) {
-		if ( QUnit[ loggingCallback ] !== loggingCallbacks[ loggingCallback ] ) {
-
-			userCallback = QUnit[ loggingCallback ];
-
-			// Restore the callback function
-			QUnit[ loggingCallback ] = loggingCallbacks[ loggingCallback ];
-
-			// Assign the deprecated given callback
-			QUnit[ loggingCallback ]( userCallback );
-
-			if ( window.console && window.console.warn ) {
-				window.console.warn(
-					"QUnit." + loggingCallback + " was replaced with a new value.\n" +
-					"Please, check out the documentation on how to apply logging callbacks.\n" +
-					"Reference: http://api.qunitjs.com/category/callbacks/"
-				);
-			}
-		}
-	}
-}
-
-// from jquery.js
-function inArray( elem, array ) {
-	if ( array.indexOf ) {
-		return array.indexOf( elem );
-	}
-
-	for ( var i = 0, length = array.length; i < length; i++ ) {
-		if ( array[ i ] === elem ) {
-			return i;
-		}
-	}
-
-	return -1;
-}
-
-function Test( settings ) {
-	var i, l;
-
-	++Test.count;
-
-	extend( this, settings );
-	this.assertions = [];
-	this.semaphore = 0;
-	this.usedAsync = false;
-	this.module = config.currentModule;
-	this.stack = sourceFromStacktrace( 3 );
-
-	// Register unique strings
-	for ( i = 0, l = this.module.tests; i < l.length; i++ ) {
-		if ( this.module.tests[ i ].name === this.testName ) {
-			this.testName += " ";
-		}
-	}
-
-	this.testId = generateHash( this.module.name, this.testName );
-
-	this.module.tests.push({
-		name: this.testName,
-		testId: this.testId
-	});
-
-	if ( settings.skip ) {
-
-		// Skipped tests will fully ignore any sent callback
-		this.callback = function() {};
-		this.async = false;
-		this.expected = 0;
-	} else {
-		this.assert = new Assert( this );
-	}
-}
-
-Test.count = 0;
-
-Test.prototype = {
-	before: function() {
-		if (
-
-			// Emit moduleStart when we're switching from one module to another
-			this.module !== config.previousModule ||
-
-				// They could be equal (both undefined) but if the previousModule property doesn't
-				// yet exist it means this is the first test in a suite that isn't wrapped in a
-				// module, in which case we'll just emit a moduleStart event for 'undefined'.
-				// Without this, reporters can get testStart before moduleStart  which is a problem.
-				!hasOwn.call( config, "previousModule" )
-		) {
-			if ( hasOwn.call( config, "previousModule" ) ) {
-				runLoggingCallbacks( "moduleDone", {
-					name: config.previousModule.name,
-					tests: config.previousModule.tests,
-					failed: config.moduleStats.bad,
-					passed: config.moduleStats.all - config.moduleStats.bad,
-					total: config.moduleStats.all,
-					runtime: now() - config.moduleStats.started
-				});
-			}
-			config.previousModule = this.module;
-			config.moduleStats = { all: 0, bad: 0, started: now() };
-			runLoggingCallbacks( "moduleStart", {
-				name: this.module.name,
-				tests: this.module.tests
-			});
-		}
-
-		config.current = this;
-
-		this.testEnvironment = extend( {}, this.module.testEnvironment );
-		delete this.testEnvironment.beforeEach;
-		delete this.testEnvironment.afterEach;
-
-		this.started = now();
-		runLoggingCallbacks( "testStart", {
-			name: this.testName,
-			module: this.module.name,
-			testId: this.testId
-		});
-
-		if ( !config.pollution ) {
-			saveGlobal();
-		}
-	},
-
-	run: function() {
-		var promise;
-
-		config.current = this;
-
-		if ( this.async ) {
-			QUnit.stop();
-		}
-
-		this.callbackStarted = now();
-
-		if ( config.notrycatch ) {
-			promise = this.callback.call( this.testEnvironment, this.assert );
-			this.resolvePromise( promise );
-			return;
-		}
-
-		try {
-			promise = this.callback.call( this.testEnvironment, this.assert );
-			this.resolvePromise( promise );
-		} catch ( e ) {
-			this.pushFailure( "Died on test #" + ( this.assertions.length + 1 ) + " " +
-				this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) );
-
-			// else next test will carry the responsibility
-			saveGlobal();
-
-			// Restart the tests if they're blocking
-			if ( config.blocking ) {
-				QUnit.start();
-			}
-		}
-	},
-
-	after: function() {
-		checkPollution();
-	},
-
-	queueHook: function( hook, hookName ) {
-		var promise,
-			test = this;
-		return function runHook() {
-			config.current = test;
-			if ( config.notrycatch ) {
-				promise = hook.call( test.testEnvironment, test.assert );
-				test.resolvePromise( promise, hookName );
-				return;
-			}
-			try {
-				promise = hook.call( test.testEnvironment, test.assert );
-				test.resolvePromise( promise, hookName );
-			} catch ( error ) {
-				test.pushFailure( hookName + " failed on " + test.testName + ": " +
-					( error.message || error ), extractStacktrace( error, 0 ) );
-			}
-		};
-	},
-
-	// Currently only used for module level hooks, can be used to add global level ones
-	hooks: function( handler ) {
-		var hooks = [];
-
-		// Hooks are ignored on skipped tests
-		if ( this.skip ) {
-			return hooks;
-		}
-
-		if ( this.module.testEnvironment &&
-				QUnit.objectType( this.module.testEnvironment[ handler ] ) === "function" ) {
-			hooks.push( this.queueHook( this.module.testEnvironment[ handler ], handler ) );
-		}
-
-		return hooks;
-	},
-
-	finish: function() {
-		config.current = this;
-		if ( config.requireExpects && this.expected === null ) {
-			this.pushFailure( "Expected number of assertions to be defined, but expect() was " +
-				"not called.", this.stack );
-		} else if ( this.expected !== null && this.expected !== this.assertions.length ) {
-			this.pushFailure( "Expected " + this.expected + " assertions, but " +
-				this.assertions.length + " were run", this.stack );
-		} else if ( this.expected === null && !this.assertions.length ) {
-			this.pushFailure( "Expected at least one assertion, but none were run - call " +
-				"expect(0) to accept zero assertions.", this.stack );
-		}
-
-		var i,
-			bad = 0;
-
-		this.runtime = now() - this.started;
-		config.stats.all += this.assertions.length;
-		config.moduleStats.all += this.assertions.length;
-
-		for ( i = 0; i < this.assertions.length; i++ ) {
-			if ( !this.assertions[ i ].result ) {
-				bad++;
-				config.stats.bad++;
-				config.moduleStats.bad++;
-			}
-		}
-
-		runLoggingCallbacks( "testDone", {
-			name: this.testName,
-			module: this.module.name,
-			skipped: !!this.skip,
-			failed: bad,
-			passed: this.assertions.length - bad,
-			total: this.assertions.length,
-			runtime: this.runtime,
-
-			// HTML Reporter use
-			assertions: this.assertions,
-			testId: this.testId,
-
-			// DEPRECATED: this property will be removed in 2.0.0, use runtime instead
-			duration: this.runtime
-		});
-
-		// QUnit.reset() is deprecated and will be replaced for a new
-		// fixture reset function on QUnit 2.0/2.1.
-		// It's still called here for backwards compatibility handling
-		QUnit.reset();
-
-		config.current = undefined;
-	},
-
-	queue: function() {
-		var bad,
-			test = this;
-
-		if ( !this.valid() ) {
-			return;
-		}
-
-		function run() {
-
-			// each of these can by async
-			synchronize([
-				function() {
-					test.before();
-				},
-
-				test.hooks( "beforeEach" ),
-
-				function() {
-					test.run();
-				},
-
-				test.hooks( "afterEach" ).reverse(),
-
-				function() {
-					test.after();
-				},
-				function() {
-					test.finish();
-				}
-			]);
-		}
-
-		// `bad` initialized at top of scope
-		// defer when previous test run passed, if storage is available
-		bad = QUnit.config.reorder && defined.sessionStorage &&
-				+sessionStorage.getItem( "qunit-test-" + this.module.name + "-" + this.testName );
-
-		if ( bad ) {
-			run();
-		} else {
-			synchronize( run, true );
-		}
-	},
-
-	push: function( result, actual, expected, message ) {
-		var source,
-			details = {
-				module: this.module.name,
-				name: this.testName,
-				result: result,
-				message: message,
-				actual: actual,
-				expected: expected,
-				testId: this.testId,
-				runtime: now() - this.started
-			};
-
-		if ( !result ) {
-			source = sourceFromStacktrace();
-
-			if ( source ) {
-				details.source = source;
-			}
-		}
-
-		runLoggingCallbacks( "log", details );
-
-		this.assertions.push({
-			result: !!result,
-			message: message
-		});
-	},
-
-	pushFailure: function( message, source, actual ) {
-		if ( !this instanceof Test ) {
-			throw new Error( "pushFailure() assertion outside test context, was " +
-				sourceFromStacktrace( 2 ) );
-		}
-
-		var details = {
-				module: this.module.name,
-				name: this.testName,
-				result: false,
-				message: message || "error",
-				actual: actual || null,
-				testId: this.testId,
-				runtime: now() - this.started
-			};
-
-		if ( source ) {
-			details.source = source;
-		}
-
-		runLoggingCallbacks( "log", details );
-
-		this.assertions.push({
-			result: false,
-			message: message
-		});
-	},
-
-	resolvePromise: function( promise, phase ) {
-		var then, message,
-			test = this;
-		if ( promise != null ) {
-			then = promise.then;
-			if ( QUnit.objectType( then ) === "function" ) {
-				QUnit.stop();
-				then.call(
-					promise,
-					QUnit.start,
-					function( error ) {
-						message = "Promise rejected " +
-							( !phase ? "during" : phase.replace( /Each$/, "" ) ) +
-							" " + test.testName + ": " + ( error.message || error );
-						test.pushFailure( message, extractStacktrace( error, 0 ) );
-
-						// else next test will carry the responsibility
-						saveGlobal();
-
-						// Unblock
-						QUnit.start();
-					}
-				);
-			}
-		}
-	},
-
-	valid: function() {
-		var include,
-			filter = config.filter && config.filter.toLowerCase(),
-			module = QUnit.urlParams.module && QUnit.urlParams.module.toLowerCase(),
-			fullName = ( this.module.name + ": " + this.testName ).toLowerCase();
-
-		// Internally-generated tests are always valid
-		if ( this.callback && this.callback.validTest ) {
-			return true;
-		}
-
-		if ( config.testId.length > 0 && inArray( this.testId, config.testId ) < 0 ) {
-			return false;
-		}
-
-		if ( module && ( !this.module.name || this.module.name.toLowerCase() !== module ) ) {
-			return false;
-		}
-
-		if ( !filter ) {
-			return true;
-		}
-
-		include = filter.charAt( 0 ) !== "!";
-		if ( !include ) {
-			filter = filter.slice( 1 );
-		}
-
-		// If the filter matches, we need to honour include
-		if ( fullName.indexOf( filter ) !== -1 ) {
-			return include;
-		}
-
-		// Otherwise, do the opposite
-		return !include;
-	}
-
-};
-
-// Resets the test setup. Useful for tests that modify the DOM.
-/*
-DEPRECATED: Use multiple tests instead of resetting inside a test.
-Use testStart or testDone for custom cleanup.
-This method will throw an error in 2.0, and will be removed in 2.1
-*/
-QUnit.reset = function() {
-
-	// Return on non-browser environments
-	// This is necessary to not break on node tests
-	if ( typeof window === "undefined" ) {
-		return;
-	}
-
-	var fixture = defined.document && document.getElementById &&
-			document.getElementById( "qunit-fixture" );
-
-	if ( fixture ) {
-		fixture.innerHTML = config.fixture;
-	}
-};
-
-QUnit.pushFailure = function() {
-	if ( !QUnit.config.current ) {
-		throw new Error( "pushFailure() assertion outside test context, in " +
-			sourceFromStacktrace( 2 ) );
-	}
-
-	// Gets current test obj
-	var currentTest = QUnit.config.current;
-
-	return currentTest.pushFailure.apply( currentTest, arguments );
-};
-
-// Based on Java's String.hashCode, a simple but not
-// rigorously collision resistant hashing function
-function generateHash( module, testName ) {
-	var hex,
-		i = 0,
-		hash = 0,
-		str = module + "\x1C" + testName,
-		len = str.length;
-
-	for ( ; i < len; i++ ) {
-		hash  = ( ( hash << 5 ) - hash ) + str.charCodeAt( i );
-		hash |= 0;
-	}
-
-	// Convert the possibly negative integer hash code into an 8 character hex string, which isn't
-	// strictly necessary but increases user understanding that the id is a SHA-like hash
-	hex = ( 0x100000000 + hash ).toString( 16 );
-	if ( hex.length < 8 ) {
-		hex = "0000000" + hex;
-	}
-
-	return hex.slice( -8 );
-}
-
-function Assert( testContext ) {
-	this.test = testContext;
-}
-
-// Assert helpers
-QUnit.assert = Assert.prototype = {
-
-	// Specify the number of expected assertions to guarantee that failed test
-	// (no assertions are run at all) don't slip through.
-	expect: function( asserts ) {
-		if ( arguments.length === 1 ) {
-			this.test.expected = asserts;
-		} else {
-			return this.test.expected;
-		}
-	},
-
-	// Increment this Test's semaphore counter, then return a single-use function that
-	// decrements that counter a maximum of once.
-	async: function() {
-		var test = this.test,
-			popped = false;
-
-		test.semaphore += 1;
-		test.usedAsync = true;
-		pauseProcessing();
-
-		return function done() {
-			if ( !popped ) {
-				test.semaphore -= 1;
-				popped = true;
-				resumeProcessing();
-			} else {
-				test.pushFailure( "Called the callback returned from `assert.async` more than once",
-					sourceFromStacktrace( 2 ) );
-			}
-		};
-	},
-
-	// Exports test.push() to the user API
-	push: function( /* result, actual, expected, message */ ) {
-		var assert = this,
-			currentTest = ( assert instanceof Assert && assert.test ) || QUnit.config.current;
-
-		// Backwards compatibility fix.
-		// Allows the direct use of global exported assertions and QUnit.assert.*
-		// Although, it's use is not recommended as it can leak assertions
-		// to other tests from async tests, because we only get a reference to the current test,
-		// not exactly the test where assertion were intended to be called.
-		if ( !currentTest ) {
-			throw new Error( "assertion outside test context, in " + sourceFromStacktrace( 2 ) );
-		}
-
-		if ( currentTest.usedAsync === true && currentTest.semaphore === 0 ) {
-			currentTest.pushFailure( "Assertion after the final `assert.async` was resolved",
-				sourceFromStacktrace( 2 ) );
-
-			// Allow this assertion to continue running anyway...
-		}
-
-		if ( !( assert instanceof Assert ) ) {
-			assert = currentTest.assert;
-		}
-		return assert.test.push.apply( assert.test, arguments );
-	},
-
-	ok: function( result, message ) {
-		message = message || ( result ? "okay" : "failed, expected argument to be truthy, was: " +
-			QUnit.dump.parse( result ) );
-		this.push( !!result, result, true, message );
-	},
-
-	notOk: function( result, message ) {
-		message = message || ( !result ? "okay" : "failed, expected argument to be falsy, was: " +
-			QUnit.dump.parse( result ) );
-		this.push( !result, result, false, message );
-	},
-
-	equal: function( actual, expected, message ) {
-		/*jshint eqeqeq:false */
-		this.push( expected == actual, actual, expected, message );
-	},
-
-	notEqual: function( actual, expected, message ) {
-		/*jshint eqeqeq:false */
-		this.push( expected != actual, actual, expected, message );
-	},
-
-	propEqual: function( actual, expected, message ) {
-		actual = objectValues( actual );
-		expected = objectValues( expected );
-		this.push( QUnit.equiv( actual, expected ), actual, expected, message );
-	},
-
-	notPropEqual: function( actual, expected, message ) {
-		actual = objectValues( actual );
-		expected = objectValues( expected );
-		this.push( !QUnit.equiv( actual, expected ), actual, expected, message );
-	},
-
-	deepEqual: function( actual, expected, message ) {
-		this.push( QUnit.equiv( actual, expected ), actual, expected, message );
-	},
-
-	notDeepEqual: function( actual, expected, message ) {
-		this.push( !QUnit.equiv( actual, expected ), actual, expected, message );
-	},
-
-	strictEqual: function( actual, expected, message ) {
-		this.push( expected === actual, actual, expected, message );
-	},
-
-	notStrictEqual: function( actual, expected, message ) {
-		this.push( expected !== actual, actual, expected, message );
-	},
-
-	"throws": function( block, expected, message ) {
-		var actual, expectedType,
-			expectedOutput = expected,
-			ok = false,
-			currentTest = ( this instanceof Assert && this.test ) || QUnit.config.current;
-
-		// 'expected' is optional unless doing string comparison
-		if ( message == null && typeof expected === "string" ) {
-			message = expected;
-			expected = null;
-		}
-
-		currentTest.ignoreGlobalErrors = true;
-		try {
-			block.call( currentTest.testEnvironment );
-		} catch (e) {
-			actual = e;
-		}
-		currentTest.ignoreGlobalErrors = false;
-
-		if ( actual ) {
-			expectedType = QUnit.objectType( expected );
-
-			// we don't want to validate thrown error
-			if ( !expected ) {
-				ok = true;
-				expectedOutput = null;
-
-			// expected is a regexp
-			} else if ( expectedType === "regexp" ) {
-				ok = expected.test( errorString( actual ) );
-
-			// expected is a string
-			} else if ( expectedType === "string" ) {
-				ok = expected === errorString( actual );
-
-			// expected is a constructor, maybe an Error constructor
-			} else if ( expectedType === "function" && actual instanceof expected ) {
-				ok = true;
-
-			// expected is an Error object
-			} else if ( expectedType === "object" ) {
-				ok = actual instanceof expected.constructor &&
-					actual.name === expected.name &&
-					actual.message === expected.message;
-
-			// expected is a validation function which returns true if validation passed
-			} else if ( expectedType === "function" && expected.call( {}, actual ) === true ) {
-				expectedOutput = null;
-				ok = true;
-			}
-		}
-
-		currentTest.assert.push( ok, actual, expectedOutput, message );
-	}
-};
-
-// Provide an alternative to assert.throws(), for enviroments that consider throws a reserved word
-// Known to us are: Closure Compiler, Narwhal
-(function() {
-	/*jshint sub:true */
-	Assert.prototype.raises = Assert.prototype[ "throws" ];
-}());
-
-// Test for equality any JavaScript type.
-// Author: Philippe Rathé <prathe@gmail.com>
-QUnit.equiv = (function() {
-
-	// Call the o related callback with the given arguments.
-	function bindCallbacks( o, callbacks, args ) {
-		var prop = QUnit.objectType( o );
-		if ( prop ) {
-			if ( QUnit.objectType( callbacks[ prop ] ) === "function" ) {
-				return callbacks[ prop ].apply( callbacks, args );
-			} else {
-				return callbacks[ prop ]; // or undefined
-			}
-		}
-	}
-
-	// the real equiv function
-	var innerEquiv,
-
-		// stack to decide between skip/abort functions
-		callers = [],
-
-		// stack to avoiding loops from circular referencing
-		parents = [],
-		parentsB = [],
-
-		getProto = Object.getPrototypeOf || function( obj ) {
-			/* jshint camelcase: false, proto: true */
-			return obj.__proto__;
-		},
-		callbacks = (function() {
-
-			// for string, boolean, number and null
-			function useStrictEquality( b, a ) {
-
-				/*jshint eqeqeq:false */
-				if ( b instanceof a.constructor || a instanceof b.constructor ) {
-
-					// to catch short annotation VS 'new' annotation of a
-					// declaration
-					// e.g. var i = 1;
-					// var j = new Number(1);
-					return a == b;
-				} else {
-					return a === b;
-				}
-			}
-
-			return {
-				"string": useStrictEquality,
-				"boolean": useStrictEquality,
-				"number": useStrictEquality,
-				"null": useStrictEquality,
-				"undefined": useStrictEquality,
-
-				"nan": function( b ) {
-					return isNaN( b );
-				},
-
-				"date": function( b, a ) {
-					return QUnit.objectType( b ) === "date" && a.valueOf() === b.valueOf();
-				},
-
-				"regexp": function( b, a ) {
-					return QUnit.objectType( b ) === "regexp" &&
-
-						// the regex itself
-						a.source === b.source &&
-
-						// and its modifiers
-						a.global === b.global &&
-
-						// (gmi) ...
-						a.ignoreCase === b.ignoreCase &&
-						a.multiline === b.multiline &&
-						a.sticky === b.sticky;
-				},
-
-				// - skip when the property is a method of an instance (OOP)
-				// - abort otherwise,
-				// initial === would have catch identical references anyway
-				"function": function() {
-					var caller = callers[ callers.length - 1 ];
-					return caller !== Object && typeof caller !== "undefined";
-				},
-
-				"array": function( b, a ) {
-					var i, j, len, loop, aCircular, bCircular;
-
-					// b could be an object literal here
-					if ( QUnit.objectType( b ) !== "array" ) {
-						return false;
-					}
-
-					len = a.length;
-					if ( len !== b.length ) {
-						// safe and faster
-						return false;
-					}
-
-					// track reference to avoid circular references
-					parents.push( a );
-					parentsB.push( b );
-					for ( i = 0; i < len; i++ ) {
-						loop = false;
-						for ( j = 0; j < parents.length; j++ ) {
-							aCircular = parents[ j ] === a[ i ];
-							bCircular = parentsB[ j ] === b[ i ];
-							if ( aCircular || bCircular ) {
-								if ( a[ i ] === b[ i ] || aCircular && bCircular ) {
-									loop = true;
-								} else {
-									parents.pop();
-									parentsB.pop();
-									return false;
-								}
-							}
-						}
-						if ( !loop && !innerEquiv( a[ i ], b[ i ] ) ) {
-							parents.pop();
-							parentsB.pop();
-							return false;
-						}
-					}
-					parents.pop();
-					parentsB.pop();
-					return true;
-				},
-
-				"object": function( b, a ) {
-
-					/*jshint forin:false */
-					var i, j, loop, aCircular, bCircular,
-						// Default to true
-						eq = true,
-						aProperties = [],
-						bProperties = [];
-
-					// comparing constructors is more strict than using
-					// instanceof
-					if ( a.constructor !== b.constructor ) {
-
-						// Allow objects with no prototype to be equivalent to
-						// objects with Object as their constructor.
-						if ( !( ( getProto( a ) === null && getProto( b ) === Object.prototype ) ||
-							( getProto( b ) === null && getProto( a ) === Object.prototype ) ) ) {
-							return false;
-						}
-					}
-
-					// stack constructor before traversing properties
-					callers.push( a.constructor );
-
-					// track reference to avoid circular references
-					parents.push( a );
-					parentsB.push( b );
-
-					// be strict: don't ensure hasOwnProperty and go deep
-					for ( i in a ) {
-						loop = false;
-						for ( j = 0; j < parents.length; j++ ) {
-							aCircular = parents[ j ] === a[ i ];
-							bCircular = parentsB[ j ] === b[ i ];
-							if ( aCircular || bCircular ) {
-								if ( a[ i ] === b[ i ] || aCircular && bCircular ) {
-									loop = true;
-								} else {
-									eq = false;
-									break;
-								}
-							}
-						}
-						aProperties.push( i );
-						if ( !loop && !innerEquiv( a[ i ], b[ i ] ) ) {
-							eq = false;
-							break;
-						}
-					}
-
-					parents.pop();
-					parentsB.pop();
-					callers.pop(); // unstack, we are done
-
-					for ( i in b ) {
-						bProperties.push( i ); // collect b's properties
-					}
-
-					// Ensures identical properties name
-					return eq && innerEquiv( aProperties.sort(), bProperties.sort() );
-				}
-			};
-		}());
-
-	innerEquiv = function() { // can take multiple arguments
-		var args = [].slice.apply( arguments );
-		if ( args.length < 2 ) {
-			return true; // end transition
-		}
-
-		return ( (function( a, b ) {
-			if ( a === b ) {
-				return true; // catch the most you can
-			} else if ( a === null || b === null || typeof a === "undefined" ||
-					typeof b === "undefined" ||
-					QUnit.objectType( a ) !== QUnit.objectType( b ) ) {
-
-				// don't lose time with error prone cases
-				return false;
-			} else {
-				return bindCallbacks( a, callbacks, [ b, a ] );
-			}
-
-			// apply transition with (1..n) arguments
-		}( args[ 0 ], args[ 1 ] ) ) &&
-			innerEquiv.apply( this, args.splice( 1, args.length - 1 ) ) );
-	};
-
-	return innerEquiv;
-}());
-
-// Based on jsDump by Ariel Flesler
-// http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html
-QUnit.dump = (function() {
-	function quote( str ) {
-		return "\"" + str.toString().replace( /"/g, "\\\"" ) + "\"";
-	}
-	function literal( o ) {
-		return o + "";
-	}
-	function join( pre, arr, post ) {
-		var s = dump.separator(),
-			base = dump.indent(),
-			inner = dump.indent( 1 );
-		if ( arr.join ) {
-			arr = arr.join( "," + s + inner );
-		}
-		if ( !arr ) {
-			return pre + post;
-		}
-		return [ pre, inner + arr, base + post ].join( s );
-	}
-	function array( arr, stack ) {
-		var i = arr.length,
-			ret = new Array( i );
-
-		if ( dump.maxDepth && dump.depth > dump.maxDepth ) {
-			return "[object Array]";
-		}
-
-		this.up();
-		while ( i-- ) {
-			ret[ i ] = this.parse( arr[ i ], undefined, stack );
-		}
-		this.down();
-		return join( "[", ret, "]" );
-	}
-
-	var reName = /^function (\w+)/,
-		dump = {
-
-			// objType is used mostly internally, you can fix a (custom) type in advance
-			parse: function( obj, objType, stack ) {
-				stack = stack || [];
-				var res, parser, parserType,
-					inStack = inArray( obj, stack );
-
-				if ( inStack !== -1 ) {
-					return "recursion(" + ( inStack - stack.length ) + ")";
-				}
-
-				objType = objType || this.typeOf( obj  );
-				parser = this.parsers[ objType ];
-				parserType = typeof parser;
-
-				if ( parserType === "function" ) {
-					stack.push( obj );
-					res = parser.call( this, obj, stack );
-					stack.pop();
-					return res;
-				}
-				return ( parserType === "string" ) ? parser : this.parsers.error;
-			},
-			typeOf: function( obj ) {
-				var type;
-				if ( obj === null ) {
-					type = "null";
-				} else if ( typeof obj === "undefined" ) {
-					type = "undefined";
-				} else if ( QUnit.is( "regexp", obj ) ) {
-					type = "regexp";
-				} else if ( QUnit.is( "date", obj ) ) {
-					type = "date";
-				} else if ( QUnit.is( "function", obj ) ) {
-					type = "function";
-				} else if ( obj.setInterval !== undefined &&
-						obj.document !== undefined &&
-						obj.nodeType === undefined ) {
-					type = "window";
-				} else if ( obj.nodeType === 9 ) {
-					type = "document";
-				} else if ( obj.nodeType ) {
-					type = "node";
-				} else if (
-
-					// native arrays
-					toString.call( obj ) === "[object Array]" ||
-
-					// NodeList objects
-					( typeof obj.length === "number" && obj.item !== undefined &&
-					( obj.length ? obj.item( 0 ) === obj[ 0 ] : ( obj.item( 0 ) === null &&
-					obj[ 0 ] === undefined ) ) )
-				) {
-					type = "array";
-				} else if ( obj.constructor === Error.prototype.constructor ) {
-					type = "error";
-				} else {
-					type = typeof obj;
-				}
-				return type;
-			},
-			separator: function() {
-				return this.multiline ? this.HTML ? "<br />" : "\n" : this.HTML ? "&#160;" : " ";
-			},
-			// extra can be a number, shortcut for increasing-calling-decreasing
-			indent: function( extra ) {
-				if ( !this.multiline ) {
-					return "";
-				}
-				var chr = this.indentChar;
-				if ( this.HTML ) {
-					chr = chr.replace( /\t/g, "   " ).replace( / /g, "&#160;" );
-				}
-				return new Array( this.depth + ( extra || 0 ) ).join( chr );
-			},
-			up: function( a ) {
-				this.depth += a || 1;
-			},
-			down: function( a ) {
-				this.depth -= a || 1;
-			},
-			setParser: function( name, parser ) {
-				this.parsers[ name ] = parser;
-			},
-			// The next 3 are exposed so you can use them
-			quote: quote,
-			literal: literal,
-			join: join,
-			//
-			depth: 1,
-			maxDepth: QUnit.config.maxDepth,
-
-			// This is the list of parsers, to modify them, use dump.setParser
-			parsers: {
-				window: "[Window]",
-				document: "[Document]",
-				error: function( error ) {
-					return "Error(\"" + error.message + "\")";
-				},
-				unknown: "[Unknown]",
-				"null": "null",
-				"undefined": "undefined",
-				"function": function( fn ) {
-					var ret = "function",
-
-						// functions never have name in IE
-						name = "name" in fn ? fn.name : ( reName.exec( fn ) || [] )[ 1 ];
-
-					if ( name ) {
-						ret += " " + name;
-					}
-					ret += "( ";
-
-					ret = [ ret, dump.parse( fn, "functionArgs" ), "){" ].join( "" );
-					return join( ret, dump.parse( fn, "functionCode" ), "}" );
-				},
-				array: array,
-				nodelist: array,
-				"arguments": array,
-				object: function( map, stack ) {
-					var keys, key, val, i, nonEnumerableProperties,
-						ret = [];
-
-					if ( dump.maxDepth && dump.depth > dump.maxDepth ) {
-						return "[object Object]";
-					}
-
-					dump.up();
-					keys = [];
-					for ( key in map ) {
-						keys.push( key );
-					}
-
-					// Some properties are not always enumerable on Error objects.
-					nonEnumerableProperties = [ "message", "name" ];
-					for ( i in nonEnumerableProperties ) {
-						key = nonEnumerableProperties[ i ];
-						if ( key in map && inArray( key, keys ) < 0 ) {
-							keys.push( key );
-						}
-					}
-					keys.sort();
-					for ( i = 0; i < keys.length; i++ ) {
-						key = keys[ i ];
-						val = map[ key ];
-						ret.push( dump.parse( key, "key" ) + ": " +
-							dump.parse( val, undefined, stack ) );
-					}
-					dump.down();
-					return join( "{", ret, "}" );
-				},
-				node: function( node ) {
-					var len, i, val,
-						open = dump.HTML ? "&lt;" : "<",
-						close = dump.HTML ? "&gt;" : ">",
-						tag = node.nodeName.toLowerCase(),
-						ret = open + tag,
-						attrs = node.attributes;
-
-					if ( attrs ) {
-						for ( i = 0, len = attrs.length; i < len; i++ ) {
-							val = attrs[ i ].nodeValue;
-
-							// IE6 includes all attributes in .attributes, even ones not explicitly
-							// set. Those have values like undefined, null, 0, false, "" or
-							// "inherit".
-							if ( val && val !== "inherit" ) {
-								ret += " " + attrs[ i ].nodeName + "=" +
-									dump.parse( val, "attribute" );
-							}
-						}
-					}
-					ret += close;
-
-					// Show content of TextNode or CDATASection
-					if ( node.nodeType === 3 || node.nodeType === 4 ) {
-						ret += node.nodeValue;
-					}
-
-					return ret + open + "/" + tag + close;
-				},
-
-				// function calls it internally, it's the arguments part of the function
-				functionArgs: function( fn ) {
-					var args,
-						l = fn.length;
-
-					if ( !l ) {
-						return "";
-					}
-
-					args = new Array( l );
-					while ( l-- ) {
-
-						// 97 is 'a'
-						args[ l ] = String.fromCharCode( 97 + l );
-					}
-					return " " + args.join( ", " ) + " ";
-				},
-				// object calls it internally, the key part of an item in a map
-				key: quote,
-				// function calls it internally, it's the content of the function
-				functionCode: "[code]",
-				// node calls it internally, it's an html attribute value
-				attribute: quote,
-				string: quote,
-				date: quote,
-				regexp: literal,
-				number: literal,
-				"boolean": literal
-			},
-			// if true, entities are escaped ( <, >, \t, space and \n )
-			HTML: false,
-			// indentation unit
-			indentChar: "  ",
-			// if true, items in a collection, are separated by a \n, else just a space.
-			multiline: true
-		};
-
-	return dump;
-}());
-
-// back compat
-QUnit.jsDump = QUnit.dump;
-
-// For browser, export only select globals
-if ( typeof window !== "undefined" ) {
-
-	// Deprecated
-	// Extend assert methods to QUnit and Global scope through Backwards compatibility
-	(function() {
-		var i,
-			assertions = Assert.prototype;
-
-		function applyCurrent( current ) {
-			return function() {
-				var assert = new Assert( QUnit.config.current );
-				current.apply( assert, arguments );
-			};
-		}
-
-		for ( i in assertions ) {
-			QUnit[ i ] = applyCurrent( assertions[ i ] );
-		}
-	})();
-
-	(function() {
-		var i, l,
-			keys = [
-				"test",
-				"module",
-				"expect",
-				"asyncTest",
-				"start",
-				"stop",
-				"ok",
-				"notOk",
-				"equal",
-				"notEqual",
-				"propEqual",
-				"notPropEqual",
-				"deepEqual",
-				"notDeepEqual",
-				"strictEqual",
-				"notStrictEqual",
-				"throws"
-			];
-
-		for ( i = 0, l = keys.length; i < l; i++ ) {
-			window[ keys[ i ] ] = QUnit[ keys[ i ] ];
-		}
-	})();
-
-	window.QUnit = QUnit;
-}
-
-// For nodejs
-if ( typeof module !== "undefined" && module && module.exports ) {
-	module.exports = QUnit;
-
-	// For consistency with CommonJS environments' exports
-	module.exports.QUnit = QUnit;
-}
-
-// For CommonJS with exports, but without module.exports, like Rhino
-if ( typeof exports !== "undefined" && exports ) {
-	exports.QUnit = QUnit;
-}
-
-if ( typeof define === "function" && define.amd ) {
-	define( function() {
-		return QUnit;
-	} );
-	QUnit.config.autostart = false;
-}
-
-// Get a reference to the global object, like window in browsers
-}( (function() {
-	return this;
-})() ));
-
-/*istanbul ignore next */
-// jscs:disable maximumLineLength
-/*
- * This file is a modified version of google-diff-match-patch's JavaScript implementation
- * (https://code.google.com/p/google-diff-match-patch/source/browse/trunk/javascript/diff_match_patch_uncompressed.js),
- * modifications are licensed as more fully set forth in LICENSE.txt.
- *
- * The original source of google-diff-match-patch is attributable and licensed as follows:
- *
- * Copyright 2006 Google Inc.
- * http://code.google.com/p/google-diff-match-patch/
- *
- * 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.
- *
- * More Info:
- *  https://code.google.com/p/google-diff-match-patch/
- *
- * Usage: QUnit.diff(expected, actual)
- *
- * QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) === "the  quick <del>brown </del> fox jump<ins>s</ins><del>ed</del over"
- */
-QUnit.diff = (function() {
-
-    function DiffMatchPatch() {
-
-        // Defaults.
-        // Redefine these in your program to override the defaults.
-
-        // Number of seconds to map a diff before giving up (0 for infinity).
-        this.DiffTimeout = 1.0;
-        // Cost of an empty edit operation in terms of edit characters.
-        this.DiffEditCost = 4;
-    }
-
-    //  DIFF FUNCTIONS
-
-    /**
-     * The data structure representing a diff is an array of tuples:
-     * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]
-     * which means: delete 'Hello', add 'Goodbye' and keep ' world.'
-     */
-    var DIFF_DELETE = -1,
-		DIFF_INSERT = 1,
-		DIFF_EQUAL = 0;
-
-    /**
-     * Find the differences between two texts.  Simplifies the problem by stripping
-     * any common prefix or suffix off the texts before diffing.
-     * @param {string} text1 Old string to be diffed.
-     * @param {string} text2 New string to be diffed.
-     * @param {boolean=} optChecklines Optional speedup flag. If present and false,
-     *     then don't run a line-level diff first to identify the changed areas.
-     *     Defaults to true, which does a faster, slightly less optimal diff.
-     * @param {number} optDeadline Optional time when the diff should be complete
-     *     by.  Used internally for recursive calls.  Users should set DiffTimeout
-     *     instead.
-     * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
-     */
-    DiffMatchPatch.prototype.DiffMain = function( text1, text2, optChecklines, optDeadline ) {
-        var deadline, checklines, commonlength,
-			commonprefix, commonsuffix, diffs;
-        // Set a deadline by which time the diff must be complete.
-        if ( typeof optDeadline === "undefined" ) {
-            if ( this.DiffTimeout <= 0 ) {
-                optDeadline = Number.MAX_VALUE;
-            } else {
-                optDeadline = ( new Date() ).getTime() + this.DiffTimeout * 1000;
-            }
-        }
-        deadline = optDeadline;
-
-        // Check for null inputs.
-        if ( text1 === null || text2 === null ) {
-            throw new Error( "Null input. (DiffMain)" );
-        }
-
-        // Check for equality (speedup).
-        if ( text1 === text2 ) {
-            if ( text1 ) {
-                return [
-                    [ DIFF_EQUAL, text1 ]
-                ];
-            }
-            return [];
-        }
-
-        if ( typeof optChecklines === "undefined" ) {
-            optChecklines = true;
-        }
-
-        checklines = optChecklines;
-
-        // Trim off common prefix (speedup).
-        commonlength = this.diffCommonPrefix( text1, text2 );
-        commonprefix = text1.substring( 0, commonlength );
-        text1 = text1.substring( commonlength );
-        text2 = text2.substring( commonlength );
-
-        // Trim off common suffix (speedup).
-        /////////
-        commonlength = this.diffCommonSuffix( text1, text2 );
-        commonsuffix = text1.substring( text1.length - commonlength );
-        text1 = text1.substring( 0, text1.length - commonlength );
-        text2 = text2.substring( 0, text2.length - commonlength );
-
-        // Compute the diff on the middle block.
-        diffs = this.diffCompute( text1, text2, checklines, deadline );
-
-        // Restore the prefix and suffix.
-        if ( commonprefix ) {
-            diffs.unshift( [ DIFF_EQUAL, commonprefix ] );
-        }
-        if ( commonsuffix ) {
-            diffs.push( [ DIFF_EQUAL, commonsuffix ] );
-        }
-        this.diffCleanupMerge( diffs );
-        return diffs;
-    };
-
-    /**
-     * Reduce the number of edits by eliminating operationally trivial equalities.
-     * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
-     */
-    DiffMatchPatch.prototype.diffCleanupEfficiency = function( diffs ) {
-        var changes, equalities, equalitiesLength, lastequality,
-			pointer, preIns, preDel, postIns, postDel;
-        changes = false;
-        equalities = []; // Stack of indices where equalities are found.
-        equalitiesLength = 0; // Keeping our own length var is faster in JS.
-        /** @type {?string} */
-        lastequality = null;
-        // Always equal to diffs[equalities[equalitiesLength - 1]][1]
-        pointer = 0; // Index of current position.
-        // Is there an insertion operation before the last equality.
-        preIns = false;
-        // Is there a deletion operation before the last equality.
-        preDel = false;
-        // Is there an insertion operation after the last equality.
-        postIns = false;
-        // Is there a deletion operation after the last equality.
-        postDel = false;
-        while ( pointer < diffs.length ) {
-            if ( diffs[ pointer ][ 0 ] === DIFF_EQUAL ) { // Equality found.
-                if ( diffs[ pointer ][ 1 ].length < this.DiffEditCost && ( postIns || postDel ) ) {
-                    // Candidate found.
-                    equalities[ equalitiesLength++ ] = pointer;
-                    preIns = postIns;
-                    preDel = postDel;
-                    lastequality = diffs[ pointer ][ 1 ];
-                } else {
-                    // Not a candidate, and can never become one.
-                    equalitiesLength = 0;
-                    lastequality = null;
-                }
-                postIns = postDel = false;
-            } else { // An insertion or deletion.
-                if ( diffs[ pointer ][ 0 ] === DIFF_DELETE ) {
-                    postDel = true;
-                } else {
-                    postIns = true;
-                }
-                /*
-                 * Five types to be split:
-                 * <ins>A</ins><del>B</del>XY<ins>C</ins><del>D</del>
-                 * <ins>A</ins>X<ins>C</ins><del>D</del>
-                 * <ins>A</ins><del>B</del>X<ins>C</ins>
-                 * <ins>A</del>X<ins>C</ins><del>D</del>
-                 * <ins>A</ins><del>B</del>X<del>C</del>
-                 */
-                if ( lastequality && ( ( preIns && preDel && postIns && postDel ) ||
-                        ( ( lastequality.length < this.DiffEditCost / 2 ) &&
-                            ( preIns + preDel + postIns + postDel ) === 3 ) ) ) {
-                    // Duplicate record.
-                    diffs.splice( equalities[equalitiesLength - 1], 0, [ DIFF_DELETE, lastequality ] );
-                    // Change second copy to insert.
-                    diffs[ equalities[ equalitiesLength - 1 ] + 1 ][ 0 ] = DIFF_INSERT;
-                    equalitiesLength--; // Throw away the equality we just deleted;
-                    lastequality = null;
-                    if (preIns && preDel) {
-                        // No changes made which could affect previous entry, keep going.
-                        postIns = postDel = true;
-                        equalitiesLength = 0;
-                    } else {
-                        equalitiesLength--; // Throw away the previous equality.
-                        pointer = equalitiesLength > 0 ? equalities[ equalitiesLength - 1 ] : -1;
-                        postIns = postDel = false;
-                    }
-                    changes = true;
-                }
-            }
-            pointer++;
-        }
-
-        if ( changes ) {
-            this.diffCleanupMerge( diffs );
-        }
-    };
-
-    /**
-     * Convert a diff array into a pretty HTML report.
-     * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
-     * @param {integer} string to be beautified.
-     * @return {string} HTML representation.
-     */
-    DiffMatchPatch.prototype.diffPrettyHtml = function( diffs ) {
-        var op, data, x, html = [];
-        for ( x = 0; x < diffs.length; x++ ) {
-            op = diffs[x][0]; // Operation (insert, delete, equal)
-            data = diffs[x][1]; // Text of change.
-            switch ( op ) {
-                case DIFF_INSERT:
-                    html[x] = "<ins>" + data + "</ins>";
-                    break;
-                case DIFF_DELETE:
-                    html[x] = "<del>" + data + "</del>";
-                    break;
-                case DIFF_EQUAL:
-                    html[x] = "<span>" + data + "</span>";
-                    break;
-            }
-        }
-        return html.join("");
-    };
-
-    /**
-     * Determine the common prefix of two strings.
-     * @param {string} text1 First string.
-     * @param {string} text2 Second string.
-     * @return {number} The number of characters common to the start of each
-     *     string.
-     */
-    DiffMatchPatch.prototype.diffCommonPrefix = function( text1, text2 ) {
-        var pointermid, pointermax, pointermin, pointerstart;
-        // Quick check for common null cases.
-        if ( !text1 || !text2 || text1.charAt(0) !== text2.charAt(0) ) {
-            return 0;
-        }
-        // Binary search.
-        // Performance analysis: http://neil.fraser.name/news/2007/10/09/
-        pointermin = 0;
-        pointermax = Math.min( text1.length, text2.length );
-        pointermid = pointermax;
-        pointerstart = 0;
-        while ( pointermin < pointermid ) {
-            if ( text1.substring( pointerstart, pointermid ) === text2.substring( pointerstart, pointermid ) ) {
-                pointermin = pointermid;
-                pointerstart = pointermin;
-            } else {
-                pointermax = pointermid;
-            }
-            pointermid = Math.floor( ( pointermax - pointermin ) / 2 + pointermin );
-        }
-        return pointermid;
-    };
-
-    /**
-     * Determine the common suffix of two strings.
-     * @param {string} text1 First string.
-     * @param {string} text2 Second string.
-     * @return {number} The number of characters common to the end of each string.
-     */
-    DiffMatchPatch.prototype.diffCommonSuffix = function( text1, text2 ) {
-        var pointermid, pointermax, pointermin, pointerend;
-        // Quick check for common null cases.
-        if (!text1 || !text2 || text1.charAt(text1.length - 1) !== text2.charAt(text2.length - 1)) {
-            return 0;
-        }
-        // Binary search.
-        // Performance analysis: http://neil.fraser.name/news/2007/10/09/
-        pointermin = 0;
-        pointermax = Math.min(text1.length, text2.length);
-        pointermid = pointermax;
-        pointerend = 0;
-        while ( pointermin < pointermid ) {
-            if (text1.substring( text1.length - pointermid, text1.length - pointerend ) ===
-                text2.substring( text2.length - pointermid, text2.length - pointerend ) ) {
-                pointermin = pointermid;
-                pointerend = pointermin;
-            } else {
-                pointermax = pointermid;
-            }
-            pointermid = Math.floor( ( pointermax - pointermin ) / 2 + pointermin );
-        }
-        return pointermid;
-    };
-
-    /**
-     * Find the differences between two texts.  Assumes that the texts do not
-     * have any common prefix or suffix.
-     * @param {string} text1 Old string to be diffed.
-     * @param {string} text2 New string to be diffed.
-     * @param {boolean} checklines Speedup flag.  If false, then don't run a
-     *     line-level diff first to identify the changed areas.
-     *     If true, then run a faster, slightly less optimal diff.
-     * @param {number} deadline Time when the diff should be complete by.
-     * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
-     * @private
-     */
-    DiffMatchPatch.prototype.diffCompute = function( text1, text2, checklines, deadline ) {
-        var diffs, longtext, shorttext, i, hm,
-			text1A, text2A, text1B, text2B,
-			midCommon, diffsA, diffsB;
-
-        if ( !text1 ) {
-            // Just add some text (speedup).
-            return [
-                [ DIFF_INSERT, text2 ]
-            ];
-        }
-
-        if (!text2) {
-            // Just delete some text (speedup).
-            return [
-                [ DIFF_DELETE, text1 ]
-            ];
-        }
-
-        longtext = text1.length > text2.length ? text1 : text2;
-        shorttext = text1.length > text2.length ? text2 : text1;
-        i = longtext.indexOf( shorttext );
-        if ( i !== -1 ) {
-            // Shorter text is inside the longer text (speedup).
-            diffs = [
-                [ DIFF_INSERT, longtext.substring( 0, i ) ],
-                [ DIFF_EQUAL, shorttext ],
-                [ DIFF_INSERT, longtext.substring( i + shorttext.length ) ]
-            ];
-            // Swap insertions for deletions if diff is reversed.
-            if ( text1.length > text2.length ) {
-                diffs[0][0] = diffs[2][0] = DIFF_DELETE;
-            }
-            return diffs;
-        }
-
-        if ( shorttext.length === 1 ) {
-            // Single character string.
-            // After the previous speedup, the character can't be an equality.
-            return [
-                [ DIFF_DELETE, text1 ],
-                [ DIFF_INSERT, text2 ]
-            ];
-        }
-
-        // Check to see if the problem can be split in two.
-        hm = this.diffHalfMatch(text1, text2);
-        if (hm) {
-            // A half-match was found, sort out the return data.
-            text1A = hm[0];
-            text1B = hm[1];
-            text2A = hm[2];
-            text2B = hm[3];
-            midCommon = hm[4];
-            // Send both pairs off for separate processing.
-            diffsA = this.DiffMain(text1A, text2A, checklines, deadline);
-            diffsB = this.DiffMain(text1B, text2B, checklines, deadline);
-            // Merge the results.
-            return diffsA.concat([
-                [ DIFF_EQUAL, midCommon ]
-            ], diffsB);
-        }
-
-        if (checklines && text1.length > 100 && text2.length > 100) {
-            return this.diffLineMode(text1, text2, deadline);
-        }
-
-        return this.diffBisect(text1, text2, deadline);
-    };
-
-    /**
-     * Do the two texts share a substring which is at least half the length of the
-     * longer text?
-     * This speedup can produce non-minimal diffs.
-     * @param {string} text1 First string.
-     * @param {string} text2 Second string.
-     * @return {Array.<string>} Five element Array, containing the prefix of
-     *     text1, the suffix of text1, the prefix of text2, the suffix of
-     *     text2 and the common middle.  Or null if there was no match.
-     * @private
-     */
-    DiffMatchPatch.prototype.diffHalfMatch = function(text1, text2) {
-        var longtext, shorttext, dmp,
-			text1A, text2B, text2A, text1B, midCommon,
-			hm1, hm2, hm;
-        if (this.DiffTimeout <= 0) {
-            // Don't risk returning a non-optimal diff if we have unlimited time.
-            return null;
-        }
-        longtext = text1.length > text2.length ? text1 : text2;
-        shorttext = text1.length > text2.length ? text2 : text1;
-        if (longtext.length < 4 || shorttext.length * 2 < longtext.length) {
-            return null; // Pointless.
-        }
-        dmp = this; // 'this' becomes 'window' in a closure.
-
-        /**
-         * Does a substring of shorttext exist within longtext such that the substring
-         * is at least half the length of longtext?
-         * Closure, but does not reference any external variables.
-         * @param {string} longtext Longer string.
-         * @param {string} shorttext Shorter string.
-         * @param {number} i Start index of quarter length substring within longtext.
-         * @return {Array.<string>} Five element Array, containing the prefix of
-         *     longtext, the suffix of longtext, the prefix of shorttext, the suffix
-         *     of shorttext and the common middle.  Or null if there was no match.
-         * @private
-         */
-        function diffHalfMatchI(longtext, shorttext, i) {
-            var seed, j, bestCommon, prefixLength, suffixLength,
-				bestLongtextA, bestLongtextB, bestShorttextA, bestShorttextB;
-            // Start with a 1/4 length substring at position i as a seed.
-            seed = longtext.substring(i, i + Math.floor(longtext.length / 4));
-            j = -1;
-            bestCommon = "";
-            while ((j = shorttext.indexOf(seed, j + 1)) !== -1) {
-                prefixLength = dmp.diffCommonPrefix(longtext.substring(i),
-                    shorttext.substring(j));
-                suffixLength = dmp.diffCommonSuffix(longtext.substring(0, i),
-                    shorttext.substring(0, j));
-                if (bestCommon.length < suffixLength + prefixLength) {
-                    bestCommon = shorttext.substring(j - suffixLength, j) +
-                        shorttext.substring(j, j + prefixLength);
-                    bestLongtextA = longtext.substring(0, i - suffixLength);
-                    bestLongtextB = longtext.substring(i + prefixLength);
-                    bestShorttextA = shorttext.substring(0, j - suffixLength);
-                    bestShorttextB = shorttext.substring(j + prefixLength);
-                }
-            }
-            if (bestCommon.length * 2 >= longtext.length) {
-                return [ bestLongtextA, bestLongtextB,
-                    bestShorttextA, bestShorttextB, bestCommon
-                ];
-            } else {
-                return null;
-            }
-        }
-
-        // First check if the second quarter is the seed for a half-match.
-        hm1 = diffHalfMatchI(longtext, shorttext,
-            Math.ceil(longtext.length / 4));
-        // Check again based on the third quarter.
-        hm2 = diffHalfMatchI(longtext, shorttext,
-            Math.ceil(longtext.length / 2));
-        if (!hm1 && !hm2) {
-            return null;
-        } else if (!hm2) {
-            hm = hm1;
-        } else if (!hm1) {
-            hm = hm2;
-        } else {
-            // Both matched.  Select the longest.
-            hm = hm1[4].length > hm2[4].length ? hm1 : hm2;
-        }
-
-        // A half-match was found, sort out the return data.
-        text1A, text1B, text2A, text2B;
-        if (text1.length > text2.length) {
-            text1A = hm[0];
-            text1B = hm[1];
-            text2A = hm[2];
-            text2B = hm[3];
-        } else {
-            text2A = hm[0];
-            text2B = hm[1];
-            text1A = hm[2];
-            text1B = hm[3];
-        }
-        midCommon = hm[4];
-        return [ text1A, text1B, text2A, text2B, midCommon ];
-    };
-
-    /**
-     * Do a quick line-level diff on both strings, then rediff the parts for
-     * greater accuracy.
-     * This speedup can produce non-minimal diffs.
-     * @param {string} text1 Old string to be diffed.
-     * @param {string} text2 New string to be diffed.
-     * @param {number} deadline Time when the diff should be complete by.
-     * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
-     * @private
-     */
-    DiffMatchPatch.prototype.diffLineMode = function(text1, text2, deadline) {
-        var a, diffs, linearray, pointer, countInsert,
-			countDelete, textInsert, textDelete, j;
-        // Scan the text on a line-by-line basis first.
-        a = this.diffLinesToChars(text1, text2);
-        text1 = a.chars1;
-        text2 = a.chars2;
-        linearray = a.lineArray;
-
-        diffs = this.DiffMain(text1, text2, false, deadline);
-
-        // Convert the diff back to original text.
-        this.diffCharsToLines(diffs, linearray);
-        // Eliminate freak matches (e.g. blank lines)
-        this.diffCleanupSemantic(diffs);
-
-        // Rediff any replacement blocks, this time character-by-character.
-        // Add a dummy entry at the end.
-        diffs.push( [ DIFF_EQUAL, "" ] );
-        pointer = 0;
-        countDelete = 0;
-        countInsert = 0;
-        textDelete = "";
-        textInsert = "";
-        while (pointer < diffs.length) {
-            switch ( diffs[pointer][0] ) {
-                case DIFF_INSERT:
-                    countInsert++;
-                    textInsert += diffs[pointer][1];
-                    break;
-                case DIFF_DELETE:
-                    countDelete++;
-                    textDelete += diffs[pointer][1];
-                    break;
-                case DIFF_EQUAL:
-                    // Upon reaching an equality, check for prior redundancies.
-                    if (countDelete >= 1 && countInsert >= 1) {
-                        // Delete the offending records and add the merged ones.
-                        diffs.splice(pointer - countDelete - countInsert,
-                            countDelete + countInsert);
-                        pointer = pointer - countDelete - countInsert;
-                        a = this.DiffMain(textDelete, textInsert, false, deadline);
-                        for (j = a.length - 1; j >= 0; j--) {
-                            diffs.splice( pointer, 0, a[j] );
-                        }
-                        pointer = pointer + a.length;
-                    }
-                    countInsert = 0;
-                    countDelete = 0;
-                    textDelete = "";
-                    textInsert = "";
-                    break;
-            }
-            pointer++;
-        }
-        diffs.pop(); // Remove the dummy entry at the end.
-
-        return diffs;
-    };
-
-    /**
-     * Find the 'middle snake' of a diff, split the problem in two
-     * and return the recursively constructed diff.
-     * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations.
-     * @param {string} text1 Old string to be diffed.
-     * @param {string} text2 New string to be diffed.
-     * @param {number} deadline Time at which to bail if not yet complete.
-     * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
-     * @private
-     */
-    DiffMatchPatch.prototype.diffBisect = function(text1, text2, deadline) {
-        var text1Length, text2Length, maxD, vOffset, vLength,
-			v1, v2, x, delta, front, k1start, k1end, k2start,
-			k2end, k2Offset, k1Offset, x1, x2, y1, y2, d, k1, k2;
-        // Cache the text lengths to prevent multiple calls.
-        text1Length = text1.length;
-        text2Length = text2.length;
-        maxD = Math.ceil((text1Length + text2Length) / 2);
-        vOffset = maxD;
-        vLength = 2 * maxD;
-        v1 = new Array(vLength);
-        v2 = new Array(vLength);
-        // Setting all elements to -1 is faster in Chrome & Firefox than mixing
-        // integers and undefined.
-        for (x = 0; x < vLength; x++) {
-            v1[x] = -1;
-            v2[x] = -1;
-        }
-        v1[vOffset + 1] = 0;
-        v2[vOffset + 1] = 0;
-        delta = text1Length - text2Length;
-        // If the total number of characters is odd, then the front path will collide
-        // with the reverse path.
-        front = (delta % 2 !== 0);
-        // Offsets for start and end of k loop.
-        // Prevents mapping of space beyond the grid.
-        k1start = 0;
-        k1end = 0;
-        k2start = 0;
-        k2end = 0;
-        for (d = 0; d < maxD; d++) {
-            // Bail out if deadline is reached.
-            if ((new Date()).getTime() > deadline) {
-                break;
-            }
-
-            // Walk the front path one step.
-            for (k1 = -d + k1start; k1 <= d - k1end; k1 += 2) {
-                k1Offset = vOffset + k1;
-                if ( k1 === -d || ( k1 !== d && v1[ k1Offset - 1 ] < v1[ k1Offset + 1 ] ) ) {
-                    x1 = v1[k1Offset + 1];
-                } else {
-                    x1 = v1[k1Offset - 1] + 1;
-                }
-                y1 = x1 - k1;
-                while (x1 < text1Length && y1 < text2Length &&
-                    text1.charAt(x1) === text2.charAt(y1)) {
-                    x1++;
-                    y1++;
-                }
-                v1[k1Offset] = x1;
-                if (x1 > text1Length) {
-                    // Ran off the right of the graph.
-                    k1end += 2;
-                } else if (y1 > text2Length) {
-                    // Ran off the bottom of the graph.
-                    k1start += 2;
-                } else if (front) {
-                    k2Offset = vOffset + delta - k1;
-                    if (k2Offset >= 0 && k2Offset < vLength && v2[k2Offset] !== -1) {
-                        // Mirror x2 onto top-left coordinate system.
-                        x2 = text1Length - v2[k2Offset];
-                        if (x1 >= x2) {
-                            // Overlap detected.
-                            return this.diffBisectSplit(text1, text2, x1, y1, deadline);
-                        }
-                    }
-                }
-            }
-
-            // Walk the reverse path one step.
-            for (k2 = -d + k2start; k2 <= d - k2end; k2 += 2) {
-                k2Offset = vOffset + k2;
-                if ( k2 === -d || (k2 !== d && v2[ k2Offset - 1 ] < v2[ k2Offset + 1 ] ) ) {
-                    x2 = v2[k2Offset + 1];
-                } else {
-                    x2 = v2[k2Offset - 1] + 1;
-                }
-                y2 = x2 - k2;
-                while (x2 < text1Length && y2 < text2Length &&
-                    text1.charAt(text1Length - x2 - 1) ===
-                    text2.charAt(text2Length - y2 - 1)) {
-                    x2++;
-                    y2++;
-                }
-                v2[k2Offset] = x2;
-                if (x2 > text1Length) {
-                    // Ran off the left of the graph.
-                    k2end += 2;
-                } else if (y2 > text2Length) {
-                    // Ran off the top of the graph.
-                    k2start += 2;
-                } else if (!front) {
-                    k1Offset = vOffset + delta - k2;
-                    if (k1Offset >= 0 && k1Offset < vLength && v1[k1Offset] !== -1) {
-                        x1 = v1[k1Offset];
-                        y1 = vOffset + x1 - k1Offset;
-                        // Mirror x2 onto top-left coordinate system.
-                        x2 = text1Length - x2;
-                        if (x1 >= x2) {
-                            // Overlap detected.
-                            return this.diffBisectSplit(text1, text2, x1, y1, deadline);
-                        }
-                    }
-                }
-            }
-        }
-        // Diff took too long and hit the deadline or
-        // number of diffs equals number of characters, no commonality at all.
-        return [
-            [ DIFF_DELETE, text1 ],
-            [ DIFF_INSERT, text2 ]
-        ];
-    };
-
-    /**
-     * Given the location of the 'middle snake', split the diff in two parts
-     * and recurse.
-     * @param {string} text1 Old string to be diffed.
-     * @param {string} text2 New string to be diffed.
-     * @param {number} x Index of split point in text1.
-     * @param {number} y Index of split point in text2.
-     * @param {number} deadline Time at which to bail if not yet complete.
-     * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
-     * @private
-     */
-    DiffMatchPatch.prototype.diffBisectSplit = function( text1, text2, x, y, deadline ) {
-        var text1a, text1b, text2a, text2b, diffs, diffsb;
-        text1a = text1.substring(0, x);
-        text2a = text2.substring(0, y);
-        text1b = text1.substring(x);
-        text2b = text2.substring(y);
-
-        // Compute both diffs serially.
-        diffs = this.DiffMain(text1a, text2a, false, deadline);
-        diffsb = this.DiffMain(text1b, text2b, false, deadline);
-
-        return diffs.concat(diffsb);
-    };
-
-    /**
-     * Reduce the number of edits by eliminating semantically trivial equalities.
-     * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
-     */
-    DiffMatchPatch.prototype.diffCleanupSemantic = function(diffs) {
-        var changes, equalities, equalitiesLength, lastequality,
-			pointer, lengthInsertions2, lengthDeletions2, lengthInsertions1,
-			lengthDeletions1, deletion, insertion, overlapLength1, overlapLength2;
-        changes = false;
-        equalities = []; // Stack of indices where equalities are found.
-        equalitiesLength = 0; // Keeping our own length var is faster in JS.
-        /** @type {?string} */
-        lastequality = null;
-        // Always equal to diffs[equalities[equalitiesLength - 1]][1]
-        pointer = 0; // Index of current position.
-        // Number of characters that changed prior to the equality.
-        lengthInsertions1 = 0;
-        lengthDeletions1 = 0;
-        // Number of characters that changed after the equality.
-        lengthInsertions2 = 0;
-        lengthDeletions2 = 0;
-        while (pointer < diffs.length) {
-            if (diffs[pointer][0] === DIFF_EQUAL) { // Equality found.
-                equalities[equalitiesLength++] = pointer;
-                lengthInsertions1 = lengthInsertions2;
-                lengthDeletions1 = lengthDeletions2;
-                lengthInsertions2 = 0;
-                lengthDeletions2 = 0;
-                lastequality = diffs[pointer][1];
-            } else { // An insertion or deletion.
-                if (diffs[pointer][0] === DIFF_INSERT) {
-                    lengthInsertions2 += diffs[pointer][1].length;
-                } else {
-                    lengthDeletions2 += diffs[pointer][1].length;
-                }
-                // Eliminate an equality that is smaller or equal to the edits on both
-                // sides of it.
-                if (lastequality && (lastequality.length <=
-                        Math.max(lengthInsertions1, lengthDeletions1)) &&
-                    (lastequality.length <= Math.max(lengthInsertions2,
-                        lengthDeletions2))) {
-                    // Duplicate record.
-                    diffs.splice( equalities[ equalitiesLength - 1 ], 0, [ DIFF_DELETE, lastequality ] );
-                    // Change second copy to insert.
-                    diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;
-                    // Throw away the equality we just deleted.
-                    equalitiesLength--;
-                    // Throw away the previous equality (it needs to be reevaluated).
-                    equalitiesLength--;
-                    pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1;
-                    lengthInsertions1 = 0; // Reset the counters.
-                    lengthDeletions1 = 0;
-                    lengthInsertions2 = 0;
-                    lengthDeletions2 = 0;
-                    lastequality = null;
-                    changes = true;
-                }
-            }
-            pointer++;
-        }
-
-        // Normalize the diff.
-        if (changes) {
-            this.diffCleanupMerge(diffs);
-        }
-
-        // Find any overlaps between deletions and insertions.
-        // e.g: <del>abcxxx</del><ins>xxxdef</ins>
-        //   -> <del>abc</del>xxx<ins>def</ins>
-        // e.g: <del>xxxabc</del><ins>defxxx</ins>
-        //   -> <ins>def</ins>xxx<del>abc</del>
-        // Only extract an overlap if it is as big as the edit ahead or behind it.
-        pointer = 1;
-        while (pointer < diffs.length) {
-            if (diffs[pointer - 1][0] === DIFF_DELETE &&
-                diffs[pointer][0] === DIFF_INSERT) {
-                deletion = diffs[pointer - 1][1];
-                insertion = diffs[pointer][1];
-                overlapLength1 = this.diffCommonOverlap(deletion, insertion);
-                overlapLength2 = this.diffCommonOverlap(insertion, deletion);
-                if (overlapLength1 >= overlapLength2) {
-                    if (overlapLength1 >= deletion.length / 2 ||
-                        overlapLength1 >= insertion.length / 2) {
-                        // Overlap found.  Insert an equality and trim the surrounding edits.
-                        diffs.splice( pointer, 0, [ DIFF_EQUAL, insertion.substring( 0, overlapLength1 ) ] );
-                        diffs[pointer - 1][1] =
-                            deletion.substring(0, deletion.length - overlapLength1);
-                        diffs[pointer + 1][1] = insertion.substring(overlapLength1);
-                        pointer++;
-                    }
-                } else {
-                    if (overlapLength2 >= deletion.length / 2 ||
-                        overlapLength2 >= insertion.length / 2) {
-                        // Reverse overlap found.
-                        // Insert an equality and swap and trim the surrounding edits.
-                        diffs.splice( pointer, 0, [ DIFF_EQUAL, deletion.substring( 0, overlapLength2 ) ] );
-                        diffs[pointer - 1][0] = DIFF_INSERT;
-                        diffs[pointer - 1][1] =
-                            insertion.substring(0, insertion.length - overlapLength2);
-                        diffs[pointer + 1][0] = DIFF_DELETE;
-                        diffs[pointer + 1][1] =
-                            deletion.substring(overlapLength2);
-                        pointer++;
-                    }
-                }
-                pointer++;
-            }
-            pointer++;
-        }
-    };
-
-    /**
-     * Determine if the suffix of one string is the prefix of another.
-     * @param {string} text1 First string.
-     * @param {string} text2 Second string.
-     * @return {number} The number of characters common to the end of the first
-     *     string and the start of the second string.
-     * @private
-     */
-    DiffMatchPatch.prototype.diffCommonOverlap = function(text1, text2) {
-        var text1Length, text2Length, textLength,
-			best, length, pattern, found;
-        // Cache the text lengths to prevent multiple calls.
-        text1Length = text1.length;
-        text2Length = text2.length;
-        // Eliminate the null case.
-        if (text1Length === 0 || text2Length === 0) {
-            return 0;
-        }
-        // Truncate the longer string.
-        if (text1Length > text2Length) {
-            text1 = text1.substring(text1Length - text2Length);
-        } else if (text1Length < text2Length) {
-            text2 = text2.substring(0, text1Length);
-        }
-        textLength = Math.min(text1Length, text2Length);
-        // Quick check for the worst case.
-        if (text1 === text2) {
-            return textLength;
-        }
-
-        // Start by looking for a single character match
-        // and increase length until no match is found.
-        // Performance analysis: http://neil.fraser.name/news/2010/11/04/
-        best = 0;
-        length = 1;
-        while (true) {
-            pattern = text1.substring(textLength - length);
-            found = text2.indexOf(pattern);
-            if (found === -1) {
-                return best;
-            }
-            length += found;
-            if (found === 0 || text1.substring(textLength - length) ===
-                text2.substring(0, length)) {
-                best = length;
-                length++;
-            }
-        }
-    };
-
-    /**
-     * Split two texts into an array of strings.  Reduce the texts to a string of
-     * hashes where each Unicode character represents one line.
-     * @param {string} text1 First string.
-     * @param {string} text2 Second string.
-     * @return {{chars1: string, chars2: string, lineArray: !Array.<string>}}
-     *     An object containing the encoded text1, the encoded text2 and
-     *     the array of unique strings.
-     *     The zeroth element of the array of unique strings is intentionally blank.
-     * @private
-     */
-    DiffMatchPatch.prototype.diffLinesToChars = function(text1, text2) {
-        var lineArray, lineHash, chars1, chars2;
-        lineArray = []; // e.g. lineArray[4] === 'Hello\n'
-        lineHash = {}; // e.g. lineHash['Hello\n'] === 4
-
-        // '\x00' is a valid character, but various debuggers don't like it.
-        // So we'll insert a junk entry to avoid generating a null character.
-        lineArray[0] = "";
-
-        /**
-         * Split a text into an array of strings.  Reduce the texts to a string of
-         * hashes where each Unicode character represents one line.
-         * Modifies linearray and linehash through being a closure.
-         * @param {string} text String to encode.
-         * @return {string} Encoded string.
-         * @private
-         */
-        function diffLinesToCharsMunge(text) {
-            var chars, lineStart, lineEnd, lineArrayLength, line;
-            chars = "";
-            // Walk the text, pulling out a substring for each line.
-            // text.split('\n') would would temporarily double our memory footprint.
-            // Modifying text would create many large strings to garbage collect.
-            lineStart = 0;
-            lineEnd = -1;
-            // Keeping our own length variable is faster than looking it up.
-            lineArrayLength = lineArray.length;
-            while (lineEnd < text.length - 1) {
-                lineEnd = text.indexOf("\n", lineStart);
-                if (lineEnd === -1) {
-                    lineEnd = text.length - 1;
-                }
-                line = text.substring(lineStart, lineEnd + 1);
-                lineStart = lineEnd + 1;
-
-                if (lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) :
-                    (lineHash[line] !== undefined)) {
-                    chars += String.fromCharCode( lineHash[ line ] );
-                } else {
-                    chars += String.fromCharCode(lineArrayLength);
-                    lineHash[line] = lineArrayLength;
-                    lineArray[lineArrayLength++] = line;
-                }
-            }
-            return chars;
-        }
-
-        chars1 = diffLinesToCharsMunge(text1);
-        chars2 = diffLinesToCharsMunge(text2);
-        return {
-            chars1: chars1,
-            chars2: chars2,
-            lineArray: lineArray
-        };
-    };
-
-    /**
-     * Rehydrate the text in a diff from a string of line hashes to real lines of
-     * text.
-     * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
-     * @param {!Array.<string>} lineArray Array of unique strings.
-     * @private
-     */
-    DiffMatchPatch.prototype.diffCharsToLines = function( diffs, lineArray ) {
-        var x, chars, text, y;
-        for ( x = 0; x < diffs.length; x++ ) {
-            chars = diffs[x][1];
-            text = [];
-            for ( y = 0; y < chars.length; y++ ) {
-                text[y] = lineArray[chars.charCodeAt(y)];
-            }
-            diffs[x][1] = text.join("");
-        }
-    };
-
-    /**
-     * Reorder and merge like edit sections.  Merge equalities.
-     * Any edit section can move as long as it doesn't cross an equality.
-     * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
-     */
-    DiffMatchPatch.prototype.diffCleanupMerge = function(diffs) {
-        var pointer, countDelete, countInsert, textInsert, textDelete,
-			commonlength, changes;
-        diffs.push( [ DIFF_EQUAL, "" ] ); // Add a dummy entry at the end.
-        pointer = 0;
-        countDelete = 0;
-        countInsert = 0;
-        textDelete = "";
-        textInsert = "";
-        commonlength;
-        while (pointer < diffs.length) {
-            switch ( diffs[ pointer ][ 0 ] ) {
-                case DIFF_INSERT:
-                    countInsert++;
-                    textInsert += diffs[pointer][1];
-                    pointer++;
-                    break;
-                case DIFF_DELETE:
-                    countDelete++;
-                    textDelete += diffs[pointer][1];
-                    pointer++;
-                    break;
-                case DIFF_EQUAL:
-                    // Upon reaching an equality, check for prior redundancies.
-                    if (countDelete + countInsert > 1) {
-                        if (countDelete !== 0 && countInsert !== 0) {
-                            // Factor out any common prefixies.
-                            commonlength = this.diffCommonPrefix(textInsert, textDelete);
-                            if (commonlength !== 0) {
-                                if ((pointer - countDelete - countInsert) > 0 &&
-                                    diffs[pointer - countDelete - countInsert - 1][0] ===
-                                    DIFF_EQUAL) {
-                                    diffs[pointer - countDelete - countInsert - 1][1] +=
-                                        textInsert.substring(0, commonlength);
-                                } else {
-                                    diffs.splice( 0, 0, [ DIFF_EQUAL,
-                                        textInsert.substring( 0, commonlength )
-                                     ] );
-                                    pointer++;
-                                }
-                                textInsert = textInsert.substring(commonlength);
-                                textDelete = textDelete.substring(commonlength);
-                            }
-                            // Factor out any common suffixies.
-                            commonlength = this.diffCommonSuffix(textInsert, textDelete);
-                            if (commonlength !== 0) {
-                                diffs[pointer][1] = textInsert.substring(textInsert.length -
-                                    commonlength) + diffs[pointer][1];
-                                textInsert = textInsert.substring(0, textInsert.length -
-                                    commonlength);
-                                textDelete = textDelete.substring(0, textDelete.length -
-                                    commonlength);
-                            }
-                        }
-                        // Delete the offending records and add the merged ones.
-                        if (countDelete === 0) {
-                            diffs.splice( pointer - countInsert,
-                                countDelete + countInsert, [ DIFF_INSERT, textInsert ] );
-                        } else if (countInsert === 0) {
-                            diffs.splice( pointer - countDelete,
-                                countDelete + countInsert, [ DIFF_DELETE, textDelete ] );
-                        } else {
-                            diffs.splice( pointer - countDelete - countInsert,
-                                countDelete + countInsert, [ DIFF_DELETE, textDelete ], [ DIFF_INSERT, textInsert ] );
-                        }
-                        pointer = pointer - countDelete - countInsert +
-                            (countDelete ? 1 : 0) + (countInsert ? 1 : 0) + 1;
-                    } else if (pointer !== 0 && diffs[pointer - 1][0] === DIFF_EQUAL) {
-                        // Merge this equality with the previous one.
-                        diffs[pointer - 1][1] += diffs[pointer][1];
-                        diffs.splice(pointer, 1);
-                    } else {
-                        pointer++;
-                    }
-                    countInsert = 0;
-                    countDelete = 0;
-                    textDelete = "";
-                    textInsert = "";
-                    break;
-            }
-        }
-        if (diffs[diffs.length - 1][1] === "") {
-            diffs.pop(); // Remove the dummy entry at the end.
-        }
-
-        // Second pass: look for single edits surrounded on both sides by equalities
-        // which can be shifted sideways to eliminate an equality.
-        // e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC
-        changes = false;
-        pointer = 1;
-        // Intentionally ignore the first and last element (don't need checking).
-        while (pointer < diffs.length - 1) {
-            if (diffs[pointer - 1][0] === DIFF_EQUAL &&
-                diffs[pointer + 1][0] === DIFF_EQUAL) {
-                // This is a single edit surrounded by equalities.
-                if ( diffs[ pointer ][ 1 ].substring( diffs[ pointer ][ 1 ].length -
-                        diffs[ pointer - 1 ][ 1 ].length ) === diffs[ pointer - 1 ][ 1 ] ) {
-                    // Shift the edit over the previous equality.
-                    diffs[pointer][1] = diffs[pointer - 1][1] +
-                        diffs[pointer][1].substring(0, diffs[pointer][1].length -
-                            diffs[pointer - 1][1].length);
-                    diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1];
-                    diffs.splice(pointer - 1, 1);
-                    changes = true;
-                } else if ( diffs[ pointer ][ 1 ].substring( 0, diffs[ pointer + 1 ][ 1 ].length ) ===
-                    diffs[ pointer + 1 ][ 1 ] ) {
-                    // Shift the edit over the next equality.
-                    diffs[pointer - 1][1] += diffs[pointer + 1][1];
-                    diffs[pointer][1] =
-                        diffs[pointer][1].substring(diffs[pointer + 1][1].length) +
-                        diffs[pointer + 1][1];
-                    diffs.splice(pointer + 1, 1);
-                    changes = true;
-                }
-            }
-            pointer++;
-        }
-        // If shifts were made, the diff needs reordering and another shift sweep.
-        if (changes) {
-            this.diffCleanupMerge(diffs);
-        }
-    };
-
-    return function(o, n) {
-		var diff, output, text;
-        diff = new DiffMatchPatch();
-        output = diff.DiffMain(o, n);
-        //console.log(output);
-        diff.diffCleanupEfficiency(output);
-        text = diff.diffPrettyHtml(output);
-
-        return text;
-    };
-}());
-// jscs:enable
-
-(function() {
-
-// Deprecated QUnit.init - Ref #530
-// Re-initialize the configuration options
-QUnit.init = function() {
-	var tests, banner, result, qunit,
-		config = QUnit.config;
-
-	config.stats = { all: 0, bad: 0 };
-	config.moduleStats = { all: 0, bad: 0 };
-	config.started = 0;
-	config.updateRate = 1000;
-	config.blocking = false;
-	config.autostart = true;
-	config.autorun = false;
-	config.filter = "";
-	config.queue = [];
-
-	// Return on non-browser environments
-	// This is necessary to not break on node tests
-	if ( typeof window === "undefined" ) {
-		return;
-	}
-
-	qunit = id( "qunit" );
-	if ( qunit ) {
-		qunit.innerHTML =
-			"<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
-			"<h2 id='qunit-banner'></h2>" +
-			"<div id='qunit-testrunner-toolbar'></div>" +
-			"<h2 id='qunit-userAgent'></h2>" +
-			"<ol id='qunit-tests'></ol>";
-	}
-
-	tests = id( "qunit-tests" );
-	banner = id( "qunit-banner" );
-	result = id( "qunit-testresult" );
-
-	if ( tests ) {
-		tests.innerHTML = "";
-	}
-
-	if ( banner ) {
-		banner.className = "";
-	}
-
-	if ( result ) {
-		result.parentNode.removeChild( result );
-	}
-
-	if ( tests ) {
-		result = document.createElement( "p" );
-		result.id = "qunit-testresult";
-		result.className = "result";
-		tests.parentNode.insertBefore( result, tests );
-		result.innerHTML = "Running...<br />&#160;";
-	}
-};
-
-// Don't load the HTML Reporter on non-Browser environments
-if ( typeof window === "undefined" ) {
-	return;
-}
-
-var config = QUnit.config,
-	hasOwn = Object.prototype.hasOwnProperty,
-	defined = {
-		document: window.document !== undefined,
-		sessionStorage: (function() {
-			var x = "qunit-test-string";
-			try {
-				sessionStorage.setItem( x, x );
-				sessionStorage.removeItem( x );
-				return true;
-			} catch ( e ) {
-				return false;
-			}
-		}())
-	},
-	modulesList = [];
-
-/**
-* Escape text for attribute or text content.
-*/
-function escapeText( s ) {
-	if ( !s ) {
-		return "";
-	}
-	s = s + "";
-
-	// Both single quotes and double quotes (for attributes)
-	return s.replace( /['"<>&]/g, function( s ) {
-		switch ( s ) {
-		case "'":
-			return "&#039;";
-		case "\"":
-			return "&quot;";
-		case "<":
-			return "&lt;";
-		case ">":
-			return "&gt;";
-		case "&":
-			return "&amp;";
-		}
-	});
-}
-
-/**
- * @param {HTMLElement} elem
- * @param {string} type
- * @param {Function} fn
- */
-function addEvent( elem, type, fn ) {
-	if ( elem.addEventListener ) {
-
-		// Standards-based browsers
-		elem.addEventListener( type, fn, false );
-	} else if ( elem.attachEvent ) {
-
-		// support: IE <9
-		elem.attachEvent( "on" + type, function() {
-			var event = window.event;
-			if ( !event.target ) {
-				event.target = event.srcElement || document;
-			}
-
-			fn.call( elem, event );
-		});
-	}
-}
-
-/**
- * @param {Array|NodeList} elems
- * @param {string} type
- * @param {Function} fn
- */
-function addEvents( elems, type, fn ) {
-	var i = elems.length;
-	while ( i-- ) {
-		addEvent( elems[ i ], type, fn );
-	}
-}
-
-function hasClass( elem, name ) {
-	return ( " " + elem.className + " " ).indexOf( " " + name + " " ) >= 0;
-}
-
-function addClass( elem, name ) {
-	if ( !hasClass( elem, name ) ) {
-		elem.className += ( elem.className ? " " : "" ) + name;
-	}
-}
-
-function toggleClass( elem, name ) {
-	if ( hasClass( elem, name ) ) {
-		removeClass( elem, name );
-	} else {
-		addClass( elem, name );
-	}
-}
-
-function removeClass( elem, name ) {
-	var set = " " + elem.className + " ";
-
-	// Class name may appear multiple times
-	while ( set.indexOf( " " + name + " " ) >= 0 ) {
-		set = set.replace( " " + name + " ", " " );
-	}
-
-	// trim for prettiness
-	elem.className = typeof set.trim === "function" ? set.trim() : set.replace( /^\s+|\s+$/g, "" );
-}
-
-function id( name ) {
-	return defined.document && document.getElementById && document.getElementById( name );
-}
-
-function getUrlConfigHtml() {
-	var i, j, val,
-		escaped, escapedTooltip,
-		selection = false,
-		len = config.urlConfig.length,
-		urlConfigHtml = "";
-
-	for ( i = 0; i < len; i++ ) {
-		val = config.urlConfig[ i ];
-		if ( typeof val === "string" ) {
-			val = {
-				id: val,
-				label: val
-			};
-		}
-
-		escaped = escapeText( val.id );
-		escapedTooltip = escapeText( val.tooltip );
-
-		if ( config[ val.id ] === undefined ) {
-			config[ val.id ] = QUnit.urlParams[ val.id ];
-		}
-
-		if ( !val.value || typeof val.value === "string" ) {
-			urlConfigHtml += "<input id='qunit-urlconfig-" + escaped +
-				"' name='" + escaped + "' type='checkbox'" +
-				( val.value ? " value='" + escapeText( val.value ) + "'" : "" ) +
-				( config[ val.id ] ? " checked='checked'" : "" ) +
-				" title='" + escapedTooltip + "' /><label for='qunit-urlconfig-" + escaped +
-				"' title='" + escapedTooltip + "'>" + val.label + "</label>";
-		} else {
-			urlConfigHtml += "<label for='qunit-urlconfig-" + escaped +
-				"' title='" + escapedTooltip + "'>" + val.label +
-				": </label><select id='qunit-urlconfig-" + escaped +
-				"' name='" + escaped + "' title='" + escapedTooltip + "'><option></option>";
-
-			if ( QUnit.is( "array", val.value ) ) {
-				for ( j = 0; j < val.value.length; j++ ) {
-					escaped = escapeText( val.value[ j ] );
-					urlConfigHtml += "<option value='" + escaped + "'" +
-						( config[ val.id ] === val.value[ j ] ?
-							( selection = true ) && " selected='selected'" : "" ) +
-						">" + escaped + "</option>";
-				}
-			} else {
-				for ( j in val.value ) {
-					if ( hasOwn.call( val.value, j ) ) {
-						urlConfigHtml += "<option value='" + escapeText( j ) + "'" +
-							( config[ val.id ] === j ?
-								( selection = true ) && " selected='selected'" : "" ) +
-							">" + escapeText( val.value[ j ] ) + "</option>";
-					}
-				}
-			}
-			if ( config[ val.id ] && !selection ) {
-				escaped = escapeText( config[ val.id ] );
-				urlConfigHtml += "<option value='" + escaped +
-					"' selected='selected' disabled='disabled'>" + escaped + "</option>";
-			}
-			urlConfigHtml += "</select>";
-		}
-	}
-
-	return urlConfigHtml;
-}
-
-// Handle "click" events on toolbar checkboxes and "change" for select menus.
-// Updates the URL with the new state of `config.urlConfig` values.
-function toolbarChanged() {
-	var updatedUrl, value,
-		field = this,
-		params = {};
-
-	// Detect if field is a select menu or a checkbox
-	if ( "selectedIndex" in field ) {
-		value = field.options[ field.selectedIndex ].value || undefined;
-	} else {
-		value = field.checked ? ( field.defaultValue || true ) : undefined;
-	}
-
-	params[ field.name ] = value;
-	updatedUrl = setUrl( params );
-
-	if ( "hidepassed" === field.name && "replaceState" in window.history ) {
-		config[ field.name ] = value || false;
-		if ( value ) {
-			addClass( id( "qunit-tests" ), "hidepass" );
-		} else {
-			removeClass( id( "qunit-tests" ), "hidepass" );
-		}
-
-		// It is not necessary to refresh the whole page
-		window.history.replaceState( null, "", updatedUrl );
-	} else {
-		window.location = updatedUrl;
-	}
-}
-
-function setUrl( params ) {
-	var key,
-		querystring = "?";
-
-	params = QUnit.extend( QUnit.extend( {}, QUnit.urlParams ), params );
-
-	for ( key in params ) {
-		if ( hasOwn.call( params, key ) ) {
-			if ( params[ key ] === undefined ) {
-				continue;
-			}
-			querystring += encodeURIComponent( key );
-			if ( params[ key ] !== true ) {
-				querystring += "=" + encodeURIComponent( params[ key ] );
-			}
-			querystring += "&";
-		}
-	}
-	return location.protocol + "//" + location.host +
-		location.pathname + querystring.slice( 0, -1 );
-}
-
-function applyUrlParams() {
-	var selectedModule,
-		modulesList = id( "qunit-modulefilter" ),
-		filter = id( "qunit-filter-input" ).value;
-
-	selectedModule = modulesList ?
-		decodeURIComponent( modulesList.options[ modulesList.selectedIndex ].value ) :
-		undefined;
-
-	window.location = setUrl({
-		module: ( selectedModule === "" ) ? undefined : selectedModule,
-		filter: ( filter === "" ) ? undefined : filter,
-
-		// Remove testId filter
-		testId: undefined
-	});
-}
-
-function toolbarUrlConfigContainer() {
-	var urlConfigContainer = document.createElement( "span" );
-
-	urlConfigContainer.innerHTML = getUrlConfigHtml();
-	addClass( urlConfigContainer, "qunit-url-config" );
-
-	// For oldIE support:
-	// * Add handlers to the individual elements instead of the container
-	// * Use "click" instead of "change" for checkboxes
-	addEvents( urlConfigContainer.getElementsByTagName( "input" ), "click", toolbarChanged );
-	addEvents( urlConfigContainer.getElementsByTagName( "select" ), "change", toolbarChanged );
-
-	return urlConfigContainer;
-}
-
-function toolbarLooseFilter() {
-	var filter = document.createElement( "form" ),
-		label = document.createElement( "label" ),
-		input = document.createElement( "input" ),
-		button = document.createElement( "button" );
-
-	addClass( filter, "qunit-filter" );
-
-	label.innerHTML = "Filter: ";
-
-	input.type = "text";
-	input.value = config.filter || "";
-	input.name = "filter";
-	input.id = "qunit-filter-input";
-
-	button.innerHTML = "Go";
-
-	label.appendChild( input );
-
-	filter.appendChild( label );
-	filter.appendChild( button );
-	addEvent( filter, "submit", function( ev ) {
-		applyUrlParams();
-
-		if ( ev && ev.preventDefault ) {
-			ev.preventDefault();
-		}
-
-		return false;
-	});
-
-	return filter;
-}
-
-function toolbarModuleFilterHtml() {
-	var i,
-		moduleFilterHtml = "";
-
-	if ( !modulesList.length ) {
-		return false;
-	}
-
-	modulesList.sort(function( a, b ) {
-		return a.localeCompare( b );
-	});
-
-	moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label>" +
-		"<select id='qunit-modulefilter' name='modulefilter'><option value='' " +
-		( QUnit.urlParams.module === undefined ? "selected='selected'" : "" ) +
-		">< All Modules ></option>";
-
-	for ( i = 0; i < modulesList.length; i++ ) {
-		moduleFilterHtml += "<option value='" +
-			escapeText( encodeURIComponent( modulesList[ i ] ) ) + "' " +
-			( QUnit.urlParams.module === modulesList[ i ] ? "selected='selected'" : "" ) +
-			">" + escapeText( modulesList[ i ] ) + "</option>";
-	}
-	moduleFilterHtml += "</select>";
-
-	return moduleFilterHtml;
-}
-
-function toolbarModuleFilter() {
-	var toolbar = id( "qunit-testrunner-toolbar" ),
-		moduleFilter = document.createElement( "span" ),
-		moduleFilterHtml = toolbarModuleFilterHtml();
-
-	if ( !toolbar || !moduleFilterHtml ) {
-		return false;
-	}
-
-	moduleFilter.setAttribute( "id", "qunit-modulefilter-container" );
-	moduleFilter.innerHTML = moduleFilterHtml;
-
-	addEvent( moduleFilter.lastChild, "change", applyUrlParams );
-
-	toolbar.appendChild( moduleFilter );
-}
-
-function appendToolbar() {
-	var toolbar = id( "qunit-testrunner-toolbar" );
-
-	if ( toolbar ) {
-		toolbar.appendChild( toolbarUrlConfigContainer() );
-		toolbar.appendChild( toolbarLooseFilter() );
-	}
-}
-
-function appendHeader() {
-	var header = id( "qunit-header" );
-
-	if ( header ) {
-		header.innerHTML = "<a href='" +
-			setUrl({ filter: undefined, module: undefined, testId: undefined }) +
-			"'>" + header.innerHTML + "</a> ";
-	}
-}
-
-function appendBanner() {
-	var banner = id( "qunit-banner" );
-
-	if ( banner ) {
-		banner.className = "";
-	}
-}
-
-function appendTestResults() {
-	var tests = id( "qunit-tests" ),
-		result = id( "qunit-testresult" );
-
-	if ( result ) {
-		result.parentNode.removeChild( result );
-	}
-
-	if ( tests ) {
-		tests.innerHTML = "";
-		result = document.createElement( "p" );
-		result.id = "qunit-testresult";
-		result.className = "result";
-		tests.parentNode.insertBefore( result, tests );
-		result.innerHTML = "Running...<br />&#160;";
-	}
-}
-
-function storeFixture() {
-	var fixture = id( "qunit-fixture" );
-	if ( fixture ) {
-		config.fixture = fixture.innerHTML;
-	}
-}
-
-function appendUserAgent() {
-	var userAgent = id( "qunit-userAgent" );
-
-	if ( userAgent ) {
-		userAgent.innerHTML = "";
-		userAgent.appendChild(
-			document.createTextNode(
-				"QUnit " + QUnit.version  + "; " + navigator.userAgent
-			)
-		);
-	}
-}
-
-function appendTestsList( modules ) {
-	var i, l, x, z, test, moduleObj;
-
-	for ( i = 0, l = modules.length; i < l; i++ ) {
-		moduleObj = modules[ i ];
-
-		if ( moduleObj.name ) {
-			modulesList.push( moduleObj.name );
-		}
-
-		for ( x = 0, z = moduleObj.tests.length; x < z; x++ ) {
-			test = moduleObj.tests[ x ];
-
-			appendTest( test.name, test.testId, moduleObj.name );
-		}
-	}
-}
-
-function appendTest( name, testId, moduleName ) {
-	var title, rerunTrigger, testBlock, assertList,
-		tests = id( "qunit-tests" );
-
-	if ( !tests ) {
-		return;
-	}
-
-	title = document.createElement( "strong" );
-	title.innerHTML = getNameHtml( name, moduleName );
-
-	rerunTrigger = document.createElement( "a" );
-	rerunTrigger.innerHTML = "Rerun";
-	rerunTrigger.href = setUrl({ testId: testId });
-
-	testBlock = document.createElement( "li" );
-	testBlock.appendChild( title );
-	testBlock.appendChild( rerunTrigger );
-	testBlock.id = "qunit-test-output-" + testId;
-
-	assertList = document.createElement( "ol" );
-	assertList.className = "qunit-assert-list";
-
-	testBlock.appendChild( assertList );
-
-	tests.appendChild( testBlock );
-}
-
-// HTML Reporter initialization and load
-QUnit.begin(function( details ) {
-	var qunit = id( "qunit" );
-
-	// Fixture is the only one necessary to run without the #qunit element
-	storeFixture();
-
-	if ( qunit ) {
-		qunit.innerHTML =
-			"<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
-			"<h2 id='qunit-banner'></h2>" +
-			"<div id='qunit-testrunner-toolbar'></div>" +
-			"<h2 id='qunit-userAgent'></h2>" +
-			"<ol id='qunit-tests'></ol>";
-	}
-
-	appendHeader();
-	appendBanner();
-	appendTestResults();
-	appendUserAgent();
-	appendToolbar();
-	appendTestsList( details.modules );
-	toolbarModuleFilter();
-
-	if ( qunit && config.hidepassed ) {
-		addClass( qunit.lastChild, "hidepass" );
-	}
-});
-
-QUnit.done(function( details ) {
-	var i, key,
-		banner = id( "qunit-banner" ),
-		tests = id( "qunit-tests" ),
-		html = [
-			"Tests completed in ",
-			details.runtime,
-			" milliseconds.<br />",
-			"<span class='passed'>",
-			details.passed,
-			"</span> assertions of <span class='total'>",
-			details.total,
-			"</span> passed, <span class='failed'>",
-			details.failed,
-			"</span> failed."
-		].join( "" );
-
-	if ( banner ) {
-		banner.className = details.failed ? "qunit-fail" : "qunit-pass";
-	}
-
-	if ( tests ) {
-		id( "qunit-testresult" ).innerHTML = html;
-	}
-
-	if ( config.altertitle && defined.document && document.title ) {
-
-		// show ✖ for good, ✔ for bad suite result in title
-		// use escape sequences in case file gets loaded with non-utf-8-charset
-		document.title = [
-			( details.failed ? "\u2716" : "\u2714" ),
-			document.title.replace( /^[\u2714\u2716] /i, "" )
-		].join( " " );
-	}
-
-	// clear own sessionStorage items if all tests passed
-	if ( config.reorder && defined.sessionStorage && details.failed === 0 ) {
-		for ( i = 0; i < sessionStorage.length; i++ ) {
-			key = sessionStorage.key( i++ );
-			if ( key.indexOf( "qunit-test-" ) === 0 ) {
-				sessionStorage.removeItem( key );
-			}
-		}
-	}
-
-	// scroll back to top to show results
-	if ( config.scrolltop && window.scrollTo ) {
-		window.scrollTo( 0, 0 );
-	}
-});
-
-function getNameHtml( name, module ) {
-	var nameHtml = "";
-
-	if ( module ) {
-		nameHtml = "<span class='module-name'>" + escapeText( module ) + "</span>: ";
-	}
-
-	nameHtml += "<span class='test-name'>" + escapeText( name ) + "</span>";
-
-	return nameHtml;
-}
-
-QUnit.testStart(function( details ) {
-	var running, testBlock, bad;
-
-	testBlock = id( "qunit-test-output-" + details.testId );
-	if ( testBlock ) {
-		testBlock.className = "running";
-	} else {
-
-		// Report later registered tests
-		appendTest( details.name, details.testId, details.module );
-	}
-
-	running = id( "qunit-testresult" );
-	if ( running ) {
-		bad = QUnit.config.reorder && defined.sessionStorage &&
-			+sessionStorage.getItem( "qunit-test-" + details.module + "-" + details.name );
-
-		running.innerHTML = ( bad ?
-			"Rerunning previously failed test: <br />" :
-			"Running: <br />" ) +
-			getNameHtml( details.name, details.module );
-	}
-
-});
-
-QUnit.log(function( details ) {
-	var assertList, assertLi,
-		message, expected, actual,
-		testItem = id( "qunit-test-output-" + details.testId );
-
-	if ( !testItem ) {
-		return;
-	}
-
-	message = escapeText( details.message ) || ( details.result ? "okay" : "failed" );
-	message = "<span class='test-message'>" + message + "</span>";
-	message += "<span class='runtime'>@ " + details.runtime + " ms</span>";
-
-	// pushFailure doesn't provide details.expected
-	// when it calls, it's implicit to also not show expected and diff stuff
-	// Also, we need to check details.expected existence, as it can exist and be undefined
-	if ( !details.result && hasOwn.call( details, "expected" ) ) {
-		expected = escapeText( QUnit.dump.parse( details.expected ) );
-		actual = escapeText( QUnit.dump.parse( details.actual ) );
-		message += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" +
-			expected +
-			"</pre></td></tr>";
-
-		if ( actual !== expected ) {
-			message += "<tr class='test-actual'><th>Result: </th><td><pre>" +
-				actual + "</pre></td></tr>" +
-				"<tr class='test-diff'><th>Diff: </th><td><pre>" +
-				QUnit.diff( expected, actual ) + "</pre></td></tr>";
-		} else {
-			if ( expected.indexOf( "[object Array]" ) !== -1 ||
-					expected.indexOf( "[object Object]" ) !== -1 ) {
-				message += "<tr class='test-message'><th>Message: </th><td>" +
-					"Diff suppressed as the depth of object is more than current max depth (" +
-					QUnit.config.maxDepth + ").<p>Hint: Use <code>QUnit.dump.maxDepth</code> to " +
-					" run with a higher max depth or <a href='" + setUrl({ maxDepth: -1 }) + "'>" +
-					"Rerun</a> without max depth.</p></td></tr>";
-			}
-		}
-
-		if ( details.source ) {
-			message += "<tr class='test-source'><th>Source: </th><td><pre>" +
-				escapeText( details.source ) + "</pre></td></tr>";
-		}
-
-		message += "</table>";
-
-	// this occours when pushFailure is set and we have an extracted stack trace
-	} else if ( !details.result && details.source ) {
-		message += "<table>" +
-			"<tr class='test-source'><th>Source: </th><td><pre>" +
-			escapeText( details.source ) + "</pre></td></tr>" +
-			"</table>";
-	}
-
-	assertList = testItem.getElementsByTagName( "ol" )[ 0 ];
-
-	assertLi = document.createElement( "li" );
-	assertLi.className = details.result ? "pass" : "fail";
-	assertLi.innerHTML = message;
-	assertList.appendChild( assertLi );
-});
-
-QUnit.testDone(function( details ) {
-	var testTitle, time, testItem, assertList,
-		good, bad, testCounts, skipped,
-		tests = id( "qunit-tests" );
-
-	if ( !tests ) {
-		return;
-	}
-
-	testItem = id( "qunit-test-output-" + details.testId );
-
-	assertList = testItem.getElementsByTagName( "ol" )[ 0 ];
-
-	good = details.passed;
-	bad = details.failed;
-
-	// store result when possible
-	if ( config.reorder && defined.sessionStorage ) {
-		if ( bad ) {
-			sessionStorage.setItem( "qunit-test-" + details.module + "-" + details.name, bad );
-		} else {
-			sessionStorage.removeItem( "qunit-test-" + details.module + "-" + details.name );
-		}
-	}
-
-	if ( bad === 0 ) {
-		addClass( assertList, "qunit-collapsed" );
-	}
-
-	// testItem.firstChild is the test name
-	testTitle = testItem.firstChild;
-
-	testCounts = bad ?
-		"<b class='failed'>" + bad + "</b>, " + "<b class='passed'>" + good + "</b>, " :
-		"";
-
-	testTitle.innerHTML += " <b class='counts'>(" + testCounts +
-		details.assertions.length + ")</b>";
-
-	if ( details.skipped ) {
-		testItem.className = "skipped";
-		skipped = document.createElement( "em" );
-		skipped.className = "qunit-skipped-label";
-		skipped.innerHTML = "skipped";
-		testItem.insertBefore( skipped, testTitle );
-	} else {
-		addEvent( testTitle, "click", function() {
-			toggleClass( assertList, "qunit-collapsed" );
-		});
-
-		testItem.className = bad ? "fail" : "pass";
-
-		time = document.createElement( "span" );
-		time.className = "runtime";
-		time.innerHTML = details.runtime + " ms";
-		testItem.insertBefore( time, assertList );
-	}
-});
-
-if ( defined.document ) {
-	if ( document.readyState === "complete" ) {
-		QUnit.load();
-	} else {
-		addEvent( window, "load", QUnit.load );
-	}
-} else {
-	config.pageLoaded = true;
-	config.autorun = true;
-}
-
-})();
--- a/modules/org.openbravo.client.myob/src/org/openbravo/client/myob/MyOpenbravoComponentProvider.java	Mon Nov 18 16:08:25 2019 +0100
+++ b/modules/org.openbravo.client.myob/src/org/openbravo/client/myob/MyOpenbravoComponentProvider.java	Tue Nov 19 17:40:39 2019 +0100
@@ -103,11 +103,4 @@
 
     return globalResources;
   }
-
-  @Override
-  public List<String> getTestResources() {
-    final List<String> testResources = new ArrayList<String>();
-    testResources.add("web/org.openbravo.client.myob/js/test/ob-myopenbravo-test.js");
-    return testResources;
-  }
 }
--- a/modules/org.openbravo.client.myob/web/org.openbravo.client.myob/js/test/ob-myopenbravo-test.js	Mon Nov 18 16:08:25 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-/*
- *************************************************************************
- * The contents of this file are subject to the Openbravo  Public  License
- * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
- * Version 1.1  with a permitted attribution clause; you may not  use this
- * file except in compliance with the License. You  may  obtain  a copy of
- * the License at http://www.openbravo.com/legal/license.html
- * Software distributed under the License  is  distributed  on  an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
- * License for the specific  language  governing  rights  and  limitations
- * under the License.
- * The Original Code is Openbravo ERP.
- * The Initial Developer of the Original Code is Openbravo SLU
- * All portions are Copyright (C) 2010-2019 Openbravo SLU
- * All Rights Reserved.
- * Contributor(s):  ______________________________________.
- ************************************************************************
- */
-
-/*global QUnit */
-
-QUnit.module('org.openbravo.client.myob');
-
-var d = {
-  eventType: '',
-  context: {
-    adminMode: false
-  }
-};
-
-OB.MyOB = OB.MyOB || {};
-
-function reloadWidgetsBeforeTest(callback) {
-  var post = isc.addProperties({}, d, {
-    eventType: 'RELOAD_WIDGETS',
-    widgets: []
-  });
-  OB.RemoteCallManager.call(
-    'org.openbravo.client.myob.MyOpenbravoActionHandler',
-    post,
-    {},
-    function(rpcResponse, data, rpcRequest) {
-      OB.MyOB.widgets = data && data.widgets;
-
-      callback(data);
-    }
-  );
-}
-
-function checkMissingDbInstanceId(w) {
-  var i,
-    widgets = w || OB.MyOB.widgets;
-  for (i = 0; i < widgets.length; i++) {
-    if (!widgets[i].dbInstanceId) {
-      // empty string is 'falsy'
-      return true;
-    }
-  }
-  return false;
-}
-
-QUnit.asyncTest('Add widget', function() {
-  QUnit.expect(2);
-  reloadWidgetsBeforeTest(function(data) {
-    var post = isc.addProperties({}, d, {
-        eventType: 'WIDGET_ADDED',
-        widgets: OB.MyOB.widgets
-      }),
-      widget = isc.addProperties({}, OB.MyOB.widgets[0]);
-
-    widget.rowNum += 1;
-    widget.dbInstanceId = '';
-
-    OB.MyOB.widgets.push(widget);
-    OB.RemoteCallManager.call(
-      'org.openbravo.client.myob.MyOpenbravoActionHandler',
-      post,
-      {},
-      function(rpcResponse, data, rpcRequest) {
-        QUnit.strictEqual(data.message.type, 'Success', 'Widget added');
-
-        OB.MyOB.widgets =
-          data && data.widgets ? eval(data.widgets) : OB.MyOB.widgets; // refreshing widgets
-        QUnit.ok(
-          !checkMissingDbInstanceId(),
-          'All widgets have a dbInstanceId'
-        );
-
-        QUnit.start(); // restart the flow
-      }
-    );
-  });
-});
-
-// skipping this test because it is unstable depending on factors like
-// instance type (community/professional), number of executions, etc.
-// TODO: fix it properly to make it stable
-QUnit.skip('Move widget', function() {
-  var post = isc.addProperties({}, d, {
-      eventType: 'WIDGET_MOVED',
-      widgets: OB.MyOB.widgets
-    }),
-    tmp = {
-      colNum: 0,
-      rowNum: 0
-    },
-    w1 = OB.MyOB.widgets[0],
-    w2 = OB.MyOB.widgets[1];
-
-  if (!w1 || !w2) {
-    QUnit.ok(true);
-    QUnit.start(); // skip the test
-    return;
-  }
-
-  QUnit.expect(3);
-
-  tmp.colNum = w1.colNum;
-  tmp.rowNum = w1.rowNum;
-  w1.colNum = w2.colNum;
-  w1.rowNum = w2.colNum;
-  w2.colNum = tmp.colNum;
-  w2.rowNum = tmp.rowNum;
-
-  QUnit.ok(
-    !checkMissingDbInstanceId(post.widgets),
-    'All posted widgets have a dbInstanceId'
-  );
-
-  OB.RemoteCallManager.call(
-    'org.openbravo.client.myob.MyOpenbravoActionHandler',
-    post,
-    {},
-    function(rpcResponse, data, rpcRequest) {
-      QUnit.strictEqual(data.message.type, 'Success', 'Widget moved');
-
-      OB.MyOB.widgets =
-        data && data.widgets ? eval(data.widgets) : OB.MyOB.widgets; // refreshing widgets
-      QUnit.ok(!checkMissingDbInstanceId(), 'All widgets have a dbInstanceId');
-
-      QUnit.start(); // restart the flow
-    }
-  );
-});
-
-QUnit.asyncTest('Remove widget', function() {
-  QUnit.expect(2);
-  reloadWidgetsBeforeTest(function(data) {
-    var post = isc.addProperties({}, d, {
-      eventType: 'WIDGET_REMOVED',
-      widgets: OB.MyOB.widgets
-    });
-
-    OB.MyOB.widgets.splice(-1, 1);
-
-    OB.RemoteCallManager.call(
-      'org.openbravo.client.myob.MyOpenbravoActionHandler',
-      post,
-      {},
-      function(rpcResponse, data, rpcRequest) {
-        QUnit.strictEqual(data.message.type, 'Success', 'Widget removed');
-
-        OB.MyOB.widgets =
-          data && data.widgets ? eval(data.widgets) : OB.MyOB.widgets; // refreshing widgets
-        QUnit.ok(
-          !checkMissingDbInstanceId(),
-          'All widgets have a dbInstanceId'
-        );
-
-        QUnit.start(); // restart the flow
-      }
-    );
-  });
-});
-
-QUnit.asyncTest('Get user widgets', function() {
-  QUnit.expect(2);
-  reloadWidgetsBeforeTest(function(data) {
-    QUnit.strictEqual(data.message.type, 'Success', 'Widgets reloaded');
-
-    QUnit.ok(!checkMissingDbInstanceId(), 'All widgets have a dbInstanceId');
-
-    QUnit.start(); // restart the flow
-  });
-});
--- a/modules/org.openbravo.client.querylist/src/org/openbravo/client/querylist/QueryListComponentProvider.java	Mon Nov 18 16:08:25 2019 +0100
+++ b/modules/org.openbravo.client.querylist/src/org/openbravo/client/querylist/QueryListComponentProvider.java	Tue Nov 19 17:40:39 2019 +0100
@@ -79,10 +79,4 @@
 
     return globalResources;
   }
-
-  @Override
-  public List<String> getTestResources() {
-    final List<String> testResources = new ArrayList<String>();
-    return testResources;
-  }
 }
--- a/modules/org.openbravo.client.widgets/src/org/openbravo/client/widgets/WidgetsCollectionComponentProvider.java	Mon Nov 18 16:08:25 2019 +0100
+++ b/modules/org.openbravo.client.widgets/src/org/openbravo/client/widgets/WidgetsCollectionComponentProvider.java	Tue Nov 19 17:40:39 2019 +0100
@@ -19,7 +19,6 @@
 package org.openbravo.client.widgets;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -53,9 +52,4 @@
         .add(createStaticResource("web/org.openbravo.client.widgets/js/ob-twitter.js", false));
     return globalResources;
   }
-
-  @Override
-  public List<String> getTestResources() {
-    return Collections.emptyList();
-  }
 }
--- a/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/HQLDataSourceService.java	Mon Nov 18 16:08:25 2019 +0100
+++ b/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/HQLDataSourceService.java	Tue Nov 19 17:40:39 2019 +0100
@@ -524,7 +524,7 @@
   }
 
   /**
-   * This method replace the column names with their alias
+   * This method replaces the column names with their alias
    * 
    * @param table
    *          the table being filtered
--- a/modules/org.openbravo.service.json/src/org/openbravo/service/json/JsonUtils.java	Mon Nov 18 16:08:25 2019 +0100
+++ b/modules/org.openbravo.service.json/src/org/openbravo/service/json/JsonUtils.java	Tue Nov 19 17:40:39 2019 +0100
@@ -11,7 +11,7 @@
  * under the License. 
  * The Original Code is Openbravo ERP. 
  * The Initial Developer of the Original Code is Openbravo SLU 
- * All portions are Copyright (C) 2009-2016 Openbravo SLU 
+ * All portions are Copyright (C) 2009-2019 Openbravo SLU 
  * All Rights Reserved. 
  * Contributor(s):  ______________________________________.
  ************************************************************************
@@ -25,13 +25,14 @@
 import java.util.List;
 import java.util.Map;
 
+import javax.persistence.QueryTimeoutException;
+
 import org.apache.commons.lang.StringUtils;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.codehaus.jettison.json.JSONArray;
 import org.codehaus.jettison.json.JSONException;
 import org.codehaus.jettison.json.JSONObject;
-import org.hibernate.QueryTimeoutException;
 import org.openbravo.authentication.AuthenticationManager;
 import org.openbravo.base.exception.OBException;
 import org.openbravo.base.exception.OBSecurityException;
@@ -238,10 +239,7 @@
         error.put("message", "OBUIAPP_ActionNotAllowed");
         error.put("type", "user");
         jsonResponse.put(JsonConstants.RESPONSE_ERROR, error);
-      } else if (localThrowable instanceof SQLTimeoutException
-          || localThrowable instanceof QueryTimeoutException
-          || (localThrowable.getCause() instanceof PSQLException && PG_QUERY_CANCELED
-              .equals(((PSQLException) localThrowable.getCause()).getSQLState()))) {
+      } else if (isQueryTimeout(localThrowable)) {
         final JSONObject error = new JSONObject();
         if (vars != null) {
           error.put("message", Utility.messageBD(new DalConnectionProvider(false),
@@ -271,6 +269,22 @@
     }
   }
 
+  private static boolean isQueryTimeout(Throwable localThrowable) {
+    // In case of query timeout in Hibernate, Oracle throws javax.persistence.QueryTimeoutException
+    // but PostgreSQL javax.persistence.PersistenceException, in PG the only way to get the root
+    // cause is to get the cause's cause and check SQL state.
+    if (localThrowable instanceof SQLTimeoutException
+        || localThrowable instanceof QueryTimeoutException) {
+      return true;
+    }
+
+    Throwable cause = localThrowable.getCause();
+    cause = cause != null ? cause.getCause() : cause;
+
+    return cause instanceof PSQLException
+        && PG_QUERY_CANCELED.equals(((PSQLException) cause).getSQLState());
+  }
+
   /**
    * Returns an empty result for a fetch call
    * 
--- a/modules/org.openbravo.v3/src-db/database/configScript.xml	Mon Nov 18 16:08:25 2019 +0100
+++ b/modules/org.openbravo.v3/src-db/database/configScript.xml	Tue Nov 19 17:40:39 2019 +0100
@@ -1313,10 +1313,6 @@
       <oldValue><![CDATA[Y]]></oldValue>
       <newValue><![CDATA[N]]></newValue>
     </columnDataChange>
-    <columnDataChange tablename="AD_FIELD" columnname="ISSAMELINE" pkRow="801022">
-      <oldValue><![CDATA[Y]]></oldValue>
-      <newValue><![CDATA[N]]></newValue>
-    </columnDataChange>
     <columnDataChange tablename="AD_FIELD" columnname="ISSAMELINE" pkRow="801025">
       <oldValue><![CDATA[Y]]></oldValue>
       <newValue><![CDATA[N]]></newValue>
@@ -1325,10 +1321,6 @@
       <oldValue><![CDATA[Y]]></oldValue>
       <newValue><![CDATA[N]]></newValue>
     </columnDataChange>
-    <columnDataChange tablename="AD_FIELD" columnname="ISSAMELINE" pkRow="801031">
-      <oldValue><![CDATA[Y]]></oldValue>
-      <newValue><![CDATA[N]]></newValue>
-    </columnDataChange>
     <columnDataChange tablename="AD_FIELD" columnname="ISDISPLAYED" pkRow="801081">
       <oldValue><![CDATA[Y]]></oldValue>
       <newValue><![CDATA[N]]></newValue>
--- a/package-lock.json	Mon Nov 18 16:08:25 2019 +0100
+++ b/package-lock.json	Tue Nov 19 17:40:39 2019 +0100
@@ -1,980 +1,9704 @@
 {
-  "name": "openbravo",
-  "version": "1.0.0",
-  "lockfileVersion": 1,
-  "requires": true,
-  "dependencies": {
-    "@babel/code-frame": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
-      "integrity": "sha1-BuKrGb21NThVWaq7W6WXKUgoAPg=",
-      "dev": true,
-      "requires": {
-        "@babel/highlight": "^7.0.0"
-      }
-    },
-    "@babel/highlight": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
-      "integrity": "sha1-9xDDjI1Fjm3ZogGvtjf8t4HOmeQ=",
-      "dev": true,
-      "requires": {
-        "chalk": "^2.0.0",
-        "esutils": "^2.0.2",
-        "js-tokens": "^4.0.0"
-      }
-    },
-    "acorn": {
-      "version": "6.1.1",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz",
-      "integrity": "sha1-fSWuBbuK0fm2mRCOEJTs14hK3B8=",
-      "dev": true
-    },
-    "acorn-jsx": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz",
-      "integrity": "sha1-MqBk/ZJUKSFqCbFBECv90YX65A4=",
-      "dev": true
-    },
-    "ajv": {
-      "version": "6.10.0",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz",
-      "integrity": "sha1-kNDVRDnaWHzX6EO/twRfUL0ivfE=",
-      "dev": true,
-      "requires": {
-        "fast-deep-equal": "^2.0.1",
-        "fast-json-stable-stringify": "^2.0.0",
-        "json-schema-traverse": "^0.4.1",
-        "uri-js": "^4.2.2"
-      }
-    },
-    "ansi-escapes": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
-      "integrity": "sha1-h4C5j/nb9WOBUtHx/lwde0RCl2s=",
-      "dev": true
-    },
-    "ansi-regex": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
-      "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
-      "dev": true
-    },
-    "ansi-styles": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-      "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=",
-      "dev": true,
-      "requires": {
-        "color-convert": "^1.9.0"
-      }
-    },
-    "argparse": {
-      "version": "1.0.10",
-      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
-      "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=",
-      "dev": true,
-      "requires": {
-        "sprintf-js": "~1.0.2"
-      }
-    },
-    "astral-regex": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
-      "integrity": "sha1-bIw/uCfdQ+45GPJ7gngqt2WKb9k=",
-      "dev": true
-    },
-    "balanced-match": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
-      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
-      "dev": true
-    },
-    "brace-expansion": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-      "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=",
-      "dev": true,
-      "requires": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
-      }
-    },
-    "callsites": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
-      "integrity": "sha1-s2MKvYlDQy9Us/BRkjjjPNffL3M=",
-      "dev": true
-    },
-    "chalk": {
-      "version": "2.4.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-      "integrity": "sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=",
-      "dev": true,
-      "requires": {
-        "ansi-styles": "^3.2.1",
-        "escape-string-regexp": "^1.0.5",
-        "supports-color": "^5.3.0"
-      }
-    },
-    "chardet": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
-      "integrity": "sha1-kAlISfCTfy7twkJdDSip5fDLrZ4=",
-      "dev": true
-    },
-    "cli-cursor": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
-      "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
-      "dev": true,
-      "requires": {
-        "restore-cursor": "^2.0.0"
-      }
-    },
-    "cli-width": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
-      "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
-      "dev": true
-    },
-    "color-convert": {
-      "version": "1.9.3",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-      "integrity": "sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=",
-      "dev": true,
-      "requires": {
-        "color-name": "1.1.3"
-      }
-    },
-    "color-name": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
-      "dev": true
-    },
-    "concat-map": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
-      "dev": true
-    },
-    "cross-spawn": {
-      "version": "6.0.5",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
-      "integrity": "sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q=",
-      "dev": true,
-      "requires": {
-        "nice-try": "^1.0.4",
-        "path-key": "^2.0.1",
-        "semver": "^5.5.0",
-        "shebang-command": "^1.2.0",
-        "which": "^1.2.9"
-      }
-    },
-    "debug": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-      "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=",
-      "dev": true,
-      "requires": {
-        "ms": "^2.1.1"
-      }
-    },
-    "deep-is": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
-      "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
-      "dev": true
-    },
-    "doctrine": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
-      "integrity": "sha1-rd6+rXKmV023g2OdyHoSF3OXOWE=",
-      "dev": true,
-      "requires": {
-        "esutils": "^2.0.2"
-      }
-    },
-    "emoji-regex": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
-      "integrity": "sha1-kzoEBShgyF6DwSJHnEdIqOTHIVY=",
-      "dev": true
-    },
-    "escape-string-regexp": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
-      "dev": true
-    },
-    "eslint": {
-      "version": "5.16.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz",
-      "integrity": "sha1-oeOsGq5KP72Clvz496tzFMu2q+o=",
-      "dev": true,
-      "requires": {
-        "@babel/code-frame": "^7.0.0",
-        "ajv": "^6.9.1",
-        "chalk": "^2.1.0",
-        "cross-spawn": "^6.0.5",
-        "debug": "^4.0.1",
-        "doctrine": "^3.0.0",
-        "eslint-scope": "^4.0.3",
-        "eslint-utils": "^1.3.1",
-        "eslint-visitor-keys": "^1.0.0",
-        "espree": "^5.0.1",
-        "esquery": "^1.0.1",
-        "esutils": "^2.0.2",
-        "file-entry-cache": "^5.0.1",
-        "functional-red-black-tree": "^1.0.1",
-        "glob": "^7.1.2",
-        "globals": "^11.7.0",
-        "ignore": "^4.0.6",
-        "import-fresh": "^3.0.0",
-        "imurmurhash": "^0.1.4",
-        "inquirer": "^6.2.2",
-        "js-yaml": "^3.13.0",
-        "json-stable-stringify-without-jsonify": "^1.0.1",
-        "levn": "^0.3.0",
-        "lodash": "^4.17.11",
-        "minimatch": "^3.0.4",
-        "mkdirp": "^0.5.1",
-        "natural-compare": "^1.4.0",
-        "optionator": "^0.8.2",
-        "path-is-inside": "^1.0.2",
-        "progress": "^2.0.0",
-        "regexpp": "^2.0.1",
-        "semver": "^5.5.1",
-        "strip-ansi": "^4.0.0",
-        "strip-json-comments": "^2.0.1",
-        "table": "^5.2.3",
-        "text-table": "^0.2.0"
-      }
-    },
-    "eslint-config-prettier": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-4.3.0.tgz",
-      "integrity": "sha512-sZwhSTHVVz78+kYD3t5pCWSYEdVSBR0PXnwjDRsUs8ytIrK8PLXw+6FKp8r3Z7rx4ZszdetWlXYKOHoUrrwPlA==",
-      "dev": true,
-      "requires": {
-        "get-stdin": "^6.0.0"
-      }
-    },
-    "eslint-scope": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
-      "integrity": "sha1-ygODMxD2iJoyZHgaqC5j65z+eEg=",
-      "dev": true,
-      "requires": {
-        "esrecurse": "^4.1.0",
-        "estraverse": "^4.1.1"
-      }
-    },
-    "eslint-utils": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz",
-      "integrity": "sha1-moUbqJ7nxGA0b5fPiTnHKYgn5RI=",
-      "dev": true
-    },
-    "eslint-visitor-keys": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
-      "integrity": "sha1-PzGA+y4pEBdxastMnW1bXDSmqB0=",
-      "dev": true
-    },
-    "espree": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz",
-      "integrity": "sha1-XWUm+k/H8HiKXPdbFfMDI+L4H3o=",
-      "dev": true,
-      "requires": {
-        "acorn": "^6.0.7",
-        "acorn-jsx": "^5.0.0",
-        "eslint-visitor-keys": "^1.0.0"
-      }
-    },
-    "esprima": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
-      "integrity": "sha1-E7BM2z5sXRnfkatph6hpVhmwqnE=",
-      "dev": true
-    },
-    "esquery": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz",
-      "integrity": "sha1-QGxRZYsfWZGl+bYrHcJbAOPlxwg=",
-      "dev": true,
-      "requires": {
-        "estraverse": "^4.0.0"
-      }
-    },
-    "esrecurse": {
-      "version": "4.2.1",
-      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
-      "integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=",
-      "dev": true,
-      "requires": {
-        "estraverse": "^4.1.0"
-      }
-    },
-    "estraverse": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
-      "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
-      "dev": true
-    },
-    "esutils": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
-      "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
-      "dev": true
-    },
-    "external-editor": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz",
-      "integrity": "sha1-WGbbKal4Jtvkvzr9JAcOrZ6kOic=",
-      "dev": true,
-      "requires": {
-        "chardet": "^0.7.0",
-        "iconv-lite": "^0.4.24",
-        "tmp": "^0.0.33"
-      }
-    },
-    "fast-deep-equal": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
-      "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
-      "dev": true
-    },
-    "fast-json-stable-stringify": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
-      "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
-      "dev": true
-    },
-    "fast-levenshtein": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
-      "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
-      "dev": true
-    },
-    "figures": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
-      "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
-      "dev": true,
-      "requires": {
-        "escape-string-regexp": "^1.0.5"
-      }
-    },
-    "file-entry-cache": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
-      "integrity": "sha1-yg9u+m3T1WEzP7FFFQZcL6/fQ5w=",
-      "dev": true,
-      "requires": {
-        "flat-cache": "^2.0.1"
-      }
-    },
-    "flat-cache": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
-      "integrity": "sha1-XSltbwS9pEpGMKMBQTvbwuwIXsA=",
-      "dev": true,
-      "requires": {
-        "flatted": "^2.0.0",
-        "rimraf": "2.6.3",
-        "write": "1.0.3"
-      }
-    },
-    "flatted": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz",
-      "integrity": "sha1-VRIrZTbqSWtLRIk+4mCBQdENmRY=",
-      "dev": true
-    },
-    "fs.realpath": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
-      "dev": true
-    },
-    "functional-red-black-tree": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
-      "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
-      "dev": true
-    },
-    "get-stdin": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz",
-      "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==",
-      "dev": true
-    },
-    "glob": {
-      "version": "7.1.3",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
-      "integrity": "sha1-OWCDLT8VdBCDQtr9OmezMsCWnfE=",
-      "dev": true,
-      "requires": {
-        "fs.realpath": "^1.0.0",
-        "inflight": "^1.0.4",
-        "inherits": "2",
-        "minimatch": "^3.0.4",
-        "once": "^1.3.0",
-        "path-is-absolute": "^1.0.0"
-      }
-    },
-    "globals": {
-      "version": "11.11.0",
-      "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz",
-      "integrity": "sha1-3Pk3V/ot5Uhvvu1xGFOK33ienC4=",
-      "dev": true
-    },
-    "has-flag": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
-      "dev": true
-    },
-    "iconv-lite": {
-      "version": "0.4.24",
-      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
-      "integrity": "sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=",
-      "dev": true,
-      "requires": {
-        "safer-buffer": ">= 2.1.2 < 3"
-      }
-    },
-    "ignore": {
-      "version": "4.0.6",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
-      "integrity": "sha1-dQ49tYYgh7RzfrrIIH/9HvJ7Jfw=",
-      "dev": true
-    },
-    "import-fresh": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz",
-      "integrity": "sha1-o9iX9CDKsOZxI2iX91vBS0iFw5A=",
-      "dev": true,
-      "requires": {
-        "parent-module": "^1.0.0",
-        "resolve-from": "^4.0.0"
-      }
-    },
-    "imurmurhash": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
-      "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
-      "dev": true
-    },
-    "inflight": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
-      "dev": true,
-      "requires": {
-        "once": "^1.3.0",
-        "wrappy": "1"
-      }
-    },
-    "inherits": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
-      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
-      "dev": true
-    },
-    "inquirer": {
-      "version": "6.3.1",
-      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.3.1.tgz",
-      "integrity": "sha1-ekE7XnlQgRATo9tJHGHR87d26Oc=",
-      "dev": true,
-      "requires": {
-        "ansi-escapes": "^3.2.0",
-        "chalk": "^2.4.2",
-        "cli-cursor": "^2.1.0",
-        "cli-width": "^2.0.0",
-        "external-editor": "^3.0.3",
-        "figures": "^2.0.0",
-        "lodash": "^4.17.11",
-        "mute-stream": "0.0.7",
-        "run-async": "^2.2.0",
-        "rxjs": "^6.4.0",
-        "string-width": "^2.1.0",
-        "strip-ansi": "^5.1.0",
-        "through": "^2.3.6"
-      },
-      "dependencies": {
-        "ansi-regex": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-          "integrity": "sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc=",
-          "dev": true
-        },
-        "strip-ansi": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-          "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "^4.1.0"
-          }
-        }
-      }
-    },
-    "is-fullwidth-code-point": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
-      "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
-      "dev": true
-    },
-    "is-promise": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
-      "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
-      "dev": true
-    },
-    "isexe": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
-      "dev": true
-    },
-    "js-tokens": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
-      "integrity": "sha1-GSA/tZmR35jjoocFDUZHzerzJJk=",
-      "dev": true
-    },
-    "js-yaml": {
-      "version": "3.13.1",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
-      "integrity": "sha1-r/FRswv9+o5J4F2iLnQV6d+jeEc=",
-      "dev": true,
-      "requires": {
-        "argparse": "^1.0.7",
-        "esprima": "^4.0.0"
-      }
-    },
-    "json-schema-traverse": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
-      "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=",
-      "dev": true
-    },
-    "json-stable-stringify-without-jsonify": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
-      "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
-      "dev": true
-    },
-    "levn": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
-      "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
-      "dev": true,
-      "requires": {
-        "prelude-ls": "~1.1.2",
-        "type-check": "~0.3.2"
-      }
-    },
-    "lodash": {
-      "version": "4.17.11",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
-      "integrity": "sha1-s56mIp72B+zYniyN8SU2iRysm40=",
-      "dev": true
-    },
-    "mimic-fn": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
-      "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=",
-      "dev": true
-    },
-    "minimatch": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
-      "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
-      "dev": true,
-      "requires": {
-        "brace-expansion": "^1.1.7"
-      }
-    },
-    "minimist": {
-      "version": "0.0.8",
-      "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
-      "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
-      "dev": true
-    },
-    "mkdirp": {
-      "version": "0.5.1",
-      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
-      "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
-      "dev": true,
-      "requires": {
-        "minimist": "0.0.8"
-      }
-    },
-    "ms": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
-      "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=",
-      "dev": true
-    },
-    "mute-stream": {
-      "version": "0.0.7",
-      "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
-      "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
-      "dev": true
-    },
-    "natural-compare": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
-      "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
-      "dev": true
-    },
-    "nice-try": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
-      "integrity": "sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y=",
-      "dev": true
-    },
-    "once": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
-      "dev": true,
-      "requires": {
-        "wrappy": "1"
-      }
-    },
-    "onetime": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
-      "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
-      "dev": true,
-      "requires": {
-        "mimic-fn": "^1.0.0"
-      }
-    },
-    "optionator": {
-      "version": "0.8.2",
-      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
-      "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
-      "dev": true,
-      "requires": {
-        "deep-is": "~0.1.3",
-        "fast-levenshtein": "~2.0.4",
-        "levn": "~0.3.0",
-        "prelude-ls": "~1.1.2",
-        "type-check": "~0.3.2",
-        "wordwrap": "~1.0.0"
-      }
-    },
-    "os-tmpdir": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
-      "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
-      "dev": true
-    },
-    "parent-module": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
-      "integrity": "sha1-aR0nCeeMefrjoVZiJFLQB2LKqqI=",
-      "dev": true,
-      "requires": {
-        "callsites": "^3.0.0"
-      }
-    },
-    "path-is-absolute": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
-      "dev": true
-    },
-    "path-is-inside": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
-      "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
-      "dev": true
-    },
-    "path-key": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
-      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
-      "dev": true
-    },
-    "prelude-ls": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
-      "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
-      "dev": true
-    },
-    "prettier": {
-      "version": "1.18.2",
-      "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz",
-      "integrity": "sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==",
-      "dev": true
-    },
-    "progress": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
-      "integrity": "sha1-foz42PW48jnBvGi+tOt4Vn1XLvg=",
-      "dev": true
-    },
-    "punycode": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
-      "integrity": "sha1-tYsBCsQMIsVldhbI0sLALHv0eew=",
-      "dev": true
-    },
-    "regexpp": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
-      "integrity": "sha1-jRnTHPYySCtYkEn4KB+T28uk0H8=",
-      "dev": true
-    },
-    "resolve-from": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
-      "integrity": "sha1-SrzYUq0y3Xuqv+m0DgCjbbXzkuY=",
-      "dev": true
-    },
-    "restore-cursor": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
-      "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
-      "dev": true,
-      "requires": {
-        "onetime": "^2.0.0",
-        "signal-exit": "^3.0.2"
-      }
-    },
-    "rimraf": {
-      "version": "2.6.3",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
-      "integrity": "sha1-stEE/g2Psnz54KHNqCYt04M8bKs=",
-      "dev": true,
-      "requires": {
-        "glob": "^7.1.3"
-      }
-    },
-    "run-async": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
-      "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
-      "dev": true,
-      "requires": {
-        "is-promise": "^2.1.0"
-      }
-    },
-    "rxjs": {
-      "version": "6.4.0",
-      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
-      "integrity": "sha1-87sP572n+2nerAwW8XtQsLh5BQQ=",
-      "dev": true,
-      "requires": {
-        "tslib": "^1.9.0"
-      }
-    },
-    "safer-buffer": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-      "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=",
-      "dev": true
-    },
-    "semver": {
-      "version": "5.7.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
-      "integrity": "sha1-eQp89v6lRZuslhELKbYEEtyP+Ws=",
-      "dev": true
-    },
-    "shebang-command": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
-      "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
-      "dev": true,
-      "requires": {
-        "shebang-regex": "^1.0.0"
-      }
-    },
-    "shebang-regex": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
-      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
-      "dev": true
-    },
-    "signal-exit": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
-      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
-      "dev": true
-    },
-    "slice-ansi": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
-      "integrity": "sha1-ys12k0YaY3pXiNkqfdT7oGjoFjY=",
-      "dev": true,
-      "requires": {
-        "ansi-styles": "^3.2.0",
-        "astral-regex": "^1.0.0",
-        "is-fullwidth-code-point": "^2.0.0"
-      }
-    },
-    "sprintf-js": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
-      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
-      "dev": true
-    },
-    "string-width": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
-      "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=",
-      "dev": true,
-      "requires": {
-        "is-fullwidth-code-point": "^2.0.0",
-        "strip-ansi": "^4.0.0"
-      }
-    },
-    "strip-ansi": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
-      "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
-      "dev": true,
-      "requires": {
-        "ansi-regex": "^3.0.0"
-      }
-    },
-    "strip-json-comments": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
-      "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
-      "dev": true
-    },
-    "supports-color": {
-      "version": "5.5.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-      "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=",
-      "dev": true,
-      "requires": {
-        "has-flag": "^3.0.0"
-      }
-    },
-    "table": {
-      "version": "5.2.3",
-      "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz",
-      "integrity": "sha1-zeDMbrBnUcAJ76sn6Mggyltnt/I=",
-      "dev": true,
-      "requires": {
-        "ajv": "^6.9.1",
-        "lodash": "^4.17.11",
-        "slice-ansi": "^2.1.0",
-        "string-width": "^3.0.0"
-      },
-      "dependencies": {
-        "ansi-regex": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-          "integrity": "sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc=",
-          "dev": true
-        },
-        "string-width": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
-          "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=",
-          "dev": true,
-          "requires": {
-            "emoji-regex": "^7.0.1",
-            "is-fullwidth-code-point": "^2.0.0",
-            "strip-ansi": "^5.1.0"
-          }
-        },
-        "strip-ansi": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-          "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "^4.1.0"
-          }
-        }
-      }
-    },
-    "text-table": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
-      "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
-      "dev": true
-    },
-    "through": {
-      "version": "2.3.8",
-      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
-      "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
-      "dev": true
-    },
-    "tmp": {
-      "version": "0.0.33",
-      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
-      "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=",
-      "dev": true,
-      "requires": {
-        "os-tmpdir": "~1.0.2"
-      }
-    },
-    "tslib": {
-      "version": "1.9.3",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
-      "integrity": "sha1-1+TdeSRdhUKMTX5IIqeZF5VMooY=",
-      "dev": true
-    },
-    "type-check": {
-      "version": "0.3.2",
-      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
-      "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
-      "dev": true,
-      "requires": {
-        "prelude-ls": "~1.1.2"
-      }
-    },
-    "uri-js": {
-      "version": "4.2.2",
-      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
-      "integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=",
-      "dev": true,
-      "requires": {
-        "punycode": "^2.1.0"
-      }
-    },
-    "which": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
-      "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=",
-      "dev": true,
-      "requires": {
-        "isexe": "^2.0.0"
-      }
-    },
-    "wordwrap": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
-      "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
-      "dev": true
-    },
-    "wrappy": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
-      "dev": true
-    },
-    "write": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
-      "integrity": "sha1-CADhRSO5I6OH5BUSPIZWFqrg9cM=",
-      "dev": true,
-      "requires": {
-        "mkdirp": "^0.5.1"
-      }
-    }
-  }
+	"name": "openbravo",
+	"version": "1.0.0",
+	"lockfileVersion": 1,
+	"requires": true,
+	"dependencies": {
+		"@babel/code-frame": {
+			"version": "7.5.5",
+			"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz",
+			"integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==",
+			"dev": true,
+			"requires": {
+				"@babel/highlight": "^7.0.0"
+			}
+		},
+		"@babel/core": {
+			"version": "7.7.0",
+			"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.0.tgz",
+			"integrity": "sha512-Bb1NjZCaiwTQC/ARL+MwDpgocdnwWDCaugvkGt6cxfBzQa8Whv1JybBoUEiBDKl8Ni3H3c7Fykwk7QChUsHRlg==",
+			"dev": true,
+			"requires": {
+				"@babel/code-frame": "^7.5.5",
+				"@babel/generator": "^7.7.0",
+				"@babel/helpers": "^7.7.0",
+				"@babel/parser": "^7.7.0",
+				"@babel/template": "^7.7.0",
+				"@babel/traverse": "^7.7.0",
+				"@babel/types": "^7.7.0",
+				"convert-source-map": "^1.1.0",
+				"debug": "^4.1.0",
+				"json5": "^2.1.0",
+				"lodash": "^4.17.13",
+				"resolve": "^1.3.2",
+				"semver": "^5.4.1",
+				"source-map": "^0.5.0"
+			},
+			"dependencies": {
+				"source-map": {
+					"version": "0.5.7",
+					"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+					"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+					"dev": true
+				}
+			}
+		},
+		"@babel/generator": {
+			"version": "7.7.0",
+			"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.0.tgz",
+			"integrity": "sha512-1wdJ6UxHyL1XoJQ119JmvuRX27LRih7iYStMPZOWAjQqeAabFg3dYXKMpgihma+to+0ADsTVVt6oRyUxWZw6Mw==",
+			"dev": true,
+			"requires": {
+				"@babel/types": "^7.7.0",
+				"jsesc": "^2.5.1",
+				"lodash": "^4.17.13",
+				"source-map": "^0.5.0"
+			},
+			"dependencies": {
+				"source-map": {
+					"version": "0.5.7",
+					"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+					"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+					"dev": true
+				}
+			}
+		},
+		"@babel/helper-function-name": {
+			"version": "7.7.0",
+			"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.0.tgz",
+			"integrity": "sha512-tDsJgMUAP00Ugv8O2aGEua5I2apkaQO7lBGUq1ocwN3G23JE5Dcq0uh3GvFTChPa4b40AWiAsLvCZOA2rdnQ7Q==",
+			"dev": true,
+			"requires": {
+				"@babel/helper-get-function-arity": "^7.7.0",
+				"@babel/template": "^7.7.0",
+				"@babel/types": "^7.7.0"
+			}
+		},
+		"@babel/helper-get-function-arity": {
+			"version": "7.7.0",
+			"resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.0.tgz",
+			"integrity": "sha512-tLdojOTz4vWcEnHWHCuPN5P85JLZWbm5Fx5ZsMEMPhF3Uoe3O7awrbM2nQ04bDOUToH/2tH/ezKEOR8zEYzqyw==",
+			"dev": true,
+			"requires": {
+				"@babel/types": "^7.7.0"
+			}
+		},
+		"@babel/helper-plugin-utils": {
+			"version": "7.0.0",
+			"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz",
+			"integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==",
+			"dev": true
+		},
+		"@babel/helper-split-export-declaration": {
+			"version": "7.7.0",
+			"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz",
+			"integrity": "sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA==",
+			"dev": true,
+			"requires": {
+				"@babel/types": "^7.7.0"
+			}
+		},
+		"@babel/helpers": {
+			"version": "7.7.0",
+			"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.0.tgz",
+			"integrity": "sha512-VnNwL4YOhbejHb7x/b5F39Zdg5vIQpUUNzJwx0ww1EcVRt41bbGRZWhAURrfY32T5zTT3qwNOQFWpn+P0i0a2g==",
+			"dev": true,
+			"requires": {
+				"@babel/template": "^7.7.0",
+				"@babel/traverse": "^7.7.0",
+				"@babel/types": "^7.7.0"
+			}
+		},
+		"@babel/highlight": {
+			"version": "7.5.0",
+			"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz",
+			"integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==",
+			"dev": true,
+			"requires": {
+				"chalk": "^2.0.0",
+				"esutils": "^2.0.2",
+				"js-tokens": "^4.0.0"
+			}
+		},
+		"@babel/parser": {
+			"version": "7.7.0",
+			"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.0.tgz",
+			"integrity": "sha512-GqL+Z0d7B7ADlQBMXlJgvXEbtt5qlqd1YQ5fr12hTSfh7O/vgrEIvJxU2e7aSVrEUn75zTZ6Nd0s8tthrlZnrQ==",
+			"dev": true
+		},
+		"@babel/plugin-syntax-object-rest-spread": {
+			"version": "7.2.0",
+			"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz",
+			"integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==",
+			"dev": true,
+			"requires": {
+				"@babel/helper-plugin-utils": "^7.0.0"
+			}
+		},
+		"@babel/template": {
+			"version": "7.7.0",
+			"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.0.tgz",
+			"integrity": "sha512-OKcwSYOW1mhWbnTBgQY5lvg1Fxg+VyfQGjcBduZFljfc044J5iDlnDSfhQ867O17XHiSCxYHUxHg2b7ryitbUQ==",
+			"dev": true,
+			"requires": {
+				"@babel/code-frame": "^7.0.0",
+				"@babel/parser": "^7.7.0",
+				"@babel/types": "^7.7.0"
+			}
+		},
+		"@babel/traverse": {
+			"version": "7.7.0",
+			"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.0.tgz",
+			"integrity": "sha512-ea/3wRZc//e/uwCpuBX2itrhI0U9l7+FsrKWyKGNyvWbuMcCG7ATKY2VI4wlg2b2TA39HHwIxnvmXvtiKsyn7w==",
+			"dev": true,
+			"requires": {
+				"@babel/code-frame": "^7.5.5",
+				"@babel/generator": "^7.7.0",
+				"@babel/helper-function-name": "^7.7.0",
+				"@babel/helper-split-export-declaration": "^7.7.0",
+				"@babel/parser": "^7.7.0",
+				"@babel/types": "^7.7.0",
+				"debug": "^4.1.0",
+				"globals": "^11.1.0",
+				"lodash": "^4.17.13"
+			}
+		},
+		"@babel/types": {
+			"version": "7.7.1",
+			"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.1.tgz",
+			"integrity": "sha512-kN/XdANDab9x1z5gcjDc9ePpxexkt+1EQ2MQUiM4XnMvQfvp87/+6kY4Ko2maLXH+tei/DgJ/ybFITeqqRwDiA==",
+			"dev": true,
+			"requires": {
+				"esutils": "^2.0.2",
+				"lodash": "^4.17.13",
+				"to-fast-properties": "^2.0.0"
+			}
+		},
+		"@cnakazawa/watch": {
+			"version": "1.0.3",
+			"resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz",
+			"integrity": "sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==",
+			"dev": true,
+			"requires": {
+				"exec-sh": "^0.3.2",
+				"minimist": "^1.2.0"
+			},
+			"dependencies": {
+				"minimist": {
+					"version": "1.2.0",
+					"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+					"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+					"dev": true
+				}
+			}
+		},
+		"@evocateur/libnpmaccess": {
+			"version": "3.1.2",
+			"resolved": "https://registry.npmjs.org/@evocateur/libnpmaccess/-/libnpmaccess-3.1.2.tgz",
+			"integrity": "sha512-KSCAHwNWro0CF2ukxufCitT9K5LjL/KuMmNzSu8wuwN2rjyKHD8+cmOsiybK+W5hdnwc5M1SmRlVCaMHQo+3rg==",
+			"dev": true,
+			"requires": {
+				"@evocateur/npm-registry-fetch": "^4.0.0",
+				"aproba": "^2.0.0",
+				"figgy-pudding": "^3.5.1",
+				"get-stream": "^4.0.0",
+				"npm-package-arg": "^6.1.0"
+			},
+			"dependencies": {
+				"aproba": {
+					"version": "2.0.0",
+					"resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
+					"integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
+					"dev": true
+				}
+			}
+		},
+		"@evocateur/libnpmpublish": {
+			"version": "1.2.2",
+			"resolved": "https://registry.npmjs.org/@evocateur/libnpmpublish/-/libnpmpublish-1.2.2.tgz",
+			"integrity": "sha512-MJrrk9ct1FeY9zRlyeoyMieBjGDG9ihyyD9/Ft6MMrTxql9NyoEx2hw9casTIP4CdqEVu+3nQ2nXxoJ8RCXyFg==",
+			"dev": true,
+			"requires": {
+				"@evocateur/npm-registry-fetch": "^4.0.0",
+				"aproba": "^2.0.0",
+				"figgy-pudding": "^3.5.1",
+				"get-stream": "^4.0.0",
+				"lodash.clonedeep": "^4.5.0",
+				"normalize-package-data": "^2.4.0",
+				"npm-package-arg": "^6.1.0",
+				"semver": "^5.5.1",
+				"ssri": "^6.0.1"
+			},
+			"dependencies": {
+				"aproba": {
+					"version": "2.0.0",
+					"resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
+					"integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
+					"dev": true
+				}
+			}
+		},
+		"@evocateur/npm-registry-fetch": {
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/@evocateur/npm-registry-fetch/-/npm-registry-fetch-4.0.0.tgz",
+			"integrity": "sha512-k1WGfKRQyhJpIr+P17O5vLIo2ko1PFLKwoetatdduUSt/aQ4J2sJrJwwatdI5Z3SiYk/mRH9S3JpdmMFd/IK4g==",
+			"dev": true,
+			"requires": {
+				"JSONStream": "^1.3.4",
+				"bluebird": "^3.5.1",
+				"figgy-pudding": "^3.4.1",
+				"lru-cache": "^5.1.1",
+				"make-fetch-happen": "^5.0.0",
+				"npm-package-arg": "^6.1.0",
+				"safe-buffer": "^5.1.2"
+			}
+		},
+		"@evocateur/pacote": {
+			"version": "9.6.5",
+			"resolved": "https://registry.npmjs.org/@evocateur/pacote/-/pacote-9.6.5.tgz",
+			"integrity": "sha512-EI552lf0aG2nOV8NnZpTxNo2PcXKPmDbF9K8eCBFQdIZwHNGN/mi815fxtmUMa2wTa1yndotICIDt/V0vpEx2w==",
+			"dev": true,
+			"requires": {
+				"@evocateur/npm-registry-fetch": "^4.0.0",
+				"bluebird": "^3.5.3",
+				"cacache": "^12.0.3",
+				"chownr": "^1.1.2",
+				"figgy-pudding": "^3.5.1",
+				"get-stream": "^4.1.0",
+				"glob": "^7.1.4",
+				"infer-owner": "^1.0.4",
+				"lru-cache": "^5.1.1",
+				"make-fetch-happen": "^5.0.0",
+				"minimatch": "^3.0.4",
+				"minipass": "^2.3.5",
+				"mississippi": "^3.0.0",
+				"mkdirp": "^0.5.1",
+				"normalize-package-data": "^2.5.0",
+				"npm-package-arg": "^6.1.0",
+				"npm-packlist": "^1.4.4",
+				"npm-pick-manifest": "^3.0.0",
+				"osenv": "^0.1.5",
+				"promise-inflight": "^1.0.1",
+				"promise-retry": "^1.1.1",
+				"protoduck": "^5.0.1",
+				"rimraf": "^2.6.3",
+				"safe-buffer": "^5.2.0",
+				"semver": "^5.7.0",
+				"ssri": "^6.0.1",
+				"tar": "^4.4.10",
+				"unique-filename": "^1.1.1",
+				"which": "^1.3.1"
+			},
+			"dependencies": {
+				"safe-buffer": {
+					"version": "5.2.0",
+					"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
+					"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==",
+					"dev": true
+				}
+			}
+		},
+		"@jest/console": {
+			"version": "24.9.0",
+			"resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz",
+			"integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==",
+			"dev": true,
+			"requires": {
+				"@jest/source-map": "^24.9.0",
+				"chalk": "^2.0.1",
+				"slash": "^2.0.0"
+			}
+		},
+		"@jest/core": {
+			"version": "24.9.0",
+			"resolved": "https://registry.npmjs.org/@jest/core/-/core-24.9.0.tgz",
+			"integrity": "sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A==",
+			"dev": true,
+			"requires": {
+				"@jest/console": "^24.7.1",
+				"@jest/reporters": "^24.9.0",
+				"@jest/test-result": "^24.9.0",
+				"@jest/transform": "^24.9.0",
+				"@jest/types": "^24.9.0",
+				"ansi-escapes": "^3.0.0",
+				"chalk": "^2.0.1",
+				"exit": "^0.1.2",
+				"graceful-fs": "^4.1.15",
+				"jest-changed-files": "^24.9.0",
+				"jest-config": "^24.9.0",
+				"jest-haste-map": "^24.9.0",
+				"jest-message-util": "^24.9.0",
+				"jest-regex-util": "^24.3.0",
+				"jest-resolve": "^24.9.0",
+				"jest-resolve-dependencies": "^24.9.0",
+				"jest-runner": "^24.9.0",
+				"jest-runtime": "^24.9.0",
+				"jest-snapshot": "^24.9.0",
+				"jest-util": "^24.9.0",
+				"jest-validate": "^24.9.0",
+				"jest-watcher": "^24.9.0",
+				"micromatch": "^3.1.10",
+				"p-each-series": "^1.0.0",
+				"realpath-native": "^1.1.0",
+				"rimraf": "^2.5.4",
+				"slash": "^2.0.0",
+				"strip-ansi": "^5.0.0"
+			},
+			"dependencies": {
+				"ansi-regex": {
+					"version": "4.1.0",
+					"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+					"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+					"dev": true
+				},
+				"strip-ansi": {
+					"version": "5.2.0",
+					"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+					"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+					"dev": true,
+					"requires": {
+						"ansi-regex": "^4.1.0"
+					}
+				}
+			}
+		},
+		"@jest/environment": {
+			"version": "24.9.0",
+			"resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz",
+			"integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==",
+			"dev": true,
+			"requires": {
+				"@jest/fake-timers": "^24.9.0",
+				"@jest/transform": "^24.9.0",
+				"@jest/types": "^24.9.0",
+				"jest-mock": "^24.9.0"
+			}
+		},
+		"@jest/fake-timers": {
+			"version": "24.9.0",
+			"resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz",
+			"integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==",
+			"dev": true,
+			"requires": {
+				"@jest/types": "^24.9.0",
+				"jest-message-util": "^24.9.0",
+				"jest-mock": "^24.9.0"
+			}
+		},
+		"@jest/reporters": {
+			"version": "24.9.0",
+			"resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.9.0.tgz",
+			"integrity": "sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw==",
+			"dev": true,
+			"requires": {
+				"@jest/environment": "^24.9.0",
+				"@jest/test-result": "^24.9.0",
+				"@jest/transform": "^24.9.0",
+				"@jest/types": "^24.9.0",
+				"chalk": "^2.0.1",
+				"exit": "^0.1.2",
+				"glob": "^7.1.2",
+				"istanbul-lib-coverage": "^2.0.2",
+				"istanbul-lib-instrument": "^3.0.1",
+				"istanbul-lib-report": "^2.0.4",
+				"istanbul-lib-source-maps": "^3.0.1",
+				"istanbul-reports": "^2.2.6",
+				"jest-haste-map": "^24.9.0",
+				"jest-resolve": "^24.9.0",
+				"jest-runtime": "^24.9.0",
+				"jest-util": "^24.9.0",
+				"jest-worker": "^24.6.0",
+				"node-notifier": "^5.4.2",
+				"slash": "^2.0.0",
+				"source-map": "^0.6.0",
+				"string-length": "^2.0.0"
+			}
+		},
+		"@jest/source-map": {
+			"version": "24.9.0",
+			"resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz",
+			"integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==",
+			"dev": true,
+			"requires": {
+				"callsites": "^3.0.0",
+				"graceful-fs": "^4.1.15",
+				"source-map": "^0.6.0"
+			}
+		},
+		"@jest/test-result": {
+			"version": "24.9.0",
+			"resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz",
+			"integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==",
+			"dev": true,
+			"requires": {
+				"@jest/console": "^24.9.0",
+				"@jest/types": "^24.9.0",
+				"@types/istanbul-lib-coverage": "^2.0.0"
+			}
+		},
+		"@jest/test-sequencer": {
+			"version": "24.9.0",
+			"resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz",
+			"integrity": "sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A==",
+			"dev": true,
+			"requires": {
+				"@jest/test-result": "^24.9.0",
+				"jest-haste-map": "^24.9.0",
+				"jest-runner": "^24.9.0",
+				"jest-runtime": "^24.9.0"
+			}
+		},
+		"@jest/transform": {
+			"version": "24.9.0",
+			"resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz",
+			"integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==",
+			"dev": true,
+			"requires": {
+				"@babel/core": "^7.1.0",
+				"@jest/types": "^24.9.0",
+				"babel-plugin-istanbul": "^5.1.0",
+				"chalk": "^2.0.1",
+				"convert-source-map": "^1.4.0",
+				"fast-json-stable-stringify": "^2.0.0",
+				"graceful-fs": "^4.1.15",
+				"jest-haste-map": "^24.9.0",
+				"jest-regex-util": "^24.9.0",
+				"jest-util": "^24.9.0",
+				"micromatch": "^3.1.10",
+				"pirates": "^4.0.1",
+				"realpath-native": "^1.1.0",
+				"slash": "^2.0.0",
+				"source-map": "^0.6.1",
+				"write-file-atomic": "2.4.1"
+			}
+		},
+		"@jest/types": {
+			"version": "24.9.0",
+			"resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz",
+			"integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==",
+			"dev": true,
+			"requires": {
+				"@types/istanbul-lib-coverage": "^2.0.0",
+				"@types/istanbul-reports": "^1.1.1",
+				"@types/yargs": "^13.0.0"
+			}
+		},
+		"@lerna/add": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/add/-/add-3.18.0.tgz",
+			"integrity": "sha512-Z5EaQbBnJn1LEPb0zb0Q2o9T8F8zOnlCsj6JYpY6aSke17UUT7xx0QMN98iBK+ueUHKjN/vdFdYlNCYRSIdujA==",
+			"dev": true,
+			"requires": {
+				"@evocateur/pacote": "^9.6.3",
+				"@lerna/bootstrap": "3.18.0",
+				"@lerna/command": "3.18.0",
+				"@lerna/filter-options": "3.18.0",
+				"@lerna/npm-conf": "3.16.0",
+				"@lerna/validation-error": "3.13.0",
+				"dedent": "^0.7.0",
+				"npm-package-arg": "^6.1.0",
+				"p-map": "^2.1.0",
+				"semver": "^6.2.0"
+			},
+			"dependencies": {
+				"semver": {
+					"version": "6.3.0",
+					"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+					"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+					"dev": true
+				}
+			}
+		},
+		"@lerna/bootstrap": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/bootstrap/-/bootstrap-3.18.0.tgz",
+			"integrity": "sha512-3DZKWIaKvr7sUImoKqSz6eqn84SsOVMnA5QHwgzXiQjoeZ/5cg9x2r+Xj3+3w/lvLoh0j8U2GNtrIaPNis4bKQ==",
+			"dev": true,
+			"requires": {
+				"@lerna/command": "3.18.0",
+				"@lerna/filter-options": "3.18.0",
+				"@lerna/has-npm-version": "3.16.5",
+				"@lerna/npm-install": "3.16.5",
+				"@lerna/package-graph": "3.18.0",
+				"@lerna/pulse-till-done": "3.13.0",
+				"@lerna/rimraf-dir": "3.16.5",
+				"@lerna/run-lifecycle": "3.16.2",
+				"@lerna/run-topologically": "3.18.0",
+				"@lerna/symlink-binary": "3.17.0",
+				"@lerna/symlink-dependencies": "3.17.0",
+				"@lerna/validation-error": "3.13.0",
+				"dedent": "^0.7.0",
+				"get-port": "^4.2.0",
+				"multimatch": "^3.0.0",
+				"npm-package-arg": "^6.1.0",
+				"npmlog": "^4.1.2",
+				"p-finally": "^1.0.0",
+				"p-map": "^2.1.0",
+				"p-map-series": "^1.0.0",
+				"p-waterfall": "^1.0.0",
+				"read-package-tree": "^5.1.6",
+				"semver": "^6.2.0"
+			},
+			"dependencies": {
+				"semver": {
+					"version": "6.3.0",
+					"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+					"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+					"dev": true
+				}
+			}
+		},
+		"@lerna/changed": {
+			"version": "3.18.3",
+			"resolved": "https://registry.npmjs.org/@lerna/changed/-/changed-3.18.3.tgz",
+			"integrity": "sha512-xZW7Rm+DlDIGc0EvKGyJZgT9f8FFa4d52mr/Y752dZuXR2qRmf9tXhVloRG39881s2A6yi3jqLtXZggKhsQW4Q==",
+			"dev": true,
+			"requires": {
+				"@lerna/collect-updates": "3.18.0",
+				"@lerna/command": "3.18.0",
+				"@lerna/listable": "3.18.0",
+				"@lerna/output": "3.13.0",
+				"@lerna/version": "3.18.3"
+			}
+		},
+		"@lerna/check-working-tree": {
+			"version": "3.16.5",
+			"resolved": "https://registry.npmjs.org/@lerna/check-working-tree/-/check-working-tree-3.16.5.tgz",
+			"integrity": "sha512-xWjVBcuhvB8+UmCSb5tKVLB5OuzSpw96WEhS2uz6hkWVa/Euh1A0/HJwn2cemyK47wUrCQXtczBUiqnq9yX5VQ==",
+			"dev": true,
+			"requires": {
+				"@lerna/collect-uncommitted": "3.16.5",
+				"@lerna/describe-ref": "3.16.5",
+				"@lerna/validation-error": "3.13.0"
+			}
+		},
+		"@lerna/child-process": {
+			"version": "3.16.5",
+			"resolved": "https://registry.npmjs.org/@lerna/child-process/-/child-process-3.16.5.tgz",
+			"integrity": "sha512-vdcI7mzei9ERRV4oO8Y1LHBZ3A5+ampRKg1wq5nutLsUA4mEBN6H7JqjWOMY9xZemv6+kATm2ofjJ3lW5TszQg==",
+			"dev": true,
+			"requires": {
+				"chalk": "^2.3.1",
+				"execa": "^1.0.0",
+				"strong-log-transformer": "^2.0.0"
+			}
+		},
+		"@lerna/clean": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/clean/-/clean-3.18.0.tgz",
+			"integrity": "sha512-BiwBELZNkarRQqj+v5NPB1aIzsOX+Y5jkZ9a5UbwHzEdBUQ5lQa0qaMLSOve/fSkaiZQxe6qnTyatN75lOcDMg==",
+			"dev": true,
+			"requires": {
+				"@lerna/command": "3.18.0",
+				"@lerna/filter-options": "3.18.0",
+				"@lerna/prompt": "3.13.0",
+				"@lerna/pulse-till-done": "3.13.0",
+				"@lerna/rimraf-dir": "3.16.5",
+				"p-map": "^2.1.0",
+				"p-map-series": "^1.0.0",
+				"p-waterfall": "^1.0.0"
+			}
+		},
+		"@lerna/cli": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/cli/-/cli-3.18.0.tgz",
+			"integrity": "sha512-AwDyfGx7fxJgeaZllEuyJ9LZ6Tdv9yqRD9RX762yCJu+PCAFvB9bp6OYuRSGli7QQgM0CuOYnSg4xVNOmuGKDA==",
+			"dev": true,
+			"requires": {
+				"@lerna/global-options": "3.13.0",
+				"dedent": "^0.7.0",
+				"npmlog": "^4.1.2",
+				"yargs": "^14.2.0"
+			},
+			"dependencies": {
+				"ansi-regex": {
+					"version": "4.1.0",
+					"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+					"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+					"dev": true
+				},
+				"string-width": {
+					"version": "3.1.0",
+					"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+					"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+					"dev": true,
+					"requires": {
+						"emoji-regex": "^7.0.1",
+						"is-fullwidth-code-point": "^2.0.0",
+						"strip-ansi": "^5.1.0"
+					}
+				},
+				"strip-ansi": {
+					"version": "5.2.0",
+					"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+					"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+					"dev": true,
+					"requires": {
+						"ansi-regex": "^4.1.0"
+					}
+				},
+				"yargs": {
+					"version": "14.2.0",
+					"resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.0.tgz",
+					"integrity": "sha512-/is78VKbKs70bVZH7w4YaZea6xcJWOAwkhbR0CFuZBmYtfTYF0xjGJF43AYd8g2Uii1yJwmS5GR2vBmrc32sbg==",
+					"dev": true,
+					"requires": {
+						"cliui": "^5.0.0",
+						"decamelize": "^1.2.0",
+						"find-up": "^3.0.0",
+						"get-caller-file": "^2.0.1",
+						"require-directory": "^2.1.1",
+						"require-main-filename": "^2.0.0",
+						"set-blocking": "^2.0.0",
+						"string-width": "^3.0.0",
+						"which-module": "^2.0.0",
+						"y18n": "^4.0.0",
+						"yargs-parser": "^15.0.0"
+					}
+				},
+				"yargs-parser": {
+					"version": "15.0.0",
+					"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.0.tgz",
+					"integrity": "sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ==",
+					"dev": true,
+					"requires": {
+						"camelcase": "^5.0.0",
+						"decamelize": "^1.2.0"
+					}
+				}
+			}
+		},
+		"@lerna/collect-uncommitted": {
+			"version": "3.16.5",
+			"resolved": "https://registry.npmjs.org/@lerna/collect-uncommitted/-/collect-uncommitted-3.16.5.tgz",
+			"integrity": "sha512-ZgqnGwpDZiWyzIQVZtQaj9tRizsL4dUOhuOStWgTAw1EMe47cvAY2kL709DzxFhjr6JpJSjXV5rZEAeU3VE0Hg==",
+			"dev": true,
+			"requires": {
+				"@lerna/child-process": "3.16.5",
+				"chalk": "^2.3.1",
+				"figgy-pudding": "^3.5.1",
+				"npmlog": "^4.1.2"
+			}
+		},
+		"@lerna/collect-updates": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/collect-updates/-/collect-updates-3.18.0.tgz",
+			"integrity": "sha512-LJMKgWsE/var1RSvpKDIxS8eJ7POADEc0HM3FQiTpEczhP6aZfv9x3wlDjaHpZm9MxJyQilqxZcasRANmRcNgw==",
+			"dev": true,
+			"requires": {
+				"@lerna/child-process": "3.16.5",
+				"@lerna/describe-ref": "3.16.5",
+				"minimatch": "^3.0.4",
+				"npmlog": "^4.1.2",
+				"slash": "^2.0.0"
+			}
+		},
+		"@lerna/command": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/command/-/command-3.18.0.tgz",
+			"integrity": "sha512-JQ0TGzuZc9Ky8xtwtSLywuvmkU8X62NTUT3rMNrUykIkOxBaO+tE0O98u2yo/9BYOeTRji9IsjKZEl5i9Qt0xQ==",
+			"dev": true,
+			"requires": {
+				"@lerna/child-process": "3.16.5",
+				"@lerna/package-graph": "3.18.0",
+				"@lerna/project": "3.18.0",
+				"@lerna/validation-error": "3.13.0",
+				"@lerna/write-log-file": "3.13.0",
+				"dedent": "^0.7.0",
+				"execa": "^1.0.0",
+				"is-ci": "^2.0.0",
+				"lodash": "^4.17.14",
+				"npmlog": "^4.1.2"
+			}
+		},
+		"@lerna/conventional-commits": {
+			"version": "3.16.4",
+			"resolved": "https://registry.npmjs.org/@lerna/conventional-commits/-/conventional-commits-3.16.4.tgz",
+			"integrity": "sha512-QSZJ0bC9n6FVaf+7KDIq5zMv8WnHXnwhyL5jG1Nyh3SgOg9q2uflqh7YsYB+G6FwaRfnPaKosh6obijpYg0llA==",
+			"dev": true,
+			"requires": {
+				"@lerna/validation-error": "3.13.0",
+				"conventional-changelog-angular": "^5.0.3",
+				"conventional-changelog-core": "^3.1.6",
+				"conventional-recommended-bump": "^5.0.0",
+				"fs-extra": "^8.1.0",
+				"get-stream": "^4.0.0",
+				"lodash.template": "^4.5.0",
+				"npm-package-arg": "^6.1.0",
+				"npmlog": "^4.1.2",
+				"pify": "^4.0.1",
+				"semver": "^6.2.0"
+			},
+			"dependencies": {
+				"pify": {
+					"version": "4.0.1",
+					"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+					"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+					"dev": true
+				},
+				"semver": {
+					"version": "6.3.0",
+					"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+					"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+					"dev": true
+				}
+			}
+		},
+		"@lerna/create": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/create/-/create-3.18.0.tgz",
+			"integrity": "sha512-y9oS7ND5T13c+cCTJHa2Y9in02ppzyjsNynVWFuS40eIzZ3z058d9+3qSBt1nkbbQlVyfLoP6+bZPsjyzap5ig==",
+			"dev": true,
+			"requires": {
+				"@evocateur/pacote": "^9.6.3",
+				"@lerna/child-process": "3.16.5",
+				"@lerna/command": "3.18.0",
+				"@lerna/npm-conf": "3.16.0",
+				"@lerna/validation-error": "3.13.0",
+				"camelcase": "^5.0.0",
+				"dedent": "^0.7.0",
+				"fs-extra": "^8.1.0",
+				"globby": "^9.2.0",
+				"init-package-json": "^1.10.3",
+				"npm-package-arg": "^6.1.0",
+				"p-reduce": "^1.0.0",
+				"pify": "^4.0.1",
+				"semver": "^6.2.0",
+				"slash": "^2.0.0",
+				"validate-npm-package-license": "^3.0.3",
+				"validate-npm-package-name": "^3.0.0",
+				"whatwg-url": "^7.0.0"
+			},
+			"dependencies": {
+				"pify": {
+					"version": "4.0.1",
+					"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+					"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+					"dev": true
+				},
+				"semver": {
+					"version": "6.3.0",
+					"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+					"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+					"dev": true
+				},
+				"whatwg-url": {
+					"version": "7.1.0",
+					"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
+					"integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
+					"dev": true,
+					"requires": {
+						"lodash.sortby": "^4.7.0",
+						"tr46": "^1.0.1",
+						"webidl-conversions": "^4.0.2"
+					}
+				}
+			}
+		},
+		"@lerna/create-symlink": {
+			"version": "3.16.2",
+			"resolved": "https://registry.npmjs.org/@lerna/create-symlink/-/create-symlink-3.16.2.tgz",
+			"integrity": "sha512-pzXIJp6av15P325sgiIRpsPXLFmkisLhMBCy4764d+7yjf2bzrJ4gkWVMhsv4AdF0NN3OyZ5jjzzTtLNqfR+Jw==",
+			"dev": true,
+			"requires": {
+				"@zkochan/cmd-shim": "^3.1.0",
+				"fs-extra": "^8.1.0",
+				"npmlog": "^4.1.2"
+			}
+		},
+		"@lerna/describe-ref": {
+			"version": "3.16.5",
+			"resolved": "https://registry.npmjs.org/@lerna/describe-ref/-/describe-ref-3.16.5.tgz",
+			"integrity": "sha512-c01+4gUF0saOOtDBzbLMFOTJDHTKbDFNErEY6q6i9QaXuzy9LNN62z+Hw4acAAZuJQhrVWncVathcmkkjvSVGw==",
+			"dev": true,
+			"requires": {
+				"@lerna/child-process": "3.16.5",
+				"npmlog": "^4.1.2"
+			}
+		},
+		"@lerna/diff": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/diff/-/diff-3.18.0.tgz",
+			"integrity": "sha512-3iLNlpurc2nV9k22w8ini2Zjm2UPo3xtQgWyqdA6eJjvge0+5AlNAWfPoV6cV+Hc1xDbJD2YDSFpZPJ1ZGilRw==",
+			"dev": true,
+			"requires": {
+				"@lerna/child-process": "3.16.5",
+				"@lerna/command": "3.18.0",
+				"@lerna/validation-error": "3.13.0",
+				"npmlog": "^4.1.2"
+			}
+		},
+		"@lerna/exec": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/exec/-/exec-3.18.0.tgz",
+			"integrity": "sha512-hwkuzg1+38+pbzdZPhGtLIYJ59z498/BCNzR8d4/nfMYm8lFbw9RgJJajLcdbuJ9LJ08cZ93hf8OlzetL84TYg==",
+			"dev": true,
+			"requires": {
+				"@lerna/child-process": "3.16.5",
+				"@lerna/command": "3.18.0",
+				"@lerna/filter-options": "3.18.0",
+				"@lerna/run-topologically": "3.18.0",
+				"@lerna/validation-error": "3.13.0",
+				"p-map": "^2.1.0"
+			}
+		},
+		"@lerna/filter-options": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/filter-options/-/filter-options-3.18.0.tgz",
+			"integrity": "sha512-UGVcixs3TGzD8XSmFSbwUVVQnAjaZ6Rmt8Vuq2RcR98ULkGB1LiGNMY89XaNBhaaA8vx7yQWiLmJi2AfmD63Qg==",
+			"dev": true,
+			"requires": {
+				"@lerna/collect-updates": "3.18.0",
+				"@lerna/filter-packages": "3.18.0",
+				"dedent": "^0.7.0",
+				"figgy-pudding": "^3.5.1",
+				"npmlog": "^4.1.2"
+			}
+		},
+		"@lerna/filter-packages": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/filter-packages/-/filter-packages-3.18.0.tgz",
+			"integrity": "sha512-6/0pMM04bCHNATIOkouuYmPg6KH3VkPCIgTfQmdkPJTullERyEQfNUKikrefjxo1vHOoCACDpy65JYyKiAbdwQ==",
+			"dev": true,
+			"requires": {
+				"@lerna/validation-error": "3.13.0",
+				"multimatch": "^3.0.0",
+				"npmlog": "^4.1.2"
+			}
+		},
+		"@lerna/get-npm-exec-opts": {
+			"version": "3.13.0",
+			"resolved": "https://registry.npmjs.org/@lerna/get-npm-exec-opts/-/get-npm-exec-opts-3.13.0.tgz",
+			"integrity": "sha512-Y0xWL0rg3boVyJk6An/vurKzubyJKtrxYv2sj4bB8Mc5zZ3tqtv0ccbOkmkXKqbzvNNF7VeUt1OJ3DRgtC/QZw==",
+			"dev": true,
+			"requires": {
+				"npmlog": "^4.1.2"
+			}
+		},
+		"@lerna/get-packed": {
+			"version": "3.16.0",
+			"resolved": "https://registry.npmjs.org/@lerna/get-packed/-/get-packed-3.16.0.tgz",
+			"integrity": "sha512-AjsFiaJzo1GCPnJUJZiTW6J1EihrPkc2y3nMu6m3uWFxoleklsSCyImumzVZJssxMi3CPpztj8LmADLedl9kXw==",
+			"dev": true,
+			"requires": {
+				"fs-extra": "^8.1.0",
+				"ssri": "^6.0.1",
+				"tar": "^4.4.8"
+			}
+		},
+		"@lerna/github-client": {
+			"version": "3.16.5",
+			"resolved": "https://registry.npmjs.org/@lerna/github-client/-/github-client-3.16.5.tgz",
+			"integrity": "sha512-rHQdn8Dv/CJrO3VouOP66zAcJzrHsm+wFuZ4uGAai2At2NkgKH+tpNhQy2H1PSC0Ezj9LxvdaHYrUzULqVK5Hw==",
+			"dev": true,
+			"requires": {
+				"@lerna/child-process": "3.16.5",
+				"@octokit/plugin-enterprise-rest": "^3.6.1",
+				"@octokit/rest": "^16.28.4",
+				"git-url-parse": "^11.1.2",
+				"npmlog": "^4.1.2"
+			}
+		},
+		"@lerna/gitlab-client": {
+			"version": "3.15.0",
+			"resolved": "https://registry.npmjs.org/@lerna/gitlab-client/-/gitlab-client-3.15.0.tgz",
+			"integrity": "sha512-OsBvRSejHXUBMgwWQqNoioB8sgzL/Pf1pOUhHKtkiMl6aAWjklaaq5HPMvTIsZPfS6DJ9L5OK2GGZuooP/5c8Q==",
+			"dev": true,
+			"requires": {
+				"node-fetch": "^2.5.0",
+				"npmlog": "^4.1.2",
+				"whatwg-url": "^7.0.0"
+			},
+			"dependencies": {
+				"whatwg-url": {
+					"version": "7.1.0",
+					"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
+					"integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
+					"dev": true,
+					"requires": {
+						"lodash.sortby": "^4.7.0",
+						"tr46": "^1.0.1",
+						"webidl-conversions": "^4.0.2"
+					}
+				}
+			}
+		},
+		"@lerna/global-options": {
+			"version": "3.13.0",
+			"resolved": "https://registry.npmjs.org/@lerna/global-options/-/global-options-3.13.0.tgz",
+			"integrity": "sha512-SlZvh1gVRRzYLVluz9fryY1nJpZ0FHDGB66U9tFfvnnxmueckRQxLopn3tXj3NU1kc3QANT2I5BsQkOqZ4TEFQ==",
+			"dev": true
+		},
+		"@lerna/has-npm-version": {
+			"version": "3.16.5",
+			"resolved": "https://registry.npmjs.org/@lerna/has-npm-version/-/has-npm-version-3.16.5.tgz",
+			"integrity": "sha512-WL7LycR9bkftyqbYop5rEGJ9sRFIV55tSGmbN1HLrF9idwOCD7CLrT64t235t3t4O5gehDnwKI5h2U3oxTrF8Q==",
+			"dev": true,
+			"requires": {
+				"@lerna/child-process": "3.16.5",
+				"semver": "^6.2.0"
+			},
+			"dependencies": {
+				"semver": {
+					"version": "6.3.0",
+					"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+					"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+					"dev": true
+				}
+			}
+		},
+		"@lerna/import": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/import/-/import-3.18.0.tgz",
+			"integrity": "sha512-2pYIkkBTZsEdccfc+dPsKZeSw3tBzKSyl0b2lGrfmNX2Y41qqOzsJCyI1WO1uvEIP8aOaLy4hPpqRIBe4ee7hw==",
+			"dev": true,
+			"requires": {
+				"@lerna/child-process": "3.16.5",
+				"@lerna/command": "3.18.0",
+				"@lerna/prompt": "3.13.0",
+				"@lerna/pulse-till-done": "3.13.0",
+				"@lerna/validation-error": "3.13.0",
+				"dedent": "^0.7.0",
+				"fs-extra": "^8.1.0",
+				"p-map-series": "^1.0.0"
+			}
+		},
+		"@lerna/init": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/init/-/init-3.18.0.tgz",
+			"integrity": "sha512-/vHpmXkMlSaJaq25v5K13mcs/2L7E32O6dSsEkHaZCDRiV2BOqsZng9jjbE/4ynfsWfLLlU9ZcydwG72C3I+mQ==",
+			"dev": true,
+			"requires": {
+				"@lerna/child-process": "3.16.5",
+				"@lerna/command": "3.18.0",
+				"fs-extra": "^8.1.0",
+				"p-map": "^2.1.0",
+				"write-json-file": "^3.2.0"
+			}
+		},
+		"@lerna/link": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/link/-/link-3.18.0.tgz",
+			"integrity": "sha512-FbbIpH0EpsC+dpAbvxCoF3cn7F1MAyJjEa5Lh3XkDGATOlinMFuKCbmX0NLpOPQZ5zghvrui97cx+jz5F2IlHw==",
+			"dev": true,
+			"requires": {
+				"@lerna/command": "3.18.0",
+				"@lerna/package-graph": "3.18.0",
+				"@lerna/symlink-dependencies": "3.17.0",
+				"p-map": "^2.1.0",
+				"slash": "^2.0.0"
+			}
+		},
+		"@lerna/list": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/list/-/list-3.18.0.tgz",
+			"integrity": "sha512-mpB7Q6T+n2CaiPFz0LuOE+rXphDfHm0mKIwShnyS/XDcii8jXv+z9Iytj8p3rfCH2I1L80j2qL6jWzyGy/uzKA==",
+			"dev": true,
+			"requires": {
+				"@lerna/command": "3.18.0",
+				"@lerna/filter-options": "3.18.0",
+				"@lerna/listable": "3.18.0",
+				"@lerna/output": "3.13.0"
+			}
+		},
+		"@lerna/listable": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/listable/-/listable-3.18.0.tgz",
+			"integrity": "sha512-9gLGKYNLSKeurD+sJ2RA+nz4Ftulr91U127gefz0RlmAPpYSjwcJkxwa0UfJvpQTXv9C7yzHLnn0BjyAQRjuew==",
+			"dev": true,
+			"requires": {
+				"@lerna/query-graph": "3.18.0",
+				"chalk": "^2.3.1",
+				"columnify": "^1.5.4"
+			}
+		},
+		"@lerna/log-packed": {
+			"version": "3.16.0",
+			"resolved": "https://registry.npmjs.org/@lerna/log-packed/-/log-packed-3.16.0.tgz",
+			"integrity": "sha512-Fp+McSNBV/P2mnLUYTaSlG8GSmpXM7krKWcllqElGxvAqv6chk2K3c2k80MeVB4WvJ9tRjUUf+i7HUTiQ9/ckQ==",
+			"dev": true,
+			"requires": {
+				"byte-size": "^5.0.1",
+				"columnify": "^1.5.4",
+				"has-unicode": "^2.0.1",
+				"npmlog": "^4.1.2"
+			}
+		},
+		"@lerna/npm-conf": {
+			"version": "3.16.0",
+			"resolved": "https://registry.npmjs.org/@lerna/npm-conf/-/npm-conf-3.16.0.tgz",
+			"integrity": "sha512-HbO3DUrTkCAn2iQ9+FF/eisDpWY5POQAOF1m7q//CZjdC2HSW3UYbKEGsSisFxSfaF9Z4jtrV+F/wX6qWs3CuA==",
+			"dev": true,
+			"requires": {
+				"config-chain": "^1.1.11",
+				"pify": "^4.0.1"
+			},
+			"dependencies": {
+				"pify": {
+					"version": "4.0.1",
+					"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+					"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+					"dev": true
+				}
+			}
+		},
+		"@lerna/npm-dist-tag": {
+			"version": "3.18.1",
+			"resolved": "https://registry.npmjs.org/@lerna/npm-dist-tag/-/npm-dist-tag-3.18.1.tgz",
+			"integrity": "sha512-vWkZh2T/O9OjPLDrba0BTWO7ug/C3sCwjw7Qyk1aEbxMBXB/eEJPqirwJTWT+EtRJQYB01ky3K8ZFOhElVyjLw==",
+			"dev": true,
+			"requires": {
+				"@evocateur/npm-registry-fetch": "^4.0.0",
+				"@lerna/otplease": "3.16.0",
+				"figgy-pudding": "^3.5.1",
+				"npm-package-arg": "^6.1.0",
+				"npmlog": "^4.1.2"
+			}
+		},
+		"@lerna/npm-install": {
+			"version": "3.16.5",
+			"resolved": "https://registry.npmjs.org/@lerna/npm-install/-/npm-install-3.16.5.tgz",
+			"integrity": "sha512-hfiKk8Eku6rB9uApqsalHHTHY+mOrrHeWEs+gtg7+meQZMTS3kzv4oVp5cBZigndQr3knTLjwthT/FX4KvseFg==",
+			"dev": true,
+			"requires": {
+				"@lerna/child-process": "3.16.5",
+				"@lerna/get-npm-exec-opts": "3.13.0",
+				"fs-extra": "^8.1.0",
+				"npm-package-arg": "^6.1.0",
+				"npmlog": "^4.1.2",
+				"signal-exit": "^3.0.2",
+				"write-pkg": "^3.1.0"
+			}
+		},
+		"@lerna/npm-publish": {
+			"version": "3.16.2",
+			"resolved": "https://registry.npmjs.org/@lerna/npm-publish/-/npm-publish-3.16.2.tgz",
+			"integrity": "sha512-tGMb9vfTxP57vUV5svkBQxd5Tzc+imZbu9ZYf8Mtwe0+HYfDjNiiHLIQw7G95w4YRdc5KsCE8sQ0uSj+f2soIg==",
+			"dev": true,
+			"requires": {
+				"@evocateur/libnpmpublish": "^1.2.2",
+				"@lerna/otplease": "3.16.0",
+				"@lerna/run-lifecycle": "3.16.2",
+				"figgy-pudding": "^3.5.1",
+				"fs-extra": "^8.1.0",
+				"npm-package-arg": "^6.1.0",
+				"npmlog": "^4.1.2",
+				"pify": "^4.0.1",
+				"read-package-json": "^2.0.13"
+			},
+			"dependencies": {
+				"pify": {
+					"version": "4.0.1",
+					"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+					"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+					"dev": true
+				}
+			}
+		},
+		"@lerna/npm-run-script": {
+			"version": "3.16.5",
+			"resolved": "https://registry.npmjs.org/@lerna/npm-run-script/-/npm-run-script-3.16.5.tgz",
+			"integrity": "sha512-1asRi+LjmVn3pMjEdpqKJZFT/3ZNpb+VVeJMwrJaV/3DivdNg7XlPK9LTrORuKU4PSvhdEZvJmSlxCKyDpiXsQ==",
+			"dev": true,
+			"requires": {
+				"@lerna/child-process": "3.16.5",
+				"@lerna/get-npm-exec-opts": "3.13.0",
+				"npmlog": "^4.1.2"
+			}
+		},
+		"@lerna/otplease": {
+			"version": "3.16.0",
+			"resolved": "https://registry.npmjs.org/@lerna/otplease/-/otplease-3.16.0.tgz",
+			"integrity": "sha512-uqZ15wYOHC+/V0WnD2iTLXARjvx3vNrpiIeyIvVlDB7rWse9mL4egex/QSgZ+lDx1OID7l2kgvcUD9cFpbqB7Q==",
+			"dev": true,
+			"requires": {
+				"@lerna/prompt": "3.13.0",
+				"figgy-pudding": "^3.5.1"
+			}
+		},
+		"@lerna/output": {
+			"version": "3.13.0",
+			"resolved": "https://registry.npmjs.org/@lerna/output/-/output-3.13.0.tgz",
+			"integrity": "sha512-7ZnQ9nvUDu/WD+bNsypmPG5MwZBwu86iRoiW6C1WBuXXDxM5cnIAC1m2WxHeFnjyMrYlRXM9PzOQ9VDD+C15Rg==",
+			"dev": true,
+			"requires": {
+				"npmlog": "^4.1.2"
+			}
+		},
+		"@lerna/pack-directory": {
+			"version": "3.16.4",
+			"resolved": "https://registry.npmjs.org/@lerna/pack-directory/-/pack-directory-3.16.4.tgz",
+			"integrity": "sha512-uxSF0HZeGyKaaVHz5FroDY9A5NDDiCibrbYR6+khmrhZtY0Bgn6hWq8Gswl9iIlymA+VzCbshWIMX4o2O8C8ng==",
+			"dev": true,
+			"requires": {
+				"@lerna/get-packed": "3.16.0",
+				"@lerna/package": "3.16.0",
+				"@lerna/run-lifecycle": "3.16.2",
+				"figgy-pudding": "^3.5.1",
+				"npm-packlist": "^1.4.4",
+				"npmlog": "^4.1.2",
+				"tar": "^4.4.10",
+				"temp-write": "^3.4.0"
+			}
+		},
+		"@lerna/package": {
+			"version": "3.16.0",
+			"resolved": "https://registry.npmjs.org/@lerna/package/-/package-3.16.0.tgz",
+			"integrity": "sha512-2lHBWpaxcBoiNVbtyLtPUuTYEaB/Z+eEqRS9duxpZs6D+mTTZMNy6/5vpEVSCBmzvdYpyqhqaYjjSLvjjr5Riw==",
+			"dev": true,
+			"requires": {
+				"load-json-file": "^5.3.0",
+				"npm-package-arg": "^6.1.0",
+				"write-pkg": "^3.1.0"
+			},
+			"dependencies": {
+				"load-json-file": {
+					"version": "5.3.0",
+					"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz",
+					"integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==",
+					"dev": true,
+					"requires": {
+						"graceful-fs": "^4.1.15",
+						"parse-json": "^4.0.0",
+						"pify": "^4.0.1",
+						"strip-bom": "^3.0.0",
+						"type-fest": "^0.3.0"
+					}
+				},
+				"pify": {
+					"version": "4.0.1",
+					"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+					"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+					"dev": true
+				}
+			}
+		},
+		"@lerna/package-graph": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/package-graph/-/package-graph-3.18.0.tgz",
+			"integrity": "sha512-BLYDHO5ihPh20i3zoXfLZ5ZWDCrPuGANgVhl7k5pCmRj90LCvT+C7V3zrw70fErGAfvkcYepMqxD+oBrAYwquQ==",
+			"dev": true,
+			"requires": {
+				"@lerna/prerelease-id-from-version": "3.16.0",
+				"@lerna/validation-error": "3.13.0",
+				"npm-package-arg": "^6.1.0",
+				"npmlog": "^4.1.2",
+				"semver": "^6.2.0"
+			},
+			"dependencies": {
+				"semver": {
+					"version": "6.3.0",
+					"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+					"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+					"dev": true
+				}
+			}
+		},
+		"@lerna/prerelease-id-from-version": {
+			"version": "3.16.0",
+			"resolved": "https://registry.npmjs.org/@lerna/prerelease-id-from-version/-/prerelease-id-from-version-3.16.0.tgz",
+			"integrity": "sha512-qZyeUyrE59uOK8rKdGn7jQz+9uOpAaF/3hbslJVFL1NqF9ELDTqjCPXivuejMX/lN4OgD6BugTO4cR7UTq/sZA==",
+			"dev": true,
+			"requires": {
+				"semver": "^6.2.0"
+			},
+			"dependencies": {
+				"semver": {
+					"version": "6.3.0",
+					"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+					"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+					"dev": true
+				}
+			}
+		},
+		"@lerna/project": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/project/-/project-3.18.0.tgz",
+			"integrity": "sha512-+LDwvdAp0BurOAWmeHE3uuticsq9hNxBI0+FMHiIai8jrygpJGahaQrBYWpwbshbQyVLeQgx3+YJdW2TbEdFWA==",
+			"dev": true,
+			"requires": {
+				"@lerna/package": "3.16.0",
+				"@lerna/validation-error": "3.13.0",
+				"cosmiconfig": "^5.1.0",
+				"dedent": "^0.7.0",
+				"dot-prop": "^4.2.0",
+				"glob-parent": "^5.0.0",
+				"globby": "^9.2.0",
+				"load-json-file": "^5.3.0",
+				"npmlog": "^4.1.2",
+				"p-map": "^2.1.0",
+				"resolve-from": "^4.0.0",
+				"write-json-file": "^3.2.0"
+			},
+			"dependencies": {
+				"load-json-file": {
+					"version": "5.3.0",
+					"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz",
+					"integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==",
+					"dev": true,
+					"requires": {
+						"graceful-fs": "^4.1.15",
+						"parse-json": "^4.0.0",
+						"pify": "^4.0.1",
+						"strip-bom": "^3.0.0",
+						"type-fest": "^0.3.0"
+					}
+				},
+				"pify": {
+					"version": "4.0.1",
+					"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+					"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+					"dev": true
+				}
+			}
+		},
+		"@lerna/prompt": {
+			"version": "3.13.0",
+			"resolved": "https://registry.npmjs.org/@lerna/prompt/-/prompt-3.13.0.tgz",
+			"integrity": "sha512-P+lWSFokdyvYpkwC3it9cE0IF2U5yy2mOUbGvvE4iDb9K7TyXGE+7lwtx2thtPvBAfIb7O13POMkv7df03HJeA==",
+			"dev": true,
+			"requires": {
+				"inquirer": "^6.2.0",
+				"npmlog": "^4.1.2"
+			}
+		},
+		"@lerna/publish": {
+			"version": "3.18.3",
+			"resolved": "https://registry.npmjs.org/@lerna/publish/-/publish-3.18.3.tgz",
+			"integrity": "sha512-XlfWOWIhaSK0Y2sX5ppNWI5Y3CDtlxMcQa1hTbZlC5rrDA6vD32iutbmH6Ix3c6wtvVbSkgA39GWsQEXxPS+7w==",
+			"dev": true,
+			"requires": {
+				"@evocateur/libnpmaccess": "^3.1.2",
+				"@evocateur/npm-registry-fetch": "^4.0.0",
+				"@evocateur/pacote": "^9.6.3",
+				"@lerna/check-working-tree": "3.16.5",
+				"@lerna/child-process": "3.16.5",
+				"@lerna/collect-updates": "3.18.0",
+				"@lerna/command": "3.18.0",
+				"@lerna/describe-ref": "3.16.5",
+				"@lerna/log-packed": "3.16.0",
+				"@lerna/npm-conf": "3.16.0",
+				"@lerna/npm-dist-tag": "3.18.1",
+				"@lerna/npm-publish": "3.16.2",
+				"@lerna/otplease": "3.16.0",
+				"@lerna/output": "3.13.0",
+				"@lerna/pack-directory": "3.16.4",
+				"@lerna/prerelease-id-from-version": "3.16.0",
+				"@lerna/prompt": "3.13.0",
+				"@lerna/pulse-till-done": "3.13.0",
+				"@lerna/run-lifecycle": "3.16.2",
+				"@lerna/run-topologically": "3.18.0",
+				"@lerna/validation-error": "3.13.0",
+				"@lerna/version": "3.18.3",
+				"figgy-pudding": "^3.5.1",
+				"fs-extra": "^8.1.0",
+				"npm-package-arg": "^6.1.0",
+				"npmlog": "^4.1.2",
+				"p-finally": "^1.0.0",
+				"p-map": "^2.1.0",
+				"p-pipe": "^1.2.0",
+				"semver": "^6.2.0"
+			},
+			"dependencies": {
+				"semver": {
+					"version": "6.3.0",
+					"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+					"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+					"dev": true
+				}
+			}
+		},
+		"@lerna/pulse-till-done": {
+			"version": "3.13.0",
+			"resolved": "https://registry.npmjs.org/@lerna/pulse-till-done/-/pulse-till-done-3.13.0.tgz",
+			"integrity": "sha512-1SOHpy7ZNTPulzIbargrgaJX387csN7cF1cLOGZiJQA6VqnS5eWs2CIrG8i8wmaUavj2QlQ5oEbRMVVXSsGrzA==",
+			"dev": true,
+			"requires": {
+				"npmlog": "^4.1.2"
+			}
+		},
+		"@lerna/query-graph": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/query-graph/-/query-graph-3.18.0.tgz",
+			"integrity": "sha512-fgUhLx6V0jDuKZaKj562jkuuhrfVcjl5sscdfttJ8dXNVADfDz76nzzwLY0ZU7/0m69jDedohn5Fx5p7hDEVEg==",
+			"dev": true,
+			"requires": {
+				"@lerna/package-graph": "3.18.0",
+				"figgy-pudding": "^3.5.1"
+			}
+		},
+		"@lerna/resolve-symlink": {
+			"version": "3.16.0",
+			"resolved": "https://registry.npmjs.org/@lerna/resolve-symlink/-/resolve-symlink-3.16.0.tgz",
+			"integrity": "sha512-Ibj5e7njVHNJ/NOqT4HlEgPFPtPLWsO7iu59AM5bJDcAJcR96mLZ7KGVIsS2tvaO7akMEJvt2P+ErwCdloG3jQ==",
+			"dev": true,
+			"requires": {
+				"fs-extra": "^8.1.0",
+				"npmlog": "^4.1.2",
+				"read-cmd-shim": "^1.0.1"
+			}
+		},
+		"@lerna/rimraf-dir": {
+			"version": "3.16.5",
+			"resolved": "https://registry.npmjs.org/@lerna/rimraf-dir/-/rimraf-dir-3.16.5.tgz",
+			"integrity": "sha512-bQlKmO0pXUsXoF8lOLknhyQjOZsCc0bosQDoX4lujBXSWxHVTg1VxURtWf2lUjz/ACsJVDfvHZbDm8kyBk5okA==",
+			"dev": true,
+			"requires": {
+				"@lerna/child-process": "3.16.5",
+				"npmlog": "^4.1.2",
+				"path-exists": "^3.0.0",
+				"rimraf": "^2.6.2"
+			}
+		},
+		"@lerna/run": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/run/-/run-3.18.0.tgz",
+			"integrity": "sha512-sblxHBZ9djaaG7wefPcfEicDqzrB7CP1m/jIB0JvPEQwG4C2qp++ewBpkjRw/mBtjtzg0t7v0nNMXzaWYrQckQ==",
+			"dev": true,
+			"requires": {
+				"@lerna/command": "3.18.0",
+				"@lerna/filter-options": "3.18.0",
+				"@lerna/npm-run-script": "3.16.5",
+				"@lerna/output": "3.13.0",
+				"@lerna/run-topologically": "3.18.0",
+				"@lerna/timer": "3.13.0",
+				"@lerna/validation-error": "3.13.0",
+				"p-map": "^2.1.0"
+			}
+		},
+		"@lerna/run-lifecycle": {
+			"version": "3.16.2",
+			"resolved": "https://registry.npmjs.org/@lerna/run-lifecycle/-/run-lifecycle-3.16.2.tgz",
+			"integrity": "sha512-RqFoznE8rDpyyF0rOJy3+KjZCeTkO8y/OB9orPauR7G2xQ7PTdCpgo7EO6ZNdz3Al+k1BydClZz/j78gNCmL2A==",
+			"dev": true,
+			"requires": {
+				"@lerna/npm-conf": "3.16.0",
+				"figgy-pudding": "^3.5.1",
+				"npm-lifecycle": "^3.1.2",
+				"npmlog": "^4.1.2"
+			}
+		},
+		"@lerna/run-topologically": {
+			"version": "3.18.0",
+			"resolved": "https://registry.npmjs.org/@lerna/run-topologically/-/run-topologically-3.18.0.tgz",
+			"integrity": "sha512-lrfEewwuUMC3ioxf9Z9NdHUakN6ihekcPfdYbzR2slmdbjYKmIA5srkWdrK8NwOpQCAuekpOovH2s8X3FGEopg==",
+			"dev": true,
+			"requires": {
+				"@lerna/query-graph": "3.18.0",
+				"figgy-pudding": "^3.5.1",
+				"p-queue": "^4.0.0"
+			}
+		},
+		"@lerna/symlink-binary": {
+			"version": "3.17.0",
+			"resolved": "https://registry.npmjs.org/@lerna/symlink-binary/-/symlink-binary-3.17.0.tgz",
+			"integrity": "sha512-RLpy9UY6+3nT5J+5jkM5MZyMmjNHxZIZvXLV+Q3MXrf7Eaa1hNqyynyj4RO95fxbS+EZc4XVSk25DGFQbcRNSQ==",
+			"dev": true,
+			"requires": {
+				"@lerna/create-symlink": "3.16.2",
+				"@lerna/package": "3.16.0",
+				"fs-extra": "^8.1.0",
+				"p-map": "^2.1.0"
+			}
+		},
+		"@lerna/symlink-dependencies": {
+			"version": "3.17.0",
+			"resolved": "https://registry.npmjs.org/@lerna/symlink-dependencies/-/symlink-dependencies-3.17.0.tgz",
+			"integrity": "sha512-KmjU5YT1bpt6coOmdFueTJ7DFJL4H1w5eF8yAQ2zsGNTtZ+i5SGFBWpb9AQaw168dydc3s4eu0W0Sirda+F59Q==",
+			"dev": true,
+			"requires": {
+				"@lerna/create-symlink": "3.16.2",
+				"@lerna/resolve-symlink": "3.16.0",
+				"@lerna/symlink-binary": "3.17.0",
+				"fs-extra": "^8.1.0",
+				"p-finally": "^1.0.0",
+				"p-map": "^2.1.0",
+				"p-map-series": "^1.0.0"
+			}
+		},
+		"@lerna/timer": {
+			"version": "3.13.0",
+			"resolved": "https://registry.npmjs.org/@lerna/timer/-/timer-3.13.0.tgz",
+			"integrity": "sha512-RHWrDl8U4XNPqY5MQHkToWS9jHPnkLZEt5VD+uunCKTfzlxGnRCr3/zVr8VGy/uENMYpVP3wJa4RKGY6M0vkRw==",
+			"dev": true
+		},
+		"@lerna/validation-error": {
+			"version": "3.13.0",
+			"resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-3.13.0.tgz",
+			"integrity": "sha512-SiJP75nwB8GhgwLKQfdkSnDufAaCbkZWJqEDlKOUPUvVOplRGnfL+BPQZH5nvq2BYSRXsksXWZ4UHVnQZI/HYA==",
+			"dev": true,
+			"requires": {
+				"npmlog": "^4.1.2"
+			}
+		},
+		"@lerna/version": {
+			"version": "3.18.3",
+			"resolved": "https://registry.npmjs.org/@lerna/version/-/version-3.18.3.tgz",
+			"integrity": "sha512-IXXRlyM3Q/jrc+QZio+bgjG4ZaK+4LYmY4Yql1xyY0wZhAKsWP/Q6ho7e1EJNjNC5dUJO99Fq7qB05MkDf2OcQ==",
+			"dev": true,
+			"requires": {
+				"@lerna/check-working-tree": "3.16.5",
+				"@lerna/child-process": "3.16.5",
+				"@lerna/collect-updates": "3.18.0",
+				"@lerna/command": "3.18.0",
+				"@lerna/conventional-commits": "3.16.4",
+				"@lerna/github-client": "3.16.5",
+				"@lerna/gitlab-client": "3.15.0",
+				"@lerna/output": "3.13.0",
+				"@lerna/prerelease-id-from-version": "3.16.0",
+				"@lerna/prompt": "3.13.0",
+				"@lerna/run-lifecycle": "3.16.2",
+				"@lerna/run-topologically": "3.18.0",
+				"@lerna/validation-error": "3.13.0",
+				"chalk": "^2.3.1",
+				"dedent": "^0.7.0",
+				"load-json-file": "^5.3.0",
+				"minimatch": "^3.0.4",
+				"npmlog": "^4.1.2",
+				"p-map": "^2.1.0",
+				"p-pipe": "^1.2.0",
+				"p-reduce": "^1.0.0",
+				"p-waterfall": "^1.0.0",
+				"semver": "^6.2.0",
+				"slash": "^2.0.0",
+				"temp-write": "^3.4.0",
+				"write-json-file": "^3.2.0"
+			},
+			"dependencies": {
+				"load-json-file": {
+					"version": "5.3.0",
+					"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz",
+					"integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==",
+					"dev": true,
+					"requires": {
+						"graceful-fs": "^4.1.15",
+						"parse-json": "^4.0.0",
+						"pify": "^4.0.1",
+						"strip-bom": "^3.0.0",
+						"type-fest": "^0.3.0"
+					}
+				},
+				"pify": {
+					"version": "4.0.1",
+					"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+					"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+					"dev": true
+				},
+				"semver": {
+					"version": "6.3.0",
+					"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+					"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+					"dev": true
+				}
+			}
+		},
+		"@lerna/write-log-file": {
+			"version": "3.13.0",
+			"resolved": "https://registry.npmjs.org/@lerna/write-log-file/-/write-log-file-3.13.0.tgz",
+			"integrity": "sha512-RibeMnDPvlL8bFYW5C8cs4mbI3AHfQef73tnJCQ/SgrXZHehmHnsyWUiE7qDQCAo+B1RfTapvSyFF69iPj326A==",
+			"dev": true,
+			"requires": {
+				"npmlog": "^4.1.2",
+				"write-file-atomic": "^2.3.0"
+			}
+		},
+		"@mrmlnc/readdir-enhanced": {
+			"version": "2.2.1",
+			"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
+			"integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==",
+			"dev": true,
+			"requires": {
+				"call-me-maybe": "^1.0.1",
+				"glob-to-regexp": "^0.3.0"
+			}
+		},
+		"@nodelib/fs.stat": {
+			"version": "1.1.3",
+			"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz",
+			"integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
+			"dev": true
+		},
+		"@octokit/endpoint": {
+			"version": "5.5.1",
+			"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-5.5.1.tgz",
+			"integrity": "sha512-nBFhRUb5YzVTCX/iAK1MgQ4uWo89Gu0TH00qQHoYRCsE12dWcG1OiLd7v2EIo2+tpUKPMOQ62QFy9hy9Vg2ULg==",
+			"dev": true,
+			"requires": {
+				"@octokit/types": "^2.0.0",
+				"is-plain-object": "^3.0.0",
+				"universal-user-agent": "^4.0.0"
+			},
+			"dependencies": {
+				"is-plain-object": {
+					"version": "3.0.0",
+					"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.0.tgz",
+					"integrity": "sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==",
+					"dev": true,
+					"requires": {
+						"isobject": "^4.0.0"
+					}
+				},
+				"isobject": {
+					"version": "4.0.0",
+					"resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz",
+					"integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==",
+					"dev": true
+				}
+			}
+		},
+		"@octokit/plugin-enterprise-rest": {
+			"version": "3.6.2",
+			"resolved": "https://registry.npmjs.org/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-3.6.2.tgz",
+			"integrity": "sha512-3wF5eueS5OHQYuAEudkpN+xVeUsg8vYEMMenEzLphUZ7PRZ8OJtDcsreL3ad9zxXmBbaFWzLmFcdob5CLyZftA==",
+			"dev": true
+		},
+		"@octokit/request": {
+			"version": "5.3.1",
+			"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.3.1.tgz",
+			"integrity": "sha512-5/X0AL1ZgoU32fAepTfEoggFinO3rxsMLtzhlUX+RctLrusn/CApJuGFCd0v7GMFhF+8UiCsTTfsu7Fh1HnEJg==",
+			"dev": true,
+			"requires": {
+				"@octokit/endpoint": "^5.5.0",
+				"@octokit/request-error": "^1.0.1",
+				"@octokit/types": "^2.0.0",
+				"deprecation": "^2.0.0",
+				"is-plain-object": "^3.0.0",
+				"node-fetch": "^2.3.0",
+				"once": "^1.4.0",
+				"universal-user-agent": "^4.0.0"
+			},
+			"dependencies": {
+				"is-plain-object": {
+					"version": "3.0.0",
+					"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.0.tgz",
+					"integrity": "sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==",
+					"dev": true,
+					"requires": {
+						"isobject": "^4.0.0"
+					}
+				},
+				"isobject": {
+					"version": "4.0.0",
+					"resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz",
+					"integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==",
+					"dev": true
+				}
+			}
+		},
+		"@octokit/request-error": {
+			"version": "1.2.0",
+			"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-1.2.0.tgz",
+			"integrity": "sha512-DNBhROBYjjV/I9n7A8kVkmQNkqFAMem90dSxqvPq57e2hBr7mNTX98y3R2zDpqMQHVRpBDjsvsfIGgBzy+4PAg==",
+			"dev": true,
+			"requires": {
+				"@octokit/types": "^2.0.0",
+				"deprecation": "^2.0.0",
+				"once": "^1.4.0"
+			}
+		},
+		"@octokit/rest": {
+			"version": "16.34.1",
+			"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-16.34.1.tgz",
+			"integrity": "sha512-JUoS12cdktf1fv86rgrjC/RvYLuL+o7p57W7zX1x7ANFJ7OvdV8emvUNkFlcidEaOkYrxK3SoWgQFt3FhNmabA==",
+			"dev": true,
+			"requires": {
+				"@octokit/request": "^5.2.0",
+				"@octokit/request-error": "^1.0.2",
+				"atob-lite": "^2.0.0",
+				"before-after-hook": "^2.0.0",
+				"btoa-lite": "^1.0.0",
+				"deprecation": "^2.0.0",
+				"lodash.get": "^4.4.2",
+				"lodash.set": "^4.3.2",
+				"lodash.uniq": "^4.5.0",
+				"octokit-pagination-methods": "^1.1.0",
+				"once": "^1.4.0",
+				"universal-user-agent": "^4.0.0"
+			}
+		},
+		"@octokit/types": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.0.1.tgz",
+			"integrity": "sha512-YDYgV6nCzdGdOm7wy43Ce8SQ3M5DMKegB8E5sTB/1xrxOdo2yS/KgUgML2N2ZGD621mkbdrAglwTyA4NDOlFFA==",
+			"dev": true,
+			"requires": {
+				"@types/node": ">= 8"
+			}
+		},
+		"@types/babel__core": {
+			"version": "7.1.3",
+			"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz",
+			"integrity": "sha512-8fBo0UR2CcwWxeX7WIIgJ7lXjasFxoYgRnFHUj+hRvKkpiBJbxhdAPTCY6/ZKM0uxANFVzt4yObSLuTiTnazDA==",
+			"dev": true,
+			"requires": {
+				"@babel/parser": "^7.1.0",
+				"@babel/types": "^7.0.0",
+				"@types/babel__generator": "*",
+				"@types/babel__template": "*",
+				"@types/babel__traverse": "*"
+			}
+		},
+		"@types/babel__generator": {
+			"version": "7.6.0",
+			"resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.0.tgz",
+			"integrity": "sha512-c1mZUu4up5cp9KROs/QAw0gTeHrw/x7m52LcnvMxxOZ03DmLwPV0MlGmlgzV3cnSdjhJOZsj7E7FHeioai+egw==",
+			"dev": true,
+			"requires": {
+				"@babel/types": "^7.0.0"
+			}
+		},
+		"@types/babel__template": {
+			"version": "7.0.2",
+			"resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz",
+			"integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==",
+			"dev": true,
+			"requires": {
+				"@babel/parser": "^7.1.0",
+				"@babel/types": "^7.0.0"
+			}
+		},
+		"@types/babel__traverse": {
+			"version": "7.0.7",
+			"resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.7.tgz",
+			"integrity": "sha512-CeBpmX1J8kWLcDEnI3Cl2Eo6RfbGvzUctA+CjZUhOKDFbLfcr7fc4usEqLNWetrlJd7RhAkyYe2czXop4fICpw==",
+			"dev": true,
+			"requires": {
+				"@babel/types": "^7.3.0"
+			}
+		},
+		"@types/events": {
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
+			"integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==",
+			"dev": true
+		},
+		"@types/glob": {
+			"version": "7.1.1",
+			"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz",
+			"integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==",
+			"dev": true,
+			"requires": {
+				"@types/events": "*",
+				"@types/minimatch": "*",
+				"@types/node": "*"
+			}
+		},
+		"@types/istanbul-lib-coverage": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz",
+			"integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==",
+			"dev": true
+		},
+		"@types/istanbul-lib-report": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz",
+			"integrity": "sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==",
+			"dev": true,
+			"requires": {
+				"@types/istanbul-lib-coverage": "*"
+			}
+		},
+		"@types/istanbul-reports": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz",
+			"integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==",
+			"dev": true,
+			"requires": {
+				"@types/istanbul-lib-coverage": "*",
+				"@types/istanbul-lib-report": "*"
+			}
+		},
+		"@types/json-schema": {
+			"version": "7.0.3",
+			"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.3.tgz",
+			"integrity": "sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==",
+			"dev": true
+		},
+		"@types/minimatch": {
+			"version": "3.0.3",
+			"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
+			"integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
+			"dev": true
+		},
+		"@types/node": {
+			"version": "12.12.6",
+			"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.6.tgz",
+			"integrity": "sha512-FjsYUPzEJdGXjwKqSpE0/9QEh6kzhTAeObA54rn6j3rR4C/mzpI9L0KNfoeASSPMMdxIsoJuCLDWcM/rVjIsSA==",
+			"dev": true
+		},
+		"@types/stack-utils": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",
+			"integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==",
+			"dev": true
+		},
+		"@types/yargs": {
+			"version": "13.0.3",
+			"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.3.tgz",
+			"integrity": "sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ==",
+			"dev": true,
+			"requires": {
+				"@types/yargs-parser": "*"
+			}
+		},
+		"@types/yargs-parser": {
+			"version": "13.1.0",
+			"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.1.0.tgz",
+			"integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==",
+			"dev": true
+		},
+		"@typescript-eslint/experimental-utils": {
+			"version": "2.6.1",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.6.1.tgz",
+			"integrity": "sha512-EVrrUhl5yBt7fC7c62lWmriq4MIc49zpN3JmrKqfiFXPXCM5ErfEcZYfKOhZXkW6MBjFcJ5kGZqu1b+lyyExUw==",
+			"dev": true,
+			"requires": {
+				"@types/json-schema": "^7.0.3",
+				"@typescript-eslint/typescript-estree": "2.6.1",
+				"eslint-scope": "^5.0.0"
+			},
+			"dependencies": {
+				"eslint-scope": {
+					"version": "5.0.0",
+					"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz",
+					"integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==",
+					"dev": true,
+					"requires": {
+						"esrecurse": "^4.1.0",
+						"estraverse": "^4.1.1"
+					}
+				}
+			}
+		},
+		"@typescript-eslint/typescript-estree": {
+			"version": "2.6.1",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.6.1.tgz",
+			"integrity": "sha512-+sTnssW6bcbDZKE8Ce7VV6LdzkQz2Bxk7jzk1J8H1rovoTxnm6iXvYIyncvNsaB/kBCOM63j/LNJfm27bNdUoA==",
+			"dev": true,
+			"requires": {
+				"debug": "^4.1.1",
+				"glob": "^7.1.4",
+				"is-glob": "^4.0.1",
+				"lodash.unescape": "4.0.1",
+				"semver": "^6.3.0",
+				"tsutils": "^3.17.1"
+			},
+			"dependencies": {
+				"semver": {
+					"version": "6.3.0",
+					"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+					"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+					"dev": true
+				}
+			}
+		},
+		"@zkochan/cmd-shim": {
+			"version": "3.1.0",
+			"resolved": "https://registry.npmjs.org/@zkochan/cmd-shim/-/cmd-shim-3.1.0.tgz",
+			"integrity": "sha512-o8l0+x7C7sMZU3v9GuJIAU10qQLtwR1dtRQIOmlNMtyaqhmpXOzx1HWiYoWfmmf9HHZoAkXpc9TM9PQYF9d4Jg==",
+			"dev": true,
+			"requires": {
+				"is-windows": "^1.0.0",
+				"mkdirp-promise": "^5.0.1",
+				"mz": "^2.5.0"
+			}
+		},
+		"JSONStream": {
+			"version": "1.3.5",
+			"resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz",
+			"integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==",
+			"dev": true,
+			"requires": {
+				"jsonparse": "^1.2.0",
+				"through": ">=2.2.7 <3"
+			}
+		},
+		"abab": {
+			"version": "2.0.2",
+			"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.2.tgz",
+			"integrity": "sha512-2scffjvioEmNz0OyDSLGWDfKCVwaKc6l9Pm9kOIREU13ClXZvHpg/nRL5xyjSSSLhOnXqft2HpsAzNEEA8cFFg==",
+			"dev": true
+		},
+		"abbrev": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+			"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+			"dev": true
+		},
+		"acorn": {
+			"version": "6.3.0",
+			"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz",
+			"integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==",
+			"dev": true
+		},
+		"acorn-globals": {
+			"version": "4.3.4",
+			"resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz",
+			"integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==",
+			"dev": true,
+			"requires": {
+				"acorn": "^6.0.1",
+				"acorn-walk": "^6.0.1"
+			}
+		},
+		"acorn-jsx": {
+			"version": "5.1.0",
+			"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz",
+			"integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==",
+			"dev": true
+		},
+		"acorn-walk": {
+			"version": "6.2.0",
+			"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz",
+			"integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==",
+			"dev": true
+		},
+		"agent-base": {
+			"version": "4.3.0",
+			"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz",
+			"integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
+			"dev": true,
+			"requires": {
+				"es6-promisify": "^5.0.0"
+			}
+		},
+		"agentkeepalive": {
+			"version": "3.5.2",
+			"resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz",
+			"integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==",
+			"dev": true,
+			"requires": {
+				"humanize-ms": "^1.2.1"
+			}
+		},
+		"ajv": {
+			"version": "6.10.2",
+			"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+			"integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+			"dev": true,
+			"requires": {
+				"fast-deep-equal": "^2.0.1",
+				"fast-json-stable-stringify": "^2.0.0",
+				"json-schema-traverse": "^0.4.1",
+				"uri-js": "^4.2.2"
+			}
+		},
+		"ansi-escapes": {
+			"version": "3.2.0",
+			"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
+			"integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
+			"dev": true
+		},
+		"ansi-regex": {
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+			"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+			"dev": true
+		},
+		"ansi-styles": {
+			"version": "3.2.1",
+			"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+			"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+			"dev": true,
+			"requires": {
+				"color-convert": "^1.9.0"
+			}
+		},
+		"any-promise": {
+			"version": "1.3.0",
+			"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+			"integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=",
+			"dev": true
+		},
+		"anymatch": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+			"integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+			"dev": true,
+			"requires": {
+				"micromatch": "^3.1.4",
+				"normalize-path": "^2.1.1"
+			}
+		},
+		"aproba": {
+			"version": "1.2.0",
+			"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+			"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+			"dev": true
+		},
+		"are-we-there-yet": {
+			"version": "1.1.5",
+			"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
+			"integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
+			"dev": true,
+			"requires": {
+				"delegates": "^1.0.0",
+				"readable-stream": "^2.0.6"
+			}
+		},
+		"argparse": {
+			"version": "1.0.10",
+			"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+			"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+			"dev": true,
+			"requires": {
+				"sprintf-js": "~1.0.2"
+			}
+		},
+		"arr-diff": {
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+			"integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+			"dev": true
+		},
+		"arr-flatten": {
+			"version": "1.1.0",
+			"resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",