Skip to content

Commit

Permalink
Merge branch 'accessibility-settings-7.6' into accessibility-settings…
Browse files Browse the repository at this point in the history
…-main

# Conflicts:
#	src/app/accessibility/accessibility-settings.service.spec.ts
#	src/app/accessibility/accessibility-settings.service.ts
#	src/app/info/accessibility-settings/accessibility-settings.component.spec.ts
#	src/app/info/accessibility-settings/accessibility-settings.component.ts
#	src/app/info/info.module.ts
#	src/app/shared/live-region/live-region.service.ts
#	src/app/shared/notifications/notifications-board/notifications-board.component.ts
  • Loading branch information
AAwouters committed Dec 11, 2024
2 parents ed0fcd9 + c71c666 commit ff7c9ba
Show file tree
Hide file tree
Showing 13 changed files with 267 additions and 108 deletions.
44 changes: 12 additions & 32 deletions src/app/accessibility/accessibility-settings.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { AuthServiceStub } from '../shared/testing/auth-service.stub';
import {
ACCESSIBILITY_COOKIE,
ACCESSIBILITY_SETTINGS_METADATA_KEY,
AccessibilitySetting,
AccessibilitySettings,
AccessibilitySettingsService,
} from './accessibility-settings.service';
Expand Down Expand Up @@ -48,17 +47,6 @@ describe('accessibilitySettingsService', () => {
);
});

describe('getALlAccessibilitySettingsKeys', () => {
it('should return an array containing all accessibility setting names', () => {
const settingNames: AccessibilitySetting[] = [
AccessibilitySetting.NotificationTimeOut,
AccessibilitySetting.LiveRegionTimeOut,
];

expect(service.getAllAccessibilitySettingKeys()).toEqual(settingNames);
});
});

describe('get', () => {
it('should return the setting if it is set', () => {
const settings: AccessibilitySettings = {
Expand All @@ -67,7 +55,7 @@ describe('accessibilitySettingsService', () => {

service.getAll = jasmine.createSpy('getAll').and.returnValue(of(settings));

service.get(AccessibilitySetting.NotificationTimeOut, 'default').subscribe(value =>
service.get('notificationTimeOut', 'default').subscribe(value =>
expect(value).toEqual('1000'),
);
});
Expand All @@ -79,7 +67,7 @@ describe('accessibilitySettingsService', () => {

service.getAll = jasmine.createSpy('getAll').and.returnValue(of(settings));

service.get(AccessibilitySetting.LiveRegionTimeOut, 'default').subscribe(value =>
service.get('liveRegionTimeOut', 'default').subscribe(value =>
expect(value).toEqual('default'),
);
});
Expand All @@ -89,23 +77,23 @@ describe('accessibilitySettingsService', () => {
it('should return the setting as number if the value for the setting can be parsed to a number', () => {
service.get = jasmine.createSpy('get').and.returnValue(of('1000'));

service.getAsNumber(AccessibilitySetting.NotificationTimeOut).subscribe(value =>
service.getAsNumber('notificationTimeOut').subscribe(value =>
expect(value).toEqual(1000),
);
});

it('should return the default value if no value is set for the setting', () => {
service.get = jasmine.createSpy('get').and.returnValue(of(null));

service.getAsNumber(AccessibilitySetting.NotificationTimeOut, 123).subscribe(value =>
service.getAsNumber('notificationTimeOut', 123).subscribe(value =>
expect(value).toEqual(123),
);
});

it('should return the default value if the value for the setting can not be parsed to a number', () => {
service.get = jasmine.createSpy('get').and.returnValue(of('text'));

service.getAsNumber(AccessibilitySetting.NotificationTimeOut, 123).subscribe(value =>
service.getAsNumber('notificationTimeOut', 123).subscribe(value =>
expect(value).toEqual(123),
);
});
Expand Down Expand Up @@ -183,7 +171,7 @@ describe('accessibilitySettingsService', () => {
it('should correctly update the chosen setting', () => {
service.updateSettings = jasmine.createSpy('updateSettings');

service.set(AccessibilitySetting.LiveRegionTimeOut, '500');
service.set('liveRegionTimeOut', '500');
expect(service.updateSettings).toHaveBeenCalledWith({ liveRegionTimeOut: '500' });
});
});
Expand Down Expand Up @@ -314,7 +302,7 @@ describe('accessibilitySettingsService', () => {
});

it('should set the settings in metadata', () => {
service.setSettingsInMetadata(ePerson, { [AccessibilitySetting.LiveRegionTimeOut]: '500' }).subscribe();
service.setSettingsInMetadata(ePerson, { ['liveRegionTimeOut']: '500' }).subscribe();
expect(ePerson.setMetadata).toHaveBeenCalled();
});

Expand All @@ -325,19 +313,19 @@ describe('accessibilitySettingsService', () => {
});

it('should create a patch with the metadata changes', () => {
service.setSettingsInMetadata(ePerson, { [AccessibilitySetting.LiveRegionTimeOut]: '500' }).subscribe();
service.setSettingsInMetadata(ePerson, { ['liveRegionTimeOut']: '500' }).subscribe();
expect(ePersonService.createPatchFromCache).toHaveBeenCalled();
});

it('should send the patch request', () => {
service.setSettingsInMetadata(ePerson, { [AccessibilitySetting.LiveRegionTimeOut]: '500' }).subscribe();
service.setSettingsInMetadata(ePerson, { ['liveRegionTimeOut']: '500' }).subscribe();
expect(ePersonService.patch).toHaveBeenCalled();
});

it('should emit true when the update succeeded', fakeAsync(() => {
ePersonService.patch = jasmine.createSpy().and.returnValue(createSuccessfulRemoteDataObject$({}));

service.setSettingsInMetadata(ePerson, { [AccessibilitySetting.LiveRegionTimeOut]: '500' })
service.setSettingsInMetadata(ePerson, { ['liveRegionTimeOut']: '500' })
.subscribe(value => {
expect(value).toBeTrue();
});
Expand All @@ -348,7 +336,7 @@ describe('accessibilitySettingsService', () => {
it('should emit false when the update failed', fakeAsync(() => {
ePersonService.patch = jasmine.createSpy().and.returnValue(createFailedRemoteDataObject$());

service.setSettingsInMetadata(ePerson, { [AccessibilitySetting.LiveRegionTimeOut]: '500' })
service.setSettingsInMetadata(ePerson, { ['liveRegionTimeOut']: '500' })
.subscribe(value => {
expect(value).toBeFalse();
});
Expand All @@ -364,7 +352,7 @@ describe('accessibilitySettingsService', () => {
});

it('should store the settings in a cookie', () => {
service.setSettingsInCookie({ [AccessibilitySetting.LiveRegionTimeOut]: '500' });
service.setSettingsInCookie({ ['liveRegionTimeOut']: '500' });
expect(cookieService.set).toHaveBeenCalled();
});

Expand All @@ -375,12 +363,4 @@ describe('accessibilitySettingsService', () => {
});
});

describe('getInputType', () => {
it('should correctly return the input type', () => {
expect(service.getInputType(AccessibilitySetting.NotificationTimeOut)).toEqual('number');
expect(service.getInputType(AccessibilitySetting.LiveRegionTimeOut)).toEqual('number');
expect(service.getInputType('unknownValue' as AccessibilitySetting)).toEqual('text');
});
});

});
6 changes: 6 additions & 0 deletions src/app/accessibility/accessibility-settings.service.stub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,10 @@ export class AccessibilitySettingsServiceStub {
setSettingsInCookie = jasmine.createSpy('setSettingsInCookie');

getInputType = jasmine.createSpy('getInputType').and.returnValue('text');

convertFormValuesToStoredValues = jasmine.createSpy('convertFormValuesToStoredValues').and.returnValue({});

convertStoredValuesToFormValues = jasmine.createSpy('convertStoredValuesToFormValues').and.returnValue({});

getPlaceholder = jasmine.createSpy('getPlaceholder').and.returnValue('placeholder');
}
112 changes: 90 additions & 22 deletions src/app/accessibility/accessibility-settings.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import { getFirstCompletedRemoteData } from '../core/shared/operators';
import {
hasValue,
isNotEmpty,
isNotEmptyOperator,
} from '../shared/empty.util';
import { createSuccessfulRemoteDataObject$ } from '../shared/remote-data.utils';

/**
* Name of the cookie used to store the settings locally
Expand All @@ -33,16 +33,30 @@ export const ACCESSIBILITY_COOKIE = 'dsAccessibilityCookie';
export const ACCESSIBILITY_SETTINGS_METADATA_KEY = 'dspace.accessibility.settings';

/**
* Enum containing all possible accessibility settings.
* When adding new settings, the {@link AccessibilitySettingsService#getInputType} method and the i18n keys for the
* accessibility settings page should be updated.
* Type containing all possible accessibility settings.
* When adding new settings, make sure to add the new setting to the accessibility-settings component form.
* The converter methods to convert from stored format to form format (and vice-versa) need to be updated as well.
*/
export enum AccessibilitySetting {
NotificationTimeOut = 'notificationTimeOut',
LiveRegionTimeOut = 'liveRegionTimeOut',
}
export type AccessibilitySetting = 'notificationTimeOut' | 'liveRegionTimeOut';

export type AccessibilitySettings = { [key in AccessibilitySetting]?: any };
/**
* Type representing an object that contains accessibility settings values for all accessibility settings.
*/
export type FullAccessibilitySettings = { [key in AccessibilitySetting]: string };

/**
* Type representing an object that contains accessibility settings values for some accessibility settings.
*/
export type AccessibilitySettings = Partial<FullAccessibilitySettings>;

/**
* The accessibility settings object format used by the accessibility-settings component form.
*/
export interface AccessibilitySettingsFormValues {
notificationTimeOutEnabled: boolean,
notificationTimeOut: string,
liveRegionTimeOut: string,
}

/**
* Service handling the retrieval and configuration of accessibility settings.
Expand All @@ -62,10 +76,6 @@ export class AccessibilitySettingsService {
) {
}

getAllAccessibilitySettingKeys(): AccessibilitySetting[] {
return Object.entries(AccessibilitySetting).map(([_, val]) => val);
}

/**
* Get the stored value for the provided {@link AccessibilitySetting}. If the value does not exist or if it is empty,
* the provided defaultValue is emitted instead.
Expand Down Expand Up @@ -204,8 +214,8 @@ export class AccessibilitySettingsService {

return this.ePersonService.createPatchFromCache(user).pipe(
take(1),
isNotEmptyOperator(),
switchMap(operations => this.ePersonService.patch(user, operations)),
switchMap(operations =>
isNotEmpty(operations) ? this.ePersonService.patch(user, operations) : createSuccessfulRemoteDataObject$({})),
getFirstCompletedRemoteData(),
map(rd => rd.hasSucceeded),
);
Expand All @@ -223,17 +233,75 @@ export class AccessibilitySettingsService {
}

/**
* Returns the input type that a form should use for the provided {@link AccessibilitySetting}
* Clears all settings in the cookie and attempts to clear settings in metadata.
* Emits true if settings in metadata were cleared and false otherwise.
*/
clearSettings(): Observable<boolean> {
this.setSettingsInCookie({});
return this.setSettingsInAuthenticatedUserMetadata({});

Check warning on line 241 in src/app/accessibility/accessibility-settings.service.ts

View check run for this annotation

Codecov / codecov/patch

src/app/accessibility/accessibility-settings.service.ts#L240-L241

Added lines #L240 - L241 were not covered by tests
}

/**
* Retrieve the placeholder to be used for the provided AccessibilitySetting.
* Returns an empty string when no placeholder is specified for the provided setting.
*/
getInputType(setting: AccessibilitySetting): string {
getPlaceholder(setting: AccessibilitySetting): string {
switch (setting) {

Check warning on line 249 in src/app/accessibility/accessibility-settings.service.ts

View check run for this annotation

Codecov / codecov/patch

src/app/accessibility/accessibility-settings.service.ts#L249

Added line #L249 was not covered by tests
case AccessibilitySetting.NotificationTimeOut:
return 'number';
case AccessibilitySetting.LiveRegionTimeOut:
return 'number';
case 'notificationTimeOut':
return millisecondsToSeconds(environment.notifications.timeOut.toString());

Check warning on line 251 in src/app/accessibility/accessibility-settings.service.ts

View check run for this annotation

Codecov / codecov/patch

src/app/accessibility/accessibility-settings.service.ts#L251

Added line #L251 was not covered by tests
case 'liveRegionTimeOut':
return millisecondsToSeconds(environment.liveRegion.messageTimeOutDurationMs.toString());

Check warning on line 253 in src/app/accessibility/accessibility-settings.service.ts

View check run for this annotation

Codecov / codecov/patch

src/app/accessibility/accessibility-settings.service.ts#L253

Added line #L253 was not covered by tests
default:
return 'text';
return '';

Check warning on line 255 in src/app/accessibility/accessibility-settings.service.ts

View check run for this annotation

Codecov / codecov/patch

src/app/accessibility/accessibility-settings.service.ts#L255

Added line #L255 was not covered by tests
}
}

/**
* Convert values in the provided accessibility settings object to values ready to be stored.
*/
convertFormValuesToStoredValues(settings: AccessibilitySettingsFormValues): FullAccessibilitySettings {
return {

Check warning on line 263 in src/app/accessibility/accessibility-settings.service.ts

View check run for this annotation

Codecov / codecov/patch

src/app/accessibility/accessibility-settings.service.ts#L263

Added line #L263 was not covered by tests
notificationTimeOut: settings.notificationTimeOutEnabled ?
secondsToMilliseconds(settings.notificationTimeOut) : '0',
liveRegionTimeOut: secondsToMilliseconds(settings.liveRegionTimeOut),
};
}

/**
* Convert values in the provided accessibility settings object to values ready to show in the form.
*/
convertStoredValuesToFormValues(settings: AccessibilitySettings): AccessibilitySettingsFormValues {
return {

Check warning on line 274 in src/app/accessibility/accessibility-settings.service.ts

View check run for this annotation

Codecov / codecov/patch

src/app/accessibility/accessibility-settings.service.ts#L274

Added line #L274 was not covered by tests
notificationTimeOutEnabled: parseFloat(settings.notificationTimeOut) !== 0,
notificationTimeOut: millisecondsToSeconds(settings.notificationTimeOut),
liveRegionTimeOut: millisecondsToSeconds(settings.liveRegionTimeOut),
};
}

}

/**
* Converts a string representing seconds to a string representing milliseconds
* Returns null if the input could not be parsed to a float
*/
function secondsToMilliseconds(secondsStr: string): string {
const seconds = parseFloat(secondsStr);

Check warning on line 288 in src/app/accessibility/accessibility-settings.service.ts

View check run for this annotation

Codecov / codecov/patch

src/app/accessibility/accessibility-settings.service.ts#L288

Added line #L288 was not covered by tests
if (isNaN(seconds)) {
return null;

Check warning on line 290 in src/app/accessibility/accessibility-settings.service.ts

View check run for this annotation

Codecov / codecov/patch

src/app/accessibility/accessibility-settings.service.ts#L290

Added line #L290 was not covered by tests
} else {
return (seconds * 1000).toString();

Check warning on line 292 in src/app/accessibility/accessibility-settings.service.ts

View check run for this annotation

Codecov / codecov/patch

src/app/accessibility/accessibility-settings.service.ts#L292

Added line #L292 was not covered by tests
}
}

/**
* Converts a string representing milliseconds to a string representing seconds
* Returns null if the input could not be parsed to a float
*/
function millisecondsToSeconds(millisecondsStr: string): string {
const milliseconds = parseFloat(millisecondsStr);

Check warning on line 301 in src/app/accessibility/accessibility-settings.service.ts

View check run for this annotation

Codecov / codecov/patch

src/app/accessibility/accessibility-settings.service.ts#L301

Added line #L301 was not covered by tests
if (isNaN(milliseconds)) {
return null;

Check warning on line 303 in src/app/accessibility/accessibility-settings.service.ts

View check run for this annotation

Codecov / codecov/patch

src/app/accessibility/accessibility-settings.service.ts#L303

Added line #L303 was not covered by tests
} else {
return (milliseconds / 1000).toString();

Check warning on line 305 in src/app/accessibility/accessibility-settings.service.ts

View check run for this annotation

Codecov / codecov/patch

src/app/accessibility/accessibility-settings.service.ts#L305

Added line #L305 was not covered by tests
}
}
Loading

0 comments on commit ff7c9ba

Please sign in to comment.