Featured project 8 · TypeScript · E2E + API + Component
Cypress + TypeScript Framework
End-to-end, API and component tests with Cypress 16 and TypeScript for a React + Node task app kept in the repository: 81 Cypress tests, green in GitHub Actions on Chrome, Firefox and Edge.
Purpose
Shows what Cypress does best: tests that control the browser's network, clock and login, and component tests next to end-to-end tests. The app under test, TaskBoard, is part of the repository, so no public demo site can break a run, every test can reset the data, and the React components can be mounted on their own.
Technology stack
| Area | Tools |
|---|---|
| Test framework | Cypress 16.2 (e2e and component testing) |
| Language | TypeScript 6.0 |
| Contracts | zod 4 strict schemas |
| App under test | React 19 + Vite 8 web app, Node.js 24 API with no dependencies (and its own node:test tests) |
| Report | cypress-mochawesome-reporter: one HTML file per run with failure screenshots |
| Code quality and CI | ESLint (type-aware + Cypress rules), Prettier, GitHub Actions with cypress-io/github-action |
Architecture overview
cypress/e2e/api, e2e/ui, component what is checked
│
cypress/pages LoginPage, BoardPage (data-cy selectors, no assertions)
cypress/support commands: resetData, loginAs (cy.session), createTask
api.ts (typed cy.request client), schemas.ts (zod)
│
TaskBoard (app/) React UI + Node API; POST /api/test/reset before every testKey engineering decisions
- The app under test lives in the repository: a reset hook and seeded users make every test start from the same data
- Login through cy.session with a validate step; the login form itself is tested once
- Setup data is created through the API, the screen under test through page objects
- zod strictObject contracts: a leaked field fails with its name (checked by leaking a server field on purpose)
- cy.intercept for states the real server rarely produces, the real backend for user flows
- No fixed waits and no chaining after actions: both are lint errors
Implemented features
- 31 API tests: login and logout, token checks, tasks CRUD, filters, validation with boundary values, another user's task answers 404
- 33 UI tests: login, adding, completing, renaming and deleting tasks (confirm accepted and cancelled), filters, search
- Network: slow answers, server errors with Retry, network failure, fixture stub, expired login, request body and header checks
- Time: the Overdue badge before, on and after the due date, a 300 ms search debounce and a 3 s toast, with cy.clock
- 17 component tests: the form, the task row, the filter bar and the toast mounted alone, callbacks recorded with cy.stub()
- Framework design notes and 86 interview questions with answers linked to the code (Markdown + PDF)
Setup and execution
npm ci
npm test # build the app, start it, run all API + UI tests
npm run cy:component # component tests
npm run cy:open # interactive runner
npm run cy:demo # report demo: 1 pass, 2 fail, 1 skip on purposeSample test results


CI workflow
On every push, pull request and night: lint, Prettier, type checks and the app's own tests first; then the API tests, the UI tests on Chrome, Firefox and Edge, and the component tests as parallel jobs. Each job builds and starts its own copy of the app, writes a summary and keeps its HTML report as an artifact.
Known limitations and future improvements
Limitations
- Specs run one after another against one server; parallel specs would need a server or data set per worker
- Visual and accessibility checks are not included yet; WebKit is not covered
Next steps
- Accessibility checks with axe-core and visual comparison
- Publish the HTML report to GitHub Pages
