qa-frontend-mean — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited qa-frontend-mean (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Write and run frontend tests for MEAN stack React applications. Cover component rendering tests, user interaction tests, hook tests, routing tests, form validation tests, and API integration tests using mocked service workers.
client/src/
├── __tests__/
│ ├── setup.js # Global test setup (MSW, custom matchers)
│ └── mocks/
│ ├── handlers.js # MSW request handlers
│ └── server.js # MSW server setup
├── components/
│ ├── common/
│ │ ├── Button.jsx
│ │ └── Button.test.jsx # Co-located test
│ └── features/
│ ├── LoginForm.jsx
│ └── LoginForm.test.jsx
├── pages/
│ ├── LoginPage.jsx
│ └── LoginPage.test.jsx
├── hooks/
│ ├── useAuth.js
│ └── useAuth.test.js
└── context/
├── AuthContext.jsx
└── AuthContext.test.jsx// components/common/Button.test.jsx
import { render, screen, fireEvent } from '@testing-library/react';
import Button from './Button';
describe('Button', () => {
it('renders children text', () => {
render(<Button>Click me</Button>);
expect(screen.getByRole('button', { name: /click me/i })).toBeInTheDocument();
});
it('calls onClick when clicked', () => {
const handleClick = jest.fn();
render(<Button onClick={handleClick}>Click</Button>);
fireEvent.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
it('shows spinner when loading', () => {
render(<Button loading>Submit</Button>);
expect(screen.getByRole('button')).toBeDisabled();
expect(screen.queryByText('Submit')).not.toBeInTheDocument();
});
it('applies variant class', () => {
render(<Button variant="danger">Delete</Button>);
expect(screen.getByRole('button')).toHaveClass('danger');
});
});// pages/DashboardPage.test.jsx
import { render, screen, waitFor } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { AuthProvider } from '../context/AuthContext';
import DashboardPage from './DashboardPage';
import { server } from '../__tests__/mocks/server';
import { rest } from 'msw';
const renderWithProviders = (component, { route = '/' } = {}) => {
return render(
<MemoryRouter initialEntries={[route]}>
<AuthProvider>{component}</AuthProvider>
</MemoryRouter>
);
};
describe('DashboardPage', () => {
it('shows loading spinner initially', () => {
renderWithProviders(<DashboardPage />);
expect(screen.getByRole('status')).toBeInTheDocument(); // spinner
});
it('displays dashboard data after loading', async () => {
renderWithProviders(<DashboardPage />);
await waitFor(() => {
expect(screen.getByText(/welcome/i)).toBeInTheDocument();
});
});
it('shows error message on API failure', async () => {
server.use(
rest.get('/api/dashboard/stats', (req, res, ctx) => {
return res(ctx.status(500), ctx.json({ success: false, error: { message: 'Server error' } }));
})
);
renderWithProviders(<DashboardPage />);
await waitFor(() => {
expect(screen.getByText(/something went wrong/i)).toBeInTheDocument();
});
});
});// components/features/LoginForm.test.jsx
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import LoginForm from './LoginForm';
describe('LoginForm', () => {
it('submits with valid credentials', async () => {
const onSubmit = jest.fn();
render(<LoginForm onSubmit={onSubmit} />);
await userEvent.type(screen.getByLabelText(/email/i), '[email protected]');
await userEvent.type(screen.getByLabelText(/password/i), 'Password123');
fireEvent.click(screen.getByRole('button', { name: /login/i }));
await waitFor(() => {
expect(onSubmit).toHaveBeenCalledWith({ email: '[email protected]', password: 'Password123' });
});
});
it('shows validation error for empty email', async () => {
render(<LoginForm onSubmit={jest.fn()} />);
fireEvent.click(screen.getByRole('button', { name: /login/i }));
await waitFor(() => {
expect(screen.getByText(/email is required/i)).toBeInTheDocument();
});
});
it('disables submit button while submitting', async () => {
const onSubmit = jest.fn(() => new Promise(resolve => setTimeout(resolve, 1000)));
render(<LoginForm onSubmit={onSubmit} />);
await userEvent.type(screen.getByLabelText(/email/i), '[email protected]');
await userEvent.type(screen.getByLabelText(/password/i), 'Password123');
fireEvent.click(screen.getByRole('button', { name: /login/i }));
expect(screen.getByRole('button', { name: /login/i })).toBeDisabled();
});
});// __tests__/mocks/handlers.js
import { rest } from 'msw';
export const handlers = [
rest.post('/api/auth/login', (req, res, ctx) => {
return res(ctx.json({
success: true,
data: { user: { id: '1', name: 'Test User', email: '[email protected]' }, token: 'fake-jwt-token' }
}));
}),
rest.get('/api/auth/me', (req, res, ctx) => {
return res(ctx.json({
success: true,
data: { id: '1', name: 'Test User', email: '[email protected]', role: 'user' }
}));
}),
rest.get('/api/dashboard/stats', (req, res, ctx) => {
return res(ctx.json({ success: true, data: { totalUsers: 100, totalPosts: 50 } }));
}),
];
// __tests__/mocks/server.js
import { setupServer } from 'msw/node';
import { handlers } from './handlers';
export const server = setupServer(...handlers);// hooks/useAuth.test.js
import { renderHook, act } from '@testing-library/react';
import { AuthProvider } from '../context/AuthContext';
import { useAuth } from './useAuth';
const wrapper = ({ children }) => <AuthProvider>{children}</AuthProvider>;
describe('useAuth', () => {
it('returns null user initially', () => {
const { result } = renderHook(() => useAuth(), { wrapper });
expect(result.current.user).toBeNull();
expect(result.current.isAuthenticated).toBe(false);
});
it('sets user after login', async () => {
const { result } = renderHook(() => useAuth(), { wrapper });
await act(async () => {
await result.current.login('[email protected]', 'Password123');
});
expect(result.current.user).toBeDefined();
expect(result.current.isAuthenticated).toBe(true);
});
it('clears user after logout', async () => {
const { result } = renderHook(() => useAuth(), { wrapper });
await act(async () => { await result.current.login('[email protected]', 'Password123'); });
act(() => { result.current.logout(); });
expect(result.current.user).toBeNull();
expect(result.current.isAuthenticated).toBe(false);
});
});Component.test.jsx next to Component.jsxuserEvent over fireEvent for user interactions (more realistic)renderWithProviders()references/. Changes to SKILL.md or scripts/ require user approval.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.