Skip to content

Commit fbe64e1

Browse files
Merge branch 'main' into fix/profile-page-authenticated-user
2 parents a8b8013 + 7a9b03a commit fbe64e1

63 files changed

Lines changed: 1647 additions & 727 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/BUTTON_VARIANTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ A reusable button system with variants, sizes, keyboard navigation, and full dar
77
Both components are exported from `@/components`:
88

99
```tsx
10-
import { Button, ButtonGroup } from '@/components';
10+
import {Button, ButtonGroup} from '@/components';
1111
import type { ButtonProps } from '@/components';
1212
```
1313

14-
## Overview
14+
##Overview
1515

1616
This project uses URL-based API versioning to protect clients from breaking changes.
1717

docs/DISCORD_OAUTH_INTEGRATION.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
This document describes the Discord OAuth2 integration implementation for the TeachLink authentication flow.
44

5-
## Overview
5+
##Overview
66

77
The Discord OAuth integration allows users to authenticate using their Discord account, providing a seamless signup/login experience.
88

docs/monitoring.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
3. Click "Enable Notifications" and allow permission
88
4. Send a test message
99

10-
## Features
10+
##Features
1111

1212
- **System Health**: Real memory, CPU, uptime from Node.js
1313
- **Notification Metrics**: Sent, Delivered, Clicked, Failed counts

lib/subscriptions.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Shared subscriptions storage for all API routes
1+
// Shared subscription storage for all API routes
22
const subscriptions = new Map();
33

44
export { subscriptions };

next.config.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { describe, expect, it } from 'vitest';
2+
import nextConfig from './next.config';
3+
4+
describe('next.config modularizeImports', () => {
5+
it('adds a lucide-react modularization rule for tree-shaken icon imports', () => {
6+
const modularizeImports = nextConfig.modularizeImports as Record<string, unknown>;
7+
8+
expect(modularizeImports).toBeDefined();
9+
expect(modularizeImports.lodash).toEqual({ transform: 'lodash/{{member}}' });
10+
expect(modularizeImports['lucide-react']).toEqual({
11+
transform: 'lucide-react/dist/esm/icons/{{member}}',
12+
});
13+
});
14+
});

next.config.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ const nextConfig: NextConfig = {
77

88
// Code-splitting optimization for heavy libraries
99
experimental: {
10-
optimizePackageImports: ['@monaco-editor/react', 'video.js', 'ethers'],
10+
optimizePackageImports: ['@monaco-editor/react', 'video.js', 'ethers', 'recharts', 'framer-motion', 'date-fns'],
1111
},
1212

1313
modularizeImports: {
1414
lodash: {
1515
transform: 'lodash/{{member}}',
1616
},
17+
'lucide-react': {
18+
transform: 'lucide-react/dist/esm/icons/{{member}}',
19+
},
1720
},
1821
eslint: {
1922
// Many legacy files do not match Prettier; keep type checking without blocking production builds.

packages/tooling/tsconfig/base.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"compilerOptions": {
33
"target": "ES2017",
44
"lib": ["dom", "dom.iterable", "esnext"],
5-
"allowJs": true,
5+
"allowJs":true,
66
"skipLibCheck": true,
77
"strict": true,
88
"noEmit": true,

scripts/fix-pnpm-lock.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const backupNames = ['pnpm-lock.yaml.broken', 'pnpm-lock.yaml.bak', 'pnpm-lock.y
77
let srcFile = null;
88
for (const name of backupNames) {
99
const p = path.join(repoRoot, name);
10+
1011
if (fs.existsSync(p)) {
1112
srcFile = p;
1213
break;

src/__tests__/sms/queue.test.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,22 @@
55
*/
66

77
import { SMSQueue } from '@/lib/sms/queue';
8-
import { TwilioProvider } from '@/lib/sms/provider';
98
import { SMSMessage } from '@/lib/sms/types';
109

10+
// Mock the TwilioProvider to return success immediately (no credentials in test env)
11+
const mockSend = vi.fn().mockResolvedValue({ success: true, provider: 'twilio', messageId: 'mock-id' });
12+
vi.mock('@/lib/sms/provider', () => {
13+
function MockTwilioProvider() {
14+
this.type = 'twilio';
15+
this.send = mockSend;
16+
}
17+
return {
18+
TwilioProvider: MockTwilioProvider as unknown as typeof import('@/lib/sms/provider').TwilioProvider,
19+
};
20+
});
21+
22+
import { TwilioProvider } from '@/lib/sms/provider';
23+
1124
describe('SMSQueue', () => {
1225
let queue: SMSQueue;
1326
let provider: TwilioProvider;
@@ -251,9 +264,11 @@ describe('SMSQueue', () => {
251264

252265
const logs = queue.getDeliveryLogs();
253266

254-
if (logs.length > 0) {
255-
expect(logs[0].metadata).toBeDefined();
256-
}
267+
expect(logs.length).toBeGreaterThan(0);
268+
// Check the most recent log (last in the array) has metadata
269+
const lastLog = logs[logs.length - 1];
270+
expect(lastLog.metadata).toBeDefined();
271+
expect(lastLog.metadata?.userId).toBe('user123');
257272
});
258273
});
259274
});

src/app/api/certificates/__tests__/certificate-security.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,22 @@ import {
2424
import { slidingWindowRateLimit } from '@/lib/ratelimit';
2525
import { appendAuditLog, queryAuditLogs } from '@/lib/audit';
2626

27+
// Mock the DB pool so generateCertificate's completion check passes
28+
vi.mock('@/lib/db/pool', () => ({
29+
query: vi.fn().mockResolvedValue({
30+
rows: [
31+
{
32+
user_id: 'user-123',
33+
course_id: 'course-123',
34+
progress: 100,
35+
completed_lessons: [],
36+
last_accessed_at: new Date().toISOString(),
37+
completed_at: new Date().toISOString(),
38+
},
39+
],
40+
}),
41+
}));
42+
2743
describe('Certificate Security', () => {
2844
const mockUserId = 'user-123';
2945
const mockCourseId = 'course-123';

0 commit comments

Comments
 (0)