Skip to content

Commit 420145a

Browse files
Refactor: strict types, DRY field mapping, SRP extraction, runtime validation
1 parent b7e5eb1 commit 420145a

2 files changed

Lines changed: 133 additions & 148 deletions

File tree

nuforc_scraper.test.ts

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ describe("parseSighting", () => {
1414
"2024-01-16",
1515
"Y",
1616
null,
17-
];
18-
const result = parseSighting(row);
17+
] as const;
18+
const result = parseSighting([...row]);
1919
expect(result.id).toBe("12345");
2020
expect(result.href).toBe("https://nuforc.org/sighting/?id=12345");
2121
expect(result.occurredAt).toBe("2024-01-15");
@@ -41,8 +41,8 @@ describe("parseSighting", () => {
4141
"2024-02-02",
4242
"N",
4343
null,
44-
];
45-
const result = parseSighting(row);
44+
] as const;
45+
const result = parseSighting([...row]);
4646
expect(result.id).toBe("");
4747
expect(result.href).toBe("");
4848
expect(result.city).toBe("Denver");
@@ -61,8 +61,8 @@ describe("parseSighting", () => {
6161
null,
6262
null,
6363
null,
64-
];
65-
const result = parseSighting(row);
64+
] as const;
65+
const result = parseSighting([...row]);
6666
expect(result.id).toBe("99");
6767
expect(result.occurredAt).toBe("");
6868
expect(result.city).toBeNull();
@@ -79,21 +79,21 @@ describe("parseSighting", () => {
7979
const makeRow = (media: string | null) => [
8080
'<a href="https://nuforc.org/sighting/?id=1">X</a>',
8181
"", null, null, null, null, null, null, media, null,
82-
];
83-
expect(parseSighting(makeRow("Y")).mediaIncluded).toBe(true);
84-
expect(parseSighting(makeRow("N")).mediaIncluded).toBe(false);
85-
expect(parseSighting(makeRow("")).mediaIncluded).toBe(false);
86-
expect(parseSighting(makeRow(null)).mediaIncluded).toBe(false);
82+
] as const;
83+
expect(parseSighting([...makeRow("Y")]).mediaIncluded).toBe(true);
84+
expect(parseSighting([...makeRow("N")]).mediaIncluded).toBe(false);
85+
expect(parseSighting([...makeRow("")]).mediaIncluded).toBe(false);
86+
expect(parseSighting([...makeRow(null)]).mediaIncluded).toBe(false);
8787
});
8888

8989
it("handles malformed HTML without throwing", () => {
9090
const row = [
9191
'<a href="broken>no closing quote',
9292
"2024-01-01",
9393
null, null, null, null, null, null, null, null,
94-
];
95-
expect(() => parseSighting(row)).not.toThrow();
96-
const result = parseSighting(row);
94+
] as const;
95+
expect(() => parseSighting([...row])).not.toThrow();
96+
const result = parseSighting([...row]);
9797
expect(result).toHaveProperty("id");
9898
expect(result).toHaveProperty("occurredAt", "2024-01-01");
9999
});
@@ -126,6 +126,25 @@ describe("parseArgs", () => {
126126
expect(result.force).toBe(false);
127127
expect(result.pretty).toBe(false);
128128
});
129+
130+
// M3: parseArgs now throws for invalid --max-records values
131+
it("throws for --max-records=abc", () => {
132+
expect(() => parseArgs(["node", "script.ts", "--max-records=abc"])).toThrow(
133+
"Invalid value for --max-records. Must be a positive number."
134+
);
135+
});
136+
137+
it("throws for --max-records=0", () => {
138+
expect(() => parseArgs(["node", "script.ts", "--max-records=0"])).toThrow(
139+
"Invalid value for --max-records. Must be a positive number."
140+
);
141+
});
142+
143+
it("throws for --max-records=-5", () => {
144+
expect(() => parseArgs(["node", "script.ts", "--max-records=-5"])).toThrow(
145+
"Invalid value for --max-records. Must be a positive number."
146+
);
147+
});
129148
});
130149

131150
describe("shouldAbortWrite", () => {

0 commit comments

Comments
 (0)