.cursor/docs/references/testing-reference.md
Unit Tests (Required)
.test.ts extensionEnd-to-End Tests (Required for user-facing changes)
app/client/cypress/e2e/Regression/Redux/React Safety Tests (For Redux/React code)
Unit Tests (Required)
Integration Tests (For complex features)
End-to-End Tests (For user-facing features)
Component.test.tsx)app/client/cypress/e2e/Regression/[Category]/[Feature]_spec.jsapp/server/src/test/java/com/appsmith/server/...import React from "react";
import { render, screen, fireEvent } from "@testing-library/react";
import MyComponent from "./MyComponent";
describe("MyComponent bug fix", () => {
it("should reproduce the bug scenario", () => {
// Arrange: Setup the conditions that trigger the bug
render(<MyComponent prop="value" />);
// Act: Perform the action that triggers the bug
fireEvent.click(screen.getByText("Button"));
// Assert: Verify the bug is fixed
expect(screen.getByText("Expected Result")).toBeInTheDocument();
});
it("should maintain existing functionality", () => {
// Test that related functionality still works
render(<MyComponent prop="otherValue" />);
expect(screen.getByText("Other Result")).toBeInTheDocument();
});
});
describe("Feature Bug Fix", { tags: ["@tag.Bugfix", "@tag.Regression"] }, function() {
before(() => {
cy.login();
cy.createTestWorkspace();
});
it("should no longer exhibit the bug", () => {
// Steps to reproduce the bug
cy.get("[data-cy=element]").click();
cy.get("[data-cy=other-element]").type("value");
// Verify the bug is fixed
cy.get("[data-cy=result]").should("have.text", "Expected Result");
});
});
import { configureStore } from '@reduxjs/toolkit';
import reducer, { selectUserData } from './userSlice';
import { renderHook } from '@testing-library/react-hooks';
import { Provider } from 'react-redux';
import React from 'react';
import { useSelector } from 'react-redux';
describe("Redux safety tests", () => {
// Test with missing nested properties
it("should handle missing nested properties safely", () => {
// Create store with incomplete state
const store = configureStore({
reducer: {
user: reducer
},
preloadedState: {
user: {
// Missing nested user data structure
}
}
});
// Test selector with missing data
const wrapper = ({ children }) => (
<Provider store={store}>{children}</Provider>
);
const { result } = renderHook(() => useSelector(selectUserData), { wrapper });
// Should not throw an error and return default/fallback value
expect(result.current).toEqual(/* expected default value */);
});
it("should handle deep property access safely", () => {
// Similar setup but with different state permutations
// Test various incomplete state structures
});
});
import { runSaga } from 'redux-saga';
import { mySaga } from './mySaga';
describe("mySaga", () => {
it("should dispatch expected actions", async () => {
// Mock dependencies
const dispatched = [];
const mockStore = {
dispatch: (action) => dispatched.push(action),
getState: () => ({ data: 'mock data' }),
};
// Run the saga
await runSaga(mockStore, mySaga, { payload: { id: '123' } }).toPromise();
// Assert expected actions were dispatched
expect(dispatched).toEqual([
{ type: 'SOME_ACTION', payload: 'mock data' },
]);
});
});
Test the User Experience
Use Descriptive Test Names
should [expected behavior] when [condition]Isolate Tests
Test Edge Cases
Keep Tests Fast
Test Coverage Guidelines
Redux/React Safety Testing
cd app/client
yarn test # Run all tests
yarn test:watch # Run in watch mode
yarn test:coverage # Generate coverage report
cd app/client
yarn cypress:open # Open Cypress UI
yarn cypress:run # Run headless
cd app/server
./mvnw test