mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
Fixed user authentication/registration accessibility issue
- Added the correct autocomplete value - Removed dangling labels, because aria labels already describe those input fields & we can't use ids in this component because otherwise there are duplicate ids on the /login page
This commit is contained in:
@@ -1,13 +1,13 @@
|
|||||||
<div class="container" *ngIf="(registration$ |async)">
|
<div class="container" *ngIf="(registration$ |async)">
|
||||||
<h3 class="mb-4">{{'forgot-password.form.head' | translate}}</h3>
|
<h1 class="mb-4">{{'forgot-password.form.head' | translate}}</h1>
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header">{{'forgot-password.form.identification.header' | translate}}</div>
|
<div class="card-header">{{'forgot-password.form.identification.header' | translate}}</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<label class="font-weight-bold"
|
<span class="font-weight-bold">{{'forgot-password.form.identification.email' | translate}} </span>
|
||||||
for="email">{{'forgot-password.form.identification.email' | translate}}</label>
|
<span [attr.data-test]="'email' | dsBrowserOnly">{{(registration$ |async).email}}</span>
|
||||||
<span id="email">{{(registration$ |async).email}}</span></div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -21,6 +21,7 @@ import {
|
|||||||
createSuccessfulRemoteDataObject$
|
createSuccessfulRemoteDataObject$
|
||||||
} from '../../shared/remote-data.utils';
|
} from '../../shared/remote-data.utils';
|
||||||
import { CoreState } from '../../core/core-state.model';
|
import { CoreState } from '../../core/core-state.model';
|
||||||
|
import { BrowserOnlyPipe } from '../../shared/utils/browser-only.pipe';
|
||||||
|
|
||||||
describe('ForgotPasswordFormComponent', () => {
|
describe('ForgotPasswordFormComponent', () => {
|
||||||
let comp: ForgotPasswordFormComponent;
|
let comp: ForgotPasswordFormComponent;
|
||||||
@@ -54,7 +55,10 @@ describe('ForgotPasswordFormComponent', () => {
|
|||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), ReactiveFormsModule],
|
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), ReactiveFormsModule],
|
||||||
declarations: [ForgotPasswordFormComponent],
|
declarations: [
|
||||||
|
BrowserOnlyPipe,
|
||||||
|
ForgotPasswordFormComponent,
|
||||||
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{provide: Router, useValue: router},
|
{provide: Router, useValue: router},
|
||||||
{provide: ActivatedRoute, useValue: route},
|
{provide: ActivatedRoute, useValue: route},
|
||||||
@@ -75,7 +79,7 @@ describe('ForgotPasswordFormComponent', () => {
|
|||||||
|
|
||||||
describe('init', () => {
|
describe('init', () => {
|
||||||
it('should initialise mail address', () => {
|
it('should initialise mail address', () => {
|
||||||
const elem = fixture.debugElement.queryAll(By.css('span#email'))[0].nativeElement;
|
const elem = fixture.debugElement.queryAll(By.css('span[data-test="email"]'))[0].nativeElement;
|
||||||
expect(elem.innerHTML).toContain('test@email.org');
|
expect(elem.innerHTML).toContain('test@email.org');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -43,7 +43,8 @@ export class ProfilePageMetadataFormComponent implements OnInit {
|
|||||||
new DynamicInputModel({
|
new DynamicInputModel({
|
||||||
id: 'email',
|
id: 'email',
|
||||||
name: 'email',
|
name: 'email',
|
||||||
readOnly: true
|
readOnly: true,
|
||||||
|
disabled: true,
|
||||||
}),
|
}),
|
||||||
new DynamicInputModel({
|
new DynamicInputModel({
|
||||||
id: 'firstname',
|
id: 'firstname',
|
||||||
@@ -55,6 +56,7 @@ export class ProfilePageMetadataFormComponent implements OnInit {
|
|||||||
errorMessages: {
|
errorMessages: {
|
||||||
required: 'This field is required'
|
required: 'This field is required'
|
||||||
},
|
},
|
||||||
|
autoComplete: 'given-name',
|
||||||
}),
|
}),
|
||||||
new DynamicInputModel({
|
new DynamicInputModel({
|
||||||
id: 'lastname',
|
id: 'lastname',
|
||||||
@@ -66,10 +68,12 @@ export class ProfilePageMetadataFormComponent implements OnInit {
|
|||||||
errorMessages: {
|
errorMessages: {
|
||||||
required: 'This field is required'
|
required: 'This field is required'
|
||||||
},
|
},
|
||||||
|
autoComplete: 'family-name',
|
||||||
}),
|
}),
|
||||||
new DynamicInputModel({
|
new DynamicInputModel({
|
||||||
id: 'phone',
|
id: 'phone',
|
||||||
name: 'eperson.phone'
|
name: 'eperson.phone',
|
||||||
|
autoComplete: 'tel',
|
||||||
}),
|
}),
|
||||||
new DynamicSelectModel<string>({
|
new DynamicSelectModel<string>({
|
||||||
id: 'language',
|
id: 'language',
|
||||||
|
@@ -39,12 +39,14 @@ export class ProfilePageSecurityFormComponent implements OnInit {
|
|||||||
new DynamicInputModel({
|
new DynamicInputModel({
|
||||||
id: 'password',
|
id: 'password',
|
||||||
name: 'password',
|
name: 'password',
|
||||||
inputType: 'password'
|
inputType: 'password',
|
||||||
|
autoComplete: 'new-password',
|
||||||
}),
|
}),
|
||||||
new DynamicInputModel({
|
new DynamicInputModel({
|
||||||
id: 'passwordrepeat',
|
id: 'passwordrepeat',
|
||||||
name: 'passwordrepeat',
|
name: 'passwordrepeat',
|
||||||
inputType: 'password'
|
inputType: 'password',
|
||||||
|
autoComplete: 'new-password',
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -79,7 +81,8 @@ export class ProfilePageSecurityFormComponent implements OnInit {
|
|||||||
id: 'current-password',
|
id: 'current-password',
|
||||||
name: 'current-password',
|
name: 'current-password',
|
||||||
inputType: 'password',
|
inputType: 'password',
|
||||||
required: true
|
required: true,
|
||||||
|
autoComplete: 'current-password',
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
if (this.passwordCanBeEmpty) {
|
if (this.passwordCanBeEmpty) {
|
||||||
|
@@ -1,8 +1,7 @@
|
|||||||
<ng-container *ngVar="(user$ | async) as user">
|
<ng-container *ngVar="(user$ | async) as user">
|
||||||
<div class="container" *ngIf="user">
|
<div class="container" *ngIf="user">
|
||||||
<h1>{{'profile.title' | translate}}</h1>
|
<h1>{{'profile.title' | translate}}</h1>
|
||||||
<ng-container *ngIf="isResearcherProfileEnabled() | async">
|
<ng-container>
|
||||||
<h2 class="mb-4">{{'profile.head' | translate}}</h2>
|
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header">{{'profile.card.researcher' | translate}}</div>
|
<div class="card-header">{{'profile.card.researcher' | translate}}</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
@@ -1,9 +1,8 @@
|
|||||||
<form class="form-login"
|
<form class="form-login"
|
||||||
(ngSubmit)="submit()"
|
(ngSubmit)="submit()"
|
||||||
[formGroup]="form" novalidate>
|
[formGroup]="form" novalidate>
|
||||||
<label class="sr-only">{{"login.form.email" | translate}}</label>
|
|
||||||
<input [attr.aria-label]="'login.form.email' |translate"
|
<input [attr.aria-label]="'login.form.email' |translate"
|
||||||
autocomplete="off"
|
autocomplete="username"
|
||||||
autofocus
|
autofocus
|
||||||
class="form-control form-control-lg position-relative"
|
class="form-control form-control-lg position-relative"
|
||||||
formControlName="email"
|
formControlName="email"
|
||||||
@@ -11,9 +10,8 @@
|
|||||||
required
|
required
|
||||||
type="email"
|
type="email"
|
||||||
[attr.data-test]="'email' | dsBrowserOnly">
|
[attr.data-test]="'email' | dsBrowserOnly">
|
||||||
<label class="sr-only">{{"login.form.password" | translate}}</label>
|
|
||||||
<input [attr.aria-label]="'login.form.password' |translate"
|
<input [attr.aria-label]="'login.form.password' |translate"
|
||||||
autocomplete="off"
|
autocomplete="current-password"
|
||||||
class="form-control form-control-lg position-relative mb-3"
|
class="form-control form-control-lg position-relative mb-3"
|
||||||
placeholder="{{'login.form.password' | translate}}"
|
placeholder="{{'login.form.password' | translate}}"
|
||||||
formControlName="password"
|
formControlName="password"
|
||||||
|
@@ -1720,7 +1720,7 @@
|
|||||||
|
|
||||||
"forgot-password.form.label.passwordrepeat": "Retype to confirm",
|
"forgot-password.form.label.passwordrepeat": "Retype to confirm",
|
||||||
|
|
||||||
"forgot-password.form.error.empty-password": "Please enter a password in the box below.",
|
"forgot-password.form.error.empty-password": "Please enter a password in the boxes above.",
|
||||||
|
|
||||||
"forgot-password.form.error.matching-passwords": "The passwords do not match.",
|
"forgot-password.form.error.matching-passwords": "The passwords do not match.",
|
||||||
|
|
||||||
@@ -3490,8 +3490,6 @@
|
|||||||
|
|
||||||
"profile.special.groups.head": "Authorization special groups you belong to",
|
"profile.special.groups.head": "Authorization special groups you belong to",
|
||||||
|
|
||||||
"profile.head": "Update Profile",
|
|
||||||
|
|
||||||
"profile.metadata.form.error.firstname.required": "First Name is required",
|
"profile.metadata.form.error.firstname.required": "First Name is required",
|
||||||
|
|
||||||
"profile.metadata.form.error.lastname.required": "Last Name is required",
|
"profile.metadata.form.error.lastname.required": "Last Name is required",
|
||||||
|
Reference in New Issue
Block a user