Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
85 changes: 80 additions & 5 deletions __tests__/components/stepper/stepper.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,81 @@
// TODO: Implement your tests here
describe("Stepper", () => {
it("TODO", () => {
expect(true).toBe(false);
});
import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import Stepper from '../../../components/stepper/stepper';
import useStepper from '../../../hooks/useStepper';

// Mock the useStepper hook
jest.mock('../../../hooks/useStepper');

const mockUseStepper = useStepper as jest.MockedFunction<typeof useStepper>;

describe('Stepper Component', () => {
const mockSteps = [
{ id: 1, title: 'Service' },
{ id: 2, title: 'Termin' },
{ id: 3, title: 'Fahrzeug' },
{ id: 4, title: 'Kontakt' },
];

const createMockStepper = (currentStep: number) => ({
currentStep,
handleNextStep: jest.fn(),
});

beforeEach(() => {
mockUseStepper.mockReturnValue(createMockStepper(1));
});

afterEach(() => {
jest.clearAllMocks();
});

it('renders without crashing', () => {
render(<Stepper steps={mockSteps} />);
expect(screen.getByText('Service')).toBeInTheDocument();
expect(screen.getByText('Termin')).toBeInTheDocument();
expect(screen.getByText('Fahrzeug')).toBeInTheDocument();
expect(screen.getByText('Kontakt')).toBeInTheDocument();
});

it('displays "No steps provided" when steps array is empty', () => {
render(<Stepper steps={[]} />);
expect(screen.getByText('No steps provided')).toBeInTheDocument();
});

it('displays "No steps provided" when steps is null', () => {
render(<Stepper steps={null as any} />);
expect(screen.getByText('No steps provided')).toBeInTheDocument();
});

it('renders step titles correctly', () => {
render(<Stepper steps={mockSteps} />);
expect(screen.getByText('Service')).toBeInTheDocument();
expect(screen.getByText('Termin')).toBeInTheDocument();
expect(screen.getByText('Fahrzeug')).toBeInTheDocument();
expect(screen.getByText('Kontakt')).toBeInTheDocument();
});

it('applies correct styles for completed steps', () => {
mockUseStepper.mockReturnValue(createMockStepper(2));
render(<Stepper steps={mockSteps} />);
const stepCircles = document.querySelectorAll('.rounded-full');
expect(stepCircles[0].className).toContain('bg-blue-500');
expect(stepCircles[1].className).toContain('bg-blue-500');
});

it('applies correct styles for inactive steps', () => {
mockUseStepper.mockReturnValue(createMockStepper(0));
render(<Stepper steps={mockSteps} />);
const stepCircles = document.querySelectorAll('.rounded-full');
expect(stepCircles[1].className).toContain('bg-gray-200');
expect(stepCircles[2].className).toContain('bg-gray-200');
expect(stepCircles[3].className).toContain('bg-gray-200');
});

it('renders connector lines between steps', () => {
render(<Stepper steps={mockSteps} />);
const connectorLines = document.querySelectorAll('.absolute.top-6');
expect(connectorLines).toHaveLength(3);
});
});
80 changes: 67 additions & 13 deletions components/stepper/stepper.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,68 @@
interface StepperProps {}

export default function Stepper() {
/*TODO: Replace this with the actual Stepper implementation*/
return (
<div
className={
"h-[100px] border border-dashed border-gray-200 rounded flex justify-center items-center"
}
>
<code className={"text-2xl"}>{"<Stepper />"}</code>
</div>
);
import useStepper from "../../hooks/useStepper";

interface Steps {
id: number
title: string
completed?: boolean
}

interface StepperProps {
steps: Steps[]
}

export default function Stepper({ steps }: StepperProps) {
const { currentStep } = useStepper();

if (!steps || steps.length === 0) {
return (
<div className="w-full max-w-md mx-auto text-center text-gray-500">
No steps provided
</div>
);
}


return (
<div className="w-full max-w-md mx-auto">
<div className="flex items-center justify-between">
{steps.map((step, index) => {
const stepNumber = index;
const isActive = stepNumber === currentStep;
const isCompleted = stepNumber < currentStep;

return (
<div key={step.id} className="flex flex-col items-center relative">
{index < steps.length - 1 && (
<div className="absolute top-6 left-12 w-24 h-0.5 bg-gray-300"/>
)}

<div
className={`
relative w-12 h-12 rounded-full flex items-center justify-center
text-lg font-semibold
${isActive
? 'bg-blue-500 text-white'
: isCompleted
? 'bg-blue-500 text-white'
: 'bg-gray-200 text-gray-600'
}
`}>
{ index + 1}
</div>

<span className={`
mt-3 text-sm font-medium text-center
${isActive || isCompleted
? 'text-blue-500'
: 'text-gray-500'
}
`}>
{step.title}
</span>
</div>
);
})}
</div>
</div>
);
}
11 changes: 9 additions & 2 deletions components/stepper/steps.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
interface Step {
title: string;
id: number;
title: string;
completed?: boolean;
}

export const steps: Step[] = [];
export const steps: Step[] = [
{ id: 1, title: 'Fahrzeug' },
{ id: 2, title: 'Termin' },
{ id: 3, title: 'Fahrzeug' },
{ id: 4, title: 'Kontakt' }
];
30 changes: 15 additions & 15 deletions pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ import MainWrapper from "../components/repareo/mainWrapper";
import StepperWrapper from "../components/repareo/stepperWrapper";
import Stepper from "../components/stepper/stepper";
import useStepper from "../hooks/useStepper";
import {steps} from "../components/stepper/steps";

export default function Home() {
const { currentStep, handleNextStep } = useStepper();
return (
<>
<Header />
<MainWrapper>
<StepperWrapper>
{/*TODO: Make sure the Stepper handles clicks on the button*/}
<Stepper />
</StepperWrapper>
<ButtonWrapper>
<Button onClick={handleNextStep}>Next</Button>
</ButtonWrapper>
</MainWrapper>
</>
);
const { currentStep, handleNextStep } = useStepper();
return (
<>
<Header />
<MainWrapper>
<StepperWrapper>
<Stepper steps={steps} />
</StepperWrapper>
<ButtonWrapper>
<Button onClick={handleNextStep}>Next</Button>
</ButtonWrapper>
</MainWrapper>
</>
);
}