Update electron to 16.0.4

This commit is contained in:
Fedor Indutny 2021-12-09 09:06:04 +01:00 committed by GitHub
parent ba043c422b
commit bbc13d058e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 491 additions and 2985 deletions

View File

@ -31,7 +31,7 @@ jobs:
- name: Setup node.js
uses: actions/setup-node@v2
with:
node-version: '16.5.0'
node-version: '16.9.1'
- name: Install global dependencies
run: npm install -g yarn@1.22.10 typescript@4.4.2 ts-node@10.2.1

View File

@ -14,7 +14,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16.5.0'
node-version: '16.9.1'
- run: npm install -g yarn@1.22.10
- name: Cache Desktop node_modules
@ -43,7 +43,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16.5.0'
node-version: '16.9.1'
- run: npm install -g yarn@1.22.10
- name: Cache Desktop node_modules
@ -63,7 +63,7 @@ jobs:
run: yarn electron:install-app-deps
- run: yarn test-node
- run: yarn test-electron
- run: yarn grunt test-release:osx
- run: yarn test-release
env:
NODE_ENV: production
@ -77,7 +77,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16.5.0'
node-version: '16.9.1'
- run: sudo apt-get install xvfb
- run: npm install -g yarn@1.22.10
@ -99,7 +99,7 @@ jobs:
env:
LANG: en_US
LANGUAGE: en_US
- run: xvfb-run --auto-servernum yarn grunt test-release:linux
- run: xvfb-run --auto-servernum yarn test-release
env:
NODE_ENV: production
@ -114,7 +114,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16.5.0'
node-version: '16.9.1'
- run: npm install -g yarn@1.22.10
- name: Cache Desktop node_modules
@ -135,7 +135,7 @@ jobs:
- run: type temp.json | findstr /v certificateSubjectName | findstr /v certificateSha1 > package.json
- run: yarn prepare-beta-build
- run: yarn build
- run: node build\grunt.js test
- run: node build\grunt.js test-release:win
- run: yarn test-electron
- run: yarn test-release
env:
SIGNAL_ENV: production

2
.gitignore vendored
View File

@ -21,9 +21,7 @@ tsconfig.tsbuildinfo
js/components.js
js/util_worker.js
libtextsecure/components.js
libtextsecure/test/test.js
stylesheets/*.css
test/test.js
/storybook-static/
preload.bundle.*
ts/sql/mainWorker.bundle.js.LICENSE.txt

2
.nvmrc
View File

@ -1 +1 @@
16.5.0
16.9.1

View File

@ -281,7 +281,7 @@ yarn generate
yarn build
```
Then, run the tests using `grunt test-release:osx --dir=release`, replacing `osx` with `linux` or `win` depending on your platform.
Then, run the tests using `yarn test-release`.
## Translations

View File

@ -1,36 +1,14 @@
// Copyright 2014-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
const { join } = require('path');
const importOnce = require('node-sass-import-once');
const rimraf = require('rimraf');
const mkdirp = require('mkdirp');
const spectron = require('spectron');
const asar = require('asar');
const fs = require('fs');
const os = require('os');
const assert = require('assert');
const sass = require('node-sass');
const packageJson = require('./package.json');
/* eslint-disable more/no-then, no-console */
module.exports = grunt => {
async function promiseToAsyncGruntTask(promise, gruntDone) {
let succeeded = false;
try {
await promise;
succeeded = true;
} catch (err) {
grunt.log.error(err);
}
if (succeeded) {
gruntDone();
} else {
gruntDone(false);
}
}
const bower = grunt.file.readJSON('bower.json');
const components = [];
// eslint-disable-next-line guard-for-in, no-restricted-syntax
@ -47,23 +25,6 @@ module.exports = grunt => {
src: components,
dest: 'js/components.js',
},
test: {
src: [
'node_modules/mocha/mocha.js',
'node_modules/chai/chai.js',
'test/_test.js',
],
dest: 'test/test.js',
},
libtextsecuretest: {
src: [
'node_modules/jquery/dist/jquery.js',
'node_modules/mocha/mocha.js',
'node_modules/chai/chai.js',
'libtextsecure/test/_test.js',
],
dest: 'libtextsecure/test/test.js',
},
},
sass: {
options: {
@ -116,24 +77,6 @@ module.exports = grunt => {
cmd: 'yarn build-protobuf',
},
},
'test-release': {
osx: {
archive: `mac/${packageJson.productName}.app/Contents/Resources/app.asar`,
exe: `mac/${packageJson.productName}.app/Contents/MacOS/${packageJson.productName}`,
},
mas: {
archive: 'mas/Signal.app/Contents/Resources/app.asar',
exe: `mas/${packageJson.productName}.app/Contents/MacOS/${packageJson.productName}`,
},
linux: {
archive: 'linux-unpacked/resources/app.asar',
exe: `linux-unpacked/${packageJson.name}`,
},
win: {
archive: 'win-unpacked/resources/app.asar',
exe: `win-unpacked/${packageJson.productName}.exe`,
},
},
gitinfo: {}, // to be populated by grunt gitinfo
});
@ -187,238 +130,12 @@ module.exports = grunt => {
mkdirp.sync('release');
});
async function runTests(environment) {
const { Application } = spectron;
const electronBinary =
process.platform === 'win32' ? 'electron.cmd' : 'electron';
const path = join(__dirname, 'node_modules', '.bin', electronBinary);
const args = [join(__dirname, 'app', 'main.js')];
grunt.log.writeln('Starting path', path, 'with args', args);
const app = new Application({
path,
args,
env: {
NODE_ENV: environment,
},
requireName: 'unused',
startTimeout: 30000,
});
function getMochaResults() {
// eslint-disable-next-line no-undef
return window.mochaResults;
}
async function logForFailure() {
const temporaryDirectory = join(
os.tmpdir(),
`Signal-Desktop-tests--${Date.now()}-${Math.random()
.toString()
.slice(2)}`
);
const renderProcessLogPath = join(
temporaryDirectory,
'render-process.log'
);
const mainProcessLogPath = join(temporaryDirectory, 'main-process.log');
await fs.promises.mkdir(temporaryDirectory, { recursive: true });
await Promise.all([
(async () => {
const logs = await app.client.getRenderProcessLogs();
await fs.promises.writeFile(
renderProcessLogPath,
logs.map(log => JSON.stringify(log)).join('\n')
);
})(),
(async () => {
const logs = await app.client.getMainProcessLogs();
await fs.promises.writeFile(mainProcessLogPath, logs.join('\n'));
})(),
]);
console.error();
grunt.log.error(
`Renderer process logs written to ${renderProcessLogPath}`
);
grunt.log.error(`Renderer process logs written to ${mainProcessLogPath}`);
grunt.log.error(
`For easier debugging, try NODE_ENV='${environment}' yarn start`
);
console.error();
}
try {
await app.start();
grunt.log.writeln('App started. Now waiting for test results...');
await app.client.waitUntil(
() =>
app.client.execute(getMochaResults).then(data => Boolean(data.value)),
25000,
'Expected to find window.mochaResults set!'
);
const results = (await app.client.execute(getMochaResults)).value;
if (!results) {
await logForFailure();
throw new Error("Couldn't extract test results");
}
if (results.failures > 0) {
const errorMessage = `Found ${results.failures} failing test${
results.failures === 1 ? '' : 's'
}.`;
grunt.log.error(errorMessage);
results.reports.forEach(report => {
grunt.log.error(JSON.stringify(report, null, 2));
});
await logForFailure();
throw new Error(errorMessage);
}
grunt.log.ok(`${results.passes} tests passed.`);
} finally {
if (app.isRunning()) {
await app.stop();
}
}
}
grunt.registerTask(
'unit-tests',
'Run unit tests w/Electron',
function thisNeeded() {
const environment = grunt.option('env') || 'test';
promiseToAsyncGruntTask(runTests(environment), this.async());
}
);
grunt.registerTask(
'lib-unit-tests',
'Run libtextsecure unit tests w/Electron',
function thisNeeded() {
const environment = grunt.option('env') || 'test-lib';
promiseToAsyncGruntTask(runTests(environment), this.async());
}
);
grunt.registerMultiTask(
'test-release',
'Test packaged releases',
function thisNeeded() {
const dir = grunt.option('dir') || 'release';
const environment = grunt.option('env') || 'production';
const config = this.data;
const archive = [dir, config.archive].join('/');
const files = [
'config/default.json',
`config/${environment}.json`,
`config/local-${environment}.json`,
];
console.log(this.target, archive);
const releaseFiles = files.concat(config.files || []);
releaseFiles.forEach(fileName => {
console.log(fileName);
try {
asar.statFile(archive, fileName);
return true;
} catch (e) {
console.log(e);
throw new Error(`Missing file ${fileName}`);
}
});
if (config.appUpdateYML) {
const appUpdateYML = [dir, config.appUpdateYML].join('/');
if (fs.existsSync(appUpdateYML)) {
console.log('auto update ok');
} else {
throw new Error(`Missing auto update config ${appUpdateYML}`);
}
}
const done = this.async();
// A simple test to verify a visible window is opened with a title
const { Application } = spectron;
const path = [dir, config.exe].join('/');
console.log('Starting path', path);
const app = new Application({
path,
});
const sleep = millis =>
new Promise(resolve => setTimeout(resolve, millis));
Promise.race([app.start(), sleep(15000)])
.then(() => {
if (!app.isRunning()) {
throw new Error('Application failed to start');
}
return app.client.getWindowCount();
})
.then(count => {
assert.equal(count, 1);
console.log('window opened');
})
.then(() =>
// Verify the window's title
app.client.waitUntil(
async () =>
(await app.client.getTitle()) === packageJson.productName,
{
timeoutMsg: `Expected window title to be ${JSON.stringify(
packageJson.productName
)}`,
}
)
)
.then(() => {
console.log('title ok');
})
.then(() => {
assert(
app.chromeDriver.logLines.indexOf(`NODE_ENV ${environment}`) > -1
);
console.log('environment ok');
})
.then(
() =>
// Successfully completed test
app.stop(),
error =>
// Test failed!
app.stop().then(() => {
grunt.fail.fatal(`Test failed: ${error.message} ${error.stack}`);
})
)
.catch(error => {
console.log('Main process logs:');
app.client.getMainProcessLogs().then(logs => {
logs.forEach(log => {
console.log(log);
});
// Test failed!
grunt.fail.fatal(`Failure! ${error.message} ${error.stack}`);
});
})
.then(done);
}
);
grunt.registerTask('tx', [
'exec:tx-pull-mostly-translated',
'exec:tx-pull-any-existing-translation',
'locale-patch',
]);
grunt.registerTask('dev', ['default', 'watch']);
grunt.registerTask('test', ['unit-tests', 'lib-unit-tests']);
grunt.registerTask('date', ['gitinfo', 'getExpireTime']);
grunt.registerTask('default', [
'exec:build-protobuf',

View File

@ -23,6 +23,7 @@ import {
screen,
shell,
systemPreferences,
desktopCapturer,
} from 'electron';
import { z } from 'zod';
@ -587,11 +588,10 @@ async function createWindow() {
if (getEnvironment() === Environment.Test) {
mainWindow.loadURL(
prepareFileUrl([__dirname, '../test/index.html'], moreKeys)
);
} else if (getEnvironment() === Environment.TestLib) {
mainWindow.loadURL(
prepareFileUrl([__dirname, '../libtextsecure/test/index.html'], moreKeys)
prepareFileUrl([__dirname, '../test/index.html'], {
...moreKeys,
argv: JSON.stringify(process.argv),
})
);
} else {
mainWindow.loadURL(
@ -1424,10 +1424,7 @@ app.on('ready', async () => {
addSensitivePath(userDataPath);
if (
getEnvironment() !== Environment.Test &&
getEnvironment() !== Environment.TestLib
) {
if (getEnvironment() !== Environment.Test) {
installFileHandler({
protocol: electronProtocol,
userDataPath,
@ -2120,3 +2117,20 @@ ipc.handle('show-save-dialog', async (_event, { defaultPath }) => {
defaultPath,
});
});
ipc.handle('getScreenCaptureSources', async () => {
return desktopCapturer.getSources({
fetchWindowIcons: true,
thumbnailSize: { height: 102, width: 184 },
types: ['window', 'screen'],
});
});
if (isTestEnvironment(getEnvironment())) {
ipc.handle('ci:test-electron:done', async (_event, info) => {
process.stdout.write(
`ci:test-electron:done=${JSON.stringify(info)}\n`,
() => app.quit()
);
});
}

View File

@ -2,19 +2,29 @@
// SPDX-License-Identifier: AGPL-3.0-only
import { join } from 'path';
import { mkdirSync } from 'fs';
import { app } from 'electron';
import { start } from './base_config';
import config from './config';
let userData: string | undefined;
// Use separate data directory for benchmarks & development
if (config.has('storagePath')) {
app.setPath('userData', String(config.get('storagePath')));
userData = String(config.get('storagePath'));
} else if (config.has('storageProfile')) {
const userData = join(
userData = join(
app.getPath('appData'),
`Signal-${config.get('storageProfile')}`
);
}
if (userData !== undefined) {
try {
mkdirSync(userData, { recursive: true });
} catch (error) {
console.error('Failed to create userData', error?.stack || String(error));
}
app.setPath('userData', userData);
}

View File

@ -1,21 +0,0 @@
// Copyright 2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
module.exports = {
env: {
browser: true,
node: false,
mocha: true,
},
parserOptions: {
sourceType: 'script',
},
rules: {
strict: 'off',
'more/no-then': 'off',
},
globals: {
assert: true,
getString: true,
},
};

View File

@ -1,70 +0,0 @@
// Copyright 2015-2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
/* global chai */
mocha.setup('bdd');
window.assert = chai.assert;
const OriginalReporter = mocha._reporter;
const SauceReporter = function Constructor(runner) {
const failedTests = [];
runner.on('end', () => {
window.mochaResults = runner.stats;
window.mochaResults.reports = failedTests;
});
runner.on('fail', (test, err) => {
const flattenTitles = item => {
const titles = [];
while (item.parent.title) {
titles.push(item.parent.title);
// eslint-disable-next-line no-param-reassign
item = item.parent;
}
return titles.reverse();
};
failedTests.push({
name: test.title,
result: false,
message: err.message,
stack: err.stack,
titles: flattenTitles(test),
});
});
// eslint-disable-next-line no-new
new OriginalReporter(runner);
};
SauceReporter.prototype = OriginalReporter.prototype;
mocha.reporter(SauceReporter);
/*
* global helpers for tests
*/
window.Whisper = window.Whisper || {};
window.Whisper.events = {
on() {},
trigger() {},
};
before(async () => {
try {
window.SignalContext.log.info('Initializing SQL in renderer');
const isTesting = true;
await window.Signal.Data.startInRenderer(isTesting);
window.SignalContext.log.info('SQL initialized in renderer');
} catch (err) {
window.SignalContext.log.error(
'SQL failed to initialize',
err && err.stack ? err.stack : err
);
}
await window.Signal.Util.initializeMessageCounter();
});

View File

@ -1,59 +0,0 @@
// Copyright 2018-2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
window.setImmediate = window.nodeSetImmediate;
const getKeysForIdentifierMap = {};
const messagesSentMap = {};
const fakeCall = () => Promise.resolve();
const fakeAPI = {
confirmCode: fakeCall,
getAttachment: fakeCall,
getAvatar: fakeCall,
getDevices: fakeCall,
// getKeysForIdentifier : fakeCall,
getMyKeys: fakeCall,
getProfile: fakeCall,
getProvisioningResource: fakeCall,
putAttachment: fakeCall,
registerKeys: fakeCall,
requestVerificationSMS: fakeCall,
requestVerificationVoice: fakeCall,
// sendMessages: fakeCall,
setSignedPreKey: fakeCall,
getKeysForIdentifier(number) {
const res = getKeysForIdentifierMap[number];
if (res !== undefined) {
delete getKeysForIdentifierMap[number];
return Promise.resolve(res);
}
throw new Error('getKeysForIdentfier of unknown/used number');
},
sendMessages(destination, messageArray) {
for (let i = 0, max = messageArray.length; i < max; i += 1) {
const msg = messageArray[i];
if (
(msg.type !== 1 && msg.type !== 3) ||
msg.destinationDeviceId === undefined ||
msg.destinationRegistrationId === undefined ||
msg.body === undefined ||
msg.timestamp === undefined ||
msg.relay !== undefined ||
msg.destination !== undefined
) {
throw new Error('Invalid message');
}
messagesSentMap[`${destination}.${messageArray[i].destinationDeviceId}`] =
msg;
}
},
};
window.WebAPI = {
connect: () => fakeAPI,
};

View File

@ -1,44 +0,0 @@
<!-- Copyright 2015-2021 Signal Messenger, LLC -->
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
<html>
<head>
<meta charset="utf-8" />
<title>libtextsecure test runner</title>
<link rel="stylesheet" href="../../node_modules/mocha/mocha.css" />
</head>
<body>
<div id="mocha"></div>
<div id="tests"></div>
<script type="text/javascript" src="fake_web_api.js"></script>
<script type="text/javascript" src="test.js"></script>
<script
type="text/javascript"
src="../protocol_wrapper.js"
data-cover
></script>
<script
type="text/javascript"
src="../../js/libphonenumber-util.js"
></script>
<script
type="text/javascript"
src="../../js/components.js"
data-cover
></script>
<script type="text/javascript" src="task_with_timeout_test.js"></script>
<script type="text/javascript" src="account_manager_test.js"></script>
<script type="text/javascript" src="sendmessage_test.js"></script>
<!-- Uncomment to start tests without code coverage enabled -->
<script type="text/javascript">
mocha.run();
window.Signal.conversationControllerStart();
</script>
</body>
</html>

View File

@ -30,7 +30,8 @@
"prepare-windows-cert": "node scripts/prepare_windows_cert.js",
"publish-to-apt": "NAME=$npm_package_name VERSION=$npm_package_version ./aptly.sh",
"test": "yarn test-node && yarn test-electron",
"test-electron": "yarn grunt test",
"test-electron": "node ts/build/test-electron.js",
"test-release": "node ts/build/test-release.js",
"test-node": "electron-mocha --file test/setup-test-node.js --recursive test/app test/modules ts/test-node ts/test-both",
"test-node-coverage": "nyc --reporter=lcov --reporter=text mocha --recursive test/app test/modules ts/test-node ts/test-both",
"eslint": "eslint --cache .",
@ -207,7 +208,7 @@
"@types/lru-cache": "5.1.0",
"@types/memoizee": "0.4.2",
"@types/mkdirp": "0.5.2",
"@types/mocha": "5.0.0",
"@types/mocha": "9.0.0",
"@types/mustache": "4.1.2",
"@types/node": "14.14.37",
"@types/node-fetch": "2.5.7",
@ -238,6 +239,7 @@
"@types/uuid": "3.4.4",
"@types/webpack-dev-server": "3.11.3",
"@types/websocket": "1.0.0",
"@types/yargs": "17.0.7",
"@typescript-eslint/eslint-plugin": "4.30.0",
"@typescript-eslint/parser": "4.30.0",
"arraybuffer-loader": "1.0.3",
@ -250,9 +252,9 @@
"core-js": "2.6.9",
"cross-env": "5.2.0",
"css-loader": "3.2.0",
"electron": "15.3.2",
"electron": "16.0.4",
"electron-builder": "22.14.5",
"electron-mocha": "10.1.0",
"electron-mocha": "11.0.2",
"electron-notarize": "0.1.1",
"eslint": "7.7.0",
"eslint-config-airbnb-typescript-prettier": "3.1.0",
@ -271,7 +273,7 @@
"grunt-gitinfo": "0.1.9",
"grunt-sass": "3.1.0",
"html-webpack-plugin": "5.3.1",
"mocha": "4.1.0",
"mocha": "9.1.3",
"mocha-testcheck": "1.0.0-rc.0",
"node-gyp": "7.1.2",
"node-sass": "6.0.1",
@ -279,11 +281,11 @@
"npm-run-all": "4.1.5",
"nyc": "11.4.1",
"patch-package": "6.4.7",
"playwright": "1.17.1",
"prettier": "2.4.1",
"react-docgen-typescript": "1.2.6",
"sass-loader": "10.2.0",
"sinon": "11.1.1",
"spectron": "5.0.0",
"style-loader": "1.0.0",
"terser-webpack-plugin": "5.1.1",
"ts-loader": "4.1.0",
@ -303,7 +305,7 @@
"sharp/color/color-string": "1.5.5"
},
"engines": {
"node": "16.5.0"
"node": "16.9.1"
},
"build": {
"appId": "org.whispersystems.signal-desktop",

View File

@ -121,7 +121,7 @@ try {
window.open = () => null;
// Playwright uses `eval` for `.evaluate()` API
if (!config.enableCI) {
if (!config.enableCI && config.environment !== 'test') {
// eslint-disable-next-line no-eval, no-multi-assign
window.eval = global.eval = () => null;
}

View File

@ -3,31 +3,26 @@
/* global window */
const { ipcRenderer } = require('electron');
window.assert = require('chai').assert;
// This is a hack to let us run TypeScript tests in the renderer process. See the
// code in `test/index.html`.
const pendingDescribeCalls = [];
window.describe = (...args) => {
pendingDescribeCalls.push(args);
};
/* eslint-disable global-require, import/no-extraneous-dependencies */
const fastGlob = require('fast-glob');
fastGlob
.sync('./ts/test-{both,electron}/**/*_test.js', {
absolute: true,
cwd: __dirname,
})
.forEach(require);
delete window.describe;
window.test = {
pendingDescribeCalls,
fastGlob,
normalizePath: require('normalize-path'),
fse: require('fs-extra'),
path: require('path'),
basePath: __dirname,
attachmentsPath: window.Signal.Migrations.attachmentsPath,
onComplete(info) {
return ipcRenderer.invoke('ci:test-electron:done', info);
},
prepareTests() {
fastGlob
.sync('./ts/test-{both,electron}/**/*_test.js', {
absolute: true,
cwd: __dirname,
})
.forEach(require);
},
};

View File

@ -161,11 +161,6 @@
{{/isError}}
</script>
<script
type="text/javascript"
src="../libtextsecure/test/fake_web_api.js"
></script>
<script type="text/javascript" src="../js/components.js"></script>
<script type="text/javascript" src="../ts/backboneJquery.js"></script>
<script
@ -173,6 +168,13 @@
src="../js/reliable_trigger.js"
data-cover
></script>
<script
type="text/javascript"
src="../node_modules/mocha/mocha.js"
></script>
<script type="text/javascript">
mocha.setup('bdd');
</script>
<script type="text/javascript" src="test.js"></script>
<script type="text/javascript" src="../js/database.js" data-cover></script>
@ -193,39 +195,13 @@
src="../js/expiring_tap_to_view_messages.js"
data-cover
></script>
<script
type="text/javascript"
src="../js/notifications.js"
data-cover
></script>
<script
type="text/javascript"
src="../js/views/react_wrapper_view.js"
></script>
<script
type="text/javascript"
src="../js/views/list_view.js"
data-cover
></script>
<script
type="text/javascript"
src="../js/views/contact_list_view.js"
data-cover
></script>
<script
type="text/javascript"
src="../js/views/group_member_list_view.js"
data-cover
></script>
<script
type="text/javascript"
src="../js/views/inbox_view.js"
data-cover
></script>
<script type="text/javascript" src="views/whisper_view_test.js"></script>
<script type="text/javascript" src="views/list_view_test.js"></script>
<script type="text/javascript" src="libphonenumber_util_test.js"></script>
<script type="text/javascript" src="reliable_trigger_test.js"></script>
@ -236,11 +212,33 @@
<script type="text/javascript">
window.Signal.conversationControllerStart();
window.test.pendingDescribeCalls.forEach(args => {
describe(...args);
});
window.test.prepareTests();
delete window.test.prepareTests;
mocha.run();
!(function () {
const passed = [];
const failed = [];
class Reporter extends Mocha.reporters.HTML {
constructor(runner, options) {
super(runner, options);
runner.on('pass', test => passed.push(test.fullTitle()));
runner.on('fail', (test, error) => {
failed.push({
testName: test.fullTitle(),
error: error?.stack || String(error),
});
});
runner.on('end', () => window.test.onComplete({ passed, failed }));
}
}
mocha.reporter(Reporter);
mocha.run();
})();
</script>
</body>
</html>

View File

@ -1,47 +1,7 @@
// Copyright 2014-2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
/* global chai, Whisper, _, Backbone */
mocha.setup('bdd');
window.assert = chai.assert;
const OriginalReporter = mocha._reporter;
const SauceReporter = function Constructor(runner) {
const failedTests = [];
runner.on('end', () => {
window.mochaResults = runner.stats;
window.mochaResults.reports = failedTests;
});
runner.on('fail', (test, err) => {
const flattenTitles = item => {
const titles = [];
while (item.parent.title) {
titles.push(item.parent.title);
// eslint-disable-next-line no-param-reassign
item = item.parent;
}
return titles.reverse();
};
failedTests.push({
name: test.title,
result: false,
message: err.message,
stack: err.stack,
titles: flattenTitles(test),
});
});
// eslint-disable-next-line no-new
new OriginalReporter(runner);
};
SauceReporter.prototype = OriginalReporter.prototype;
mocha.reporter(SauceReporter);
/* global Whisper, _, Backbone */
// Override the database id.
window.Whisper = window.Whisper || {};

54
ts/build/test-electron.ts Normal file
View File

@ -0,0 +1,54 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
/* eslint-disable no-console */
import { execFileSync } from 'child_process';
import { join } from 'path';
const ROOT_DIR = join(__dirname, '..', '..');
const ELECTRON = join(
ROOT_DIR,
'node_modules',
'.bin',
process.platform === 'win32' ? 'electron.cmd' : 'electron'
);
const stdout = execFileSync(ELECTRON, [ROOT_DIR], {
cwd: ROOT_DIR,
env: {
...process.env,
NODE_ENV: 'test',
},
encoding: 'utf8',
});
const match = stdout.match(/ci:test-electron:done=(.*)?\n/);
if (!match) {
throw new Error('No test results were found in stdout');
}
const {
passed,
failed,
}: {
passed: Array<string>;
failed: Array<{ testName: string; error: string }>;
} = JSON.parse(match[1]);
const total = passed.length + failed.length;
for (const { testName, error } of failed) {
console.error(`- ${testName}`);
console.error(error);
console.error('');
}
console.log(
`Passed ${passed.length} | Failed ${failed.length} | Total ${total}`
);
if (failed.length !== 0) {
process.exit(1);
}

80
ts/build/test-release.ts Normal file
View File

@ -0,0 +1,80 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
/* eslint-disable no-console */
import asar from 'asar';
import assert from 'assert';
import { join } from 'path';
import { _electron as electron } from 'playwright';
import packageJson from '../../package.json';
const ENVIRONMENT = 'production';
const RELEASE_DIR = join(__dirname, '..', '..', 'release');
let archive: string;
let exe: string;
if (process.platform === 'darwin') {
archive = join(
'mac',
`${packageJson.productName}.app`,
'Contents',
'Resources',
'app.asar'
);
exe = join(
'mac',
`${packageJson.productName}.app`,
'Contents',
'MacOS',
packageJson.productName
);
} else if (process.platform === 'win32') {
archive = join('win-unpacked', 'resources', 'app.asar');
exe = join('win-unpacked', `${packageJson.productName}.exe`);
} else if (process.platform === 'linux') {
archive = join('linux-unpacked', 'resources', 'app.asar');
exe = join('linux-unpacked', packageJson.name);
} else {
throw new Error(`Unsupported platform: ${process.platform}`);
}
const files = [
join('config', 'default.json'),
join('config', `${ENVIRONMENT}.json`),
join('config', `local-${ENVIRONMENT}.json`),
];
for (const fileName of files) {
console.log(`Checking that ${fileName} exists in asar ${archive}`);
try {
asar.statFile(join(RELEASE_DIR, archive), fileName);
} catch (e) {
console.log(e);
throw new Error(`Missing file ${fileName}`);
}
}
// A simple test to verify a visible window is opened with a title
const main = async () => {
const executablePath = join(RELEASE_DIR, exe);
console.log('Starting path', executablePath);
const app = await electron.launch({
executablePath,
locale: 'en',
});
console.log('Waiting for a first window');
const window = await app.firstWindow();
await window.waitForLoadState();
console.log('Checking window title');
assert.strictEqual(await window.title(), packageJson.productName);
await app.close();
};
main().catch(error => {
console.error(error);
process.exit(1);
});

View File

@ -9,7 +9,6 @@ export enum Environment {
Production = 'production',
Staging = 'staging',
Test = 'test',
TestLib = 'test-lib',
}
let environment: undefined | Environment;
@ -41,4 +40,4 @@ export const parseEnvironment = makeEnumParser(
);
export const isTestEnvironment = (env: Environment): boolean =>
env === Environment.Test || env === Environment.TestLib;
env === Environment.Test;

View File

@ -43,9 +43,7 @@ let globalLogger: undefined | pino.Logger;
let shouldRestart = false;
const isRunningFromConsole =
Boolean(process.stdout.isTTY) ||
getEnvironment() === Environment.Test ||
getEnvironment() === Environment.TestLib;
Boolean(process.stdout.isTTY) || getEnvironment() === Environment.Test;
export async function initialize(
getMainWindow: () => undefined | BrowserWindow

View File

@ -1,7 +1,8 @@
// Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { desktopCapturer, ipcRenderer } from 'electron';
import type { DesktopCapturerSource } from 'electron';
import { ipcRenderer } from 'electron';
import type {
AudioDevice,
CallId,
@ -1097,11 +1098,8 @@ export class CallingClass {
}
async getPresentingSources(): Promise<Array<PresentableSource>> {
const sources = await desktopCapturer.getSources({
fetchWindowIcons: true,
thumbnailSize: { height: 102, width: 184 },
types: ['window', 'screen'],
});
const sources: ReadonlyArray<DesktopCapturerSource> =
await ipcRenderer.invoke('getScreenCaptureSources');
const presentableSources: Array<PresentableSource> = [];

View File

@ -37,10 +37,6 @@ describe('environment utilities', () => {
it('parses "test" as Environment.Test', () => {
assert.equal(parseEnvironment('test'), Environment.Test);
});
it('parses "test-lib" as Environment.TestLib', () => {
assert.equal(parseEnvironment('test-lib'), Environment.TestLib);
});
});
describe('isTestEnvironment', () => {
@ -52,7 +48,6 @@ describe('environment utilities', () => {
it('returns true for test environments', () => {
assert.isTrue(isTestEnvironment(Environment.Test));
assert.isTrue(isTestEnvironment(Environment.TestLib));
});
});
});

View File

@ -1352,7 +1352,7 @@ describe('calling duck', () => {
describe('thunk', () => {
function noopTest(connectionState: GroupCallConnectionState) {
return async function test(this: Mocha.ITestCallbackContext) {
return async function test(this: Mocha.Context) {
const dispatch = sinon.spy();
await peekNotConnectedGroupCall({

View File

@ -1,8 +1,10 @@
// Copyright 2019-2020 Signal Messenger, LLC
// Copyright 2019-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
/* global textsecure, WebAPI */
/* eslint-disable no-console */
import { assert } from 'chai';
import MessageSender from '../../textsecure/SendMessage';
import type { WebAPIType } from '../../textsecure/WebAPI';
const BUCKET_SIZES = [
541, 568, 596, 626, 657, 690, 725, 761, 799, 839, 881, 925, 972, 1020, 1071,
@ -34,17 +36,11 @@ const BUCKET_SIZES = [
80095580, 84100359, 88305377, 92720646, 97356678, 102224512, 107335738,
];
describe('sendmessage', () => {
let originalWebAPIConnect = null;
let sendmessage = null;
before(() => {
originalWebAPIConnect = WebAPI.connect;
WebAPI.connect = () => null;
describe('SendMessage', () => {
let sendMessage: MessageSender;
sendmessage = new textsecure.MessageSender();
});
after(() => {
WebAPI.connect = originalWebAPIConnect;
before(() => {
sendMessage = new MessageSender({} as unknown as WebAPIType);
});
describe('#_getAttachmentSizeBucket', () => {
@ -52,7 +48,7 @@ describe('sendmessage', () => {
for (let size = 0, max = BUCKET_SIZES[0]; size < max; size += 1) {
assert.strictEqual(
BUCKET_SIZES[0],
sendmessage._getAttachmentSizeBucket(size)
sendMessage._getAttachmentSizeBucket(size)
);
}
});
@ -60,17 +56,18 @@ describe('sendmessage', () => {
it('properly calculates entire table', () => {
let count = 0;
const failures = new Array<string>();
for (let i = 0, max = BUCKET_SIZES.length - 1; i < max; i += 1) {
// Exact
if (
BUCKET_SIZES[i] !==
sendmessage._getAttachmentSizeBucket(BUCKET_SIZES[i])
sendMessage._getAttachmentSizeBucket(BUCKET_SIZES[i])
) {
count += 1;
console.log(
failures.push(
`${
BUCKET_SIZES[i]
} does not equal ${sendmessage._getAttachmentSizeBucket(
} does not equal ${sendMessage._getAttachmentSizeBucket(
BUCKET_SIZES[i]
)}`
);
@ -79,13 +76,13 @@ describe('sendmessage', () => {
// Just under
if (
BUCKET_SIZES[i] !==
sendmessage._getAttachmentSizeBucket(BUCKET_SIZES[i] - 1)
sendMessage._getAttachmentSizeBucket(BUCKET_SIZES[i] - 1)
) {
count += 1;
console.log(
failures.push(
`${
BUCKET_SIZES[i]
} does not equal ${sendmessage._getAttachmentSizeBucket(
} does not equal ${sendMessage._getAttachmentSizeBucket(
BUCKET_SIZES[i] - 1
)}`
);
@ -94,21 +91,20 @@ describe('sendmessage', () => {
// Just over
if (
BUCKET_SIZES[i + 1] !==
sendmessage._getAttachmentSizeBucket(BUCKET_SIZES[i] + 1)
sendMessage._getAttachmentSizeBucket(BUCKET_SIZES[i] + 1)
) {
count += 1;
console.log(
failures.push(
`${
BUCKET_SIZES[i + 1]
} does not equal ${sendmessage._getAttachmentSizeBucket(
} does not equal ${sendMessage._getAttachmentSizeBucket(
BUCKET_SIZES[i] + 1
)}`
);
}
}
console.log(`Failures: ${count}`);
assert.strictEqual(count, 0);
assert.strictEqual(count, 0, failures.join('\n'));
});
});
});

File diff suppressed because it is too large Load Diff

View File

@ -105,6 +105,7 @@ const excludedFilesRegexp = RegExp(
// Modules used only in test/development scenarios
'^node_modules/@babel/.+',
'^node_modules/@chanzuckerberg/axe-storybook-testing/.+',
'^node_modules/@svgr/.+',
'^node_modules/@types/.+',
'^node_modules/@webassemblyjs/.+',
@ -116,8 +117,6 @@ const excludedFilesRegexp = RegExp(
'^node_modules/ansi-colors/.+',
'^node_modules/anymatch/.+',
'^node_modules/app-builder-lib/.+',
'^node_modules/archiver-utils/.+', // Used by spectron
'^node_modules/archiver/.+', // Used by spectron
'^node_modules/asn1\\.js/.+',
'^node_modules/autoprefixer/.+',
'^node_modules/babel.+',
@ -130,6 +129,7 @@ const excludedFilesRegexp = RegExp(
'^node_modules/builder-util/.+',
'^node_modules/catharsis/.+',
'^node_modules/chai/.+',
'^node_modules/chokidar/.+',
'^node_modules/clean-css/.+',
'^node_modules/cli-table2/.+',
'^node_modules/cliui/.+',
@ -161,10 +161,13 @@ const excludedFilesRegexp = RegExp(
'^node_modules/@typescript-eslint.+',
'^node_modules/esprima/.+',
'^node_modules/express/.+',
'^node_modules/fast-glob/.+',
'^node_modules/file-loader/.+',
'^node_modules/file-system-cache/.+', // Currently only used in storybook
'^node_modules/finalhandler/.+',
'^node_modules/foreground-chat/.+',
'^node_modules/fsevents/.+',
'^node_modules/gauge/.+',
'^node_modules/global-agent/.+',
'^node_modules/globule/.+',
'^node_modules/grunt-cli/.+',
@ -208,6 +211,8 @@ const excludedFilesRegexp = RegExp(
'^node_modules/optionator/.+',
'^node_modules/plist/.+',
'^node_modules/phantomjs-prebuilt/.+',
'^node_modules/playwright/.+',
'^node_modules/playwright-core/.+',
'^node_modules/postcss.+',
'^node_modules/preserve/.+',
'^node_modules/prettier/.+',
@ -233,7 +238,6 @@ const excludedFilesRegexp = RegExp(
'^node_modules/snapdragon-util/.+',
'^node_modules/snapdragon/.+',
'^node_modules/sockjs-client/.+',
'^node_modules/spectron/.+',
'^node_modules/style-loader/.+',
'^node_modules/svgo/.+',
'^node_modules/terser/.+',

983
yarn.lock

File diff suppressed because it is too large Load Diff