First off, thank you for considering contributing to TestPlanIt! It's people like you that make TestPlanIt such a great tool. We welcome contributions from everyone, regardless of their experience level.
- Code of Conduct
- Getting Started
- How Can I Contribute?
- Development Setup
- Development Workflow
- Style Guidelines
- Commit Guidelines
- Pull Request Process
- Release Process
- Community
- Recognition
This project and everyone participating in it is governed by our Code of Conduct. By participating, you are expected to uphold this code. Please report unacceptable behavior to conduct@testplanit.com.
Before we can accept your contributions, we need you to:
-
Sign the Contributor License Agreement (CLA): This allows us to distribute your contributions under our dual license model.
- Individual CLA: For individual contributors
- Corporate CLA: For contributions on behalf of your employer
- Sign at: https://testplanit.com/cla
-
Understand the Licensing: All contributions will be licensed under both AGPL-3.0 and our commercial license. By contributing, you agree to this dual licensing approach.
- Git knowledge and a GitHub account
- Basic understanding of test planning and management
- Familiarity with our tech stack (see Development Setup)
Before creating bug reports, please check existing issues to avoid duplicates. When creating a bug report, please include:
- Clear and descriptive title
- Steps to reproduce the issue
- Expected behavior vs actual behavior
- Screenshots if applicable
- System information (OS, browser, version)
- Error messages and logs
- Test case that demonstrates the bug
Submit bug reports as GitHub Issues.
Enhancement suggestions are tracked as GitHub Issues. When creating an enhancement suggestion, please include:
- Use case: What problem does this solve?
- Proposed solution: How should it work?
- Alternatives considered: What other solutions did you consider?
- Additional context: Mockups, examples, etc.
Submit enhancements as GitHub Issues.
Look for issues labeled:
good-first-issue- Simple fixes to get you familiar with the codebasehelp-wanted- Issues where we need community helpdocumentation- Documentation improvements
- Bug fixes: Fix reported issues
- Features: Implement new functionality
- Performance: Optimize existing code
- Documentation: Improve docs, add examples
- Tests: Add missing tests, improve coverage
- Translations: Help translate TestPlanIt
- Node.js 18+ and npm 9+
- Git 2.30+
- PostgreSQL 14+ (for backend development)
- Docker (optional, for containerized development)
-
Fork and clone the repository
git clone https://github.com/YOUR_USERNAME/testplanit.git cd testplanit -
Install dependencies
npm install
-
Set up environment
cp .env.example .env # Edit .env with your configuration -
Set up database
npm run db:setup npm run db:migrate npm run db:seed # Optional: add sample data -
Start development server
npm run dev
-
Run tests
npm test # Unit tests npm run test:e2e # End-to-end tests npm run test:all # All tests
docker-compose up -d
docker-compose exec app npm run dev-
Create a branch
git checkout -b feature/your-feature-name # or git checkout -b fix/issue-number-description -
Make your changes
- Write code following our style guidelines
- Add/update tests as needed
- Update documentation if required
-
Test your changes
npm test npm run lint npm run type-check -
Commit your changes (see Commit Guidelines)
-
Push to your fork
git push origin feature/your-feature-name
-
Create a Pull Request
We use automated tooling to maintain consistent code style:
- ESLint: JavaScript/TypeScript linting
- Prettier: Code formatting
- Stylelint: CSS/SCSS linting
Run all checks:
npm run lint
npm run format- Clear over clever: Write readable, maintainable code
- Test everything: Aim for >80% test coverage
- Document complex logic: Add comments for non-obvious code
- Follow SOLID principles: Keep code modular and maintainable
- Performance matters: Consider performance implications
src/
├── components/ # Reusable UI components
├── features/ # Feature-specific code
├── hooks/ # Custom React hooks
├── services/ # API and external services
├── utils/ # Utility functions
├── types/ # TypeScript type definitions
└── tests/ # Test files
Any modal that contains a form (create/edit/delete dialogs, wizards, etc.) must be conditionally mounted by its parent. The parent page owns the open state (and the row being edited/deleted, when applicable) and renders the trigger button inline; the modal file is a pure form component that takes { open, onClose } as props.
Add modal:
// parent page
const [addTagOpen, setAddTagOpen] = useState(false);
return (
<>
<Button onClick={() => setAddTagOpen(true)}>Add Tag</Button>
{addTagOpen && (
<AddTag open={addTagOpen} onClose={() => setAddTagOpen(false)} />
)}
</>
);Edit/Delete modal (row-driven):
// parent page
const [editingTag, setEditingTag] = useState<Tag | null>(null);
const [deletingTag, setDeletingTag] = useState<Tag | null>(null);
const columns = useMemo(
() => getColumns(tCommon, setEditingTag, setDeletingTag),
[tCommon]
);
return (
<>
<DataTable columns={columns} data={tags} />
{editingTag && (
<EditTag
tag={editingTag}
open={editingTag !== null}
onClose={() => setEditingTag(null)}
/>
)}
{deletingTag && (
<DeleteTag
tag={deletingTag}
open={deletingTag !== null}
onClose={() => setDeletingTag(null)}
/>
)}
</>
);The columns file accepts onEditX / onDeleteX callback props and wires them to plain Button onClick handlers — no <DialogTrigger> lives inside columns or modals.
The modal component must NOT:
- Hold its own
const [open, setOpen] = useState(false)for the dialog state - Include a
<DialogTrigger>,<AlertDialogTrigger>, or the trigger button itself - Rely on
useEffector imperativereset()calls to clear form state on close
Why this matters: If the modal holds its own open state, it stays mounted for the entire page lifetime, so useForm state and any local useState values persist across open/close cycles. This leaks form data — including sensitive fields like passwords, API keys, upload URLs, and editor content — into subsequent uses of the dialog. Conditional mounting makes React's unmount handle all cleanup automatically, so the bug is structurally impossible.
Reference implementations:
- Add:
app/[locale]/admin/tags/AddTag.tsx,app/[locale]/admin/groups/AddGroup.tsx,app/[locale]/admin/llm/AddLlmIntegration.tsx - Edit:
app/[locale]/admin/tags/EditTag.tsx,app/[locale]/admin/users/EditUser.tsx,app/[locale]/admin/llm/EditLlmIntegration.tsx - Delete:
app/[locale]/admin/tags/DeleteTag.tsx,app/[locale]/admin/users/DeleteUser.tsx,app/[locale]/admin/issues/DeleteIssue.tsx
An optional CI check is available via pnpm check:modal-pattern and reports any file matching the anti-pattern (useForm + local [open, setOpen] state + DialogTrigger). It is not part of pnpm lint — run it manually when refactoring modals.
We follow Conventional Commits:
<type>(<scope>): <subject>
<body>
<footer>
- feat: New feature
- fix: Bug fix
- docs: Documentation changes
- style: Code style changes (formatting, etc.)
- refactor: Code refactoring
- perf: Performance improvements
- test: Test additions or corrections
- build: Build system changes
- ci: CI configuration changes
- chore: Other changes (dependencies, etc.)
feat(auth): add OAuth2 integration with Google
Implements Google OAuth2 for user authentication.
Includes token refresh and profile synchronization.
Closes #123fix(tests): correct flaky test in plan creation
The test was failing intermittently due to timing issues.
Added proper wait conditions.
Fixes #456-
Before submitting:
- Ensure all tests pass
- Update documentation
- Add entry to CHANGELOG.md
- Squash commits if needed
- Rebase on latest main branch
-
PR Title Format: Follow commit message format
feat(component): add new feature -
PR Description Template:
## Description Brief description of changes ## Type of Change - [ ] Bug fix - [ ] New feature - [ ] Breaking change - [ ] Documentation update ## Testing - [ ] Unit tests pass - [ ] E2E tests pass - [ ] Manual testing completed ## Checklist - [ ] Code follows style guidelines - [ ] Self-review completed - [ ] Documentation updated - [ ] No new warnings - [ ] Tests added/updated - [ ] CLA signed ## Related Issues Closes #(issue number) ## Screenshots (if applicable)
-
Review Process:
- At least one maintainer review required
- All CI checks must pass
- No merge conflicts
- CLA must be signed
-
After Merge:
- Delete your feature branch
- Pull latest changes to your local main
- Celebrate your contribution! 🎉
We use semantic-release to fully automate releases. Version bumps are determined automatically based on commit messages.
- Push commits to main with conventional commit messages
- semantic-release runs automatically and:
- Analyzes commits since the last release
- Determines the version bump (patch/minor/major)
- Updates CHANGELOG.md and package.json
- Creates a git tag (e.g.,
v0.1.40) - Creates a GitHub Release
- Docker images are built automatically when the tag is pushed
| Commit Type | Version Bump | Example |
|---|---|---|
fix: |
Patch (0.1.34 → 0.1.35) | fix: resolve login timeout |
feat: |
Minor (0.1.34 → 0.2.0) | feat: add dark mode toggle |
feat!: or BREAKING CHANGE: |
Major (0.1.34 → 1.0.0) | feat!: redesign API |
Push to main → semantic-release analyzes commits → Tag + Release + Docker builds
No manual intervention required. Just use conventional commit messages and releases happen automatically.
- GitHub Discussions: General discussions and Q&A
- Discord: Real-time chat and support - Join here
- Twitter: Updates and announcements - @testplanit
- Documentation: https://docs.testplanit.com
- Support: support@testplanit.com
- Security Issues: security@testplanit.com (do not use public issues)
All contributors are recognized in our:
- CONTRIBUTORS.md file
- Release notes
- Annual contributor report
Active contributors may receive:
- TestPlanIt swag (t-shirts, stickers)
- Free commercial license for personal projects
- Invitation to contributor-only events
- Recognition in our Hall of Fame
Consistent, high-quality contributors may be invited to become maintainers with:
- Write access to the repository
- Decision-making input on project direction
- Access to maintainer resources and support
If you have questions about contributing, please:
- Check our FAQ
- Ask in GitHub Discussions
- Join our Discord
- Email us at opensource@testplanit.com
Thank you for contributing to TestPlanIt! Your efforts help make test planning better for everyone. 🚀
This guide is a living document. Suggestions for improvements are welcome!