mirror of
https://github.com/element-hq/element-web.git
synced 2025-12-11 01:40:42 +00:00
Compare commits
343 Commits
t3chguy/re
...
t3chguy/je
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b619c5121 | ||
|
|
b07d10cb23 | ||
|
|
179b17434e | ||
|
|
ab401160f8 | ||
|
|
5448de5dd6 | ||
|
|
be181d2c79 | ||
|
|
baaed75c4b | ||
|
|
cd7cf86b96 | ||
|
|
2c4a079153 | ||
|
|
9099338af8 | ||
|
|
f621c342ff | ||
|
|
4c1924311f | ||
|
|
a7e3764c27 | ||
|
|
07f1680ba0 | ||
|
|
3fbc9e6de6 | ||
|
|
117bee787f | ||
|
|
580213da5d | ||
|
|
22530d6ea5 | ||
|
|
e7d9df24e2 | ||
|
|
95c879c9e5 | ||
|
|
cbc1838755 | ||
|
|
c2799a1812 | ||
|
|
980b922348 | ||
|
|
ad77f7943b | ||
|
|
89d7dca464 | ||
|
|
aa44cadb02 | ||
|
|
941f4e1005 | ||
|
|
9b85c2d0fd | ||
|
|
1e0dfd0241 | ||
|
|
bea1b8eb85 | ||
|
|
d5db16ca24 | ||
|
|
edaf9773c0 | ||
|
|
7ea188cf89 | ||
|
|
a581e776a8 | ||
|
|
8d261d9819 | ||
|
|
299270e52d | ||
|
|
943b817194 | ||
|
|
2aa72bb40b | ||
|
|
a755e399cf | ||
|
|
8dff758153 | ||
|
|
cf3bdbdc7a | ||
|
|
ba98c2085d | ||
|
|
b330de5d6e | ||
|
|
b86bb5cc2f | ||
|
|
e835cab139 | ||
|
|
af3040fb62 | ||
|
|
b6ba3335ec | ||
|
|
6b7c94905f | ||
|
|
a4e8bb3f9a | ||
|
|
2b4000d47f | ||
|
|
01304439ee | ||
|
|
c659afa8db | ||
|
|
9cc5564d50 | ||
|
|
549300726f | ||
|
|
319dab5920 | ||
|
|
5c51d179b9 | ||
|
|
dbdb23f6bc | ||
|
|
5686666ad2 | ||
|
|
0c4189f2ed | ||
|
|
450cb608ec | ||
|
|
7e03f38a3b | ||
|
|
9bf3d22439 | ||
|
|
5547101bcc | ||
|
|
085854b125 | ||
|
|
ee24989f49 | ||
|
|
5a418f3f19 | ||
|
|
db5b3359c6 | ||
|
|
188f910dc7 | ||
|
|
619e41e3a2 | ||
|
|
c1838b34b6 | ||
|
|
1d51323451 | ||
|
|
d0d0b8212d | ||
|
|
974d3c175a | ||
|
|
d0e19d3e03 | ||
|
|
b016cf59e9 | ||
|
|
cfdfc4e640 | ||
|
|
d0fea745bb | ||
|
|
f3ef9e6602 | ||
|
|
af0391b86a | ||
|
|
36108c0c22 | ||
|
|
d2acce1221 | ||
|
|
b72c053d1a | ||
|
|
865c5b0e9c | ||
|
|
ce3fa2164f | ||
|
|
60b0e8b237 | ||
|
|
823828fc17 | ||
|
|
8774a68a13 | ||
|
|
4730352092 | ||
|
|
0429809c00 | ||
|
|
06fa3481df | ||
|
|
e75ff818d3 | ||
|
|
2c3e01a31c | ||
|
|
84709df3c9 | ||
|
|
00aadf1580 | ||
|
|
d8ebc68aa8 | ||
|
|
5d72735b1f | ||
|
|
2099aaa663 | ||
|
|
6d8cbf39f5 | ||
|
|
b87437d439 | ||
|
|
8619a22f57 | ||
|
|
418f121f96 | ||
|
|
351774d3e3 | ||
|
|
70f898c71d | ||
|
|
4f276c1690 | ||
|
|
2b4ce627b8 | ||
|
|
d68c5a26af | ||
|
|
95175caf0c | ||
|
|
08418c16c9 | ||
|
|
6798239aa8 | ||
|
|
9c74110969 | ||
|
|
1bee3becfb | ||
|
|
bfac727307 | ||
|
|
8e213c5d34 | ||
|
|
c34cbd011d | ||
|
|
e10ecc9a4d | ||
|
|
3dbcb5efa3 | ||
|
|
2b883a8aa0 | ||
|
|
bb54a0e063 | ||
|
|
af3a9777e8 | ||
|
|
61542ff3a8 | ||
|
|
ec460326f1 | ||
|
|
af846f8be9 | ||
|
|
de5ddcf6f7 | ||
|
|
8d28dd3784 | ||
|
|
df7703a4a5 | ||
|
|
fe7ac68478 | ||
|
|
bda045fad0 | ||
|
|
8a7cdaa3ef | ||
|
|
7796200562 | ||
|
|
80cd93678a | ||
|
|
b8c178d133 | ||
|
|
5f4d789259 | ||
|
|
85711be352 | ||
|
|
a891dcddc2 | ||
|
|
61947deef5 | ||
|
|
c1549e6aaa | ||
|
|
adfc66bd1b | ||
|
|
dbfb84eb77 | ||
|
|
3d48168394 | ||
|
|
9ddd5d96eb | ||
|
|
e6dc6b93a7 | ||
|
|
bd0bb879ec | ||
|
|
903928c33c | ||
|
|
0525887be4 | ||
|
|
4259e96c90 | ||
|
|
20532144d2 | ||
|
|
d2eeb3d8af | ||
|
|
b4445fed53 | ||
|
|
9860f9320a | ||
|
|
c8f46a0191 | ||
|
|
4285b4b140 | ||
|
|
de820e11fc | ||
|
|
94130be5a7 | ||
|
|
0333cba258 | ||
|
|
2ebc1b4a89 | ||
|
|
756ce2c639 | ||
|
|
c519361b4e | ||
|
|
15bd59b81a | ||
|
|
c74f9159ad | ||
|
|
2ac2bae4fa | ||
|
|
a478463b75 | ||
|
|
3f221891f7 | ||
|
|
a2a066d8b4 | ||
|
|
ede91bf921 | ||
|
|
fd7c50f61d | ||
|
|
3d6664109b | ||
|
|
7d20bd4d06 | ||
|
|
e0e522a0e9 | ||
|
|
8df26a54cf | ||
|
|
c2ce7dbc5e | ||
|
|
affa4e5211 | ||
|
|
04604e5171 | ||
|
|
0e38df84c8 | ||
|
|
2ce588ac64 | ||
|
|
cdfb58501d | ||
|
|
f89f050f07 | ||
|
|
eddaf7c47e | ||
|
|
3860226ee2 | ||
|
|
b907ec380f | ||
|
|
5d7c71210f | ||
|
|
d8844c682b | ||
|
|
72989ea646 | ||
|
|
95630f525f | ||
|
|
d5c111f656 | ||
|
|
7329a5f1fc | ||
|
|
2063624fb6 | ||
|
|
03a1d89785 | ||
|
|
5cdcf44b6f | ||
|
|
ca33d9165a | ||
|
|
2dffadc92e | ||
|
|
48fd330dd9 | ||
|
|
f0af77712f | ||
|
|
60ff33fecc | ||
|
|
3bcc27a444 | ||
|
|
7e33f03a02 | ||
|
|
0d5c9a338b | ||
|
|
d4ab40990b | ||
|
|
c8e4ffe1dd | ||
|
|
0ae74a9e1f | ||
|
|
ed9795137b | ||
|
|
4f8e9eb9ac | ||
|
|
08f41a48a8 | ||
|
|
9b316e8e7f | ||
|
|
72a2773629 | ||
|
|
abf6d58b7b | ||
|
|
cafa02ccc2 | ||
|
|
28640eec5f | ||
|
|
ce928e8d1f | ||
|
|
774b767b80 | ||
|
|
e7cd322559 | ||
|
|
ae3ca52bd2 | ||
|
|
d36cfc37e2 | ||
|
|
e3f8a7b13d | ||
|
|
048f88e10e | ||
|
|
9a126795a8 | ||
|
|
5b0aa511a6 | ||
|
|
346b45751c | ||
|
|
4f7c61ff68 | ||
|
|
da2e126ce1 | ||
|
|
18ef975386 | ||
|
|
ec96d33ed7 | ||
|
|
926c45488d | ||
|
|
b8e54750a0 | ||
|
|
84bd188dd7 | ||
|
|
ca239fee4d | ||
|
|
349c9b0c26 | ||
|
|
73db771ff3 | ||
|
|
f77d9b4bcb | ||
|
|
27b62d022e | ||
|
|
5c3a518576 | ||
|
|
3132fe3233 | ||
|
|
6e5f593c98 | ||
|
|
8bf3ec8376 | ||
|
|
eb938c21d6 | ||
|
|
e5c0cdc402 | ||
|
|
8a756b592c | ||
|
|
c67e67af4e | ||
|
|
7b1e303328 | ||
|
|
27a43e860a | ||
|
|
9b5d0866e0 | ||
|
|
86c6ba9dd7 | ||
|
|
0faf298e05 | ||
|
|
ef382584f0 | ||
|
|
d8d60170ac | ||
|
|
159d62f7d3 | ||
|
|
6424853f27 | ||
|
|
84b07cbbaa | ||
|
|
b03c84f51e | ||
|
|
ad2dda960e | ||
|
|
ee63710ef1 | ||
|
|
90f9f53bc1 | ||
|
|
3c00a40a1d | ||
|
|
54d7974863 | ||
|
|
1fd497fd55 | ||
|
|
26e961489f | ||
|
|
21a309290a | ||
|
|
08cb450d25 | ||
|
|
4bdd4f4f49 | ||
|
|
6d1b702214 | ||
|
|
bbe474ae57 | ||
|
|
bebf44d9ee | ||
|
|
231073c578 | ||
|
|
a00c343435 | ||
|
|
1e2e8844e5 | ||
|
|
6bc8080ec5 | ||
|
|
bff17ff470 | ||
|
|
c0a313abae | ||
|
|
db30bc51a1 | ||
|
|
c8c107405f | ||
|
|
6134cfd9c4 | ||
|
|
3f70105204 | ||
|
|
4ff08f942d | ||
|
|
29b75385a3 | ||
|
|
17de66140d | ||
|
|
f3d0fc4d68 | ||
|
|
0b636aec4b | ||
|
|
d0cddc5b66 | ||
|
|
cb0d72fc2f | ||
|
|
9a6be72c10 | ||
|
|
536d6ad360 | ||
|
|
b604a6ea8c | ||
|
|
da4672d715 | ||
|
|
74a919cb65 | ||
|
|
b92101a3da | ||
|
|
5057668705 | ||
|
|
931edd7419 | ||
|
|
044eaf7eb5 | ||
|
|
88c72a1514 | ||
|
|
d06cf09bf0 | ||
|
|
2f8e98242c | ||
|
|
1c6408081f | ||
|
|
3ff5a511e5 | ||
|
|
f3e976d67d | ||
|
|
21930a10ae | ||
|
|
82a6826a02 | ||
|
|
1c06ebadcd | ||
|
|
458b4a45e5 | ||
|
|
01039137b5 | ||
|
|
f86099c76e | ||
|
|
464be37815 | ||
|
|
f919d1654a | ||
|
|
7093c9a61b | ||
|
|
9ef3b0b994 | ||
|
|
6042625198 | ||
|
|
9d79a934bf | ||
|
|
a355292a7f | ||
|
|
24fabfff89 | ||
|
|
0b6ed44390 | ||
|
|
a6ce6dc7ab | ||
|
|
15984455af | ||
|
|
6e4bd564d5 | ||
|
|
aeabf3b188 | ||
|
|
c9d9c421bc | ||
|
|
d7d96b6b8b | ||
|
|
2631b908b6 | ||
|
|
502cc91dfe | ||
|
|
38e5eeea00 | ||
|
|
1ccbdb21e9 | ||
|
|
b1ef099cd6 | ||
|
|
00d46f1c8f | ||
|
|
8e304713a2 | ||
|
|
0899165d9e | ||
|
|
2d9982f9f0 | ||
|
|
b8fd98ab3c | ||
|
|
a27dfa1825 | ||
|
|
a3ece9d902 | ||
|
|
23613ac37e | ||
|
|
195337d865 | ||
|
|
4bb9f2ed7b | ||
|
|
e0ffddf3eb | ||
|
|
386b782f2a | ||
|
|
849f2c9818 | ||
|
|
8ebfaadeed | ||
|
|
1d49a46dd2 | ||
|
|
dabe6722aa | ||
|
|
10a63b3c23 | ||
|
|
9ce515a646 | ||
|
|
1df72ce2d0 | ||
|
|
6a960204b3 | ||
|
|
26cd13ae3c | ||
|
|
3793c6daca | ||
|
|
65f0d7930a | ||
|
|
8b914c02d0 |
@@ -1,60 +0,0 @@
|
||||
module.exports = {
|
||||
plugins: ["matrix-org"],
|
||||
extends: ["./.eslintrc.js"],
|
||||
parserOptions: {
|
||||
project: ["./tsconfig.module_system.json"],
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ["module_system/**/*.{ts,tsx}"],
|
||||
extends: ["plugin:matrix-org/typescript", "plugin:matrix-org/react"],
|
||||
// NOTE: These rules are frozen and new rules should not be added here.
|
||||
// New changes belong in https://github.com/matrix-org/eslint-plugin-matrix-org/
|
||||
rules: {
|
||||
// Things we do that break the ideal style
|
||||
"prefer-promise-reject-errors": "off",
|
||||
"quotes": "off",
|
||||
|
||||
// We disable this while we're transitioning
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
// We're okay with assertion errors when we ask for them
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
|
||||
// Ban matrix-js-sdk/src imports in favour of matrix-js-sdk/src/matrix imports to prevent unleashing hell.
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
paths: [
|
||||
{
|
||||
name: "matrix-js-sdk",
|
||||
message: "Please use matrix-js-sdk/src/matrix instead",
|
||||
},
|
||||
{
|
||||
name: "matrix-js-sdk/",
|
||||
message: "Please use matrix-js-sdk/src/matrix instead",
|
||||
},
|
||||
{
|
||||
name: "matrix-js-sdk/src",
|
||||
message: "Please use matrix-js-sdk/src/matrix instead",
|
||||
},
|
||||
{
|
||||
name: "matrix-js-sdk/src/",
|
||||
message: "Please use matrix-js-sdk/src/matrix instead",
|
||||
},
|
||||
{
|
||||
name: "matrix-js-sdk/src/index",
|
||||
message: "Please use matrix-js-sdk/src/matrix instead",
|
||||
},
|
||||
],
|
||||
patterns: [
|
||||
{
|
||||
group: ["matrix-js-sdk/lib", "matrix-js-sdk/lib/", "matrix-js-sdk/lib/**"],
|
||||
message: "Please use matrix-js-sdk/src/* instead",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
65
.eslintrc.js
65
.eslintrc.js
@@ -42,6 +42,10 @@ module.exports = {
|
||||
name: "setImmediate",
|
||||
message: "Use setTimeout instead.",
|
||||
},
|
||||
{
|
||||
name: "Buffer",
|
||||
message: "Buffer is not available in the web.",
|
||||
},
|
||||
],
|
||||
|
||||
"import/no-duplicates": ["error"],
|
||||
@@ -117,10 +121,6 @@ module.exports = {
|
||||
"!matrix-js-sdk/src/extensible_events_v1/PollResponseEvent",
|
||||
"!matrix-js-sdk/src/extensible_events_v1/PollEndEvent",
|
||||
"!matrix-js-sdk/src/extensible_events_v1/InvalidEventError",
|
||||
"!matrix-js-sdk/src/crypto",
|
||||
"!matrix-js-sdk/src/crypto/keybackup",
|
||||
"!matrix-js-sdk/src/crypto/deviceinfo",
|
||||
"!matrix-js-sdk/src/crypto/dehydration",
|
||||
"!matrix-js-sdk/src/oidc",
|
||||
"!matrix-js-sdk/src/oidc/discovery",
|
||||
"!matrix-js-sdk/src/oidc/authorize",
|
||||
@@ -259,6 +259,9 @@ module.exports = {
|
||||
additionalTestBlockFunctions: ["beforeAll", "beforeEach", "oldBackendOnly"],
|
||||
},
|
||||
],
|
||||
|
||||
// These are fine in tests
|
||||
"no-restricted-globals": "off",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -270,6 +273,60 @@ module.exports = {
|
||||
"react-hooks/rules-of-hooks": ["off"],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["module_system/**/*.{ts,tsx}"],
|
||||
parserOptions: {
|
||||
project: ["./tsconfig.module_system.json"],
|
||||
},
|
||||
extends: ["plugin:matrix-org/typescript", "plugin:matrix-org/react"],
|
||||
// NOTE: These rules are frozen and new rules should not be added here.
|
||||
// New changes belong in https://github.com/matrix-org/eslint-plugin-matrix-org/
|
||||
rules: {
|
||||
// Things we do that break the ideal style
|
||||
"prefer-promise-reject-errors": "off",
|
||||
"quotes": "off",
|
||||
|
||||
// We disable this while we're transitioning
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
// We're okay with assertion errors when we ask for them
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
|
||||
// Ban matrix-js-sdk/src imports in favour of matrix-js-sdk/src/matrix imports to prevent unleashing hell.
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
paths: [
|
||||
{
|
||||
name: "matrix-js-sdk",
|
||||
message: "Please use matrix-js-sdk/src/matrix instead",
|
||||
},
|
||||
{
|
||||
name: "matrix-js-sdk/",
|
||||
message: "Please use matrix-js-sdk/src/matrix instead",
|
||||
},
|
||||
{
|
||||
name: "matrix-js-sdk/src",
|
||||
message: "Please use matrix-js-sdk/src/matrix instead",
|
||||
},
|
||||
{
|
||||
name: "matrix-js-sdk/src/",
|
||||
message: "Please use matrix-js-sdk/src/matrix instead",
|
||||
},
|
||||
{
|
||||
name: "matrix-js-sdk/src/index",
|
||||
message: "Please use matrix-js-sdk/src/matrix instead",
|
||||
},
|
||||
],
|
||||
patterns: [
|
||||
{
|
||||
group: ["matrix-js-sdk/lib", "matrix-js-sdk/lib/", "matrix-js-sdk/lib/**"],
|
||||
message: "Please use matrix-js-sdk/src/* instead",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
settings: {
|
||||
react: {
|
||||
|
||||
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@@ -13,6 +13,7 @@
|
||||
|
||||
# Ignore translations as those will be updated by GHA for Localazy download
|
||||
/src/i18n/strings
|
||||
/src/i18n/strings/en_EN.json @element-hq/element-web-reviewers
|
||||
# Ignore the synapse plugin as this is updated by GHA for docker image updating
|
||||
/playwright/plugins/homeserver/synapse/index.ts
|
||||
|
||||
|
||||
38
.github/actions/download-verify-element-tarball/action.yml
vendored
Normal file
38
.github/actions/download-verify-element-tarball/action.yml
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
name: Upload release assets
|
||||
description: Uploads assets to an existing release and optionally signs them
|
||||
inputs:
|
||||
tag:
|
||||
description: GitHub release tag to fetch assets from.
|
||||
required: true
|
||||
out-file-path:
|
||||
description: Path to where the webapp should be extracted to.
|
||||
required: true
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Download release tarball
|
||||
uses: robinraju/release-downloader@a96f54c1b5f5e09e47d9504526e96febd949d4c2 # v1
|
||||
with:
|
||||
tag: ${{ inputs.tag }}
|
||||
fileName: element-*.tar.gz*
|
||||
out-file-path: ${{ runner.temp }}/download-verify-element-tarball
|
||||
|
||||
- name: Verify tarball
|
||||
shell: bash
|
||||
run: gpg --verify element-*.tar.gz.asc element-*.tar.gz
|
||||
working-directory: ${{ runner.temp }}/download-verify-element-tarball
|
||||
|
||||
- name: Extract tarball
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir webapp
|
||||
tar xvzf element-*.tar.gz -C webapp --strip-components=1
|
||||
working-directory: ${{ runner.temp }}/download-verify-element-tarball
|
||||
|
||||
- name: Move webapp to out-file-path
|
||||
shell: bash
|
||||
run: mv ${{ runner.temp }}/download-verify-element-tarball/webapp ${{ inputs.out-file-path }}
|
||||
|
||||
- name: Clean up temp directory
|
||||
shell: bash
|
||||
run: rm -R ${{ runner.temp }}/download-verify-element-tarball
|
||||
3
.github/labels.yml
vendored
3
.github/labels.yml
vendored
@@ -232,6 +232,9 @@
|
||||
- name: "Z-Flaky-Test"
|
||||
description: "A test is raising false alarms"
|
||||
color: "ededed"
|
||||
- name: "Z-Flaky-Jest-Test"
|
||||
description: "A Jest test is raising false alarms"
|
||||
color: "ededed"
|
||||
- name: "Z-FOSDEM"
|
||||
description: "Issues in chat.fosdem.org"
|
||||
color: "ededed"
|
||||
|
||||
2
.github/workflows/backport.yml
vendored
2
.github/workflows/backport.yml
vendored
@@ -7,6 +7,8 @@ on:
|
||||
branches:
|
||||
- develop
|
||||
|
||||
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||
|
||||
jobs:
|
||||
backport:
|
||||
name: Backport
|
||||
|
||||
1
.github/workflows/build.yml
vendored
1
.github/workflows/build.yml
vendored
@@ -10,6 +10,7 @@ env:
|
||||
# These must be set for fetchdep.sh to get the right branch
|
||||
REPOSITORY: ${{ github.repository }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
permissions: {} # No permissions required
|
||||
jobs:
|
||||
build:
|
||||
name: "Build on ${{ matrix.image }}"
|
||||
|
||||
1
.github/workflows/build_debian.yaml
vendored
1
.github/workflows/build_debian.yaml
vendored
@@ -3,6 +3,7 @@ on:
|
||||
release:
|
||||
types: [published]
|
||||
concurrency: ${{ github.workflow }}
|
||||
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||
jobs:
|
||||
build:
|
||||
name: Build package
|
||||
|
||||
5
.github/workflows/build_develop.yml
vendored
5
.github/workflows/build_develop.yml
vendored
@@ -9,6 +9,7 @@ on:
|
||||
concurrency:
|
||||
group: ${{ github.repository_owner }}-${{ github.workflow }}-${{ github.ref_name }}
|
||||
cancel-in-progress: true
|
||||
permissions: {}
|
||||
jobs:
|
||||
build:
|
||||
name: "Build & Deploy develop.element.io"
|
||||
@@ -16,6 +17,10 @@ jobs:
|
||||
if: github.repository == 'element-hq/element-web'
|
||||
runs-on: ubuntu-24.04
|
||||
environment: develop
|
||||
permissions:
|
||||
checks: read
|
||||
pages: write
|
||||
deployments: write
|
||||
env:
|
||||
R2_BUCKET: "element-web-develop"
|
||||
R2_URL: ${{ vars.CF_R2_S3_API }}
|
||||
|
||||
98
.github/workflows/deploy.yml
vendored
Normal file
98
.github/workflows/deploy.yml
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
# Manual deploy workflow for deploying to app.element.io & staging.element.io
|
||||
# Runs automatically for staging.element.io when an RC or Release is published
|
||||
# Note: Does *NOT* run automatically for app.element.io so that it gets tested on staging.element.io beforehand
|
||||
name: Deploy release
|
||||
run-name: Deploy ${{ github.ref_name }} to ${{ inputs.site || 'staging.element.io' }}
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
site:
|
||||
description: Which site to deploy to
|
||||
required: true
|
||||
default: staging.element.io
|
||||
type: choice
|
||||
options:
|
||||
- staging.element.io
|
||||
- app.element.io
|
||||
skip-checks:
|
||||
description: Skip CI on the tagged commit
|
||||
required: true
|
||||
default: false
|
||||
type: boolean
|
||||
concurrency: ${{ inputs.site || 'staging.element.io' }}
|
||||
permissions: {}
|
||||
jobs:
|
||||
deploy:
|
||||
name: "Deploy to Cloudflare Pages"
|
||||
runs-on: ubuntu-24.04
|
||||
environment: ${{ inputs.site || 'staging.element.io' }}
|
||||
permissions:
|
||||
checks: read
|
||||
deployments: write
|
||||
env:
|
||||
SITE: ${{ inputs.site || 'staging.element.io' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Load GPG key
|
||||
run: |
|
||||
curl https://packages.element.io/element-release-key.gpg | gpg --import
|
||||
gpg -k "$GPG_FINGERPRINT"
|
||||
env:
|
||||
GPG_FINGERPRINT: ${{ vars.GPG_FINGERPRINT }}
|
||||
|
||||
- name: Check current version on deployment
|
||||
id: current_version
|
||||
run: |
|
||||
version=$(curl -s https://$SITE/version)
|
||||
echo "version=${version#v}" >> $GITHUB_OUTPUT
|
||||
|
||||
# The current version bundle melding dance is skipped if the version we're deploying is the same
|
||||
# as then we're just doing a re-deploy of the same version with potentially different configs.
|
||||
- name: Download current version for its old bundles
|
||||
id: current_download
|
||||
if: steps.current_version.outputs.version != github.ref_name
|
||||
uses: ./.github/actions/download-verify-element-tarball
|
||||
with:
|
||||
tag: v${{ steps.current_version.outputs.version }}
|
||||
out-file-path: _current_version
|
||||
|
||||
- name: Download target version
|
||||
uses: ./.github/actions/download-verify-element-tarball
|
||||
with:
|
||||
tag: ${{ github.ref_name }}
|
||||
out-file-path: _deploy
|
||||
|
||||
- name: Merge current bundles into target
|
||||
if: steps.current_download.outcome == 'success'
|
||||
run: cp -vnpr _current_version/bundles/* _deploy/bundles/
|
||||
|
||||
- name: Copy config
|
||||
run: cp element.io/app/config.json _deploy/config.json
|
||||
|
||||
- name: Populate 404.html
|
||||
run: echo "404 Not Found" > _deploy/404.html
|
||||
|
||||
- name: Populate _headers
|
||||
run: cp .github/cfp_headers _deploy/_headers
|
||||
|
||||
- name: Wait for other steps to succeed
|
||||
uses: t3chguy/wait-on-check-action@18541021811b56544d90e0f073401c2b99e249d6 # fork
|
||||
if: inputs.skip-checks != true
|
||||
with:
|
||||
ref: ${{ github.sha }}
|
||||
running-workflow-name: "Deploy to Cloudflare Pages"
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
wait-interval: 10
|
||||
check-regexp: ^((?!SonarCloud|SonarQube|issue|board|label|Release|prepare|GitHub Pages).)*$
|
||||
|
||||
- name: Deploy to Cloudflare Pages
|
||||
uses: cloudflare/pages-action@f0a1cd58cd66095dee69bfa18fa5efd1dde93bca # v1
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_PAGES_TOKEN }}
|
||||
accountId: ${{ secrets.CF_PAGES_ACCOUNT_ID }}
|
||||
projectName: ${{ env.SITE == 'staging.element.io' && 'element-web-staging' || 'element-web' }}
|
||||
directory: _deploy
|
||||
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
14
.github/workflows/dockerhub.yaml
vendored
14
.github/workflows/dockerhub.yaml
vendored
@@ -7,27 +7,27 @@ on:
|
||||
# This job can take a while, and we have usage limits, so just publish develop only twice a day
|
||||
- cron: "0 7/12 * * *"
|
||||
concurrency: ${{ github.workflow }}-${{ github.ref_name }}
|
||||
|
||||
permissions:
|
||||
id-token: write # needed for signing the images with GitHub OIDC Token
|
||||
permissions: {}
|
||||
jobs:
|
||||
buildx:
|
||||
name: Docker Buildx
|
||||
runs-on: ubuntu-24.04
|
||||
environment: dockerhub
|
||||
permissions:
|
||||
id-token: write # needed for signing the images with GitHub OIDC Token
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # needed for docker-package to be able to calculate the version
|
||||
|
||||
- name: Install Cosign
|
||||
uses: sigstore/cosign-installer@4959ce089c160fddf62f7b42464195ba1a56d382 # v3
|
||||
uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db # v3
|
||||
uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3
|
||||
with:
|
||||
install: true
|
||||
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5
|
||||
uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 # v5
|
||||
with:
|
||||
images: |
|
||||
vectorim/element-web
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
|
||||
- name: Build and push
|
||||
id: build-and-push
|
||||
uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # v6
|
||||
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
|
||||
8
.github/workflows/docs.yml
vendored
8
.github/workflows/docs.yml
vendored
@@ -5,10 +5,7 @@ on:
|
||||
branches: [develop]
|
||||
workflow_dispatch: {}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
permissions: {}
|
||||
|
||||
concurrency:
|
||||
group: "pages"
|
||||
@@ -100,6 +97,9 @@ jobs:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
needs: build
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
|
||||
@@ -11,20 +11,23 @@ concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch || github.run_id }}
|
||||
cancel-in-progress: ${{ github.event.workflow_run.event == 'pull_request' }}
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
report:
|
||||
if: github.event.workflow_run.conclusion != 'cancelled'
|
||||
name: Report results
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
environment: Netlify
|
||||
permissions:
|
||||
statuses: write
|
||||
deployments: write
|
||||
actions: read
|
||||
steps:
|
||||
- name: Download HTML report
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
name: html-report
|
||||
path: playwright-report
|
||||
|
||||
58
.github/workflows/end-to-end-tests.yaml
vendored
58
.github/workflows/end-to-end-tests.yaml
vendored
@@ -3,6 +3,9 @@
|
||||
# as an artifact and run end-to-end tests.
|
||||
name: End to End Tests
|
||||
on:
|
||||
# CRON to run all Projects at 6am UTC
|
||||
schedule:
|
||||
- cron: "0 6 * * *"
|
||||
pull_request: {}
|
||||
merge_group:
|
||||
types: [checks_requested]
|
||||
@@ -32,12 +35,19 @@ concurrency:
|
||||
env:
|
||||
# fetchdep.sh needs to know our PR number
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
# Use 6 runners in the default case, but 4 when running on a schedule where we run all 5 projects (20 runners total)
|
||||
NUM_RUNNERS: ${{ github.event_name == 'schedule' && 4 || 6 }}
|
||||
|
||||
permissions: {} # No permissions required
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: "Build Element-Web"
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
if: inputs.skip != true
|
||||
outputs:
|
||||
num-runners: ${{ env.NUM_RUNNERS }}
|
||||
runners-matrix: ${{ steps.runner-vars.outputs.matrix }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
@@ -69,7 +79,6 @@ jobs:
|
||||
VERSION: "${{ steps.layered_build.outputs.VERSION }}"
|
||||
run: |
|
||||
yarn build
|
||||
echo $VERSION > webapp/version
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -78,11 +87,20 @@ jobs:
|
||||
path: webapp
|
||||
retention-days: 1
|
||||
|
||||
- name: Calculate runner variables
|
||||
id: runner-vars
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const numRunners = parseInt(process.env.NUM_RUNNERS, 10);
|
||||
const matrix = Array.from({ length: numRunners }, (_, i) => i + 1);
|
||||
core.setOutput("matrix", JSON.stringify(matrix));
|
||||
|
||||
playwright:
|
||||
name: "Run Tests ${{ matrix.runner }}/${{ strategy.job-total }}"
|
||||
name: "Run Tests [${{ matrix.project }}] ${{ matrix.runner }}/${{ needs.build.outputs.num-runners }}"
|
||||
needs: build
|
||||
if: inputs.skip != true
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
actions: read
|
||||
issues: read
|
||||
@@ -91,7 +109,19 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# Run multiple instances in parallel to speed up the tests
|
||||
runner: [1, 2, 3, 4, 5, 6]
|
||||
runner: ${{ fromJSON(needs.build.outputs.runners-matrix) }}
|
||||
project:
|
||||
- Chrome
|
||||
- Firefox
|
||||
- WebKit
|
||||
isCron:
|
||||
- ${{ github.event_name == 'schedule' }}
|
||||
# Skip the Firefox & Safari runs unless this was a cron trigger
|
||||
exclude:
|
||||
- isCron: false
|
||||
project: Firefox
|
||||
- isCron: false
|
||||
project: WebKit
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
@@ -127,16 +157,26 @@ jobs:
|
||||
|
||||
- name: Install Playwright browsers
|
||||
if: steps.playwright-cache.outputs.cache-hit != 'true'
|
||||
run: yarn playwright install --with-deps
|
||||
run: yarn playwright install --with-deps --no-shell
|
||||
|
||||
- name: Install system dependencies for WebKit
|
||||
# Some WebKit dependencies seem to lay outside the cache and will need to be installed separately
|
||||
if: matrix.project == 'WebKit' && steps.playwright-cache.outputs.cache-hit == 'true'
|
||||
run: yarn playwright install-deps webkit
|
||||
|
||||
# We skip tests tagged with @mergequeue when running on PRs, but run them in MQ and everywhere else
|
||||
- name: Run Playwright tests
|
||||
run: yarn playwright test --shard ${{ matrix.runner }}/${{ strategy.job-total }}
|
||||
run: |
|
||||
yarn playwright test \
|
||||
--shard "${{ matrix.runner }}/${{ needs.build.outputs.num-runners }}" \
|
||||
--project="${{ matrix.project }}" \
|
||||
${{ github.event_name == 'pull_request' && '--grep-invert @mergequeue' || '' }}
|
||||
|
||||
- name: Upload blob report to GitHub Actions Artifacts
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: all-blob-reports-${{ matrix.runner }}
|
||||
name: all-blob-reports-${{ matrix.project }}-${{ matrix.runner }}
|
||||
path: blob-report
|
||||
retention-days: 1
|
||||
|
||||
@@ -144,7 +184,7 @@ jobs:
|
||||
name: end-to-end-tests
|
||||
needs: playwright
|
||||
if: always()
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
if: inputs.skip != true
|
||||
|
||||
1
.github/workflows/issue_closed.yml
vendored
1
.github/workflows/issue_closed.yml
vendored
@@ -4,6 +4,7 @@
|
||||
on:
|
||||
issues:
|
||||
types: [closed]
|
||||
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||
jobs:
|
||||
tidy:
|
||||
name: Tidy closed issues
|
||||
|
||||
2
.github/workflows/localazy_download.yaml
vendored
2
.github/workflows/localazy_download.yaml
vendored
@@ -3,6 +3,8 @@ on:
|
||||
workflow_dispatch: {}
|
||||
schedule:
|
||||
- cron: "0 6 * * 1,3,5" # Every Monday, Wednesday and Friday at 6am UTC
|
||||
permissions:
|
||||
pull-requests: write # needed to auto-approve PRs
|
||||
jobs:
|
||||
download:
|
||||
uses: matrix-org/matrix-web-i18n/.github/workflows/localazy_download.yaml@main
|
||||
|
||||
1
.github/workflows/localazy_upload.yaml
vendored
1
.github/workflows/localazy_upload.yaml
vendored
@@ -4,6 +4,7 @@ on:
|
||||
branches: [develop]
|
||||
paths:
|
||||
- "src/i18n/strings/en_EN.json"
|
||||
permissions: {} # No permissions needed
|
||||
jobs:
|
||||
upload:
|
||||
uses: matrix-org/matrix-web-i18n/.github/workflows/localazy_upload.yaml@main
|
||||
|
||||
7
.github/workflows/netlify.yaml
vendored
7
.github/workflows/netlify.yaml
vendored
@@ -9,8 +9,11 @@ on:
|
||||
jobs:
|
||||
deploy:
|
||||
if: github.event.workflow_run.conclusion != 'cancelled' && github.event.workflow_run.event == 'pull_request'
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
environment: Netlify
|
||||
permissions:
|
||||
actions: read
|
||||
deployments: write
|
||||
steps:
|
||||
- name: 📝 Create Deployment
|
||||
uses: bobheadxi/deployments@648679e8e4915b27893bd7dbc35cb504dc915bc8 # v1
|
||||
@@ -27,7 +30,7 @@ jobs:
|
||||
- name: 📥 Download artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
name: webapp
|
||||
path: webapp
|
||||
|
||||
1
.github/workflows/pending-reviews.yaml
vendored
1
.github/workflows/pending-reviews.yaml
vendored
@@ -6,6 +6,7 @@ on:
|
||||
#schedule:
|
||||
# - cron: "*/10 * * * *"
|
||||
concurrency: ${{ github.workflow }}
|
||||
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||
jobs:
|
||||
bot:
|
||||
name: Pending reviews bot
|
||||
|
||||
@@ -3,9 +3,12 @@ on:
|
||||
workflow_dispatch: {}
|
||||
schedule:
|
||||
- cron: "0 6 * * *" # Every day at 6am UTC
|
||||
permissions: {}
|
||||
jobs:
|
||||
update:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
|
||||
3
.github/workflows/pull_request.yaml
vendored
3
.github/workflows/pull_request.yaml
vendored
@@ -4,8 +4,11 @@ on:
|
||||
types: [opened, edited, labeled, unlabeled, synchronize]
|
||||
merge_group:
|
||||
types: [checks_requested]
|
||||
permissions: {}
|
||||
jobs:
|
||||
action:
|
||||
uses: matrix-org/matrix-js-sdk/.github/workflows/pull_request.yaml@develop
|
||||
permissions:
|
||||
pull-requests: write
|
||||
secrets:
|
||||
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
@@ -2,10 +2,11 @@ name: Pull Request Base Branch
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, synchronize]
|
||||
permissions: {} # No permissions required
|
||||
jobs:
|
||||
check_base_branch:
|
||||
name: Check PR base branch
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/github-script@v7
|
||||
with:
|
||||
|
||||
3
.github/workflows/release-drafter.yml
vendored
3
.github/workflows/release-drafter.yml
vendored
@@ -4,6 +4,9 @@ on:
|
||||
branches: [staging]
|
||||
workflow_dispatch: {}
|
||||
concurrency: ${{ github.workflow }}
|
||||
permissions: {}
|
||||
jobs:
|
||||
draft:
|
||||
permissions:
|
||||
contents: write
|
||||
uses: matrix-org/matrix-js-sdk/.github/workflows/release-drafter-workflow.yml@develop
|
||||
|
||||
1
.github/workflows/release-gitflow.yml
vendored
1
.github/workflows/release-gitflow.yml
vendored
@@ -4,6 +4,7 @@ on:
|
||||
push:
|
||||
branches: [master]
|
||||
concurrency: ${{ github.repository }}-${{ github.workflow }}
|
||||
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||
jobs:
|
||||
merge:
|
||||
uses: matrix-org/matrix-js-sdk/.github/workflows/release-gitflow.yml@develop
|
||||
|
||||
9
.github/workflows/release.yml
vendored
9
.github/workflows/release.yml
vendored
@@ -11,9 +11,14 @@ on:
|
||||
- rc
|
||||
- final
|
||||
concurrency: ${{ github.workflow }}
|
||||
permissions: {}
|
||||
jobs:
|
||||
release:
|
||||
uses: matrix-org/matrix-js-sdk/.github/workflows/release-make.yml@develop
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
pull-requests: read
|
||||
secrets:
|
||||
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||
@@ -42,6 +47,8 @@ jobs:
|
||||
name: Post release checks
|
||||
needs: release
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
checks: read
|
||||
steps:
|
||||
- name: Wait for dockerhub
|
||||
uses: t3chguy/wait-on-check-action@18541021811b56544d90e0f073401c2b99e249d6 # fork
|
||||
@@ -49,7 +56,7 @@ jobs:
|
||||
ref: master
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
wait-interval: 10
|
||||
check-name: "Docker Buildx (vanilla)"
|
||||
check-name: "Docker Buildx"
|
||||
allowed-conclusions: success
|
||||
|
||||
- name: Wait for debian package
|
||||
|
||||
16
.github/workflows/release_prepare.yml
vendored
16
.github/workflows/release_prepare.yml
vendored
@@ -17,9 +17,25 @@ on:
|
||||
required: true
|
||||
type: boolean
|
||||
default: true
|
||||
permissions: {} # Uses ELEMENT_BOT_TOKEN instead
|
||||
jobs:
|
||||
checks:
|
||||
name: Sanity checks
|
||||
strategy:
|
||||
matrix:
|
||||
repo:
|
||||
- matrix-org/matrix-js-sdk
|
||||
- element-hq/element-web
|
||||
- element-hq/element-desktop
|
||||
uses: matrix-org/matrix-js-sdk/.github/workflows/release-checks.yml@develop
|
||||
secrets:
|
||||
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
with:
|
||||
repository: ${{ matrix.repo }}
|
||||
|
||||
prepare:
|
||||
runs-on: ubuntu-24.04
|
||||
needs: checks
|
||||
env:
|
||||
# The order is specified bottom-up to avoid any races for allchange
|
||||
REPOS: matrix-js-sdk element-web element-desktop
|
||||
|
||||
5
.github/workflows/sonarqube.yml
vendored
5
.github/workflows/sonarqube.yml
vendored
@@ -7,11 +7,16 @@ on:
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch }}
|
||||
cancel-in-progress: true
|
||||
permissions: {}
|
||||
jobs:
|
||||
sonarqube:
|
||||
name: 🩻 SonarQube
|
||||
if: github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event != 'merge_group'
|
||||
uses: matrix-org/matrix-js-sdk/.github/workflows/sonarcloud.yml@develop
|
||||
permissions:
|
||||
actions: read
|
||||
statuses: write
|
||||
id-token: write # sonar
|
||||
secrets:
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
33
.github/workflows/static_analysis.yaml
vendored
33
.github/workflows/static_analysis.yaml
vendored
@@ -16,6 +16,8 @@ env:
|
||||
REPOSITORY: ${{ github.repository }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
|
||||
permissions: {} # No permissions required
|
||||
|
||||
jobs:
|
||||
ts_lint:
|
||||
name: "Typescript Syntax Check"
|
||||
@@ -34,30 +36,11 @@ jobs:
|
||||
- name: Typecheck
|
||||
run: "yarn run lint:types"
|
||||
|
||||
- name: Switch js-sdk to release mode
|
||||
working-directory: node_modules/matrix-js-sdk
|
||||
run: |
|
||||
scripts/switch_package_to_release.cjs
|
||||
yarn install
|
||||
yarn run build:compile
|
||||
yarn run build:types
|
||||
|
||||
- name: Typecheck (release mode)
|
||||
run: "yarn run lint:types"
|
||||
|
||||
# Temporary while we directly import matrix-js-sdk/src/* which means we need
|
||||
# certain @types/* packages to make sense of matrix-js-sdk types.
|
||||
#- name: Typecheck (release mode; no yarn link)
|
||||
# if: github.event_name != 'pull_request' && github.ref_name != 'master'
|
||||
# run: |
|
||||
# yarn unlink matrix-js-sdk
|
||||
# yarn add github:matrix-org/matrix-js-sdk#develop
|
||||
# yarn install --force
|
||||
# yarn run lint:types
|
||||
|
||||
i18n_lint:
|
||||
name: "i18n Check"
|
||||
uses: matrix-org/matrix-web-i18n/.github/workflows/i18n_check.yml@main
|
||||
permissions:
|
||||
pull-requests: read
|
||||
with:
|
||||
hardcoded-words: "Element"
|
||||
allowed-hardcoded-keys: |
|
||||
@@ -71,7 +54,7 @@ jobs:
|
||||
|
||||
rethemendex_lint:
|
||||
name: "Rethemendex Check"
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@@ -144,6 +127,12 @@ jobs:
|
||||
cache: "yarn"
|
||||
node-version: "lts/*"
|
||||
|
||||
- name: Install Deps
|
||||
run: "yarn install --frozen-lockfile"
|
||||
|
||||
- name: Run linter
|
||||
run: "yarn run lint:knip"
|
||||
|
||||
- name: Install Deps
|
||||
run: "scripts/layered.sh"
|
||||
|
||||
|
||||
3
.github/workflows/sync-labels.yml
vendored
3
.github/workflows/sync-labels.yml
vendored
@@ -8,6 +8,9 @@ on:
|
||||
- develop
|
||||
paths:
|
||||
- .github/labels.yml
|
||||
|
||||
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||
|
||||
jobs:
|
||||
sync-labels:
|
||||
uses: element-hq/element-meta/.github/workflows/sync-labels.yml@develop
|
||||
|
||||
10
.github/workflows/tests.yml
vendored
10
.github/workflows/tests.yml
vendored
@@ -26,10 +26,12 @@ env:
|
||||
# fetchdep.sh needs to know our PR number
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
jest:
|
||||
name: Jest
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -93,14 +95,16 @@ jobs:
|
||||
name: jest-tests
|
||||
needs: jest
|
||||
if: always()
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
statuses: write
|
||||
steps:
|
||||
- if: needs.jest.result != 'skipped' && needs.jest.result != 'success'
|
||||
run: exit 1
|
||||
|
||||
- name: Skip SonarCloud in merge queue
|
||||
if: github.event_name == 'merge_group' || inputs.disable_coverage == 'true'
|
||||
uses: Sibz/github-status-action@faaa4d96fecf273bd762985e0e7f9f933c774918 # v1
|
||||
uses: guibranco/github-status-action-v2@d469d49426f5a7b8a1fbcac20ad274d3e4892321
|
||||
with:
|
||||
authToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
state: success
|
||||
|
||||
2
.github/workflows/triage-assigned.yml
vendored
2
.github/workflows/triage-assigned.yml
vendored
@@ -4,6 +4,8 @@ on:
|
||||
issues:
|
||||
types: [assigned]
|
||||
|
||||
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||
|
||||
jobs:
|
||||
web-app-team:
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
2
.github/workflows/triage-incoming.yml
vendored
2
.github/workflows/triage-incoming.yml
vendored
@@ -4,6 +4,8 @@ on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||
|
||||
jobs:
|
||||
automate-project-columns:
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
2
.github/workflows/triage-labelled.yml
vendored
2
.github/workflows/triage-labelled.yml
vendored
@@ -8,6 +8,8 @@ on:
|
||||
ELEMENT_BOT_TOKEN:
|
||||
required: true
|
||||
|
||||
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||
|
||||
jobs:
|
||||
apply_Z-Labs_label:
|
||||
name: Add Z-Labs label for features behind labs flags
|
||||
|
||||
@@ -3,6 +3,7 @@ on:
|
||||
pull_request_target:
|
||||
types: [review_requested]
|
||||
|
||||
permissions: {} # Uses ELEMENT_BOT_TOKEN instead
|
||||
jobs:
|
||||
add_design_pr_to_project:
|
||||
name: Move PRs asking for design review to the design board
|
||||
|
||||
@@ -2,6 +2,7 @@ name: Close stale flaky issues
|
||||
on:
|
||||
schedule:
|
||||
- cron: "30 1 * * *"
|
||||
permissions: {}
|
||||
jobs:
|
||||
close:
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
4
.github/workflows/triage-unlabelled.yml
vendored
4
.github/workflows/triage-unlabelled.yml
vendored
@@ -3,11 +3,13 @@ name: Move unlabelled from needs info columns to triaged
|
||||
on:
|
||||
issues:
|
||||
types: [unlabeled]
|
||||
|
||||
permissions: {}
|
||||
jobs:
|
||||
Move_Unabeled_Issue_On_Project_Board:
|
||||
name: Move no longer X-Needs-Info issues to Triaged
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
repository-projects: read
|
||||
if: >
|
||||
${{
|
||||
!contains(github.event.issue.labels.*.name, 'X-Needs-Info') }}
|
||||
|
||||
1
.github/workflows/update-jitsi.yml
vendored
1
.github/workflows/update-jitsi.yml
vendored
@@ -4,6 +4,7 @@ on:
|
||||
workflow_dispatch: {}
|
||||
schedule:
|
||||
- cron: "0 3 * * 0" # 3am every Sunday
|
||||
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||
jobs:
|
||||
update:
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
1
.github/workflows/update-topics.yaml
vendored
1
.github/workflows/update-topics.yaml
vendored
@@ -15,6 +15,7 @@ on:
|
||||
required: true
|
||||
type: string
|
||||
concurrency: ${{ github.workflow }}
|
||||
permissions: {} # No permissions required
|
||||
jobs:
|
||||
bot:
|
||||
name: Release topic update
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
"*": "prettier --write",
|
||||
"src/**/*.(ts|tsx)": ["eslint --fix"],
|
||||
"scripts/**/*.(ts|tsx)": ["eslint --fix"],
|
||||
"module_system/**/*.(ts|tsx)": ["eslint --fix --config .eslintrc-module_system.js module_system"],
|
||||
"module_system/**/*.(ts|tsx)": ["eslint --fix"],
|
||||
"*.pcss": ["stylelint --fix"]
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module.exports = {
|
||||
extends: ["stylelint-config-standard"],
|
||||
customSyntax: require("postcss-scss"),
|
||||
plugins: ["stylelint-scss"],
|
||||
customSyntax: "postcss-scss",
|
||||
plugins: ["stylelint-scss", "stylelint-value-no-unknown-custom-properties"],
|
||||
rules: {
|
||||
"comment-empty-line-before": null,
|
||||
"declaration-empty-line-before": null,
|
||||
@@ -46,5 +46,33 @@ module.exports = {
|
||||
"number-max-precision": null,
|
||||
"no-invalid-double-slash-comments": true,
|
||||
"media-feature-range-notation": null,
|
||||
"csstools/value-no-unknown-custom-properties": [
|
||||
true,
|
||||
{
|
||||
importFrom: [
|
||||
{ from: "res/css/_common.pcss", type: "css" },
|
||||
{ from: "res/themes/light/css/_light.pcss", type: "css" },
|
||||
// Right now our styles share vars all over the place, this is not ideal but acceptable for now
|
||||
{ from: "res/css/views/rooms/_EventTile.pcss", type: "css" },
|
||||
{ from: "res/css/views/rooms/_IRCLayout.pcss", type: "css" },
|
||||
{ from: "res/css/views/rooms/_EventBubbleTile.pcss", type: "css" },
|
||||
{ from: "res/css/views/rooms/_ReadReceiptGroup.pcss", type: "css" },
|
||||
{ from: "res/css/views/rooms/_EditMessageComposer.pcss", type: "css" },
|
||||
{ from: "res/css/views/right_panel/_BaseCard.pcss", type: "css" },
|
||||
{ from: "res/css/views/messages/_MessageTimestamp.pcss", type: "css" },
|
||||
{ from: "res/css/views/messages/_EventTileBubble.pcss", type: "css" },
|
||||
{ from: "res/css/views/messages/_MessageActionBar.pcss", type: "css" },
|
||||
{ from: "res/css/views/voip/LegacyCallView/_LegacyCallViewButtons.pcss", type: "css" },
|
||||
{ from: "res/css/views/elements/_ToggleSwitch.pcss", type: "css" },
|
||||
{ from: "res/css/views/settings/tabs/_SettingsTab.pcss", type: "css" },
|
||||
{ from: "res/css/structures/_RoomView.pcss", type: "css" },
|
||||
// Compound vars
|
||||
"node_modules/@vector-im/compound-design-tokens/assets/web/css/cpd-common-base.css",
|
||||
"node_modules/@vector-im/compound-design-tokens/assets/web/css/cpd-common-semantic.css",
|
||||
"node_modules/@vector-im/compound-design-tokens/assets/web/css/cpd-theme-light-base-mq.css",
|
||||
"node_modules/@vector-im/compound-design-tokens/assets/web/css/cpd-theme-light-semantic-mq.css",
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
158
CHANGELOG.md
158
CHANGELOG.md
@@ -1,3 +1,161 @@
|
||||
Changes in [1.11.89](https://github.com/element-hq/element-web/releases/tag/v1.11.89) (2024-12-18)
|
||||
==================================================================================================
|
||||
This is a patch release to fix a bug which could prevent loading stored crypto state from storage, and also to fix URL previews when switching back to a room.
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
|
||||
* Upgrade matrix-sdk-crypto-wasm to 1.11.0 (https://github.com/matrix-org/matrix-js-sdk/pull/4593)
|
||||
* Fix url preview display ([#28766](https://github.com/element-hq/element-web/pull/28766)).
|
||||
|
||||
|
||||
Changes in [1.11.88](https://github.com/element-hq/element-web/releases/tag/v1.11.88) (2024-12-17)
|
||||
==================================================================================================
|
||||
## ✨ Features
|
||||
|
||||
* Allow trusted Element Call widget to send and receive media encryption key to-device messages ([#28316](https://github.com/element-hq/element-web/pull/28316)). Contributed by @hughns.
|
||||
* increase ringing timeout from 10 seconds to 90 seconds ([#28630](https://github.com/element-hq/element-web/pull/28630)). Contributed by @fkwp.
|
||||
* Add `Close` tooltip to dialog ([#28617](https://github.com/element-hq/element-web/pull/28617)). Contributed by @florianduros.
|
||||
* New UX for Share dialog ([#28598](https://github.com/element-hq/element-web/pull/28598)). Contributed by @florianduros.
|
||||
* Improve performance of RoomContext in RoomHeader ([#28574](https://github.com/element-hq/element-web/pull/28574)). Contributed by @t3chguy.
|
||||
* Remove `Features.RustCrypto` flag ([#28582](https://github.com/element-hq/element-web/pull/28582)). Contributed by @florianduros.
|
||||
* Add Modernizr warning when running in non-secure context ([#28581](https://github.com/element-hq/element-web/pull/28581)). Contributed by @t3chguy.
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
|
||||
* Fix jumpy timeline when the pinned message banner is displayed ([#28654](https://github.com/element-hq/element-web/pull/28654)). Contributed by @florianduros.
|
||||
* Fix font \& spaces in settings subsection ([#28631](https://github.com/element-hq/element-web/pull/28631)). Contributed by @florianduros.
|
||||
* Remove manual device verification which is not supported by the new cryptography stack ([#28588](https://github.com/element-hq/element-web/pull/28588)). Contributed by @florianduros.
|
||||
* Fix code block highlighting not working reliably with many code blocks ([#28613](https://github.com/element-hq/element-web/pull/28613)). Contributed by @t3chguy.
|
||||
* Remove remaining reply fallbacks code ([#28610](https://github.com/element-hq/element-web/pull/28610)). Contributed by @t3chguy.
|
||||
* Provide a way to activate GIFs via the keyboard for a11y ([#28611](https://github.com/element-hq/element-web/pull/28611)). Contributed by @t3chguy.
|
||||
* Fix format bar position ([#28591](https://github.com/element-hq/element-web/pull/28591)). Contributed by @florianduros.
|
||||
* Fix room taking long time to load ([#28579](https://github.com/element-hq/element-web/pull/28579)). Contributed by @florianduros.
|
||||
* Show the correct shield status in tooltip for more conditions ([#28476](https://github.com/element-hq/element-web/pull/28476)). Contributed by @uhoreg.
|
||||
|
||||
|
||||
Changes in [1.11.87](https://github.com/element-hq/element-web/releases/tag/v1.11.87) (2024-12-03)
|
||||
==================================================================================================
|
||||
## ✨ Features
|
||||
|
||||
* Send and respect MSC4230 is\_animated flag ([#28513](https://github.com/element-hq/element-web/pull/28513)). Contributed by @t3chguy.
|
||||
* Display a warning when an unverified user's identity changes ([#28211](https://github.com/element-hq/element-web/pull/28211)). Contributed by @uhoreg.
|
||||
* Swap out Twitter link for Mastodon on auth footer ([#28508](https://github.com/element-hq/element-web/pull/28508)). Contributed by @t3chguy.
|
||||
* Consider `org.matrix.msc3417.call` as video room in create room dialog ([#28497](https://github.com/element-hq/element-web/pull/28497)). Contributed by @t3chguy.
|
||||
* Standardise icons using Compound Design Tokens ([#28217](https://github.com/element-hq/element-web/pull/28217)). Contributed by @t3chguy.
|
||||
* Start sending stable `m.marked_unread` events ([#28478](https://github.com/element-hq/element-web/pull/28478)). Contributed by @tulir.
|
||||
* Upgrade to compound-design-tokens v2 ([#28471](https://github.com/element-hq/element-web/pull/28471)). Contributed by @t3chguy.
|
||||
* Standardise icons using Compound Design Tokens ([#28286](https://github.com/element-hq/element-web/pull/28286)). Contributed by @t3chguy.
|
||||
* Remove reply fallbacks as per merged MSC2781 ([#28406](https://github.com/element-hq/element-web/pull/28406)). Contributed by @t3chguy.
|
||||
* Use React Suspense when rendering async modals ([#28386](https://github.com/element-hq/element-web/pull/28386)). Contributed by @t3chguy.
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
|
||||
* Add spinner when room encryption is loading in room settings ([#28535](https://github.com/element-hq/element-web/pull/28535)). Contributed by @florianduros.
|
||||
* Fix getOidcCallbackUrl for Element Desktop ([#28521](https://github.com/element-hq/element-web/pull/28521)). Contributed by @t3chguy.
|
||||
* Filter out redacted poll votes to avoid crashing the Poll widget ([#28498](https://github.com/element-hq/element-web/pull/28498)). Contributed by @t3chguy.
|
||||
* Fix force tab complete not working since switching to React 18 createRoot API ([#28505](https://github.com/element-hq/element-web/pull/28505)). Contributed by @t3chguy.
|
||||
* Fix media captions in bubble layout ([#28480](https://github.com/element-hq/element-web/pull/28480)). Contributed by @tulir.
|
||||
* Reset cross-signing before backup when resetting both ([#28402](https://github.com/element-hq/element-web/pull/28402)). Contributed by @uhoreg.
|
||||
* Listen to events so that encryption icon updates when status changes ([#28407](https://github.com/element-hq/element-web/pull/28407)). Contributed by @uhoreg.
|
||||
* Check that the file the user chose has a MIME type of `image/*` ([#28467](https://github.com/element-hq/element-web/pull/28467)). Contributed by @t3chguy.
|
||||
* Fix download button size in message action bar ([#28472](https://github.com/element-hq/element-web/pull/28472)). Contributed by @t3chguy.
|
||||
* Allow tab completing users in brackets ([#28460](https://github.com/element-hq/element-web/pull/28460)). Contributed by @t3chguy.
|
||||
* Fix React 18 strict mode breaking spotlight dialog ([#28452](https://github.com/element-hq/element-web/pull/28452)). Contributed by @MidhunSureshR.
|
||||
|
||||
|
||||
Changes in [1.11.86](https://github.com/element-hq/element-web/releases/tag/v1.11.86) (2024-11-19)
|
||||
==================================================================================================
|
||||
## ✨ Features
|
||||
|
||||
* Deduplicate icons using Compound Design Tokens ([#28419](https://github.com/element-hq/element-web/pull/28419)). Contributed by @t3chguy.
|
||||
* Let widget driver send error details ([#28357](https://github.com/element-hq/element-web/pull/28357)). Contributed by @AndrewFerr.
|
||||
* Deduplicate icons using Compound Design Tokens ([#28381](https://github.com/element-hq/element-web/pull/28381)). Contributed by @t3chguy.
|
||||
* Auto approvoce `io.element.call.reaction` capability for element call widgets ([#28401](https://github.com/element-hq/element-web/pull/28401)). Contributed by @toger5.
|
||||
* Show message type prefix in thread root \& reply previews ([#28361](https://github.com/element-hq/element-web/pull/28361)). Contributed by @t3chguy.
|
||||
* Support sending encrypted to device messages from widgets ([#28315](https://github.com/element-hq/element-web/pull/28315)). Contributed by @hughns.
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
|
||||
* Feed events to widgets as they are decrypted (even if out of order) ([#28376](https://github.com/element-hq/element-web/pull/28376)). Contributed by @robintown.
|
||||
* Handle authenticated media when downloading from ImageView ([#28379](https://github.com/element-hq/element-web/pull/28379)). Contributed by @t3chguy.
|
||||
* Ignore `m.3pid_changes` for Identity service 3PID changes ([#28375](https://github.com/element-hq/element-web/pull/28375)). Contributed by @t3chguy.
|
||||
* Fix markdown escaping wrongly passing html through ([#28363](https://github.com/element-hq/element-web/pull/28363)). Contributed by @t3chguy.
|
||||
* Remove "Upgrade your encryption" flow in `CreateSecretStorageDialog` ([#28290](https://github.com/element-hq/element-web/pull/28290)). Contributed by @florianduros.
|
||||
|
||||
|
||||
Changes in [1.11.85](https://github.com/element-hq/element-web/releases/tag/v1.11.85) (2024-11-12)
|
||||
==================================================================================================
|
||||
# Security
|
||||
- Fixes for [CVE-2024-51750](https://www.cve.org/CVERecord?id=CVE-2024-51750) / [GHSA-w36j-v56h-q9pc](https://github.com/element-hq/element-web/security/advisories/GHSA-w36j-v56h-q9pc)
|
||||
- Fixes for [CVE-2024-51749](https://www.cve.org/CVERecord?id=CVE-2024-51749) / [GHSA-5486-384g-mcx2](https://github.com/element-hq/element-web/security/advisories/GHSA-5486-384g-mcx2)
|
||||
- Update JS SDK with the fixes for [CVE-2024-50336](https://www.cve.org/CVERecord?id=CVE-2024-50336) / [GHSA-xvg8-m4x3-w6xr](https://github.com/matrix-org/matrix-js-sdk/security/advisories/GHSA-xvg8-m4x3-w6xr)
|
||||
|
||||
|
||||
Changes in [1.11.84](https://github.com/element-hq/element-web/releases/tag/v1.11.84) (2024-11-05)
|
||||
==================================================================================================
|
||||
## ✨ Features
|
||||
|
||||
* Remove abandoned MSC3886, MSC3903, MSC3906 implementations ([#28274](https://github.com/element-hq/element-web/pull/28274)). Contributed by @t3chguy.
|
||||
* Update to React 18 ([#24763](https://github.com/element-hq/element-web/pull/24763)). Contributed by @t3chguy.
|
||||
* Deduplicate icons using Compound ([#28239](https://github.com/element-hq/element-web/pull/28239)). Contributed by @t3chguy.
|
||||
* Replace legacy Tooltips with Compound tooltips ([#28231](https://github.com/element-hq/element-web/pull/28231)). Contributed by @t3chguy.
|
||||
* Deduplicate icons using Compound Design Tokens ([#28219](https://github.com/element-hq/element-web/pull/28219)). Contributed by @t3chguy.
|
||||
* Add reactions to html export ([#28210](https://github.com/element-hq/element-web/pull/28210)). Contributed by @langleyd.
|
||||
* Remove feature\_dehydration ([#28173](https://github.com/element-hq/element-web/pull/28173)). Contributed by @florianduros.
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
|
||||
* Remove upgrade encryption in `DeviceListener` and `SetupEncryptionToast` ([#28299](https://github.com/element-hq/element-web/pull/28299)). Contributed by @florianduros.
|
||||
* Fix 'remove alias' button in room settings ([#28269](https://github.com/element-hq/element-web/pull/28269)). Contributed by @Dev-Gurjar.
|
||||
* Add back unencrypted path in `StopGapWidgetDriver.sendToDevice` ([#28295](https://github.com/element-hq/element-web/pull/28295)). Contributed by @florianduros.
|
||||
* Fix other devices not being decorated as such ([#28279](https://github.com/element-hq/element-web/pull/28279)). Contributed by @t3chguy.
|
||||
* Fix pill contrast in invitation dialog ([#28250](https://github.com/element-hq/element-web/pull/28250)). Contributed by @florianduros.
|
||||
* Close right panel chat when minimising maximised voip widget ([#28241](https://github.com/element-hq/element-web/pull/28241)). Contributed by @t3chguy.
|
||||
* Fix develop changelog parsing ([#28232](https://github.com/element-hq/element-web/pull/28232)). Contributed by @t3chguy.
|
||||
* Fix Ctrl+F shortcut not working with minimised room summary card ([#28223](https://github.com/element-hq/element-web/pull/28223)). Contributed by @t3chguy.
|
||||
* Fix network dropdown missing checkbox \& aria-checked ([#28220](https://github.com/element-hq/element-web/pull/28220)). Contributed by @t3chguy.
|
||||
|
||||
|
||||
Changes in [1.11.83](https://github.com/element-hq/element-web/releases/tag/v1.11.83) (2024-10-29)
|
||||
==================================================================================================
|
||||
## ✨ Features
|
||||
|
||||
* Enable Element Call by default on release instances ([#28314](https://github.com/element-hq/element-web/pull/28314)). Contributed by @t3chguy.
|
||||
|
||||
|
||||
|
||||
Changes in [1.11.82](https://github.com/element-hq/element-web/releases/tag/v1.11.82) (2024-10-22)
|
||||
==================================================================================================
|
||||
## ✨ Features
|
||||
|
||||
* Deduplicate more icons using Compound Design Tokens ([#132](https://github.com/element-hq/matrix-react-sdk/pull/132)). Contributed by @t3chguy.
|
||||
* Always show link new device flow even if unsupported ([#147](https://github.com/element-hq/matrix-react-sdk/pull/147)). Contributed by @t3chguy.
|
||||
* Update design of files list in right panel ([#144](https://github.com/element-hq/matrix-react-sdk/pull/144)). Contributed by @t3chguy.
|
||||
* Remove feature\_dehydration ([#138](https://github.com/element-hq/matrix-react-sdk/pull/138)). Contributed by @florianduros.
|
||||
* Upgrade emojibase-bindings and remove local handling of emoticon variations ([#127](https://github.com/element-hq/matrix-react-sdk/pull/127)). Contributed by @langleyd.
|
||||
* Add support for rendering media captions ([#43](https://github.com/element-hq/matrix-react-sdk/pull/43)). Contributed by @tulir.
|
||||
* Replace composer icons with Compound variants ([#123](https://github.com/element-hq/matrix-react-sdk/pull/123)). Contributed by @t3chguy.
|
||||
* Tweak default right panel size to be 320px except for maximised widgets at 420px ([#110](https://github.com/element-hq/matrix-react-sdk/pull/110)). Contributed by @t3chguy.
|
||||
* Add a pinned message badge under a pinned message ([#118](https://github.com/element-hq/matrix-react-sdk/pull/118)). Contributed by @florianduros.
|
||||
* Ditch right panel tabs and re-add close button ([#99](https://github.com/element-hq/matrix-react-sdk/pull/99)). Contributed by @t3chguy.
|
||||
* Force verification even for refreshed clients ([#44](https://github.com/element-hq/matrix-react-sdk/pull/44)). Contributed by @dbkr.
|
||||
* Update emoji text, border and background colour in timeline ([#119](https://github.com/element-hq/matrix-react-sdk/pull/119)). Contributed by @florianduros.
|
||||
* Disable ICE fallback based on well-known configuration ([#111](https://github.com/element-hq/matrix-react-sdk/pull/111)). Contributed by @t3chguy.
|
||||
* Remove legacy room header and promote beta room header ([#105](https://github.com/element-hq/matrix-react-sdk/pull/105)). Contributed by @t3chguy.
|
||||
* Respect `io.element.jitsi` `useFor1To1Calls` in well-known ([#112](https://github.com/element-hq/matrix-react-sdk/pull/112)). Contributed by @t3chguy.
|
||||
* Use Compound close icon in favour of mishmash of x/close icons ([#108](https://github.com/element-hq/matrix-react-sdk/pull/108)). Contributed by @t3chguy.
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
|
||||
* Correct typo in option documentation ([#28148](https://github.com/element-hq/element-web/pull/28148)). Contributed by @AndrewKvalheim.
|
||||
* Revert #124 and #135 ([#139](https://github.com/element-hq/matrix-react-sdk/pull/139)). Contributed by @dbkr.
|
||||
* Add aria-label to e2e icon ([#136](https://github.com/element-hq/matrix-react-sdk/pull/136)). Contributed by @florianduros.
|
||||
* Fix bell icons on room list hover being black squares ([#135](https://github.com/element-hq/matrix-react-sdk/pull/135)). Contributed by @dbkr.
|
||||
* Fix vertical overflow on the mobile register screen ([#137](https://github.com/element-hq/matrix-react-sdk/pull/137)). Contributed by @langleyd.
|
||||
* Allow to unpin redacted event ([#98](https://github.com/element-hq/matrix-react-sdk/pull/98)). Contributed by @florianduros.
|
||||
|
||||
|
||||
|
||||
Changes in [1.11.81](https://github.com/element-hq/element-web/releases/tag/v1.11.81) (2024-10-15)
|
||||
==================================================================================================
|
||||
This release fixes High severity vulnerability CVE-2024-47771 / GHSA-963w-49j9-gxj6
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
// Stub out FontManager for tests as it doesn't validate anything we don't already know given
|
||||
// our fixed test environment and it requires the installation of node-canvas.
|
||||
|
||||
module.exports = {
|
||||
fixupColorFonts: () => Promise.resolve(),
|
||||
};
|
||||
@@ -1,5 +1 @@
|
||||
{
|
||||
"src/components/views/auth/AuthFooter.tsx": "src/components/views/auth/VectorAuthFooter.tsx",
|
||||
"src/components/views/auth/AuthHeaderLogo.tsx": "src/components/views/auth/VectorAuthHeaderLogo.tsx",
|
||||
"src/components/views/auth/AuthPage.tsx": "src/components/views/auth/VectorAuthPage.tsx"
|
||||
}
|
||||
{}
|
||||
|
||||
@@ -592,4 +592,3 @@ The following are undocumented or intended for developer use only.
|
||||
2. `sync_timeline_limit`
|
||||
3. `dangerously_allow_unsafe_and_insecure_passwords`
|
||||
4. `latex_maths_delims`: An optional setting to override the default delimiters used for maths parsing. See https://github.com/matrix-org/matrix-react-sdk/pull/5939 for details. Only used when `feature_latex_maths` is enabled.
|
||||
5. `voice_broadcast.chunk_length`: Target chunk length in seconds for the Voice Broadcast feature currently under development.
|
||||
|
||||
@@ -11,8 +11,8 @@ Customisations will be removed from the codebase in a future release.
|
||||
Element Web and the React SDK support "customisation points" that can be used to
|
||||
easily add custom logic specific to a particular deployment of Element Web.
|
||||
|
||||
An example of this is the [security customisations
|
||||
module](https://github.com/element-hq/element-web/blob/develop/src/customisations/Security.ts).
|
||||
An example of this is the [media customisations
|
||||
module](https://github.com/element-hq/element-web/blob/develop/src/customisations/Media.ts).
|
||||
This module in the React SDK only defines some empty functions and their types:
|
||||
it does not do anything by default.
|
||||
|
||||
@@ -21,14 +21,14 @@ Web so that you can add your own code. Even though the default module is part of
|
||||
the React SDK, you can still override it from the Element Web layer:
|
||||
|
||||
1. Copy the default customisation module to
|
||||
`element-web/src/customisations/YourNameSecurity.ts`
|
||||
`element-web/src/customisations/YourNameMedia.ts`
|
||||
2. Edit customisations points and make sure export the ones you actually want to
|
||||
activate
|
||||
3. Create/add an entry to `customisations.json` next to the webpack config:
|
||||
|
||||
```json
|
||||
{
|
||||
"src/customisations/Security.ts": "src/customisations/YourNameSecurity.ts"
|
||||
"src/customisations/Media.ts": "src/customisations/YourNameMedia.ts"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -41,7 +41,15 @@ The Docker image can be used to serve element-web as a web server. The easiest w
|
||||
it is to use the prebuilt image:
|
||||
|
||||
```bash
|
||||
docker run -p 80:80 vectorim/element-web
|
||||
docker run --rm -p 127.0.0.1:80:80 vectorim/element-web
|
||||
```
|
||||
|
||||
A server can also be made available to clients outside the local host by omitting the
|
||||
explicit local address as described in
|
||||
[docker run documentation](https://docs.docker.com/engine/reference/commandline/run/#publish-or-expose-port--p---expose):
|
||||
|
||||
```bash
|
||||
docker run --rm -p 80:80 vectorim/element-web
|
||||
```
|
||||
|
||||
To supply your own custom `config.json`, map a volume to `/app/config.json`. For example,
|
||||
@@ -49,7 +57,7 @@ if your custom config was located at `/etc/element-web/config.json` then your Do
|
||||
would be:
|
||||
|
||||
```bash
|
||||
docker run -p 80:80 -v /etc/element-web/config.json:/app/config.json vectorim/element-web
|
||||
docker run --rm -p 127.0.0.1:80:80 -v /etc/element-web/config.json:/app/config.json vectorim/element-web
|
||||
```
|
||||
|
||||
To build the image yourself:
|
||||
|
||||
@@ -53,15 +53,11 @@ yarn run test:playwright:open --headed --debug
|
||||
|
||||
See more command line options at <https://playwright.dev/docs/test-cli>.
|
||||
|
||||
### Running with Rust cryptography
|
||||
## Projects
|
||||
|
||||
`matrix-js-sdk` is currently in the
|
||||
[process](https://github.com/vector-im/element-web/issues/21972) of being
|
||||
updated to replace its end-to-end encryption implementation to use the [Matrix
|
||||
Rust SDK](https://github.com/matrix-org/matrix-rust-sdk). This is not currently
|
||||
enabled by default, but it is possible to have Playwright configure Element to use
|
||||
the Rust crypto implementation by passing `--project="Rust Crypto"` or using
|
||||
the top left options in open mode.
|
||||
By default, Playwright will run all "Projects", this means tests will run against Chrome, Firefox and "Safari" (Webkit).
|
||||
We only run tests against Chrome in pull request CI, but all projects in the merge queue.
|
||||
Some tests are excluded from running on certain browsers due to incompatibilities in the test harness.
|
||||
|
||||
## How the Tests Work
|
||||
|
||||
@@ -217,3 +213,21 @@ instead of the native `toHaveScreenshot`.
|
||||
|
||||
If you are running Linux and are unfortunate that the screenshots are not rendering identically,
|
||||
you may wish to specify `--ignore-snapshots` and rely on Docker to render them for you.
|
||||
|
||||
## Test Tags
|
||||
|
||||
We use test tags to categorise tests for running subsets more efficiently.
|
||||
|
||||
- `@mergequeue`: Tests that are slow or flaky and cover areas of the app we update seldom, should not be run on every PR commit but will be run in the Merge Queue.
|
||||
- `@screenshot`: Tests that use `toMatchScreenshot` to speed up a run of `test:playwright:screenshots`. A test with this tag must not also have the `@mergequeue` tag as this would cause false positives in the stale screenshot detection.
|
||||
- `@no-$project`: Tests which are unsupported in $Project. These tests will be skipped when running in $Project.
|
||||
|
||||
Anything testing Matrix media will need to have `@no-firefox` and `@no-webkit` as those rely on the service worker which
|
||||
has to be disabled in Playwright on Firefox & Webkit to retain routing functionality.
|
||||
Anything testing VoIP/microphone will need to have `@no-webkit` as fake microphone functionality is not available
|
||||
there at this time.
|
||||
|
||||
## Colima
|
||||
|
||||
If you are running under Colima, you may need to set the environment variable `TMPDIR` to `/tmp/colima` or a path
|
||||
within `$HOME` to allow bind mounting temporary directories into the Docker containers.
|
||||
|
||||
@@ -29,7 +29,7 @@ default theme, you would use `default_theme: "custom-Electric Blue"`.
|
||||
|
||||
e.g. in config.json:
|
||||
|
||||
```
|
||||
```json5
|
||||
"setting_defaults": {
|
||||
"custom_themes": [
|
||||
{
|
||||
@@ -59,6 +59,10 @@ e.g. in config.json:
|
||||
"timeline-text-color": "#2e2f32",
|
||||
"timeline-text-secondary-color": "#61708b",
|
||||
"timeline-highlights-color": "#f3f8fd",
|
||||
|
||||
// These should both be 8 values long
|
||||
"username-colors": ["#ff0000", /*...*/],
|
||||
"avatar-background-colors": ["#cc0000", /*...*/]
|
||||
},
|
||||
"compound": {
|
||||
"--cpd-color-icon-accent-tertiary": "var(--cpd-color-blue-800)",
|
||||
|
||||
@@ -14,6 +14,8 @@ const config: Config = {
|
||||
testEnvironment: "jsdom",
|
||||
testEnvironmentOptions: {
|
||||
url: "http://localhost/",
|
||||
// This is needed to be able to load dual CJS/ESM WASM packages e.g. rust crypto & matrix-wywiwyg
|
||||
customExportConditions: ["browser", "node"],
|
||||
},
|
||||
testMatch: ["<rootDir>/test/**/*-test.[tj]s?(x)"],
|
||||
globalSetup: "<rootDir>/test/globalSetup.ts",
|
||||
@@ -32,13 +34,12 @@ const config: Config = {
|
||||
"decoderWorker\\.min\\.wasm": "<rootDir>/__mocks__/empty.js",
|
||||
"waveWorker\\.min\\.js": "<rootDir>/__mocks__/empty.js",
|
||||
"context-filter-polyfill": "<rootDir>/__mocks__/empty.js",
|
||||
"FontManager.ts": "<rootDir>/__mocks__/FontManager.js",
|
||||
"workers/(.+)Factory": "<rootDir>/__mocks__/workerFactoryMock.js",
|
||||
"^!!raw-loader!.*": "jest-raw-loader",
|
||||
"recorderWorkletFactory": "<rootDir>/__mocks__/empty.js",
|
||||
"^fetch-mock$": "<rootDir>/node_modules/fetch-mock",
|
||||
},
|
||||
transformIgnorePatterns: ["/node_modules/(?!matrix-js-sdk).+$"],
|
||||
transformIgnorePatterns: ["/node_modules/(?!(mime|matrix-js-sdk)).+$"],
|
||||
collectCoverageFrom: [
|
||||
"<rootDir>/src/**/*.{js,ts,tsx}",
|
||||
// getSessionLock is piped into a different JS context via stringification, and the coverage functionality is
|
||||
|
||||
53
knip.ts
Normal file
53
knip.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { KnipConfig } from "knip";
|
||||
|
||||
export default {
|
||||
entry: [
|
||||
"src/vector/index.ts",
|
||||
"src/serviceworker/index.ts",
|
||||
"src/workers/*.worker.ts",
|
||||
"src/utils/exportUtils/exportJS.js",
|
||||
"scripts/**",
|
||||
"playwright/**",
|
||||
"test/**",
|
||||
"res/decoder-ring/**",
|
||||
],
|
||||
project: ["**/*.{js,ts,jsx,tsx}"],
|
||||
ignore: [
|
||||
"docs/**",
|
||||
"res/jitsi_external_api.min.js",
|
||||
// Used by jest
|
||||
"__mocks__/maplibre-gl.js",
|
||||
// Keep for now
|
||||
"src/hooks/useLocalStorageState.ts",
|
||||
"src/components/views/elements/InfoTooltip.tsx",
|
||||
"src/components/views/elements/StyledCheckbox.tsx",
|
||||
],
|
||||
ignoreDependencies: [
|
||||
// Required for `action-validator`
|
||||
"@action-validator/*",
|
||||
// Used for git pre-commit hooks
|
||||
"husky",
|
||||
// Used by jest
|
||||
"babel-jest",
|
||||
// Used by babel
|
||||
"@babel/runtime",
|
||||
"@babel/plugin-transform-class-properties",
|
||||
// Referenced in PCSS
|
||||
"github-markdown-css",
|
||||
// False positive
|
||||
"sw.js",
|
||||
// Used by webpack
|
||||
"buffer",
|
||||
"process",
|
||||
"util",
|
||||
// Used by workflows
|
||||
"ts-prune",
|
||||
// Required due to bug in bloom-filters https://github.com/Callidon/bloom-filters/issues/75
|
||||
"@types/seedrandom",
|
||||
],
|
||||
ignoreBinaries: [
|
||||
// Used in scripts & workflows
|
||||
"jq",
|
||||
],
|
||||
ignoreExportsUsedInFile: true,
|
||||
} satisfies KnipConfig;
|
||||
70
package.json
70
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "element-web",
|
||||
"version": "1.11.81",
|
||||
"version": "1.11.89",
|
||||
"description": "A feature-rich client for Matrix.org",
|
||||
"author": "New Vector Ltd.",
|
||||
"repository": {
|
||||
@@ -35,7 +35,7 @@
|
||||
"i18n:lint": "matrix-i18n-lint && prettier --log-level=silent --write src/i18n/strings/ --ignore-path /dev/null",
|
||||
"i18n:diff": "cp src/i18n/strings/en_EN.json src/i18n/strings/en_EN_orig.json && yarn i18n && matrix-compare-i18n-files src/i18n/strings/en_EN_orig.json src/i18n/strings/en_EN.json",
|
||||
"make-component": "node scripts/make-react-component.js",
|
||||
"rethemendex": "res/css/rethemendex.sh",
|
||||
"rethemendex": "./res/css/rethemendex.sh",
|
||||
"clean": "rimraf lib webapp",
|
||||
"build": "yarn clean && yarn build:genfiles && yarn build:bundle",
|
||||
"build-stats": "yarn clean && yarn build:genfiles && yarn build:bundle-stats",
|
||||
@@ -45,58 +45,56 @@
|
||||
"build:bundle": "webpack --progress --mode production",
|
||||
"build:bundle-stats": "webpack --progress --mode production --json > webpack-stats.json",
|
||||
"build:module_system": "ts-node --project ./tsconfig.module_system.json module_system/scripts/install.ts",
|
||||
"dist": "scripts/package.sh",
|
||||
"dist": "./scripts/package.sh",
|
||||
"start": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n modules,res \"yarn build:module_system\" \"yarn build:res\" && concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n res,element-js \"yarn start:res\" \"yarn start:js\"",
|
||||
"start:https": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n res,element-js \"yarn start:res\" \"yarn start:js --server-type https\"",
|
||||
"start:res": "ts-node scripts/copy-res.ts -w",
|
||||
"start:js": "webpack serve --output-path webapp --output-filename=bundles/_dev_/[name].js --output-chunk-filename=bundles/_dev_/[name].js --mode development",
|
||||
"lint": "yarn lint:types && yarn lint:js && yarn lint:style && yarn lint:workflows",
|
||||
"lint:js": "yarn lint:js:src && yarn lint:js:module_system",
|
||||
"lint:js:src": "eslint --max-warnings 0 src test playwright && prettier --check .",
|
||||
"lint:js:module_system": "eslint --max-warnings 0 --config .eslintrc-module_system.js module_system",
|
||||
"lint:js-fix": "yarn lint:js-fix:src && yarn lint:js-fix:module_system",
|
||||
"lint:js-fix:src": "prettier --log-level=warn --write . && eslint --fix src test playwright",
|
||||
"lint:js-fix:module_system": "eslint --fix --config .eslintrc-module_system.js module_system",
|
||||
"lint:js": "eslint --max-warnings 0 src test playwright module_system && prettier --check .",
|
||||
"lint:js-fix": "prettier --log-level=warn --write . && eslint --fix src test playwright module_system",
|
||||
"lint:types": "yarn lint:types:src && yarn lint:types:module_system",
|
||||
"lint:types:src": "tsc --noEmit --jsx react && tsc --noEmit --jsx react -p playwright",
|
||||
"lint:types:module_system": "tsc --noEmit --project ./tsconfig.module_system.json",
|
||||
"lint:style": "stylelint \"res/css/**/*.pcss\"",
|
||||
"lint:workflows": "find .github/workflows -type f \\( -iname '*.yaml' -o -iname '*.yml' \\) | xargs -I {} sh -c 'echo \"Linting {}\"; action-validator \"{}\"'",
|
||||
"lint:knip": "knip",
|
||||
"test": "jest",
|
||||
"test:playwright": "playwright test",
|
||||
"test:playwright:open": "yarn test:playwright --ui",
|
||||
"test:playwright:screenshots": "yarn test:playwright:screenshots:build && yarn test:playwright:screenshots:run",
|
||||
"test:playwright:screenshots:build": "docker build playwright -t element-web-playwright",
|
||||
"test:playwright:screenshots:run": "docker run --rm --network host -e BASE_URL -e CI -v $(pwd):/work/ -v $(node -e 'console.log(require(`path`).dirname(require.resolve(`matrix-js-sdk/package.json`)))'):/work/node_modules/matrix-js-sdk -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/:/tmp/ -it element-web-playwright",
|
||||
"test:playwright:screenshots:run": "docker run --rm --network host -e BASE_URL -e CI -v $(pwd):/work/ -v $(node -e 'console.log(require(`path`).dirname(require.resolve(`matrix-js-sdk/package.json`)))'):/work/node_modules/matrix-js-sdk -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/:/tmp/ -it element-web-playwright --grep @screenshot --project=Chrome",
|
||||
"coverage": "yarn test --coverage",
|
||||
"analyse:unused-exports": "ts-node ./scripts/analyse_unused_exports.ts",
|
||||
"analyse:webpack-bundles": "webpack-bundle-analyzer webpack-stats.json webapp",
|
||||
"update:jitsi": "curl -s https://meet.element.io/libs/external_api.min.js > ./res/jitsi_external_api.min.js"
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/seedrandom": "3.0.8",
|
||||
"oidc-client-ts": "3.1.0",
|
||||
"jwt-decode": "4.0.0",
|
||||
"caniuse-lite": "1.0.30001668",
|
||||
"caniuse-lite": "1.0.30001684",
|
||||
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0",
|
||||
"wrap-ansi": "npm:wrap-ansi@^7.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@fontsource/inconsolata": "^5",
|
||||
"@fontsource/inter": "^5",
|
||||
"@formatjs/intl-segmenter": "^11.5.7",
|
||||
"@matrix-org/analytics-events": "^0.28.0",
|
||||
"@matrix-org/analytics-events": "^0.29.0",
|
||||
"@matrix-org/emojibase-bindings": "^1.3.3",
|
||||
"@vector-im/matrix-wysiwyg": "2.37.13",
|
||||
"@matrix-org/react-sdk-module-api": "^2.4.0",
|
||||
"@matrix-org/spec": "^1.7.0",
|
||||
"@sentry/browser": "^8.0.0",
|
||||
"@vector-im/compound-design-tokens": "^1.8.0",
|
||||
"@vector-im/compound-web": "^7.1.0",
|
||||
"@vector-im/compound-design-tokens": "^2.0.1",
|
||||
"@vector-im/compound-web": "^7.5.0",
|
||||
"@vector-im/matrix-wysiwyg": "2.37.13",
|
||||
"@zxcvbn-ts/core": "^3.0.4",
|
||||
"@zxcvbn-ts/language-common": "^3.0.4",
|
||||
"@zxcvbn-ts/language-en": "^3.0.2",
|
||||
"await-lock": "^2.1.0",
|
||||
"bloom-filters": "^3.0.1",
|
||||
"bloom-filters": "^3.0.3",
|
||||
"blurhash": "^2.0.3",
|
||||
"browserslist": "^4.23.2",
|
||||
"classnames": "^2.2.6",
|
||||
@@ -114,28 +112,29 @@
|
||||
"highlight.js": "^11.3.1",
|
||||
"html-entities": "^2.0.0",
|
||||
"is-ip": "^3.1.0",
|
||||
"jsrsasign": "^11.0.0",
|
||||
"js-xxhash": "^4.0.0",
|
||||
"jsrsasign": "^11.0.0",
|
||||
"jszip": "^3.7.0",
|
||||
"katex": "^0.16.0",
|
||||
"linkify-element": "4.1.3",
|
||||
"linkify-react": "4.1.3",
|
||||
"linkify-string": "4.1.3",
|
||||
"linkifyjs": "4.1.3",
|
||||
"linkify-element": "4.2.0",
|
||||
"linkify-react": "4.2.0",
|
||||
"linkify-string": "4.2.0",
|
||||
"linkifyjs": "4.2.0",
|
||||
"lodash": "^4.17.21",
|
||||
"maplibre-gl": "^2.0.0",
|
||||
"maplibre-gl": "^4.0.0",
|
||||
"matrix-encrypt-attachment": "^1.0.3",
|
||||
"matrix-events-sdk": "0.0.1",
|
||||
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop",
|
||||
"matrix-widget-api": "^1.9.0",
|
||||
"matrix-widget-api": "^1.10.0",
|
||||
"memoize-one": "^6.0.0",
|
||||
"mime": "^4.0.4",
|
||||
"oidc-client-ts": "^3.0.1",
|
||||
"opus-recorder": "^8.0.3",
|
||||
"pako": "^2.0.3",
|
||||
"png-chunks-extract": "^1.0.0",
|
||||
"posthog-js": "1.157.2",
|
||||
"qrcode": "1.5.4",
|
||||
"re-resizable": "6.9.17",
|
||||
"re-resizable": "6.10.1",
|
||||
"react": "^18.3.1",
|
||||
"react-beautiful-dnd": "^13.1.0",
|
||||
"react-blurhash": "^0.3.0",
|
||||
@@ -155,11 +154,9 @@
|
||||
"@action-validator/cli": "^0.6.0",
|
||||
"@action-validator/core": "^0.6.0",
|
||||
"@axe-core/playwright": "^4.8.1",
|
||||
"@babel/cli": "^7.12.10",
|
||||
"@babel/core": "^7.12.10",
|
||||
"@babel/eslint-parser": "^7.12.10",
|
||||
"@babel/eslint-plugin": "^7.12.10",
|
||||
"@babel/parser": "^7.12.11",
|
||||
"@babel/plugin-proposal-export-default-from": "^7.12.1",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/plugin-transform-class-properties": "^7.12.1",
|
||||
@@ -172,7 +169,6 @@
|
||||
"@babel/preset-env": "^7.12.11",
|
||||
"@babel/preset-react": "^7.12.10",
|
||||
"@babel/preset-typescript": "^7.12.7",
|
||||
"@babel/register": "^7.12.10",
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@casualbot/jest-sonar-reporter": "2.2.7",
|
||||
"@peculiar/webcrypto": "^1.4.3",
|
||||
@@ -186,7 +182,6 @@
|
||||
"@testing-library/react": "^16.0.0",
|
||||
"@testing-library/user-event": "^14.5.2",
|
||||
"@types/commonmark": "^0.27.4",
|
||||
"@types/content-type": "^1.1.5",
|
||||
"@types/counterpart": "^0.18.1",
|
||||
"@types/css-tree": "^2.3.8",
|
||||
"@types/diff-match-patch": "^1.0.32",
|
||||
@@ -211,20 +206,16 @@
|
||||
"@types/react-dom": "18.3.1",
|
||||
"@types/react-transition-group": "^4.4.0",
|
||||
"@types/sanitize-html": "2.13.0",
|
||||
"@types/sdp-transform": "^2.4.6",
|
||||
"@types/seedrandom": "3.0.8",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@types/tar-js": "^0.3.5",
|
||||
"@types/ua-parser-js": "^0.7.36",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
||||
"@typescript-eslint/parser": "^8.0.0",
|
||||
"axe-core": "4.10.2",
|
||||
"babel-jest": "^29.0.0",
|
||||
"babel-loader": "^9.0.0",
|
||||
"babel-plugin-jsx-remove-data-test-id": "^3.0.0",
|
||||
"blob-polyfill": "^9.0.0",
|
||||
"buffer": "^6.0.3",
|
||||
"chokidar": "^4.0.0",
|
||||
"concurrently": "^9.0.0",
|
||||
"copy-webpack-plugin": "^12.0.0",
|
||||
@@ -259,14 +250,12 @@
|
||||
"jest-mock": "^29.6.2",
|
||||
"jest-raw-loader": "^1.0.1",
|
||||
"jsqr": "^1.4.0",
|
||||
"knip": "^5.36.2",
|
||||
"lint-staged": "^15.0.2",
|
||||
"mailhog": "^4.16.0",
|
||||
"matrix-mock-request": "^2.5.0",
|
||||
"matrix-web-i18n": "^3.2.1",
|
||||
"mini-css-extract-plugin": "2.9.0",
|
||||
"minimist": "^1.2.6",
|
||||
"mkdirp": "^3.0.0",
|
||||
"mocha-junit-reporter": "^2.2.0",
|
||||
"modernizr": "^3.12.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"playwright-core": "^1.45.1",
|
||||
@@ -276,28 +265,31 @@
|
||||
"postcss-import": "16.1.0",
|
||||
"postcss-loader": "8.1.1",
|
||||
"postcss-mixins": "^11.0.0",
|
||||
"postcss-nested": "^6.0.0",
|
||||
"postcss-nested": "^7.0.0",
|
||||
"postcss-preset-env": "^10.0.0",
|
||||
"postcss-scss": "^4.0.4",
|
||||
"postcss-simple-vars": "^7.0.1",
|
||||
"prettier": "3.3.3",
|
||||
"prettier": "3.4.2",
|
||||
"process": "^0.11.10",
|
||||
"raw-loader": "^4.0.2",
|
||||
"rimraf": "^6.0.0",
|
||||
"semver": "^7.5.2",
|
||||
"source-map-loader": "^5.0.0",
|
||||
"stylelint": "^16.1.0",
|
||||
"stylelint-config-standard": "^36.0.0",
|
||||
"stylelint-scss": "^6.0.0",
|
||||
"stylelint-value-no-unknown-custom-properties": "^6.0.1",
|
||||
"terser-webpack-plugin": "^5.3.9",
|
||||
"ts-node": "^10.9.1",
|
||||
"ts-prune": "^0.10.3",
|
||||
"typescript": "5.6.3",
|
||||
"typescript": "5.7.2",
|
||||
"util": "^0.12.5",
|
||||
"web-streams-polyfill": "^4.0.0",
|
||||
"webpack": "^5.89.0",
|
||||
"webpack-bundle-analyzer": "^4.8.0",
|
||||
"webpack-cli": "^5.0.0",
|
||||
"webpack-dev-server": "^5.0.0",
|
||||
"webpack-version-file-plugin": "^0.5.0",
|
||||
"yaml": "^2.3.3"
|
||||
},
|
||||
"@casualbot/jest-sonar-reporter": {
|
||||
|
||||
@@ -6,20 +6,54 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { defineConfig } from "@playwright/test";
|
||||
import { defineConfig, devices } from "@playwright/test";
|
||||
|
||||
const baseURL = process.env["BASE_URL"] ?? "http://localhost:8080";
|
||||
|
||||
export default defineConfig({
|
||||
projects: [
|
||||
{
|
||||
name: "Chrome",
|
||||
use: {
|
||||
...devices["Desktop Chrome"],
|
||||
channel: "chromium",
|
||||
permissions: ["clipboard-write", "clipboard-read", "microphone"],
|
||||
launchOptions: {
|
||||
args: ["--use-fake-ui-for-media-stream", "--use-fake-device-for-media-stream", "--mute-audio"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Firefox",
|
||||
use: {
|
||||
...devices["Desktop Firefox"],
|
||||
launchOptions: {
|
||||
firefoxUserPrefs: {
|
||||
"permissions.default.microphone": 1,
|
||||
},
|
||||
},
|
||||
// This is needed to work around an issue between Playwright routes, Firefox, and Service workers
|
||||
// https://github.com/microsoft/playwright/issues/33561#issuecomment-2471642120
|
||||
serviceWorkers: "block",
|
||||
},
|
||||
ignoreSnapshots: true,
|
||||
},
|
||||
{
|
||||
name: "WebKit",
|
||||
use: {
|
||||
...devices["Desktop Safari"],
|
||||
// Seemingly WebKit has the same issue as Firefox in Playwright routes not working
|
||||
// https://playwright.dev/docs/network#missing-network-events-and-service-workers
|
||||
serviceWorkers: "block",
|
||||
},
|
||||
ignoreSnapshots: true,
|
||||
},
|
||||
],
|
||||
use: {
|
||||
viewport: { width: 1280, height: 720 },
|
||||
ignoreHTTPSErrors: true,
|
||||
video: "retain-on-failure",
|
||||
baseURL,
|
||||
permissions: ["clipboard-write", "clipboard-read", "microphone"],
|
||||
launchOptions: {
|
||||
args: ["--use-fake-ui-for-media-stream", "--use-fake-device-for-media-stream", "--mute-audio"],
|
||||
},
|
||||
trace: "on-first-retry",
|
||||
},
|
||||
webServer: {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM mcr.microsoft.com/playwright:v1.48.2-jammy
|
||||
FROM mcr.microsoft.com/playwright:v1.49.1-noble
|
||||
|
||||
WORKDIR /work
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { test, expect } from "../../element-web-test";
|
||||
|
||||
test(`shows error page if browser lacks Intl support`, async ({ page }) => {
|
||||
test(`shows error page if browser lacks Intl support`, { tag: "@screenshot" }, async ({ page }) => {
|
||||
await page.addInitScript({ content: `delete window.Intl;` });
|
||||
await page.goto("/");
|
||||
|
||||
@@ -21,7 +21,7 @@ test(`shows error page if browser lacks Intl support`, async ({ page }) => {
|
||||
await expect(page).toMatchScreenshot("unsupported-browser.png");
|
||||
});
|
||||
|
||||
test(`shows error page if browser lacks WebAssembly support`, async ({ page }) => {
|
||||
test(`shows error page if browser lacks WebAssembly support`, { tag: "@screenshot" }, async ({ page }) => {
|
||||
await page.addInitScript({ content: `delete window.WebAssembly;` });
|
||||
await page.goto("/");
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import { SettingLevel } from "../../../src/settings/SettingLevel";
|
||||
import { Layout } from "../../../src/settings/enums/Layout";
|
||||
import { ElementAppPage } from "../../pages/ElementAppPage";
|
||||
|
||||
test.describe("Audio player", () => {
|
||||
test.describe("Audio player", { tag: ["@no-firefox", "@no-webkit"] }, () => {
|
||||
test.use({
|
||||
displayName: "Hanako",
|
||||
});
|
||||
@@ -134,18 +134,22 @@ test.describe("Audio player", () => {
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test("should be correctly rendered - light theme", async ({ page, app }) => {
|
||||
test("should be correctly rendered - light theme", { tag: "@screenshot" }, async ({ page, app }) => {
|
||||
await uploadFile(page, "playwright/sample-files/1sec-long-name-audio-file.ogg");
|
||||
await takeSnapshots(page, app, "Selected EventTile of audio player (light theme)");
|
||||
});
|
||||
|
||||
test("should be correctly rendered - light theme with monospace font", async ({ page, app }) => {
|
||||
test(
|
||||
"should be correctly rendered - light theme with monospace font",
|
||||
{ tag: "@screenshot" },
|
||||
async ({ page, app }) => {
|
||||
await uploadFile(page, "playwright/sample-files/1sec-long-name-audio-file.ogg");
|
||||
|
||||
await takeSnapshots(page, app, "Selected EventTile of audio player (light theme, monospace font)", true); // Enable monospace
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test("should be correctly rendered - high contrast theme", async ({ page, app }) => {
|
||||
test("should be correctly rendered - high contrast theme", { tag: "@screenshot" }, async ({ page, app }) => {
|
||||
// Disable system theme in case ThemeWatcher enables the theme automatically,
|
||||
// so that the high contrast theme can be enabled
|
||||
await app.settings.setValue("use_system_theme", null, SettingLevel.DEVICE, false);
|
||||
@@ -161,7 +165,7 @@ test.describe("Audio player", () => {
|
||||
await takeSnapshots(page, app, "Selected EventTile of audio player (high contrast)");
|
||||
});
|
||||
|
||||
test("should be correctly rendered - dark theme", async ({ page, app }) => {
|
||||
test("should be correctly rendered - dark theme", { tag: "@screenshot" }, async ({ page, app }) => {
|
||||
// Enable dark theme
|
||||
await app.settings.setValue("theme", null, SettingLevel.ACCOUNT, "dark");
|
||||
|
||||
@@ -207,7 +211,10 @@ test.describe("Audio player", () => {
|
||||
expect(download.suggestedFilename()).toBe("1sec.ogg");
|
||||
});
|
||||
|
||||
test("should support replying to audio file with another audio file", async ({ page, app }) => {
|
||||
test(
|
||||
"should support replying to audio file with another audio file",
|
||||
{ tag: "@screenshot" },
|
||||
async ({ page, app }) => {
|
||||
await uploadFile(page, "playwright/sample-files/1sec.ogg");
|
||||
|
||||
// Assert the audio player is rendered
|
||||
@@ -230,9 +237,13 @@ test.describe("Audio player", () => {
|
||||
await expect(button.locator(".mx_MFileBody_info_filename")).toBeVisible();
|
||||
|
||||
await takeSnapshots(page, app, "Selected EventTile of audio player with a reply");
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test("should support creating a reply chain with multiple audio files", async ({ page, app, user }) => {
|
||||
test(
|
||||
"should support creating a reply chain with multiple audio files",
|
||||
{ tag: "@screenshot" },
|
||||
async ({ page, app, user }) => {
|
||||
// Note: "mx_ReplyChain" element is used not only for replies which
|
||||
// create a reply chain, but also for a single reply without a replied
|
||||
// message. This test checks whether a reply chain which consists of
|
||||
@@ -293,7 +304,8 @@ test.describe("Audio player", () => {
|
||||
|
||||
// Take snapshots
|
||||
await takeSnapshots(page, app, "Selected EventTile of audio player with a reply chain");
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test("should be rendered, play, and support replying on a thread", async ({ page, app }) => {
|
||||
await uploadFile(page, "playwright/sample-files/1sec-long-name-audio-file.ogg");
|
||||
|
||||
@@ -89,7 +89,10 @@ test.describe("HTML Export", () => {
|
||||
},
|
||||
});
|
||||
|
||||
test("should export html successfully and match screenshot", async ({ page, app, room }) => {
|
||||
test(
|
||||
"should export html successfully and match screenshot",
|
||||
{ tag: "@screenshot" },
|
||||
async ({ page, app, room }) => {
|
||||
// Set a fixed time rather than masking off the line with the time in it: we don't need to worry
|
||||
// about the width changing and we can actually test this line looks correct.
|
||||
page.clock.setSystemTime(new Date("2024-01-01T00:00:00Z"));
|
||||
@@ -127,5 +130,6 @@ test.describe("HTML Export", () => {
|
||||
page.locator(".mx_MessageTimestamp"),
|
||||
],
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -9,6 +9,8 @@ Please see LICENSE files in the repository root for full details.
|
||||
import { type Page } from "@playwright/test";
|
||||
|
||||
import { test, expect } from "../../element-web-test";
|
||||
import { test as masTest, registerAccountMas } from "../oidc";
|
||||
import { isDendrite } from "../../plugins/homeserver/dendrite";
|
||||
|
||||
async function expectBackupVersionToBe(page: Page, version: string) {
|
||||
await expect(page.locator(".mx_SecureBackupPanel_statusList tr:nth-child(5) td")).toHaveText(
|
||||
@@ -18,12 +20,41 @@ async function expectBackupVersionToBe(page: Page, version: string) {
|
||||
await expect(page.locator(".mx_SecureBackupPanel_statusList tr:nth-child(6) td")).toHaveText(version);
|
||||
}
|
||||
|
||||
masTest.describe("Encryption state after registration", () => {
|
||||
masTest.skip(isDendrite, "does not yet support MAS");
|
||||
|
||||
masTest("Key backup is enabled by default", async ({ page, mailhog, app }) => {
|
||||
await page.goto("/#/login");
|
||||
await page.getByRole("button", { name: "Continue" }).click();
|
||||
await registerAccountMas(page, mailhog.api, "alice", "alice@email.com", "Pa$sW0rD!");
|
||||
|
||||
await app.settings.openUserSettings("Security & Privacy");
|
||||
expect(page.getByText("This session is backing up your keys.")).toBeVisible();
|
||||
});
|
||||
|
||||
masTest("user is prompted to set up recovery", async ({ page, mailhog, app }) => {
|
||||
await page.goto("/#/login");
|
||||
await page.getByRole("button", { name: "Continue" }).click();
|
||||
await registerAccountMas(page, mailhog.api, "alice", "alice@email.com", "Pa$sW0rD!");
|
||||
|
||||
await page.getByRole("button", { name: "Add room" }).click();
|
||||
await page.getByRole("menuitem", { name: "New room" }).click();
|
||||
await page.getByRole("textbox", { name: "Name" }).fill("test room");
|
||||
await page.getByRole("button", { name: "Create room" }).click();
|
||||
|
||||
await expect(page.getByRole("heading", { name: "Set up recovery" })).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("Backups", () => {
|
||||
test.use({
|
||||
displayName: "Hanako",
|
||||
});
|
||||
|
||||
test("Create, delete and recreate a keys backup", async ({ page, user, app }, workerInfo) => {
|
||||
test(
|
||||
"Create, delete and recreate a keys backup",
|
||||
{ tag: "@no-webkit" },
|
||||
async ({ page, user, app }, workerInfo) => {
|
||||
// Create a backup
|
||||
const securityTab = await app.settings.openUserSettings("Security & Privacy");
|
||||
|
||||
@@ -108,5 +139,6 @@ test.describe("Backups", () => {
|
||||
// go back to the settings to check that no backup was created (the setup button should still be there)
|
||||
await app.settings.openUserSettings("Security & Privacy");
|
||||
await expect(securityTab.getByRole("button", { name: "Set up", exact: true })).toBeVisible();
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -81,7 +81,7 @@ test.describe("Cryptography", function () {
|
||||
* Verify that the `m.cross_signing.${keyType}` key is available on the account data on the server
|
||||
* @param keyType
|
||||
*/
|
||||
async function verifyKey(app: ElementAppPage, keyType: string) {
|
||||
async function verifyKey(app: ElementAppPage, keyType: "master" | "self_signing" | "user_signing") {
|
||||
const accountData: { encrypted: Record<string, Record<string, string>> } = await app.client.evaluate(
|
||||
(cli, keyType) => cli.getAccountDataFromServer(`m.cross_signing.${keyType}`),
|
||||
keyType,
|
||||
@@ -204,12 +204,10 @@ test.describe("Cryptography", function () {
|
||||
await expect(page.locator(".mx_Dialog")).toHaveCount(1);
|
||||
});
|
||||
|
||||
test("creating a DM should work, being e2e-encrypted / user verification", async ({
|
||||
page,
|
||||
app,
|
||||
bot: bob,
|
||||
user: aliceCredentials,
|
||||
}) => {
|
||||
test(
|
||||
"creating a DM should work, being e2e-encrypted / user verification",
|
||||
{ tag: "@screenshot" },
|
||||
async ({ page, app, bot: bob, user: aliceCredentials }) => {
|
||||
await app.client.bootstrapCrossSigning(aliceCredentials);
|
||||
await startDMWithBob(page, bob);
|
||||
// send first message
|
||||
@@ -227,7 +225,8 @@ test.describe("Cryptography", function () {
|
||||
|
||||
// Take a snapshot of RoomSummaryCard with a verified E2EE icon
|
||||
await expect(page.locator(".mx_RightPanel")).toMatchScreenshot("RoomSummaryCard-with-verified-e2ee.png");
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test("should allow verification when there is no existing DM", async ({
|
||||
page,
|
||||
|
||||
@@ -67,6 +67,9 @@ test.describe("Cryptography", function () {
|
||||
await page.locator(".mx_AuthPage").getByRole("button", { name: "I'll verify later" }).click();
|
||||
await app.viewRoomByName("Test room");
|
||||
|
||||
// In this case, the call to cryptoApi.isEncryptionEnabledInRoom is taking a long time to resolve
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// There should be two historical events in the timeline
|
||||
const tiles = await page.locator(".mx_EventTile").all();
|
||||
expect(tiles.length).toBeGreaterThanOrEqual(2);
|
||||
|
||||
@@ -8,11 +8,11 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { Locator, type Page } from "@playwright/test";
|
||||
|
||||
import { test as base, expect } from "../../element-web-test";
|
||||
import { test as base, expect, Fixtures } from "../../element-web-test";
|
||||
import { viewRoomSummaryByName } from "../right-panel/utils";
|
||||
import { isDendrite } from "../../plugins/homeserver/dendrite";
|
||||
|
||||
const test = base.extend({
|
||||
const test = base.extend<Fixtures>({
|
||||
// eslint-disable-next-line no-empty-pattern
|
||||
startHomeserverOpts: async ({}, use) => {
|
||||
await use("dehydration");
|
||||
@@ -50,8 +50,6 @@ test.describe("Dehydration", () => {
|
||||
});
|
||||
|
||||
test("Create dehydrated device", async ({ page, user, app }, workerInfo) => {
|
||||
test.skip(workerInfo.project.name === "Legacy Crypto", "This test only works with Rust crypto.");
|
||||
|
||||
// Create a backup (which will create SSSS, and dehydrated device)
|
||||
|
||||
const securityTab = await app.settings.openUserSettings("Security & Privacy");
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
} from "./utils";
|
||||
import { Bot } from "../../pages/bot";
|
||||
|
||||
test.describe("Device verification", () => {
|
||||
test.describe("Device verification", { tag: "@no-webkit" }, () => {
|
||||
let aliceBotClient: Bot;
|
||||
|
||||
/** The backup version that was set up by the bot client. */
|
||||
@@ -102,7 +102,7 @@ test.describe("Device verification", () => {
|
||||
// feed the QR code into the verification request.
|
||||
const qrData = await readQrCode(infoDialog);
|
||||
const verifier = await verificationRequest.evaluateHandle(
|
||||
(request, qrData) => request.scanQRCode(new Uint8Array(qrData)),
|
||||
(request, qrData) => request.scanQRCode(new Uint8ClampedArray(qrData)),
|
||||
[...qrData],
|
||||
);
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { Locator } from "@playwright/test";
|
||||
|
||||
import { expect, test } from "../../element-web-test";
|
||||
import {
|
||||
autoJoin,
|
||||
@@ -16,6 +18,8 @@ import {
|
||||
logOutOfElement,
|
||||
verify,
|
||||
} from "./utils";
|
||||
import { bootstrapCrossSigningForClient } from "../../pages/client.ts";
|
||||
import { ElementAppPage } from "../../pages/ElementAppPage.ts";
|
||||
|
||||
test.describe("Cryptography", function () {
|
||||
test.use({
|
||||
@@ -129,8 +133,7 @@ test.describe("Cryptography", function () {
|
||||
"Encrypted by a device not verified by its owner.",
|
||||
);
|
||||
|
||||
/* In legacy crypto: should show a grey padlock for a message from a deleted device.
|
||||
* In rust crypto: should show a red padlock for a message from an unverified device.
|
||||
/* Should show a red padlock for a message from an unverified device.
|
||||
* Rust crypto remembers the verification state of the sending device, so it will know that the device was
|
||||
* unverified, even if it gets deleted. */
|
||||
// bob deletes his second device
|
||||
@@ -164,9 +167,7 @@ test.describe("Cryptography", function () {
|
||||
await expect(lastE2eIcon).toHaveClass(/mx_EventTile_e2eIcon_warning/);
|
||||
await lastE2eIcon.focus();
|
||||
await expect(await app.getTooltipForElement(lastE2eIcon)).toContainText(
|
||||
workerInfo.project.name === "Legacy Crypto"
|
||||
? "Encrypted by an unknown or deleted device."
|
||||
: "Encrypted by a device not verified by its owner.",
|
||||
"Encrypted by a device not verified by its owner.",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -276,6 +277,15 @@ test.describe("Cryptography", function () {
|
||||
bot: bob,
|
||||
homeserver,
|
||||
}) => {
|
||||
// Workaround for https://github.com/element-hq/element-web/issues/28640:
|
||||
// make sure that Alice has seen Bob's identity before she goes offline. We do this by opening
|
||||
// his user info.
|
||||
await app.toggleRoomInfoPanel();
|
||||
const rightPanel = page.locator(".mx_RightPanel");
|
||||
await rightPanel.getByRole("menuitem", { name: "People" }).click();
|
||||
await rightPanel.getByRole("button", { name: bob.credentials!.userId }).click();
|
||||
await expect(rightPanel.locator(".mx_UserInfo_devices")).toContainText("1 session");
|
||||
|
||||
// Our app is blocked from syncing while Bob sends his messages.
|
||||
await app.client.network.goOffline();
|
||||
|
||||
@@ -305,7 +315,50 @@ test.describe("Cryptography", function () {
|
||||
);
|
||||
|
||||
const penultimate = page.locator(".mx_EventTile").filter({ hasText: "test encrypted from verified" });
|
||||
await expect(penultimate.locator(".mx_EventTile_e2eIcon")).not.toBeVisible();
|
||||
await assertNoE2EIcon(penultimate, app);
|
||||
});
|
||||
|
||||
test("should show correct shields on events sent by users with changed identity", async ({
|
||||
page,
|
||||
app,
|
||||
bot: bob,
|
||||
homeserver,
|
||||
}) => {
|
||||
// Verify Bob
|
||||
await verify(app, bob);
|
||||
|
||||
// Bob logs in a new device and resets cross-signing
|
||||
const bobSecondDevice = await createSecondBotDevice(page, homeserver, bob);
|
||||
await bootstrapCrossSigningForClient(await bobSecondDevice.prepareClient(), bob.credentials, true);
|
||||
|
||||
/* should show an error for a message from a previously verified device */
|
||||
await bobSecondDevice.sendMessage(testRoomId, "test encrypted from user that was previously verified");
|
||||
const last = page.locator(".mx_EventTile_last");
|
||||
await expect(last).toContainText("test encrypted from user that was previously verified");
|
||||
const lastE2eIcon = last.locator(".mx_EventTile_e2eIcon");
|
||||
await expect(lastE2eIcon).toHaveClass(/mx_EventTile_e2eIcon_warning/);
|
||||
await lastE2eIcon.focus();
|
||||
await expect(await app.getTooltipForElement(lastE2eIcon)).toContainText(
|
||||
"Sender's verified identity has changed",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Check that the given message doesn't have an E2E warning icon.
|
||||
*
|
||||
* If it does, throw an error.
|
||||
*/
|
||||
async function assertNoE2EIcon(messageLocator: Locator, app: ElementAppPage) {
|
||||
// Make sure the message itself exists, before we check if it has any icons
|
||||
await messageLocator.waitFor();
|
||||
|
||||
const e2eIcon = messageLocator.locator(".mx_EventTile_e2eIcon");
|
||||
if ((await e2eIcon.count()) > 0) {
|
||||
// uh-oh, there is an e2e icon. Let's find out what it's about so that we can throw a helpful error.
|
||||
await e2eIcon.focus();
|
||||
const tooltip = await app.getTooltipForElement(e2eIcon);
|
||||
throw new Error(`Found an unexpected e2eIcon with tooltip '${await tooltip.textContent()}'`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,6 @@ test.describe("Invisible cryptography", () => {
|
||||
/* should show an error for a message from a previously verified device */
|
||||
await bobSecondDevice.sendMessage(testRoomId, "test encrypted from user that was previously verified");
|
||||
const lastTile = page.locator(".mx_EventTile_last");
|
||||
await expect(lastTile).toContainText("Verified identity has changed");
|
||||
await expect(lastTile).toContainText("Sender's verified identity has changed");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,9 +9,9 @@ Please see LICENSE files in the repository root for full details.
|
||||
import path from "path";
|
||||
import { readFile } from "node:fs/promises";
|
||||
|
||||
import { expect, test as base } from "../../element-web-test";
|
||||
import { expect, Fixtures, test as base } from "../../element-web-test";
|
||||
|
||||
const test = base.extend({
|
||||
const test = base.extend<Fixtures>({
|
||||
// Replace the `user` fixture with one which populates the indexeddb data before starting the app.
|
||||
user: async ({ context, pageWithCredentials: page, credentials }, use) => {
|
||||
await page.route(`/test_indexeddb_cryptostore_dump/*`, async (route, request) => {
|
||||
@@ -25,11 +25,10 @@ const test = base.extend({
|
||||
},
|
||||
});
|
||||
|
||||
test.describe("migration", function () {
|
||||
test.describe("migration", { tag: "@no-webkit" }, function () {
|
||||
test.use({ displayName: "Alice" });
|
||||
|
||||
test("Should support migration from legacy crypto", async ({ context, user, page }, workerInfo) => {
|
||||
test.skip(workerInfo.project.name === "Legacy Crypto", "This test only works with Rust crypto.");
|
||||
test.slow();
|
||||
|
||||
// We should see a migration progress bar
|
||||
|
||||
@@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { type Preset, type Visibility } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import type { Page } from "@playwright/test";
|
||||
import { test, expect } from "../../element-web-test";
|
||||
import { doTwoWaySasVerification, awaitVerifier } from "./utils";
|
||||
import { Client } from "../../pages/client";
|
||||
@@ -38,6 +39,8 @@ test.describe("User verification", () => {
|
||||
toasts,
|
||||
room: { roomId: dmRoomId },
|
||||
}) => {
|
||||
await waitForDeviceKeys(page);
|
||||
|
||||
// once Alice has joined, Bob starts the verification
|
||||
const bobVerificationRequest = await bob.evaluateHandle(
|
||||
async (client, { dmRoomId, aliceCredentials }) => {
|
||||
@@ -87,6 +90,8 @@ test.describe("User verification", () => {
|
||||
toasts,
|
||||
room: { roomId: dmRoomId },
|
||||
}) => {
|
||||
await waitForDeviceKeys(page);
|
||||
|
||||
// once Alice has joined, Bob starts the verification
|
||||
const bobVerificationRequest = await bob.evaluateHandle(
|
||||
async (client, { dmRoomId, aliceCredentials }) => {
|
||||
@@ -149,3 +154,15 @@ async function createDMRoom(client: Client, userId: string): Promise<string> {
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until we get the other user's device keys.
|
||||
* In newer rust-crypto versions, the verification request will be ignored if we
|
||||
* don't have the sender's device keys.
|
||||
*/
|
||||
async function waitForDeviceKeys(page: Page): Promise<void> {
|
||||
await expect(page.getByRole("button", { name: "Avatar" })).toBeVisible();
|
||||
const avatar = await page.getByRole("button", { name: "Avatar" });
|
||||
await avatar.click();
|
||||
await expect(page.getByText("1 session")).toBeVisible();
|
||||
}
|
||||
|
||||
@@ -220,11 +220,7 @@ export async function doTwoWaySasVerification(page: Page, verifier: JSHandle<Ver
|
||||
for (let i = 0; i < emojis.length; i++) {
|
||||
const emoji = emojis[i];
|
||||
const emojiBlock = emojiBlocks.nth(i);
|
||||
const textContent = await emojiBlock.textContent();
|
||||
// VerificationShowSas munges the case of the emoji descriptions returned by the js-sdk before
|
||||
// displaying them. Once we drop support for legacy crypto, that code can go away, and so can the
|
||||
// case-munging here.
|
||||
expect(textContent.toLowerCase()).toEqual(emoji[0] + emoji[1].toLowerCase());
|
||||
await expect(emojiBlock).toHaveText(emoji[0] + emoji[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,10 @@ test.describe("Editing", () => {
|
||||
botCreateOpts: { displayName: "Bob" },
|
||||
});
|
||||
|
||||
test("should render and interact with the message edit history dialog", async ({ page, user, app, room }) => {
|
||||
test(
|
||||
"should render and interact with the message edit history dialog",
|
||||
{ tag: "@screenshot" },
|
||||
async ({ page, user, app, room }) => {
|
||||
// Click the "Remove" button on the message edit history dialog
|
||||
const clickButtonRemove = async (locator: Locator) => {
|
||||
const eventTileLine = locator.locator(".mx_EventTile_line");
|
||||
@@ -185,7 +188,8 @@ test.describe("Editing", () => {
|
||||
.locator(".mx_RoomView_MessageList")
|
||||
.locator(".mx_EventTile_last .mx_RedactedBody", { hasText: "Message deleted" }),
|
||||
).toBeVisible();
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test("should render 'View Source' button in developer mode on the message edit history dialog", async ({
|
||||
page,
|
||||
|
||||
@@ -25,7 +25,7 @@ test.describe("Image Upload", () => {
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test("should show image preview when uploading an image", async ({ page, app }) => {
|
||||
test("should show image preview when uploading an image", { tag: "@screenshot" }, async ({ page, app }) => {
|
||||
await page
|
||||
.locator(".mx_MessageComposer_actions input[type='file']")
|
||||
.setInputFiles("playwright/sample-files/riot.png");
|
||||
|
||||
@@ -26,7 +26,7 @@ test.describe("Forgot Password", () => {
|
||||
}),
|
||||
});
|
||||
|
||||
test("renders properly", async ({ page, homeserver }) => {
|
||||
test("renders properly", { tag: "@screenshot" }, async ({ page, homeserver }) => {
|
||||
await page.goto("/");
|
||||
|
||||
await page.getByRole("link", { name: "Sign in" }).click();
|
||||
@@ -39,7 +39,7 @@ test.describe("Forgot Password", () => {
|
||||
await expect(page.getByRole("main")).toMatchScreenshot("forgot-password.png");
|
||||
});
|
||||
|
||||
test("renders email verification dialog properly", async ({ page, homeserver }) => {
|
||||
test("renders email verification dialog properly", { tag: "@screenshot" }, async ({ page, homeserver }) => {
|
||||
const user = await homeserver.registerUser(username, password);
|
||||
|
||||
await homeserver.setThreepid(user.userId, "email", email);
|
||||
|
||||
@@ -9,6 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import type { Page } from "@playwright/test";
|
||||
import { test, expect } from "../../element-web-test";
|
||||
import { openIntegrationManager } from "./utils";
|
||||
import type { UserWidget } from "../../../src/utils/WidgetUtils-types.ts";
|
||||
|
||||
const ROOM_NAME = "Integration Manager Test";
|
||||
|
||||
@@ -92,7 +93,7 @@ test.describe("Integration Manager: Get OpenID Token", () => {
|
||||
},
|
||||
},
|
||||
id: "integration-manager",
|
||||
},
|
||||
} as unknown as UserWidget,
|
||||
});
|
||||
|
||||
// Succeed when checking the token is valid
|
||||
|
||||
@@ -9,6 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import type { Page } from "@playwright/test";
|
||||
import { test, expect } from "../../element-web-test";
|
||||
import { openIntegrationManager } from "./utils";
|
||||
import type { UserWidget } from "../../../src/utils/WidgetUtils-types.ts";
|
||||
|
||||
const ROOM_NAME = "Integration Manager Test";
|
||||
const USER_DISPLAY_NAME = "Alice";
|
||||
@@ -136,7 +137,7 @@ test.describe("Integration Manager: Kick", () => {
|
||||
},
|
||||
},
|
||||
id: "integration-manager",
|
||||
},
|
||||
} as unknown as UserWidget,
|
||||
});
|
||||
|
||||
// Succeed when checking the token is valid
|
||||
|
||||
@@ -9,6 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import type { Page } from "@playwright/test";
|
||||
import { test, expect } from "../../element-web-test";
|
||||
import { openIntegrationManager } from "./utils";
|
||||
import type { UserWidget } from "../../../src/utils/WidgetUtils-types.ts";
|
||||
|
||||
const ROOM_NAME = "Integration Manager Test";
|
||||
|
||||
@@ -107,7 +108,7 @@ test.describe("Integration Manager: Read Events", () => {
|
||||
},
|
||||
},
|
||||
id: "integration-manager",
|
||||
},
|
||||
} as unknown as UserWidget,
|
||||
});
|
||||
|
||||
// Succeed when checking the token is valid
|
||||
|
||||
@@ -9,6 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import type { Page } from "@playwright/test";
|
||||
import { test, expect } from "../../element-web-test";
|
||||
import { openIntegrationManager } from "./utils";
|
||||
import type { UserWidget } from "../../../src/utils/WidgetUtils-types.ts";
|
||||
|
||||
const ROOM_NAME = "Integration Manager Test";
|
||||
|
||||
@@ -113,7 +114,7 @@ test.describe("Integration Manager: Send Event", () => {
|
||||
},
|
||||
},
|
||||
id: "integration-manager",
|
||||
},
|
||||
} as unknown as UserWidget,
|
||||
});
|
||||
|
||||
// Succeed when checking the token is valid
|
||||
|
||||
@@ -19,7 +19,7 @@ test.describe("Invite dialog", function () {
|
||||
|
||||
const botName = "BotAlice";
|
||||
|
||||
test("should support inviting a user to a room", async ({ page, app, user, bot }) => {
|
||||
test("should support inviting a user to a room", { tag: "@screenshot" }, async ({ page, app, user, bot }) => {
|
||||
// Create and view a room
|
||||
await app.client.createRoom({ name: "Test Room" });
|
||||
await app.viewRoomByName("Test Room");
|
||||
@@ -73,12 +73,17 @@ test.describe("Invite dialog", function () {
|
||||
await expect(page.getByText(`${botName} joined the room`)).toBeVisible();
|
||||
});
|
||||
|
||||
test("should support inviting a user to Direct Messages", async ({ page, app, user, bot }) => {
|
||||
test(
|
||||
"should support inviting a user to Direct Messages",
|
||||
{ tag: "@screenshot" },
|
||||
async ({ page, app, user, bot }) => {
|
||||
await page.locator(".mx_RoomList").getByRole("button", { name: "Start chat" }).click();
|
||||
|
||||
const other = page.locator(".mx_InviteDialog_other");
|
||||
// Assert that the header is rendered
|
||||
await expect(other.locator(".mx_Dialog_header .mx_Dialog_title").getByText("Direct Messages")).toBeVisible();
|
||||
await expect(
|
||||
other.locator(".mx_Dialog_header .mx_Dialog_title").getByText("Direct Messages"),
|
||||
).toBeVisible();
|
||||
|
||||
// Assert that the bar is rendered
|
||||
await expect(other.locator(".mx_InviteDialog_addressBar")).toBeVisible();
|
||||
@@ -88,7 +93,9 @@ test.describe("Invite dialog", function () {
|
||||
|
||||
await other.getByTestId("invite-dialog-input").fill(bot.credentials.userId);
|
||||
|
||||
await expect(other.locator(".mx_InviteDialog_tile_nameStack").getByText(bot.credentials.userId)).toBeVisible();
|
||||
await expect(
|
||||
other.locator(".mx_InviteDialog_tile_nameStack").getByText(bot.credentials.userId),
|
||||
).toBeVisible();
|
||||
await other.locator(".mx_InviteDialog_tile_nameStack").getByText(botName).click();
|
||||
|
||||
await expect(
|
||||
@@ -108,7 +115,10 @@ test.describe("Invite dialog", function () {
|
||||
// TODO: implement the test on room-header.spec.ts
|
||||
const roomHeader = page.locator(".mx_RoomHeader");
|
||||
await roomHeader.locator(".mx_RoomHeader_heading").hover();
|
||||
await expect(roomHeader.locator(".mx_RoomHeader_heading")).toHaveCSS("background-color", "rgba(0, 0, 0, 0)");
|
||||
await expect(roomHeader.locator(".mx_RoomHeader_heading")).toHaveCSS(
|
||||
"background-color",
|
||||
"rgba(0, 0, 0, 0)",
|
||||
);
|
||||
|
||||
// Send a message to invite the bots
|
||||
const composer = app.getComposer().locator("[contenteditable]");
|
||||
@@ -120,5 +130,6 @@ test.describe("Invite dialog", function () {
|
||||
|
||||
// Assert that the message is displayed at the bottom
|
||||
await expect(page.locator(".mx_EventTile_last").getByText("Hello")).toBeVisible();
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -10,7 +10,8 @@ import { Locator, Page } from "@playwright/test";
|
||||
|
||||
import { test, expect } from "../../element-web-test";
|
||||
|
||||
test.describe("Location sharing", () => {
|
||||
// Firefox headless lacks WebGL support https://bugzilla.mozilla.org/show_bug.cgi?id=1375585
|
||||
test.describe("Location sharing", { tag: "@no-firefox" }, () => {
|
||||
const selectLocationShareTypeOption = (page: Page, shareType: string): Locator => {
|
||||
return page.getByTestId(`share-location-option-${shareType}`);
|
||||
};
|
||||
|
||||
@@ -63,7 +63,7 @@ test.describe("Message rendering", () => {
|
||||
{ direction: "ltr", displayName: "Quentin" },
|
||||
{ direction: "rtl", displayName: "كوينتين" },
|
||||
].forEach(({ direction, displayName }) => {
|
||||
test.describe(`with ${direction} display name`, () => {
|
||||
test.describe(`with ${direction} display name`, { tag: "@screenshot" }, () => {
|
||||
test.use({
|
||||
displayName,
|
||||
room: async ({ user, app }, use) => {
|
||||
@@ -72,14 +72,18 @@ test.describe("Message rendering", () => {
|
||||
},
|
||||
});
|
||||
|
||||
test("should render a basic LTR text message", async ({ page, user, app, room }) => {
|
||||
test(
|
||||
"should render a basic LTR text message",
|
||||
{ tag: "@screenshot" },
|
||||
async ({ page, user, app, room }) => {
|
||||
await page.goto(`#/room/${room.roomId}`);
|
||||
|
||||
const msgTile = await sendMessage(page, "Hello, world!");
|
||||
await expect(msgTile).toMatchScreenshot(`basic-message-ltr-${direction}displayname.png`, {
|
||||
mask: [page.locator(".mx_MessageTimestamp")],
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test("should render an LTR emote", async ({ page, user, app, room }) => {
|
||||
await page.goto(`#/room/${room.roomId}`);
|
||||
|
||||
@@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import { test, expect, registerAccountMas } from ".";
|
||||
import { isDendrite } from "../../plugins/homeserver/dendrite";
|
||||
|
||||
test.describe("OIDC Aware", () => {
|
||||
test.describe("OIDC Aware", { tag: ["@no-firefox", "@no-webkit"] }, () => {
|
||||
test.skip(isDendrite, "does not yet support MAS");
|
||||
test.slow(); // trace recording takes a while here
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import { test, expect, registerAccountMas } from ".";
|
||||
import { isDendrite } from "../../plugins/homeserver/dendrite";
|
||||
import { ElementAppPage } from "../../pages/ElementAppPage.ts";
|
||||
|
||||
test.describe("OIDC Native", () => {
|
||||
test.describe("OIDC Native", { tag: ["@no-firefox", "@no-webkit"] }, () => {
|
||||
test.skip(isDendrite, "does not yet support MAS");
|
||||
test.slow(); // trace recording takes a while here
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ test.describe("permalinks", () => {
|
||||
displayName: "Alice",
|
||||
});
|
||||
|
||||
test("shoud render permalinks as expected", async ({ page, app, user, homeserver }) => {
|
||||
test("shoud render permalinks as expected", { tag: "@screenshot" }, async ({ page, app, user, homeserver }) => {
|
||||
const bob = new Bot(page, homeserver, { displayName: "Bob" });
|
||||
const charlotte = new Bot(page, homeserver, { displayName: "Charlotte" });
|
||||
await bob.prepareClient();
|
||||
|
||||
@@ -129,6 +129,7 @@ export class Helpers {
|
||||
const timelineMessage = this.page.locator(".mx_MTextBody", { hasText: message });
|
||||
await timelineMessage.click({ button: "right" });
|
||||
await this.page.getByRole("menuitem", { name: "Pin", exact: true }).click();
|
||||
await this.assertMessageInBanner(message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,20 +10,22 @@ import { test } from "./index";
|
||||
import { expect } from "../../element-web-test";
|
||||
|
||||
test.describe("Pinned messages", () => {
|
||||
test("should show the empty state when there are no pinned messages", async ({ page, app, room1, util }) => {
|
||||
test(
|
||||
"should show the empty state when there are no pinned messages",
|
||||
{ tag: "@screenshot" },
|
||||
async ({ page, app, room1, util }) => {
|
||||
await util.goTo(room1);
|
||||
await util.openRoomInfo();
|
||||
await util.assertPinnedCountInRoomInfo(0);
|
||||
await util.openPinnedMessagesList();
|
||||
await util.assertEmptyPinnedMessagesList();
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test("should pin one message and to have the pinned message badge in the timeline", async ({
|
||||
page,
|
||||
app,
|
||||
room1,
|
||||
util,
|
||||
}) => {
|
||||
test(
|
||||
"should pin one message and to have the pinned message badge in the timeline",
|
||||
{ tag: "@screenshot" },
|
||||
async ({ page, app, room1, util }) => {
|
||||
await util.goTo(room1);
|
||||
await util.receiveMessages(room1, ["Msg1"]);
|
||||
await util.pinMessages(["Msg1"]);
|
||||
@@ -38,7 +40,8 @@ test.describe("Pinned messages", () => {
|
||||
}
|
||||
`,
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test("should pin messages and show them in the room info panel", async ({ page, app, room1, util }) => {
|
||||
await util.goTo(room1);
|
||||
@@ -73,7 +76,7 @@ test.describe("Pinned messages", () => {
|
||||
await util.assertPinnedCountInRoomInfo(2);
|
||||
});
|
||||
|
||||
test("should unpin all messages", async ({ page, app, room1, util }) => {
|
||||
test("should unpin all messages", { tag: "@screenshot" }, async ({ page, app, room1, util }) => {
|
||||
await util.goTo(room1);
|
||||
await util.receiveMessages(room1, ["Msg1", "Msg2", "Msg3", "Msg4"]);
|
||||
await util.pinMessages(["Msg1", "Msg2", "Msg4"]);
|
||||
@@ -98,7 +101,7 @@ test.describe("Pinned messages", () => {
|
||||
await util.assertPinnedCountInRoomInfo(0);
|
||||
});
|
||||
|
||||
test("should display one message in the banner", async ({ page, app, room1, util }) => {
|
||||
test("should display one message in the banner", { tag: "@screenshot" }, async ({ page, app, room1, util }) => {
|
||||
await util.goTo(room1);
|
||||
await util.receiveMessages(room1, ["Msg1"]);
|
||||
await util.pinMessages(["Msg1"]);
|
||||
@@ -106,7 +109,7 @@ test.describe("Pinned messages", () => {
|
||||
await expect(util.getBanner()).toMatchScreenshot("pinned-message-banner-1-Msg1.png");
|
||||
});
|
||||
|
||||
test("should display 2 messages in the banner", async ({ page, app, room1, util }) => {
|
||||
test("should display 2 messages in the banner", { tag: "@screenshot" }, async ({ page, app, room1, util }) => {
|
||||
await util.goTo(room1);
|
||||
await util.receiveMessages(room1, ["Msg1", "Msg2"]);
|
||||
await util.pinMessages(["Msg1", "Msg2"]);
|
||||
@@ -123,7 +126,7 @@ test.describe("Pinned messages", () => {
|
||||
await expect(util.getBanner()).toMatchScreenshot("pinned-message-banner-2-Msg2.png");
|
||||
});
|
||||
|
||||
test("should display 4 messages in the banner", async ({ page, app, room1, util }) => {
|
||||
test("should display 4 messages in the banner", { tag: "@screenshot" }, async ({ page, app, room1, util }) => {
|
||||
await util.goTo(room1);
|
||||
await util.receiveMessages(room1, ["Msg1", "Msg2", "Msg3", "Msg4"]);
|
||||
await util.pinMessages(["Msg1", "Msg2", "Msg3", "Msg4"]);
|
||||
|
||||
@@ -93,7 +93,7 @@ test.describe("Polls", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("should be creatable and votable", async ({ page, app, bot, user }) => {
|
||||
test("should be creatable and votable", { tag: "@screenshot" }, async ({ page, app, bot, user }) => {
|
||||
const roomId: string = await app.client.createRoom({});
|
||||
await app.client.inviteUser(roomId, bot.credentials.userId);
|
||||
await page.goto("/#/room/" + roomId);
|
||||
@@ -219,7 +219,10 @@ test.describe("Polls", () => {
|
||||
await expect(page.locator(".mx_ErrorDialog")).toBeAttached();
|
||||
});
|
||||
|
||||
test("should be displayed correctly in thread panel", async ({ page, app, user, bot, homeserver }) => {
|
||||
test(
|
||||
"should be displayed correctly in thread panel",
|
||||
{ tag: "@screenshot" },
|
||||
async ({ page, app, user, bot, homeserver }) => {
|
||||
const botCharlie = new Bot(page, homeserver, { displayName: "BotCharlie" });
|
||||
await botCharlie.prepareClient();
|
||||
|
||||
@@ -229,7 +232,9 @@ test.describe("Polls", () => {
|
||||
await page.goto("/#/room/" + roomId);
|
||||
|
||||
// wait until the bots joined
|
||||
await expect(page.getByText("BotBob and one other were invited and joined")).toBeAttached({ timeout: 10000 });
|
||||
await expect(page.getByText("BotBob and one other were invited and joined")).toBeAttached({
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
const locator = await app.openMessageComposerOptions();
|
||||
await locator.getByRole("menuitem", { name: "Poll" }).click();
|
||||
@@ -274,22 +279,30 @@ test.describe("Polls", () => {
|
||||
|
||||
// and thread view
|
||||
await expect(
|
||||
page.locator(".mx_ThreadView .mx_MPollBody_totalVotes").getByText("2 votes cast. Vote to see the results"),
|
||||
page
|
||||
.locator(".mx_ThreadView .mx_MPollBody_totalVotes")
|
||||
.getByText("2 votes cast. Vote to see the results"),
|
||||
).toBeAttached();
|
||||
|
||||
// Take snapshots of poll on ThreadView
|
||||
await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Bubble);
|
||||
await expect(page.locator(".mx_ThreadView .mx_EventTile[data-layout='bubble']").first()).toBeVisible();
|
||||
await expect(page.locator(".mx_ThreadView")).toMatchScreenshot("ThreadView_with_a_poll_on_bubble_layout.png", {
|
||||
await expect(page.locator(".mx_ThreadView")).toMatchScreenshot(
|
||||
"ThreadView_with_a_poll_on_bubble_layout.png",
|
||||
{
|
||||
mask: [page.locator(".mx_MessageTimestamp")],
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Group);
|
||||
await expect(page.locator(".mx_ThreadView .mx_EventTile[data-layout='group']").first()).toBeVisible();
|
||||
|
||||
await expect(page.locator(".mx_ThreadView")).toMatchScreenshot("ThreadView_with_a_poll_on_group_layout.png", {
|
||||
await expect(page.locator(".mx_ThreadView")).toMatchScreenshot(
|
||||
"ThreadView_with_a_poll_on_group_layout.png",
|
||||
{
|
||||
mask: [page.locator(".mx_MessageTimestamp")],
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
const roomViewLocator = page.locator(".mx_RoomView_body");
|
||||
// vote 'Maybe' in the main timeline poll
|
||||
@@ -321,5 +334,6 @@ test.describe("Polls", () => {
|
||||
|
||||
// and in thread view tile
|
||||
await expectVoteCounts(page.locator(".mx_ThreadView"));
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { test } from ".";
|
||||
|
||||
test.describe("Read receipts", () => {
|
||||
test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
||||
test.describe("editing messages", () => {
|
||||
test.describe("in threads", () => {
|
||||
test("An edit of a threaded message makes the room unread", async ({
|
||||
|
||||
@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { test } from ".";
|
||||
|
||||
test.describe("Read receipts", () => {
|
||||
test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
||||
test.describe("editing messages", () => {
|
||||
test.describe("in the main timeline", () => {
|
||||
test("Editing a message leaves a room read", async ({ roomAlpha: room1, roomBeta: room2, util, msg }) => {
|
||||
|
||||
@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { test } from ".";
|
||||
|
||||
test.describe("Read receipts", () => {
|
||||
test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
||||
test.describe("editing messages", () => {
|
||||
test.describe("thread roots", () => {
|
||||
test("An edit of a thread root leaves the room read", async ({
|
||||
|
||||
@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { customEvent, many, test } from ".";
|
||||
|
||||
test.describe("Read receipts", () => {
|
||||
test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
||||
test.describe("Ignored events", () => {
|
||||
test("If all events after receipt are unimportant, the room is read", async ({
|
||||
roomAlpha: room1,
|
||||
|
||||
@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { test } from ".";
|
||||
|
||||
test.describe("Read receipts", () => {
|
||||
test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
||||
test.describe("Message ordering", () => {
|
||||
test.describe("in the main timeline", () => {
|
||||
test.fixme(
|
||||
|
||||
@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { test } from ".";
|
||||
|
||||
test.describe("Read receipts", () => {
|
||||
test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
||||
test.describe("messages with missing referents", () => {
|
||||
test.fixme(
|
||||
"A message in an unknown thread is not visible and the room is read",
|
||||
|
||||
@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { many, test } from ".";
|
||||
|
||||
test.describe("Read receipts", () => {
|
||||
test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
||||
test.describe("new messages", () => {
|
||||
test.describe("in threads", () => {
|
||||
test("Receiving a message makes a room unread", async ({
|
||||
|
||||
@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { many, test } from ".";
|
||||
|
||||
test.describe("Read receipts", () => {
|
||||
test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
||||
test.describe("new messages", () => {
|
||||
test.describe("in the main timeline", () => {
|
||||
test("Receiving a message makes a room unread", async ({
|
||||
|
||||
@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { many, test } from ".";
|
||||
|
||||
test.describe("Read receipts", () => {
|
||||
test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
||||
test.describe("new messages", () => {
|
||||
test.describe("thread roots", () => {
|
||||
test("Reading a thread root does not mark the thread as read", async ({
|
||||
|
||||
@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { test } from ".";
|
||||
|
||||
test.describe("Read receipts", () => {
|
||||
test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
||||
test.describe("Notifications", () => {
|
||||
test.describe("in the main timeline", () => {
|
||||
test.fixme("A new message that mentions me shows a notification", () => {});
|
||||
|
||||
@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { test, expect } from ".";
|
||||
|
||||
test.describe("Read receipts", () => {
|
||||
test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
||||
test.describe("reactions", () => {
|
||||
test.describe("in threads", () => {
|
||||
test("A reaction to a threaded message does not make the room unread", async ({
|
||||
|
||||
@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { test } from ".";
|
||||
|
||||
test.describe("Read receipts", () => {
|
||||
test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
||||
test.describe("reactions", () => {
|
||||
test.describe("in the main timeline", () => {
|
||||
test("Receiving a reaction to a message does not make a room unread", async ({
|
||||
|
||||
@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { test } from ".";
|
||||
|
||||
test.describe("Read receipts", () => {
|
||||
test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
||||
test.describe("reactions", () => {
|
||||
test.describe("thread roots", () => {
|
||||
test("A reaction to a thread root does not make the room unread", async ({
|
||||
|
||||
@@ -13,7 +13,7 @@ import { ElementAppPage } from "../../pages/ElementAppPage";
|
||||
import { Bot } from "../../pages/bot";
|
||||
import { test } from ".";
|
||||
|
||||
test.describe("Read receipts", () => {
|
||||
test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
||||
test.use({
|
||||
displayName: "Mae",
|
||||
botCreateOpts: { displayName: "Other User" },
|
||||
|
||||
@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { test } from ".";
|
||||
|
||||
test.describe("Read receipts", () => {
|
||||
test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
||||
test.describe("redactions", () => {
|
||||
test.describe("in threads", () => {
|
||||
test("Redacting the threaded message pointed to by my receipt leaves the room read", async ({
|
||||
|
||||
@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { test } from ".";
|
||||
|
||||
test.describe("Read receipts", () => {
|
||||
test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
||||
test.describe("redactions", () => {
|
||||
test.describe("in the main timeline", () => {
|
||||
test("Redacting the message pointed to by my receipt leaves the room read", async ({
|
||||
|
||||
@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { test } from ".";
|
||||
|
||||
test.describe("Read receipts", () => {
|
||||
test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
||||
test.describe("redactions", () => {
|
||||
test.describe("thread roots", () => {
|
||||
test("Redacting a thread root after it was read leaves the room read", async ({
|
||||
|
||||
@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { test } from ".";
|
||||
|
||||
test.describe("Read receipts", () => {
|
||||
test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
||||
test.describe("Room list order", () => {
|
||||
test("Rooms with unread messages appear at the top of room list if 'unread first' is selected", async ({
|
||||
roomAlpha: room1,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user