Skip to content
Open
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
1 change: 1 addition & 0 deletions libs/components/grids/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
},
"homepage": "https://github.com/blackbaud/skyux#readme",
"peerDependencies": {
"@angular/cdk": "^20.2.3",
"@angular/common": "^20.3.0",
"@angular/core": "^20.3.0",
"@angular/forms": "^20.3.0",
Expand Down
20 changes: 17 additions & 3 deletions libs/components/grids/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"projectType": "library",
"sourceRoot": "libs/components/grids/src",
"prefix": "sky",
"tags": ["component", "npm"],
"targets": {
"build": {
"executor": "@nx/angular:package",
Expand All @@ -19,7 +20,21 @@
"tsConfig": "libs/components/grids/tsconfig.lib.json"
}
},
"defaultConfiguration": "production"
"defaultConfiguration": "production",
"dependsOn": [
"^build",
{
"projects": ["core"],
"target": "build"
}
],
"inputs": [
"buildInputs",
"^buildInputs",
"{workspaceRoot}/libs/components/grids/testing/src/**/*",
"!{workspaceRoot}/libs/components/grids/testing/src/**/*.spec.ts",
"!{workspaceRoot}/libs/components/grids/testing/src/**/fixtures/**/*"
]
},
"test": {
"executor": "@angular-devkit/build-angular:karma",
Expand Down Expand Up @@ -61,6 +76,5 @@
]
}
}
},
"tags": ["component", "npm"]
}
}
5 changes: 5 additions & 0 deletions libs/components/grids/testing/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const prettier = require('eslint-config-prettier');
const baseConfig = require('../../../../eslint-base.config');
const overrides = require('../../../../eslint-overrides.config');

module.exports = [...baseConfig, ...overrides, prettier];
19 changes: 19 additions & 0 deletions libs/components/grids/testing/karma.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html

const { join } = require('path');
const getBaseKarmaConfig = require('../../../../karma.conf');

module.exports = function (config) {
const baseConfig = getBaseKarmaConfig();
config.set({
...baseConfig,
coverageReporter: {
...baseConfig.coverageReporter,
dir: join(
__dirname,
'../../../../coverage/libs/components/grids/testing',
),
},
});
};
5 changes: 5 additions & 0 deletions libs/components/grids/testing/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"lib": {
"entryFile": "src/public-api.ts"
}
}
47 changes: 47 additions & 0 deletions libs/components/grids/testing/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "grids-testing",
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
"projectType": "library",
"sourceRoot": "libs/components/grids/testing/src",
"prefix": "sky",
"tags": ["testing"],
"targets": {
"test": {
"executor": "@angular-devkit/build-angular:karma",
"options": {
"tsConfig": "libs/components/grids/testing/tsconfig.spec.json",
"karmaConfig": "libs/components/grids/testing/karma.conf.js",
"codeCoverage": true,
"codeCoverageExclude": ["**/fixtures/**"],
"styles": [
"libs/components/theme/src/lib/styles/sky.scss",
"libs/components/theme/src/lib/styles/themes/modern/styles.scss"
],
"polyfills": [
"zone.js",
"zone.js/testing",
"libs/components/packages/src/polyfills.js"
],
"inlineStyleLanguage": "scss",
"stylePreprocessorOptions": {
"includePaths": ["{workspaceRoot}"]
}
},
"configurations": {
"ci": {
"browsers": "ChromeHeadlessNoSandbox",
"codeCoverage": true,
"progress": false,
"sourceMap": true,
"watch": false
}
}
},
"lint": {
"executor": "@nx/eslint:lint",
"options": {
"lintFilePatterns": ["{projectRoot}/src/**/*.ts"]
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { SkyHarnessFilters } from '@skyux/core/testing';

/**
* A set of criteria that can be used to filter a list of `SkyGridHarness` instances.
*/
// eslint-disable-next-line @typescript-eslint/no-empty-interface, @typescript-eslint/no-empty-object-type
export interface SkyGridHarnessFilters extends SkyHarnessFilters {}
188 changes: 188 additions & 0 deletions libs/components/grids/testing/src/modules/grid/grid-harness.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { Component } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { expect } from '@skyux-sdk/testing';
import { SkyGridModule } from '@skyux/grids';

import { SkyGridHarness } from './grid-harness';

//#region Test Component
@Component({
selector: 'sky-grid-test',
template: `
<sky-grid
[data]="data"
[enableMultiselect]="enableMultiselect"
[selectedRowIds]="selectedRowIds"
[rowHighlightedId]="rowHighlightedId"
>
<sky-grid-column field="name" heading="Name" />
<sky-grid-column field="age" heading="Age" />
</sky-grid>
<sky-grid data-sky-id="other-grid" [data]="otherData">
<sky-grid-column field="name" heading="Name" />
<sky-grid-column field="age" heading="Age" />
</sky-grid>
`,
standalone: false,
})
class TestComponent {
public data = [
{ id: '1', name: 'John', age: 30 },
{ id: '2', name: 'Jane', age: 25 },
{ id: '3', name: 'Bob', age: 35 },
];

public otherData = [{ id: '4', name: 'Alice', age: 28 }];

public enableMultiselect = false;
public selectedRowIds: string[] = [];
public rowHighlightedId: string | undefined;
}
//#endregion Test Component

describe('Grid harness', () => {
async function setupTest(options: { dataSkyId?: string } = {}): Promise<{
gridHarness: SkyGridHarness;
fixture: ComponentFixture<TestComponent>;
loader: HarnessLoader;
}> {
await TestBed.configureTestingModule({
declarations: [TestComponent],
imports: [SkyGridModule],
}).compileComponents();

const fixture = TestBed.createComponent(TestComponent);
const loader = TestbedHarnessEnvironment.loader(fixture);

let gridHarness: SkyGridHarness;

if (options.dataSkyId) {
gridHarness = await loader.getHarness(
SkyGridHarness.with({
dataSkyId: options.dataSkyId,
}),
);
} else {
gridHarness = await loader.getHarness(SkyGridHarness);
}

fixture.detectChanges();

return { gridHarness, fixture, loader };
}

it('should get the grid from its data-sky-id', async () => {
const { gridHarness } = await setupTest({
dataSkyId: 'other-grid',
});
const rowCount = await gridHarness.getRowCount();
expect(rowCount).toBe(1);
});

it('should get the column count', async () => {
const { gridHarness } = await setupTest();
const columnCount = await gridHarness.getColumnCount();
expect(columnCount).toBe(2);
});

it('should get the column headings', async () => {
const { gridHarness } = await setupTest();
const headings = await gridHarness.getColumnHeadings();
expect(headings.length).toBe(2);
});

it('should get the row count', async () => {
const { gridHarness } = await setupTest();
const rowCount = await gridHarness.getRowCount();
expect(rowCount).toBe(3);
});

it('should get cell text', async () => {
const { gridHarness } = await setupTest();
const cellText = await gridHarness.getCellText(0, 0);
expect(cellText).toBe('John');
});

it('should throw error for invalid row index when getting cell text', async () => {
const { gridHarness } = await setupTest();
await expectAsync(gridHarness.getCellText(10, 0)).toBeRejectedWithError(
'Row index 10 is out of bounds. Grid has 3 rows.',
);
});

it('should throw error for invalid column index when getting cell text', async () => {
const { gridHarness } = await setupTest();
await expectAsync(gridHarness.getCellText(0, 10)).toBeRejectedWithError(
'Column index 10 is out of bounds. Row has 2 columns.',
);
});

it('should check if multiselect is enabled', async () => {
const { gridHarness, fixture } = await setupTest();
expect(await gridHarness.hasMultiselect()).toBe(false);

fixture.componentInstance.enableMultiselect = true;
fixture.detectChanges();

expect(await gridHarness.hasMultiselect()).toBe(true);
});

it('should check if row is selected', async () => {
const { gridHarness, fixture } = await setupTest();
fixture.componentInstance.enableMultiselect = true;
fixture.componentInstance.selectedRowIds = ['1'];
fixture.detectChanges();

expect(await gridHarness.isRowSelected(0)).toBe(true);
expect(await gridHarness.isRowSelected(1)).toBe(false);
});

it('should throw error for invalid row index when checking selection', async () => {
const { gridHarness } = await setupTest();
await expectAsync(gridHarness.isRowSelected(10)).toBeRejectedWithError(
'Row index 10 is out of bounds. Grid has 3 rows.',
);
});

it('should check if row is highlighted', async () => {
const { gridHarness, fixture } = await setupTest();
fixture.componentInstance.rowHighlightedId = '2';
fixture.detectChanges();

expect(await gridHarness.isRowHighlighted(0)).toBe(false);
expect(await gridHarness.isRowHighlighted(1)).toBe(true);
});

it('should throw error for invalid row index when checking highlight', async () => {
const { gridHarness } = await setupTest();
await expectAsync(gridHarness.isRowHighlighted(10)).toBeRejectedWithError(
'Row index 10 is out of bounds. Grid has 3 rows.',
);
});

it('should click a row', async () => {
const { gridHarness } = await setupTest();
await gridHarness.clickRow(0);
});

it('should throw error for invalid row index when clicking', async () => {
const { gridHarness } = await setupTest();
await expectAsync(gridHarness.clickRow(10)).toBeRejectedWithError(
'Row index 10 is out of bounds. Grid has 3 rows.',
);
});

it('should click a column header', async () => {
const { gridHarness } = await setupTest();
await gridHarness.clickColumnHeader(0);
});

it('should throw error for invalid column index when clicking header', async () => {
const { gridHarness } = await setupTest();
await expectAsync(gridHarness.clickColumnHeader(10)).toBeRejectedWithError(
'Column index 10 is out of bounds. Grid has 2 columns.',
);
});
});
Loading
Loading