- Notifications
You must be signed in to change notification settings - Fork 0
Contributing
Welcome to QA Test Manager! We're excited that you want to contribute to making manual testing more efficient and enjoyable.
- Bug fixes: Help resolve reported issues
- Feature development: Add new functionality
- Performance improvements: Optimize existing code
- Test coverage: Add or improve tests
- Documentation: Improve code documentation
- Bug reports: Identify and report issues
- Feature requests: Suggest new features
- Documentation: Improve user guides and wiki
- Design feedback: UI/UX suggestions
- Community support: Help other users
- Internationalization: Help translate the interface
- Localization: Adapt for different regions
Before contributing, ensure you have:
- Node.js 18+ installed
- Git configured with your GitHub account
- GitHub account for pull requests
- Code editor (VS Code recommended)
-
Fork the repository
# Click "Fork" on GitHub, then clone your fork git clone https://github.com/YOUR-USERNAME/qa-demo-1.git cd qa-demo-1
-
Add upstream remote
git remote add upstream https://github.com/synjan/qa-demo-1.git git remote -v
-
Install dependencies
npm install
-
Set up environment
cp .env.example .env.local # Edit .env.local with your values -
Start development server
npm run dev
-
Verify setup
- Open http://localhost:3000
- Check that authentication works
- Create a test case to verify functionality
-
Sync with upstream
git checkout main git pull upstream main git push origin main
-
Create feature branch
git checkout -b feature/amazing-new-feature # or git checkout -b fix/bug-description
- Follow coding standards (see below)
- Write tests for new functionality
- Update documentation as needed
- Test thoroughly before submitting
We use conventional commits for clear history:
# Feature git commit -m "feat: add batch test execution with progress tracking" # Bug fix git commit -m "fix: resolve test case loading issue with special characters" # Documentation git commit -m "docs: update API reference with new endpoints" # Refactor git commit -m "refactor: simplify test result storage logic" # Tests git commit -m "test: add unit tests for file utilities"-
feat: New features -
fix: Bug fixes -
docs: Documentation changes -
style: Code formatting (no logic changes) -
refactor: Code restructuring (no feature changes) -
test: Adding or updating tests -
chore: Build process or auxiliary tool changes
-
Push your branch
git push origin feature/amazing-new-feature
-
Create pull request
- Go to GitHub and click "New Pull Request"
- Use clear, descriptive title
- Fill out the PR template completely
- Link to related issues
-
PR Template (auto-populated):
## Summary Brief description of changes ## Type of Change - [ ] Bug fix - [ ] New feature - [ ] Breaking change - [ ] Documentation update ## Testing - [ ] Tests pass locally - [ ] New tests added (if applicable) - [ ] Manual testing completed ## Screenshots (if applicable) ## Checklist - [ ] Code follows project style guidelines - [ ] Self-review completed - [ ] Documentation updated - [ ] No breaking changes (or clearly documented)
// Use explicit types for function parameters and returns function createTestCase(data: TestCaseInput): Promise<TestCase> { // Implementation } // Use interfaces for object types interface TestCaseInput { title: string; description: string; priority: Priority; steps: TestStep[]; } // Use type unions for specific values type Priority = 'critical' | 'high' | 'medium' | 'low'; // Use optional properties with ? interface TestCaseOptions { tags?: string[]; githubIssue?: string; }// Use functional components with TypeScript interface TestCaseCardProps { testCase: TestCase; onEdit: (id: string) => void; onRun: (id: string) => void; } export function TestCaseCard({ testCase, onEdit, onRun }: TestCaseCardProps) { return ( <Card> <CardHeader> <CardTitle>{testCase.title}</CardTitle> </CardHeader> <CardContent> {/* Content */} </CardContent> </Card> ); } // Use proper prop destructuring // Use semantic HTML elements // Follow accessibility guidelinessrc/ βββ app/ # Next.js app router pages β βββ (auth)/ # Route groups β βββ api/ # API routes β βββ testcases/ # Test case pages β β βββ page.tsx # List page β β βββ new/ # New test case β β βββ [id]/ # Dynamic routes β βββ globals.css # Global styles βββ components/ # Reusable components β βββ ui/ # Base UI components (shadcn/ui) β βββ layout/ # Layout components β βββ forms/ # Form components β βββ specialized/ # Domain-specific components βββ lib/ # Utilities and shared logic β βββ types.ts # Type definitions β βββ utils.ts # General utilities β βββ file-utils.ts # File operations β βββ api-client.ts # API client βββ hooks/ # Custom React hooks // Files: kebab-case test-case-form.tsx file-utils.ts api-client.ts // Components: PascalCase TestCaseForm BatchRunner NavigationHeader // Functions: camelCase createTestCase executeTestStep generateReport // Constants: UPPER_SNAKE_CASE const MAX_TEST_CASES = 1000; const DEFAULT_PRIORITY = 'medium'; // Types/Interfaces: PascalCase interface TestCase { } type ExecutionStatus = 'pass' | 'fail';/* Use Tailwind CSS classes primarily */ <div className="flex items-center justify-between p-4 bg-card border rounded-lg"> /* Use semantic color variables */ <div className="text-foreground bg-background border-border"> /* Use responsive design */ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> /* Custom CSS only when necessary */ .custom-scroll { scrollbar-width: thin; scrollbar-color: hsl(var(--muted)) transparent; }# Run all tests npm test # Run tests in watch mode npm test -- --watch # Run tests with coverage npm test -- --coverage # Run specific test file npm test test-case-utils.test.ts// Unit test example import { parseTestSteps } from '@/lib/file-utils'; describe('parseTestSteps', () => { it('should parse markdown test steps correctly', () => { const markdown = ` ## Test Steps 1. **Action**: Click login button **Expected Result**: Login form appears `; const steps = parseTestSteps(markdown); expect(steps).toHaveLength(1); expect(steps[0].action).toBe('Click login button'); expect(steps[0].expectedResult).toBe('Login form appears'); }); it('should handle empty markdown', () => { const steps = parseTestSteps(''); expect(steps).toHaveLength(0); }); }); // Component test example import { render, screen, fireEvent } from '@testing-library/react'; import { TestCaseCard } from '@/components/test-case-card'; describe('TestCaseCard', () => { const mockTestCase = { id: 'tc-001', title: 'Test Login', description: 'Test user login functionality', priority: 'high' as const, steps: [] }; it('should render test case information', () => { render( <TestCaseCard testCase={mockTestCase} onEdit={() => {}} onRun={() => {}} /> ); expect(screen.getByText('Test Login')).toBeInTheDocument(); expect(screen.getByText('Test user login functionality')).toBeInTheDocument(); }); it('should call onRun when run button is clicked', () => { const onRun = jest.fn(); render( <TestCaseCard testCase={mockTestCase} onEdit={() => {}} onRun={onRun} /> ); fireEvent.click(screen.getByText('Run')); expect(onRun).toHaveBeenCalledWith('tc-001'); }); });- Unit Tests: Test individual functions and utilities
- Component Tests: Test React components in isolation
- Integration Tests: Test component interactions
- API Tests: Test API endpoints
- E2E Tests: Test complete user workflows (future)
/** * Creates a new test case and saves it to the file system * * @param testCaseData - The test case data to create * @returns Promise that resolves to the created test case with generated ID * * @example * ```typescript * const testCase = await createTestCase({ * title: 'Login Test', * description: 'Test user login functionality', * priority: 'high', * steps: [ * { action: 'Enter credentials', expectedResult: 'User logged in' } * ] * }); * ``` */ export async function createTestCase(testCaseData: TestCaseInput): Promise<TestCase> { // Implementation }/** * TestCaseCard displays a test case with actions for editing and running * * @component * @example * ```tsx * <TestCaseCard * testCase={testCase} * onEdit={(id) => router.push(`/testcases/${id}/edit`)} * onRun={(id) => router.push(`/testcases/${id}/run`)} * /> * ``` */ interface TestCaseCardProps { /** The test case to display */ testCase: TestCase; /** Callback when edit button is clicked */ onEdit: (id: string) => void; /** Callback when run button is clicked */ onRun: (id: string) => void; }When adding features, update relevant documentation:
- Main README.md
- API documentation
- User guide
- This contributing guide
- Clear title: Summarize the issue
- Environment: OS, Node.js version, browser
- Steps to reproduce: Numbered list
- Expected behavior: What should happen
- Actual behavior: What actually happens
- Screenshots: For visual issues
- Console logs: Any error messages
- Additional context: Anything else relevant
**Bug Description** A clear description of what the bug is. **To Reproduce** 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error **Expected Behavior** A clear description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. **Environment:** - OS: [e.g. macOS, Windows, Ubuntu] - Browser [e.g. chrome, safari] - Node.js version [e.g. 18.17.0] - App version [e.g. 0.1.0] **Additional Context** Add any other context about the problem here.- Problem statement: What problem does this solve?
- Proposed solution: How should it work?
- Alternatives: Other ways to solve the problem
- Use cases: Who would use this feature?
- Priority: How important is this feature?
**Is your feature request related to a problem?** A clear description of what the problem is. Ex. I'm always frustrated when [...] **Describe the solution you'd like** A clear description of what you want to happen. **Describe alternatives you've considered** A clear description of any alternative solutions or features you've considered. **Use Cases** Describe who would use this feature and how. **Additional Context** Add any other context or screenshots about the feature request here.// Use React state for local component state const [isLoading, setIsLoading] = useState(false); // Use custom hooks for shared logic function useTestCases() { const [testCases, setTestCases] = useState<TestCase[]>([]); const loadTestCases = useCallback(async () => { // Implementation }, []); return { testCases, loadTestCases }; } // Use Context for global state (sparingly) const ThemeContext = createContext<ThemeContextValue>();// RESTful API design GET /api/testcases # List test cases POST /api/testcases # Create test case GET /api/testcases/:id # Get test case PUT /api/testcases/:id # Update test case DELETE /api/testcases/:id # Delete test case // Consistent response format interface ApiResponse<T> { success: boolean; data?: T; error?: { code: string; message: string; }; }// Client-side error handling try { const response = await fetch('/api/testcases'); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const data = await response.json(); return data; } catch (error) { console.error('Failed to fetch test cases:', error); throw error; } // Server-side error handling export async function GET(request: Request) { try { const testCases = await loadTestCases(); return NextResponse.json(testCases); } catch (error) { console.error('Error loading test cases:', error); return NextResponse.json( { error: 'Failed to load test cases' }, { status: 500 } ); } }- Self-review your code before submitting
- Test thoroughly on different browsers/devices
- Update documentation for any changes
- Respond promptly to review feedback
- Make requested changes in new commits
- Code follows project conventions
- Tests are included and passing
- Documentation is updated
- No breaking changes (or properly documented)
- Performance considerations addressed
- Accessibility guidelines followed
- Security implications considered
- Request review from maintainers
- Be patient - reviews take time
- Address feedback constructively
- Ask questions if feedback is unclear
- Learn from feedback for future contributions
- Bug fixes: Resolve existing issues
- Test coverage: Improve automated testing
- Performance: Optimize slow operations
- Accessibility: Ensure WCAG compliance
- New features: Add requested functionality
- Documentation: Improve user guides
- Developer experience: Better dev tools
- Internationalization: Multi-language support
- Database support: PostgreSQL, MySQL integration
- Real-time features: WebSocket support
- Mobile app: React Native version
- Enterprise features: SSO, advanced permissions
All contributors are recognized:
- Contributors file: Listed in CONTRIBUTORS.md
- Release notes: Mentioned in release announcements
- GitHub insights: Visible in repository statistics
- Community: Recognized in discussions
Regular contributors may be invited to become maintainers:
- Code quality: Consistent high-quality contributions
- Community involvement: Helping other contributors
- Expertise: Deep understanding of the codebase
- Reliability: Sustained involvement over time
- GitHub Discussions: Ask questions about contributing
- Discord/Slack: Real-time chat with maintainers (future)
- Email: Contact maintainers directly
- Pair programming: Schedule sessions with maintainers
- Be respectful: Treat everyone with respect
- Be constructive: Provide helpful feedback
- Be patient: Allow time for responses
- Be clear: Communicate clearly and concisely
Thank you for contributing to QA Test Manager! Your efforts help make manual testing better for everyone. π
Happy coding! π
π Main Repository | π Latest Release | π€ Contributing
QA Test Manager - Making manual testing efficient and enjoyable! π