Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 46 additions & 23 deletions test/upstash-rest.test.mjs → test/upstash-rest.test.ts
Original file line number Diff line number Diff line change
@@ -1,103 +1,126 @@
import assert from "node:assert/strict";
import test from "node:test";
import { describe, it, expect } from "vitest";

import {
getUpstashConfig,
upstashRateLimitFixedWindow,
upstashTryAcquireLock,
} from "../src/lib/upstash-rest.ts";

Check failure on line 7 in test/upstash-rest.test.ts

View workflow job for this annotation

GitHub Actions / Type check

An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.

test("getUpstashConfig returns null when env is missing", () => {
describe("upstash-rest", () => {
it("getUpstashConfig returns null when env is missing", () => {
delete process.env.UPSTASH_REDIS_REST_URL;
delete process.env.UPSTASH_REDIS_REST_TOKEN;
assert.equal(getUpstashConfig(), null);
expect(getUpstashConfig()).toBe(null);
});

test("upstashRateLimitFixedWindow sets expiry for new buckets", async () => {
it("getUpstashConfig returns { url, token } when both env vars are set", () => {
process.env.UPSTASH_REDIS_REST_URL = "https://example.upstash.io";
process.env.UPSTASH_REDIS_REST_TOKEN = "token";
process.env.UPSTASH_REDIS_REST_TOKEN = "test-token";
expect(getUpstashConfig()).toEqual({
url: "https://example.upstash.io",
token: "test-token",
});
delete process.env.UPSTASH_REDIS_REST_URL;
delete process.env.UPSTASH_REDIS_REST_TOKEN;
});

it("getUpstashConfig returns null when either env var is an empty string", () => {
process.env.UPSTASH_REDIS_REST_URL = "";
process.env.UPSTASH_REDIS_REST_TOKEN = "test-token";
expect(getUpstashConfig()).toBe(null);

process.env.UPSTASH_REDIS_REST_URL = "https://example.upstash.io";
process.env.UPSTASH_REDIS_REST_TOKEN = "";
expect(getUpstashConfig()).toBe(null);

delete process.env.UPSTASH_REDIS_REST_URL;
delete process.env.UPSTASH_REDIS_REST_TOKEN;
});

it("upstashRateLimitFixedWindow sets expiry for new buckets", async () => {
process.env.UPSTASH_REDIS_REST_URL = "https://example.upstash.io";
process.env.UPSTASH_REDIS_REST_TOKEN = "token";
const originalFetch = globalThis.fetch;
let call = 0;
globalThis.fetch = async (url, init) => {

Check failure on line 45 in test/upstash-rest.test.ts

View workflow job for this annotation

GitHub Actions / Type check

Type '(url: any, init: any) => Promise<{ ok: boolean; json(): Promise<{ result: number; }[]>; }>' is not assignable to type '{ (input: URL | RequestInfo, init?: RequestInit | undefined): Promise<Response>; (input: string | URL | Request, init?: RequestInit | undefined): Promise<...>; }'.
call += 1;
assert.ok(String(url).includes("/pipeline"));
expect(String(url).includes("/pipeline")).toBe(true);
const body = JSON.parse(init.body);

if (call === 1) {
assert.deepEqual(body, [["INCR", "k"], ["TTL", "k"]]);
expect(body).toEqual([
["INCR", "k"],
["TTL", "k"],
]);
return {
ok: true,
async json() {
return [{ result: 1 }, { result: -1 }];
},
};
}

assert.deepEqual(body, [["EXPIRE", "k", 60]]);
expect(body).toEqual([["EXPIRE", "k", 60]]);
return {
ok: true,
async json() {
return [{ result: 1 }];
},
};
};

try {
const result = await upstashRateLimitFixedWindow({
key: "k",
limit: 20,
windowSeconds: 60,
});
assert.deepEqual(result, { allowed: true });
expect(result).toEqual({ allowed: true });
} finally {
globalThis.fetch = originalFetch;
}
});

test("upstashRateLimitFixedWindow returns retryAfter from TTL", async () => {
it("upstashRateLimitFixedWindow returns retryAfter from TTL", async () => {
process.env.UPSTASH_REDIS_REST_URL = "https://example.upstash.io";
process.env.UPSTASH_REDIS_REST_TOKEN = "token";

const originalFetch = globalThis.fetch;
globalThis.fetch = async () => ({

Check failure on line 85 in test/upstash-rest.test.ts

View workflow job for this annotation

GitHub Actions / Type check

Type 'Promise<{ ok: boolean; json(): Promise<{ result: number; }[]>; }>' is not assignable to type 'Promise<Response>'.
ok: true,
async json() {
return [{ result: 21 }, { result: 10 }];
},
});

try {
const result = await upstashRateLimitFixedWindow({
key: "k2",
limit: 20,
windowSeconds: 60,
});
assert.deepEqual(result, { allowed: false, retryAfter: 10 });
expect(result).toEqual({ allowed: false, retryAfter: 10 });
} finally {
globalThis.fetch = originalFetch;
}
});

test("upstashTryAcquireLock returns true only when SET succeeds", async () => {
it("upstashTryAcquireLock returns true only when SET succeeds", async () => {
process.env.UPSTASH_REDIS_REST_URL = "https://example.upstash.io";
process.env.UPSTASH_REDIS_REST_TOKEN = "token";

const originalFetch = globalThis.fetch;
let returnedOk = false;
globalThis.fetch = async () => ({

Check failure on line 108 in test/upstash-rest.test.ts

View workflow job for this annotation

GitHub Actions / Type check

Type 'Promise<{ ok: boolean; json(): Promise<{ result: string | null; }[]>; }>' is not assignable to type 'Promise<Response>'.
ok: true,
async json() {
returnedOk = !returnedOk;
return [{ result: returnedOk ? "OK" : null }];
},
});

try {
assert.equal(await upstashTryAcquireLock({ key: "lock", ttlSeconds: 30 }), true);
assert.equal(await upstashTryAcquireLock({ key: "lock", ttlSeconds: 30 }), false);
expect(
await upstashTryAcquireLock({ key: "lock", ttlSeconds: 30 })
).toBe(true);
expect(
await upstashTryAcquireLock({ key: "lock", ttlSeconds: 30 })
).toBe(false);
} finally {
globalThis.fetch = originalFetch;
}
});

});
Loading