← back to Homesonspec
collectors/david-weekley/src/index.test.ts
76 lines
import { readFileSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import { davidWeekleyAdapter, parseHomes } from "./index";
const FIXTURE = readFileSync(
join(import.meta.dirname, "..", "fixtures", "dfw-homes-ready-soon.html"),
"utf8",
);
const PAGE_URL = "https://www.davidweekleyhomes.com/new-homes/tx/dallas-ft-worth/homes-ready-soon";
describe("david-weekley adapter", () => {
it("has the registry-matching key", () => {
expect(davidWeekleyAdapter.key).toBe("david-weekley-site");
});
it("parses per-home QMI cards with full facts from the DFW list page", () => {
const homes = parseHomes(FIXTURE);
expect(homes.length).toBeGreaterThan(0);
const h = homes[0]!;
// real per-home fields, not community ranges
expect(h.jobNumber).toMatch(/^\d{4,}$/);
expect(h.street).toBeTruthy();
expect(h.state).toBe("TX");
expect(typeof h.price).toBe("number");
expect(h.price! > 100000 && h.price! < 5_000_000).toBe(true);
});
it("splits address into street / city / state / zip", () => {
const homes = parseHomes(FIXTURE);
const withZip = homes.find((x) => x.zip);
expect(withZip).toBeTruthy();
expect(withZip!.zip).toMatch(/^\d{5}$/);
expect(withZip!.city).toBeTruthy();
expect(withZip!.street).not.toMatch(/,/); // city/state/zip stripped off
});
it("extract() emits inventory_home records that pass basic shape", () => {
const out = davidWeekleyAdapter.extract({
url: PAGE_URL,
retrievedAt: new Date().toISOString(),
contentType: "text/html",
body: Buffer.from(FIXTURE, "utf8"),
contentHash: "test",
});
expect(out.errors).toHaveLength(0);
const homes = out.records.filter((r) => r.entityType === "inventory_home");
expect(homes.length).toBeGreaterThan(0);
const f = homes[0]!.fields;
expect((f.price as { value: number }).value).toBeGreaterThan(0);
expect((f.street as { value: string }).value).toBeTruthy();
expect(["MOVE_IN_READY", "UNDER_CONSTRUCTION"]).toContain((f.constructionStatus as { value: string }).value);
expect((f.builderInventoryId as { value: string }).value).toMatch(/^\d{4,}$/);
// facts-only: no images
expect((f.images as { value: string[] }).value).toEqual([]);
});
it("does not emit duplicate homes for the same jobNumber", () => {
const homes = parseHomes(FIXTURE);
const jobs = homes.map((h) => h.jobNumber);
expect(new Set(jobs).size).toBe(jobs.length);
});
it("emits a community record per distinct community", () => {
const out = davidWeekleyAdapter.extract({
url: PAGE_URL,
retrievedAt: new Date().toISOString(),
contentType: "text/html",
body: Buffer.from(FIXTURE, "utf8"),
contentHash: "test",
});
const comms = out.records.filter((r) => r.entityType === "community");
expect(comms.length).toBeGreaterThan(0);
});
});