- Implemented popup.html for user interface with search functionality and request display. - Developed popup.js to manage search items, matched requests, and clipboard operations. - Created mergeConflictManager.js for automated git operations in specified repositories. - Added projects.txt to maintain a list of relevant projects. - Introduced pushReleaseBranches.js for managing release branches across multiple projects. - Developed releasePrepper.js to prepare projects for release with branch management. - Created stashUpdater.js to update git origins for projects. - Added updatedProjects.txt to track projects that have been updated.
8.0 KiB
8.0 KiB
applyTo
| applyTo |
|---|
| **/*.spec.js,**/*.test.js |
JavaScript Unit Test Instructions (Quick Reference)
Summary Table
| Area | Key Rules/Practices |
|---|---|
| Vue Components | Use mountCompositionAPIComponent, translations, a11y, group tests |
| Utilities | Table-driven, pure, stateless, edge/error cases |
| Stores | Mock APIs, test actions/mutations/getters |
| General | Arrange-Act-Assert, descriptive names, linting |
1. General Principles (Checklist)
- Test the public interface, not implementation details.
- Use Arrange-Act-Assert structure in each test.
- Use descriptive names for tests (start with 'should...').
- Mock or stub external dependencies; avoid testing third-party code directly.
- Always test edge and error conditions.
- Aim for high coverage, but prioritize meaningful tests over 100% coverage.
- Remove or refactor brittle tests tightly coupled to implementation.
- Use linting and formatting for test files.
- Document complex test logic with comments.
- Prefer pure functions and stateless modules for easier testing.
- Use path aliases from
moduleNameMapperfor all imports. - Use nested
describeblocks to group tests for subcomponents and related behaviors. - Use
beforeAll/beforeEachfor setup at appropriate scopes. - Add comments or TODOs for incomplete, brittle, or future test cases.
- After writing or updating tests, run them using the current filename to verify correctness:
- Use the command:
npm run test FILENAME(replaceFILENAMEwith the actual file, e.g.,npm run test MyComponent.spec.js).
- Use the command:
2. Forbidden Patterns (Checklist)
- Use of
mountorshallowMountdirectly (always usemountCompositionAPIComponent) - Hard-coded translations (always use
getTranslation) - Direct DOM manipulation
- Skipping edge/error cases
- Not testing accessibility for UI components
3. Vue Components
- Use Vue Test Utils and Jest or Vitest.
- Use
mountCompositionAPIComponentfrom@@/store-configfor mounting. - Use
getTranslationfor translation assertions. - Simulate user interactions and assert DOM/events. Prefer simulating user events (emit, click, etc.) over direct state mutation.
- Use
await/nextTickfor DOM updates after events. - Assert on both UI and state after interactions.
- Test accessibility: roles, labels, keyboard navigation (WCAG, AODA, semantic HTML). Require at least one explicit accessibility test per UI component.
- Use path aliases from
moduleNameMapperfor imports. - Always use
beforeAllto set up the component under test. - Declare a
let wrapper;variable in the outerdescribeblock so it is accessible in all tests. - Test with different props, slots, and edge-case data.
- Mock stores, router, and APIs as needed.
- Use snapshot testing for simple, stable components, but avoid over-reliance.
- Explicitly test i18n/translation for all user-facing text.
- Explicitly test common edge cases: empty data, missing/invalid props, error states, max/min selections.
- Always mock browser APIs (e.g., canvas, ResizeObserver) if the component or its children use them.
- Use or import realistic, reusable mock data files; update mock files as APIs evolve. Add TODOs if mock data is incomplete.
Example:
import { mountCompositionAPIComponent, getTranslation } from '@@/store-config';
import MyButton from '@/components/MyButton.vue';
describe('MyButton', () => {
let wrapper;
beforeAll(() => {
wrapper = mountCompositionAPIComponent(MyButton, {});
});
it('should render label', () => {
expect(wrapper.text()).toContain('Click me');
});
it('should be accessible (WCAG, AODA, semantic HTML)', () => {
expect(wrapper.attributes('role')).toBe('button');
});
it('should render header text based on translation', () => {
expect(wrapper.find('.header').text()).toBe(getTranslation('en', 'webComponents.marketResearch.marketSnapshot.marketMovers.subheader'));
});
// TODO: Add tests for error state when API changes
});
4. Utility Files (Helpers, Formatters, etc.)
- Test all input/output combinations, including edge and invalid cases.
- Use table-driven tests (arrays of input/output pairs) for concise coverage.
- Ensure utilities are stateless and have no side effects.
- Test error handling for invalid inputs.
- Prefer pure functions for easier testing and predictability.
Example:
import { formatDate } from '../formatDate';
describe('formatDate', () => {
it.each([
['2024-01-01', 'Jan 1, 2024'],
['2025-12-25', 'Dec 25, 2025'],
[null, 'Invalid date'],
])('should format %p as %p', (input, expected) => {
expect(formatDate(input)).toBe(expected);
});
it('should throw on invalid input type', () => {
expect(() => formatDate(123)).toThrow();
});
});
5. Stores (Pinia/Vuex)
- Test that actions and mutations update state as expected.
- Mock API calls and test loading, success, and error states for async actions.
- Test getters for various state scenarios.
- Isolate store state between tests using setup/teardown hooks.
- Test error handling for failed actions or invalid mutations.
Example:
import { setActivePinia, createPinia } from 'pinia';
import { useUserStore } from '../userStore';
describe('userStore', () => {
beforeEach(() => {
setActivePinia(createPinia());
});
it('should set user on login when username and password are provided', async () => {
const store = useUserStore();
await store.login({ username: 'test', password: 'pass' });
expect(store.user).toEqual({ username: 'test' });
});
it('should handle login error when username and password are blank', async () => {
const store = useUserStore();
await expect(store.login({ username: '', password: '' })).rejects.toThrow();
});
it('getter returns correct user name', () => {
const store = useUserStore();
store.user = { username: 'alice' };
expect(store.userName).toBe('alice');
});
});
6. Accessibility & Additional Best Practices
- Test accessibility for all UI components (WCAG, AODA, semantic HTML). Require at least one explicit accessibility test per UI component.
- Use semantic HTML elements and check for roles, labels, and keyboard navigation.
- Write code that is easily testable with unit tests.
- Avoid magic numbers; use named constants.
- Remove dead or unused code.
- Use ES module syntax for imports/exports.
- Document public APIs and exported functions with JSDoc or comments.
- Add comments/TODOs for incomplete, brittle, or complex test logic.
7. Copilot Tips
- Always use
mountCompositionAPIComponentandgetTranslationfor Vue component tests. - Always use path aliases from
moduleNameMapperfor imports. - Always test accessibility for UI components.
- Always test edge and error cases, including empty data, missing/invalid props, error states, and max/min selections.
- Always mock browser APIs (e.g., canvas, ResizeObserver) if the component or its children use them.
- Use or import realistic, reusable mock data files; update mock files as APIs evolve. Add TODOs if mock data is incomplete.
- Use nested
describeblocks to group tests for subcomponents and related behaviors. - Prefer simulating user interactions/events (emit, click) over direct state mutation. Use
await/nextTickfor DOM updates. - Assert on both UI and state after interactions.
- Add comments/TODOs for incomplete, brittle, or complex test logic.
- Never use forbidden patterns listed above.