Skip to content

Commit

Permalink
feat(components/lookup): add search test harness (#2798)
Browse files Browse the repository at this point in the history
  • Loading branch information
Blackbaud-SandhyaRajasabeson authored Oct 4, 2024
1 parent 537ef63 commit ad579e7
Show file tree
Hide file tree
Showing 5 changed files with 262 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
</sky-toolbar-item>
<sky-toolbar-item>
<sky-search
data-sky-id="demo-search"
[ariaLabel]="searchAriaLabel"
[searchText]="searchText"
[debounceTime]="250"
[placeholderText]="placeholderText"
(searchApply)="searchApplied($event)"
(searchChange)="searchApplied($event)"
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { SkySearchHarness } from '@skyux/lookup/testing';

import { DemoComponent } from './demo.component';

describe('Basic search demo', () => {
async function setupTest(options: { dataSkyId: string }): Promise<{
harness: SkySearchHarness;
fixture: ComponentFixture<DemoComponent>;
}> {
const fixture = TestBed.createComponent(DemoComponent);
const loader = TestbedHarnessEnvironment.loader(fixture);

const harness = await loader.getHarness(
SkySearchHarness.with({ dataSkyId: options.dataSkyId }),
);

fixture.detectChanges();
await fixture.whenStable();

return { harness, fixture };
}

beforeEach(() => {
TestBed.configureTestingModule({
imports: [NoopAnimationsModule, DemoComponent],
});
});

it('should setup search component', async () => {
const { harness } = await setupTest({
dataSkyId: 'demo-search',
});

await expectAsync(harness.getAriaLabel()).toBeResolvedTo(
'Search reminders',
);
await expectAsync(harness.getPlaceholderText()).toBeResolvedTo(
'Search through reminders.',
);
});

it('should interact with search function', async () => {
const { harness } = await setupTest({
dataSkyId: 'demo-search',
});

await harness.enterText('Send');
await expectAsync(harness.getValue()).toBeResolvedTo('Send');

await harness.clickClearButton();
await expectAsync(harness.getValue()).toBeResolvedTo('');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export class DemoComponent {
},
];

protected placeholderText = 'Search through reminders.';
protected searchAriaLabel = 'Search reminders';
protected searchText = '';

Expand Down
112 changes: 110 additions & 2 deletions libs/components/lookup/testing/src/search/search-harness.spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SkyMediaBreakpoints, SkyMediaQueryService } from '@skyux/core';
import { MockSkyMediaQueryService } from '@skyux/core/testing';

import { SearchHarnessTestComponent } from './fixtures/search-harness-test.component';
import { SearchHarnessTestModule } from './fixtures/search-harness-test.module';
import { SkySearchHarness } from './search-harness';

describe('Search harness', () => {
async function setupTest(options: { dataSkyId: string }) {
const mediaQuery = new MockSkyMediaQueryService();

await TestBed.configureTestingModule({
imports: [SearchHarnessTestModule],
providers: [
{
provide: SkyMediaQueryService,
useValue: mediaQuery,
},
],
}).compileComponents();

const fixture = TestBed.createComponent(SearchHarnessTestComponent);
Expand All @@ -18,7 +28,7 @@ describe('Search harness', () => {
SkySearchHarness.with({ dataSkyId: options.dataSkyId }),
);

return { searchHarness, fixture, loader };
return { searchHarness, fixture, loader, mediaQuery };
}

it('should focus and blur input', async () => {
Expand Down Expand Up @@ -93,4 +103,102 @@ describe('Search harness', () => {
'My placeholder text.',
);
});

it('should click the clear button', async () => {
const { searchHarness } = await setupTest({
dataSkyId: 'my-search-1',
});

await searchHarness.enterText('abc');
await expectAsync(searchHarness.getValue()).toBeResolvedTo('abc');

await searchHarness.clickClearButton();
await expectAsync(searchHarness.getValue()).toBeResolvedTo('');
});

it('should should throw an error when trying to click dismiss on a non collapsible search', async () => {
const { searchHarness } = await setupTest({
dataSkyId: 'my-search-1',
});
await expectAsync(
searchHarness.clickDismissSearchButton(),
).toBeRejectedWithError(
'Cannot find dismiss search button. Is a collapsed search open?',
);
});

it('should should throw an error when trying to click open on a non collapsed search', async () => {
const { searchHarness } = await setupTest({
dataSkyId: 'my-search-1',
});
await expectAsync(
searchHarness.clickOpenSearchButton(),
).toBeRejectedWithError(
'Cannot click search open button as search is not collapsed',
);
});

describe('In mobile view', () => {
async function setMobileView(
fixture: ComponentFixture<SearchHarnessTestComponent>,
mockMediaQueryService: MockSkyMediaQueryService,
): Promise<void> {
mockMediaQueryService.fire(SkyMediaBreakpoints.xs);
fixture.detectChanges();
await fixture.whenStable();
}
it('should throw errors trying to interact with collapsed search input', async () => {
const { fixture, searchHarness, mediaQuery } = await setupTest({
dataSkyId: 'my-search-1',
});

await setMobileView(fixture, mediaQuery);

await expectAsync(searchHarness.blur()).toBeRejectedWithError(
'Failed to blur the search input. Search is collapsed.',
);
await expectAsync(searchHarness.clear()).toBeRejectedWithError(
'Failed to clear the search input. Search is collapsed.',
);
await expectAsync(searchHarness.clickClearButton()).toBeRejectedWithError(
'Failed to click clear button. Search is collapsed.',
);
await expectAsync(
searchHarness.clickSubmitButton(),
).toBeRejectedWithError(
'Failed to click the submit button. Search is collapsed.',
);
await expectAsync(searchHarness.enterText('abc')).toBeRejectedWithError(
'Failed to enter text into the search input. Search is collapsed.',
);
await expectAsync(searchHarness.focus()).toBeRejectedWithError(
'Failed to focus the search input. Search is collapsed.',
);
await expectAsync(
searchHarness.getPlaceholderText(),
).toBeRejectedWithError(
'Failed to get the placeholder text. Search is collapsed.',
);
await expectAsync(searchHarness.getValue()).toBeRejectedWithError(
'Failed to get the value of the search input. Search is collapsed.',
);
await expectAsync(searchHarness.isFocused()).toBeRejectedWithError(
'Failed to get the search input focus status. Search is collapsed.',
);
});

it('should open and close a collapsible search get whether the search is collapsed', async () => {
const { fixture, searchHarness, mediaQuery } = await setupTest({
dataSkyId: 'my-search-1',
});

await setMobileView(fixture, mediaQuery);

await expectAsync(searchHarness.isCollapsed()).toBeResolvedTo(true);
await searchHarness.clickOpenSearchButton();
await expectAsync(searchHarness.isCollapsed()).toBeResolvedTo(false);
await searchHarness.clickDismissSearchButton();
await expectAsync(searchHarness.isCollapsed()).toBeResolvedTo(true);
});
});
});
Loading

0 comments on commit ad579e7

Please sign in to comment.