Skip to content

Commit 428e133

Browse files
pigchipaguzmancruzCopilot
authored
Fix/add unit testing coverage (#4032)
* chore: add test utilities and coverage infrastructure - Update jest.config.js with coverage collection exclusions - Add test-utils.tsx with renderWithProviders and createMockStore helpers - Add @testing-library/jest-dom and @testing-library/react dev dependencies Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test: add unit tests across all modules (1,900 tests, 95% coverage) - 197 test suites covering utilities, Redux slices, async thunks, middleware, React components, hooks, caches, and service modules - Line coverage: 95.07% (5816/6117) - Statement coverage: 95.03% (6063/6380) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: resolve TypeScript build errors and test failures in spec files - Fix TS2344 in permissions-action-creator.util.spec.ts: cast InstanceType<typeof RevokePermissionsUtil> to unknown as RevokePermissionsUtil - Fix TS2345/TS2739/TS2571/TS2322/TS2352/TS2556/TS2769 across spec files: cast sampleBody/payload as unknown as IQuery, add missing IPermissionGrant fields (clientId/resourceId), fix status literal types, cast result.payload as any, add missing PopupsComponent props, fix Provider overload - Fix Auth test infinite useEffect loop: moved state object outside mockImplementation so authToken reference is stable across re-renders - Fix 13 ESLint errors introduced by fixes: wrap long lines in permission-grants.slice.spec.ts and fix double-quotes + max-len in ShareQuery.spec.tsx - Add @babel/plugin-proposal-private-property-in-object to devDependencies (suppress babel-preset-react-app warning) - Centralize ResizeObserver mock in setupTests.ts - Fix all 204 ESLint max-len/no-empty/quotes violations across ~60 spec files Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * revert --------- Co-authored-by: aguzmancruz <aguzmancruz@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent a2f49ba commit 428e133

168 files changed

Lines changed: 23818 additions & 206 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.eslintignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ build
22
eslintrc.js
33
public
44
scripts
5+
coverage
6+
coverage/**

jest.config.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ module.exports = {
99
'!src/**/*.d.ts',
1010
'!src/index.tsx',
1111
'!src/app/middleware/telemetryMiddleware.ts',
12-
'!src/telemetry/telemetry.ts'
12+
'!src/telemetry/telemetry.ts',
13+
'!src/tests/**',
14+
'!src/**/*.spec.{ts,tsx}',
15+
'!src/**/*.test.{ts,tsx}'
1316
],
1417
resolver: `${__dirname}/src/tests/common/resolver.js`,
1518
setupFiles: ['react-app-polyfill/jsdom'],

package-lock.json

Lines changed: 574 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@
9292
"@axe-core/playwright": "4.10.1",
9393
"@eslint/js": "9.23.0",
9494
"@playwright/test": "1.51.1",
95+
"@testing-library/jest-dom": "^6.9.1",
96+
"@testing-library/react": "^16.3.2",
9597
"@types/chromedriver": "81.0.1",
9698
"@types/isomorphic-fetch": "0.0.39",
9799
"@types/jest": "29.5.14",
@@ -119,6 +121,7 @@
119121
"jest-sonar-reporter": "2.0.0",
120122
"jest-watch-typeahead": "2.2.2",
121123
"markdown-it": "14.1.0",
124+
"monocart-reporter": "^2.10.0",
122125
"node-notifier": "10.0.1",
123126
"react-dev-utils": "12.0.1",
124127
"redux-logger": "3.0.6",
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import {
2+
DirectReports, Files, FullPersonCard, Groups,
3+
InsightsTrending, Messages, Profile, Site, Sites, User, Users
4+
} from './index';
5+
6+
describe('adaptivecards-templates', () => {
7+
it('exports DirectReports template', () => {
8+
expect(DirectReports).toBeDefined();
9+
expect(typeof DirectReports).toBe('object');
10+
});
11+
12+
it('exports Files template', () => {
13+
expect(Files).toBeDefined();
14+
});
15+
16+
it('exports FullPersonCard template', () => {
17+
expect(FullPersonCard).toBeDefined();
18+
});
19+
20+
it('exports Groups template', () => {
21+
expect(Groups).toBeDefined();
22+
});
23+
24+
it('exports InsightsTrending template', () => {
25+
expect(InsightsTrending).toBeDefined();
26+
});
27+
28+
it('exports Messages template', () => {
29+
expect(Messages).toBeDefined();
30+
});
31+
32+
it('exports Profile template', () => {
33+
expect(Profile).toBeDefined();
34+
});
35+
36+
it('exports Site template', () => {
37+
expect(Site).toBeDefined();
38+
});
39+
40+
it('exports Sites template', () => {
41+
expect(Sites).toBeDefined();
42+
});
43+
44+
it('exports User template', () => {
45+
expect(User).toBeDefined();
46+
});
47+
48+
it('exports Users template', () => {
49+
expect(Users).toBeDefined();
50+
});
51+
});
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import localStorageMiddleware from './localStorageMiddleware';
2+
3+
jest.mock('../../modules/cache/collections.cache', () => ({
4+
collectionsCache: {
5+
read: jest.fn(),
6+
update: jest.fn(),
7+
create: jest.fn()
8+
}
9+
}));
10+
11+
jest.mock('../../modules/cache/samples.cache', () => ({
12+
samplesCache: {
13+
saveSamples: jest.fn()
14+
}
15+
}));
16+
17+
jest.mock('../utils/local-storage', () => ({
18+
saveToLocalStorage: jest.fn()
19+
}));
20+
21+
jest.mock('../services/reducers/collections-reducer.util', () => ({
22+
getUniquePaths: jest.fn((existing: any[], newPaths: any[]) => [...existing, ...newPaths])
23+
}));
24+
25+
import { collectionsCache } from '../../modules/cache/collections.cache';
26+
import { samplesCache } from '../../modules/cache/samples.cache';
27+
import { saveToLocalStorage } from '../utils/local-storage';
28+
import {
29+
CHANGE_THEME_SUCCESS, SAMPLES_FETCH_SUCCESS,
30+
RESOURCEPATHS_ADD_SUCCESS, RESOURCEPATHS_DELETE_SUCCESS,
31+
COLLECTION_CREATE_SUCCESS
32+
} from '../services/redux-constants';
33+
34+
describe('localStorageMiddleware', () => {
35+
const next = jest.fn((action) => action);
36+
const store = {} as any;
37+
const middleware = localStorageMiddleware(store)(next);
38+
39+
beforeEach(() => {
40+
jest.clearAllMocks();
41+
});
42+
43+
it('should save theme to localStorage on CHANGE_THEME_SUCCESS', async () => {
44+
await middleware({ type: CHANGE_THEME_SUCCESS, payload: 'dark' });
45+
expect(saveToLocalStorage).toHaveBeenCalledWith('CURRENT_THEME', 'dark');
46+
expect(next).toHaveBeenCalled();
47+
});
48+
49+
it('should save samples to cache on SAMPLES_FETCH_SUCCESS', async () => {
50+
const samples = [{ id: '1', humanName: 'Test' }];
51+
await middleware({ type: SAMPLES_FETCH_SUCCESS, payload: samples });
52+
expect(samplesCache.saveSamples).toHaveBeenCalledWith(samples);
53+
expect(next).toHaveBeenCalled();
54+
});
55+
56+
it('should update collection paths on RESOURCEPATHS_ADD_SUCCESS', async () => {
57+
const mockCollection = { id: '1', isDefault: true, paths: [{ key: 'existing' }] };
58+
(collectionsCache.read as jest.Mock).mockResolvedValue([mockCollection]);
59+
60+
const newPaths = [{ key: 'new-path' }];
61+
await middleware({ type: RESOURCEPATHS_ADD_SUCCESS, payload: newPaths });
62+
63+
expect(collectionsCache.read).toHaveBeenCalled();
64+
expect(collectionsCache.update).toHaveBeenCalled();
65+
expect(next).toHaveBeenCalled();
66+
});
67+
68+
it('should delete paths from collection on RESOURCEPATHS_DELETE_SUCCESS', async () => {
69+
const mockCollection = { id: '1', isDefault: true, paths: [{ key: 'path1' }, { key: 'path2' }] };
70+
(collectionsCache.read as jest.Mock).mockResolvedValue([mockCollection]);
71+
72+
await middleware({ type: RESOURCEPATHS_DELETE_SUCCESS, payload: [{ key: 'path1' }] });
73+
74+
expect(collectionsCache.read).toHaveBeenCalled();
75+
expect(collectionsCache.update).toHaveBeenCalled();
76+
expect(next).toHaveBeenCalled();
77+
});
78+
79+
it('should create collection on COLLECTION_CREATE_SUCCESS', async () => {
80+
const collection = { id: '1', name: 'Test Collection' };
81+
await middleware({ type: COLLECTION_CREATE_SUCCESS, payload: collection });
82+
83+
expect(collectionsCache.create).toHaveBeenCalledWith(collection);
84+
expect(next).toHaveBeenCalled();
85+
});
86+
87+
it('should pass through unhandled actions', async () => {
88+
await middleware({ type: 'UNKNOWN_ACTION', payload: null });
89+
expect(next).toHaveBeenCalled();
90+
expect(saveToLocalStorage).not.toHaveBeenCalled();
91+
expect(samplesCache.saveSamples).not.toHaveBeenCalled();
92+
});
93+
});

0 commit comments

Comments
 (0)