Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
ff95805
Updated React Dependency Versions
NewtonLC Apr 28, 2026
b6c3a3f
style: align globals.css with main freeCodeCamp platform
NewtonLC Jun 13, 2026
7044014
style: align tailwind color tokens with main freeCodeCamp platform
NewtonLC Jun 13, 2026
4b50b6b
Merge branch 'freeCodeCamp:main' into feat/css-fcc-alignment
NewtonLC Jun 14, 2026
761e107
Synchronized Classroom CSS with FCC Proper
NewtonLC Jun 15, 2026
3c21a1e
Updated Test and Snapshots
NewtonLC Jun 16, 2026
ce920bb
feat: improve teacher feedback for fetch failures and empty classroom…
NewtonLC Jun 17, 2026
fc9695c
Merge branch 'freeCodeCamp:main' into feat/606-fetch-error-empty-clas…
NewtonLC Jun 22, 2026
1da354f
fix(navbar): show Dashboard instead of Classes label for admin users
AbiramiR-27 Jun 6, 2026
cbb1617
fix(navbar): hide classes link for unauthenticated and non-admin/teac…
AbiramiR-27 Jun 8, 2026
f0d8147
fix: prevent page crashes when mock-fcc-data server is offline
AbiramiR-27 Jun 10, 2026
59f3a4d
fix: address review comments on offline crash prevention
AbiramiR-27 Jun 15, 2026
512f1e5
Removed redundant null catch code
NewtonLC Jun 16, 2026
2b76083
Improve UI Feedback for Failing Student Fetches and Empty Classrooms
NewtonLC Jun 22, 2026
1996496
Reversed changes on dead files
NewtonLC Jun 22, 2026
f5d7444
Added Certification List tooltip to Classes page
NewtonLC Aug 4, 2026
3fb1372
Add Client-side CSS Text-Wrapping and Character Count Caps
NewtonLC Aug 4, 2026
e8ccbd5
Redesign Create and Edit Class Modals
NewtonLC Aug 10, 2026
5ccc79d
Merge branch 'feat/css-fcc-alignment' into feat/609-ui-ux-polish
NewtonLC Sep 26, 2026
9e4fd04
Merge branch 'redesign/class-modals' into feat/609-ui-ux-polish
NewtonLC Sep 26, 2026
ce9a536
Merge branch 'feat/class-card-redesign' into feat/609-ui-ux-polish
NewtonLC Sep 26, 2026
df5451a
chore(ui): install @freecodecamp/ui and adopt its design tokens
NewtonLC Sep 26, 2026
c413fc7
feat(ui): use @freecodecamp/ui Button and fCC typography
NewtonLC Sep 27, 2026
3121022
feat(ui): rebuild Create/Edit Class modal on @freecodecamp/ui Modal
NewtonLC Sep 27, 2026
f75c342
feat(ui): use @freecodecamp/ui form controls for admin forms
NewtonLC Sep 27, 2026
abdc5ce
feat(ui): rebuild class card on @freecodecamp/ui Panel and Dropdown
NewtonLC Sep 27, 2026
7ae9e1f
feat(ui): replace alert/confirm with fCC Modal, toasts, Alert and Cal…
NewtonLC Sep 27, 2026
e8542dc
feat(ui): use @freecodecamp/ui HeadlessDisclosure for collapsible sec…
NewtonLC Sep 27, 2026
87f5d78
feat(ui): use @freecodecamp/ui Table for dashboard and admin tables
NewtonLC Sep 27, 2026
22cc041
feat(ui): rebuild the navbar after freeCodeCamp's header
NewtonLC Sep 27, 2026
0b555a3
feat(ui): theme toasts like the @freecodecamp/ui Alert
NewtonLC Sep 27, 2026
93f8503
feat(ui): shared fCC-styled pagination for the admin tables
NewtonLC Sep 27, 2026
8567c7d
feat(ui): fCC-styled activity status and progress bar on the dashboard
NewtonLC Sep 27, 2026
a969b35
feat(ui): restyle the student details page with fCC patterns
NewtonLC Sep 27, 2026
9e49d24
feat: role-aware onboarding guides on the landing page
NewtonLC Sep 27, 2026
b55e2b7
Merge PR #607 (feat/606-fetch-error-empty-classroom) into feat/609-ui…
NewtonLC Sep 27, 2026
5a887fe
feat: class page header with details and invite link
NewtonLC Sep 27, 2026
2f2ba44
chore(ui): clean up page titles and leftover create-next-app styles
NewtonLC Sep 27, 2026
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
100 changes: 100 additions & 0 deletions __tests__/api/editClass.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// next-auth's main entry transitively pulls in openid-client/jose
// (ESM-only), which Jest's default transform can't parse. Stub it out.
jest.mock('next-auth', () => ({
__esModule: true,
default: jest.fn(() => jest.fn()),
unstable_getServerSession: jest.fn()
}));

jest.mock('../../pages/api/auth/[...nextauth]', () => ({
authOptions: {}
}));

jest.mock('../../prisma/prisma', () => ({
__esModule: true,
default: {
user: {
findUniqueOrThrow: jest.fn()
},
classroom: {
update: jest.fn()
}
}
}));

import { unstable_getServerSession } from 'next-auth';
import prisma from '../../prisma/prisma';
import editClassHandler from '../../pages/api/editclass';

const createReq = body => ({ method: 'PUT', body });

const createRes = () => {
const res = {};
res.status = jest.fn().mockReturnValue(res);
res.json = jest.fn().mockReturnValue(res);
res.end = jest.fn().mockReturnValue(res);
return res;
};

describe('PUT /api/editclass', () => {
beforeEach(() => {
jest.clearAllMocks();
unstable_getServerSession.mockResolvedValue({
user: { email: 'teacher@example.com' }
});
prisma.user.findUniqueOrThrow.mockResolvedValue({ role: 'TEACHER' });
prisma.classroom.update.mockImplementation(({ where, data }) =>
Promise.resolve({ classroomId: where.classroomId, ...data })
);
});

// Regression test: an empty list used to be turned into "no change", so a
// class could be created without certifications but never edited to have none.
it('saves an empty certification list when every certification is removed', async () => {
const res = createRes();

await editClassHandler(
createReq({ classroomId: 'class-1', fccCertifications: [] }),
res
);

expect(prisma.classroom.update).toHaveBeenCalledWith({
where: { classroomId: 'class-1' },
data: {
classroomName: undefined,
description: undefined,
fccCertifications: []
}
});
expect(res.json).toHaveBeenCalledWith(
expect.objectContaining({ fccCertifications: [] })
);
});

it('saves a new name sent as classroomName', async () => {
const res = createRes();

await editClassHandler(
createReq({ classroomId: 'class-1', classroomName: 'Renamed' }),
res
);

expect(prisma.classroom.update).toHaveBeenCalledWith({
where: { classroomId: 'class-1' },
data: {
classroomName: 'Renamed',
description: undefined,
fccCertifications: undefined
}
});
});

it('responds 304 without updating when no fields are sent', async () => {
const res = createRes();

await editClassHandler(createReq({ classroomId: 'class-1' }), res);

expect(res.status).toHaveBeenCalledWith(304);
expect(prisma.classroom.update).not.toHaveBeenCalled();
});
});
Loading
Loading