Skip to content

Commit e1f7e7e

Browse files
authored
Added tests for the Templates flow (#97)
TemplatesContext is covered for registering and cleaning up the Dynamo callback, updating context from received template data, and normalizing template fields (date to DateModified, default Author/Description). PageRecent is covered for rendering templates from context, switching the Templates section to list view, and opening a template row through the shared openFile flow
1 parent f81df14 commit e1f7e7e

2 files changed

Lines changed: 146 additions & 5 deletions

File tree

tests/unit/Recent/PageRecent.test.tsx

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { screen, fireEvent, act } from '@testing-library/react';
22
import { renderWithProviders } from '../testUtils';
33
import { RecentPage } from '../../../src/components/Recent/PageRecent';
4+
import { useTemplates } from '../../../src/components/TemplatesContext';
5+
import { openFile } from '../../../src/functions/utility';
46

57
jest.mock('../../../src/components/Recent/GraphGridItem', () => ({
68
GraphGridItem: (props: unknown) => {
@@ -12,8 +14,8 @@ jest.mock('../../../src/components/Recent/GraphGridItem', () => ({
1214
jest.mock('../../../src/components/Recent/GraphTable', () => ({
1315
GraphTable: (props: unknown) => {
1416
const { data, onRowClick } = props as {
15-
data: Array<{ id: string; Caption: string }>;
16-
onRowClick: (row: { original: { id: string; Caption: string } }) => void;
17+
data: Array<{ id: string; Caption: string; ContextData: string }>;
18+
onRowClick: (row: { original: { id: string; Caption: string; ContextData: string } }) => void;
1719
};
1820
return (
1921
<div data-testid="graph-table">
@@ -32,6 +34,10 @@ jest.mock('../../../src/functions/utility', () => ({
3234
saveHomePageSettings: jest.fn(),
3335
}));
3436

37+
jest.mock('../../../src/components/TemplatesContext', () => ({
38+
useTemplates: jest.fn(),
39+
}));
40+
3541
const defaultProps = {
3642
setIsDisabled: jest.fn(),
3743
recentPageViewMode: 'grid' as const,
@@ -42,9 +48,24 @@ const mockGraphs = [
4248
{ id: '2', Caption: 'Graph Two', ContextData: '/path/two.dyn', DateModified: '2024-01-02', Thumbnail: null, Description: '' },
4349
];
4450

51+
const mockTemplates = [
52+
{
53+
id: 'template-1',
54+
Caption: 'Template One',
55+
ContextData: '/path/template-one.dyn',
56+
DateModified: '2024-02-01',
57+
Thumbnail: '',
58+
Author: '',
59+
Description: '',
60+
},
61+
];
62+
63+
const mockUseTemplates = useTemplates as jest.MockedFunction<typeof useTemplates>;
64+
4565
describe('RecentPage', () => {
4666
beforeEach(() => {
4767
jest.clearAllMocks();
68+
mockUseTemplates.mockReturnValue([]);
4869
});
4970

5071
it('renders "Recent" title', () => {
@@ -134,4 +155,33 @@ describe('RecentPage', () => {
134155
unmount();
135156
expect(window.receiveGraphDataFromDotNet).toBeUndefined();
136157
});
158+
159+
it('renders templates returned by TemplatesContext', () => {
160+
mockUseTemplates.mockReturnValue(mockTemplates);
161+
renderWithProviders(<RecentPage {...defaultProps} recentPageViewMode="grid" />);
162+
163+
expect(screen.getByText('Templates')).toBeInTheDocument();
164+
expect(screen.getByText('Template One')).toBeInTheDocument();
165+
});
166+
167+
it('switches templates to list view', () => {
168+
mockUseTemplates.mockReturnValue(mockTemplates);
169+
renderWithProviders(<RecentPage {...defaultProps} recentPageViewMode="grid" />);
170+
171+
fireEvent.click(screen.getByTestId('templates-view-toggle-list'));
172+
173+
expect(screen.getByTestId('graph-table')).toBeInTheDocument();
174+
expect(screen.getByText('Template One')).toBeInTheDocument();
175+
});
176+
177+
it('opens a template from the templates table', () => {
178+
mockUseTemplates.mockReturnValue(mockTemplates);
179+
renderWithProviders(<RecentPage {...defaultProps} recentPageViewMode="grid" />);
180+
181+
fireEvent.click(screen.getByTestId('templates-view-toggle-list'));
182+
fireEvent.click(screen.getByText('Template One'));
183+
184+
expect(defaultProps.setIsDisabled).toHaveBeenCalledWith(true);
185+
expect(openFile).toHaveBeenCalledWith('/path/template-one.dyn');
186+
});
137187
});

tests/unit/TemplatesContext.test.tsx

Lines changed: 94 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
1-
import { act, render } from '@testing-library/react';
2-
import { TemplatesProvider } from '../../src/components/TemplatesContext';
1+
import { act, render, screen } from '@testing-library/react';
2+
import { TemplatesProvider, useTemplates } from '../../src/components/TemplatesContext';
3+
4+
const TemplatesConsumer = () => {
5+
const templates = useTemplates();
6+
7+
return (
8+
<div>
9+
{templates.map((template) => (
10+
<div key={template.id}>
11+
<span>{template.Caption}</span>
12+
<span>{`date:${template.DateModified}`}</span>
13+
<span>{`author:${template.Author}`}</span>
14+
<span>{`description:${template.Description}`}</span>
15+
</div>
16+
))}
17+
</div>
18+
);
19+
};
320

421
describe('TemplatesProvider', () => {
522
beforeEach(() => {
@@ -15,7 +32,7 @@ describe('TemplatesProvider', () => {
1532
it('clears loading state when template data is received', () => {
1633
render(
1734
<TemplatesProvider>
18-
<div />
35+
<TemplatesConsumer />
1936
</TemplatesProvider>
2037
);
2138

@@ -25,4 +42,78 @@ describe('TemplatesProvider', () => {
2542

2643
expect(window.setShowStartPageChanged).toHaveBeenCalledWith(true);
2744
});
45+
46+
it('registers receiveTemplatesDataFromDotNet on mount', () => {
47+
render(
48+
<TemplatesProvider>
49+
<TemplatesConsumer />
50+
</TemplatesProvider>
51+
);
52+
53+
expect(typeof window.receiveTemplatesDataFromDotNet).toBe('function');
54+
});
55+
56+
it('updates templates from receiveTemplatesDataFromDotNet', () => {
57+
render(
58+
<TemplatesProvider>
59+
<TemplatesConsumer />
60+
</TemplatesProvider>
61+
);
62+
63+
act(() => {
64+
window.receiveTemplatesDataFromDotNet([
65+
{
66+
id: 'template-1',
67+
Caption: 'Template One',
68+
ContextData: '/path/template-one.dyn',
69+
DateModified: '2024-02-01',
70+
Thumbnail: '',
71+
Author: 'Dynamo Team',
72+
Description: 'Template description',
73+
},
74+
]);
75+
});
76+
77+
expect(screen.getByText('Template One')).toBeInTheDocument();
78+
expect(screen.getByText('date:2024-02-01')).toBeInTheDocument();
79+
expect(screen.getByText('author:Dynamo Team')).toBeInTheDocument();
80+
expect(screen.getByText('description:Template description')).toBeInTheDocument();
81+
});
82+
83+
it('normalizes date, Author, and Description fields from template input', () => {
84+
render(
85+
<TemplatesProvider>
86+
<TemplatesConsumer />
87+
</TemplatesProvider>
88+
);
89+
90+
act(() => {
91+
window.receiveTemplatesDataFromDotNet([
92+
{
93+
id: 'template-1',
94+
Caption: 'Template One',
95+
ContextData: '/path/template-one.dyn',
96+
date: '2024-03-01',
97+
Thumbnail: '',
98+
},
99+
]);
100+
});
101+
102+
expect(screen.getByText('Template One')).toBeInTheDocument();
103+
expect(screen.getByText('date:2024-03-01')).toBeInTheDocument();
104+
expect(screen.getByText('author:')).toBeInTheDocument();
105+
expect(screen.getByText('description:')).toBeInTheDocument();
106+
});
107+
108+
it('removes receiveTemplatesDataFromDotNet on unmount', () => {
109+
const { unmount } = render(
110+
<TemplatesProvider>
111+
<TemplatesConsumer />
112+
</TemplatesProvider>
113+
);
114+
115+
unmount();
116+
117+
expect(window.receiveTemplatesDataFromDotNet).toBeUndefined();
118+
});
28119
});

0 commit comments

Comments
 (0)