Skip to content

Commit 48eed62

Browse files
authored
Add components tree as filter to global callback traces (#945)
* add reset and highlighting * add specs * add tests * change forms field to decoded id and fix tests * export encode function to components * refactor and fix e2e test * remove old test * add more tests * cr suggestions * fix tests
1 parent ef22ec4 commit 48eed62

15 files changed

Lines changed: 991 additions & 319 deletions

File tree

e2e/tests/global_traces.spec.ts

Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
import {
2+
expect,
3+
findSwitchTracingButton,
4+
findRefreshTracesButton,
5+
findClearTracesButton,
6+
prepareDevDebuggerPairTest,
7+
Page,
8+
} from './dev-dbg-test';
9+
10+
const test = prepareDevDebuggerPairTest();
11+
12+
const globalTracesNavbarItem = (page: Page) =>
13+
page.locator('#global-traces-navbar-item a');
14+
const globalTracesTitle = (page: Page, text: string) =>
15+
page.locator('h1', { hasText: text });
16+
const noTracesInfo = (page: Page) =>
17+
page.locator('#global-traces-stream-empty', {
18+
hasText: 'No traces have been recorded yet.',
19+
});
20+
const findTraces = (page: Page) =>
21+
page.locator('#global-traces-stream details');
22+
const traceName = (page: Page, text: string) =>
23+
page.locator('#global-traces-stream details p.font-medium', {
24+
hasText: text,
25+
});
26+
const traceModule = (page: Page, text: string) =>
27+
page.locator('#global-traces-stream details div.col-span-3', {
28+
hasText: text,
29+
});
30+
const searchBar = (page: Page) => page.locator('#trace-search-input');
31+
const traceFullscreen = (page: Page) => page.locator('#trace-fullscreen');
32+
const sidebarBasicInfo = (page: Page) =>
33+
page.locator('#node-inspector-basic-info');
34+
const openFullscreenButton = (page: Page) =>
35+
page.locator('button[phx-click="open-trace"]');
36+
37+
const traceDiffsCheckbox = (page: Page) =>
38+
page.locator('#filters-sidebar-form #filters-sidebar-form_trace_diffs');
39+
const componentCheckbox = (page: Page, name: string) =>
40+
page
41+
.locator('#filters-sidebar-form label', { hasText: name })
42+
.locator('input[type="checkbox"]');
43+
const applyButton = (page: Page) =>
44+
page.locator('#filters-sidebar-form button[type="submit"]', {
45+
hasText: 'Apply',
46+
});
47+
const resetAllButton = (page: Page) =>
48+
page.locator('#filters-sidebar-form button', { hasText: 'Reset all' });
49+
const filtersSidebar = (page: Page) => page.locator('#filters-sidebar');
50+
51+
test('user can trace callbacks globally', async ({ devApp, dbgApp }) => {
52+
await globalTracesNavbarItem(dbgApp).click();
53+
await expect(
54+
globalTracesTitle(dbgApp, 'Global Callback Traces')
55+
).toBeVisible();
56+
57+
await expect(findTraces(dbgApp)).toHaveCount(25);
58+
59+
await findSwitchTracingButton(dbgApp).click();
60+
await findClearTracesButton(dbgApp).click();
61+
await expect(findTraces(dbgApp)).toHaveCount(0);
62+
await expect(noTracesInfo(dbgApp)).toBeVisible();
63+
64+
await findSwitchTracingButton(dbgApp).click();
65+
await devApp.locator('button#send-button').click();
66+
await findSwitchTracingButton(dbgApp).click();
67+
68+
const traces = findTraces(dbgApp);
69+
await expect(traces).toHaveCount(3);
70+
await expect(traceName(dbgApp, 'handle_event/3')).toHaveCount(1);
71+
await expect(traceName(dbgApp, 'handle_info/2')).toHaveCount(1);
72+
await expect(traceName(dbgApp, 'render/1')).toHaveCount(1);
73+
74+
await expect(
75+
traceModule(dbgApp, 'LiveDebuggerDev.LiveViews.Main')
76+
).toHaveCount(2);
77+
await expect(
78+
traceModule(dbgApp, 'LiveDebuggerDev.LiveComponents.Send (4)')
79+
).toHaveCount(1);
80+
81+
await findClearTracesButton(dbgApp).click();
82+
await expect(findTraces(dbgApp)).toHaveCount(0);
83+
await expect(noTracesInfo(dbgApp)).toBeVisible();
84+
85+
await devApp.locator('button#increment-button').click();
86+
87+
await findRefreshTracesButton(dbgApp).click();
88+
await expect(findTraces(dbgApp)).toHaveCount(2);
89+
await expect(traceName(dbgApp, 'handle_event/3')).toHaveCount(1);
90+
await expect(traceName(dbgApp, 'render/1')).toHaveCount(1);
91+
});
92+
93+
test('user can go to specific node from global callbacks', async ({
94+
devApp,
95+
dbgApp,
96+
}) => {
97+
await globalTracesNavbarItem(dbgApp).click();
98+
await findSwitchTracingButton(dbgApp).click();
99+
await findClearTracesButton(dbgApp).click();
100+
await findSwitchTracingButton(dbgApp).click();
101+
await devApp.locator('button#send-button').click();
102+
103+
await dbgApp
104+
.getByRole('link', { name: 'LiveDebuggerDev.LiveViews.Main', exact: true })
105+
.first()
106+
.click();
107+
108+
await expect(sidebarBasicInfo(dbgApp)).toContainText('LiveView');
109+
await expect(sidebarBasicInfo(dbgApp)).toContainText(
110+
'LiveDebuggerDev.LiveViews.Main'
111+
);
112+
113+
await globalTracesNavbarItem(dbgApp).click();
114+
await dbgApp
115+
.getByRole('link', {
116+
name: 'LiveDebuggerDev.LiveComponents.Send (4)',
117+
exact: true,
118+
})
119+
.first()
120+
.click();
121+
122+
await expect(sidebarBasicInfo(dbgApp)).toContainText('LiveComponent');
123+
await expect(sidebarBasicInfo(dbgApp)).toContainText(
124+
'LiveDebuggerDev.LiveComponents.Send'
125+
);
126+
});
127+
128+
test('user can search for callbacks using the searchbar', async ({
129+
devApp,
130+
dbgApp,
131+
}) => {
132+
await globalTracesNavbarItem(dbgApp).click();
133+
await findSwitchTracingButton(dbgApp).click();
134+
await findClearTracesButton(dbgApp).click();
135+
await findSwitchTracingButton(dbgApp).click();
136+
await devApp.locator('button#send-button').click();
137+
await findSwitchTracingButton(dbgApp).click();
138+
139+
await searchBar(dbgApp).fill(':new_datetime');
140+
await expect(findTraces(dbgApp)).toHaveCount(1);
141+
142+
await findClearTracesButton(dbgApp).click();
143+
await devApp.locator('button#increment-button').click();
144+
145+
await searchBar(dbgApp).fill('deep value');
146+
await dbgApp.waitForTimeout(250);
147+
148+
const traces = findTraces(dbgApp);
149+
await expect(traces).toHaveCount(2);
150+
151+
const renderTrace = traces.first();
152+
await renderTrace.locator('summary').click();
153+
await expect(
154+
renderTrace.locator('pre', { hasText: '"deep value"' })
155+
).toHaveCount(2);
156+
157+
await openFullscreenButton(dbgApp).first().click();
158+
await expect(traceFullscreen(dbgApp)).toBeVisible();
159+
await expect(
160+
traceFullscreen(dbgApp).locator('pre', { hasText: '"deep value"' })
161+
).toHaveCount(2);
162+
await dbgApp.locator('#trace-fullscreen-close').click();
163+
});
164+
165+
test('incoming traces are filtered by search phrase', async ({
166+
devApp,
167+
dbgApp,
168+
}) => {
169+
await globalTracesNavbarItem(dbgApp).click();
170+
await findSwitchTracingButton(dbgApp).click();
171+
await findClearTracesButton(dbgApp).click();
172+
173+
await searchBar(dbgApp).fill(':new_datetime');
174+
await findSwitchTracingButton(dbgApp).click();
175+
176+
await devApp.locator('button#send-button').click();
177+
await expect(findTraces(dbgApp)).toHaveCount(1);
178+
});
179+
180+
test('user can enable diff tracing and see diff traces', async ({
181+
devApp,
182+
dbgApp,
183+
}) => {
184+
await dbgApp.setViewportSize({ width: 1920, height: 1080 });
185+
await globalTracesNavbarItem(dbgApp).click();
186+
await expect(
187+
globalTracesTitle(dbgApp, 'Global Callback Traces')
188+
).toBeVisible();
189+
190+
await findSwitchTracingButton(dbgApp).click();
191+
await findClearTracesButton(dbgApp).click();
192+
await expect(findTraces(dbgApp)).toHaveCount(0);
193+
await expect(noTracesInfo(dbgApp)).toBeVisible();
194+
await expect(filtersSidebar(dbgApp)).toBeVisible();
195+
196+
await traceDiffsCheckbox(dbgApp).check();
197+
await applyButton(dbgApp).click();
198+
await findSwitchTracingButton(dbgApp).click();
199+
200+
await devApp.locator('button#increment-button').click();
201+
202+
await findSwitchTracingButton(dbgApp).click();
203+
204+
const traces = findTraces(dbgApp);
205+
await expect(traces).toHaveCount(3);
206+
await expect(traceName(dbgApp, 'handle_event/3')).toBeVisible();
207+
await expect(traceName(dbgApp, 'render/1')).toBeVisible();
208+
await expect(traceName(dbgApp, 'Diff sent')).toBeVisible();
209+
210+
const diffTrace = traces.filter({ hasText: 'Diff sent' }).first();
211+
await diffTrace.locator('summary').click();
212+
await expect(
213+
diffTrace.locator('pre', { hasText: '"diff"' }).nth(1)
214+
).toBeVisible();
215+
216+
await openFullscreenButton(dbgApp).first().click();
217+
await expect(traceFullscreen(dbgApp)).toBeVisible();
218+
await expect(
219+
traceFullscreen(dbgApp).locator('pre', { hasText: '"diff"' }).nth(1)
220+
).toBeVisible();
221+
222+
await dbgApp.locator('#trace-fullscreen-close').click();
223+
await expect(traceFullscreen(dbgApp)).toBeHidden();
224+
});
225+
226+
test.describe('Global Traces Filtering', () => {
227+
test.beforeEach(async ({ dbgApp }) => {
228+
await globalTracesNavbarItem(dbgApp).click();
229+
await findSwitchTracingButton(dbgApp).click();
230+
await findClearTracesButton(dbgApp).click();
231+
await findSwitchTracingButton(dbgApp).click();
232+
});
233+
234+
test('user can filter existing traces by component', async ({
235+
devApp,
236+
dbgApp,
237+
}) => {
238+
await devApp.locator('button#increment-button').click();
239+
await expect(findTraces(dbgApp)).not.toHaveCount(0);
240+
241+
let traces = dbgApp
242+
.locator('#global-traces-stream details div.col-span-3')
243+
.filter({ hasText: 'LiveDebuggerDev.LiveViews.Main' });
244+
245+
await expect(traces).toHaveCount(2);
246+
247+
await findSwitchTracingButton(dbgApp).click();
248+
const mainLabel = dbgApp.locator('#filters-sidebar label', {
249+
hasText: 'LiveDebuggerDev.LiveViews.Main',
250+
});
251+
252+
const checkboxId = await mainLabel.getAttribute('for');
253+
await dbgApp.locator(`[id="${checkboxId}"]`).uncheck();
254+
255+
await applyButton(dbgApp).click();
256+
257+
await expect(traces).toHaveCount(0);
258+
});
259+
260+
test('new traces are filtered out when component is unchecked', async ({
261+
devApp,
262+
dbgApp,
263+
}) => {
264+
await findSwitchTracingButton(dbgApp).click();
265+
const mainLabel = dbgApp.locator('#filters-sidebar label', {
266+
hasText: 'LiveDebuggerDev.LiveViews.Main',
267+
});
268+
const checkboxId = await mainLabel.getAttribute('for');
269+
270+
await dbgApp.locator(`[id="${checkboxId}"]`).uncheck();
271+
await applyButton(dbgApp).click();
272+
273+
await findSwitchTracingButton(dbgApp).click();
274+
275+
await devApp.locator('button#increment-button').click();
276+
277+
const traces = findTraces(dbgApp);
278+
await expect(traces).toHaveCount(0);
279+
});
280+
281+
test('reset all button restores all component filters and shows hidden traces', async ({
282+
devApp,
283+
dbgApp,
284+
}) => {
285+
await findSwitchTracingButton(dbgApp).click();
286+
287+
const mainLabel = dbgApp.locator('#filters-sidebar label', {
288+
hasText: 'LiveDebuggerDev.LiveViews.Main',
289+
});
290+
const checkboxId = await mainLabel.getAttribute('for');
291+
const checkbox = dbgApp.locator(`[id="${checkboxId}"]`);
292+
293+
await checkbox.uncheck();
294+
await applyButton(dbgApp).click();
295+
296+
await findSwitchTracingButton(dbgApp).click();
297+
await devApp.locator('button#increment-button').click();
298+
299+
const tracesBeforeReset = dbgApp
300+
.locator('#global-traces-stream details div.col-span-3')
301+
.filter({ hasText: 'LiveDebuggerDev.LiveViews.Main' });
302+
await expect(tracesBeforeReset).toHaveCount(0);
303+
304+
await findSwitchTracingButton(dbgApp).click();
305+
await expect(resetAllButton(dbgApp)).toBeVisible();
306+
await resetAllButton(dbgApp).click();
307+
308+
await expect(checkbox).toBeChecked();
309+
310+
if (await applyButton(dbgApp).isEnabled()) {
311+
await applyButton(dbgApp).click();
312+
}
313+
314+
await findSwitchTracingButton(dbgApp).click();
315+
const tracesAfterReset = dbgApp
316+
.locator('#global-traces-stream details div.col-span-3')
317+
.filter({ hasText: 'LiveDebuggerDev.LiveViews.Main' });
318+
319+
await expect(tracesAfterReset).not.toHaveCount(0);
320+
const count = await tracesAfterReset.count();
321+
for (let i = 0; i < count; i++) {
322+
await expect(tracesAfterReset.nth(i)).toBeVisible();
323+
}
324+
});
325+
});

0 commit comments

Comments
 (0)