-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
created ci/cd workflow folder with basic pipeline; logout flow WIP
- Loading branch information
Showing
8 changed files
with
287 additions
and
139 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
name: CI/CD Pipeline | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
pull_request: | ||
branches: | ||
- main | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
|
||
strategy: | ||
matrix: | ||
node-version: [16.x, 18.x] | ||
|
||
steps: | ||
- name: Checkout repository | ||
uses: actions/checkout@v3 | ||
|
||
- name: Set up Node.js | ||
uses: actions/setup-node@v3 | ||
with: | ||
node-version: ${{ matrix.node-version }} | ||
|
||
- name: Install dependencies | ||
run: npm install | ||
|
||
- name: Run tests | ||
run: npm run test | ||
|
||
- name: Build Next.js app | ||
run: npm run build | ||
|
||
- name: Deploy to Vercel | ||
run: vercel --prod | ||
env: | ||
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// app/dashboard/Dashboard.test.tsx | ||
import React from 'react'; | ||
import { render, screen } from '@testing-library/react'; | ||
import '@testing-library/jest-dom'; | ||
import DashboardPage from '../dashboard/page'; | ||
import DashboardClient from '../dashboard/DashboardClient'; | ||
import { cookies } from 'next/headers'; | ||
import { redirect } from 'next/navigation'; | ||
|
||
// Mock next/headers and next/navigation | ||
jest.mock('next/headers', () => ({ | ||
cookies: jest.fn(), | ||
})); | ||
|
||
jest.mock('next/navigation', () => ({ | ||
redirect: jest.fn(), | ||
})); | ||
|
||
// Sample user data for the tests | ||
const mockUserData = { | ||
id: '1', | ||
email: '[email protected]', | ||
fullName: 'Test User', | ||
lastName: 'User', | ||
}; | ||
|
||
describe('DashboardPage (Server Component)', () => { | ||
it('should redirect if no user data cookie is found', () => { | ||
// Mock cookies to return no data | ||
(cookies as jest.Mock).mockReturnValue({ | ||
get: jest.fn().mockReturnValue(undefined), | ||
}); | ||
|
||
const { container } = render(<DashboardPage />); | ||
|
||
// Ensure redirect is called | ||
expect(redirect).toHaveBeenCalledWith('/'); | ||
// Ensure the component doesn't render anything (returns null) | ||
expect(container.firstChild).toBeNull(); | ||
}); | ||
|
||
it('should render DashboardClient when user data is found in cookies', () => { | ||
// Mock cookies to return user data | ||
(cookies as jest.Mock).mockReturnValue({ | ||
get: jest.fn().mockReturnValue({ | ||
value: JSON.stringify(mockUserData), | ||
}), | ||
}); | ||
|
||
render(<DashboardPage />); | ||
|
||
// Ensure DashboardClient is rendered | ||
const greeting = screen.getByText(`Hello ${mockUserData.fullName}!`); | ||
expect(greeting).toBeInTheDocument(); | ||
}); | ||
}); | ||
|
||
describe('DashboardClient (Client Component)', () => { | ||
it('renders the user information and ExampleEquations component', () => { | ||
render(<DashboardClient userData={mockUserData} />); | ||
|
||
// Check if the user's name is displayed | ||
const greeting = screen.getByText(`Hello ${mockUserData.fullName}!`); | ||
expect(greeting).toBeInTheDocument(); | ||
|
||
// Instead of matching "ExampleEquations", look for the actual content it renders, like buttons or headers | ||
const exampleEquationText = screen.getByText(/Select an Example/i); // Assuming ExampleEquations renders this text | ||
expect(exampleEquationText).toBeInTheDocument(); | ||
|
||
// Alternatively, if ExampleEquations renders buttons, use getByRole: | ||
const firstExampleButton = screen.getByRole('button', { name: /x \+ 1 = 2/i }); | ||
expect(firstExampleButton).toBeInTheDocument(); | ||
}); | ||
|
||
it('should render correctly when userData is provided', () => { | ||
const mockUserData = { | ||
id: '1', | ||
email: '[email protected]', | ||
fullName: 'Test User', | ||
lastName: 'User' | ||
}; | ||
|
||
render(<DashboardClient userData={mockUserData} />); | ||
|
||
const greeting = screen.getByText(/Hello Test User!/i); | ||
expect(greeting).toBeInTheDocument(); | ||
}); | ||
|
||
}); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,84 +1,79 @@ | ||
import React from 'react'; | ||
import { render, fireEvent, screen } from '@testing-library/react'; | ||
import { render, screen, fireEvent, waitFor } from '@testing-library/react'; | ||
import '@testing-library/jest-dom'; | ||
import Calcbar from '../components/Calcbar'; | ||
import mathsteps from 'mathsteps'; | ||
|
||
jest.mock('mathsteps'); | ||
// Type the mock function | ||
jest.mock('mathsteps', () => ({ | ||
solveEquation: jest.fn(), | ||
})); | ||
|
||
describe('Calcbar', () => { | ||
const mockUserId = 'test-user-id'; | ||
// Define the type for steps | ||
interface Step { | ||
newEquation: { ascii: () => string }; | ||
changeType: string; | ||
} | ||
|
||
describe('Calcbar Component', () => { | ||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
it('renders the Calcbar component', () => { | ||
render(<Calcbar userId={''} />); | ||
test('renders correctly with default props', () => { | ||
render(<Calcbar userId="123" />); | ||
|
||
expect(screen.getByLabelText(/Enter an algebraic equation/i)).toBeInTheDocument(); | ||
expect(screen.getByText(/Solve/i)).toBeInTheDocument(); | ||
}); | ||
|
||
it('displays the solution when a valid equation is solved', () => { | ||
const stepsMock = [ | ||
{ newEquation: { ascii: () => 'x = 1' }, changeType: 'SOLVE_EQUATION' }, | ||
test('renders example input and solves equation on load', async () => { | ||
const mockSteps: Step[] = [ | ||
{ newEquation: { ascii: () => 'x = 2' }, changeType: 'simplify' }, | ||
{ newEquation: { ascii: () => 'x = 3' }, changeType: 'simplify' }, | ||
]; | ||
(mathsteps.solveEquation as jest.Mock).mockReturnValue(stepsMock); | ||
|
||
render(<Calcbar userId={''} />); | ||
|
||
fireEvent.change(screen.getByLabelText(/Enter an algebraic equation/i), { target: { value: 'x + 1 = 2' } }); | ||
fireEvent.click(screen.getByText(/Solve/i)); | ||
|
||
expect(screen.getByText(/Solution: x = 1/i)).toBeInTheDocument(); | ||
(mathsteps.solveEquation as jest.Mock).mockReturnValue(mockSteps); | ||
|
||
render(<Calcbar exampleInput="x + 2 = 4" userId="123" />); | ||
|
||
// Check that the input field has the example input value | ||
expect(screen.getByLabelText(/Enter an algebraic equation/i)).toHaveValue('x + 2 = 4'); | ||
|
||
// Wait for the solution to appear | ||
await waitFor(() => expect(screen.getByText(/Solution: x = 3/i)).toBeInTheDocument()); | ||
|
||
// Check steps | ||
expect(screen.getByText(/Step 1/i)).toBeInTheDocument(); | ||
expect(screen.getByText(/simplify/i)).toBeInTheDocument(); | ||
}); | ||
|
||
it('displays "Invalid equation" when an invalid equation is entered', () => { | ||
(mathsteps.solveEquation as jest.Mock).mockImplementation(() => { throw new Error('Invalid equation'); }); | ||
|
||
render(<Calcbar userId={''} />); | ||
test('handles invalid equation', async () => { | ||
(mathsteps.solveEquation as jest.Mock).mockImplementation(() => { throw new Error(); }); | ||
|
||
render(<Calcbar userId="123" />); | ||
|
||
fireEvent.change(screen.getByLabelText(/Enter an algebraic equation/i), { target: { value: 'invalid equation' } }); | ||
fireEvent.click(screen.getByText(/Solve/i)); | ||
|
||
expect(screen.getByText(/Solution: Invalid equation/i)).toBeInTheDocument(); | ||
|
||
// Wait for the solution to update | ||
await waitFor(() => expect(screen.getByText(/Invalid equation/i)).toBeInTheDocument()); | ||
}); | ||
|
||
it('displays steps when a valid equation is solved', () => { | ||
const stepsMock = [ | ||
{ newEquation: { ascii: () => 'x + 1 = 2' }, changeType: 'ADD_CONSTANT' }, | ||
{ newEquation: { ascii: () => 'x = 1' }, changeType: 'SOLVE_EQUATION' }, | ||
]; | ||
(mathsteps.solveEquation as jest.Mock).mockReturnValue(stepsMock); | ||
|
||
render(<Calcbar userId={''} />); | ||
test('calls handleSolve on input change and button click', async () => { | ||
const mockSteps: Step[] = [{ newEquation: { ascii: () => 'x = 2' }, changeType: 'simplify' }]; | ||
(mathsteps.solveEquation as jest.Mock).mockReturnValue(mockSteps); | ||
|
||
fireEvent.change(screen.getByLabelText(/Enter an algebraic equation/i), { target: { value: 'x + 1 = 2' } }); | ||
render(<Calcbar userId="123" />); | ||
|
||
fireEvent.change(screen.getByLabelText(/Enter an algebraic equation/i), { target: { value: 'x + 2 = 4' } }); | ||
fireEvent.click(screen.getByText(/Solve/i)); | ||
|
||
expect(screen.getByText(/Steps/i)).toBeInTheDocument(); | ||
expect(screen.getByText(/Step 1/i)).toBeInTheDocument(); | ||
expect(screen.getAllByText(/x \+ 1 = 2/i)).toHaveLength(1); | ||
expect(screen.getByText(/add constant/i)).toBeInTheDocument(); | ||
expect(screen.getByText(/Step 2/i)).toBeInTheDocument(); | ||
expect(screen.getAllByText(/x = 1/i)).toHaveLength(2); | ||
expect(screen.getByText(/solve equation/i)).toBeInTheDocument(); | ||
|
||
await waitFor(() => expect(screen.getByText(/Solution: x = 2/i)).toBeInTheDocument()); | ||
}); | ||
|
||
it('opens the Add to Study Guide modal when AddButton is clicked', () => { | ||
const stepsMock = [ | ||
{ newEquation: { ascii: () => 'x = 1' }, changeType: 'SOLVE_EQUATION' }, | ||
]; | ||
(mathsteps.solveEquation as jest.Mock).mockReturnValue(stepsMock); | ||
|
||
render(<Calcbar userId={mockUserId} />); | ||
|
||
fireEvent.change(screen.getByLabelText(/Enter an algebraic equation/i), { target: { value: 'x + 1 = 2' } }); | ||
fireEvent.click(screen.getByText(/Solve/i)); | ||
fireEvent.click(screen.getByText(/Add to Study Guide/i)); | ||
|
||
expect(screen.getByText(/Add to Study Guide/i)).toBeInTheDocument(); | ||
expect(screen.getByLabelText(/New Title/i)).toBeInTheDocument(); | ||
expect(screen.getByLabelText(/Existing Title/i)).toBeInTheDocument(); | ||
test('does not render AddButton component', async () => { | ||
render(<Calcbar userId="123" exampleInput="x + 2 = 4" />); | ||
|
||
// Ensure AddButton is not rendered | ||
expect(screen.queryByText(/AddButton Mock/i)).not.toBeInTheDocument(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,19 @@ | ||
import { NextRequest, NextResponse } from 'next/server' | ||
import { createClient } from '../../utils/supabase/server' | ||
import { deleteCookie } from '../../utils/supabase/cookies' | ||
import { NextRequest, NextResponse } from 'next/server'; | ||
import { createClient } from '../../utils/supabase/server'; | ||
import { deleteCookie } from '../../utils/supabase/cookies'; | ||
|
||
export async function POST(req: NextRequest): Promise<NextResponse> { | ||
const supabase = createClient(); | ||
|
||
export async function POST(req: NextRequest) { | ||
const supabase = createClient(); | ||
const { error } = await supabase.auth.signOut(); | ||
|
||
const { error } = await supabase.auth.signOut() | ||
if (error) { | ||
console.error('Failed to logout', error); | ||
return NextResponse.redirect(new URL('/error', req.url)); // Redirect to an error page if there's an error | ||
} | ||
|
||
if (error) { | ||
return NextResponse.redirect(new URL('/error', req.url)) | ||
} | ||
const response = NextResponse.redirect(new URL('/', req.url)); // Redirect to the home page | ||
deleteCookie(response, 'user-data'); // Delete cookies if needed | ||
|
||
const response = NextResponse.redirect(new URL('/login', req.url)) | ||
// Delete cookies if needed | ||
deleteCookie(response, 'user-data') | ||
|
||
return response | ||
} | ||
return response; | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.