Skip to content

Commit

Permalink
Merge branch '10.x.x' into release-please--branches--10.x.x--componen…
Browse files Browse the repository at this point in the history
…ts--skyux
  • Loading branch information
Blackbaud-SteveBrush authored Jul 25, 2024
2 parents ab7f043 + 55e7030 commit 0817178
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 7 deletions.
4 changes: 2 additions & 2 deletions apps/playground/src/app/shared/help.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { Injectable } from '@angular/core';
import { SkyHelpOpenArgs, SkyHelpService } from '@skyux/core';

@Injectable()
export class PlaygroundHelpService implements SkyHelpService {
public openHelp(args: SkyHelpOpenArgs): void {
export class PlaygroundHelpService extends SkyHelpService {
public override openHelp(args: SkyHelpOpenArgs): void {
alert('help key: ' + args.helpKey);
}
}
10 changes: 10 additions & 0 deletions libs/components/core/src/lib/modules/help/help.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { TestBed } from '@angular/core/testing';

import { firstValueFrom } from 'rxjs';

import { SkyHelpService } from './help.service';

describe('Help service', () => {
Expand All @@ -18,4 +20,12 @@ describe('Help service', () => {
}),
).toThrowError();
});

it('should default widget ready state to false', async () => {
const helpService = TestBed.inject(SkyHelpService);

await expectAsync(
firstValueFrom(helpService.widgetReadyStateChange),
).toBeResolvedTo(false);
});
});
9 changes: 9 additions & 0 deletions libs/components/core/src/lib/modules/help/help.service.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { Injectable } from '@angular/core';

import { Observable, of } from 'rxjs';

import { SkyHelpOpenArgs } from './help-open-args';

/**
* Provides methods for opening a globally accessible help dialog.
*/
@Injectable()
export abstract class SkyHelpService {
/**
* Emits when the help widget ready state changes.
*/
public get widgetReadyStateChange(): Observable<boolean> {
return of(false);
}

/**
* Opens a globally accessible help dialog.
* @param args The options for opening the help dialog.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { TestBed } from '@angular/core/testing';
import { SkyHelpService } from '@skyux/core';

import { firstValueFrom } from 'rxjs';

import { SkyHelpTestingController } from './help-testing-controller';
import { SkyHelpTestingModule } from './help-testing.module';

Expand Down Expand Up @@ -50,4 +52,10 @@ describe('Help testing controller', () => {
`Expected current help key to be 'test', but the current help key is undefined.`,
);
});

it('should set widget ready state to "true" on init', async () => {
await expectAsync(
firstValueFrom(helpSvc.widgetReadyStateChange),
).toBeResolvedTo(true);
});
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { inject } from '@angular/core';
// eslint-disable-next-line @nx/enforce-module-boundaries
import { SkyHelpService } from '@skyux/core';

import { SkyHelpTestingService } from './help-testing.service';
Expand Down
7 changes: 7 additions & 0 deletions libs/components/core/testing/src/help/help-testing.service.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import { Injectable } from '@angular/core';
// eslint-disable-next-line @nx/enforce-module-boundaries
import { SkyHelpOpenArgs, SkyHelpService } from '@skyux/core';

import { Observable, of } from 'rxjs';

/**
* @internal
*/
@Injectable()
export class SkyHelpTestingService extends SkyHelpService {
public override get widgetReadyStateChange(): Observable<boolean> {
return of(true);
}

#currentHelpKey: string | undefined;

public override openHelp(args: SkyHelpOpenArgs): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,16 @@ export class SkyHelpInlineAriaControlsPipe implements PipeTransform {
ariaControls: string | undefined,
popoverId: string | undefined,
helpKey: string | undefined,
widgetReadyState: boolean | null,
): string | undefined {
if (helpKey && this.#helpGlobalOptions) {
return this.#helpGlobalOptions.ariaControls;
if (helpKey) {
if (!widgetReadyState) {
return;
}

if (this.#helpGlobalOptions) {
return this.#helpGlobalOptions.ariaControls;
}
}

return popoverId || ariaControls;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
class="sky-help-inline"
type="button"
[attr.aria-controls]="
ariaControls | skyHelpInlineAriaControls: popoverId : helpKey
ariaControls
| skyHelpInlineAriaControls
: popoverId
: helpKey
: (helpSvc?.widgetReadyStateChange | async)
"
[attr.aria-expanded]="
ariaExpanded | skyHelpInlineAriaExpanded: ariaControls : isPopoverOpened
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ describe('Help inline component', () => {
options.ariaExpanded,
);

if (options.ariaHaspopup) {
if (options.ariaHaspopup !== undefined) {
expect(helpInlineEl?.getAttribute('aria-haspopup')).toBe(
options.ariaHaspopup,
);
Expand Down Expand Up @@ -90,11 +90,14 @@ describe('Help inline component', () => {
let mockThemeSvc: { settingsChange: BehaviorSubject<SkyThemeSettingsChange> };
let uniqueId = 0;
let mockHelpSvc: jasmine.SpyObj<SkyHelpService>;
let readyStateChange: BehaviorSubject<boolean>;

function setupTest(
provideHelpSvc?: boolean,
globalOptions?: SkyHelpGlobalOptions,
): void {
readyStateChange = new BehaviorSubject<boolean>(false);

mockThemeSvc = {
settingsChange: new BehaviorSubject<SkyThemeSettingsChange>({
currentSettings: new SkyThemeSettings(
Expand All @@ -105,7 +108,16 @@ describe('Help inline component', () => {
}),
};

mockHelpSvc = jasmine.createSpyObj('SkyHelpService', ['openHelp']);
mockHelpSvc = jasmine.createSpyObj(
'SkyHelpService',
['openHelp'],
['widgetReadyStateChange'],
);

(
Object.getOwnPropertyDescriptor(mockHelpSvc, 'widgetReadyStateChange')
?.get as unknown as jasmine.Spy
).and.returnValue(readyStateChange);

const providers: Provider[] = [
{ provide: SkyThemeService, useValue: mockThemeSvc },
Expand Down Expand Up @@ -434,6 +446,7 @@ describe('Help inline component', () => {
});

component.helpKey = 'test.html';
readyStateChange.next(true);

fixture.detectChanges();

Expand All @@ -445,6 +458,43 @@ describe('Help inline component', () => {
});
});

it('should pass accessibility when a non-existent element is provided to the global ariaControls', async () => {
const ariaControls = 'lazy-element';

setupTest(true, {
ariaControls,
ariaHaspopup: 'dialog',
});

component.helpKey = 'foo.html';
fixture.detectChanges();

await checkAriaPropertiesAndAccessibility({
ariaLabel: 'Show help content',
ariaControls: null,
ariaExpanded: null,
ariaHaspopup: 'dialog',
});

// Create the ariaControls element.
const div = document.createElement('div');
div.id = ariaControls;
document.body.appendChild(div);

// Fire the ready state change event.
readyStateChange.next(true);
fixture.detectChanges();

await checkAriaPropertiesAndAccessibility({
ariaLabel: 'Show help content',
ariaControls,
ariaExpanded: null,
ariaHaspopup: 'dialog',
});

div.remove();
});

describe('and help service is not provided but helpKey is specified', () => {
it('should hide the help button', () => {
setupTest(false);
Expand Down

0 comments on commit 0817178

Please sign in to comment.