Skip to content

Commit

Permalink
(core) bump mocha version to allow parallel tests; move more tests to…
Browse files Browse the repository at this point in the history
… core

Summary:
This uses a newer version of mocha in grist-core so that tests can be run in parallel. That allows more tests to be moved without slowing things down overall. Tests moved are venerable browser tests; only the ones that "just work" or worked without too much trouble to are moved, in order to keep the diff from growing too large. Will wrestle with more in follow up.

Parallelism is at the file level, rather than the individual test.

The newer version of mocha isn't needed for grist-saas repo; tests are parallelized in our internal CI by other means. I've chosen to allocate files to workers in a cruder way than our internal CI, based on initial characters rather than an automated process. The automated process would need some reworking to be compatible with mocha running in parallel mode.

Test Plan: this diff was tested first on grist-core, then ported to grist-saas so saas repo history will correctly track history of moved files.

Reviewers: jarek

Reviewed By: jarek

Subscribers: jarek

Differential Revision: https://phab.getgrist.com/D3927
  • Loading branch information
paulfitz committed Jun 27, 2023
1 parent 7d3b4b4 commit bcbf57d
Show file tree
Hide file tree
Showing 126 changed files with 6,833 additions and 759 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module.exports = {
env: {
node: true,
es6: true,
mocha: true,
},
// Set parser to support, e.g. import() function for dynamic imports (see
// https://stackoverflow.com/a/47833471/328565 and https://stackoverflow.com/a/69557309/328565).
Expand Down
17 changes: 10 additions & 7 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,21 @@ jobs:
build_and_test:
runs-on: ubuntu-latest
strategy:
# it is helpful to know which sets of tests would have succeeded,
# even when there is a failure.
fail-fast: false
matrix:
python-version: [3.9]
node-version: [14.x]
tests:
- ':lint:python:client:common:smoke:'
- ':server-1-of-2:'
- ':server-2-of-2:'
- ':nbrowser-1-of-5:'
- ':nbrowser-2-of-5:'
- ':nbrowser-3-of-5:'
- ':nbrowser-4-of-5:'
- ':nbrowser-5-of-5:'
- ':nbrowser-^[A-G]:'
- ':nbrowser-^[H-L]:'
- ':nbrowser-^[M-O]:'
- ':nbrowser-^[P-S]:'
- ':nbrowser-^[^A-S]:'
steps:
- uses: actions/checkout@v3

Expand Down Expand Up @@ -95,8 +98,8 @@ jobs:
- name: Run main tests without minio and redis
if: contains(matrix.tests, ':nbrowser-')
run: |
export TEST_SPLITS=$(echo $TESTS | sed "s/.*:nbrowser-\([^:]*\).*/\1/")
MOCHA_WEBDRIVER_HEADLESS=1 yarn run test:nbrowser
export GREP_TESTS=$(echo $TESTS | sed "s/.*:nbrowser-\([^:]*\).*/\1/")
MOCHA_WEBDRIVER_SKIP_CLEANUP=1 MOCHA_WEBDRIVER_HEADLESS=1 yarn run test:nbrowser --parallel --jobs 3
env:
TESTS: ${{ matrix.tests }}

Expand Down
7 changes: 7 additions & 0 deletions buildtools/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ module.exports = {
account: "app/client/accountMain",
billing: "app/client/billingMain",
activation: "app/client/activationMain",
test: "test/client-harness/client",
},
output: {
filename: "[name].bundle.js",
Expand Down Expand Up @@ -78,4 +79,10 @@ module.exports = {
// To strip all locales except “en”
new MomentLocalesPlugin()
],
externals: {
// for test bundle: jsdom should not be touched within browser
jsdom: 'alert',
// for test bundle: jquery will be available as jQuery
jquery: 'jQuery'
},
};
24 changes: 16 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
"install:python3": "buildtools/prepare_python3.sh",
"build:prod": "buildtools/build.sh",
"start:prod": "sandbox/run.sh",
"test": "GRIST_SESSION_COOKIE=grist_test_cookie GRIST_TEST_LOGIN=1 TEST_SUPPORT_API_KEY=api_key_for_support TEST_CLEAN_DATABASE=true NODE_PATH=_build:_build/stubs:_build/ext mocha ${DEBUG:+-b --no-exit} --slow 8000 ${DEBUG:---forbid-only} -g ${GREP_TESTS:-''} '_build/test/common/*.js' '_build/test/client/*.js' '_build/test/nbrowser/*.js' '_build/test/server/**/*.js' '_build/test/gen-server/**/*.js'",
"test:nbrowser": "TEST_SUITE=nbrowser TEST_SUITE_FOR_TIMINGS=nbrowser TIMINGS_FILE=test/timings/nbrowser.txt GRIST_SESSION_COOKIE=grist_test_cookie GRIST_TEST_LOGIN=1 TEST_SUPPORT_API_KEY=api_key_for_support TEST_CLEAN_DATABASE=true NODE_PATH=_build:_build/stubs:_build/ext mocha ${DEBUG:+-b --no-exit} ${DEBUG:---forbid-only} -g ${GREP_TESTS:-''} --slow 8000 -R test/xunit-file '_build/test/nbrowser/**/*.js'",
"test:client": "GRIST_SESSION_COOKIE=grist_test_cookie NODE_PATH=_build:_build/stubs:_build/ext mocha ${DEBUG:+'-b'} '_build/test/client/**/*.js'",
"test:common": "GRIST_SESSION_COOKIE=grist_test_cookie NODE_PATH=_build:_build/stubs:_build/ext mocha ${DEBUG:+'-b'} '_build/test/common/**/*.js'",
"test:server": "TEST_SUITE=server TEST_SUITE_FOR_TIMINGS=server TIMINGS_FILE=test/timings/server.txt GRIST_SESSION_COOKIE=grist_test_cookie NODE_PATH=_build:_build/stubs:_build/ext mocha ${DEBUG:+'-b'} -R test/xunit-file '_build/test/server/**/*.js' '_build/test/gen-server/**/*.js'",
"test:smoke": "NODE_PATH=_build:_build/stubs:_build/ext mocha _build/test/nbrowser/Smoke.js",
"test": "GRIST_SESSION_COOKIE=grist_test_cookie GRIST_TEST_LOGIN=1 TEST_SUPPORT_API_KEY=api_key_for_support TEST_CLEAN_DATABASE=true mocha ${DEBUG:+-b --no-exit} --slow 8000 ${DEBUG:---forbid-only} -g \"${GREP_TESTS}\" '_build/test/common/*.js' '_build/test/client/*.js' '_build/test/nbrowser/*.js' '_build/test/server/**/*.js' '_build/test/gen-server/**/*.js'",
"test:nbrowser": "TEST_SUITE=nbrowser TEST_SUITE_FOR_TIMINGS=nbrowser TIMINGS_FILE=test/timings/nbrowser.txt GRIST_SESSION_COOKIE=grist_test_cookie GRIST_TEST_LOGIN=1 TEST_SUPPORT_API_KEY=api_key_for_support TEST_CLEAN_DATABASE=true mocha ${DEBUG:+-b --no-exit} ${DEBUG:---forbid-only} -g \"${GREP_TESTS}\" --slow 8000 -R test/xunit-file '_build/test/nbrowser/**/*.js'",
"test:client": "GRIST_SESSION_COOKIE=grist_test_cookie mocha ${DEBUG:+'-b'} '_build/test/client/**/*.js'",
"test:common": "GRIST_SESSION_COOKIE=grist_test_cookie mocha ${DEBUG:+'-b'} '_build/test/common/**/*.js'",
"test:server": "TEST_SUITE=server TEST_SUITE_FOR_TIMINGS=server TIMINGS_FILE=test/timings/server.txt GRIST_SESSION_COOKIE=grist_test_cookie mocha ${DEBUG:+'-b'} -R test/xunit-file '_build/test/server/**/*.js' '_build/test/gen-server/**/*.js'",
"test:smoke": "mocha _build/test/nbrowser/Smoke.js",
"test:docker": "./test/test_under_docker.sh",
"test:python": "sandbox_venv3/bin/python sandbox/grist/runtests.py ${GREP_TESTS:+discover -p \"test*${GREP_TESTS}*.py\"}",
"cli": "NODE_PATH=_build:_build/stubs:_build/ext node _build/app/server/companion.js",
Expand Down Expand Up @@ -91,8 +91,8 @@
"http-proxy": "1.18.1",
"i18next-scanner": "4.1.0",
"jsdom": "16.5.0",
"mocha": "5.2.0",
"mocha-webdriver": "0.2.9",
"mocha": "10.2.0",
"mocha-webdriver": "0.2.13",
"moment-locales-webpack-plugin": "^1.2.0",
"nodemon": "^2.0.4",
"otplib": "12.0.1",
Expand Down Expand Up @@ -187,5 +187,13 @@
"jquery": "3.5.0",
"ts-interface-checker": "1.0.2",
"@gristlabs/sqlite3": "5.1.4-grist.8"
},
"mocha": {
"require": ["test/setupPaths",
"source-map-support/register",
"test/report-why-tests-hang",
"test/init-mocha-webdriver",
"test/split-tests",
"test/chai-as-promised"]
}
}
1 change: 1 addition & 0 deletions static/mocha.css
1 change: 1 addition & 0 deletions static/mocha.js
104 changes: 104 additions & 0 deletions static/test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8">
<base href="/v/gtag/">
<title>Grist Tests</title>
<script src="jquery/dist/jquery.min.js"></script>
<script src="plotly/plotly-latest.min.js"></script>
<script src="./mocha.js"></script>
<script>mocha.setup('bdd')</script>
<script src="./test.bundle.js"></script>
<script>
onload = function() {
$('#app-test').ready(function() {
try {
window.loadTests();
} catch (err) {
console.log("ERROR", err);
mocha.failedTests = [];
mocha.failedTests.push({title: 'Failed to load', error: err.toString()});
document.getElementById('mocha-status').textContent = 'DONE - FAILED TO LOAD';
return;
}

mocha.checkLeaks();
// fxdriver_id is set by selenium, execWebdriverJQuery by webdriverjq.js.
mocha.globals(['cmd', 'fxdriver_id', 'execWebdriverJQuery']);
var runner = mocha.run();
mocha.failedTests = [];
runner.on('fail', function(test, err) {
mocha.failedTests.push({title: test.fullTitle(), error: err.toString()});
});
runner.on('end', function() {
document.getElementById('mocha-status').textContent = runner.failures > 0 ? 'DONE - FAILURE :(' : 'DONE - SUCCESS :)';
});
});
};

function scrollToBottom() {
var bottom = document.getElementById('mocha-end');
bottom.scrollIntoView(true);
}

afterEach(function() {
// keep scrolled to the bottom
return scrollToBottom();
});

after(function() {
// keep scrolled to the bottom
return scrollToBottom();
});
</script>

<style>
#mocha {
width: 50%;
}

#app-test {
position: fixed;
margin: -8px;
width: 40%;
height: 80%;
top: 20%;
left: 60%;
}

#mocha-status {
position: fixed;
bottom: 0px;
padding: 1rem;
border: 2px solid #cc9;
font-family: Helvetica, Arial, sans-serif;
}

/* mostly match #mocha-stats class */
.extra-info {
position: fixed;
top: 60px;
right: 10px;
font-size: 12px;
color: #888;
z-index: 1;
}

</style>

<link rel="stylesheet" href="./mocha.css">
</head>

<body>
<div id="mocha">
<div class="extra-info">
<a href="/test.html?timing=1">Run tests with timings</a>
</div>
</div>
<div id="mocha-end">&nbsp;</div>
<div id="mocha-status">TBD - RUNNING...</div>
</body>

</html>

24 changes: 24 additions & 0 deletions static/testWebdriverJQuery.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<base href="/v/gtag/">
<title>WebdriverJQuery test</title>
<script src="jquery/dist/jquery.min.js"></script>
</head>

<body>
<div class="foo bar">
<span class="baz">
Hello world
</span>
</div>
<div class="bar">
<span class="baz">
Good bye
<input id="btn" type="button" value="Go" onclick="this.value += 'o'">
</span>
</div>
</body>

</html>
3 changes: 3 additions & 0 deletions stubs/app/server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ export async function main() {
if (process.env.GRIST_TESTING_SOCKET) {
await server.addTestingHooks();
}
if (process.env.GRIST_SERVE_PLUGINS_PORT) {
await server.startCopy('pluginServer', parseInt(process.env.GRIST_SERVE_PLUGINS_PORT, 10));
}
return server;
}

Expand Down
30 changes: 30 additions & 0 deletions test/client-harness/client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* global window */
window.loadTests = function() {
require('test/common/BinaryIndexedTree');
require('test/common/CircularArray');
require('test/common/MemBuffer');
require('test/common/arraySplice');
require('test/common/gutil');
require('test/common/marshal');
require('test/common/promises');
require('test/common/serializeTiming');
require('test/common/timeFormat');
require('test/common/ValueFormatter');
require('test/common/InactivityTimer');

require('test/client/clientUtil');
require('test/client/components/Layout');
require('test/client/components/commands');
require('test/client/components/sampleLayout');
require('test/client/lib/ObservableMap');
require('test/client/lib/ObservableSet');
require('test/client/lib/dispose');
require('test/client/lib/dom');
require('test/client/lib/koArray');
require('test/client/lib/koDom');
require('test/client/lib/koForm');
require('test/client/lib/koUtil');
require('test/client/models/modelUtil');
require('test/client/models/rowset');
require('test/client/lib/localStorageObs');
}
1 change: 0 additions & 1 deletion test/client/clientUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ function setTmpMochaGlobals() {
return;
}

/* global before, after */
const {JSDOM} = require('jsdom');

var prevGlobals;
Expand Down
2 changes: 0 additions & 2 deletions test/client/components/Layout.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* global describe, beforeEach, afterEach, it */

var assert = require('chai').assert;
var clientUtil = require('../clientUtil');
var dom = require('app/client/lib/dom');
Expand Down
2 changes: 0 additions & 2 deletions test/client/components/commands.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* global describe, beforeEach, before, after, it */

var _ = require('underscore');
var sinon = require('sinon');
var assert = require('chai').assert;
Expand Down
2 changes: 0 additions & 2 deletions test/client/lib/Delay.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* global describe, it */

var assert = require('chai').assert;
var sinon = require('sinon');
var Promise = require('bluebird');
Expand Down
2 changes: 0 additions & 2 deletions test/client/lib/ObservableMap.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* global describe, it, before */

const assert = require('chai').assert;
const ko = require('knockout');

Expand Down
2 changes: 0 additions & 2 deletions test/client/lib/ObservableSet.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* global describe, it */

var assert = require('chai').assert;
var ko = require('knockout');

Expand Down
13 changes: 8 additions & 5 deletions test/client/lib/dispose.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* global describe, it, before, after */

var dispose = require('app/client/lib/dispose');

var bluebird = require('bluebird');
Expand All @@ -9,6 +7,8 @@ var sinon = require('sinon');
var clientUtil = require('../clientUtil');
var dom = require('app/client/lib/dom');

require('chai').config.truncateThreshold = 10000;

describe('dispose', function() {

clientUtil.setTmpMochaGlobals();
Expand Down Expand Up @@ -153,9 +153,12 @@ describe('dispose', function() {
assert.equal(baz.dispose.callCount, 1);
assert(baz.dispose.calledBefore(bar.dispose));

assert.deepEqual(consoleErrors[0], ['Error constructing %s:', 'Foo', 'Error: test-error1']);
assert.deepEqual(consoleErrors[1], ['Error constructing %s:', 'Foo', 'Error: test-error2']);
assert.deepEqual(consoleErrors[2], ['Error constructing %s:', 'Foo', 'Error: test-error3']);
const name = consoleErrors[0][1]; // may be Foo, or minified.
assert(name === 'Foo' || name === 'o'); // this may not be reliable,
// just what I happen to see.
assert.deepEqual(consoleErrors[0], ['Error constructing %s:', name, 'Error: test-error1']);
assert.deepEqual(consoleErrors[1], ['Error constructing %s:', name, 'Error: test-error2']);
assert.deepEqual(consoleErrors[2], ['Error constructing %s:', name, 'Error: test-error3']);
assert.equal(consoleErrors.length, 3);
});

Expand Down
2 changes: 0 additions & 2 deletions test/client/lib/dom.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* global describe, it, before, after */

var assert = require('chai').assert;
var sinon = require('sinon');
var Promise = require('bluebird');
Expand Down
2 changes: 0 additions & 2 deletions test/client/lib/koArray.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* global describe, it */

var _ = require('underscore');
var assert = require('assert');
var ko = require('knockout');
Expand Down
2 changes: 0 additions & 2 deletions test/client/lib/koDom.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* global describe, it */

var assert = require('assert');
var ko = require('knockout');
var sinon = require('sinon');
Expand Down
2 changes: 0 additions & 2 deletions test/client/lib/koDomScrolly.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ const G = require('app/client/lib/browserGlobals').get('window', '$');
const sinon = require('sinon');
const assert = require('assert');

/* global describe, it, after, before, beforeEach */

describe("koDomScrolly", function() {

clientUtil.setTmpMochaGlobals();
Expand Down
2 changes: 0 additions & 2 deletions test/client/lib/koForm.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* global describe, it */

var assert = require('chai').assert;
var ko = require('knockout');

Expand Down
2 changes: 0 additions & 2 deletions test/client/lib/koUtil.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* global describe, it */

var assert = require('assert');
var ko = require('knockout');
var sinon = require('sinon');
Expand Down
2 changes: 0 additions & 2 deletions test/client/models/modelUtil.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* global describe, it */

var assert = require('assert');
var ko = require('knockout');

Expand Down
Loading

0 comments on commit bcbf57d

Please sign in to comment.