Faster CI runs
This commit is contained in:
parent
109c3036c9
commit
ec8d6a7359
26 changed files with 242 additions and 207 deletions
183
.github/workflows/benchmark.yml
vendored
183
.github/workflows/benchmark.yml
vendored
|
@ -14,6 +14,52 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
linux:
|
linux:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
metric:
|
||||||
|
- startup
|
||||||
|
- send
|
||||||
|
- groupSend
|
||||||
|
- largeGroupSendWithBlocks
|
||||||
|
- largeGroupSend
|
||||||
|
- convoOpen
|
||||||
|
- callHistorySearch
|
||||||
|
- backup
|
||||||
|
include:
|
||||||
|
- metric: startup
|
||||||
|
script: ts/test-mock/benchmarks/startup_bench.js
|
||||||
|
runCount: 10
|
||||||
|
- metric: send
|
||||||
|
script: ts/test-mock/benchmarks/send_bench.js
|
||||||
|
runCount: 100
|
||||||
|
- metric: groupSend
|
||||||
|
script: ts/test-mock/benchmarks/group_send_bench.js
|
||||||
|
runCount: 100
|
||||||
|
conversationSize: 500
|
||||||
|
- metric: largeGroupSendWithBlocks
|
||||||
|
script: ts/test-mock/benchmarks/group_send_bench.js
|
||||||
|
runCount: 50
|
||||||
|
conversationSize: 500
|
||||||
|
groupSize: 500
|
||||||
|
contactCount: 500
|
||||||
|
blockedCount: 10
|
||||||
|
discardCount: 2
|
||||||
|
- metric: largeGroupSend
|
||||||
|
script: ts/test-mock/benchmarks/group_send_bench.js
|
||||||
|
runCount: 20
|
||||||
|
conversationSize: 50
|
||||||
|
groupSize: 500
|
||||||
|
contactCount: 500
|
||||||
|
discardCount: 2
|
||||||
|
- metric: convoOpen
|
||||||
|
script: ts/test-mock/benchmarks/group_send_bench.js
|
||||||
|
runCount: 100
|
||||||
|
- metric: callHistorySearch
|
||||||
|
script: ts/test-mock/benchmarks/call_history_search_bench.js
|
||||||
|
runCount: 100
|
||||||
|
- metric: backup
|
||||||
|
script: ts/test-mock/benchmarks/backup_bench.js
|
||||||
|
|
||||||
runs-on: ubuntu-22.04-8-cores
|
runs-on: ubuntu-22.04-8-cores
|
||||||
if: ${{ github.repository == 'signalapp/Signal-Desktop-Private' && (!github.event.schedule || github.ref == 'refs/heads/main') }}
|
if: ${{ github.repository == 'signalapp/Signal-Desktop-Private' && (!github.event.schedule || github.ref == 'refs/heads/main') }}
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
|
@ -72,132 +118,22 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
echo "MAX_CYCLES=2" >> "$GITHUB_ENV"
|
echo "MAX_CYCLES=2" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
- name: Run startup benchmarks
|
- name: Run ${{ matrix.metric }}
|
||||||
run: |
|
run: |
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
xvfb-run --auto-servernum node ts/test-mock/benchmarks/startup_bench.js |
|
xvfb-run --auto-servernum node ${{ matrix.script }} | tee benchmark.log
|
||||||
tee benchmark-startup.log
|
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
env:
|
env:
|
||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
RUN_COUNT: 10
|
|
||||||
ELECTRON_ENABLE_STACK_DUMPING: on
|
ELECTRON_ENABLE_STACK_DUMPING: on
|
||||||
DEBUG: 'mock:benchmarks'
|
DEBUG: 'mock:benchmarks'
|
||||||
ARTIFACTS_DIR: artifacts/startup
|
ARTIFACTS_DIR: artifacts/${{ matrix.metric }}
|
||||||
|
GROUP_SIZE: ${{ matrix.groupSize }}
|
||||||
- name: Run send benchmarks
|
CONTACT_COUNT: ${{ matrix.contactCount }}
|
||||||
run: |
|
BLOCKED_COUNT: ${{ matrix.blockedCount }}
|
||||||
set -o pipefail
|
DISCARD_COUNT: ${{ matrix.discardCount }}
|
||||||
rm -rf /tmp/mock
|
RUN_COUNT: ${{ matrix.runCount }}
|
||||||
xvfb-run --auto-servernum node ts/test-mock/benchmarks/send_bench.js |
|
CONVERSATION_SIZE: ${{ matrix.conversationSize }}
|
||||||
tee benchmark-send.log
|
|
||||||
timeout-minutes: 10
|
|
||||||
env:
|
|
||||||
NODE_ENV: production
|
|
||||||
RUN_COUNT: 100
|
|
||||||
ELECTRON_ENABLE_STACK_DUMPING: on
|
|
||||||
# DEBUG: 'mock:benchmarks'
|
|
||||||
ARTIFACTS_DIR: artifacts/send
|
|
||||||
|
|
||||||
- name: Run group send benchmarks
|
|
||||||
run: |
|
|
||||||
set -o pipefail
|
|
||||||
rm -rf /tmp/mock
|
|
||||||
xvfb-run --auto-servernum node \
|
|
||||||
ts/test-mock/benchmarks/group_send_bench.js | \
|
|
||||||
tee benchmark-group-send.log
|
|
||||||
timeout-minutes: 10
|
|
||||||
env:
|
|
||||||
NODE_ENV: production
|
|
||||||
RUN_COUNT: 100
|
|
||||||
CONVERSATION_SIZE: 500
|
|
||||||
ELECTRON_ENABLE_STACK_DUMPING: on
|
|
||||||
# DEBUG: 'mock:benchmarks'
|
|
||||||
ARTIFACTS_DIR: artifacts/group-send
|
|
||||||
|
|
||||||
- name: Run large group send benchmarks with blocks
|
|
||||||
run: |
|
|
||||||
set -o pipefail
|
|
||||||
rm -rf /tmp/mock
|
|
||||||
xvfb-run --auto-servernum node \
|
|
||||||
ts/test-mock/benchmarks/group_send_bench.js | \
|
|
||||||
tee benchmark-large-group-send-with-blocks.log
|
|
||||||
timeout-minutes: 10
|
|
||||||
env:
|
|
||||||
NODE_ENV: production
|
|
||||||
GROUP_SIZE: 500
|
|
||||||
CONTACT_COUNT: 500
|
|
||||||
BLOCKED_COUNT: 10
|
|
||||||
DISCARD_COUNT: 2
|
|
||||||
RUN_COUNT: 50
|
|
||||||
CONVERSATION_SIZE: 500
|
|
||||||
ELECTRON_ENABLE_STACK_DUMPING: on
|
|
||||||
# DEBUG: 'mock:benchmarks'
|
|
||||||
ARTIFACTS_DIR: artifacts/group-send
|
|
||||||
|
|
||||||
- name: Run large group send benchmarks with delivery receipts
|
|
||||||
run: |
|
|
||||||
set -o pipefail
|
|
||||||
rm -rf /tmp/mock
|
|
||||||
xvfb-run --auto-servernum node \
|
|
||||||
ts/test-mock/benchmarks/group_send_bench.js | \
|
|
||||||
tee benchmark-large-group-send.log
|
|
||||||
timeout-minutes: 10
|
|
||||||
env:
|
|
||||||
NODE_ENV: production
|
|
||||||
GROUP_SIZE: 500
|
|
||||||
CONTACT_COUNT: 500
|
|
||||||
GROUP_DELIVERY_RECEIPTS: 500
|
|
||||||
DISCARD_COUNT: 2
|
|
||||||
RUN_COUNT: 20
|
|
||||||
CONVERSATION_SIZE: 50
|
|
||||||
ELECTRON_ENABLE_STACK_DUMPING: on
|
|
||||||
# DEBUG: 'mock:benchmarks'
|
|
||||||
ARTIFACTS_DIR: artifacts/large-group-send
|
|
||||||
|
|
||||||
- name: Run conversation open benchmarks
|
|
||||||
run: |
|
|
||||||
set -o pipefail
|
|
||||||
rm -rf /tmp/mock
|
|
||||||
xvfb-run --auto-servernum node \
|
|
||||||
ts/test-mock/benchmarks/convo_open_bench.js | \
|
|
||||||
tee benchmark-convo-open.log
|
|
||||||
timeout-minutes: 10
|
|
||||||
env:
|
|
||||||
NODE_ENV: production
|
|
||||||
RUN_COUNT: 100
|
|
||||||
ELECTRON_ENABLE_STACK_DUMPING: on
|
|
||||||
# DEBUG: 'mock:benchmarks'
|
|
||||||
ARTIFACTS_DIR: artifacts/convo-open
|
|
||||||
|
|
||||||
- name: Run call history search benchmarks
|
|
||||||
run: |
|
|
||||||
set -o pipefail
|
|
||||||
rm -rf /tmp/mock
|
|
||||||
xvfb-run --auto-servernum node \
|
|
||||||
ts/test-mock/benchmarks/call_history_search_bench.js | \
|
|
||||||
tee benchmark-call-history-search.log
|
|
||||||
timeout-minutes: 10
|
|
||||||
env:
|
|
||||||
NODE_ENV: production
|
|
||||||
RUN_COUNT: 100
|
|
||||||
ELECTRON_ENABLE_STACK_DUMPING: on
|
|
||||||
# DEBUG: 'mock:benchmarks'
|
|
||||||
ARTIFACTS_DIR: artifacts/call-history-search
|
|
||||||
|
|
||||||
- name: Run backup benchmarks
|
|
||||||
run: |
|
|
||||||
set -o pipefail
|
|
||||||
rm -rf /tmp/mock
|
|
||||||
xvfb-run --auto-servernum node \
|
|
||||||
ts/test-mock/benchmarks/backup_bench.js | \
|
|
||||||
tee benchmark-backup.log
|
|
||||||
timeout-minutes: 10
|
|
||||||
env:
|
|
||||||
NODE_ENV: production
|
|
||||||
ELECTRON_ENABLE_STACK_DUMPING: on
|
|
||||||
# DEBUG: 'mock:benchmarks'
|
|
||||||
ARTIFACTS_DIR: artifacts/backup-bench
|
|
||||||
|
|
||||||
- name: Upload benchmark logs on failure
|
- name: Upload benchmark logs on failure
|
||||||
if: failure()
|
if: failure()
|
||||||
|
@ -222,13 +158,6 @@ jobs:
|
||||||
- name: Publish to DataDog
|
- name: Publish to DataDog
|
||||||
working-directory: benchmark-results
|
working-directory: benchmark-results
|
||||||
run: |
|
run: |
|
||||||
node ./bin/publish.js ../benchmark-startup.log desktop.ci.performance.startup
|
node ./bin/publish.js ../benchmark.log destop.ci.performance.${{ matrix.metric }}
|
||||||
node ./bin/publish.js ../benchmark-send.log desktop.ci.performance.send
|
|
||||||
node ./bin/publish.js ../benchmark-group-send.log desktop.ci.performance.groupSend
|
|
||||||
node ./bin/publish.js ../benchmark-large-group-send-with-blocks.log desktop.ci.performance.largeGroupSendWithBlocks
|
|
||||||
node ./bin/publish.js ../benchmark-large-group-send.log desktop.ci.performance.largeGroupSend
|
|
||||||
node ./bin/publish.js ../benchmark-convo-open.log desktop.ci.performance.convoOpen
|
|
||||||
node ./bin/publish.js ../benchmark-call-history-search.log desktop.ci.performance.callHistorySearch
|
|
||||||
node ./bin/publish.js ../benchmark-backup.log desktop.ci.performance.backup
|
|
||||||
env:
|
env:
|
||||||
DD_API_KEY: ${{ secrets.DATADOG_API_KEY }}
|
DD_API_KEY: ${{ secrets.DATADOG_API_KEY }}
|
||||||
|
|
19
.github/workflows/ci.yml
vendored
19
.github/workflows/ci.yml
vendored
|
@ -370,6 +370,11 @@ jobs:
|
||||||
|
|
||||||
mock-tests:
|
mock-tests:
|
||||||
needs: lint
|
needs: lint
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
workerIndex: [0, 1, 2, 3]
|
||||||
|
|
||||||
runs-on: ubuntu-22.04-8-cores
|
runs-on: ubuntu-22.04-8-cores
|
||||||
if: ${{ github.repository == 'signalapp/Signal-Desktop-Private' }}
|
if: ${{ github.repository == 'signalapp/Signal-Desktop-Private' }}
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
|
@ -429,12 +434,24 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
xvfb-run --auto-servernum pnpm run test-mock
|
xvfb-run --auto-servernum pnpm run test-mock
|
||||||
|
timeout-minutes: 15
|
||||||
|
env:
|
||||||
|
NODE_ENV: production
|
||||||
|
DEBUG: mock:test:*
|
||||||
|
ARTIFACTS_DIR: artifacts/mock
|
||||||
|
WORKER_INDEX: ${{ matrix.workerIndex }}
|
||||||
|
WORKER_COUNT: 4
|
||||||
|
|
||||||
|
- name: Run docker mock server tests
|
||||||
|
if: ${{ matrix.workerIndex == 0 }}
|
||||||
|
run: |
|
||||||
|
set -o pipefail
|
||||||
xvfb-run --auto-servernum pnpm run test-mock-docker
|
xvfb-run --auto-servernum pnpm run test-mock-docker
|
||||||
timeout-minutes: 15
|
timeout-minutes: 15
|
||||||
env:
|
env:
|
||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
DEBUG: mock:test:*
|
DEBUG: mock:test:*
|
||||||
ARTIFACTS_DIR: artifacts/startup
|
ARTIFACTS_DIR: artifacts/mock-docker
|
||||||
|
|
||||||
- name: Upload mock server test logs on failure
|
- name: Upload mock server test logs on failure
|
||||||
if: failure()
|
if: failure()
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
"test-electron": "node ts/scripts/test-electron.js",
|
"test-electron": "node ts/scripts/test-electron.js",
|
||||||
"test-release": "node ts/scripts/test-release.js",
|
"test-release": "node ts/scripts/test-release.js",
|
||||||
"test-node": "cross-env LANG=en-us electron-mocha --timeout 10000 --main test/fix-linux-gtk.js --file test/setup-test-node.js --recursive ts/test-node",
|
"test-node": "cross-env LANG=en-us electron-mocha --timeout 10000 --main test/fix-linux-gtk.js --file test/setup-test-node.js --recursive ts/test-node",
|
||||||
"test-mock": "mocha --require ts/test-mock/setup-ci.js ts/test-mock/**/*_test.js",
|
"test-mock": "node ts/scripts/mocha-separator.js --require ts/test-mock/setup-ci.js -- ts/test-mock/**/*_test.js",
|
||||||
"test-mock-docker": "mocha --require ts/test-mock/setup-ci.js ts/test-mock/**/*_test.docker.js",
|
"test-mock-docker": "mocha --require ts/test-mock/setup-ci.js ts/test-mock/**/*_test.docker.js",
|
||||||
"test-eslint": "mocha .eslint/rules/**/*.test.js --ignore-leaks",
|
"test-eslint": "mocha .eslint/rules/**/*.test.js --ignore-leaks",
|
||||||
"test-lint-intl": "ts-node ./build/intl-linter/linter.ts --test",
|
"test-lint-intl": "ts-node ./build/intl-linter/linter.ts --test",
|
||||||
|
@ -336,7 +336,7 @@
|
||||||
"npm-run-all": "4.1.5",
|
"npm-run-all": "4.1.5",
|
||||||
"p-limit": "3.1.0",
|
"p-limit": "3.1.0",
|
||||||
"pixelmatch": "5.3.0",
|
"pixelmatch": "5.3.0",
|
||||||
"playwright": "1.45.0",
|
"playwright": "1.54.2",
|
||||||
"pngjs": "7.0.0",
|
"pngjs": "7.0.0",
|
||||||
"postcss": "8.5.3",
|
"postcss": "8.5.3",
|
||||||
"postcss-loader": "8.1.1",
|
"postcss-loader": "8.1.1",
|
||||||
|
|
28
pnpm-lock.yaml
generated
28
pnpm-lock.yaml
generated
|
@ -745,8 +745,8 @@ importers:
|
||||||
specifier: 5.3.0
|
specifier: 5.3.0
|
||||||
version: 5.3.0
|
version: 5.3.0
|
||||||
playwright:
|
playwright:
|
||||||
specifier: 1.45.0
|
specifier: 1.54.2
|
||||||
version: 1.45.0
|
version: 1.54.2
|
||||||
pngjs:
|
pngjs:
|
||||||
specifier: 7.0.0
|
specifier: 7.0.0
|
||||||
version: 7.0.0
|
version: 7.0.0
|
||||||
|
@ -8578,18 +8578,18 @@ packages:
|
||||||
resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==}
|
resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==}
|
||||||
engines: {node: '>=14.16'}
|
engines: {node: '>=14.16'}
|
||||||
|
|
||||||
playwright-core@1.45.0:
|
|
||||||
resolution: {integrity: sha512-lZmHlFQ0VYSpAs43dRq1/nJ9G/6SiTI7VPqidld9TDefL9tX87bTKExWZZUF5PeRyqtXqd8fQi2qmfIedkwsNQ==}
|
|
||||||
engines: {node: '>=18'}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
playwright-core@1.50.1:
|
playwright-core@1.50.1:
|
||||||
resolution: {integrity: sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ==}
|
resolution: {integrity: sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
playwright@1.45.0:
|
playwright-core@1.54.2:
|
||||||
resolution: {integrity: sha512-4z3ac3plDfYzGB6r0Q3LF8POPR20Z8D0aXcxbJvmfMgSSq1hkcgvFRXJk9rUq5H/MJ0Ktal869hhOdI/zUTeLA==}
|
resolution: {integrity: sha512-n5r4HFbMmWsB4twG7tJLDN9gmBUeSPcsBZiWSE4DnYz9mJMAFqr2ID7+eGC9kpEnxExJ1epttwR59LEWCk8mtA==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
|
playwright@1.54.2:
|
||||||
|
resolution: {integrity: sha512-Hu/BMoA1NAdRUuulyvQC0pEqZ4vQbGfn8f7wPXcnqQmM+zct9UliKxsIkLNmz/ku7LElUNqmaiv1TG/aL5ACsw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
@ -14312,7 +14312,7 @@ snapshots:
|
||||||
jest-serializer-html: 7.1.0
|
jest-serializer-html: 7.1.0
|
||||||
jest-watch-typeahead: 2.2.2(jest@29.7.0(@types/node@20.17.6)(ts-node@10.9.2(@swc/core@1.10.16(@swc/helpers@0.5.15))(@types/node@20.17.6)(typescript@5.6.3)))
|
jest-watch-typeahead: 2.2.2(jest@29.7.0(@types/node@20.17.6)(ts-node@10.9.2(@swc/core@1.10.16(@swc/helpers@0.5.15))(@types/node@20.17.6)(typescript@5.6.3)))
|
||||||
nyc: 15.1.0
|
nyc: 15.1.0
|
||||||
playwright: 1.45.0
|
playwright: 1.54.2
|
||||||
storybook: 8.4.4(bufferutil@4.0.9)(prettier@3.3.3)(utf-8-validate@5.0.10)
|
storybook: 8.4.4(bufferutil@4.0.9)(prettier@3.3.3)(utf-8-validate@5.0.10)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@swc/helpers'
|
- '@swc/helpers'
|
||||||
|
@ -20302,13 +20302,13 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
find-up: 6.3.0
|
find-up: 6.3.0
|
||||||
|
|
||||||
playwright-core@1.45.0: {}
|
|
||||||
|
|
||||||
playwright-core@1.50.1: {}
|
playwright-core@1.50.1: {}
|
||||||
|
|
||||||
playwright@1.45.0:
|
playwright-core@1.54.2: {}
|
||||||
|
|
||||||
|
playwright@1.54.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
playwright-core: 1.45.0
|
playwright-core: 1.54.2
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents: 2.3.2
|
fsevents: 2.3.2
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,11 @@ const fn = script.runInThisContext({
|
||||||
|
|
||||||
// See `ts/scripts/generate-preload-cache.ts`
|
// See `ts/scripts/generate-preload-cache.ts`
|
||||||
if (process.env.GENERATE_PRELOAD_CACHE) {
|
if (process.env.GENERATE_PRELOAD_CACHE) {
|
||||||
|
// Use hottest cache possible in CI
|
||||||
|
if (process.env.CI) {
|
||||||
|
fn(require, __dirname);
|
||||||
|
window.startApp();
|
||||||
|
}
|
||||||
writeFileSync(cachePath, script.createCachedData());
|
writeFileSync(cachePath, script.createCachedData());
|
||||||
ipcRenderer.send('shutdown');
|
ipcRenderer.send('shutdown');
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -351,6 +351,16 @@ export class ConversationController {
|
||||||
if (isGroupV1(conversation.attributes)) {
|
if (isGroupV1(conversation.attributes)) {
|
||||||
maybeDeriveGroupV2Id(conversation);
|
maybeDeriveGroupV2Id(conversation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If conversation does not have pre-existing storageID and is not our
|
||||||
|
// own (that we create on link), it might need to be uploaded to storage
|
||||||
|
// service.
|
||||||
|
if (conversation.attributes.storageID == null) {
|
||||||
|
StorageService.storageServiceUploadJob({
|
||||||
|
reason: 'new conversation',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
await saveConversation(conversation.attributes);
|
await saveConversation(conversation.attributes);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error(
|
log.error(
|
||||||
|
@ -1221,11 +1231,15 @@ export class ConversationController {
|
||||||
log.warn(`${logId}: Update messages table`);
|
log.warn(`${logId}: Update messages table`);
|
||||||
await migrateConversationMessages(obsoleteId, currentId);
|
await migrateConversationMessages(obsoleteId, currentId);
|
||||||
|
|
||||||
log.warn(`${logId}: Emit refreshConversation event to close old/open new`);
|
if (
|
||||||
window.Whisper.events.trigger('refreshConversation', {
|
window.reduxStore.getState().conversations.selectedConversationId ===
|
||||||
newId: currentId,
|
obsoleteId
|
||||||
oldId: obsoleteId,
|
) {
|
||||||
});
|
log.warn(`${logId}: opening new conversation`);
|
||||||
|
window.reduxActions.conversations.showConversation({
|
||||||
|
conversationId: currentId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
log.warn(
|
log.warn(
|
||||||
`${logId}: Eliminate old conversation from ConversationController lookups`
|
`${logId}: Eliminate old conversation from ConversationController lookups`
|
||||||
|
@ -1236,8 +1250,10 @@ export class ConversationController {
|
||||||
current.captureChange('combineConversations');
|
current.captureChange('combineConversations');
|
||||||
drop(current.updateLastMessage());
|
drop(current.updateLastMessage());
|
||||||
|
|
||||||
const state = window.reduxStore.getState();
|
if (
|
||||||
if (state.conversations.selectedConversationId === current.id) {
|
window.reduxStore.getState().conversations.selectedConversationId ===
|
||||||
|
current.id
|
||||||
|
) {
|
||||||
// TODO: DESKTOP-4807
|
// TODO: DESKTOP-4807
|
||||||
drop(current.loadNewestMessages(undefined, undefined));
|
drop(current.loadNewestMessages(undefined, undefined));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1457,6 +1457,7 @@ export async function startApp(): Promise<void> {
|
||||||
await StorageService.runStorageServiceSyncJob({
|
await StorageService.runStorageServiceSyncJob({
|
||||||
reason: andSync,
|
reason: andSync,
|
||||||
});
|
});
|
||||||
|
StorageService.runStorageServiceSyncJob.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -318,14 +318,15 @@ export function ConversationList({
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderRow: ListRowRenderer = useCallback(
|
const renderRow: ListRowRenderer = useCallback(
|
||||||
({ key, index, style }) => {
|
({ key: providedKey, index, style }) => {
|
||||||
const row = getRow(index);
|
const row = getRow(index);
|
||||||
if (!row) {
|
if (!row) {
|
||||||
assertDev(false, `Expected a row at index ${index}`);
|
assertDev(false, `Expected a row at index ${index}`);
|
||||||
return <div key={key} style={style} />;
|
return <div key={providedKey} style={style} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
let result: ReactNode;
|
let result: ReactNode;
|
||||||
|
let key: string;
|
||||||
switch (row.type) {
|
switch (row.type) {
|
||||||
case RowType.ArchiveButton:
|
case RowType.ArchiveButton:
|
||||||
result = (
|
result = (
|
||||||
|
@ -344,9 +345,11 @@ export function ConversationList({
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
key = 'archive';
|
||||||
break;
|
break;
|
||||||
case RowType.Blank:
|
case RowType.Blank:
|
||||||
result = undefined;
|
result = undefined;
|
||||||
|
key = `blank:${providedKey}`;
|
||||||
break;
|
break;
|
||||||
case RowType.Contact: {
|
case RowType.Contact: {
|
||||||
const { isClickable = true, hasContextMenu = false } = row;
|
const { isClickable = true, hasContextMenu = false } = row;
|
||||||
|
@ -368,6 +371,7 @@ export function ConversationList({
|
||||||
onRemove={isClickable ? removeConversation : undefined}
|
onRemove={isClickable ? removeConversation : undefined}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
key = `contact:${row.contact.id}`;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case RowType.ContactCheckbox:
|
case RowType.ContactCheckbox:
|
||||||
|
@ -382,6 +386,7 @@ export function ConversationList({
|
||||||
theme={theme}
|
theme={theme}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
key = `contact-checkbox:${row.contact.id}`;
|
||||||
break;
|
break;
|
||||||
case RowType.ClearFilterButton:
|
case RowType.ClearFilterButton:
|
||||||
result = (
|
result = (
|
||||||
|
@ -400,6 +405,7 @@ export function ConversationList({
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
key = 'clear-filter';
|
||||||
break;
|
break;
|
||||||
case RowType.PhoneNumberCheckbox:
|
case RowType.PhoneNumberCheckbox:
|
||||||
result = (
|
result = (
|
||||||
|
@ -419,6 +425,7 @@ export function ConversationList({
|
||||||
theme={theme}
|
theme={theme}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
key = `phone-number-checkbox:${row.phoneNumber.e164}`;
|
||||||
break;
|
break;
|
||||||
case RowType.UsernameCheckbox:
|
case RowType.UsernameCheckbox:
|
||||||
result = (
|
result = (
|
||||||
|
@ -438,6 +445,7 @@ export function ConversationList({
|
||||||
theme={theme}
|
theme={theme}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
key = `username-checkbox:${row.username}`;
|
||||||
break;
|
break;
|
||||||
case RowType.GenericCheckbox:
|
case RowType.GenericCheckbox:
|
||||||
result = (
|
result = (
|
||||||
|
@ -453,6 +461,7 @@ export function ConversationList({
|
||||||
clickable
|
clickable
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
key = `generic-checkbox:${providedKey}`;
|
||||||
break;
|
break;
|
||||||
case RowType.Conversation: {
|
case RowType.Conversation: {
|
||||||
const itemProps = pick(row.conversation, [
|
const itemProps = pick(row.conversation, [
|
||||||
|
@ -486,6 +495,7 @@ export function ConversationList({
|
||||||
'serviceId',
|
'serviceId',
|
||||||
]);
|
]);
|
||||||
const { badges, title, unreadCount, lastMessage } = itemProps;
|
const { badges, title, unreadCount, lastMessage } = itemProps;
|
||||||
|
key = `conversation:${itemProps.id}`;
|
||||||
result = (
|
result = (
|
||||||
<ConversationListItem
|
<ConversationListItem
|
||||||
{...itemProps}
|
{...itemProps}
|
||||||
|
@ -514,6 +524,7 @@ export function ConversationList({
|
||||||
onClick={showChooseGroupMembers}
|
onClick={showChooseGroupMembers}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
key = 'create-new-group';
|
||||||
break;
|
break;
|
||||||
case RowType.FindByUsername:
|
case RowType.FindByUsername:
|
||||||
result = (
|
result = (
|
||||||
|
@ -523,6 +534,7 @@ export function ConversationList({
|
||||||
onClick={showFindByUsername}
|
onClick={showFindByUsername}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
key = 'find-by-username';
|
||||||
break;
|
break;
|
||||||
case RowType.FindByPhoneNumber:
|
case RowType.FindByPhoneNumber:
|
||||||
result = (
|
result = (
|
||||||
|
@ -532,6 +544,7 @@ export function ConversationList({
|
||||||
onClick={showFindByPhoneNumber}
|
onClick={showFindByPhoneNumber}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
key = 'find-by-phonenumber';
|
||||||
break;
|
break;
|
||||||
case RowType.Header: {
|
case RowType.Header: {
|
||||||
const headerText = row.getHeaderText(i18n);
|
const headerText = row.getHeaderText(i18n);
|
||||||
|
@ -543,16 +556,20 @@ export function ConversationList({
|
||||||
{headerText}
|
{headerText}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
key = `header:${providedKey}`;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case RowType.MessageSearchResult:
|
case RowType.MessageSearchResult:
|
||||||
result = <>{renderMessageSearchResult?.(row.messageId)}</>;
|
result = <>{renderMessageSearchResult?.(row.messageId)}</>;
|
||||||
|
key = `message-search-result:${row.messageId}`;
|
||||||
break;
|
break;
|
||||||
case RowType.SearchResultsLoadingFakeHeader:
|
case RowType.SearchResultsLoadingFakeHeader:
|
||||||
result = <SearchResultsLoadingFakeHeaderComponent />;
|
result = <SearchResultsLoadingFakeHeaderComponent />;
|
||||||
|
key = `loading-header:${providedKey}`;
|
||||||
break;
|
break;
|
||||||
case RowType.SearchResultsLoadingFakeRow:
|
case RowType.SearchResultsLoadingFakeRow:
|
||||||
result = <SearchResultsLoadingFakeRowComponent />;
|
result = <SearchResultsLoadingFakeRowComponent />;
|
||||||
|
key = `loading-row:${providedKey}`;
|
||||||
break;
|
break;
|
||||||
case RowType.SelectSingleGroup:
|
case RowType.SelectSingleGroup:
|
||||||
result = (
|
result = (
|
||||||
|
@ -562,6 +579,7 @@ export function ConversationList({
|
||||||
onSelectGroup={onSelectConversation}
|
onSelectGroup={onSelectConversation}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
key = 'select-single-group';
|
||||||
break;
|
break;
|
||||||
case RowType.StartNewConversation:
|
case RowType.StartNewConversation:
|
||||||
result = (
|
result = (
|
||||||
|
@ -577,6 +595,7 @@ export function ConversationList({
|
||||||
showConversation={showConversation}
|
showConversation={showConversation}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
key = 'start-new-conversation';
|
||||||
break;
|
break;
|
||||||
case RowType.UsernameSearchResult:
|
case RowType.UsernameSearchResult:
|
||||||
result = (
|
result = (
|
||||||
|
@ -592,6 +611,7 @@ export function ConversationList({
|
||||||
showConversation={showConversation}
|
showConversation={showConversation}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
key = `username-search-result:${row.username}`;
|
||||||
break;
|
break;
|
||||||
case RowType.EmptyResults:
|
case RowType.EmptyResults:
|
||||||
result = (
|
result = (
|
||||||
|
@ -599,6 +619,7 @@ export function ConversationList({
|
||||||
{row.message}
|
{row.message}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
key = 'empty-results';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw missingCaseError(row);
|
throw missingCaseError(row);
|
||||||
|
|
|
@ -272,7 +272,13 @@ function renderNode({
|
||||||
!isLinkSneaky(node.url)
|
!isLinkSneaky(node.url)
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
<a key={key} className={formattingClasses} href={node.url}>
|
<a
|
||||||
|
key={key}
|
||||||
|
className={formattingClasses}
|
||||||
|
href={node.url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
{content}
|
{content}
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
|
|
|
@ -48,7 +48,7 @@ export const parseEnvironment = makeEnumParser(
|
||||||
export const isTestEnvironment = (env: Environment): boolean =>
|
export const isTestEnvironment = (env: Environment): boolean =>
|
||||||
env === Environment.Test;
|
env === Environment.Test;
|
||||||
|
|
||||||
const isMockEnvironment = (): boolean => {
|
export const isMockEnvironment = (): boolean => {
|
||||||
if (isMockTestEnvironment == null) {
|
if (isMockTestEnvironment == null) {
|
||||||
log.error('Mock test environment not set');
|
log.error('Mock test environment not set');
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,9 @@ export async function commonShouldJobContinue({
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await waitForOnline({ timeout: timeRemaining });
|
if (isDeviceLinked()) {
|
||||||
|
await waitForOnline({ timeout: timeRemaining });
|
||||||
|
}
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
log.info("didn't come online in time, giving up");
|
log.info("didn't come online in time, giving up");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -39,6 +39,7 @@ async function main(): Promise<void> {
|
||||||
WAYLAND_DISPLAY: process.env.WAYLAND_DISPLAY,
|
WAYLAND_DISPLAY: process.env.WAYLAND_DISPLAY,
|
||||||
XAUTHORITY: process.env.XAUTHORITY,
|
XAUTHORITY: process.env.XAUTHORITY,
|
||||||
|
|
||||||
|
CI: process.env.CI ? 'on' : undefined,
|
||||||
GENERATE_PRELOAD_CACHE: 'on',
|
GENERATE_PRELOAD_CACHE: 'on',
|
||||||
SIGNAL_CI_CONFIG: JSON.stringify({
|
SIGNAL_CI_CONFIG: JSON.stringify({
|
||||||
storagePath,
|
storagePath,
|
||||||
|
|
27
ts/scripts/mocha-separator.ts
Normal file
27
ts/scripts/mocha-separator.ts
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// Copyright 2025 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import { spawnSync } from 'node:child_process';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
|
||||||
|
const MOCHA = join(__dirname, '..', '..', 'node_modules', '.bin', 'mocha');
|
||||||
|
const WORKER_COUNT = parseInt(process.env.WORKER_COUNT || '1', 10);
|
||||||
|
const WORKER_INDEX = parseInt(process.env.WORKER_INDEX || '0', 10);
|
||||||
|
|
||||||
|
const separator = process.argv.indexOf('--');
|
||||||
|
if (separator === -1) {
|
||||||
|
throw new Error('Expected `--` separator between options and files');
|
||||||
|
}
|
||||||
|
|
||||||
|
const flags = process.argv.slice(2, separator);
|
||||||
|
const files = process.argv.slice(separator + 1);
|
||||||
|
|
||||||
|
const filteredFiles = files.filter((_file, index) => {
|
||||||
|
return index % WORKER_COUNT === WORKER_INDEX;
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`Running on ${filteredFiles.length}/${files.length} of files`);
|
||||||
|
|
||||||
|
spawnSync(MOCHA, [...flags, ...filteredFiles], {
|
||||||
|
stdio: 'inherit',
|
||||||
|
});
|
|
@ -1034,6 +1034,7 @@ export class BackupsService {
|
||||||
window.Whisper.events.once('storageService:syncComplete', resolve);
|
window.Whisper.events.once('storageService:syncComplete', resolve);
|
||||||
|
|
||||||
runStorageServiceSyncJob({ reason });
|
runStorageServiceSyncJob({ reason });
|
||||||
|
runStorageServiceSyncJob.flush();
|
||||||
await storageService;
|
await storageService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,9 @@ import {
|
||||||
getRoomIdFromRootKeyString,
|
getRoomIdFromRootKeyString,
|
||||||
} from '../util/callLinksRingrtc';
|
} from '../util/callLinksRingrtc';
|
||||||
import { fromPniUuidBytesOrUntaggedString } from '../util/ServiceId';
|
import { fromPniUuidBytesOrUntaggedString } from '../util/ServiceId';
|
||||||
|
import { isDone as isRegistrationDone } from '../util/registration';
|
||||||
import { callLinkRefreshJobQueue } from '../jobs/callLinkRefreshJobQueue';
|
import { callLinkRefreshJobQueue } from '../jobs/callLinkRefreshJobQueue';
|
||||||
|
import { isMockEnvironment } from '../environment';
|
||||||
|
|
||||||
const log = createLogger('storage');
|
const log = createLogger('storage');
|
||||||
|
|
||||||
|
@ -2083,7 +2085,6 @@ async function upload({
|
||||||
if (!window.storage.get('storageKey')) {
|
if (!window.storage.get('storageKey')) {
|
||||||
// requesting new keys runs the sync job which will detect the conflict
|
// requesting new keys runs the sync job which will detect the conflict
|
||||||
// and re-run the upload job once we're merged and up-to-date.
|
// and re-run the upload job once we're merged and up-to-date.
|
||||||
log.info(`${logId}: no storageKey, requesting new keys`);
|
|
||||||
backOff.reset();
|
backOff.reset();
|
||||||
|
|
||||||
if (window.ConversationController.areWePrimaryDevice()) {
|
if (window.ConversationController.areWePrimaryDevice()) {
|
||||||
|
@ -2091,6 +2092,12 @@ async function upload({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isRegistrationDone()) {
|
||||||
|
log.warn(`${logId}: no storageKey, unlinked`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info(`${logId}: no storageKey, requesting new keys`);
|
||||||
await singleProtoJobQueue.add(MessageSender.getRequestKeySyncMessage());
|
await singleProtoJobQueue.add(MessageSender.getRequestKeySyncMessage());
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -2267,7 +2274,7 @@ export const storageServiceUploadJob = debounce(
|
||||||
`upload v${window.storage.get('manifestVersion')}`
|
`upload v${window.storage.get('manifestVersion')}`
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
500
|
isMockEnvironment() ? 0 : 500
|
||||||
);
|
);
|
||||||
|
|
||||||
export const runStorageServiceSyncJob = debounce(
|
export const runStorageServiceSyncJob = debounce(
|
||||||
|
@ -2289,7 +2296,7 @@ export const runStorageServiceSyncJob = debounce(
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
500
|
isMockEnvironment() ? 0 : 500
|
||||||
);
|
);
|
||||||
|
|
||||||
export const addPendingDelete = (item: ExtendedStorageID): void => {
|
export const addPendingDelete = (item: ExtendedStorageID): void => {
|
||||||
|
|
|
@ -4879,14 +4879,17 @@ function onConversationClosed(
|
||||||
): ThunkAction<void, RootStateType, unknown, ConversationUnloadedActionType> {
|
): ThunkAction<void, RootStateType, unknown, ConversationUnloadedActionType> {
|
||||||
return async dispatch => {
|
return async dispatch => {
|
||||||
const conversation = window.ConversationController.get(conversationId);
|
const conversation = window.ConversationController.get(conversationId);
|
||||||
|
// Conversation was removed due to the merge
|
||||||
if (!conversation) {
|
if (!conversation) {
|
||||||
throw new Error('onConversationClosed: Conversation not found');
|
log.warn(
|
||||||
|
`onConversationClosed: Conversation ${conversationId} not found`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const logId = `onConversationClosed/${conversation.idForLogging()}`;
|
const logId = `onConversationClosed/${conversation?.idForLogging() ?? conversationId}`;
|
||||||
log.info(`${logId}: unloading due to ${reason}`);
|
log.info(`${logId}: unloading due to ${reason}`);
|
||||||
|
|
||||||
if (conversation.get('draftChanged')) {
|
if (conversation?.get('draftChanged')) {
|
||||||
if (conversation.hasDraft()) {
|
if (conversation.hasDraft()) {
|
||||||
log.info(`${logId}: new draft info needs update`);
|
log.info(`${logId}: new draft info needs update`);
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
|
|
@ -102,18 +102,6 @@ export const SmartChatsTab = memo(function SmartChatsTab() {
|
||||||
}, [prevConversationId, selectedConversationId]);
|
}, [prevConversationId, selectedConversationId]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function refreshConversation({
|
|
||||||
newId,
|
|
||||||
oldId,
|
|
||||||
}: {
|
|
||||||
newId: string;
|
|
||||||
oldId: string;
|
|
||||||
}) {
|
|
||||||
if (prevConversationId === oldId) {
|
|
||||||
showConversation({ conversationId: newId });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close current opened conversation to reload the group information once
|
// Close current opened conversation to reload the group information once
|
||||||
// linked.
|
// linked.
|
||||||
function unload() {
|
function unload() {
|
||||||
|
@ -128,12 +116,10 @@ export const SmartChatsTab = memo(function SmartChatsTab() {
|
||||||
}
|
}
|
||||||
|
|
||||||
window.Whisper.events.on('pack-install-failed', packInstallFailed);
|
window.Whisper.events.on('pack-install-failed', packInstallFailed);
|
||||||
window.Whisper.events.on('refreshConversation', refreshConversation);
|
|
||||||
window.Whisper.events.on('setupAsNewDevice', unload);
|
window.Whisper.events.on('setupAsNewDevice', unload);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
window.Whisper.events.off('pack-install-failed', packInstallFailed);
|
window.Whisper.events.off('pack-install-failed', packInstallFailed);
|
||||||
window.Whisper.events.off('refreshConversation', refreshConversation);
|
|
||||||
window.Whisper.events.off('setupAsNewDevice', unload);
|
window.Whisper.events.off('setupAsNewDevice', unload);
|
||||||
};
|
};
|
||||||
}, [onConversationClosed, prevConversationId, showConversation, showToast]);
|
}, [onConversationClosed, prevConversationId, showConversation, showToast]);
|
||||||
|
|
|
@ -400,17 +400,22 @@ export class Bootstrap {
|
||||||
await app.stageLocalBackupForImport(localBackup);
|
await app.stageLocalBackupForImport(localBackup);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug('looking for QR code or relink button');
|
let gotProvisionURL = false;
|
||||||
const qrCode = window.locator(
|
|
||||||
'.module-InstallScreenQrCodeNotScannedStep__qr-code__code'
|
drop(
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const relinkButton = window.locator('.LeftPaneDialog__icon--relink');
|
||||||
|
await relinkButton.waitFor();
|
||||||
|
if (gotProvisionURL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await relinkButton.click();
|
||||||
|
} catch {
|
||||||
|
// Ignore, provision will fail if QR code was never generated
|
||||||
|
}
|
||||||
|
})()
|
||||||
);
|
);
|
||||||
const relinkButton = window.locator('.LeftPaneDialog__icon--relink');
|
|
||||||
await qrCode.or(relinkButton).waitFor();
|
|
||||||
if (await relinkButton.isVisible()) {
|
|
||||||
debug('unlinked, clicking left pane button');
|
|
||||||
await relinkButton.click();
|
|
||||||
await qrCode.waitFor();
|
|
||||||
}
|
|
||||||
|
|
||||||
debug('waiting for provision');
|
debug('waiting for provision');
|
||||||
const provision = await this.server.waitForProvision();
|
const provision = await this.server.waitForProvision();
|
||||||
|
@ -418,6 +423,8 @@ export class Bootstrap {
|
||||||
debug('waiting for provision URL');
|
debug('waiting for provision URL');
|
||||||
const provisionURL = await app.waitForProvisionURL();
|
const provisionURL = await app.waitForProvisionURL();
|
||||||
|
|
||||||
|
gotProvisionURL = true;
|
||||||
|
|
||||||
debug('completing provision');
|
debug('completing provision');
|
||||||
this.#privDesktop = await provision.complete({
|
this.#privDesktop = await provision.complete({
|
||||||
provisionURL,
|
provisionURL,
|
||||||
|
|
|
@ -57,7 +57,9 @@ describe('readSync', function (this: Mocha.Suite) {
|
||||||
const leftPane = page.locator('#LeftPane');
|
const leftPane = page.locator('#LeftPane');
|
||||||
|
|
||||||
await leftPane
|
await leftPane
|
||||||
.locator('.module-conversation-list__item--contact-or-conversation')
|
.locator(
|
||||||
|
'.module-conversation-list__item--contact-or-conversation >> "<(˶ᵔᵕᵔ˶)>"'
|
||||||
|
)
|
||||||
.first()
|
.first()
|
||||||
.waitFor();
|
.waitFor();
|
||||||
|
|
||||||
|
|
|
@ -87,11 +87,13 @@ describe('messaging/relink', function (this: Mocha.Suite) {
|
||||||
)
|
)
|
||||||
.waitFor();
|
.waitFor();
|
||||||
|
|
||||||
|
debug('unlinkng');
|
||||||
await app.unlink();
|
await app.unlink();
|
||||||
await app.waitForUnlink();
|
await app.waitForUnlink();
|
||||||
await phone.unlink(desktop);
|
await phone.unlink(desktop);
|
||||||
await server.removeDevice(desktop.number, desktop.deviceId);
|
await server.removeDevice(desktop.number, desktop.deviceId);
|
||||||
|
|
||||||
|
debug('closing');
|
||||||
await app.close();
|
await app.close();
|
||||||
|
|
||||||
debug('change pinned contact, identity key');
|
debug('change pinned contact, identity key');
|
||||||
|
|
|
@ -88,9 +88,7 @@ describe('unprocessed', function (this: Mocha.Suite) {
|
||||||
const page = await app.getWindow();
|
const page = await app.getWindow();
|
||||||
|
|
||||||
debug('opening conversation');
|
debug('opening conversation');
|
||||||
await page
|
await page.getByTestId(alice.device.aci).click();
|
||||||
.locator(`[data-testid="${alice.device.aci}"] >> "${alice.profileName}"`)
|
|
||||||
.click();
|
|
||||||
|
|
||||||
await page.locator('.module-message__text >> "hello: 4"').waitFor();
|
await page.locator('.module-message__text >> "hello: 4"').waitFor();
|
||||||
await page.locator('.module-message__text >> "hello: 5"').waitFor();
|
await page.locator('.module-message__text >> "hello: 5"').waitFor();
|
||||||
|
|
|
@ -83,6 +83,7 @@ export class App extends EventEmitter {
|
||||||
snapshots: true,
|
snapshots: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
await page?.emulateMedia({ reducedMotion: 'reduce' });
|
||||||
await page?.waitForLoadState('load');
|
await page?.waitForLoadState('load');
|
||||||
})(),
|
})(),
|
||||||
20 * SECOND
|
20 * SECOND
|
||||||
|
|
|
@ -110,10 +110,12 @@ describe('storage service', function (this: Mocha.Suite) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatedState = await phone.setStorageState(
|
const updatedState = await phone.setStorageState(
|
||||||
state.addRecord({
|
state
|
||||||
type: IdentifierType.ACCOUNT,
|
.addRecord({
|
||||||
record: oldAccount.record,
|
type: IdentifierType.ACCOUNT,
|
||||||
})
|
record: oldAccount.record,
|
||||||
|
})
|
||||||
|
.updateAccount({})
|
||||||
);
|
);
|
||||||
|
|
||||||
debug('sending fetch storage');
|
debug('sending fetch storage');
|
||||||
|
|
|
@ -48,20 +48,21 @@ describe('storage service', function (this: Mocha.Suite) {
|
||||||
debug('Unpinning group via storage service');
|
debug('Unpinning group via storage service');
|
||||||
{
|
{
|
||||||
const state = await phone.expectStorageState('initial state');
|
const state = await phone.expectStorageState('initial state');
|
||||||
|
const newState = state.unpinGroup(group);
|
||||||
|
|
||||||
await phone.setStorageState(state.unpinGroup(group));
|
await phone.setStorageState(newState);
|
||||||
await phone.sendFetchStorage({
|
await phone.sendFetchStorage({
|
||||||
timestamp: bootstrap.getTimestamp(),
|
timestamp: bootstrap.getTimestamp(),
|
||||||
});
|
});
|
||||||
|
|
||||||
await leftPane.locator(`[data-testid="${group.id}"]`).waitFor();
|
await app.waitForManifestVersion(newState.version);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug('Pinning group in the app');
|
debug('Pinning group in the app');
|
||||||
{
|
{
|
||||||
const state = await phone.expectStorageState('consistency check');
|
const state = await phone.expectStorageState('consistency check');
|
||||||
|
|
||||||
const convo = leftPane.locator(`[data-testid="${group.id}"]`);
|
const convo = leftPane.getByTestId(group.id);
|
||||||
await convo.click();
|
await convo.click();
|
||||||
|
|
||||||
const moreButton = conversationStack.locator(
|
const moreButton = conversationStack.locator(
|
||||||
|
|
|
@ -70,11 +70,10 @@ describe('storage service', function (this: Mocha.Suite) {
|
||||||
|
|
||||||
await conversationView
|
await conversationView
|
||||||
.locator(`a:has-text("${STICKER_PACKS[0].id.toString('hex')}")`)
|
.locator(`a:has-text("${STICKER_PACKS[0].id.toString('hex')}")`)
|
||||||
.click({ noWaitAfter: true });
|
.click();
|
||||||
await window
|
await window
|
||||||
.locator(
|
.getByTestId('StickerPreviewModal')
|
||||||
'.module-sticker-manager__preview-modal__footer--install button >> "Install"'
|
.getByRole('button', { name: 'Install' })
|
||||||
)
|
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
debug('waiting for sync message');
|
debug('waiting for sync message');
|
||||||
|
@ -114,12 +113,10 @@ describe('storage service', function (this: Mocha.Suite) {
|
||||||
|
|
||||||
await conversationView
|
await conversationView
|
||||||
.locator(`a:has-text("${STICKER_PACKS[0].id.toString('hex')}")`)
|
.locator(`a:has-text("${STICKER_PACKS[0].id.toString('hex')}")`)
|
||||||
.click({ noWaitAfter: true });
|
.click();
|
||||||
await window
|
await window
|
||||||
.locator(
|
.getByTestId('StickerPreviewModal')
|
||||||
'.module-sticker-manager__preview-modal__footer--install button ' +
|
.getByRole('button', { name: 'Uninstall' })
|
||||||
'>> "Uninstall"'
|
|
||||||
)
|
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
// Confirm
|
// Confirm
|
||||||
|
|
|
@ -28,6 +28,7 @@ import type {
|
||||||
import createTaskWithTimeout from './TaskWithTimeout';
|
import createTaskWithTimeout from './TaskWithTimeout';
|
||||||
import * as Bytes from '../Bytes';
|
import * as Bytes from '../Bytes';
|
||||||
import * as Errors from '../types/errors';
|
import * as Errors from '../types/errors';
|
||||||
|
import { isMockEnvironment } from '../environment';
|
||||||
import { senderCertificateService } from '../services/senderCertificate';
|
import { senderCertificateService } from '../services/senderCertificate';
|
||||||
import { backupsService } from '../services/backups';
|
import { backupsService } from '../services/backups';
|
||||||
import {
|
import {
|
||||||
|
@ -96,7 +97,9 @@ const LAST_RESORT_KEY_UPDATE_TIME_KEY: StorageKeyByServiceIdKind = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const PRE_KEY_ARCHIVE_AGE = 90 * DAY;
|
const PRE_KEY_ARCHIVE_AGE = 90 * DAY;
|
||||||
const PRE_KEY_GEN_BATCH_SIZE = 100;
|
// Use 20 keys for mock tests which is above the minimum, but takes much less
|
||||||
|
// time to generate and store in the database (especially for PQ keys)
|
||||||
|
const PRE_KEY_GEN_BATCH_SIZE = isMockEnvironment() ? 20 : 100;
|
||||||
const PRE_KEY_MAX_COUNT = 200;
|
const PRE_KEY_MAX_COUNT = 200;
|
||||||
const PRE_KEY_ID_KEY: StorageKeyByServiceIdKind = {
|
const PRE_KEY_ID_KEY: StorageKeyByServiceIdKind = {
|
||||||
[ServiceIdKind.ACI]: 'maxPreKeyId',
|
[ServiceIdKind.ACI]: 'maxPreKeyId',
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue