Skip to content
Merged
Show file tree
Hide file tree
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
63 changes: 63 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: CI

on:
push:
branches: [main, master]
pull_request:
branches: [main, master]

jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Deno
uses: denoland/setup-deno@v2
with:
deno-version: v2.x

- name: Check formatting
run: deno fmt --check

- name: Run linter
run: deno lint

- name: Type check
run: deno check source/mod.ts

test:
name: Test
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Deno
uses: denoland/setup-deno@v2
with:
deno-version: v2.x

- name: Run tests
run: deno task test

- name: Run tests with coverage
run: deno task test:coverage

publish-dry-run:
name: Publish Dry Run
runs-on: ubuntu-latest
needs: [lint, test]
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Deno
uses: denoland/setup-deno@v2
with:
deno-version: v2.x

- name: Dry run publish to JSR
run: deno publish --dry-run --allow-slow-types
4 changes: 2 additions & 2 deletions .github/workflows/update-and-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
pull_request:
branches: main
paths:
- source/**
- source/**

jobs:
release:
Expand All @@ -33,4 +33,4 @@ jobs:
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
deno run --allow-all --unstable-broadcast-channel --unstable-kv https://deno.land/x/automation_scripts@0.0.6/ci-cd/scripts/UpdateSemverDeployJsr.ts
deno run --allow-all --unstable-broadcast-channel --unstable-kv https://deno.land/x/automation_scripts@0.0.6/ci-cd/scripts/UpdateSemverDeployJsr.ts
20 changes: 19 additions & 1 deletion deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
"versionsFilePath": "./source/versions.ts"
}
},
"imports": {
"@std/assert": "https://deno.land/std@0.224.0/assert/mod.ts"
},
"exports": {
".": "./source/mod.ts",
"./types": "./source/types.ts",
Expand All @@ -14,6 +17,12 @@
},
"lock": false,
"tasks": {
"test": "deno test --allow-net source/",
"test:coverage": "deno test --allow-net --coverage=coverage source/",
"lint": "deno lint",
"fmt": "deno fmt",
"fmt:check": "deno fmt --check",
"check": "deno check source/mod.ts",
"ex2": "deno run -A ./examples/ex2.ts",
"ex5": "deno run -A ./examples/ex5.ts",
"ex6": "deno run -A ./examples/ex5.ts",
Expand All @@ -23,5 +32,14 @@
"exclude": [
"./source/versions.ts"
]
},
"lint": {
"exclude": [
"./examples/",
"./scripts/"
],
"rules": {
"exclude": ["no-slow-types"]
}
}
}
}
192 changes: 192 additions & 0 deletions source/Fetch_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
import { assertEquals } from "@std/assert";
import { Fetchify } from "./Fetch.ts";

function mockFetch() {
const originalFetch = globalThis.fetch;
const calls: { url: string; method: string; headers?: HeadersInit }[] = [];

globalThis.fetch = (input: RequestInfo | URL, init?: RequestInit) => {
calls.push({
url: input.toString(),
method: init?.method || "GET",
headers: init?.headers,
});
return Promise.resolve(
new Response(JSON.stringify({ ok: true }), { status: 200 }),
);
};

return {
calls,
cleanup: () => {
globalThis.fetch = originalFetch;
},
};
}

const testOpts = { sanitizeOps: false, sanitizeResources: false };

Deno.test("Fetchify - GET request", testOpts, async () => {
const { calls, cleanup } = mockFetch();
const client = new Fetchify();

try {
const response = await client.get("https://example.com/api/users");
assertEquals(response.status, 200);
assertEquals(calls[0].method, "GET");
assertEquals(calls[0].url, "https://example.com/api/users");
} finally {
cleanup();
}
});

Deno.test("Fetchify - POST request", testOpts, async () => {
const { calls, cleanup } = mockFetch();
const client = new Fetchify();

try {
const response = await client.post("https://example.com/api/users");
assertEquals(response.status, 200);
assertEquals(calls[0].method, "POST");
} finally {
cleanup();
}
});

Deno.test("Fetchify - PUT request", testOpts, async () => {
const { calls, cleanup } = mockFetch();
const client = new Fetchify();

try {
const response = await client.put("https://example.com/api/users/1");
assertEquals(response.status, 200);
assertEquals(calls[0].method, "PUT");
} finally {
cleanup();
}
});

Deno.test("Fetchify - DELETE request", testOpts, async () => {
const { calls, cleanup } = mockFetch();
const client = new Fetchify();

try {
const response = await client.delete("https://example.com/api/users/1");
assertEquals(response.status, 200);
assertEquals(calls[0].method, "DELETE");
} finally {
cleanup();
}
});

Deno.test("Fetchify - HEAD request", testOpts, async () => {
const { calls, cleanup } = mockFetch();
const client = new Fetchify();

try {
const response = await client.head("https://example.com/api/users");
assertEquals(response.status, 200);
assertEquals(calls[0].method, "HEAD");
} finally {
cleanup();
}
});

Deno.test("Fetchify - PATCH request", testOpts, async () => {
const { calls, cleanup } = mockFetch();
const client = new Fetchify();

try {
const response = await client.patch("https://example.com/api/users/1");
assertEquals(response.status, 200);
assertEquals(calls[0].method, "PATCH");
} finally {
cleanup();
}
});

Deno.test("Fetchify - uses baseURL", testOpts, async () => {
const { calls, cleanup } = mockFetch();
const client = new Fetchify({
baseURL: "https://api.example.com",
});

try {
await client.get("/users");
assertEquals(calls[0].url, "https://api.example.com/users");
} finally {
cleanup();
}
});

Deno.test("Fetchify - uses default headers", testOpts, async () => {
const { calls, cleanup } = mockFetch();
const client = new Fetchify({
headers: {
Authorization: "Bearer token123",
"Content-Type": "application/json",
},
});

try {
await client.get("https://example.com/api");
assertEquals(
(calls[0].headers as Record<string, string>)?.["Authorization"],
"Bearer token123",
);
} finally {
cleanup();
}
});

Deno.test(
"Fetchify - combines baseURL with path correctly",
testOpts,
async () => {
const { calls, cleanup } = mockFetch();
const client = new Fetchify({
baseURL: "https://api.example.com/v1",
});

try {
await client.get("/users/123");
assertEquals(calls[0].url, "https://api.example.com/v1/users/123");
} finally {
cleanup();
}
},
);

Deno.test("Fetchify - with rate limiting config", testOpts, async () => {
const { cleanup } = mockFetch();
const client = new Fetchify({
limiter: { rps: 5 },
});

try {
const response = await client.get("https://example.com/api");
assertEquals(response.status, 200);
} finally {
cleanup();
}
});

Deno.test("Fetchify - multiple requests in sequence", testOpts, async () => {
const { calls, cleanup } = mockFetch();
const client = new Fetchify({
baseURL: "https://api.example.com",
});

try {
await client.get("/users");
await client.post("/users");
await client.delete("/users/1");

assertEquals(calls.length, 3);
assertEquals(calls[0].method, "GET");
assertEquals(calls[1].method, "POST");
assertEquals(calls[2].method, "DELETE");
} finally {
cleanup();
}
});
Loading