Skip to content

Testing‐Manual‐Frontend‐Web

Selman Akman edited this page May 13, 2025 · 1 revision

Testing Guide

Overview

The Greener frontend uses Jest and React Testing Library for unit and integration tests, configured via Create React App.

Running Tests

  1. Run All Tests:
    npm test
    
  • Launches Jest in watch mode.

  • Press a to run all tests, or select specific files.

  • Single Test File: npm test src/App.test.js

  • Coverage Report: npm test -- --coverage

Writing Tests

  • Location: Place test files alongside components (e.g., Component.test.js).
  • Tools:
    • React Testing Library: render, screen, fireEvent for DOM interactions.
    • Jest: Assertions (expect) and mocks.
    • @testing-library/user-event: Simulates user interactions like typing and clicking.

Best Practices

  • Test user-facing behavior, not implementation details.
  • Mock API calls using Jest's jest.fn() or mock modules.
  • Use data-testid attributes for stable DOM queries.
  • Cover critical paths: rendering, user interactions, error states.

Example Test

  • See docs/testing/sample-tests.md for a sample unit test for LoginPage.js.

Sample Tests

Unit Test for LoginPage.js

This test verifies the login form's rendering and submission behavior.

File: src/components/auth/LoginPage.test.js

import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import axios from 'axios';
import LoginPage from './LoginPage';

// Mock axios
jest.mock('axios');

describe('LoginPage', () => {
  // Mock useNavigate
  const mockedNavigate = jest.fn();
  jest.mock('react-router-dom', () => ({
    ...jest.requireActual('react-router-dom'),
    useNavigate: () => mockedNavigate,
  }));

  // Wrapper for routing context
  const renderWithRouter = (ui) => render(ui, { wrapper: BrowserRouter });

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

  test('renders login form and submits credentials', async () => {
    // Mock successful API response
    axios.post.mockResolvedValue({
      data: {
        access: 'mock-token',
        refresh: 'mock-refresh',
        user_id: '1',
        email: '[email protected]',
        role: 'user',
      },
    });

    // Render component
    renderWithRouter(<LoginPage />);

    // Check form elements
    expect(screen.getByLabelText(/email address/i)).toBeInTheDocument();
    expect(screen.getByLabelText(/password/i)).toBeInTheDocument();
    expect(screen.getByRole('button', { name: /login/i })).toBeInTheDocument();

    // Fill form
    fireEvent.change(screen.getByLabelText(/email address/i), {
      target: { value: '[email protected]' },
    });
    fireEvent.change(screen.getByLabelText(/password/i), {
      target: { value: 'password123' },
    });

    // Submit form
    fireEvent.click(screen.getByRole('button', { name: /login/i }));

    // Verify API call
    await waitFor(() => {
      expect(axios.post).toHaveBeenCalledWith(
        'http://127.0.0.1:8000/api/token/',
        {
          email: '[email protected]',
          password: 'password123',
        }
      );
    });

    // Verify localStorage and navigation
    expect(localStorage.getItem('access_token')).toBe('mock-token');
    expect(mockedNavigate).toHaveBeenCalledWith('/dashboard');
  });

  test('displays error on failed login', async () => {
    // Mock failed API response
    axios.post.mockRejectedValue({
      response: { data: { detail: 'Invalid credentials' } },
    });

    renderWithRouter(<LoginPage />);

    // Fill and submit form
    fireEvent.change(screen.getByLabelText(/email address/i), {
      target: { value: '[email protected]' },
    });
    fireEvent.change(screen.getByLabelText(/password/i), {
      target: { value: 'wrong' },
    });
    fireEvent.click(screen.getByRole('button', { name: /login/i }));

    // Check error message
    await waitFor(() => {
      expect(screen.getByText(/Invalid credentials/i)).toBeInTheDocument();
    });
  });
});

Explanation

  • Test Setup: Mocks axios and useNavigate to isolate dependencies.
  • Test Cases:
    • Successful Login: Verifies form rendering, submission, API call, localStorage updates, and navigation.
    • Failed Login: Tests error handling when the API returns an error.
  • Tools: Uses render, screen, and fireEvent from React Testing Library, with waitFor for async operations.

Labs

Team Members

Weekly Reports

Ahmet Okta
Barathan Aslan
Berke Kartal
Mehmet Çağlar Kurt
Mehmet Emin Atak
Muhammet Berkay Keskin
Mustafa Taha Söylemez
Nilsu Tüysüz
Selman Akman
Ömer Faruk Bayram

Meetings

Milestones

Templates

Research on Git

Projects

Project Resources

Software Design Diagrams

Documentation(Manuals & Research Doc)

CMPE352 Archive

Projects

Project Resources

Software Design Diagrams

Documentation(Manuals & Research Doc)



Documentation(Individual Contributions and/or Milestone Report)

Individual Contributions

Meeting Notes

Clone this wiki locally