Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(components/tabs): add harnesses for tab component #3064

Merged
merged 23 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -25,7 +25,7 @@ export class DemoComponent {

#tabCounter = 3;

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

this.tabArray.push({
Expand All @@ -34,7 +34,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 @@ -10,7 +10,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,14 +1,16 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { SkyTabIndex } from '@skyux/tabs';

@Component({
selector: 'app-tabs',
templateUrl: './tabs.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
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
Loading