-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAppConfigPersistence.test.jsx
More file actions
120 lines (100 loc) · 3.71 KB
/
Copy pathAppConfigPersistence.test.jsx
File metadata and controls
120 lines (100 loc) · 3.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import React from 'react';
import { render, screen, waitFor, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, it, expect, beforeEach, vi } from 'vitest';
import '@testing-library/jest-dom/vitest';
import App from '../../App.jsx';
import i18n from '../../i18n';
// Mock chart.js and react-chartjs-2 to avoid canvas requirements
vi.mock('chart.js', () => {
const Chart = {
register: vi.fn(),
defaults: { plugins: { legend: { labels: { generateLabels: vi.fn(() => []) } } } }
};
return {
Chart,
ChartJS: Chart,
CategoryScale: {},
LinearScale: {},
PointElement: {},
LineElement: {},
Title: {},
Tooltip: {},
Legend: {},
Decimation: {},
};
});
vi.mock('react-chartjs-2', async () => {
const React = await import('react');
return {
Line: React.forwardRef(() => <div data-testid="line-chart" />)
};
});
vi.mock('chartjs-plugin-zoom', () => ({ default: {} }));
function stubFileReader(result) {
class FileReaderMock {
constructor() {
this.onload = null;
}
readAsText() {
this.onload({ target: { result } });
}
}
global.FileReader = FileReaderMock;
}
describe('App configuration persistence', () => {
beforeEach(() => {
localStorage.clear();
});
it('saves and restores config from localStorage', async () => {
stubFileReader('loss: 1');
const user = userEvent.setup();
const { unmount } = render(<App />);
const input = screen.getByLabelText(i18n.t('fileUpload.aria'));
const file = new File(['hello'], 'test.log', { type: 'text/plain' });
await user.upload(input, file);
const stepToggle = screen.getAllByLabelText(i18n.t('useStepKeyword'))[0];
await user.click(stepToggle);
const stepInput = screen.getByPlaceholderText(i18n.t('placeholder.step'));
fireEvent.change(stepInput, { target: { value: 'iter:' } });
await waitFor(() => expect(JSON.parse(localStorage.getItem('uploadedFiles'))).toHaveLength(1));
await waitFor(() => {
const cfg = JSON.parse(localStorage.getItem('globalParsingConfig'));
expect(cfg.stepKeyword).toBe('iter:');
expect(cfg.useStepKeyword).toBe(true);
});
unmount();
render(<App />);
expect(await screen.findByText('test.log')).toBeInTheDocument();
const restoredToggle = screen.getAllByLabelText(i18n.t('useStepKeyword'))[0];
expect(restoredToggle).toBeChecked();
const restoredInput = screen.getByPlaceholderText(i18n.t('placeholder.step'));
expect(restoredInput.value).toBe('iter:');
});
it('resets config and clears localStorage', async () => {
localStorage.setItem('globalParsingConfig', JSON.stringify({ metrics: [], useStepKeyword: true, stepKeyword: 'foo:' }));
localStorage.setItem('uploadedFiles', JSON.stringify([
{
id: '1',
name: 'saved.log',
enabled: true,
content: 'loss:1',
config: { metrics: [], dataRange: { start: 0, end: undefined, useRange: false }, useStepKeyword: true, stepKeyword: 'foo:' }
}
]));
const user = userEvent.setup();
render(<App />);
expect(screen.getByText('saved.log')).toBeInTheDocument();
expect(screen.getAllByLabelText(i18n.t('useStepKeyword'))[0]).toBeChecked();
const resetButtons = screen.getAllByRole('button', { name: i18n.t('resetConfig') });
for (const btn of resetButtons) {
await user.click(btn);
}
await waitFor(() => {
expect(localStorage.getItem('uploadedFiles')).toBeNull();
expect(localStorage.getItem('globalParsingConfig')).toBeNull();
expect(screen.queryByText('saved.log')).not.toBeInTheDocument();
});
expect(screen.getAllByLabelText(i18n.t('useStepKeyword'))[0]).not.toBeChecked();
});
});