From 599fe6d4f57505a090e3531bb0947469d52f0ea6 Mon Sep 17 00:00:00 2001 From: Mike Nichols Date: Thu, 9 Jan 2025 10:46:44 -0600 Subject: [PATCH] Rewrite tests to use transparent test data --- src/__tests__/expiration-year.ts | 380 ++++++++++++------------------- 1 file changed, 140 insertions(+), 240 deletions(-) diff --git a/src/__tests__/expiration-year.ts b/src/__tests__/expiration-year.ts index 4331d27..13bd0d8 100644 --- a/src/__tests__/expiration-year.ts +++ b/src/__tests__/expiration-year.ts @@ -1,263 +1,163 @@ import { expirationYear, ExpirationYearVerification } from "../expiration-year"; -const currentYear = new Date().getFullYear(); +const INVALID: ExpirationYearVerification = { + isValid: false, + isPotentiallyValid: false, + isCurrentYear: false, +}; -function yearsFromNow(fromNow: number, digits?: number): string { - let result = String(currentYear + fromNow); +const POTENTIALLY_VALID: ExpirationYearVerification = { + isValid: false, + isPotentiallyValid: true, + isCurrentYear: false, +}; - if (digits === 2) { - result = result.substr(2, 2); - } +const VALID: ExpirationYearVerification = { + isValid: true, + isPotentiallyValid: true, + isCurrentYear: false, +}; - return result; -} +const CURRENT_YEAR: ExpirationYearVerification = { + isValid: true, + isPotentiallyValid: true, + isCurrentYear: true, +}; describe("expirationYear", () => { - const FALSE_VALIDATION = { - isValid: false, - isPotentiallyValid: false, - isCurrentYear: false, - }; + // Date picked at random from the past 5 years + const mockToday = new Date(2021, 5, 9); + jest.useFakeTimers().setSystemTime(mockToday); - describe.each([ - [ - "returns false if not a string", - [ - [[], FALSE_VALIDATION], - [{}, FALSE_VALIDATION], - [null, FALSE_VALIDATION], - [undefined, FALSE_VALIDATION], // eslint-disable-line no-undefined - [Infinity, FALSE_VALIDATION], - [0 / 0, FALSE_VALIDATION], - [0, FALSE_VALIDATION], - [1, FALSE_VALIDATION], - [2, FALSE_VALIDATION], - [12, FALSE_VALIDATION], - [-1, FALSE_VALIDATION], - [-12, FALSE_VALIDATION], - ], - ], + describe("given a non-string value", () => { + test.each([ + [[], INVALID], + [{}, INVALID], + [null, INVALID], + [undefined, INVALID], // eslint-disable-line no-undefined + [Infinity, INVALID], + [0 / 0, INVALID], + [0, INVALID], + [1, INVALID], + [2, INVALID], + [12, INVALID], + [-1, INVALID], + [-12, INVALID], + ])("%p is invalid", (value, output) => { + expect(expirationYear(value)).toEqual(output); + }); + }); - [ - "returns false for malformed strings", - [ - ["foo", FALSE_VALIDATION], - ["1.2", FALSE_VALIDATION], - ["1/20", FALSE_VALIDATION], - ["1 2", FALSE_VALIDATION], - ["1 ", FALSE_VALIDATION], - [" 1", FALSE_VALIDATION], - ["20015", FALSE_VALIDATION], - ], - ], + describe("given an empty string", () => { + it("returns as potentially valid", () => { + expect(expirationYear("")).toEqual(POTENTIALLY_VALID); + }); + }); - [ - "returns the appropriate values for incomplete strings", - [ - [ - "", - { isValid: false, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - "2", - { isValid: false, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - "9", - { isValid: false, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - "200", - { isValid: false, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - "123", - { isValid: false, isPotentiallyValid: false, isCurrentYear: false }, - ], - [ - "20", - { isValid: false, isPotentiallyValid: true, isCurrentYear: false }, - ], - ], - ], + describe("given only whitespace", () => { + it("returns as potentially valid", () => { + expect(expirationYear(" ")).toEqual(POTENTIALLY_VALID); + }); + }); - [ - "accepts four-digit years", - [ - [ - yearsFromNow(0), - { isValid: true, isPotentiallyValid: true, isCurrentYear: true }, - ], - [ - yearsFromNow(-5), - { isValid: false, isPotentiallyValid: false, isCurrentYear: false }, - ], - [ - yearsFromNow(5), - { isValid: true, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - yearsFromNow(10), - { isValid: true, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - yearsFromNow(11), - { isValid: true, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - yearsFromNow(12), - { isValid: true, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - yearsFromNow(19), - { isValid: true, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - yearsFromNow(20), - { isValid: false, isPotentiallyValid: false, isCurrentYear: false }, - ], - [ - yearsFromNow(25), - { isValid: false, isPotentiallyValid: false, isCurrentYear: false }, - ], - [ - yearsFromNow(33), - { isValid: false, isPotentiallyValid: false, isCurrentYear: false }, - ], - ], - ], + describe("given a malformed string value", () => { + test.each([ + ["foo", INVALID], + ["1.2", INVALID], + ["1/20", INVALID], + ["1 2", INVALID], + ["1 ", INVALID], + [" 1", INVALID], + ["20015", INVALID], + ])("%p is invalid", (value, output) => { + expect(expirationYear(value)).toEqual(output); + }); + }); - [ - "accepts two-digit years", - [ - [ - "19", - { isValid: false, isPotentiallyValid: false, isCurrentYear: false }, - ], - [ - "20", - { isValid: false, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - // When this test case fails in 2081 (because 21 will become a valid - // year prefix) you can just switch isPotentiallyValid to true and - // delete this comment. - "21", - { isValid: false, isPotentiallyValid: false, isCurrentYear: false }, - ], - [ - yearsFromNow(0, 2), - { isValid: true, isPotentiallyValid: true, isCurrentYear: true }, - ], - [ - yearsFromNow(5, 2), - { isValid: true, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - yearsFromNow(10, 2), - { isValid: true, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - yearsFromNow(11, 2), - { isValid: true, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - yearsFromNow(12, 2), - { isValid: true, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - yearsFromNow(19, 2), - { isValid: true, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - yearsFromNow(20, 2), - { isValid: false, isPotentiallyValid: false, isCurrentYear: false }, - ], - [ - yearsFromNow(25, 2), - { isValid: false, isPotentiallyValid: false, isCurrentYear: false }, - ], - [ - yearsFromNow(33, 2), - { isValid: false, isPotentiallyValid: false, isCurrentYear: false }, - ], - ], - ], + describe("given a 1 digit string", () => { + describe("that's not a number", () => { + test.each( + ["a", "#", ";", "\\", "+"] + )("%p is invalid", (value) => { + expect(expirationYear(value)).toEqual(INVALID); + }); + }); - /* - * This doesn't take 20xx -> 21xx into account, but probably YAGNI - * (with apologies to whoever is possibly looking at this legacy - * code long after we're dead - * */ - [ - "accepts three-digit years", - [ - [ - yearsFromNow(-3).slice(0, 3), - { isValid: false, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - yearsFromNow(-1).slice(0, 3), - { isValid: false, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - yearsFromNow(0).slice(0, 3), - { isValid: false, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - yearsFromNow(1).slice(0, 3), - { isValid: false, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - yearsFromNow(5).slice(0, 3), - { isValid: false, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - yearsFromNow(11).slice(0, 3), - { isValid: false, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - yearsFromNow(17).slice(0, 3), - { isValid: false, isPotentiallyValid: true, isCurrentYear: false }, - ], - [ - yearsFromNow(23).slice(0, 3), - { isValid: false, isPotentiallyValid: true, isCurrentYear: false }, - ], - ], - ], - ] as Array<[string, Array<[unknown, ExpirationYearVerification]>]>)( - "%s", - (description, tests) => { - it.each(tests)("parses %s to be %p", (exp, meta) => { - expect(expirationYear(exp)).toEqual(meta); + describe("that is a number", () => { + test.each( + ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] + )("%p is potentially valid", (value) => { + expect(expirationYear(value)).toEqual(POTENTIALLY_VALID); }); - }, - ); + }); + }); - it("defaults maxElapsedYear is 19", () => { - expect(expirationYear(yearsFromNow(19))).toEqual({ - isValid: true, - isPotentiallyValid: true, - isCurrentYear: false, + describe("given a 2 digit string", () => { + test.each([ + ["19", INVALID], + ["20", POTENTIALLY_VALID], + ["21", CURRENT_YEAR], + ["22", VALID], + ["40", VALID], + ["41", INVALID], + ])("%p gives expected output", (value, output) => { + expect(expirationYear(value)).toEqual(output); }); - expect(expirationYear(yearsFromNow(20))).toEqual({ - isValid: false, - isPotentiallyValid: false, - isCurrentYear: false, + }); + + describe("given a 3 digit string", () => { + test.each([ + ["000", INVALID], + ["123", INVALID], + ["200", POTENTIALLY_VALID], + ["201", POTENTIALLY_VALID], + ["202", POTENTIALLY_VALID], + ["203", POTENTIALLY_VALID], + ["204", POTENTIALLY_VALID], + ["205", POTENTIALLY_VALID], + ["206", POTENTIALLY_VALID], + ["207", POTENTIALLY_VALID], + ["208", POTENTIALLY_VALID], + ["209", POTENTIALLY_VALID], + ["210", INVALID], + ["300", INVALID], + ["999", INVALID], + ])("%p gives expected output", (value, output) => { + expect(expirationYear(value)).toEqual(output); }); }); - it("accepts maxElapsedYear", () => { - expect(expirationYear(yearsFromNow(20), 20)).toEqual({ - isValid: true, - isPotentiallyValid: true, - isCurrentYear: false, + describe("given a 4 digit string", () => { + test.each([ + ["0000", INVALID], + ["1234", INVALID], + ["2020", INVALID], + ["2021", CURRENT_YEAR], + ["2022", VALID], + ["2040", VALID], + ["2041", INVALID], + ["3000", INVALID], + ["9999", INVALID], + ])("%p gives expected output", (value, output) => { + expect(expirationYear(value)).toEqual(output); }); - expect(expirationYear(yearsFromNow(21), 20)).toEqual({ - isValid: false, - isPotentiallyValid: false, - isCurrentYear: false, + }); + + describe("given a more than 4 digit string", () => { + test.each( + ["00000", "12345", "20021", "20202", "20211", "30000", "99999"] + )("%p is invalid", (value) => { + expect(expirationYear(value)).toEqual(INVALID); + }); + }); + + describe("given a custom max elapsed year", () => { + it("uses it correctly", () => { + expect(expirationYear("2020", 5)).toEqual(INVALID); + expect(expirationYear("2021", 5)).toEqual(CURRENT_YEAR); + expect(expirationYear("2022", 5)).toEqual(VALID); + expect(expirationYear("2026", 5)).toEqual(VALID); + expect(expirationYear("2027", 5)).toEqual(INVALID); }); }); });