Skip to content

Commit d0d9a36

Browse files
author
Kerry
authored
Use semantic headings in user settings - account (matrix-org#10972)
* account password section * account email and phone numbers * update cypress selectors
1 parent 8d77d6e commit d0d9a36

File tree

9 files changed

+101
-103
lines changed

9 files changed

+101
-103
lines changed

cypress/e2e/settings/general-user-settings-tab.spec.ts

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,14 @@ describe("General user settings tab", () => {
8383
});
8484

8585
// Wait until spinners disappear
86-
cy.get(".mx_GeneralUserSettingsTab_section--account .mx_Spinner").should("not.exist");
87-
cy.get(".mx_GeneralUserSettingsTab_section--discovery .mx_Spinner").should("not.exist");
86+
cy.findByTestId("accountSection").within(() => {
87+
cy.get(".mx_Spinner").should("not.exist");
88+
});
89+
cy.findByTestId("discoverySection").within(() => {
90+
cy.get(".mx_Spinner").should("not.exist");
91+
});
8892

89-
cy.get(".mx_GeneralUserSettingsTab_section--account").within(() => {
93+
cy.findByTestId("accountSection").within(() => {
9094
// Assert that input areas for changing a password exists
9195
cy.get("form.mx_GeneralUserSettingsTab_section--account_changePassword")
9296
.scrollIntoView()
@@ -95,29 +99,28 @@ describe("General user settings tab", () => {
9599
cy.findByLabelText("New Password").should("be.visible");
96100
cy.findByLabelText("Confirm password").should("be.visible");
97101
});
102+
});
103+
// Check email addresses area
104+
cy.findByTestId("mx_AccountEmailAddresses")
105+
.scrollIntoView()
106+
.within(() => {
107+
// Assert that an input area for a new email address is rendered
108+
cy.findByRole("textbox", { name: "Email Address" }).should("be.visible");
98109

99-
// Check email addresses area
100-
cy.get(".mx_EmailAddresses")
101-
.scrollIntoView()
102-
.within(() => {
103-
// Assert that an input area for a new email address is rendered
104-
cy.findByRole("textbox", { name: "Email Address" }).should("be.visible");
105-
106-
// Assert the add button is visible
107-
cy.findByRole("button", { name: "Add" }).should("be.visible");
108-
});
110+
// Assert the add button is visible
111+
cy.findByRole("button", { name: "Add" }).should("be.visible");
112+
});
109113

110-
// Check phone numbers area
111-
cy.get(".mx_PhoneNumbers")
112-
.scrollIntoView()
113-
.within(() => {
114-
// Assert that an input area for a new phone number is rendered
115-
cy.findByRole("textbox", { name: "Phone Number" }).should("be.visible");
114+
// Check phone numbers area
115+
cy.findByTestId("mx_AccountPhoneNumbers")
116+
.scrollIntoView()
117+
.within(() => {
118+
// Assert that an input area for a new phone number is rendered
119+
cy.findByRole("textbox", { name: "Phone Number" }).should("be.visible");
116120

117-
// Assert that the add button is rendered
118-
cy.findByRole("button", { name: "Add" }).should("be.visible");
119-
});
120-
});
121+
// Assert that the add button is rendered
122+
cy.findByRole("button", { name: "Add" }).should("be.visible");
123+
});
121124

122125
// Check language and region setting dropdown
123126
cy.get(".mx_GeneralUserSettingsTab_section_languageInput")
@@ -188,7 +191,7 @@ describe("General user settings tab", () => {
188191

189192
it("should set a country calling code based on default_country_code", () => {
190193
// Check phone numbers area
191-
cy.get(".mx_PhoneNumbers")
194+
cy.findByTestId("mx_AccountPhoneNumbers")
192195
.scrollIntoView()
193196
.within(() => {
194197
// Assert that an input area for a new phone number is rendered

res/css/views/elements/_TagComposer.pcss

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,12 @@ limitations under the License.
1717
.mx_TagComposer {
1818
.mx_TagComposer_input {
1919
display: flex;
20-
21-
.mx_Field {
22-
flex: 1;
23-
margin: 0; /* override from field styles */
24-
}
20+
flex-direction: row;
2521

2622
.mx_AccessibleButton {
2723
min-width: 70px;
2824
padding: 0 8px; /* override from button styles */
29-
margin-left: 16px; /* distance from <Field> */
25+
align-self: stretch; /* override default settingstab style */
3026
}
3127

3228
.mx_Field,

res/css/views/settings/tabs/_SettingsTab.pcss

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,24 @@ limitations under the License.
2424
a {
2525
color: $links;
2626
}
27+
28+
form {
29+
display: flex;
30+
flex-direction: column;
31+
gap: $spacing-8;
32+
flex-grow: 1;
33+
}
34+
// never want full width buttons
35+
// event when other content is 100% width
36+
.mx_AccessibleButton {
37+
align-self: flex-start;
38+
justify-self: flex-start;
39+
}
40+
41+
.mx_Field {
42+
margin: 0;
43+
flex: 1;
44+
}
2745
}
2846

2947
.mx_SettingsTab_warningText {

res/css/views/settings/tabs/user/_GeneralUserSettingsTab.pcss

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,41 +14,9 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
.mx_GeneralUserSettingsTab_section--account_changePassword {
18-
.mx_Field {
19-
margin-inline-end: var(--SettingsTab_fullWidthField-margin-inline-end);
20-
21-
&:first-child {
22-
margin-top: 0;
23-
}
24-
}
25-
}
26-
27-
/* TODO: Make this selector less painful */
28-
.mx_GeneralUserSettingsTab_section--account .mx_SettingsTab_subheading:nth-child(n + 1),
29-
.mx_GeneralUserSettingsTab_section--discovery .mx_SettingsTab_subheading:nth-child(n + 2),
30-
.mx_SetIdServer .mx_SettingsTab_subheading {
31-
margin-top: 24px;
32-
}
33-
34-
.mx_GeneralUserSettingsTab_section--account,
35-
.mx_GeneralUserSettingsTab_section--discovery {
36-
.mx_Spinner {
37-
/* Move the spinner to the left side of the container (default center) */
38-
justify-content: flex-start;
39-
}
40-
}
41-
42-
.mx_GeneralUserSettingsTab_section--account .mx_EmailAddresses,
43-
.mx_GeneralUserSettingsTab_section--account .mx_PhoneNumbers,
44-
.mx_GeneralUserSettingsTab_section--discovery .mx_GeneralUserSettingsTab_section--discovery_existing {
45-
margin-inline-end: var(--SettingsTab_fullWidthField-margin-inline-end);
46-
}
47-
4817
.mx_GeneralUserSettingsTab_section--discovery_existing {
4918
display: flex;
5019
align-items: center;
51-
margin-bottom: 5px;
5220
}
5321

5422
.mx_GeneralUserSettingsTab_section--discovery_existing_address,

src/components/views/settings/account/EmailAddresses.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ export default class EmailAddresses extends React.Component<IProps, IState> {
276276
}
277277

278278
return (
279-
<div className="mx_EmailAddresses">
279+
<>
280280
{existingEmailElements}
281281
<form onSubmit={this.onAddClick} autoComplete="off" noValidate={true}>
282282
<Field
@@ -289,7 +289,7 @@ export default class EmailAddresses extends React.Component<IProps, IState> {
289289
/>
290290
{addButton}
291291
</form>
292-
</div>
292+
</>
293293
);
294294
}
295295
}

src/components/views/settings/account/PhoneNumbers.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ export default class PhoneNumbers extends React.Component<IProps, IState> {
305305
);
306306

307307
return (
308-
<div className="mx_PhoneNumbers">
308+
<>
309309
{existingPhoneElements}
310310
<form onSubmit={this.onAddClick} autoComplete="off" noValidate={true} className="mx_PhoneNumbers_new">
311311
<div className="mx_PhoneNumbers_input">
@@ -321,7 +321,7 @@ export default class PhoneNumbers extends React.Component<IProps, IState> {
321321
</div>
322322
</form>
323323
{addVerifySection}
324-
</div>
324+
</>
325325
);
326326
}
327327
}

src/components/views/settings/discovery/PhoneNumbers.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ export default class PhoneNumbers extends React.Component<IProps> {
294294

295295
return (
296296
<SettingsSubsection
297-
data-testid="mx_PhoneNumbers"
297+
data-testid="mx_DiscoveryPhoneNumbers"
298298
heading={_t("Phone numbers")}
299299
description={description}
300300
stretchContent

src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ import { SettingsSection } from "../../shared/SettingsSection";
6060
import SettingsSubsection, { SettingsSubsectionText } from "../../shared/SettingsSubsection";
6161
import { SettingsSubsectionHeading } from "../../shared/SettingsSubsectionHeading";
6262
import Heading from "../../../typography/Heading";
63+
import InlineSpinner from "../../../elements/InlineSpinner";
6364

6465
interface IProps {
6566
closeSettingsFn: () => void;
@@ -196,7 +197,6 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
196197
);
197198
logger.warn(e);
198199
}
199-
200200
this.setState({
201201
emails: threepids.filter((a) => a.medium === ThreepidMedium.Email),
202202
msisdns: threepids.filter((a) => a.medium === ThreepidMedium.Phone),
@@ -329,16 +329,6 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
329329
}
330330

331331
private renderAccountSection(): JSX.Element {
332-
let passwordChangeForm: ReactNode = (
333-
<ChangePassword
334-
className="mx_GeneralUserSettingsTab_section--account_changePassword"
335-
rowClassName=""
336-
buttonKind="primary"
337-
onError={this.onPasswordChangeError}
338-
onFinished={this.onPasswordChanged}
339-
/>
340-
);
341-
342332
let threepidSection: ReactNode = null;
343333

344334
// For older homeservers without separate 3PID add and bind methods (MSC2290),
@@ -351,33 +341,52 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
351341
(this.state.haveIdServer || this.state.serverSupportsSeparateAddAndBind === true)
352342
) {
353343
const emails = this.state.loading3pids ? (
354-
<Spinner />
344+
<InlineSpinner />
355345
) : (
356346
<AccountEmailAddresses emails={this.state.emails} onEmailsChange={this.onEmailsChange} />
357347
);
358348
const msisdns = this.state.loading3pids ? (
359-
<Spinner />
349+
<InlineSpinner />
360350
) : (
361351
<AccountPhoneNumbers msisdns={this.state.msisdns} onMsisdnsChange={this.onMsisdnsChange} />
362352
);
363353
threepidSection = (
364-
<div>
365-
<span className="mx_SettingsTab_subheading">{_t("Email addresses")}</span>
366-
{emails}
354+
<>
355+
<SettingsSubsection
356+
heading={_t("Email addresses")}
357+
stretchContent
358+
data-testid="mx_AccountEmailAddresses"
359+
>
360+
{emails}
361+
</SettingsSubsection>
367362

368-
<span className="mx_SettingsTab_subheading">{_t("Phone numbers")}</span>
369-
{msisdns}
370-
</div>
363+
<SettingsSubsection
364+
heading={_t("Phone numbers")}
365+
stretchContent
366+
data-testid="mx_AccountPhoneNumbers"
367+
>
368+
{msisdns}
369+
</SettingsSubsection>
370+
</>
371371
);
372372
} else if (this.state.serverSupportsSeparateAddAndBind === null) {
373373
threepidSection = <Spinner />;
374374
}
375375

376-
let passwordChangeText: ReactNode = _t("Set a new account password…");
377-
if (!this.state.canChangePassword) {
378-
// Just don't show anything if you can't do anything.
379-
passwordChangeText = null;
380-
passwordChangeForm = null;
376+
let passwordChangeSection: ReactNode = null;
377+
if (this.state.canChangePassword) {
378+
passwordChangeSection = (
379+
<>
380+
<SettingsSubsectionText>{_t("Set a new account password…")}</SettingsSubsectionText>
381+
<ChangePassword
382+
className="mx_GeneralUserSettingsTab_section--account_changePassword"
383+
rowClassName=""
384+
buttonKind="primary"
385+
onError={this.onPasswordChangeError}
386+
onFinished={this.onPasswordChanged}
387+
/>
388+
</>
389+
);
381390
}
382391

383392
let externalAccountManagement: JSX.Element | undefined;
@@ -386,13 +395,13 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
386395

387396
externalAccountManagement = (
388397
<>
389-
<p className="mx_SettingsTab_subsectionText" data-testid="external-account-management-outer">
398+
<SettingsSubsectionText data-testid="external-account-management-outer">
390399
{_t(
391400
"Your account details are managed separately at <code>%(hostname)s</code>.",
392401
{ hostname },
393402
{ code: (sub) => <code>{sub}</code> },
394403
)}
395-
</p>
404+
</SettingsSubsectionText>
396405
<AccessibleButton
397406
onClick={null}
398407
element="a"
@@ -408,13 +417,13 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
408417
);
409418
}
410419
return (
411-
<div className="mx_SettingsTab_section mx_GeneralUserSettingsTab_section--account">
412-
<span className="mx_SettingsTab_subheading">{_t("Account")}</span>
413-
{externalAccountManagement}
414-
<p className="mx_SettingsTab_subsectionText">{passwordChangeText}</p>
415-
{passwordChangeForm}
420+
<>
421+
<SettingsSubsection heading={_t("Account")} stretchContent data-testid="accountSection">
422+
{externalAccountManagement}
423+
{passwordChangeSection}
424+
</SettingsSubsection>
416425
{threepidSection}
417-
</div>
426+
</>
418427
);
419428
}
420429

@@ -540,7 +549,11 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
540549
{_t("Discovery")}
541550
</Heading>
542551
);
543-
discoverySection = <SettingsSection heading={heading}>{this.renderDiscoverySection()}</SettingsSection>;
552+
discoverySection = (
553+
<SettingsSection heading={heading} data-testid="discoverySection">
554+
{this.renderDiscoverySection()}
555+
</SettingsSection>
556+
);
544557
}
545558

546559
return (

test/components/views/settings/discovery/__snapshots__/PhoneNumbers-test.tsx.snap

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ exports[`<PhoneNumbers /> should handle no numbers 1`] = `
44
<div>
55
<div
66
class="mx_SettingsSubsection"
7-
data-testid="mx_PhoneNumbers"
7+
data-testid="mx_DiscoveryPhoneNumbers"
88
>
99
<div
1010
class="mx_SettingsSubsectionHeading"
@@ -32,7 +32,7 @@ exports[`<PhoneNumbers /> should render a loader while loading 1`] = `
3232
<div>
3333
<div
3434
class="mx_SettingsSubsection"
35-
data-testid="mx_PhoneNumbers"
35+
data-testid="mx_DiscoveryPhoneNumbers"
3636
>
3737
<div
3838
class="mx_SettingsSubsectionHeading"
@@ -64,7 +64,7 @@ exports[`<PhoneNumbers /> should render phone numbers 1`] = `
6464
<div>
6565
<div
6666
class="mx_SettingsSubsection"
67-
data-testid="mx_PhoneNumbers"
67+
data-testid="mx_DiscoveryPhoneNumbers"
6868
>
6969
<div
7070
class="mx_SettingsSubsectionHeading"

0 commit comments

Comments
 (0)