Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit b09b52d

Browse files
authored
Merge branch 'develop' into weeman1337/fix-confirm-reset-password-twice
2 parents bad3d16 + 70d3d03 commit b09b52d

File tree

3 files changed

+77
-41
lines changed

3 files changed

+77
-41
lines changed

src/PasswordReset.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ export default class PasswordReset {
104104
);
105105
}
106106

107+
public setLogoutDevices(logoutDevices: boolean): void {
108+
this.logoutDevices = logoutDevices;
109+
}
110+
107111
public async setNewPassword(password: string): Promise<void> {
108112
this.password = password;
109113
await this.checkEmailLinkClicked();

src/components/structures/auth/ForgotPassword.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ export default class ForgotPassword extends React.Component<Props, State> {
258258
}
259259

260260
this.phase = Phase.ResettingPassword;
261+
this.reset.setLogoutDevices(this.state.logoutDevices);
261262

262263
try {
263264
await this.reset.setNewPassword(this.state.password);

test/components/structures/auth/ForgotPassword-test.tsx

Lines changed: 72 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,17 @@ describe("<ForgotPassword>", () => {
4949
});
5050
};
5151

52-
const clickButton = async (label: string): Promise<void> => {
52+
const click = async (element: Element): Promise<void> => {
5353
await act(async () => {
54-
await userEvent.click(screen.getByText(label), { delay: null });
54+
await userEvent.click(element, { delay: null });
5555
});
5656
};
5757

58+
const waitForDialog = async (): Promise<void> => {
59+
await flushPromisesWithFakeTimers();
60+
await flushPromisesWithFakeTimers();
61+
};
62+
5863
const itShouldCloseTheDialogAndShowThePasswordInput = (): void => {
5964
it("should close the dialog and show the password input", () => {
6065
expect(screen.queryByText("Verify your email to continue")).not.toBeInTheDocument();
@@ -121,17 +126,17 @@ describe("<ForgotPassword>", () => {
121126
});
122127
});
123128

124-
describe("when clicking »Sign in instead«", () => {
129+
describe("and clicking »Sign in instead«", () => {
125130
beforeEach(async () => {
126-
await clickButton("Sign in instead");
131+
await click(screen.getByText("Sign in instead"));
127132
});
128133

129134
it("should call onLoginClick()", () => {
130135
expect(onLoginClick).toHaveBeenCalled();
131136
});
132137
});
133138

134-
describe("when entering a non-email value", () => {
139+
describe("and entering a non-email value", () => {
135140
beforeEach(async () => {
136141
await typeIntoField("Email address", "not en email");
137142
});
@@ -141,27 +146,27 @@ describe("<ForgotPassword>", () => {
141146
});
142147
});
143148

144-
describe("when submitting an unknown email", () => {
149+
describe("and submitting an unknown email", () => {
145150
beforeEach(async () => {
146151
await typeIntoField("Email address", testEmail);
147152
mocked(client).requestPasswordEmailToken.mockRejectedValue({
148153
errcode: "M_THREEPID_NOT_FOUND",
149154
});
150-
await clickButton("Send email");
155+
await click(screen.getByText("Send email"));
151156
});
152157

153158
it("should show an email not found message", () => {
154159
expect(screen.getByText("This email address was not found")).toBeInTheDocument();
155160
});
156161
});
157162

158-
describe("when a connection error occurs", () => {
163+
describe("and a connection error occurs", () => {
159164
beforeEach(async () => {
160165
await typeIntoField("Email address", testEmail);
161166
mocked(client).requestPasswordEmailToken.mockRejectedValue({
162167
name: "ConnectionError",
163168
});
164-
await clickButton("Send email");
169+
await click(screen.getByText("Send email"));
165170
});
166171

167172
it("should show an info about that", () => {
@@ -174,7 +179,7 @@ describe("<ForgotPassword>", () => {
174179
});
175180
});
176181

177-
describe("when the server liveness check fails", () => {
182+
describe("and the server liveness check fails", () => {
178183
beforeEach(async () => {
179184
await typeIntoField("Email address", testEmail);
180185
mocked(AutoDiscoveryUtils.validateServerConfigWithStaticUrls).mockRejectedValue({});
@@ -183,21 +188,21 @@ describe("<ForgotPassword>", () => {
183188
serverIsAlive: false,
184189
serverDeadError: "server down",
185190
});
186-
await clickButton("Send email");
191+
await click(screen.getByText("Send email"));
187192
});
188193

189194
it("should show the server error", () => {
190195
expect(screen.queryByText("server down")).toBeInTheDocument();
191196
});
192197
});
193198

194-
describe("when submitting an known email", () => {
199+
describe("and submitting an known email", () => {
195200
beforeEach(async () => {
196201
await typeIntoField("Email address", testEmail);
197202
mocked(client).requestPasswordEmailToken.mockResolvedValue({
198203
sid: testSid,
199204
});
200-
await clickButton("Send email");
205+
await click(screen.getByText("Send email"));
201206
});
202207

203208
it("should send the mail and show the check email view", () => {
@@ -210,19 +215,19 @@ describe("<ForgotPassword>", () => {
210215
expect(screen.getByText(testEmail)).toBeInTheDocument();
211216
});
212217

213-
describe("when clicking re-enter email", () => {
218+
describe("and clicking »Re-enter email address«", () => {
214219
beforeEach(async () => {
215-
await clickButton("Re-enter email address");
220+
await click(screen.getByText("Re-enter email address"));
216221
});
217222

218223
it("go back to the email input", () => {
219224
expect(screen.queryByText("Enter your email to reset password")).toBeInTheDocument();
220225
});
221226
});
222227

223-
describe("when clicking resend email", () => {
228+
describe("and clicking »Resend«", () => {
224229
beforeEach(async () => {
225-
await userEvent.click(screen.getByText("Resend"), { delay: null });
230+
await click(screen.getByText("Resend"));
226231
// the message is shown after some time
227232
jest.advanceTimersByTime(500);
228233
});
@@ -237,16 +242,16 @@ describe("<ForgotPassword>", () => {
237242
});
238243
});
239244

240-
describe("when clicking next", () => {
245+
describe("and clicking »Next«", () => {
241246
beforeEach(async () => {
242-
await clickButton("Next");
247+
await click(screen.getByText("Next"));
243248
});
244249

245250
it("should show the password input view", () => {
246251
expect(screen.getByText("Reset your password")).toBeInTheDocument();
247252
});
248253

249-
describe("when entering different passwords", () => {
254+
describe("and entering different passwords", () => {
250255
beforeEach(async () => {
251256
await typeIntoField("New Password", testPassword);
252257
await typeIntoField("Confirm new password", testPassword + "asd");
@@ -257,7 +262,7 @@ describe("<ForgotPassword>", () => {
257262
});
258263
});
259264

260-
describe("when entering a new password", () => {
265+
describe("and entering a new password", () => {
261266
beforeEach(async () => {
262267
mocked(client.setPassword).mockRejectedValue({ httpStatus: 401 });
263268
await typeIntoField("New Password", testPassword);
@@ -273,7 +278,7 @@ describe("<ForgotPassword>", () => {
273278
retry_after_ms: (13 * 60 + 37) * 1000,
274279
},
275280
});
276-
await clickButton("Reset password");
281+
await click(screen.getByText("Reset password"));
277282
});
278283

279284
it("should show the rate limit error message", () => {
@@ -316,10 +321,8 @@ describe("<ForgotPassword>", () => {
316321

317322
describe("and submitting it", () => {
318323
beforeEach(async () => {
319-
await clickButton("Reset password");
320-
// double flush promises for the modal to appear
321-
await flushPromisesWithFakeTimers();
322-
await flushPromisesWithFakeTimers();
324+
await click(screen.getByText("Reset password"));
325+
await waitForDialog();
323326
});
324327

325328
it("should send the new password and show the click validation link dialog", () => {
@@ -347,33 +350,25 @@ describe("<ForgotPassword>", () => {
347350
await act(async () => {
348351
await userEvent.click(screen.getByTestId("dialog-background"), { delay: null });
349352
});
350-
// double flush promises for the modal to disappear
351-
await flushPromisesWithFakeTimers();
352-
await flushPromisesWithFakeTimers();
353+
await waitForDialog();
353354
});
354355

355356
itShouldCloseTheDialogAndShowThePasswordInput();
356357
});
357358

358359
describe("and dismissing the dialog", () => {
359360
beforeEach(async () => {
360-
await act(async () => {
361-
await userEvent.click(screen.getByLabelText("Close dialog"), { delay: null });
362-
});
363-
// double flush promises for the modal to disappear
364-
await flushPromisesWithFakeTimers();
365-
await flushPromisesWithFakeTimers();
361+
await click(screen.getByLabelText("Close dialog"));
362+
await waitForDialog();
366363
});
367364

368365
itShouldCloseTheDialogAndShowThePasswordInput();
369366
});
370367

371-
describe("when clicking re-enter email", () => {
368+
describe("and clicking »Re-enter email address«", () => {
372369
beforeEach(async () => {
373-
await clickButton("Re-enter email address");
374-
// double flush promises for the modal to disappear
375-
await flushPromisesWithFakeTimers();
376-
await flushPromisesWithFakeTimers();
370+
await click(screen.getByText("Re-enter email address"));
371+
await waitForDialog();
377372
});
378373

379374
it("should close the dialog and go back to the email input", () => {
@@ -382,7 +377,7 @@ describe("<ForgotPassword>", () => {
382377
});
383378
});
384379

385-
describe("when validating the link from the mail", () => {
380+
describe("and validating the link from the mail", () => {
386381
beforeEach(async () => {
387382
mocked(client.setPassword).mockResolvedValue({});
388383
// be sure the next set password attempt was sent
@@ -400,6 +395,42 @@ describe("<ForgotPassword>", () => {
400395
});
401396
});
402397
});
398+
399+
describe("and clicking »Sign out of all devices« and »Reset password«", () => {
400+
beforeEach(async () => {
401+
await click(screen.getByText("Sign out of all devices"));
402+
await click(screen.getByText("Reset password"));
403+
await waitForDialog();
404+
});
405+
406+
it("should show the sign out warning dialog", async () => {
407+
expect(
408+
screen.getByText(
409+
"Signing out your devices will delete the message encryption keys stored on them, making encrypted chat history unreadable.",
410+
),
411+
).toBeInTheDocument();
412+
413+
// confirm dialog
414+
await click(screen.getByText("Continue"));
415+
416+
// expect setPassword with logoutDevices = true
417+
expect(client.setPassword).toHaveBeenCalledWith(
418+
{
419+
type: "m.login.email.identity",
420+
threepid_creds: {
421+
client_secret: expect.any(String),
422+
sid: testSid,
423+
},
424+
threepidCreds: {
425+
client_secret: expect.any(String),
426+
sid: testSid,
427+
},
428+
},
429+
testPassword,
430+
true,
431+
);
432+
});
433+
});
403434
});
404435
});
405436
});

0 commit comments

Comments
 (0)