Files
gitea-mirror/src/lib/gitea-enhanced.test.ts
Arunavo Ray 5d5429ac71 test fix
2025-07-27 20:19:47 +05:30

492 lines
14 KiB
TypeScript

import { describe, test, expect, mock, beforeEach, afterEach } from "bun:test";
import { createMockResponse, mockFetch } from "@/tests/mock-fetch";
// Mock the helpers module before importing gitea-enhanced
const mockCreateMirrorJob = mock(() => Promise.resolve("mock-job-id"));
mock.module("@/lib/helpers", () => ({
createMirrorJob: mockCreateMirrorJob
}));
// Mock the database module
const mockDb = {
insert: mock((table: any) => ({
values: mock((data: any) => Promise.resolve({ insertedId: "mock-id" }))
})),
update: mock(() => ({
set: mock(() => ({
where: mock(() => Promise.resolve())
}))
}))
};
mock.module("@/lib/db", () => ({
db: mockDb,
mirrorJobs: {},
repositories: {}
}));
// Now import the modules we're testing
import {
getGiteaRepoInfo,
getOrCreateGiteaOrgEnhanced,
syncGiteaRepoEnhanced,
handleExistingNonMirrorRepo
} from "./gitea-enhanced";
import { HttpError } from "./http-client";
import type { Config, Repository } from "./db/schema";
import { repoStatusEnum } from "@/types/Repository";
describe("Enhanced Gitea Operations", () => {
let originalFetch: typeof global.fetch;
let originalTimeout: typeof global.setTimeout;
beforeEach(() => {
originalFetch = global.fetch;
originalTimeout = global.setTimeout;
// Clear mocks
mockCreateMirrorJob.mockClear();
mockDb.insert.mockClear();
mockDb.update.mockClear();
// Mock setTimeout for consistent timing in tests
global.setTimeout = ((fn: Function, delay: number) => {
// Execute immediately in tests to avoid timing issues
fn();
return 0;
}) as any;
});
afterEach(() => {
global.fetch = originalFetch;
global.setTimeout = originalTimeout;
});
describe("getGiteaRepoInfo", () => {
test("should return repo info for existing mirror repository", async () => {
global.fetch = mockFetch(() =>
createMockResponse({
id: 123,
name: "test-repo",
owner: "starred",
mirror: true,
mirror_interval: "8h",
clone_url: "https://github.com/user/test-repo.git",
private: false,
})
);
const config: Partial<Config> = {
giteaConfig: {
url: "https://gitea.example.com",
token: "encrypted-token",
defaultOwner: "testuser",
},
};
const repoInfo = await getGiteaRepoInfo({
config,
owner: "starred",
repoName: "test-repo",
});
expect(repoInfo).toBeTruthy();
expect(repoInfo?.mirror).toBe(true);
expect(repoInfo?.name).toBe("test-repo");
});
test("should return repo info for existing non-mirror repository", async () => {
global.fetch = mockFetch(() =>
createMockResponse({
id: 124,
name: "regular-repo",
owner: "starred",
mirror: false,
private: false,
})
);
const config: Partial<Config> = {
giteaConfig: {
url: "https://gitea.example.com",
token: "encrypted-token",
defaultOwner: "testuser",
},
};
const repoInfo = await getGiteaRepoInfo({
config,
owner: "starred",
repoName: "regular-repo",
});
expect(repoInfo).toBeTruthy();
expect(repoInfo?.mirror).toBe(false);
});
test("should return null for non-existent repository", async () => {
global.fetch = mockFetch(() =>
createMockResponse(
"Not Found",
{ ok: false, status: 404, statusText: "Not Found" }
)
);
const config: Partial<Config> = {
giteaConfig: {
url: "https://gitea.example.com",
token: "encrypted-token",
defaultOwner: "testuser",
},
};
const repoInfo = await getGiteaRepoInfo({
config,
owner: "starred",
repoName: "non-existent",
});
expect(repoInfo).toBeNull();
});
});
describe("getOrCreateGiteaOrgEnhanced", () => {
test("should handle duplicate organization constraint error with retry", async () => {
let attemptCount = 0;
global.fetch = mockFetch(async (url: string, options?: RequestInit) => {
attemptCount++;
if (url.includes("/api/v1/orgs/starred") && options?.method !== "POST") {
// First two attempts: org doesn't exist
if (attemptCount <= 2) {
return createMockResponse(
"Not Found",
{ ok: false, status: 404, statusText: "Not Found" }
);
}
// Third attempt: org now exists (created by another process)
return createMockResponse({ id: 999, username: "starred" });
}
if (url.includes("/api/v1/orgs") && options?.method === "POST") {
// Simulate duplicate constraint error
return createMockResponse(
{ message: "pq: duplicate key value violates unique constraint \"UQE_user_lower_name\"" },
{ ok: false, status: 422, statusText: "Unprocessable Entity" }
);
}
return createMockResponse(
"Internal Server Error",
{ ok: false, status: 500 }
);
});
const config: Partial<Config> = {
userId: "user123",
giteaConfig: {
url: "https://gitea.example.com",
token: "encrypted-token",
defaultOwner: "testuser",
visibility: "public",
},
};
const orgId = await getOrCreateGiteaOrgEnhanced({
orgName: "starred",
config,
maxRetries: 3,
retryDelay: 10,
});
expect(orgId).toBe(999);
expect(attemptCount).toBeGreaterThanOrEqual(3);
});
test("should create organization on first attempt", async () => {
let getOrgCalled = false;
let createOrgCalled = false;
global.fetch = mockFetch(async (url: string, options?: RequestInit) => {
if (url.includes("/api/v1/orgs/neworg") && options?.method !== "POST") {
getOrgCalled = true;
return createMockResponse(
"Not Found",
{ ok: false, status: 404, statusText: "Not Found" }
);
}
if (url.includes("/api/v1/orgs") && options?.method === "POST") {
createOrgCalled = true;
return createMockResponse(
{ id: 777, username: "neworg" },
{ ok: true, status: 201 }
);
}
return createMockResponse(
"Internal Server Error",
{ ok: false, status: 500 }
);
});
const config: Partial<Config> = {
userId: "user123",
githubConfig: {
username: "testuser",
token: "github-token",
privateRepositories: false,
mirrorStarred: true,
},
giteaConfig: {
url: "https://gitea.example.com",
token: "encrypted-token",
defaultOwner: "testuser",
},
};
const orgId = await getOrCreateGiteaOrgEnhanced({
orgName: "neworg",
config,
});
expect(orgId).toBe(777);
expect(getOrgCalled).toBe(true);
expect(createOrgCalled).toBe(true);
});
});
describe("syncGiteaRepoEnhanced", () => {
test("should fail gracefully when repository is not a mirror", async () => {
global.fetch = mockFetch(async (url: string) => {
if (url.includes("/api/v1/repos/starred/non-mirror-repo") && !url.includes("mirror-sync")) {
return createMockResponse({
id: 456,
name: "non-mirror-repo",
owner: "starred",
mirror: false, // Not a mirror
private: false,
});
}
return createMockResponse(
"Not Found",
{ ok: false, status: 404 }
);
});
const config: Partial<Config> = {
userId: "user123",
githubConfig: {
username: "testuser",
token: "github-token",
privateRepositories: false,
mirrorStarred: true,
},
giteaConfig: {
url: "https://gitea.example.com",
token: "encrypted-token",
defaultOwner: "testuser",
},
};
const repository: Repository = {
id: "repo123",
name: "non-mirror-repo",
fullName: "user/non-mirror-repo",
owner: "user",
cloneUrl: "https://github.com/user/non-mirror-repo.git",
isPrivate: false,
isStarred: true,
status: repoStatusEnum.parse("mirrored"),
visibility: "public",
userId: "user123",
createdAt: new Date(),
updatedAt: new Date(),
};
// Mock getGiteaRepoOwnerAsync
const mockGetOwner = mock(() => Promise.resolve("starred"));
global.import = mock(async (path: string) => {
if (path === "./gitea") {
return { getGiteaRepoOwnerAsync: mockGetOwner };
}
return {};
}) as any;
await expect(
syncGiteaRepoEnhanced({ config, repository })
).rejects.toThrow("Repository non-mirror-repo is not a mirror. Cannot sync.");
});
test("should successfully sync a mirror repository", async () => {
let syncCalled = false;
global.fetch = mockFetch(async (url: string, options?: RequestInit) => {
if (url.includes("/api/v1/repos/starred/mirror-repo") && !url.includes("mirror-sync")) {
return createMockResponse({
id: 789,
name: "mirror-repo",
owner: "starred",
mirror: true,
mirror_interval: "8h",
private: false,
});
}
if (url.includes("/mirror-sync") && options?.method === "POST") {
syncCalled = true;
return createMockResponse({ success: true });
}
return createMockResponse(
"Not Found",
{ ok: false, status: 404 }
);
});
const config: Partial<Config> = {
userId: "user123",
githubConfig: {
username: "testuser",
token: "github-token",
privateRepositories: false,
mirrorStarred: true,
},
giteaConfig: {
url: "https://gitea.example.com",
token: "encrypted-token",
defaultOwner: "testuser",
},
};
const repository: Repository = {
id: "repo456",
name: "mirror-repo",
fullName: "user/mirror-repo",
owner: "user",
cloneUrl: "https://github.com/user/mirror-repo.git",
isPrivate: false,
isStarred: true,
status: repoStatusEnum.parse("mirrored"),
visibility: "public",
userId: "user123",
createdAt: new Date(),
updatedAt: new Date(),
};
// Mock getGiteaRepoOwnerAsync
const mockGetOwner = mock(() => Promise.resolve("starred"));
global.import = mock(async (path: string) => {
if (path === "./gitea") {
return { getGiteaRepoOwnerAsync: mockGetOwner };
}
return {};
}) as any;
const result = await syncGiteaRepoEnhanced({ config, repository });
expect(result).toEqual({ success: true });
expect(syncCalled).toBe(true);
});
});
describe("handleExistingNonMirrorRepo", () => {
test("should skip non-mirror repository with skip strategy", async () => {
const repoInfo = {
id: 123,
name: "test-repo",
owner: "starred",
mirror: false,
private: false,
};
const repository: Repository = {
id: "repo123",
name: "test-repo",
fullName: "user/test-repo",
owner: "user",
cloneUrl: "https://github.com/user/test-repo.git",
isPrivate: false,
isStarred: true,
status: repoStatusEnum.parse("imported"),
visibility: "public",
userId: "user123",
createdAt: new Date(),
updatedAt: new Date(),
};
const config: Partial<Config> = {
giteaConfig: {
url: "https://gitea.example.com",
token: "encrypted-token",
defaultOwner: "testuser",
},
};
await handleExistingNonMirrorRepo({
config,
repository,
repoInfo,
strategy: "skip",
});
// Test passes if no error is thrown
expect(true).toBe(true);
});
test("should delete non-mirror repository with delete strategy", async () => {
let deleteCalled = false;
global.fetch = mockFetch(async (url: string, options?: RequestInit) => {
if (url.includes("/api/v1/repos/starred/test-repo") && options?.method === "DELETE") {
deleteCalled = true;
return {
ok: true,
status: 204,
};
}
return { ok: false, status: 404 };
});
const repoInfo = {
id: 124,
name: "test-repo",
owner: "starred",
mirror: false,
private: false,
};
const repository: Repository = {
id: "repo124",
name: "test-repo",
fullName: "user/test-repo",
owner: "user",
cloneUrl: "https://github.com/user/test-repo.git",
isPrivate: false,
isStarred: true,
status: repoStatusEnum.parse("imported"),
visibility: "public",
userId: "user123",
createdAt: new Date(),
updatedAt: new Date(),
};
const config: Partial<Config> = {
giteaConfig: {
url: "https://gitea.example.com",
token: "encrypted-token",
defaultOwner: "testuser",
},
};
await handleExistingNonMirrorRepo({
config,
repository,
repoInfo,
strategy: "delete",
});
expect(deleteCalled).toBe(true);
});
});
});