Merge branch 'develop' into dbkr/refactor_createcrosssigningdialog

This commit is contained in:
David Baker
2024-10-17 18:31:23 +01:00
committed by GitHub
26 changed files with 110 additions and 101 deletions
+1 -1
View File
@@ -10,7 +10,7 @@ on:
jobs:
backport:
name: Backport
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
# Only react to merged PRs for security reasons.
# See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target.
if: >
+5 -5
View File
@@ -18,15 +18,15 @@ jobs:
fail-fast: false
matrix:
image:
- ubuntu-latest
- windows-latest
- macos-latest
- ubuntu-24.04
- windows-2022
- macos-14
isDevelop:
- ${{ github.event_name == 'push' && github.ref_name == 'develop' }}
# Skip the ubuntu-latest build for the develop branch as the dedicated CD build_develop workflow handles that
# Skip the ubuntu-24.04 build for the develop branch as the dedicated CD build_develop workflow handles that
exclude:
- isDevelop: true
image: ubuntu-latest
image: ubuntu-24.04
runs-on: ${{ matrix.image }}
defaults:
run:
+1 -1
View File
@@ -7,7 +7,7 @@ jobs:
build:
name: Build package
environment: packages.element.io
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
env:
R2_INCOMING_BUCKET: ${{ vars.R2_INCOMING_BUCKET }}
R2_URL: ${{ vars.CF_R2_S3_API }}
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
name: "Build & Deploy develop.element.io"
# Only respect triggers from our develop branch, ignore that of forks
if: github.repository == 'element-hq/element-web'
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
environment: develop
env:
R2_BUCKET: "element-web-develop"
+1 -1
View File
@@ -13,7 +13,7 @@ permissions:
jobs:
buildx:
name: Docker Buildx
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
environment: dockerhub
strategy:
fail-fast: false
+2 -2
View File
@@ -17,7 +17,7 @@ concurrency:
jobs:
build:
name: GitHub Pages
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- name: Fetch element-desktop
uses: actions/checkout@v4
@@ -99,7 +99,7 @@ jobs:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
needs: build
steps:
- name: Deploy to GitHub Pages
+1 -1
View File
@@ -7,7 +7,7 @@ on:
jobs:
tidy:
name: Tidy closed issues
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/github-script@v7
id: main
+1 -1
View File
@@ -9,7 +9,7 @@ concurrency: ${{ github.workflow }}
jobs:
bot:
name: Pending reviews bot
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
environment: Matrix
env:
URL: "https://github.com/pulls?q=is%3Apr+is%3Aopen+repo%3Amatrix-org%2Fmatrix-js-sdk+repo%3Amatrix-org%2Fmatrix-react-sdk+repo%3Aelement-hq%2Felement-web+repo%3Aelement-hq%2Felement-desktop+review-requested%3A%40me+sort%3Aupdated-desc+"
+2 -2
View File
@@ -27,7 +27,7 @@ jobs:
notify-downstream:
name: Trigger release drafter downstream
needs: release
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- name: Notify element-desktop repo that element-web release has completed to re-trigger release-drafter
uses: benc-uk/workflow-dispatch@e2e5e9a103e331dad343f381a29e654aea3cf8fc # v1
@@ -41,7 +41,7 @@ jobs:
check:
name: Post release checks
needs: release
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- name: Wait for dockerhub
uses: t3chguy/wait-on-check-action@18541021811b56544d90e0f073401c2b99e249d6 # fork
+1 -1
View File
@@ -19,7 +19,7 @@ on:
default: true
jobs:
prepare:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- name: Checkout Element Desktop
uses: actions/checkout@v4
+5 -5
View File
@@ -19,7 +19,7 @@ env:
jobs:
ts_lint:
name: "Typescript Syntax Check"
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
@@ -81,7 +81,7 @@ jobs:
js_lint:
name: "ESLint"
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
@@ -99,7 +99,7 @@ jobs:
style_lint:
name: "Style Lint"
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
@@ -117,7 +117,7 @@ jobs:
workflow_lint:
name: "Workflow Lint"
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
@@ -135,7 +135,7 @@ jobs:
analyse_dead_code:
name: "Analyse Dead Code"
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
+1 -1
View File
@@ -6,7 +6,7 @@ on:
jobs:
web-app-team:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
if: |
contains(github.event.issue.assignees.*.login, 't3chguy') ||
contains(github.event.issue.assignees.*.login, 'andybalaam') ||
+1 -1
View File
@@ -6,7 +6,7 @@ on:
jobs:
automate-project-columns:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/add-to-project@main
with:
+10 -10
View File
@@ -11,7 +11,7 @@ on:
jobs:
apply_Z-Labs_label:
name: Add Z-Labs label for features behind labs flags
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
if: >
contains(github.event.issue.labels.*.name, 'A-Maths') ||
contains(github.event.issue.labels.*.name, 'A-Location-Sharing') ||
@@ -37,7 +37,7 @@ jobs:
apply_Help-Wanted_label:
name: Add "Help Wanted" label to all "good first issue" and Hacktoberfest
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
if: >
contains(github.event.issue.labels.*.name, 'good first issue') ||
contains(github.event.issue.labels.*.name, 'Hacktoberfest')
@@ -54,7 +54,7 @@ jobs:
move_needs_info_issues:
name: X-Needs-Info issues to Need info column on triage board
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
if: >
contains(github.event.issue.labels.*.name, 'X-Needs-Info')
steps:
@@ -77,7 +77,7 @@ jobs:
move_flakey_test_issues:
name: Z-Flaky-Test issues to Sized for maintainer column on triage board
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
if: >
contains(github.event.issue.labels.*.name, 'Z-Flaky-Test')
steps:
@@ -100,7 +100,7 @@ jobs:
add_priority_design_issues_to_project:
name: P1 X-Needs-Design to Design project board
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
if: >
contains(github.event.issue.labels.*.name, 'X-Needs-Design') &&
(contains(github.event.issue.labels.*.name, 'S-Critical') &&
@@ -117,7 +117,7 @@ jobs:
add_product_issues:
name: X-Needs-Product to product project board
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
if: >
contains(github.event.issue.labels.*.name, 'X-Needs-Product')
steps:
@@ -128,7 +128,7 @@ jobs:
Search_issues_to_board:
name: Search issues to project board
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
if: >
contains(github.event.issue.labels.*.name, 'A-New-Search-Experience')
steps:
@@ -139,7 +139,7 @@ jobs:
voip:
name: Add labelled issues to VoIP project board
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
if: >
contains(github.event.issue.labels.*.name, 'Team: VoIP')
steps:
@@ -150,7 +150,7 @@ jobs:
verticals_feature:
name: Add labelled issues to Verticals Feature project
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
if: >
contains(github.event.issue.labels.*.name, 'Team: Verticals Feature')
steps:
@@ -161,7 +161,7 @@ jobs:
tech_debt:
name: Add labelled issues to tech debt project
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
if: >
contains(github.event.issue.labels.*.name, 'A-Developer-Experience') ||
contains(github.event.issue.labels.*.name, 'A-Documentation') ||
@@ -6,7 +6,7 @@ on:
jobs:
add_design_pr_to_project:
name: Move PRs asking for design review to the design board
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: octokit/graphql-action@v2.x
id: find_team_members
@@ -73,7 +73,7 @@ jobs:
add_product_pr_to_project:
name: Move PRs asking for design review to the design board
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: octokit/graphql-action@v2.x
id: find_team_members
@@ -4,7 +4,7 @@ on:
- cron: "30 1 * * *"
jobs:
close:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
permissions:
actions: write
issues: write
+2 -2
View File
@@ -7,7 +7,7 @@ on:
jobs:
Move_Unabeled_Issue_On_Project_Board:
name: Move no longer X-Needs-Info issues to Triaged
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
if: >
${{
!contains(github.event.issue.labels.*.name, 'X-Needs-Info') }}
@@ -44,7 +44,7 @@ jobs:
remove_Z-Labs_label:
name: Remove Z-Labs label when features behind labs flags are removed
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
if: >
!(contains(github.event.issue.labels.*.name, 'A-Maths') ||
contains(github.event.issue.labels.*.name, 'A-Message-Pinning') ||
+1 -1
View File
@@ -6,7 +6,7 @@ on:
- cron: "0 3 * * 0" # 3am every Sunday
jobs:
update:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
+4 -4
View File
@@ -18,7 +18,7 @@ concurrency: ${{ github.workflow }}
jobs:
bot:
name: Release topic update
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
environment: Matrix
steps:
- uses: actions/github-script@v7
@@ -56,7 +56,7 @@ jobs:
headers,
body: "{}",
});
let res = await fetch(apiUrl, {
method: "GET",
headers,
@@ -69,7 +69,7 @@ jobs:
const data = await res.json();
console.log(roomId, "got event", data);
const topic = data.topic.replace(regex, releaseTopic);
if (topic === data.topic) {
console.log(roomId, "nothing to do");
@@ -89,7 +89,7 @@ jobs:
}),
headers,
});
if (res.ok) {
console.log(roomId, "topic updated:", topic);
} else {
@@ -15,6 +15,9 @@ test.describe("Landmark navigation tests", () => {
});
test("without any rooms", async ({ page, homeserver, app, user }) => {
// sometimes the space button doesn't appear right away
await expect(page.locator(".mx_SpaceButton_active")).toBeVisible();
/**
* Without any rooms, there is no tile in the roomlist to be focused.
* So the next landmark in the list should be focused instead.
+1 -1
View File
@@ -217,7 +217,7 @@ test.describe("Login", () => {
const h1 = await page.getByRole("heading", { name: "Verify this device", level: 1 });
await expect(h1).toBeVisible();
expect(h1.locator(".mx_CompleteSecurity_skip")).not.toBeVisible();
await expect(h1.locator(".mx_CompleteSecurity_skip")).toHaveCount(0);
});
});
});
@@ -140,4 +140,51 @@ test.describe("Account user settings tab", () => {
await expect(page.locator(".mx_UserMenu .mx_BaseAvatar").getByText("A")).toBeVisible(); // Alice
await expect(page.locator(".mx_RoomView_wrapper .mx_BaseAvatar").getByText("A")).toBeVisible(); // Alice
});
// ported to a playwright test because the jest test was very flakey for no obvious reason
test("should display an error if the code is incorrect when adding a phone number", async ({ uut, page }) => {
const dummyUrl = "https://nowhere.dummy/_matrix/client/unstable/add_threepid/msisdn/submit_token";
await page.route(
`**/_matrix/client/v3/account/3pid/msisdn/requestToken`,
async (route) => {
await route.fulfill({
json: {
success: true,
sid: "1",
msisdn: "447700900000",
intl_fmt: "+44 7700 900000",
submit_url: dummyUrl,
},
});
},
{ times: 1 },
);
await page.route(
dummyUrl,
async (route) => {
await route.fulfill({
status: 400,
json: {
errcode: "M_THREEPID_AUTH_FAILED",
error: "That code is definitely wrong",
},
});
},
{ times: 1 },
);
const phoneSection = page.getByTestId("mx_AccountPhoneNumbers");
await phoneSection.getByRole("textbox", { name: "Phone Number" }).fill("07700900000");
await phoneSection.getByRole("button", { name: "Add" }).click();
await phoneSection
.getByRole("textbox", { name: "Verification code" })
.fill("A small eurasian field mouse dancing the paso doble");
await phoneSection.getByRole("button", { name: "Continue" }).click();
await expect(page.getByRole("heading", { name: "Unable to verify phone number." })).toBeVisible();
});
});
@@ -106,6 +106,10 @@ type IProps<T> = WithKeyFunction<T> & {
AdditionalOptions?: FunctionComponent<AdditionalOptionsProps>;
};
function calculateKey<T>(value: T, toKey: ((key: T) => Key) | undefined): Key {
return toKey ? toKey(value) : (value as Key);
}
export function GenericDropdownMenu<T>({
value,
onChange,
@@ -119,23 +123,24 @@ export function GenericDropdownMenu<T>({
}: IProps<T>): JSX.Element {
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu<HTMLElement>();
const valueKey = calculateKey(value, toKey);
const selected: GenericDropdownMenuItem<T> | undefined = options
.flatMap((it) => (isGenericDropdownMenuGroup(it) ? [it, ...it.options] : [it]))
.find((option) => (toKey ? toKey(option.key) === toKey(value) : option.key === value));
.find((option) => calculateKey(option.key, toKey) === valueKey);
let contextMenuOptions: JSX.Element;
if (options && isGenericDropdownMenuGroupArray(options)) {
contextMenuOptions = (
<>
{options.map((group) => (
<GenericDropdownMenuGroup
key={toKey?.(group.key) ?? (group.key as Key)}
key={calculateKey(group.key, toKey)}
label={group.label}
description={group.description}
adornment={group.adornment}
>
{group.options.map((option) => (
<GenericDropdownMenuOption
key={toKey?.(option.key) ?? (option.key as Key)}
key={calculateKey(option.key, toKey)}
label={option.label}
description={option.description}
onClick={(ev: ButtonEvent) => {
@@ -144,7 +149,7 @@ export function GenericDropdownMenu<T>({
onClose?.(ev);
}}
adornment={option.adornment}
isSelected={option === selected}
isSelected={calculateKey(option.key, toKey) === valueKey}
/>
))}
</GenericDropdownMenuGroup>
@@ -156,7 +161,7 @@ export function GenericDropdownMenu<T>({
<>
{options.map((option) => (
<GenericDropdownMenuOption
key={toKey?.(option.key) ?? (option.key as Key)}
key={calculateKey(option.key, toKey)}
label={option.label}
description={option.description}
onClick={(ev: ButtonEvent) => {
@@ -165,7 +170,7 @@ export function GenericDropdownMenu<T>({
onClose?.(ev);
}}
adornment={option.adornment}
isSelected={option === selected}
isSelected={calculateKey(option.key, toKey) === valueKey}
/>
))}
</>
@@ -80,6 +80,7 @@ export default class RightPanelStore extends ReadyWatchingStore {
if (this.currentCard.phase !== RightPanelPhases.RoomSummary) {
this.setCard({ phase: RightPanelPhases.RoomSummary, state: { focusRoomSearch: true } });
}
this.show(null);
}
}
}
@@ -40,6 +40,8 @@ export interface IRightPanelCardStateStored {
initialEventId?: string;
isInitialEventHighlighted?: boolean;
initialEventScrollIntoView?: boolean;
// room summary card
focusRoomSearch?: boolean;
}
export interface IRightPanelCard {
@@ -85,6 +87,7 @@ export function convertCardToStore(panelState: IRightPanelCard): IRightPanelCard
memberInfoEventId: !!state?.memberInfoEvent?.getId() ? state.memberInfoEvent.getId() : undefined,
initialEventId: !!state?.initialEvent?.getId() ? state.initialEvent.getId() : undefined,
memberId: !!state?.member?.userId ? state.member.userId : undefined,
focusRoomSearch: state.focusRoomSearch,
};
return { state: stateStored, phase: panelState.phase };
@@ -105,6 +108,7 @@ function convertStoreToCard(panelStateStore: IRightPanelCardStored, room: Room):
: undefined,
initialEvent: !!stateStored?.initialEventId ? room.findEventById(stateStored.initialEventId) : undefined,
member: (!!stateStored?.memberId && room.getMember(stateStored.memberId)) || undefined,
focusRoomSearch: stateStored?.focusRoomSearch,
};
return { state: state, phase: panelStateStore.phase };
@@ -254,57 +254,6 @@ describe("AddRemoveThreepids", () => {
expect(onChangeFn).toHaveBeenCalled();
}, 10000);
it("should display an error if the code is incorrect", async () => {
const onChangeFn = jest.fn();
const createDialogFn = jest.spyOn(Modal, "createDialog");
mocked(client.requestAdd3pidMsisdnToken).mockResolvedValue({
sid: "1",
msisdn: PHONE1.address,
intl_fmt: "+" + PHONE1.address,
success: true,
submit_url: "https://example.dummy",
});
render(
<AddRemoveThreepids
mode="hs"
medium={ThreepidMedium.Phone}
threepids={[]}
isLoading={false}
onChange={onChangeFn}
/>,
{
wrapper: clientProviderWrapper,
},
);
const input = screen.getByRole("textbox", { name: "Phone Number" });
await userEvent.type(input, PHONE1_LOCALNUM);
const countryDropdown = screen.getByRole("button", { name: /Country Dropdown/ });
await userEvent.click(countryDropdown);
const gbOption = screen.getByRole("option", { name: "🇬🇧 United Kingdom (+44)" });
await userEvent.click(gbOption);
const addButton = screen.getByRole("button", { name: /Add/ });
await userEvent.click(addButton);
mocked(client).addThreePidOnly.mockRejectedValueOnce(new Error("Unauthorized"));
const verificationInput = screen.getByRole("textbox", { name: "Verification code" });
await userEvent.type(verificationInput, "123457");
const continueButton = screen.getByRole("button", { name: /Continue/ });
await userEvent.click(continueButton);
expect(createDialogFn).toHaveBeenCalledWith(expect.anything(), {
description: "Unauthorized",
title: "Unable to verify phone number.",
});
expect(onChangeFn).not.toHaveBeenCalled();
});
it("should remove an email address", async () => {
const onChangeFn = jest.fn();
render(