Test file
Connector contracts and signatures
Each provider’s signature checked against the exact bytes received, tokens encrypted to their workspace, rate limits, retry timing and order parsing.
tests/integrations.test.ts · 133 lines
import { describe, it, expect } from "vitest";
import { randomBytes } from "node:crypto";
import {
sign,
verify,
signatureHeader,
providerConnector,
TokenVault,
retryDelay,
takePermit,
newLimit,
needsRefresh,
classify,
type Provider,
type Gateway,
} from "../packages/integrations/src/index";
const webhookProviders: Provider[] = [
"shopify",
"square",
"xero",
"quickbooks",
];
describe("reusable integration foundations", () => {
it.each(webhookProviders)(
"%s verifies the exact raw bytes and rejects altered signatures",
(provider) => {
const body = '{"message":"demo"}';
const secret = "test-secret";
const notificationUrl = "https://example.test/hooks";
const signature = sign(provider, body, secret, notificationUrl);
const delivery = {
body,
notificationUrl,
headers: { [signatureHeader[provider]]: signature },
};
expect(verify(provider, delivery, secret)).toBe(true);
// One added byte breaks the signature: it is checked before parsing.
const altered = { ...delivery, body: body + " " };
expect(verify(provider, altered, secret)).toBe(false);
const unsigned = { ...delivery, headers: {} };
expect(verify(provider, unsigned, secret)).toBe(false);
if (provider === "square") {
// Square signs the notification URL too, so a replay to another
// endpoint fails.
const elsewhere = {
...delivery,
notificationUrl: "https://other.test/hooks",
};
expect(verify(provider, elsewhere, secret)).toBe(false);
}
},
);
it("encrypts tokens bound to their workspace and connection", () => {
const vault = new TokenVault(randomBytes(32));
const sealed = vault.seal("secret-token", "tenant-a/connection");
expect(sealed).not.toContain("secret-token");
expect(vault.open(sealed, "tenant-a/connection")).toBe("secret-token");
// The context is authenticated: another workspace can't open it.
expect(() => vault.open(sealed, "tenant-b/connection")).toThrow();
// A fresh nonce each time, so equal tokens don't look equal.
const again = vault.seal("secret-token", "tenant-a/connection");
expect(again).not.toBe(sealed);
});
it("enforces per-connection windows and Xero's documented daily limit", () => {
// Xero allows 60 calls a minute and 5,000 a day per connection.
const busy = newLimit();
const quiet = newLimit();
const start = 1000;
for (let call = 0; call < 60; call++)
expect(takePermit(busy, start)).toBe(0);
// The 61st waits for the minute to turn over.
expect(takePermit(busy, start)).toBe(59000);
expect(takePermit(quiet, start)).toBe(0);
expect(takePermit(busy, start + 60000)).toBe(0);
busy.dayCount = 5000;
expect(takePermit(busy, start + 60001)).toBeGreaterThan(0);
});
it("classifies failures, bounds jitter and refreshes tokens early", () => {
expect(classify(429, "3").retryAfterMs).toBe(3000);
// Retry-After can also be a date: wait until then.
const fiveSecondsIn = new Date(5000).toUTCString();
expect(classify(429, fiveSecondsIn, 0).retryAfterMs).toBe(5000);
expect(classify(503).kind).toBe("transient");
expect(classify(400).kind).toBe("permanent");
expect(classify(401).kind).toBe("auth");
// A second attempt waits between half and all of 2^2 seconds.
expect(retryDelay(2, () => 0)).toBe(2000);
expect(retryDelay(2, () => 1)).toBe(4000);
// Tokens are refreshed when under two minutes remain.
const expiresAt = new Date(61000).toISOString();
expect(needsRefresh(expiresAt, 0)).toBe(true);
});
it("parses a Shopify order from the docs without the domain package", async () => {
const body = JSON.stringify({
id: 91,
created_at: "2026-10-11T10:00:00Z",
updated_at: "2026-10-11T10:01:00Z",
line_items: [{ variant_id: 41, quantity: 2 }],
});
const delivery = {
body,
headers: {
"x-shopify-topic": "orders/create",
"x-shopify-webhook-id": "delivery-1",
},
notificationUrl: "",
};
const events = await providerConnector("shopify").parse(
delivery,
{} as Gateway,
);
expect(events[0]).toMatchObject({
id: "delivery-1",
objectId: "91",
type: "order.created",
lines: [{ itemId: "41", quantity: 2 }],
});
});
});