Skip to content

Commit

Permalink
feat(components/tabs): add harnesses for tab component (#3064) (#3095)
Browse files Browse the repository at this point in the history
🍒 Cherry pick from[ #3064
](#3064)


[AB#2195550](https://dev.azure.com/blackbaud/Products/_boards/board/t/SKY%20UX%20Program/Stories/?workitem=2195550)

Co-authored-by: Sandhya Raja Sabeson <sandhya.rajasabeson@blackbaud.me>
  • Loading branch information
Blackbaud-SandhyaRajasabeson and Sandhya Raja Sabeson authored Feb 3, 2025
1 parent 4343e0a commit 37d2e90
Show file tree
Hide file tree
Showing 25 changed files with 962 additions and 60 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { provideRouter } from '@angular/router';
import { SkyTabsetHarness } from '@skyux/tabs/testing';

import { RecordPageContentComponent } from './record-page-content.component';
import { RecordPageOverviewTabHarness } from './record-page-overview-tab-harness';

describe('Record page content', () => {
async function setupTest(): Promise<{
recordPageHarness: SkyTabsetHarness;
fixture: ComponentFixture<RecordPageContentComponent>;
}> {
await TestBed.configureTestingModule({
providers: [provideRouter([])],
}).compileComponents();
const fixture = TestBed.createComponent(RecordPageContentComponent);
const loader = TestbedHarnessEnvironment.loader(fixture);

const recordPageHarness = await loader.getHarness(SkyTabsetHarness);

return { recordPageHarness, fixture };
}

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

it("should get the overview tab's content harness", async () => {
const { recordPageHarness } = await setupTest();

const overviewTabHarness = await (
await recordPageHarness.getTabContentHarness('Overview')
).queryHarness(RecordPageOverviewTabHarness);

const overviewBoxes = await overviewTabHarness.getBoxes();

expect(overviewBoxes.length).toBe(3);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ComponentHarness } from '@angular/cdk/testing';
import { SkyBoxHarness } from '@skyux/layout/testing';

export class RecordPageOverviewTabHarness extends ComponentHarness {
public static hostSelector = 'app-record-page-overview-tab';

public async getBoxes(): Promise<SkyBoxHarness[]> {
return await this.locatorForAll(SkyBoxHarness)();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<sky-tabset ariaLabel="Tab demonstration" (newTab)="onNewTabClick()">
<sky-tabset
ariaLabel="Tab demonstration"
data-sky-id="tab-demo"
(newTab)="onNewTabClick()"
>
@for (tab of tabArray; track tab; let i = $index) {
<sky-tab [tabHeading]="tab.tabHeading" (close)="onCloseClick(i)">
{{ tab.tabContent }}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { provideRouter } from '@angular/router';
import { SkyTabsetHarness } from '@skyux/tabs/testing';

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

describe('Static tabs demo with add and close', () => {
async function setupTest(options: { dataSkyId?: string }): Promise<{
harness: SkyTabsetHarness;
fixture: ComponentFixture<DemoComponent>;
}> {
await TestBed.configureTestingModule({
providers: [provideRouter([])],
}).compileComponents();
const fixture = TestBed.createComponent(DemoComponent);
const loader = TestbedHarnessEnvironment.loader(fixture);

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

return { harness, fixture };
}

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

it('should set up tabs', async () => {
const { harness } = await setupTest({ dataSkyId: 'tab-demo' });

await harness.clickNewTabButton();
const tabButtonHarnesses = await harness.getTabButtonHarnesses();
expect(tabButtonHarnesses.length).toBe(4);

const activeTab = await harness.getActiveTabButton();
await expectAsync(activeTab?.getTabHeading()).toBeResolvedTo('Tab 1');
});

it('should hide Tab 3 if it is closed', async () => {
const { harness } = await setupTest({ dataSkyId: 'tab-demo' });

const tab3Harness = await harness.getTabButtonHarness('Tab 3');
await tab3Harness.clickRemoveButton();

const tabButtons = await harness.getTabButtonHarnesses();
expect(tabButtons.length).toBe(2);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export class DemoComponent {

#tabCounter = 3;

protected onNewTabClick(): void {
public onNewTabClick(): void {
this.#tabCounter++;

this.tabArray.push({
Expand All @@ -33,7 +33,7 @@ export class DemoComponent {
});
}

protected onCloseClick(arrayIndex: number): void {
public onCloseClick(arrayIndex: number): void {
this.tabArray.splice(arrayIndex, 1);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<sky-tabset ariaLabel="Tab demonstration">
<sky-tabset ariaLabel="Tab demonstration" data-sky-id="tab-demo">
@for (tab of tabArray; track tab) {
<sky-tab [tabHeading]="tab.tabHeading">
{{ tab.tabContent }}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { provideRouter } from '@angular/router';
import { SkyTabsetHarness } from '@skyux/tabs/testing';

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

describe('Static tabs demo with add and close', () => {
async function setupTest(options: { dataSkyId?: string }): Promise<{
harness: SkyTabsetHarness;
fixture: ComponentFixture<DemoComponent>;
}> {
await TestBed.configureTestingModule({
providers: [provideRouter([])],
}).compileComponents();
const fixture = TestBed.createComponent(DemoComponent);
const loader = TestbedHarnessEnvironment.loader(fixture);

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

return { harness, fixture };
}

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

it('should set up tabs', async () => {
const { harness } = await setupTest({ dataSkyId: 'tab-demo' });

const tabButtonHarnesses = await harness.getTabButtonHarnesses();
expect(tabButtonHarnesses.length).toBe(3);

const activeTab = await harness.getActiveTabButton();
await expectAsync(activeTab?.getTabHeading()).toBeResolvedTo('Tab 1');
});
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<sky-tabset ariaLabel="Tab demonstration" (newTab)="onNewTabClick()">
<sky-tabset
data-sky-id="tab-demo"
ariaLabel="Tab demonstration"
(newTab)="onNewTabClick()"
>
<sky-tab [tabHeading]="'Tab 1'"> Content for Tab 1 </sky-tab>
<sky-tab [tabHeading]="'Tab 2'"> Content for Tab 2 </sky-tab>
@if (showTab3) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { provideRouter } from '@angular/router';
import { SkyTabsetHarness } from '@skyux/tabs/testing';

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

describe('Static tabs demo with add and close', () => {
async function setupTest(options: { dataSkyId?: string }): Promise<{
harness: SkyTabsetHarness;
fixture: ComponentFixture<DemoComponent>;
}> {
await TestBed.configureTestingModule({
providers: [provideRouter([])],
}).compileComponents();
const fixture = TestBed.createComponent(DemoComponent);
const loader = TestbedHarnessEnvironment.loader(fixture);

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

return { harness, fixture };
}

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

it('should set up tabs', async () => {
const { harness, fixture } = await setupTest({ dataSkyId: 'tab-demo' });

const spy = spyOn(fixture.componentInstance, 'onNewTabClick');
await harness.clickNewTabButton();

expect(spy).toHaveBeenCalled();

const tabButtonHarnesses = await harness.getTabButtonHarnesses();
expect(tabButtonHarnesses.length).toBe(3);

const activeTab = await harness.getActiveTabButton();
await expectAsync(activeTab?.getTabHeading()).toBeResolvedTo('Tab 1');
});

it('should hide Tab 3 if it is closed', async () => {
const { harness } = await setupTest({ dataSkyId: 'tab-demo' });

const tab3Harness = await harness.getTabButtonHarness('Tab 3');
await tab3Harness.clickRemoveButton();

const tabButtons = await harness.getTabButtonHarnesses();
expect(tabButtons.length).toBe(2);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { SkyTabsModule } from '@skyux/tabs';
export class DemoComponent {
protected showTab3 = true;

protected onNewTabClick(): void {
public onNewTabClick(): void {
alert('Add tab clicked!');
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<sky-tabset ariaLabel="Tab demonstration">
<sky-tabset ariaLabel="Tab demonstration" data-sky-id="tab-demo">
<sky-tab [tabHeading]="'Tab 1'"> Content for Tab 1 </sky-tab>
<sky-tab [tabHeading]="'Tab 2'"> Content for Tab 2 </sky-tab>
<sky-tab [tabHeading]="'Tab 3'"> Content for Tab 3 </sky-tab>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { provideRouter } from '@angular/router';
import { SkyTabsetHarness } from '@skyux/tabs/testing';

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

describe('Static tabs demo with add and close', () => {
async function setupTest(options: { dataSkyId?: string }): Promise<{
harness: SkyTabsetHarness;
fixture: ComponentFixture<DemoComponent>;
}> {
await TestBed.configureTestingModule({
providers: [provideRouter([])],
}).compileComponents();
const fixture = TestBed.createComponent(DemoComponent);
const loader = TestbedHarnessEnvironment.loader(fixture);

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

return { harness, fixture };
}

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

it('should set up tabs', async () => {
const { harness } = await setupTest({ dataSkyId: 'tab-demo' });

const tabButtonHarnesses = await harness.getTabButtonHarnesses();
expect(tabButtonHarnesses.length).toBe(3);

const activeTab = await harness.getActiveTabButton();
await expectAsync(activeTab?.getTabHeading()).toBeResolvedTo('Tab 1');
});
});
58 changes: 11 additions & 47 deletions apps/playground/src/app/components/tabs/tabs/tabs.component.html
Original file line number Diff line number Diff line change
@@ -1,47 +1,11 @@
<sky-page>
<div id="screenshot-tabset" style="height: 200px">
<sky-tabset
permalinkId="sample"
[active]="1"
(newTab)="newTabClick()"
(openTab)="openTabClick()"
>
<sky-tab [disabled]="true" [tabHeading]="'Tab 1'" (close)="closeTab()">
Tab 1 Content
</sky-tab>
<sky-tab [tabHeading]="'Tab 2'" (close)="closeTab()">
Tab 2 Content
</sky-tab>
<sky-tab [tabHeading]="'Tab 3'" (close)="closeTab()">
Tab 3 Content
</sky-tab>
<sky-tab [tabHeading]="'Tab 4'" (close)="closeTab()">
Tab 4 Content
</sky-tab>
<sky-tab tabHeading="Permanent tab" [tabHeaderCount]="9">
This tab cannot be closed
</sky-tab>
<sky-tab
permalinkValue="foobar"
tabHeading="Tab 3"
[tabHeaderCount]="144"
(close)="closeTab()"
>
Tab 3 Content
</sky-tab>
</sky-tabset>
</div>

<div id="screenshot-tabset-long" style="margin-top: 300px; height: 200px">
<sky-tabset [active]="0">
<sky-tab
[tabHeading]="
'Tab 1 Content really really really long tab name you know here is even more header content okay okay okay'
"
>
Tab 1 Content
</sky-tab>
<sky-tab [tabHeading]="'Tab 2'"> Tab 2 Content </sky-tab>
</sky-tabset>
</div>
</sky-page>
<sky-tabset ariaLabel="Tab demonstration" (newTab)="onNewTabClick()">
<sky-tab [tabHeading]="'Tab 1'" [tabIndexValue]="tabIndexValue">
Content for Tab 1</sky-tab
>
<sky-tab [tabHeading]="'Tab 2'"> Content for Tab 2 </sky-tab>
@if (showTab3) {
<sky-tab [tabHeading]="'Tab 3'" (close)="showTab3 = false">
Content for Tab 3
</sky-tab>
}
</sky-tabset>
10 changes: 6 additions & 4 deletions apps/playground/src/app/components/tabs/tabs/tabs.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { SkyTabIndex } from '@skyux/tabs';

@Component({
selector: 'app-tabs',
Expand All @@ -7,9 +8,10 @@ import { ChangeDetectionStrategy, Component } from '@angular/core';
standalone: false,
})
export class TabsComponent {
public newTabClick() {}
protected showTab3 = true;
protected tabIndexValue: SkyTabIndex = '2';

public openTabClick() {}

public closeTab() {}
protected onNewTabClick(): void {
alert('Add tab clicked!');
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { HarnessPredicate } from '@angular/cdk/testing';
import { SkyComponentHarness, SkyOverlayHarness } from '@skyux/core/testing';
import {
SkyOverlayHarness,
SkyQueryableComponentHarness,
} from '@skyux/core/testing';

import { SkyDropdownItemHarness } from './dropdown-item-harness';
import { SkyDropdownItemHarnessFilters } from './dropdown-item-harness.filters';
Expand All @@ -8,7 +11,7 @@ import { SkyDropdownMenuHarnessFilters } from './dropdown-menu-harness.filters';
/**
* Harness for interacting with dropdown menu in tests.
*/
export class SkyDropdownMenuHarness extends SkyComponentHarness {
export class SkyDropdownMenuHarness extends SkyQueryableComponentHarness {
/**
* @internal
*/
Expand Down
Loading

0 comments on commit 37d2e90

Please sign in to comment.