From ce94c4efb02c2660c17c326c740b24ad66c82164 Mon Sep 17 00:00:00 2001 From: Ashley Kapaso Date: Mon, 30 Sep 2024 18:56:23 +0200 Subject: [PATCH 1/2] fix grades 500 error --- src/src/routes/(app)/grades/+page.server.ts | 4 +- src/src/routes/(app)/grades/+page.svelte | 52 +++++++++++-------- .../routes/(app)/workspaces/+page.server.ts | 2 + .../[workspace]/grades/+page.server.ts | 8 +-- .../[workspace]/grades/+page.svelte | 41 ++++++++------- src/static/templates/student-welcome.html | 4 +- 6 files changed, 63 insertions(+), 48 deletions(-) diff --git a/src/src/routes/(app)/grades/+page.server.ts b/src/src/routes/(app)/grades/+page.server.ts index 39856f5b..b5881417 100644 --- a/src/src/routes/(app)/grades/+page.server.ts +++ b/src/src/routes/(app)/grades/+page.server.ts @@ -17,7 +17,7 @@ export async function load({ locals }) { acc[workspaceName].push({ average: 0, - score: grade.mark, + score: grade.mark * 10, assessment: grade.quizID.title, quizID: grade.quizID._id.toString(), date: grade.quizID.date.toDateString() @@ -31,7 +31,7 @@ export async function load({ locals }) { const allGrades = await Grades.find({ quizID: assessment.quizID }); const average = allGrades.reduce((sum, g) => sum + g.mark, 0) / allGrades.length; - assessment.average = Math.round(average); + assessment.average = Math.round(average) * 10; } } diff --git a/src/src/routes/(app)/grades/+page.svelte b/src/src/routes/(app)/grades/+page.svelte index 37c0e6de..dfafd52a 100644 --- a/src/src/routes/(app)/grades/+page.svelte +++ b/src/src/routes/(app)/grades/+page.svelte @@ -19,28 +19,36 @@

Student Grades

- {#each workspaces as workspace} - - - - Assessment - Date & Time - Your Score (%) - Class Average (%) - + {#if workspaces.length === 0} +

No grades available

+ {:else} + {#each workspaces as workspace} + + {#if workspace.grades.length === 0} +

No grades available

+ {:else} +
+ + Assessment + Date & Time + Your Score (%) + Class Average (%) + - - {#each workspace.grades as grade} - - {grade.assessment} - {grade.date} - {grade.score} - {grade.average} - - {/each} - -
-
- {/each} + + {#each workspace.grades as grade} + + {grade.assessment} + {grade.date} + {grade.score} + {grade.average} + + {/each} + + + {/if} + + {/each} + {/if}
diff --git a/src/src/routes/(app)/workspaces/+page.server.ts b/src/src/routes/(app)/workspaces/+page.server.ts index 7b586a00..cf4a4718 100644 --- a/src/src/routes/(app)/workspaces/+page.server.ts +++ b/src/src/routes/(app)/workspaces/+page.server.ts @@ -4,6 +4,8 @@ import { fail, error, redirect } from '@sveltejs/kit'; import { upload, deleteFile } from '$lib/server/storage'; import Users from '$db/schemas/User'; +// eslint-disable-next-line +import Grades from '$db/schemas/Grades'; import Workspaces from '$db/schemas/Workspace'; import type { Workspace, User } from '$src/types'; diff --git a/src/src/routes/(app)/workspaces/[workspace]/grades/+page.server.ts b/src/src/routes/(app)/workspaces/[workspace]/grades/+page.server.ts index f01d485a..706b1c52 100644 --- a/src/src/routes/(app)/workspaces/[workspace]/grades/+page.server.ts +++ b/src/src/routes/(app)/workspaces/[workspace]/grades/+page.server.ts @@ -1,5 +1,5 @@ import { error } from '@sveltejs/kit'; -import Grades from '$lib/server/database/schemas/Grades'; +import Grades from '$db/schemas/Grades'; export async function load({ locals, params }) { if (!locals.user || locals.user.role !== 'student') throw error(401, 'Unauthorised'); @@ -13,7 +13,7 @@ export async function load({ locals, params }) { const workspaceGrades = grades.map((grade) => ({ average: 0, - score: grade.mark, + score: grade.mark * 10, assessment: grade.quizID.title, quizID: grade.quizID._id.toString(), date: grade.quizID.date.toDateString() @@ -23,9 +23,11 @@ export async function load({ locals, params }) { const allGrades = await Grades.find({ quizID: assessment.quizID }); const average = allGrades.reduce((sum, g) => sum + g.mark, 0) / allGrades.length; - assessment.average = Math.round(average); + assessment.average = Math.round(average) * 10; } + console.log(workspaceGrades); + return { grades: workspaceGrades }; } catch (e) { console.error('Error fetching grades:', e); diff --git a/src/src/routes/(app)/workspaces/[workspace]/grades/+page.svelte b/src/src/routes/(app)/workspaces/[workspace]/grades/+page.svelte index f35bd1f4..ad1dc557 100644 --- a/src/src/routes/(app)/workspaces/[workspace]/grades/+page.svelte +++ b/src/src/routes/(app)/workspaces/[workspace]/grades/+page.svelte @@ -15,24 +15,27 @@

Grades

+ {#if grades.length === 0} +

No grades available

+ {:else} + + + Assessment + Date & Time + Your Score (%) + Class Average (%) + -
- - Assessment - Date & Time - Your Score (%) - Class Average (%) - - - - {#each grades as grade} - - {grade.assessment} - {grade.date} - {grade.score} - {grade.average} - - {/each} - -
+ + {#each grades as grade} + + {grade.assessment} + {grade.date} + {grade.score} + {grade.average} + + {/each} + + + {/if}
diff --git a/src/static/templates/student-welcome.html b/src/static/templates/student-welcome.html index bf3802b3..1b1e32ba 100644 --- a/src/static/templates/student-welcome.html +++ b/src/static/templates/student-welcome.html @@ -54,8 +54,8 @@

🎓 Welcome to ClassConnect!

Congratulations, {{name}}! 🎉

- Your application to attend {{organisation has been approved! We're thrilled - to welcome you to our learning community on the ClassConnect platform. + Your application to attend {{organisation}} has been approved! We're + thrilled to welcome you to our learning community on the ClassConnect platform.

🔑 Your Account Details

Your generated username is: {{username}}

From 6c1a476c3771990cbae21e72b3224b900a8d08d4 Mon Sep 17 00:00:00 2001 From: Ashley Kapaso Date: Mon, 30 Sep 2024 19:25:26 +0200 Subject: [PATCH 2/2] fix tests --- src/src/routes/(app)/grades/+page.server.ts | 4 +- .../[workspace]/grades/+page.server.ts | 4 +- .../(app)/workspaces/page.server.test.ts | 268 ------------------ src/src/tests/unit/server/workspace.test.ts | 8 + 4 files changed, 12 insertions(+), 272 deletions(-) delete mode 100644 src/src/routes/(app)/workspaces/page.server.test.ts diff --git a/src/src/routes/(app)/grades/+page.server.ts b/src/src/routes/(app)/grades/+page.server.ts index b5881417..39856f5b 100644 --- a/src/src/routes/(app)/grades/+page.server.ts +++ b/src/src/routes/(app)/grades/+page.server.ts @@ -17,7 +17,7 @@ export async function load({ locals }) { acc[workspaceName].push({ average: 0, - score: grade.mark * 10, + score: grade.mark, assessment: grade.quizID.title, quizID: grade.quizID._id.toString(), date: grade.quizID.date.toDateString() @@ -31,7 +31,7 @@ export async function load({ locals }) { const allGrades = await Grades.find({ quizID: assessment.quizID }); const average = allGrades.reduce((sum, g) => sum + g.mark, 0) / allGrades.length; - assessment.average = Math.round(average) * 10; + assessment.average = Math.round(average); } } diff --git a/src/src/routes/(app)/workspaces/[workspace]/grades/+page.server.ts b/src/src/routes/(app)/workspaces/[workspace]/grades/+page.server.ts index 706b1c52..c0a0df78 100644 --- a/src/src/routes/(app)/workspaces/[workspace]/grades/+page.server.ts +++ b/src/src/routes/(app)/workspaces/[workspace]/grades/+page.server.ts @@ -13,7 +13,7 @@ export async function load({ locals, params }) { const workspaceGrades = grades.map((grade) => ({ average: 0, - score: grade.mark * 10, + score: grade.mark, assessment: grade.quizID.title, quizID: grade.quizID._id.toString(), date: grade.quizID.date.toDateString() @@ -23,7 +23,7 @@ export async function load({ locals, params }) { const allGrades = await Grades.find({ quizID: assessment.quizID }); const average = allGrades.reduce((sum, g) => sum + g.mark, 0) / allGrades.length; - assessment.average = Math.round(average) * 10; + assessment.average = Math.round(average); } console.log(workspaceGrades); diff --git a/src/src/routes/(app)/workspaces/page.server.test.ts b/src/src/routes/(app)/workspaces/page.server.test.ts deleted file mode 100644 index 4d77e86f..00000000 --- a/src/src/routes/(app)/workspaces/page.server.test.ts +++ /dev/null @@ -1,268 +0,0 @@ -import { fail, error, redirect } from '@sveltejs/kit'; -import { describe, it, expect, vi, beforeEach } from 'vitest'; - -import User from '$db/schemas/User'; -import Workspace from '$db/schemas/Workspace'; -import * as workspaceModule from './+page.server'; - -vi.mock('$db/schemas/User', () => { - const UserMock: any = vi.fn().mockImplementation(() => ({ - save: vi.fn() - })); - - UserMock.find = vi.fn(); - UserMock.findById = vi.fn(); - UserMock.findByIdAndUpdate = vi.fn(); - UserMock.updateMany = vi.fn(); - - return { default: UserMock }; -}); - -vi.mock('$db/schemas/Workspace', () => { - const WorkspaceMock: any = vi.fn().mockImplementation(() => ({ - save: vi.fn() - })); - - WorkspaceMock.find = vi.fn(); - WorkspaceMock.findById = vi.fn(); - WorkspaceMock.findByIdAndDelete = vi.fn(); - - return { default: WorkspaceMock }; -}); - -vi.mock('@sveltejs/kit', async () => { - const actual = await vi.importActual('@sveltejs/kit'); - return { - ...actual, - fail: vi.fn(), - error: vi.fn(), - redirect: vi.fn() - }; -}); - -describe('Workspace Management', () => { - beforeEach(() => { - vi.resetAllMocks(); - }); - - describe('load function', () => { - it('should redirect if user is not authenticated', async () => { - const locals = { user: null }; - - await workspaceModule.load({ locals } as any); - - expect(redirect).toHaveBeenCalledWith(302, '/signin'); - }); - - it('should return workspaces and lecturers for admin users', async () => { - const locals = { user: { role: 'admin', organisation: 'org1' } }; - const mockWorkspaces = [ - { _id: '1', name: 'Workspace1', image: 'img1', owner: 'owner1' }, - { _id: '2', name: 'Workspace2', image: 'img2', owner: 'owner2' } - ]; - const mockLecturers = [ - { _id: '1', name: 'Lecturer1', surname: 'Surname1' }, - { _id: '2', name: 'Lecturer2', surname: 'Surname2' } - ]; - - const mockOwner = { name: 'TestName', surname: 'TestSurname' }; - - (Workspace.find as any).mockResolvedValue(mockWorkspaces); - (User.findById as any).mockReturnValue({ select: vi.fn().mockResolvedValue(mockOwner) }); - (User.find as any).mockReturnValue({ select: vi.fn().mockResolvedValue(mockLecturers) }); - - const result = await workspaceModule.load({ locals } as any); - - expect(result).toEqual({ - organisation: 'org1', - role: 'admin', - lecturers: [ - { id: '1', name: 'Lecturer1', surname: 'Surname1' }, - { id: '2', name: 'Lecturer2', surname: 'Surname2' } - ], - workspaces: [ - { - id: '1', - name: 'Workspace1', - image: 'img1', - description: '', - owner: 'TestName TestSurname' - }, - { - id: '2', - name: 'Workspace2', - image: 'img2', - description: '', - owner: 'TestName TestSurname' - } - ] - }); - }); - - it('should return workspaces for non-admin users', async () => { - const locals = { user: { id: 'user1', role: 'lecturer' } }; - const mockUser = { workspaces: ['1', '2'] }; - const mockWorkspaces = [ - { _id: '1', name: 'Workspace1', image: 'img1', description: 'Desc1' }, - { _id: '2', name: 'Workspace2', image: 'img2', description: 'Desc2' } - ]; - - (User.findById as any).mockImplementation(() => ({ - select: () => Promise.resolve(mockUser) - })); - (Workspace.find as any).mockResolvedValue(mockWorkspaces); - - const result = await workspaceModule.load({ locals } as any); - - expect(result).toEqual({ - workspaces: [ - { - id: '1', - name: 'Workspace1', - owner: '', - image: 'img1', - description: 'Desc1', - ownerImage: '' - }, - { - id: '2', - name: 'Workspace2', - owner: '', - image: 'img2', - description: 'Desc2', - ownerImage: '' - } - ] - }); - }); - }); - - describe('actions.create', () => { - it('should create a new workspace successfully', async () => { - const mockFormData = new FormData(); - mockFormData.append('name', 'New Workspace'); - mockFormData.append('owner', 'owner1'); - - const mockRequest = { - formData: vi.fn().mockResolvedValue(mockFormData) - }; - - const locals = { user: { role: 'admin', organisation: 'org1' } }; - - const mockUser = { workspaces: [], save: vi.fn() }; - (User.findById as any).mockResolvedValue(mockUser); - - const mockWorkspace = { save: vi.fn() }; - (Workspace as any).mockImplementation(() => mockWorkspace); - - const result = await workspaceModule.actions.create({ request: mockRequest, locals } as any); - - expect(result).toEqual({ success: true }); - expect(Workspace).toHaveBeenCalledWith({ - name: 'New Workspace', - owner: 'owner1', - organisation: 'org1', - image: '/images/workspace-placeholder.png' - }); - expect(mockWorkspace.save).toHaveBeenCalled(); - }); - - it('should fail if user is not admin', async () => { - const locals = { user: { role: 'lecturer' } }; - - await expect(workspaceModule.actions.create({ locals } as any)).rejects.toEqual( - error(401, 'Unauthorised') - ); - }); - }); - - describe('actions.edit', () => { - it('should edit a workspace successfully', async () => { - const mockFormData = new FormData(); - mockFormData.append('id', '123'); - mockFormData.append('name', 'Updated Workspace'); - mockFormData.append('owner', 'newowner'); - - const mockRequest = { - formData: vi.fn().mockResolvedValue(mockFormData) - }; - - const locals = { user: { role: 'admin' } }; - - const mockWorkspace = { - name: 'Old Workspace', - owner: 'oldowner', - save: vi.fn() - }; - (Workspace.findById as any).mockResolvedValue(mockWorkspace); - (User.findByIdAndUpdate as any).mockResolvedValue({}); - - const result = await workspaceModule.actions.edit({ request: mockRequest, locals } as any); - - expect(result).toEqual({ success: true }); - expect(mockWorkspace.name).toBe('Updated Workspace'); - expect(User.findByIdAndUpdate).toHaveBeenCalledTimes(2); - }); - - it('should fail if workspace not found', async () => { - const mockFormData = new FormData(); - mockFormData.append('id', '123'); - - const mockRequest = { - formData: vi.fn().mockResolvedValue(mockFormData) - }; - - const locals = { user: { role: 'admin' } }; - (Workspace.findById as any).mockResolvedValue(null); - - await workspaceModule.actions.delete({ request: mockRequest, locals } as any); - - expect(fail).toHaveBeenCalledWith(404, { error: 'Workspace not found' }); - }); - }); - - describe('actions.delete', () => { - it('should delete a workspace successfully', async () => { - const mockFormData = new FormData(); - mockFormData.append('id', '123'); - - const mockRequest = { - formData: vi.fn().mockResolvedValue(mockFormData) - }; - - const locals = { user: { role: 'admin' } }; - const mockDeletedWorkspace = { _id: '123', owner: 'owner1' }; - (Workspace.findByIdAndDelete as any).mockResolvedValue(mockDeletedWorkspace); - (User.findByIdAndUpdate as any).mockResolvedValue({}); - (User.updateMany as any).mockResolvedValue({}); - - const result = await workspaceModule.actions.delete({ request: mockRequest, locals } as any); - - expect(result).toEqual({ success: true }); - expect(Workspace.findByIdAndDelete).toHaveBeenCalledWith('123'); - expect(User.findByIdAndUpdate).toHaveBeenCalledWith('owner1', { - $pull: { workspaces: '123' } - }); - expect(User.updateMany).toHaveBeenCalledWith( - { workspaces: '123' }, - { $pull: { workspaces: '123' } } - ); - }); - - it('should fail if workspace not found', async () => { - const mockFormData = new FormData(); - mockFormData.append('id', '123'); - - const mockRequest = { - formData: vi.fn().mockResolvedValue(mockFormData) - }; - - const locals = { user: { role: 'admin' } }; - (Workspace.findByIdAndDelete as any).mockResolvedValue(null); - - await workspaceModule.actions.delete({ request: mockRequest, locals } as any); - - expect(fail).toHaveBeenCalledWith(404, { error: 'Workspace not found' }); - }); - }); -}); diff --git a/src/src/tests/unit/server/workspace.test.ts b/src/src/tests/unit/server/workspace.test.ts index 25739996..8b4bdd37 100644 --- a/src/src/tests/unit/server/workspace.test.ts +++ b/src/src/tests/unit/server/workspace.test.ts @@ -5,6 +5,14 @@ import User from '$db/schemas/User'; import Workspace from '$db/schemas/Workspace'; import * as workspaceModule from '$src/routes/(app)/workspaces/+page.server'; +vi.mock('$db/schemas/Grades', () => { + const GradesMock: any = vi.fn().mockImplementation(() => ({ + save: vi.fn() + })); + GradesMock.find = vi.fn(); + return { default: GradesMock }; +}); + vi.mock('$db/schemas/User', () => { const UserMock: any = vi.fn().mockImplementation(() => ({ save: vi.fn()