Added testing on pull request

Disable proxy in tests.
This commit is contained in:
Mikunj 2020-02-27 12:11:08 +11:00
parent 55c1410793
commit a09e370e1d
17 changed files with 430 additions and 307 deletions

67
.github/workflows/pull-request.yml vendored Normal file
View file

@ -0,0 +1,67 @@
# This script will run tests anytime a pull request is added
name: Session Test
on:
pull_request:
branches:
- development
- clearnet
- github-actions
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [windows-2016, macos-latest, ubuntu-latest]
env:
SIGNAL_ENV: production
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- run: git config --global core.autocrlf false
- name: Checkout git repo
uses: actions/checkout@v1
- name: Install node
uses: actions/setup-node@v1
with:
node-version: 10.13.0
- name: Setup node for windows
if: runner.os == 'Windows'
run: |
npm install --global --production windows-build-tools@4.0.0
npm install --global node-gyp@latest
npm config set python python2.7
npm config set msvs_version 2015
- name: Install yarn
run: npm install yarn --no-save
- name: Install Dependencies
run: yarn install --frozen-lockfile
- name: Generate and concat files
run: yarn generate
- name: Lint Files
run: |
yarn format-full --list-different
yarn eslint
yarn tslint
- name: Make linux use en_US locale
if: runner.os == 'Linux'
run: |
sudo apt-get install -y hunspell-en-us
sudo locale-gen en_US.UTF-8
sudo dpkg-reconfigure locales
echo ::set-env name=DISPLAY:::9.0
echo ::set-env name=LANG::en_US.UTF-8
- name: Test
uses: GabrielBB/xvfb-action@v1.0
with:
run: yarn test

View file

@ -1422,7 +1422,7 @@
if (this.get('type') !== 'friend-request') {
const c = this.getConversation();
// Don't bother sending sync messages to public chats
if (!c.isPublic()) {
if (c && !c.isPublic()) {
this.sendSyncMessage();
}
}

View file

@ -217,7 +217,12 @@ class LokiMessageAPI {
}
return true;
} catch (e) {
log.warn('Loki send message error:', e.code, e.message, `from ${address}`);
log.warn(
'Loki send message error:',
e.code,
e.message,
`from ${address}`
);
if (e instanceof textsecure.WrongSwarmError) {
const { newSwarm } = e;
await lokiSnodeAPI.updateSwarmNodes(params.pubKey, newSwarm);

View file

@ -70,7 +70,10 @@ const sendToProxy = async (options = {}, targetNode) => {
// detect SNode is not ready (not in swarm; not done syncing)
if (response.status === 503) {
const ciphertext = await response.text();
log.error(`lokiRpc sendToProxy snode ${randSnode.ip}:${randSnode.port} error`, ciphertext);
log.error(
`lokiRpc sendToProxy snode ${randSnode.ip}:${randSnode.port} error`,
ciphertext
);
// mark as bad for this round (should give it some time and improve success rates)
lokiSnodeAPI.markRandomNodeUnreachable(randSnode);
// retry for a new working snode
@ -104,7 +107,7 @@ const sendToProxy = async (options = {}, targetNode) => {
const textDecoder = new TextDecoder();
plaintext = textDecoder.decode(plaintextBuffer);
} catch(e) {
} catch (e) {
log.error(
'lokiRpc sendToProxy decode error',
e.code,

View file

@ -31,7 +31,10 @@ class LokiSnodeAPI {
];
}
async initialiseRandomPool(seedNodes = [...window.seedNodeList], consecutiveErrors = 0) {
async initialiseRandomPool(
seedNodes = [...window.seedNodeList],
consecutiveErrors = 0
) {
const params = {
limit: 20,
active_only: true,
@ -71,7 +74,10 @@ class LokiSnodeAPI {
if (consecutiveErrors < 3) {
// retry after a possible delay
setTimeout(() => {
log.info('Retrying initialising random snode pool, try #', consecutiveErrors);
log.info(
'Retrying initialising random snode pool, try #',
consecutiveErrors
);
this.initialiseRandomPool(seedNodes, consecutiveErrors + 1);
}, consecutiveErrors * consecutiveErrors * 5000);
} else {
@ -181,7 +187,12 @@ class LokiSnodeAPI {
const snodes = result.snodes.filter(tSnode => tSnode.ip !== '0.0.0.0');
return snodes;
} catch (e) {
log.error('getSnodesForPubkey error', e.code, e.message, `for ${snode.ip}:${snode.port}`);
log.error(
'getSnodesForPubkey error',
e.code,
e.message,
`for ${snode.ip}:${snode.port}`
);
this.markRandomNodeUnreachable(snode);
return [];
}
@ -197,7 +208,9 @@ class LokiSnodeAPI {
const resList = await this.getSnodesForPubkey(rSnode, pubKey);
// should we only activate entries that are in all results?
resList.map(item => {
const hasItem = snodes.some(hItem => item.ip === hItem.ip && item.port === hItem.port);
const hasItem = snodes.some(
hItem => item.ip === hItem.ip && item.port === hItem.port
);
if (!hasItem) {
snodes.push(item);
}

View file

@ -1,6 +1,9 @@
/* global window, mocha, chai, assert, Whisper */
mocha.setup('bdd');
mocha
.setup('bdd')
.fullTrace()
.timeout(10000);
window.assert = chai.assert;
window.PROTO_ROOT = '../../protos';

View file

@ -59,7 +59,10 @@ function MessageReceiver(username, password, signalingKey, options = {}) {
lokiPublicChatAPI.removeAllListeners('publicMessage');
// we only need one MR in the system handling these
// bind events
lokiPublicChatAPI.on('publicMessage', this.handleUnencryptedMessage.bind(this));
lokiPublicChatAPI.on(
'publicMessage',
this.handleUnencryptedMessage.bind(this)
);
openGroupBound = true;
}
} else {

View file

@ -1,6 +1,9 @@
/* global mocha, chai, assert */
mocha.setup('bdd');
mocha
.setup('bdd')
.fullTrace()
.timeout(10000);
window.assert = chai.assert;
window.PROTO_ROOT = '../../protos';

View file

@ -42,6 +42,7 @@
"test-node-coverage": "nyc --reporter=lcov --reporter=text mocha --recursive test/app test/modules ts/test libloki/test/node",
"test-node-coverage-html": "nyc --reporter=lcov --reporter=html mocha --recursive test/a/* */pp test/modules ts/test libloki/test/node",
"eslint": "eslint --cache .",
"eslint-fix": "eslint --fix .",
"eslint-full": "eslint .",
"lint": "yarn format --list-different && yarn lint-windows",
"lint-full": "yarn format-full --list-different; yarn lint-windows-full",
@ -124,7 +125,7 @@
"reselect": "4.0.0",
"rimraf": "2.6.2",
"semver": "5.4.1",
"spellchecker": "3.5.1",
"spellchecker": "3.7.0",
"tar": "4.4.8",
"testcheck": "1.0.0-rc.2",
"tmp": "0.0.33",

View file

@ -475,23 +475,6 @@ contextMenu({
// /tmp mounted as noexec on Linux.
require('./js/spell_check');
if (config.environment === 'test') {
const isTravis = 'TRAVIS' in process.env && 'CI' in process.env;
const isWindows = process.platform === 'win32';
/* eslint-disable global-require, import/no-extraneous-dependencies */
window.test = {
glob: require('glob'),
fse: require('fs-extra'),
tmp: require('tmp'),
path: require('path'),
basePath: __dirname,
attachmentsPath: window.Signal.Migrations.attachmentsPath,
isTravis,
isWindows,
};
/* eslint-enable global-require, import/no-extraneous-dependencies */
}
window.shortenPubkey = pubkey => `(...${pubkey.substring(pubkey.length - 6)})`;
window.pubkeyPattern = /@[a-fA-F0-9]{64,66}\b/g;
@ -509,3 +492,28 @@ Promise.prototype.ignore = function() {
// eslint-disable-next-line more/no-then
this.then(() => {});
};
if (config.environment.includes('test')) {
const isTravis = 'TRAVIS' in process.env && 'CI' in process.env;
const isWindows = process.platform === 'win32';
/* eslint-disable global-require, import/no-extraneous-dependencies */
window.test = {
glob: require('glob'),
fse: require('fs-extra'),
tmp: require('tmp'),
path: require('path'),
basePath: __dirname,
attachmentsPath: window.Signal.Migrations.attachmentsPath,
isTravis,
isWindows,
};
/* eslint-enable global-require, import/no-extraneous-dependencies */
window.lokiFeatureFlags = {};
window.lokiSnodeAPI = {
refreshSwarmNodesForPubKey: () => [],
getFreshSwarmNodes: () => [],
updateSwarmNodes: () => {},
updateLastHash: () => {},
getSwarmNodesForPubKey: () => [],
};
}

View file

@ -1,6 +1,9 @@
/* global chai, Whisper, _, Backbone */
mocha.setup('bdd');
mocha
.setup('bdd')
.fullTrace()
.timeout(10000);
window.assert = chai.assert;
window.PROTO_ROOT = '../protos';

View file

@ -239,20 +239,12 @@ describe('Backup', () => {
it('exports then imports to produce the same data we started with', async function thisNeeded() {
this.timeout(6000);
const {
attachmentsPath,
fse,
glob,
path,
tmp,
isTravis,
isWindows,
} = window.test;
const { attachmentsPath, fse, glob, path, tmp, isWindows } = window.test;
// Skip this test on travis windows
// Skip this test on windows
// because it always fails due to lstat permission error.
// Don't know how to fix it so this is a temp work around.
if (isTravis && isWindows) {
if (isWindows) {
console.log(
'Skipping exports then imports to produce the same data we started'
);

View file

@ -1,7 +1,7 @@
<html>
<head>
<meta charset='utf-8'>
<meta charset="utf-8">
<title>TextSecure test runner</title>
<link rel="stylesheet" href="../node_modules/mocha/mocha.css" />
<link rel="stylesheet" href="../stylesheets/manifest.css" />
@ -11,90 +11,90 @@
</div>
<div id="tests">
</div>
<div id="render-light-theme" class='index' style="width: 800; height: 500; margin:10px; border: solid 1px black;">
<div id="render-light-theme" class="index" style="width: 800; height: 500; margin:10px; border: solid 1px black;">
</div>
<div id="render-dark-theme" class='index' style="width: 800; height: 500; margin:10px; border: solid 1px black;">
<div id="render-dark-theme" class="index" style="width: 800; height: 500; margin:10px; border: solid 1px black;">
</div>
</div>
<script type='text/x-tmpl-mustache' id='app-loading-screen'>
<div class='content'>
<img src='images/session/full-logo.svg' class='session-full-logo' />
<script type="text/x-tmpl-mustache" id="app-loading-screen">
<div class="content">
<img src="images/session/full-logo.svg" class="session-full-logo" />
</div>
</script>
<script type='text/x-tmpl-mustache' id='conversation-loading-screen'>
<div class='content'>
<img src='images/session/full-logo.svg' class='session-full-logo' />
<script type="text/x-tmpl-mustache" id="conversation-loading-screen">
<div class="content">
<img src="images/session/full-logo.svg" class="session-full-logo" />
</div>
</script>
<script type='text/x-tmpl-mustache' id='two-column'>
<div class='gutter'>
<div class='network-status-container'></div>
<div class='left-pane-placeholder'></div>
<script type="text/x-tmpl-mustache" id="two-column">
<div class="gutter">
<div class="network-status-container"></div>
<div class="left-pane-placeholder"></div>
</div>
<div class='conversation-stack'>
<div class='conversation placeholder'>
<div class='conversation-header'></div>
<div class='container'>
<div class='content'>
<img src='images/session/full-logo.svg' class='session-full-logo' />
<div class="conversation-stack">
<div class="conversation placeholder">
<div class="conversation-header"></div>
<div class="container">
<div class="content">
<img src="images/session/full-logo.svg" class="session-full-logo" />
</div>
</div>
</div>
</div>
<div class='lightbox-container'></div>
<div class="lightbox-container"></div>
</script>
<script type='text/x-tmpl-mustache' id='scroll-down-button-view'>
<button class='text module-scroll-down__button {{ buttonClass }}' alt='{{ moreBelow }}'>
<div class='module-scroll-down__icon'></div>
<script type="text/x-tmpl-mustache" id="scroll-down-button-view">
<button class="text module-scroll-down__button {{ buttonClass }}" alt="{{ moreBelow }}">
<div class="module-scroll-down__icon"></div>
</button>
</script>
<script type='text/x-tmpl-mustache' id='last-seen-indicator-view'>
<div class='module-last-seen-indicator__bar'/>
<div class='module-last-seen-indicator__text'>
<script type="text/x-tmpl-mustache" id="last-seen-indicator-view">
<div class="module-last-seen-indicator__bar"/>
<div class="module-last-seen-indicator__text">
{{ unreadMessages }}
</div>
</script>
<script type='text/x-tmpl-mustache' id='banner'>
<div class='body'>
<span class='icon warning'></span>
<script type="text/x-tmpl-mustache" id="banner">
<div class="body">
<span class="icon warning"></span>
{{ message }}
<span class='icon dismiss'></span>
<span class="icon dismiss"></span>
</div>
</script>
<script type='text/x-tmpl-mustache' id='toast'>
<script type="text/x-tmpl-mustache" id="toast">
{{ toastMessage }}
</script>
<script type='text/x-tmpl-mustache' id='conversation'>
<div class='conversation-header'></div>
<div class='main panel'>
<div class='discussion-container'>
<div class='bar-container hide'>
<div class='bar active progress-bar-striped progress-bar'></div>
<script type="text/x-tmpl-mustache" id="conversation">
<div class="conversation-header"></div>
<div class="main panel">
<div class="discussion-container">
<div class="bar-container hide">
<div class="bar active progress-bar-striped progress-bar"></div>
</div>
</div>
<div class='bottom-bar' id='footer'>
<div class='emoji-panel-container'></div>
<div class='attachment-list'></div>
<div class='compose'>
<form class='send clearfix file-input'>
<div class='flex'>
<button class='emoji'></button>
<textarea class='send-message' placeholder='{{ send-message }}' rows='1' dir='auto'></textarea>
<div class='capture-audio'>
<button class='microphone'></button>
<div class="bottom-bar" id="footer">
<div class="emoji-panel-container"></div>
<div class="attachment-list"></div>
<div class="compose">
<form class="send clearfix file-input">
<div class="flex">
<button class="emoji"></button>
<textarea class="send-message" placeholder="{{ send-message }}" rows="1" dir="auto"></textarea>
<div class="capture-audio">
<button class="microphone"></button>
</div>
<div class='choose-file'>
<button class='paperclip thumbnail'></button>
<input type='file' class='file-input' multiple='multiple'>
<div class="choose-file">
<button class="paperclip thumbnail"></button>
<input type="file" class="file-input" multiple="multiple">
</div>
</div>
</form>
@ -103,39 +103,39 @@
</div>
</script>
<script type='text/x-tmpl-mustache' id='message-list'>
<div class='messages'></div>
<div class='typing-container'></div>
<script type="text/x-tmpl-mustache" id="message-list">
<div class="messages"></div>
<div class="typing-container"></div>
</script>
<script type='text/x-tmpl-mustache' id='recorder'>
<button class='finish'><span class='icon'></span></button>
<span class='time'>0:00</span>
<button class='close'><span class='icon'></span></button>
<script type="text/x-tmpl-mustache" id="recorder">
<button class="finish"><span class="icon"></span></button>
<span class="time">0:00</span>
<button class="close"><span class="icon"></span></button>
</script>
<script type='text/x-tmpl-mustache' id='nickname-dialog'>
<div class='content'>
<div class='message'>{{ message }}</div>
<input type='text' name='name' class='name' placeholder='Type a name' value='{{ name }}'>
<div class='buttons'>
<button class='clear' tabindex='3'>{{ clear }}</button>
<button class='cancel' tabindex='2'>{{ cancel }}</button>
<button class='ok' tabindex='1'>{{ ok }}</button>
</div>
</div>
</script>
<script type='text/x-tmpl-mustache' id='confirmation-dialog'>
<script type="text/x-tmpl-mustache" id="nickname-dialog">
<div class="content">
<div class='message'>{{ message }}</div>
<div class='buttons'>
{{ #showCancel }}
<button class='cancel' tabindex='2'>{{ cancel }}</button>
{{ /showCancel }}
<button class='ok' tabindex='1'>{{ ok }}</button>
<div class="message">{{ message }}</div>
<input type="text" name="name" class="name" placeholder="Type a name" value="{{ name }}">
<div class="buttons">
<button class="clear" tabindex="3">{{ clear }}</button>
<button class="cancel" tabindex="2">{{ cancel }}</button>
<button class="ok" tabindex="1">{{ ok }}</button>
</div>
</div>
</script>
<script type='text/x-tmpl-mustache' id='beta-disclaimer-dialog'>
<script type="text/x-tmpl-mustache" id="confirmation-dialog">
<div class="content">
<div class="message">{{ message }}</div>
<div class="buttons">
{{ #showCancel }}
<button class="cancel" tabindex="2">{{ cancel }}</button>
{{ /showCancel }}
<button class="ok" tabindex="1">{{ ok }}</button>
</div>
</div>
</script>
<script type="text/x-tmpl-mustache" id="beta-disclaimer-dialog">
<div class="content">
<div class="betaDisclaimerView" style="display: none;">
<h2>
@ -167,101 +167,101 @@
As a beta, this software is still experimental. When things aren't working for you, or you feel confused by the app, please let us know by filing an issue on <a href="https://github.com/loki-project/loki-messenger">Github</a> or making suggestions on <a href="https://discordapp.com/invite/67GXfD6">Discord</a>.
</p>
<button class='ok' tabindex='1'>{{ ok }}</button>
<button class="ok" tabindex="1">{{ ok }}</button>
</div>
</div>
</script>
<script type='text/x-tmpl-mustache' id='identicon-svg'>
<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100'>
<circle cx='50' cy='50' r='40' fill='{{ color }}' />
<text text-anchor='middle' fill='white' font-family='sans-serif' font-size='24px' x='50' y='50' baseline-shift='-8px'>
<script type="text/x-tmpl-mustache" id="identicon-svg">
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
<circle cx="50" cy="50" r="40" fill="{{ color }}" />
<text text-anchor="middle" fill="white" font-family="sans-serif" font-size="24px" x="50" y="50" baseline-shift="-8px">
{{ content }}
</text>
</svg>
</script>
<script type='text/x-tmpl-mustache' id='phone-number'>
<div class='phone-input-form'>
<div class='number-container'>
<input type='tel' class='number' placeholder="Phone Number" />
<script type="text/x-tmpl-mustache" id="phone-number">
<div class="phone-input-form">
<div class="number-container">
<input type="tel" class="number" placeholder="Phone Number" />
</div>
</div>
</script>
<script type='text/x-tmpl-mustache' id='file-size-modal'>
<script type="text/x-tmpl-mustache" id="file-size-modal">
{{ file-size-warning }}
({{ limit }}{{ units }})
</script>
<script type='text/x-tmpl-mustache' id='attachment-type-modal'>
<script type="text/x-tmpl-mustache" id="attachment-type-modal">
Sorry, your attachment has a type, {{type}}, that is not currently supported.
</script>
<script type='text/x-tmpl-mustache' id='group-member-list'>
<div class='container'>
{{ #summary }} <div class='summary'>{{ summary }}</div>{{ /summary }}
<script type="text/x-tmpl-mustache" id="group-member-list">
<div class="container">
{{ #summary }} <div class="summary">{{ summary }}</div>{{ /summary }}
</div>
</script>
<script type='text/x-tmpl-mustache' id='key-verification'>
<div class='container'>
<script type="text/x-tmpl-mustache" id="key-verification">
<div class="container">
{{ ^hasTheirKey }}
<div class='placeholder'>{{ theirKeyUnknown }}</div>
<div class="placeholder">{{ theirKeyUnknown }}</div>
{{ /hasTheirKey }}
{{ #hasTheirKey }}
<label> {{ yourSafetyNumberWith }} </label>
<!--<div class='qr'></div>-->
<div class='key'>
<!--<div class="qr"></div>-->
<div class="key">
{{ #chunks }} <span>{{ . }}</span> {{ /chunks }}
</div>
{{ /hasTheirKey }}
{{ verifyHelp }}
<p> {{> link_to_support }} </p>
<div class='summary'>
<div class="summary">
{{ #isVerified }}
<span class='icon verified'></span>
<span class="icon verified"></span>
{{ /isVerified }}
{{ ^isVerified }}
<span class='icon shield'></span>
<span class="icon shield"></span>
{{ /isVerified }}
{{ verifiedStatus }}
</div>
<div class='verify'>
<button class='verify grey'>
<div class="verify">
<button class="verify grey">
{{ verifyButton }}
</button>
</div>
</div>
</script>
<script type='text/x-tmpl-mustache' id='clear-data'>
<script type="text/x-tmpl-mustache" id="clear-data">
{{#isStep1}}
<div class='step'>
<div class='inner'>
<div class='step-body'>
<span class='banner-icon alert-outline-red'></span>
<div class='header'>{{ header }}</div>
<div class='body-text-wide'>{{ body }}</div>
<div class="step">
<div class="inner">
<div class="step-body">
<span class="banner-icon alert-outline-red"></span>
<div class="header">{{ header }}</div>
<div class="body-text-wide">{{ body }}</div>
</div>
<div class='nav'>
<div class="nav">
<div>
<a class='button neutral cancel'>{{ cancelButton }}</a>
<a class='button destructive delete-all-data'>{{ deleteButton }}</a>
<a class="button neutral cancel">{{ cancelButton }}</a>
<a class="button destructive delete-all-data">{{ deleteButton }}</a>
</div>
</div>
</div>
</div>
{{/isStep1}}
{{#isStep2}}
<div id='step3' class='step'>
<div class='inner'>
<div class='step-body'>
<span class='banner-icon delete'></span>
<div class='header'>{{ deleting }}</div>
<div id="step3" class="step">
<div class="inner">
<div class="step-body">
<span class="banner-icon delete"></span>
<div class="header">{{ deleting }}</div>
</div>
<div class='progress'>
<div class='bar-container'>
<div class='bar progress-bar progress-bar-striped active'></div>
<div class="progress">
<div class="bar-container">
<div class="bar progress-bar progress-bar-striped active"></div>
</div>
</div>
</div>
@ -269,8 +269,8 @@
{{/isStep2}}
</script>
<script type='text/x-tmpl-mustache' id='networkStatus'>
<div class='network-status-message'>
<script type="text/x-tmpl-mustache" id="networkStatus">
<div class="network-status-message">
<h3>{{ message }}</h3>
<span>{{ instructions }}</span>
</div>
@ -281,60 +281,60 @@
{{/reconnectDurationAsSeconds }}
{{ #action }}
<div class="action">
<button class='small blue {{ buttonClass }}'>{{ action }}</button>
<button class="small blue {{ buttonClass }}">{{ action }}</button>
</div>
{{/action }}
</script>
<script type='text/x-tmpl-mustache' id='import-flow-template'>
<script type="text/x-tmpl-mustache" id="import-flow-template">
{{#isStep2}}
<div id='step2' class='step'>
<div class='inner'>
<div class='step-body'>
<span class='banner-icon folder-outline'></span>
<div class='header'>{{ chooseHeader }}</div>
<div class='body-text'>{{ choose }}</div>
<div id="step2" class="step">
<div class="inner">
<div class="step-body">
<span class="banner-icon folder-outline"></span>
<div class="header">{{ chooseHeader }}</div>
<div class="body-text">{{ choose }}</div>
</div>
<div class='nav'>
<div class="nav">
<div>
<a class='button choose'>{{ chooseButton }}</a>
<a class="button choose">{{ chooseButton }}</a>
</div>
</div>
</div>
</div>
{{/isStep2}}
{{#isStep3}}
<div id='step3' class='step'>
<div class='inner'>
<div class='step-body'>
<span class='banner-icon import'></span>
<div class='header'>{{ importingHeader }}</div>
<div id="step3" class="step">
<div class="inner">
<div class="step-body">
<span class="banner-icon import"></span>
<div class="header">{{ importingHeader }}</div>
</div>
<div class='progress'>
<div class='bar-container'>
<div class='bar progress-bar progress-bar-striped active'></div>
<div class="progress">
<div class="bar-container">
<div class="bar progress-bar progress-bar-striped active"></div>
</div>
</div>
</div>
</div>
{{/isStep3}}
{{#isStep4}}
<div id='step4' class='step'>
<div class='inner'>
<div class='step-body'>
<span class='banner-icon check-circle-outline'></span>
<div class='header'>{{ completeHeader }}</div>
<div id="step4" class="step">
<div class="inner">
<div class="step-body">
<span class="banner-icon check-circle-outline"></span>
<div class="header">{{ completeHeader }}</div>
</div>
<div class='nav'>
<div class="nav">
{{#restartButton}}
<div>
<a class='button restart'>{{ restartButton }}</a>
<a class="button restart">{{ restartButton }}</a>
</div>
{{/restartButton}}
{{#registerButton}}
<div>
<a class='button register'>{{ registerButton }}</a>
<a class="button register">{{ registerButton }}</a>
</div>
{{/registerButton}}
</div>
@ -343,19 +343,19 @@
{{/isStep4}}
{{#isError}}
<div id='error' class='step'>
<div class='inner error-dialog clearfix'>
<div class='step-body'>
<span class='banner-icon alert-outline'></span>
<div class='header'>{{ errorHeader }}</div>
<div class='body-text-wide'>
<div id="error" class="step">
<div class="inner error-dialog clearfix">
<div class="step-body">
<span class="banner-icon alert-outline"></span>
<div class="header">{{ errorHeader }}</div>
<div class="body-text-wide">
{{ errorMessageFirst }}
<p>{{ errorMessageSecond }}</p>
</div>
</div>
<div class='nav'>
<div class="nav">
<div>
<a class='button choose'>{{ chooseButton }}</a>
<a class="button choose">{{ chooseButton }}</a>
</div>
</div>
</div>
@ -363,37 +363,37 @@
{{/isError}}
</script>
<script type='text/x-tmpl-mustache' id='link-flow-template'>
<script type="text/x-tmpl-mustache" id="link-flow-template">
{{#isStep3}}
<div id='step3' class='step'>
<div class='inner'>
<div class='step-body'>
<div class='header'>{{ linkYourPhone }}</div>
<div id="step3" class="step">
<div class="inner">
<div class="step-body">
<div class="header">{{ linkYourPhone }}</div>
<div id="qr">
<div class='container'>
<span class='dot'></span>
<span class='dot'></span>
<span class='dot'></span>
<div class="container">
<span class="dot"></span>
<span class="dot"></span>
<span class="dot"></span>
</div>
</div>
</div>
<div class='nav'>
<div class='instructions'>
<div class='android'>
<div class='label'>
<span class='os-icon android'></span>
<div class="nav">
<div class="instructions">
<div class="android">
<div class="label">
<span class="os-icon android"></span>
</div>
<div class='body'>
<div class="body">
<div>→ {{ signalSettings }}</div>
<div>→ {{ linkedDevices }}</div>
<div>→ {{ androidFinalStep }}</div>
</div>
</div>
<div class='apple'>
<div class='label'>
<span class='os-icon apple'></span>
<div class="apple">
<div class="label">
<span class="os-icon apple"></span>
</div>
<div class='body'>
<div class="body">
<div>→ {{ signalSettings }}</div>
<div>→ {{ linkedDevices }}</div>
<div>→ {{ appleFinalStep }}</div>
@ -405,20 +405,20 @@
</div>
{{/isStep3}}
{{#isStep4}}
<form id='link-phone'>
<div id='step4' class='step'>
<div class='inner'>
<div class='step-body'>
<span class='banner-icon lead-pencil'></span>
<div class='header'>{{ chooseName }}</div>
<form id="link-phone">
<div id="step4" class="step">
<div class="inner">
<div class="step-body">
<span class="banner-icon lead-pencil"></span>
<div class="header">{{ chooseName }}</div>
<div>
<input type='text' class='device-name' spellcheck='false' maxlength='50' />
<input type="text" class="device-name" spellcheck="false" maxlength="50" />
</div>
</div>
<div class='nav'>
<div class="nav">
<div>
<a class='button finish'>{{ finishLinkingPhoneButton }}</a>
<a class="button finish">{{ finishLinkingPhoneButton }}</a>
</div>
</div>
</div>
@ -426,15 +426,15 @@
</form>
{{/isStep4}}
{{#isStep5}}
<div id='step5' class='step'>
<div class='inner'>
<div class='step-body'>
<span class='banner-icon sync'></span>
<div class='header'>{{ syncing }}</div>
<div id="step5" class="step">
<div class="inner">
<div class="step-body">
<span class="banner-icon sync"></span>
<div class="header">{{ syncing }}</div>
</div>
<div class='progress'>
<div class='bar-container'>
<div class='bar progress-bar progress-bar-striped active'></div>
<div class="progress">
<div class="bar-container">
<div class="bar progress-bar progress-bar-striped active"></div>
</div>
</div>
</div>
@ -442,44 +442,44 @@
{{/isStep5}}
{{#isError}}
<div id='error' class='step'>
<div class='inner'>
<div class='step-body'>
<span class='banner-icon alert-outline'></span>
<div class='header'>{{ errorHeader }}</div>
<div class='body'>{{ errorMessage }}</div>
<div id="error" class="step">
<div class="inner">
<div class="step-body">
<span class="banner-icon alert-outline"></span>
<div class="header">{{ errorHeader }}</div>
<div class="body">{{ errorMessage }}</div>
</div>
<div class='nav'>
<a class='button try-again'>{{ errorButton }}</a>
<div class="nav">
<a class="button try-again">{{ errorButton }}</a>
</div>
</div>
</div>
{{/isError}}
</script>
<script type='text/x-tmpl-mustache' id='standalone'>
<div class='step'>
<div class='inner'>
<div class='step-body'>
<img class='banner-image' src='images/icon_128.png' />
<div class='header'>Create your Signal Account</div>
<div id='phone-number-input'>
<div class='phone-input-form'>
<div id='number-container' class='number-container'>
<input type='tel' class='number' placeholder='Phone Number' />
<script type="text/x-tmpl-mustache" id="standalone">
<div class="step">
<div class="inner">
<div class="step-body">
<img class="banner-image" src="images/icon_128.png" />
<div class="header">Create your Signal Account</div>
<div id="phone-number-input">
<div class="phone-input-form">
<div id="number-container" class="number-container">
<input type="tel" class="number" placeholder="Phone Number" />
</div>
</div>
</div>
<div class='clearfix'>
<a class='button' id='request-sms'>Send SMS</a>
<a class='link' id='request-voice' tabindex=-1>Call</a>
<div class="clearfix">
<a class="button" id="request-sms">Send SMS</a>
<a class="link" id="request-voice" tabindex=-1>Call</a>
</div>
<input class='form-control' type='text' pattern='\s*[0-9]{3}-?[0-9]{3}\s*' title='Enter your 6-digit verification code. If you did not receive a code, click Call or Send SMS to request a new one' id='code' placeholder='Verification Code' autocomplete='off'>
<div id='error' class='collapse'></div>
<input class="form-control" type="text" pattern="\s*[0-9]{3}-?[0-9]{3}\s*" title="Enter your 6-digit verification code. If you did not receive a code, click Call or Send SMS to request a new one" id="code" placeholder="Verification Code" autocomplete="off">
<div id="error" class="collapse"></div>
<div id=status></div>
</div>
<div class='nav'>
<a class='button' id='verifyCode' data-loading-text='Please wait...'>Register</a>
<div class="nav">
<a class="button" id="verifyCode" data-loading-text="Please wait...">Register</a>
</div>
</div>
</div>
@ -491,7 +491,7 @@
<script type="text/javascript" src="../js/reliable_trigger.js" data-cover></script>
<script type="text/javascript" src="test.js"></script>
<script type='text/javascript' src='../js/registration.js' data-cover></script>
<script type="text/javascript" src="../js/registration.js" data-cover></script>
<script type="text/javascript" src="../js/expire.js" data-cover></script>
<script type="text/javascript" src="../js/chromium.js" data-cover></script>
<script type="text/javascript" src="../js/database.js" data-cover></script>
@ -505,50 +505,62 @@
<script type="text/javascript" src="../js/models/conversations.js" data-cover></script>
<script type="text/javascript" src="../js/models/blockedNumbers.js" data-cover></script>
<script type="text/javascript" src="../js/conversation_controller.js" data-cover></script>
<script type='text/javascript' src='../js/blocked_number_controller.js'></script>
<script type="text/javascript" src="../js/blocked_number_controller.js"></script>
<script type="text/javascript" src="../js/message_controller.js" data-cover></script>
<script type="text/javascript" src="../js/keychange_listener.js" data-cover></script>
<script type='text/javascript' src='../js/expiring_messages.js' data-cover></script>
<script type='text/javascript' src='../js/notifications.js' data-cover></script>
<script type='text/javascript' src='../js/focus_listener.js'></script>
<script type="text/javascript" src="../js/expiring_messages.js" data-cover></script>
<script type="text/javascript" src="../js/notifications.js" data-cover></script>
<script type="text/javascript" src="../js/focus_listener.js"></script>
<script type="text/javascript" src="../js/chromium.js" data-cover></script>
<script type='text/javascript' src='../js/views/react_wrapper_view.js'></script>
<script type='text/javascript' src='../js/views/whisper_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/debug_log_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/toast_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/file_input_view.js' data-cover></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/timestamp_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/message_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/key_verification_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/message_list_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/member_list_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/bulk_edit_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/recorder_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/conversation_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/hint_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/inbox_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/network_status_view.js'></script>
<script type='text/javascript' src='../js/views/confirmation_dialog_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/nickname_dialog_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/password_dialog_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/seed_dialog_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/qr_dialog_view.js'></script>
<script type='text/javascript' src='../js/views/add_server_dialog_view.js'></script>
<script type='text/javascript' src='../js/views/identicon_svg_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/last_seen_indicator_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/scroll_down_button_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/banner_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/conversation_loading_view.js'></script>
<script type='text/javascript' src='../js/views/create_group_dialog_view.js'></script>
<script type='text/javascript' src='../js/views/confirm_session_reset_view.js'></script>
<script type='text/javascript' src='../js/views/invite_friends_dialog_view.js'></script>
<script type='text/javascript' src='../js/views/beta_release_disclaimer_view.js'></script>
<script type="text/javascript" src="../js/views/react_wrapper_view.js"></script>
<script type="text/javascript" src="../js/views/whisper_view.js"></script>
<script type="text/javascript" src="../js/views/last_seen_indicator_view.js"></script>
<script type="text/javascript" src="../js/views/scroll_down_button_view.js"></script>
<script type="text/javascript" src="../js/views/toast_view.js"></script>
<script type="text/javascript" src="../js/views/session_toast_view.js"></script>
<script type="text/javascript" src="../js/views/conversation_loading_view.js"></script>
<script type="text/javascript" src="../js/views/session_toggle_view.js"></script>
<script type="text/javascript" src="../js/views/session_modal_view.js"></script>
<script type="text/javascript" src="../js/views/session_dropdown_view.js"></script>
<script type="text/javascript" src="../js/views/session_confirm_view.js"></script>
<script type="text/javascript" src="../js/views/file_input_view.js"></script>
<script type="text/javascript" src="../js/views/list_view.js"></script>
<script type="text/javascript" src="../js/views/contact_list_view.js"></script>
<script type="text/javascript" src="../js/views/message_view.js"></script>
<script type="text/javascript" src="../js/views/key_verification_view.js"></script>
<script type="text/javascript" src="../js/views/message_list_view.js"></script>
<script type="text/javascript" src="../js/views/member_list_view.js"></script>
<script type="text/javascript" src="../js/views/bulk_edit_view.js"></script>
<script type="text/javascript" src="../js/views/group_member_list_view.js"></script>
<script type="text/javascript" src="../js/views/recorder_view.js"></script>
<script type="text/javascript" src="../js/views/conversation_view.js"></script>
<script type="text/javascript" src="../js/views/inbox_view.js"></script>
<script type="text/javascript" src="../js/views/network_status_view.js"></script>
<script type="text/javascript" src="../js/views/confirmation_dialog_view.js"></script>
<script type="text/javascript" src="../js/views/nickname_dialog_view.js"></script>
<script type="text/javascript" src="../js/views/password_dialog_view.js"></script>
<script type="text/javascript" src="../js/views/seed_dialog_view.js"></script>
<script type="text/javascript" src="../js/views/qr_dialog_view.js"></script>
<script type="text/javascript" src="../js/views/connecting_to_server_dialog_view.js"></script>
<script type="text/javascript" src="../js/views/beta_release_disclaimer_view.js"></script>
<script type="text/javascript" src="../js/views/identicon_svg_view.js"></script>
<script type="text/javascript" src="../js/views/install_view.js"></script>
<script type="text/javascript" src="../js/views/banner_view.js"></script>
<script type="text/javascript" src="../js/views/phone-input-view.js"></script>
<script type="text/javascript" src="../js/views/session_registration_view.js"></script>
<script type="text/javascript" src="../js/views/app_view.js"></script>
<script type="text/javascript" src="../js/views/import_view.js"></script>
<script type="text/javascript" src="../js/views/device_pairing_dialog_view.js"></script>
<script type="text/javascript" src="../js/views/device_pairing_words_dialog_view.js"></script>
<script type="text/javascript" src="../js/views/create_group_dialog_view.js"></script>
<script type="text/javascript" src="../js/views/confirm_session_reset_view.js"></script>
<script type="text/javascript" src="../js/views/edit_profile_dialog_view.js"></script>
<script type="text/javascript" src="../js/views/invite_friends_dialog_view.js"></script>
<script type="text/javascript" src="../js/views/moderators_add_dialog_view.js"></script>
<script type="text/javascript" src="../js/views/moderators_remove_dialog_view.js"></script>
<script type="text/javascript" src="../js/views/user_details_dialog_view.js"></script>
<!-- <script type="text/javascript" src="metadata/SecretSessionCipher_test.js"></script> -->
@ -559,11 +571,10 @@
<script type="text/javascript" src="views/inbox_view_test.js"></script>
<script type="text/javascript" src="views/network_status_view_test.js"></script>
<script type="text/javascript" src="views/last_seen_indicator_view_test.js"></script>
<script type='text/javascript' src='views/scroll_down_button_view_test.js'></script>
<script type="text/javascript" src="views/scroll_down_button_view_test.js"></script>
<script type="text/javascript" src="models/conversations_test.js"></script>
<script type="text/javascript" src="models/messages_test.js"></script>
<script type="text/javascript" src="models/profile_test.js"></script>
<script type="text/javascript" src="libphonenumber_util_test.js"></script>
<script type="text/javascript" src="blocked_number_controller_test.js"></script>

View file

@ -1,6 +1,12 @@
describe('spellChecker', () => {
it('should work', () => {
assert(window.spellChecker.spellCheck('correct'));
assert(!window.spellChecker.spellCheck('fhqwgads'));
assert(
window.spellChecker.spellCheck('correct'),
'Spellchecker returned false on a correct word.'
);
assert(
!window.spellChecker.spellCheck('fhqwgads'),
'Spellchecker returned true on a incorrect word.'
);
});
});

View file

@ -95,7 +95,11 @@ export class CreateGroupDialog extends React.Component<Props, State> {
);
return (
<SessionModal title={titleText} onClose={this.closeDialog} onOk={() => null}>
<SessionModal
title={titleText}
onClose={this.closeDialog}
onOk={() => null}
>
<div className="spacer-lg" />
<p className={errorMessageClasses}>{this.state.errorMessage}</p>

View file

@ -73,6 +73,7 @@ const excludedFiles = [
'^js/Mp3LameEncoder.min.js',
// Test files
'^libloki/test/*',
'^libtextsecure/test/*',
'^test/*',

View file

@ -9704,13 +9704,13 @@ speedometer@~0.1.2:
resolved "https://registry.yarnpkg.com/speedometer/-/speedometer-0.1.4.tgz#9876dbd2a169d3115402d48e6ea6329c8816a50d"
integrity sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=
spellchecker@3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/spellchecker/-/spellchecker-3.5.1.tgz#72cc2bcbb0c610536bc2a36df1ced9b2665816cc"
integrity sha512-R1qUBsDZzio+7MFZN6/AtPUe5NGvnc0wywckuXAlp9akASaYSFqKuI5O8p3rSiA+yKP31qC7Iijjoygmzkh6xw==
spellchecker@3.7.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/spellchecker/-/spellchecker-3.7.0.tgz#d63e6fd612352b0108e7bbf942f271665ff63c8b"
integrity sha512-saQT4BR9nivbK70s0YjyIlSbZzO6bfWRULcGL2JU7fi7wotOnWl70P0QoUwwLywNQJQ47osgCo6GmOlqzRTxbQ==
dependencies:
any-promise "^1.3.0"
nan "^2.10.0"
nan "^2.14.0"
split-string@^3.0.1, split-string@^3.0.2:
version "3.1.0"