Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: Improve code coverage #208

Merged
merged 14 commits into from
Jun 26, 2024
Merged
7 changes: 3 additions & 4 deletions .github/workflows/api-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
- name: 🛠️ Setup Supabase CLI
uses: supabase/setup-cli@v1
with:
version: 1.172.2
version: latest

- name: 🚀 Start Supabase
run: |
Expand All @@ -64,12 +64,11 @@ jobs:
run:
pnpm -F api test:cov

- name: 'Report Coverage'
if: always()
- name: 📊 Coverage report
uses: davelosert/vitest-coverage-report-action@v2
with:
working-directory: ./apps/api
name: 'API Coverage'
name: API

- name: 🧹 Stop supabase
run: supabase stop --no-backup
20 changes: 4 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,16 @@ env:
jobs:
ci:
runs-on: self-hosted
timeout-minutes: 10
timeout-minutes: 5
steps:
- name: 📦 Checkout Repository
uses: actions/checkout@v4

- name: 🛠️ Setup pnpm
uses: pnpm/action-setup@v4

- name: 🛠️ Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm

- name: ⬆️ Install dependencies
run: pnpm --color install
- name: 🛠️ Setup Biome
uses: biomejs/setup-biome@v2

- name: 🚀 Run Biome
run: pnpm run lint:check

# - name: 🧪 Check type coverage
# run: npx type-coverage --detail --at-least 90 -p tsconfig.json
run: biome ci

- if: github.ref == 'refs/heads/main'
name: 🚀 Setup Supabase CLI
Expand Down
4 changes: 2 additions & 2 deletions apps/admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@hookform/resolvers": "^3.6.0",
"@repo/ui": "workspace:*",
"date-fns": "^3.6.0",
"lucide-react": "^0.396.0",
"lucide-react": "^0.397.0",
"next": "^14.2.4",
"next-themes": "^0.3.0",
"react": "^18.3.1",
Expand All @@ -28,7 +28,7 @@
"devDependencies": {
"@repo/biome-config": "workspace:*",
"@repo/typescript-config": "workspace:*",
"@types/node": "^20.14.8",
"@types/node": "^20.14.9",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"autoprefixer": "^10.4.19",
Expand Down
6 changes: 3 additions & 3 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@
"@hono/zod-openapi": "0.14.5",
"@hono/zod-validator": "^0.2.2",
"@repo/types": "workspace:*",
"@supabase/supabase-js": "^2.43.6",
"@vitest/coverage-v8": "^1.6.0",
"@supabase/supabase-js": "^2.44.0",
"hono": "^4.4.8",
"stripe": "^16.0.0",
"zod": "^3.23.8",
Expand All @@ -31,8 +30,9 @@
"devDependencies": {
"@repo/biome-config": "workspace:*",
"@repo/typescript-config": "workspace:*",
"@types/node": "^20.14.8",
"@types/node": "^20.14.9",
"@types/swagger-ui-dist": "^3.30.5",
"@vitest/coverage-v8": "^1.6.0",
"supabase": "^1.178.2",
"tsx": "^4.15.7",
"typescript": "^5.5.2",
Expand Down
29 changes: 25 additions & 4 deletions apps/api/src/handlers/activities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ activities.openapi(updateActivity, async (c) => {
const { data, error } = await supabase
.from('ACTIVITIES')
.update({
name,
description,
max_participants,
min_participants,
Expand Down Expand Up @@ -255,12 +256,22 @@ activities.openapi(deleteActivity, async (c) => {
const roles = user.roles;
await checkRole(roles, false);

const { error } = await supabase.from('ACTIVITIES').delete().eq('id', id);
const { data: existingActivity, error: fetchError } = await supabase
.from('ACTIVITIES')
.select('id')
.eq('id', id)
.single();

if (error) {
if (fetchError || !existingActivity) {
return c.json({ error: 'Activity not found' }, 404);
}

const { error: deleteError } = await supabase.from('ACTIVITIES').delete().eq('id', id);

if (deleteError) {
return c.json({ error: deleteError.message }, 500);
}

return c.json({ message: 'Activity deleted' }, 200);
});

Expand Down Expand Up @@ -395,12 +406,22 @@ activities.openapi(deleteActivityExceptions, async (c) => {
const roles = user.roles;
await checkRole(roles, false);

const { error } = await supabase.from('ACTIVITIES_EXCEPTIONS').delete().eq('id', id);
const { data: existingException, error: fetchError } = await supabase
.from('ACTIVITIES_EXCEPTIONS')
.select('id')
.eq('id', id)
.single();

if (error) {
if (fetchError || !existingException) {
return c.json({ error: 'Activity exception not found' }, 404);
}

const { error: deleteError } = await supabase.from('ACTIVITIES_EXCEPTIONS').delete().eq('id', id);

if (deleteError) {
return c.json({ error: deleteError.message }, 500);
}

return c.json({ message: 'Activity exception deleted' }, 200);
});

Expand Down
15 changes: 13 additions & 2 deletions apps/api/src/handlers/location.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,22 @@ location.openapi(deleteAddress, async (c) => {
const roles = user.roles;
await checkRole(roles, false);
const { id } = c.req.valid('param');
const { error } = await supabase.from('ADDRESSES').delete().eq('id', id);

if (error) {
const { data: existingAddress, error: fetchError } = await supabase
.from('ADDRESSES')
.select('id')
.eq('id', id)
.single();

if (fetchError || !existingAddress) {
return c.json({ error: 'Address not found' }, 404);
}

const { error: deleteError } = await supabase.from('ADDRESSES').delete().eq('id', id);

if (deleteError) {
return c.json({ error: deleteError.message }, 500);
}

return c.json({ message: 'Address deleted' }, 200);
});
17 changes: 12 additions & 5 deletions apps/api/src/handlers/reasons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ reasons.openapi(createReason, async (c) => {
await checkRole(roles, false, [Role.ADMIN]);

const { reason } = c.req.valid('json');
const { data, error } = await supabase.from('REASONS').insert({ reason }).single();
const { data, error } = await supabase.from('REASONS').insert({ reason }).select().single();

if (error) {
return c.json({ error: error.message }, 500);
Expand All @@ -54,7 +54,7 @@ reasons.openapi(updateReason, async (c) => {

const { id } = c.req.valid('param');
const { reason } = c.req.valid('json');
const { data, error } = await supabase.from('REASONS').update({ reason }).eq('id', id).single();
const { data, error } = await supabase.from('REASONS').update({ reason }).eq('id', id).select().single();

if (error) {
return c.json({ error: error.message }, 404);
Expand All @@ -69,10 +69,17 @@ reasons.openapi(deleteReason, async (c) => {
await checkRole(roles, false, [Role.ADMIN]);

const { id } = c.req.valid('param');
const { error } = await supabase.from('REASONS').delete().eq('id', id);

if (error) {
return c.json({ error: error.message }, 404);
const { data: existingReason, error: fetchError } = await supabase.from('REASONS').select('id').eq('id', id).single();

if (fetchError || !existingReason) {
return c.json({ error: 'Reason not found' }, 404);
}

const { error: deleteError } = await supabase.from('REASONS').delete().eq('id', id);

if (deleteError) {
return c.json({ error: deleteError.message }, 500);
}

return c.json({ message: 'Reason deleted' }, 200);
Expand Down
11 changes: 8 additions & 3 deletions apps/api/src/handlers/sports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,23 @@ sports.openapi(updateSport, async (c) => {

return c.json(data, 200);
});

sports.openapi(deleteSport, async (c) => {
const { id } = c.req.valid('param');
const user = c.get('user');
const roles = user.roles;
await checkRole(roles, false);

const { error } = await supabase.from('SPORTS').delete().eq('id', id);
const { data: existingSport, error: fetchError } = await supabase.from('SPORTS').select('id').eq('id', id).single();

if (error) {
if (fetchError || !existingSport) {
return c.json({ error: 'Sport not found' }, 404);
}

const { error: deleteError } = await supabase.from('SPORTS').delete().eq('id', id);

if (deleteError) {
return c.json({ error: deleteError.message }, 500);
}

return c.json({ message: `Sport with id ${id} deleted` }, 200);
});
11 changes: 9 additions & 2 deletions apps/api/src/handlers/votes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,13 +134,20 @@ polls.openapi(deletePoll, async (c) => {
const user = c.get('user');
const roles = user.roles;
await checkRole(roles, false, [Role.ADMIN]);

const { id } = c.req.valid('param');
const { error } = await supabase.from('POLLS').delete().eq('id', id);
const { data: existingPoll, error: fetchError } = await supabase.from('POLLS').select('id').eq('id', id).single();

if (error) {
if (fetchError || !existingPoll) {
return c.json({ error: 'Poll not found' }, 404);
}

const { error: deleteError } = await supabase.from('POLLS').delete().eq('id', id);

if (deleteError) {
return c.json({ error: deleteError.message }, 500);
}

return c.json({ message: 'Poll deleted' }, 200);
});

Expand Down
2 changes: 2 additions & 0 deletions apps/api/src/libs/activities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export function getOccurences(
) {
const occurences = [];

if (startDate > endDate) return [];

for (let currentDate = startDate; currentDate <= endDate; currentDate.setDate(currentDate.getDate() + 1)) {
const dayOfWeek = currentDate.getDay();
if (daysToFind.includes(days.get(dayOfWeek))) {
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/middlewares/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ so it has no roles but we don't remove user roles from the database.

if date is not null and it's greater than the current date it means that the user subscription is still valid.
*/
function accountRolesValidity(date: null | string, roles: { id_role: number }[]): number[] {
export function accountRolesValidity(date: null | string, roles: { id_role: number }[]): number[] {
if (date === null) return [];

if (date !== null && new Date(date) < new Date()) return [];
Expand Down
20 changes: 10 additions & 10 deletions apps/api/src/routes/reasons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export const getReasons = createRoute({
'application/json': {
schema: z.array(
z.object({
id: z.number(),
reason: z.string(),
id: z.number().min(1),
reason: z.string().min(5).max(255),
}),
),
},
Expand All @@ -40,8 +40,8 @@ export const getReasonById = createRoute({
content: {
'application/json': {
schema: z.object({
id: z.number(),
reason: z.string(),
id: z.number().min(1),
reason: z.string().min(5).max(255),
}),
},
},
Expand All @@ -64,7 +64,7 @@ export const createReason = createRoute({
content: {
'application/json': {
schema: z.object({
reason: z.string(),
reason: z.string().min(5).max(255),
}),
},
},
Expand All @@ -76,8 +76,8 @@ export const createReason = createRoute({
content: {
'application/json': {
schema: z.object({
id: z.number(),
reason: z.string(),
id: z.number().min(1),
reason: z.string().min(5).max(255),
}),
},
},
Expand All @@ -101,7 +101,7 @@ export const updateReason = createRoute({
content: {
'application/json': {
schema: z.object({
reason: z.string(),
reason: z.string().min(5).max(255),
}),
},
},
Expand All @@ -113,8 +113,8 @@ export const updateReason = createRoute({
content: {
'application/json': {
schema: z.object({
id: z.number(),
reason: z.string(),
id: z.number().min(1),
reason: z.string().min(5).max(255),
}),
},
},
Expand Down
Loading
Loading