import { describe, expect, it } from "vitest"; import { clientGstinStateError, gstinChecksumError, gstinFullError, vendorGstinError } from "./validators"; // Same GSTINs as the Rust tests in src-tauri/src/gst.rs. describe("GSTIN checksum", () => { it("accepts valid GSTINs", () => { expect(gstinChecksumError("27AAPFU0939F1ZV")).toBeUndefined(); expect(gstinChecksumError("07AAGFF2194N1Z1")).toBeUndefined(); expect(gstinChecksumError("29ABCDE1234F1ZW")).toBeUndefined(); }); it("rejects a wrong check digit and bad shapes", () => { expect(gstinChecksumError("29ABCDE1234F1Z5")).toMatch(/expected W/); expect(gstinChecksumError("27AAPFU0939F1ZX")).toMatch(/check digit/); expect(gstinChecksumError("27AAPFU0939F1Z")).toMatch(/15-character/); }); it("cross-checks the PAN and the state", () => { expect(gstinFullError("27AAPFU0939F1ZV", "AAPFU0939F")).toBeUndefined(); expect(gstinFullError("27AAPFU0939F1ZV", "AAPFU0939G")).toMatch(/PAN/); expect(gstinFullError("")).toBeUndefined(); expect(vendorGstinError("unregistered", "", "", "29")).toBeUndefined(); expect(vendorGstinError("regular", "", "", "27")).toMatch(/needs a GSTIN/); expect(vendorGstinError("regular", "27AAPFU0939F1ZV", "AAPFU0939F", "29")).toMatch(/state code/); expect(vendorGstinError("regular", "27AAPFU0939F1ZV", "AAPFU0939F", "27")).toBeUndefined(); }); }); describe("clientGstinStateError", () => { it("allows empty and NA", () => { expect(clientGstinStateError("", "29")).toBeUndefined(); expect(clientGstinStateError("NA", "29")).toBeUndefined(); }); it("checks shape and checksum", () => { expect(clientGstinStateError("29ABCDE1234F1Z5", "29")).toMatch(/check digit/); expect(clientGstinStateError("29ABC", "")).toMatch(/15-character/); }); it("checks the state prefix only when a state is chosen", () => { expect(clientGstinStateError("29ABCDE1234F1ZW", "29")).toBeUndefined(); expect(clientGstinStateError("29abcde1234f1zw", "")).toBeUndefined(); expect(clientGstinStateError("29ABCDE1234F1ZW", "27")).toMatch(/starts with 29/); }); });