Files
lore/src/app/staff/staff.spec.ts
T
naomi 0b5b4eadb9
Node.js CI / CI (push) Successful in 40s
Security Scan and Upload / Security & DefectDojo Upload (push) Successful in 1m29s
feat: new site (#1)
### Explanation

_No response_

### Issue

_No response_

### Attestations

- [ ] I have read and agree to the [Code of Conduct](https://docs.nhcarrigan.com/community/coc/)
- [ ] I have read and agree to the [Community Guidelines](https://docs.nhcarrigan.com/community/guide/).
- [ ] My contribution complies with the [Contributor Covenant](https://docs.nhcarrigan.com/dev/covenant/).

### Dependencies

- [ ] I have pinned the dependencies to a specific patch version.

### Style

- [ ] I have run the linter and resolved any errors.
- [ ] My pull request uses an appropriate title, matching the conventional commit standards.
- [ ] My scope of feat/fix/chore/etc. correctly matches the nature of changes in my pull request.

### Tests

- [ ] My contribution adds new code, and I have added tests to cover it.
- [ ] My contribution modifies existing code, and I have updated the tests to reflect these changes.
- [ ] All new and existing tests pass locally with my changes.
- [ ] Code coverage remains at or above the configured threshold.

### Documentation

_No response_

### Versioning

_No response_

Reviewed-on: #1
Co-authored-by: Naomi Carrigan <commits@nhcarrigan.com>
Co-committed-by: Naomi Carrigan <commits@nhcarrigan.com>
2025-12-28 04:54:35 +01:00

205 lines
6.7 KiB
TypeScript

/**
* @copyright NHCarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { type ComponentFixture, TestBed } from "@angular/core/testing";
import {
describe,
beforeEach,
it,
expect,
vi,
afterEach,
type MockedFunction,
} from "vitest";
import { bios } from "../config/bios";
import { staffNames } from "../config/staffNames";
import { Staff } from "./staff";
import type { Staff as StaffType } from "../../interfaces/staff";
describe("staff", () => {
let component: Staff;
let fixture: ComponentFixture<Staff>;
let scrollToSpy: MockedFunction<typeof globalThis.window.scrollTo>;
beforeEach(async() => {
scrollToSpy = vi.spyOn(globalThis.window, "scrollTo").
mockImplementation(vi.fn());
await TestBed.configureTestingModule({
imports: [ Staff ],
}).compileComponents();
fixture = TestBed.createComponent(Staff);
component = fixture.componentInstance;
await fixture.whenStable();
});
afterEach(() => {
scrollToSpy.mockRestore();
});
it("should create", () => {
expect.assertions(1);
expect(component, "did not compile").toBeTruthy();
});
it("should initialize with no staff member selected", () => {
expect.assertions(1);
// @ts-expect-error - We want it protected, but need to use it in the test.
expect(component.staffName(),
"should start with no staff member").toBeUndefined();
});
it("should select a staff member", () => {
expect.assertions(2);
const staffMember: StaffType = "naomi";
component.selectStaffMember(staffMember);
// @ts-expect-error - We want it protected, but need to use it in the test.
expect(component.staffName(),
"should have selected staff member").toBe(staffMember);
expect(scrollToSpy, "should scroll to top").
toHaveBeenCalledWith({ behavior: "smooth", top: 0 });
});
it("should deselect staff member when undefined is passed", () => {
expect.assertions(2);
component.selectStaffMember("naomi");
// @ts-expect-error - We want it protected, but need to use it in the test.
expect(component.staffName(),
"should have selected staff member").toBe("naomi");
component.selectStaffMember(undefined);
// @ts-expect-error - We want it protected, but need to use it in the test.
expect(component.staffName(),
"should deselect staff member").toBeUndefined();
});
it("should get bio for selected staff member", () => {
expect.assertions(2);
const staffMember: StaffType = "naomi";
component.selectStaffMember(staffMember);
const bio = component.getBio();
expect(bio, "should return bio array").toBeInstanceOf(Array);
expect(bio.length, "bio should have content").toBeGreaterThan(0);
});
it("should return empty array when no staff member is selected", () => {
expect.assertions(1);
const bio = component.getBio();
expect(bio, "should return empty array").toStrictEqual([]);
});
it("should return correct bio for each staff member", () => {
expect.assertions(8);
const staffMembers: Array<StaffType> = [
"naomi",
"hikari",
"amari",
"keiko",
"yumiko",
"tatsumi",
"reina",
"minori",
];
for (const member of staffMembers) {
component.selectStaffMember(member);
const bio = component.getBio();
expect(bio, `should return bio for ${member}`).toStrictEqual(bios[member]);
}
});
it("should get name for selected staff member", () => {
expect.assertions(2);
const staffMember: StaffType = "naomi";
component.selectStaffMember(staffMember);
const name = component.getName();
expect(name, "should return name").toBeDefined();
expect(name, "should return correct name").toBe(staffNames[staffMember]);
});
it("should return undefined name when no staff member is selected", () => {
expect.assertions(1);
const name = component.getName();
expect(name, "should return undefined").toBeUndefined();
});
it("should return correct name for each staff member", () => {
expect.assertions(8);
const staffMembers: Array<StaffType> = [
"naomi",
"hikari",
"amari",
"keiko",
"yumiko",
"tatsumi",
"reina",
"minori",
];
for (const member of staffMembers) {
component.selectStaffMember(member);
const name = component.getName();
expect(name, `should return correct name for ${member}`).toBe(staffNames[member]);
}
});
it("should scroll to top when selecting staff member", () => {
expect.assertions(1);
component.selectStaffMember("naomi");
expect(scrollToSpy, "should scroll to top").
toHaveBeenCalledWith({ behavior: "smooth", top: 0 });
});
it("should scroll to top when deselecting staff member", () => {
expect.assertions(1);
scrollToSpy.mockClear();
component.selectStaffMember("naomi");
scrollToSpy.mockClear();
component.selectStaffMember(undefined);
expect(scrollToSpy, "should scroll to top").
toHaveBeenCalledWith({ behavior: "smooth", top: 0 });
});
it("should render staff list when no member is selected", () => {
expect.assertions(1);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
const heading = compiled.querySelector("h1");
expect(heading?.textContent.trim(),
"should render staff list heading").toBe("OUR STAFF");
});
it("should render staff member details when selected", () => {
expect.assertions(3);
component.selectStaffMember("naomi");
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
const heading = compiled.querySelector("h1");
const backButton = compiled.querySelector("button");
expect(heading?.textContent.trim(),
"should render staff member name").toBe(staffNames.naomi);
expect(backButton?.textContent.trim(),
"should render back button").toContain("Back to Staff");
const paragraphs = compiled.querySelectorAll("p");
expect(paragraphs.length, "should render bio paragraphs").
toBeGreaterThan(0);
});
it("should handle back button click", () => {
expect.assertions(2);
scrollToSpy.mockClear();
component.selectStaffMember("naomi");
scrollToSpy.mockClear();
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
const backButton = compiled.querySelector("button") as HTMLButtonElement;
backButton.click();
fixture.detectChanges();
// @ts-expect-error - We want it protected, but need to use it in the test.
expect(component.staffName(),
"should deselect staff member").toBeUndefined();
expect(scrollToSpy, "should scroll to top").
toHaveBeenCalledWith({ behavior: "smooth", top: 0 });
});
});