Skip to content

Sprint3

HardCoder19 edited this page Apr 1, 2025 · 5 revisions

Sprint 3 Report - Sportify

Work Completed in Sprint 3

During Sprint 3, the backend team implemented the event management system. An event denotes a sport event that any user can create, and other users can join. This includes endpoints for creating, updating, joining, and deleting sports events, along with database schema enhancements. On the Frontend part the site went into major look overhaul for making it more aesthetically pleasing so it now has a new background and custom logo and we added the my profile page which displays the profile information for each user and now there is also a "+" symbol on the nav bar from which you can create events which has the location autocomplete feature implemented though google maps api, the event gets displayed on home page after creation and the enhancement which we'll be working on is making it all integrated with the backend by the next sprint.


Issues for Sprint 3

Issue Number Title Objective Status
34 Create Event API Implement API to create new events. Completed
47 Update Event API Implement API to update existing events. Completed
48 Fetch All Events API Develop API to retrieve event list. Completed
49 Get Event by ID API Implement API to fetch event details by ID. Completed
50 Join Event API Develop API to allow users to join events. Completed
51 Leave Event API Implement API to allow users to leave events. Completed
52 Delete Event API Create API to delete existing events. Completed
61 New Event tile Generate new event till on home page Completed
60 unit tests for new page write tests for new pages and features Completed
59 Integrate Google map api add address api in event create form Completed
58 add event create to the nav bar Add option to create events on home page Completed
57 Event create page frontend for the page for event creation Completed
56 MyProfile Page frontend for the MyProfile page Completed

1. Backend Enhancements - Event APIs

  • Database Schema Additions:

    • events table

      CREATE TABLE events (
          id SERIAL PRIMARY KEY,
          event_owner INT REFERENCES users(id) ON DELETE CASCADE,
          sport TEXT NOT NULL,
          event_datetime TIMESTAMP NOT NULL,
          max_players INT NOT NULL CHECK (max_players > 0),
          location_name TEXT NOT NULL,
          latitude DECIMAL(9,6) NOT NULL,
          longitude DECIMAL(9,6) NOT NULL,
          description TEXT,
          title TEXT,
          is_full BOOLEAN,
          created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
          updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
      );
    • event_participants table

      CREATE TABLE event_participants (
          id SERIAL PRIMARY KEY,
          event_id INT REFERENCES events(id) ON DELETE CASCADE,
          user_id INT REFERENCES users(id) ON DELETE CASCADE,
          joined_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
      );
  • New Event Endpoints:

    • POST /events: Create a new event.
    • GET /events: Retrieve all events with optional filters.
    • GET /events/:id: Retrieve a single event by ID.
    • PUT /events/:id: Update an event.
    • POST /events/:id/join: Join an event.
    • DELETE /events/:id/leave: Leave an event.
    • DELETE /events/:id: Delete an event.
  • Example Request/Response:

    • POST /events Request:

      {
        "sport": "Football",
        "event_date": "2025-03-25T15:00:00Z",
        "max_players": 20,
        "location_name": "Central Park, NY",
        "latitude": 40.785091,
        "longitude": -73.968285,
        "description": "Need players for a friendly football match",
        "title": "Lets football!"
      }
    • POST /events Response:

      {
        "id": 1,
        "event_owner": 1,
        "sport": "Football",
        "event_datetime": "2025-03-25T15:00:00Z",
        "max_players": 20,
        "location_name": "Central Park, NY",
        "latitude": 40.785091,
        "longitude": -73.968285,
        "description": "Friendly football match",
        "title": "Lets football!",
        "created_at": "2025-03-25T10:00:00Z",
        "updated_at": "2025-03-25T10:00:00Z",
        "is_full": false,
        "registered_count": 0
      }
  • Business Logic:

    • Event capacity is updated automatically when users join or leave.
    • Events are marked as full (is_full=true) when registered_count >= max_players.

2. Frontend Enhancements

Aesthetic Overhaul and New Features:

  • Site Overhaul:

    • The site went through a major aesthetic overhaul to make it more visually appealing. This includes:

      • A new background for the pages.

      • A custom logo to represent the brand.

  • My Profile Page:

    • A "My Profile" page has been added, where users can view their profile information.
  • Event Creation via Menu Bar:

    • We added a "+" button to the menu bar, which allows users to create events.

    • The Create Event page includes a location autocomplete feature to help users select a location easily.

  • Home Page Display:

    • After creating an event, the event is displayed on the home page for users to view.
  • Future Enhancements:

    • In the next sprint, we will work on integrating the frontend with the backend to make the event creation and other features fully functional.

3. Unit and Cypress Tests

Frontend Unit Tests for Sprint 3

  • src/test/:

    • CreateEvent_test

      • Test Purpose:
    • The test checks that the CreateEvent form renders correctly with all required fields and elements (heading, form fields, and submit button).

      • Test Setup:

      • render: The render function from React Testing Library is used to render the CreateEvent component within a BrowserRouter wrapper. This is necessary because the component likely uses routing via react-router-dom.

      • Check for Heading:

      • expect(screen.getByRole('heading', { name: /Create Event/i })):

      • This checks that the heading with the text "Create Event" is present in the DOM. The regular expression /Create Event/i ensures that it is case-insensitive.

      • Check for Form Fields:

        • expect(screen.getByLabelText(/Event Title/i)):

        • This checks that the form input field for "Event Title" is present in the DOM. The getByLabelText method looks for form fields by their associated label text.

      • Similarly, the other form fields checked are:

      • Description

      • Sport

      • Maximum Players

      • Location

      • Date and Time

      • Check for Submit Button:

      • expect(screen.getByRole('button', { name: /Create Event/i })):

      • This checks that the submit button labeled "Create Event" is present and can be interacted with. The getByRole method is used to find buttons or other interactive elements by their role.

      • Assertions:

      • Each expect() statement asserts that a specific element (heading, form field, or button) is rendered correctly. If any of these elements are missing, the test will fail.

    • MyProfile.test.js *- Test Setup:

      • The render function from React Testing Library is used to render the MyProfile component wrapped in MemoryRouter (to handle routing in tests).

      • useNavigate from react-router-dom is mocked using jest.fn() to simulate navigation during the tests.

    • Test 1: "should render the My profile form correctly":

      • Verifies that all required input fields (First Name, Last Name, Age, Gender, and Sports dropdown) are rendered correctly on the page.

      • Assertions: Check for placeholders and text content in the form.

    • Test 2: "should allow user to enter profile details":

      • Simulates user input by firing change events on the form fields (First Name, Last Name, Age).

      • Assertions: Ensures that the form fields' values are updated correctly after user input.

    • Test 3: "should allow user to select gender":

      • Simulates the selection of a gender from a dropdown.

      • Assertions: Checks if the selected gender value is updated correctly after user interaction.

    • Test 4: "should open and close sports dropdown":

      • Simulates opening and closing the sports dropdown.

      • Assertions: Ensures that the dropdown content (e.g., "Football") is displayed when opened and hidden when closed.

    • Test 5: "should allow user to select and deselect sports preferences":

      • Simulates selecting and deselecting a sports preference checkbox (e.g., "Football").

      • Assertions: Ensures that the checkbox toggles between checked and unchecked states as expected.

    • Test 6: "should navigate to /home when form is submitted":

      • Simulates clicking the "Update" button to submit the form.

      • Assertions: Ensures that clicking the button triggers navigation to the /home route (via the mocked useNavigate function).

Backend Unit Tests for Sprint 3

  • cmd/api/events_test:

    • createEventHandler_test

      • Should allow creation of a valid event via the /events route and return 201 Created.
      • Should reject event creation with invalid/missing fields via the /events route and return 400 Bad Request.
      • Should reject unauthorized event creation via the /events route and return 401 Unauthorized.
    • getEventHandler_test

      • Should return event details successfully via the /events/{id} route and return 200 OK.
      • Should reject request with invalid event ID via the /events/{id} route and return 400 Bad Request.
      • Should reject unauthorized access to event via the /events/{id} route and return 401 Unauthorized.
    • updateEventHandler_test

      • Should allow valid updates to an event via the /events/{id} route and return 200 OK.
      • Should reject unauthorized update requests via the /events/{id} route and return 401 Unauthorized.
      • Should reject update attempts by non-owners via the /events/{id} route and return 403 Forbidden.
    • deleteEventHandler_test

      • Should allow event deletion by owner via the /events/{id} route and return 200 OK.
      • Should reject unauthorized delete requests via the /events/{id} route and return 401 Unauthorized.
      • Should reject delete attempts by non-owners via the /events/{id} route and return 403 Forbidden.
  • internal/store/events_test:

    • eventStore_Create_test

      • Should create a valid event in the database and return success.
      • Should return an error when creating an event with missing required fields.
    • eventStore_GetByID_test

      • Should retrieve an existing event by ID and return correct event details.
      • Should return ErrEventNotFound for a non-existent event ID.
    • eventStore_Delete_test

      • Should delete an existing event and confirm it no longer exists in the database.
      • Should return ErrEventNotFound when attempting to delete a non-existent event.
    • eventStore_Join_test

      • Should allow a valid user to join an existing event and update participant list.
      • Should return ErrAlreadyJoined if the same user attempts to join the event again.
      • Should return an error when attempting to join a non-existent event.
  • Also updated all existing tests to work with auth middleware

4. API Documentation & Backend Endpoints

All backend endpoints are documented using Swagger UI at:
http://localhost:8080/v1/swagger/index.html#/

Event APIs

POST /events

  • Description: Creates a new event.
  • Headers:
    Authorization: Bearer JWT_TOKEN_HERE
    Content-Type: application/json
    
  • Request Body:
    {
      "sport": "Football",
      "event_date": "2025-03-25T15:00:00Z",
      "max_players": 20,
      "location_name": "Central Park, NY",
      "latitude": 40.785091,
      "longitude": -73.968285,
      "description": "Need players for a friendly football match",
      "title": "Lets football!"
    }
  • Response (200 OK):
    {
      "id": 1,
      "event_owner": 1,
      "sport": "Football",
      "event_datetime": "2025-03-25T15:00:00Z",
      "max_players": 20,
      "location_name": "Central Park, NY",
      "latitude": 40.785091,
      "longitude": -73.968285,
      "description": "Friendly football match",
      "title": "Lets football!",
      "created_at": "2025-03-25T10:00:00Z",
      "updated_at": "2025-03-25T10:00:00Z",
      "is_full": false,
      "registered_count": 0
    }

GET /events

  • Description: Retrieves a list of events with optional filters.
  • Headers:
    Authorization: Bearer JWT_TOKEN_HERE
    Content-Type: application/json
    
  • Response (200 OK):
    [
      {
        "id": 1,
        "event_owner": 1,
        "sport": "Football",
        "event_datetime": "2025-03-25T15:00:00Z",
        "max_players": 20,
        "location_name": "Central Park, NY",
        "latitude": 40.785091,
        "longitude": -73.968285,
        "description": "Friendly football match",
        "title": "Lets football!",
        "created_at": "2025-03-25T10:00:00Z",
        "updated_at": "2025-03-25T10:00:00Z",
        "is_full": false,
        "registered_count": 2,
        "event_participants": [
          {
            "id": 2,
            "name": "John Doe",
            "email": "johndoe@gmail.com"
          },
          {
            "id": 3,
            "name": "John Does",
            "email": "johndoes@gmail.com"
          }
        ]
      }
    ]

GET /events/:id

  • Description: Retrieves details of a single event by ID.
  • Headers:
    Authorization: Bearer JWT_TOKEN_HERE
    
  • Response (200 OK): Same structure as above.

PUT /events/:id

  • Description: Updates the given fields of an event.
  • Headers:
    Authorization: Bearer JWT_TOKEN_HERE
    Content-Type: application/json
    
  • Request Body: Any subset of event fields.
  • Response (200 OK):
    {
      "message": "Event updated successfully."
    }

POST /events/:id/join

  • Description: User joins an event.
  • Headers:
    Authorization: Bearer JWT_TOKEN_HERE
    
  • Response (200 OK):
    {
      "message": "You have successfully joined the event!"
    }

DELETE /events/:id/leave

  • Description: User leaves an event.
  • Headers:
    Authorization: Bearer JWT_TOKEN_HERE
    
  • Response (200 OK):
    {
      "message": "You have successfully left the event!"
    }

DELETE /events/:id

  • Description: Deletes an event.
  • Headers:
    Authorization: Bearer JWT_TOKEN_HERE
    
  • Response (200 OK):
    {
      "message": "You have successfully deleted the event!"
    }

5. Github Repository Link

Here's our Github Repository for Sportify - Sportify Repo

6. Github Project

Here's our Github Project Board - Sportify Project Board

7. Docs

This document is also available in our Github Wiki Page

Along with this, we also added our design documentation (originally or Atlassian Confluence) onto our Github Repo