- Settings gets an Integrations tab: connection fields with a write-only API secret, a CA PEM option, Test connection with versions and warnings, live mapping lists loaded after a test, naming mode, toggles and its own Save. - Pushing for a GST-registered vendor is refused until a connection test result is stored. The UI shows the reason and disables Send. - History shows an ERPNext status column from one bulk call, a row Send and Open in ERPNext, and a bulk Send selected with a draft-or-submit confirm step and per-row results that never abort the batch. The detail view gets an ERPNext panel and per-payment send. All of it is hidden or disabled when the integration is not configured. - Optional auto-push after issue runs in the background and never blocks or fails the issue. - Generic export: a deterministic voiced.invoice.v1 JSON (and CSV line items) for selected invoices, documented in docs/voiced-invoice-v1.md with a golden test. Money is integer paise plus a decimal string. The new screens have not been run in a webview yet. The ERPNext Payment Entry deduction fields still need a live check.
24 lines
1010 B
TypeScript
24 lines
1010 B
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { SETTINGS_TABS, loadSettingsTab, parseSettingsTab, requestSettingsTab, saveSettingsTab } from "./settingsTab";
|
|
|
|
describe("settings tab persistence", () => {
|
|
it("maps stored ids to indexes and falls back to the first tab", () => {
|
|
expect(parseSettingsTab("fonts")).toBe(SETTINGS_TABS.findIndex((t) => t.id === "fonts"));
|
|
expect(parseSettingsTab("nope")).toBe(0);
|
|
expect(parseSettingsTab(null)).toBe(0);
|
|
});
|
|
|
|
it("does not throw when storage is unavailable", () => {
|
|
// The node test environment has no localStorage at all.
|
|
expect(loadSettingsTab()).toBe(0);
|
|
expect(() => saveSettingsTab(2)).not.toThrow();
|
|
expect(() => saveSettingsTab(99)).not.toThrow();
|
|
});
|
|
|
|
it("honours a requested tab once, then goes back to the stored one", () => {
|
|
requestSettingsTab("integrations");
|
|
expect(loadSettingsTab()).toBe(SETTINGS_TABS.findIndex((t) => t.id === "integrations"));
|
|
expect(loadSettingsTab()).toBe(0);
|
|
});
|
|
});
|