I focus on testing behavior over implementation using:
My philosophy: test components as users interact with them — clicking, typing, and observing outputs — rather than internal state.
// Counter.test.tsx
import { render, screen, fireEvent } from "@testing-library/react";
import Counter from "./Counter";
test("increments count on click", () => {
render(<Counter />);
fireEvent.click(screen.getByText(/increment/i));
expect(screen.getByText(/count: 1/i)).toBeInTheDocument();
});
Button component’s click handler.Unit tests are faster and more focused; integration tests provide higher confidence for real-world flows.
I use MSW (Mock Service Worker) for realistic API mocking at the network level.
Example:
import { rest } from "msw";
import { setupServer } from "msw/node";
const server = setupServer(
rest.get("/api/user", (req, res, ctx) => res(ctx.json({ name: "Alice" })))
);
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
This keeps tests close to how the app behaves in production.
I isolate the API logic from the UI component and test both:
getUser()).This separation improves test reliability and clarity.
// cypress/e2e/form_spec.cy.js
describe("Contact Form", () => {
it("submits the form successfully", () => {
cy.visit("/contact");
cy.get('input[name="email"]').type("test@example.com");
cy.get('textarea[name="message"]').type("Hello!");
cy.intercept("POST", "/api/contact", { statusCode: 200 }).as("submitForm");
cy.get('button[type="submit"]').click();
cy.wait("@submitForm");
cy.contains("Thank you for contacting us").should("be.visible");
});
});
I simulate user behavior based on roles (e.g., admin vs. user):
admin/, user/ folders).I focus on testing value , not just numbers:
-coverage in Jest) to identify untested branches — then decide if they warrant a test.setState calls).Regular test reviews and manual QA help reinforce quality beyond the metrics.