Files
data/test/projects.spec.ts
T
naomi ac3068ff05
Node.js CI / Lint and Test (push) Failing after 26s
feat: add new testimonials
2025-12-12 21:02:38 -08:00

192 lines
6.2 KiB
TypeScript

/* eslint-disable @typescript-eslint/naming-convention -- We are dealing with repository names, which are in kebab-case */
/**
* @copyright NHCarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { readFile } from "node:fs/promises";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import { parse } from "yaml";
import type { Projects } from "../src/interfaces/projects.js";
interface Repository {
id: number;
owner: {
id: number;
login: string;
login_name: string;
source_id: number;
full_name: string;
email: string;
avatar_url: string;
html_url: string;
language: string;
is_admin: boolean;
last_login: string;
created: string;
restricted: boolean;
active: boolean;
prohibit_login: boolean;
location: string;
website: string;
description: string;
visibility: string;
followers_count: number;
following_count: number;
starred_repos_count: number;
username: string;
};
name: string;
full_name: string;
description: string;
empty: boolean;
private: boolean;
fork: boolean;
template: boolean;
mirror: boolean;
size: number;
language: string;
languages_url: string;
html_url: string;
url: string;
link: string;
ssh_url: string;
clone_url: string;
original_url: string;
website: string;
stars_count: number;
forks_count: number;
watchers_count: number;
open_issues_count: number;
open_pr_counter: number;
release_counter: number;
default_branch: string;
archived: boolean;
created_at: string;
updated_at: string;
archived_at: string;
permissions: {
admin: boolean;
push: boolean;
pull: boolean;
};
has_issues: boolean;
internal_tracker: {
enable_time_tracker: boolean;
allow_only_contributors_to_track_time: boolean;
enable_issue_dependencies: boolean;
};
has_wiki: boolean;
has_pull_requests: boolean;
has_projects: boolean;
projects_mode: string;
has_releases: boolean;
has_packages: boolean;
has_actions: boolean;
ignore_whitespace_conflicts: boolean;
allow_merge_commits: boolean;
allow_rebase: boolean;
allow_rebase_explicit: boolean;
allow_squash_merge: boolean;
allow_fast_forward_only_merge: boolean;
allow_rebase_update: boolean;
default_delete_branch_after_merge: boolean;
default_merge_style: string;
default_allow_maintainer_edit: boolean;
avatar_url: string;
internal: boolean;
mirror_interval: string;
object_format_name: string;
mirror_updated: string;
topics: Array<unknown>;
licenses: Array<unknown>;
}
const getRepositories = async(): Promise<Array<Repository>> => {
const repos: Array<Repository> = [];
const orgs = [
"nhcarrigan",
"nhcarrigan-games",
];
for (const org of orgs) {
const response = await fetch(`https://git.nhcarrigan.com/api/v1/orgs/${org}/repos?limit=50`);
const data = await response.json();
repos.push(...data);
if (data.length === 50) {
let page = 2;
while (true) {
const responseInner = await fetch(`https://git.nhcarrigan.com/api/v1/orgs/${org}/repos?limit=50&page=${page}`);
const dataInner = await responseInner.json();
repos.push(...dataInner);
if (dataInner.length < 50) {
break;
}
page = page + 1;
}
}
}
return repos;
};
const repoNameMap = {
"a4p-bot": "Artists4Palestine Bot",
"beccalia-origins": "Beccalia: Origins",
"beccalia-prologue": "Beccalia: Prologue",
"blog": "Naomi's Blog",
"data": "Data API",
"docs": "NHCarrigan Documentation",
"eslint-config": "ESLint Config",
"fcc-review-generator": "freeCodeCamp Review Generator",
"life-of-a-naomi": "Life of a Naomi",
"naomis-adventure-1": "Naomi's Adventure I: An Isekai Story",
"ruu-goblin-quest": "Ruu's Goblin Quest",
"typescript-config": "TypeScript Config",
"vscode-themes": "Naomi's VSCode Themes",
};
const excludedRepos = new Set<string>([
"template",
"espanso",
"rig-task-bot",
"security",
"nginx-configs",
".profile",
".gitea",
"womp-womp",
"sakura",
"dsa",
]);
const convertKebabCaseToTitleCase = (string_: string): string => {
return string_.replaceAll("-", " ").replaceAll(/\b\w/g, (char) => {
return char.toUpperCase();
});
};
describe("projects data", () => {
it("should include all repositories", async() => {
expect.hasAssertions();
const repos = await getRepositories();
const data = await readFile(
join(import.meta.dirname, "..", "data", "projects.yml"),
"utf8",
);
const parsed = parse(data) as Projects;
expect(parsed, `Parsed projects data should be defined`).toBeDefined();
expect(Array.isArray(parsed), `Parsed projects data should be an array`).toBeTruthy();
expect(parsed.length, `There should be at least one project`).toBeGreaterThan(0);
for (const repo of repos) {
if (excludedRepos.has(repo.name)) {
continue;
}
const project = parsed.find((p) => {
return repo.name in repoNameMap
? p.name === repoNameMap[repo.name]
: p.name === convertKebabCaseToTitleCase(repo.name);
});
expect(project, `Project should be defined for repository ${convertKebabCaseToTitleCase(repo.name)}`).toBeDefined();
}
});
});