Skip to main content

Featr API Testing Manual & Data Flow Guide

πŸš€ Quick Start Testing Setup

Prerequisites

# Start the backend server
make run
# or
go run .

# Server should be running on http://localhost:8080

Testing Tools

  • Postman Collection (recommended)
  • curl commands (provided below)
  • Thunder Client (VS Code extension)
  • Insomnia (alternative to Postman)

πŸ“Š MVP Data Flow Overview

User Registration β†’ Project Creation β†’ Feature Request Submission β†’ Community Voting β†’ Decision Making

Core MVP Flow:

  1. User signs up via OAuth (GitHub/Google)
  2. Project owner creates a project with settings
  3. Users discover public projects
  4. Users submit feature requests
  5. Community votes on requests
  6. Owner moderates and prioritizes
  7. Users track implementation progress

πŸ” Authentication Endpoints

1. Get Current User

GET /api/v1/auth/me
Headers:
Authorization: Bearer <JWT_TOKEN>
Test Command:
curl -X GET http://localhost:8080/api/v1/auth/me \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Expected Response (200):
{
    "success": true,
    "message": "User retrieved successfully",
    "data": {
        "id": "65f1a2b3c4d5e6f7a8b9c0d1",
        "email": "user@example.com",
        "username": "johnbuilder",
        "name": "John Builder",
        "avatar": "https://github.com/user.png",
        "subscription": {
            "tier": "free",
            "status": "active"
        },
        "created_at": "2024-01-15T10:30:00Z"
    }
}
Test Cases:
  • βœ… Valid JWT token returns user data
  • ❌ Invalid/expired token returns 401
  • ❌ No token returns 401

2. OAuth Callbacks (GitHub/Google)

GET /api/v1/auth/github/callback?code=abc123
GET /api/v1/auth/google/callback?code=def456
Note: These endpoints are typically called by OAuth providers, not manually tested. They should:
  1. Exchange code for access token
  2. Fetch user data from provider
  3. Create or update user in database
  4. Generate JWT token
  5. Redirect to frontend with token

πŸ—οΈ Project Management Endpoints

1. Get Public Projects

GET /api/v1/projects?limit=10&offset=0
Test Command:
curl -X GET "http://localhost:8080/api/v1/projects?limit=5&offset=0"
Expected Response (200):
{
    "success": true,
    "message": "Public projects retrieved successfully",
    "data": [
        {
            "id": "65f1a2b3c4d5e6f7a8b9c0d2",
            "name": "My Awesome App",
            "description": "A productivity app for indie builders",
            "slug": "my-awesome-app",
            "owner_id": "65f1a2b3c4d5e6f7a8b9c0d1",
            "settings": {
                "is_public": true,
                "allow_anonymous": false,
                "require_approval": true
            },
            "stats": {
                "total_requests": 15,
                "total_votes": 127,
                "total_comments": 43
            },
            "created_at": "2024-01-10T08:00:00Z"
        }
    ]
}

2. Create Project

POST /api/v1/projects
Headers:
Authorization: Bearer <JWT_TOKEN>
Content-Type: application/json
Request Body:
{
    "name": "Feature Tracker Pro",
    "description": "Advanced feature request management for SaaS products",
    "slug": "feature-tracker-pro"
}
Test Command:
curl -X POST http://localhost:8080/api/v1/projects \
  -H "Authorization: Bearer <JWT_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Test Project",
    "description": "A test project for API validation",
    "slug": "test-project"
  }'
Expected Response (201):
{
    "success": true,
    "message": "Project created successfully",
    "data": {
        "id": "65f1a2b3c4d5e6f7a8b9c0d3",
        "name": "Test Project",
        "description": "A test project for API validation",
        "slug": "test-project",
        "owner_id": "65f1a2b3c4d5e6f7a8b9c0d1",
        "settings": {
            "is_public": true,
            "allow_anonymous": false,
            "require_approval": true
        },
        "stats": {
            "total_requests": 0,
            "total_votes": 0,
            "total_comments": 0
        },
        "created_at": "2024-01-15T14:30:00Z"
    }
}
Test Cases:
  • βœ… Valid project data creates project
  • ❌ Duplicate slug returns 400
  • ❌ Missing required fields returns 400
  • ❌ No auth token returns 401

3. Get User’s Projects

GET /api/v1/projects/my
Headers:
Authorization: Bearer <JWT_TOKEN>
Test Command:
curl -X GET http://localhost:8080/api/v1/projects/my \
  -H "Authorization: Bearer <JWT_TOKEN>"

4. Get Specific Project

GET /api/v1/projects/:id
Test Command:
curl -X GET http://localhost:8080/api/v1/projects/65f1a2b3c4d5e6f7a8b9c0d3

5. Update Project

PUT /api/v1/projects/:id
Headers:
Authorization: Bearer <JWT_TOKEN>
Content-Type: application/json
Request Body:
{
    "name": "Updated Project Name",
    "description": "Updated description",
    "settings": {
        "is_public": false,
        "require_approval": false
    }
}
Test Cases:
  • βœ… Owner can update project
  • ❌ Non-owner cannot update (403)
  • ❌ Invalid project ID returns 404

6. Delete Project

DELETE /api/v1/projects/:id
Headers:
Authorization: Bearer <JWT_TOKEN>
Test Command:
curl -X DELETE http://localhost:8080/api/v1/projects/65f1a2b3c4d5e6f7a8b9c0d3 \
  -H "Authorization: Bearer <JWT_TOKEN>"

πŸ’‘ Feature Request Endpoints

1. Get Project Requests

GET /api/v1/projects/:id/requests?limit=20&offset=0&status=approved&sort=votes_count&order=desc
Query Parameters:
  • limit (optional): Number of requests to return (default: 20, max: 100)
  • offset (optional): Number of requests to skip (default: 0)
  • status (optional): Filter by status (pending, approved, rejected, completed)
  • category (optional): Filter by category
  • sort (optional): Sort field (created_at, votes_count, title)
  • order (optional): Sort order (asc, desc)
Test Command:
curl -X GET "http://localhost:8080/api/v1/projects/65f1a2b3c4d5e6f7a8b9c0d3/requests?limit=10&status=approved"
Expected Response (200):
{
    "success": true,
    "message": "Requests retrieved successfully",
    "data": {
        "requests": [
            {
                "id": "65f1a2b3c4d5e6f7a8b9c0d4",
                "project_id": "65f1a2b3c4d5e6f7a8b9c0d3",
                "author_id": "65f1a2b3c4d5e6f7a8b9c0d1",
                "title": "Add dark mode support",
                "description": "Users have been requesting dark mode to reduce eye strain during night usage.",
                "status": "approved",
                "category": "ui-ux",
                "tags": ["dark-mode", "accessibility"],
                "priority": "medium",
                "votes_count": 23,
                "comments_count": 7,
                "created_at": "2024-01-12T16:45:00Z",
                "updated_at": "2024-01-13T09:30:00Z"
            }
        ],
        "total": 1,
        "limit": 10,
        "offset": 0
    }
}

2. Create Feature Request

POST /api/v1/projects/:id/requests
Headers:
Authorization: Bearer <JWT_TOKEN>
Content-Type: application/json
Request Body:
{
    "title": "Add export to PDF functionality",
    "description": "Users need the ability to export their data as PDF reports for sharing with stakeholders.",
    "category": "export",
    "tags": ["pdf", "export", "reports"],
    "priority": "high"
}
Test Command:
curl -X POST http://localhost:8080/api/v1/projects/65f1a2b3c4d5e6f7a8b9c0d3/requests \
  -H "Authorization: Bearer <JWT_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Mobile app support",
    "description": "Native mobile apps for iOS and Android to improve user accessibility",
    "category": "mobile",
    "tags": ["mobile", "ios", "android"],
    "priority": "high"
  }'
Expected Response (201):
{
    "success": true,
    "message": "Feature request created successfully",
    "data": {
        "id": "65f1a2b3c4d5e6f7a8b9c0d5",
        "project_id": "65f1a2b3c4d5e6f7a8b9c0d3",
        "author_id": "65f1a2b3c4d5e6f7a8b9c0d1",
        "title": "Mobile app support",
        "description": "Native mobile apps for iOS and Android to improve user accessibility",
        "status": "pending",
        "category": "mobile",
        "tags": ["mobile", "ios", "android"],
        "priority": "high",
        "votes_count": 0,
        "comments_count": 0,
        "created_at": "2024-01-15T15:00:00Z",
        "updated_at": "2024-01-15T15:00:00Z"
    }
}
Test Cases:
  • βœ… Valid request data creates request
  • βœ… Status set to β€œpending” if project requires approval
  • βœ… Status set to β€œapproved” if auto-approval enabled
  • ❌ Missing title/description returns 400
  • ❌ Invalid project ID returns 404
  • ❌ No auth token returns 401

3. Get Specific Request

GET /api/v1/requests/:id
Test Command:
curl -X GET http://localhost:8080/api/v1/requests/65f1a2b3c4d5e6f7a8b9c0d5

4. Update Request

PUT /api/v1/requests/:id
Headers:
Authorization: Bearer <JWT_TOKEN>
Content-Type: application/json
Request Body:
{
    "title": "Updated: Mobile app support with offline mode",
    "description": "Native mobile apps for iOS and Android with offline synchronization capabilities",
    "category": "mobile",
    "tags": ["mobile", "ios", "android", "offline"],
    "priority": "critical"
}
Test Cases:
  • βœ… Request author can update request
  • βœ… Project owner/moderator can update request
  • ❌ Other users cannot update (403)

5. Delete Request

DELETE /api/v1/requests/:id
Headers:
Authorization: Bearer <JWT_TOKEN>
Test Cases:
  • βœ… Request author can delete request
  • βœ… Project owner/moderator can delete request
  • ❌ Other users cannot delete (403)

πŸ—³οΈ Voting System Endpoints

1. Vote on Request

POST /api/v1/requests/:id/vote
Headers:
Authorization: Bearer <JWT_TOKEN>
Content-Type: application/json
Request Body:
{
    "type": "upvote"
}
Valid Vote Types:
  • upvote - Positive vote
  • downvote - Negative vote
Test Command:
curl -X POST http://localhost:8080/api/v1/requests/65f1a2b3c4d5e6f7a8b9c0d5/vote \
  -H "Authorization: Bearer <JWT_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"type": "upvote"}'
Expected Response (200):
{
    "success": true,
    "message": "Vote recorded successfully",
    "data": {
        "total_votes": 1,
        "up_votes": 1,
        "down_votes": 0,
        "user_vote": "upvote",
        "user_vote_id": "65f1a2b3c4d5e6f7a8b9c0d6"
    }
}
Test Cases:
  • βœ… First vote creates new vote record
  • βœ… Changing vote type updates existing vote
  • ❌ Same vote type returns β€œalready voted” error
  • ❌ Voting on non-approved request returns error
  • ❌ No auth token returns 401

2. Remove Vote

DELETE /api/v1/requests/:id/vote
Headers:
Authorization: Bearer <JWT_TOKEN>
Test Command:
curl -X DELETE http://localhost:8080/api/v1/requests/65f1a2b3c4d5e6f7a8b9c0d5/vote \
  -H "Authorization: Bearer <JWT_TOKEN>"
Expected Response (200):
{
    "success": true,
    "message": "Vote removed successfully",
    "data": {
        "total_votes": 0,
        "up_votes": 0,
        "down_votes": 0,
        "user_vote": "",
        "user_vote_id": ""
    }
}

3. Get Request Vote Information

GET /api/v1/requests/:id/votes
Headers (Optional):
Authorization: Bearer <JWT_TOKEN>
Test Command:
curl -X GET http://localhost:8080/api/v1/requests/65f1a2b3c4d5e6f7a8b9c0d5/votes \
  -H "Authorization: Bearer <JWT_TOKEN>"
Expected Response (200):
{
    "success": true,
    "message": "Vote information retrieved successfully",
    "data": {
        "total_votes": 15,
        "up_votes": 12,
        "down_votes": 3,
        "user_vote": "upvote",
        "user_vote_id": "65f1a2b3c4d5e6f7a8b9c0d6"
    }
}
Note: If no auth token provided, user_vote and user_vote_id will be empty.

πŸ§ͺ Complete MVP Testing Flow

1. User Authentication Flow

# Step 1: Simulate OAuth callback (manual process)
# In real app, user clicks "Login with GitHub" and gets redirected

# Step 2: Verify authentication
curl -X GET http://localhost:8080/api/v1/auth/me \
  -H "Authorization: Bearer <JWT_TOKEN>"

2. Project Management Flow

# Step 1: Create a project
curl -X POST http://localhost:8080/api/v1/projects \
  -H "Authorization: Bearer <JWT_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "MVP Test Project",
    "description": "Testing the complete flow",
    "slug": "mvp-test"
  }'

# Step 2: Get project details
PROJECT_ID="<returned_project_id>"
curl -X GET http://localhost:8080/api/v1/projects/$PROJECT_ID

# Step 3: List user's projects
curl -X GET http://localhost:8080/api/v1/projects/my \
  -H "Authorization: Bearer <JWT_TOKEN>"

3. Feature Request Flow

# Step 1: Create a feature request
curl -X POST http://localhost:8080/api/v1/projects/$PROJECT_ID/requests \
  -H "Authorization: Bearer <JWT_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Add user notifications",
    "description": "Email notifications when requests are approved or rejected",
    "category": "notifications",
    "priority": "medium"
  }'

# Step 2: Get project requests
curl -X GET http://localhost:8080/api/v1/projects/$PROJECT_ID/requests

# Step 3: Get specific request
REQUEST_ID="<returned_request_id>"
curl -X GET http://localhost:8080/api/v1/requests/$REQUEST_ID

4. Voting Flow

# Step 1: Vote on request
curl -X POST http://localhost:8080/api/v1/requests/$REQUEST_ID/vote \
  -H "Authorization: Bearer <JWT_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"type": "upvote"}'

# Step 2: Check vote counts
curl -X GET http://localhost:8080/api/v1/requests/$REQUEST_ID/votes \
  -H "Authorization: Bearer <JWT_TOKEN>"

# Step 3: Remove vote
curl -X DELETE http://localhost:8080/api/v1/requests/$REQUEST_ID/vote \
  -H "Authorization: Bearer <JWT_TOKEN>"

πŸ” Error Responses & Status Codes

Common Error Responses

400 Bad Request:
{
    "success": false,
    "message": "Invalid request data",
    "error": "Missing required field: title"
}
401 Unauthorized:
{
    "success": false,
    "message": "User not authenticated",
    "error": "Invalid or expired token"
}
403 Forbidden:
{
    "success": false,
    "message": "Unauthorized to perform this action",
    "error": "Only project owner can update settings"
}
404 Not Found:
{
    "success": false,
    "message": "Resource not found",
    "error": "Project with ID 123 not found"
}
429 Too Many Requests:
{
    "success": false,
    "message": "Rate limit exceeded",
    "error": "Too many requests from this IP"
}

πŸ“ Testing Checklist

Authentication

  • Valid JWT returns user data
  • Invalid JWT returns 401
  • Missing JWT returns 401
  • OAuth callbacks work correctly

Projects

  • Public projects list loads
  • Authenticated user can create project
  • User can view their own projects
  • Owner can update project settings
  • Owner can delete project
  • Non-owner cannot modify project

Feature Requests

  • Requests load for public projects
  • Authenticated user can submit request
  • Request status set correctly based on project settings
  • Author can update own request
  • Project owner can update any request
  • Author/owner can delete request

Voting

  • User can vote on approved requests
  • Vote counts update correctly
  • User cannot vote twice with same type
  • User can change vote type
  • User can remove vote
  • Vote information loads correctly
  • Anonymous users see vote counts without user vote status

Edge Cases

  • Invalid MongoDB ObjectIDs return 400
  • Non-existent resources return 404
  • Rate limiting works correctly
  • Large request bodies are handled
  • Special characters in text fields work
  • Pagination works correctly

πŸ› οΈ Postman Collection Setup

Create a Postman collection with these environment variables:
{
    "name": "Featr API Testing",
    "values": [
        {
            "key": "base_url",
            "value": "http://localhost:8080",
            "enabled": true
        },
        {
            "key": "jwt_token",
            "value": "{{JWT_TOKEN_HERE}}",
            "enabled": true
        },
        {
            "key": "project_id",
            "value": "",
            "enabled": true
        },
        {
            "key": "request_id",
            "value": "",
            "enabled": true
        }
    ]
}
Import the endpoints using the base_url variable and set up automatic token refresh for seamless testing. This manual provides comprehensive testing coverage for your MVP while ensuring all critical paths work correctly before frontend integration.