Skip to content

Commit 6ad697c

Browse files
committed
Add tests for the source code cache
1 parent f8bff82 commit 6ad697c

File tree

1 file changed

+214
-0
lines changed

1 file changed

+214
-0
lines changed
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
import { getSourceViewCode, getSourceCodeCache } from '../../selectors/code';
6+
import { storeWithProfile } from '../fixtures/stores';
7+
import { updateUrlState } from '../../actions/app';
8+
import { stateFromLocation } from '../../app-logic/url-handling';
9+
10+
import type {
11+
State,
12+
Store,
13+
SourceCodeStatus,
14+
IndexIntoSourceTable,
15+
} from 'firefox-profiler/types';
16+
17+
describe('source code cache with IndexIntoSourceTable', function () {
18+
function setupStoreWithSourceIndex(sourceIndex: IndexIntoSourceTable | null) {
19+
const store = storeWithProfile();
20+
if (sourceIndex !== null) {
21+
const urlState = stateFromLocation({
22+
pathname: '/public/fakehash/',
23+
search: `?sourceViewIndex=${sourceIndex}`,
24+
hash: '',
25+
});
26+
store.dispatch(updateUrlState(urlState));
27+
}
28+
return store;
29+
}
30+
31+
function createStateWithMockCache(
32+
store: Store,
33+
mockCache: Map<IndexIntoSourceTable, SourceCodeStatus>
34+
): State {
35+
return {
36+
...store.getState(),
37+
code: {
38+
...store.getState().code,
39+
sourceCodeCache: mockCache,
40+
},
41+
};
42+
}
43+
44+
function createMockCache(): Map<IndexIntoSourceTable, SourceCodeStatus> {
45+
const cache = new Map<IndexIntoSourceTable, SourceCodeStatus>();
46+
cache.set(0, {
47+
type: 'AVAILABLE',
48+
code: 'console.log("Source 0");',
49+
});
50+
cache.set(1, {
51+
type: 'AVAILABLE',
52+
code: 'function source1() { return "hello"; }',
53+
});
54+
cache.set(2, {
55+
type: 'LOADING',
56+
source: { type: 'URL', url: 'https://example.com/source2.js' },
57+
});
58+
cache.set(3, {
59+
type: 'ERROR',
60+
errors: [
61+
{
62+
type: 'NETWORK_ERROR',
63+
url: 'https://example.com/source3.js',
64+
networkErrorMessage: 'Failed to fetch',
65+
},
66+
],
67+
});
68+
return cache;
69+
}
70+
71+
it('returns undefined when no source code is cached', function () {
72+
const store = setupStoreWithSourceIndex(0);
73+
const sourceViewCode = getSourceViewCode(store.getState());
74+
expect(sourceViewCode).toBeUndefined();
75+
});
76+
77+
it('returns undefined when sourceIndex is null', function () {
78+
const store = setupStoreWithSourceIndex(null);
79+
const sourceViewCode = getSourceViewCode(store.getState());
80+
expect(sourceViewCode).toBeUndefined();
81+
});
82+
83+
it('returns undefined when sourceIndex is not in cache', function () {
84+
const store = setupStoreWithSourceIndex(999); // sourceIndex not in cache
85+
const cache = createMockCache();
86+
const state = createStateWithMockCache(store, cache);
87+
88+
const sourceViewCode = getSourceViewCode(state);
89+
expect(sourceViewCode).toBeUndefined();
90+
});
91+
92+
it('retrieves cached source code for AVAILABLE status', function () {
93+
const store = setupStoreWithSourceIndex(0);
94+
const cache = createMockCache();
95+
const state = createStateWithMockCache(store, cache);
96+
97+
const sourceViewCode = getSourceViewCode(state);
98+
expect(sourceViewCode).toEqual({
99+
type: 'AVAILABLE',
100+
code: 'console.log("Source 0");',
101+
});
102+
});
103+
104+
it('retrieves cached source code for LOADING status with URL', function () {
105+
const store = setupStoreWithSourceIndex(2);
106+
const cache = createMockCache();
107+
const state = createStateWithMockCache(store, cache);
108+
109+
const sourceViewCode = getSourceViewCode(state);
110+
expect(sourceViewCode).toEqual({
111+
type: 'LOADING',
112+
source: { type: 'URL', url: 'https://example.com/source2.js' },
113+
});
114+
});
115+
116+
it('retrieves cached source code for ERROR status', function () {
117+
const store = setupStoreWithSourceIndex(3);
118+
const cache = createMockCache();
119+
const state = createStateWithMockCache(store, cache);
120+
121+
const sourceViewCode = getSourceViewCode(state);
122+
expect(sourceViewCode).toEqual({
123+
type: 'ERROR',
124+
errors: [
125+
{
126+
type: 'NETWORK_ERROR',
127+
url: 'https://example.com/source3.js',
128+
networkErrorMessage: 'Failed to fetch',
129+
},
130+
],
131+
});
132+
});
133+
134+
it('retrieves cached source code for LOADING status with BROWSER_CONNECTION', function () {
135+
const store = setupStoreWithSourceIndex(4);
136+
const cache = new Map<IndexIntoSourceTable, SourceCodeStatus>();
137+
cache.set(4, {
138+
type: 'LOADING',
139+
source: { type: 'BROWSER_CONNECTION' },
140+
});
141+
const state = createStateWithMockCache(store, cache);
142+
143+
const sourceViewCode = getSourceViewCode(state);
144+
expect(sourceViewCode).toEqual({
145+
type: 'LOADING',
146+
source: { type: 'BROWSER_CONNECTION' },
147+
});
148+
});
149+
150+
describe('getSourceCodeCache selector', function () {
151+
it('returns the cache Map directly', function () {
152+
const store = setupStoreWithSourceIndex(null);
153+
const cache = createMockCache();
154+
const state = createStateWithMockCache(store, cache);
155+
156+
const result = getSourceCodeCache(state);
157+
expect(result).toBe(cache);
158+
expect(result.get(0)).toEqual({
159+
type: 'AVAILABLE',
160+
code: 'console.log("Source 0");',
161+
});
162+
});
163+
164+
it('returns empty Map when no cache is set', function () {
165+
const store = setupStoreWithSourceIndex(null);
166+
const state = store.getState();
167+
168+
const result = getSourceCodeCache(state);
169+
expect(result).toBeInstanceOf(Map);
170+
expect(result.size).toBe(0);
171+
});
172+
});
173+
174+
describe('edge cases', function () {
175+
it('handles different SourceCodeStatus types correctly', function () {
176+
const cache = createMockCache();
177+
178+
// Test each type of status
179+
expect(cache.get(0)?.type).toBe('AVAILABLE');
180+
expect(cache.get(2)?.type).toBe('LOADING');
181+
expect(cache.get(3)?.type).toBe('ERROR');
182+
});
183+
184+
it('handles multiple error types', function () {
185+
const store = setupStoreWithSourceIndex(5);
186+
const cache = new Map<IndexIntoSourceTable, SourceCodeStatus>();
187+
cache.set(5, {
188+
type: 'ERROR',
189+
errors: [
190+
{
191+
type: 'NETWORK_ERROR',
192+
url: 'https://example.com/source.js',
193+
networkErrorMessage: 'Network failed',
194+
},
195+
{ type: 'NO_KNOWN_CORS_URL' },
196+
],
197+
});
198+
const state = createStateWithMockCache(store, cache);
199+
200+
const sourceViewCode = getSourceViewCode(state);
201+
expect(sourceViewCode).toEqual({
202+
type: 'ERROR',
203+
errors: [
204+
{
205+
type: 'NETWORK_ERROR',
206+
url: 'https://example.com/source.js',
207+
networkErrorMessage: 'Network failed',
208+
},
209+
{ type: 'NO_KNOWN_CORS_URL' },
210+
],
211+
});
212+
});
213+
});
214+
});

0 commit comments

Comments
 (0)