Skip to content

Commit 8cb7231

Browse files
hjanuschkadevtools-frontend-scoped@luci-project-accounts.iam.gserviceaccount.com
authored andcommitted
Add collapse/expand all toggle button to Console
Add a toolbar toggle button that collapses or expands all console groups and stack traces at once, reducing clutter from console.trace(). Bug: 427657550 Change-Id: Ifc5bc617c244338f69b818343973baf4c0bf147d Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/7575527 Reviewed-by: Simon Zünd <szuend@chromium.org> Reviewed-by: Samiya Caur <samiyac@chromium.org> Commit-Queue: Helmut Januschka <helmut@januschka.com>
1 parent 230cc90 commit 8cb7231

7 files changed

Lines changed: 328 additions & 29 deletions

File tree

config/gni/devtools_grd_files.gni

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ grd_files_bundled_sources = [
134134
"front_end/Images/empty.svg",
135135
"front_end/Images/errorWave.svg",
136136
"front_end/Images/exclamation.svg",
137+
"front_end/Images/expand.svg",
137138
"front_end/Images/experiment-check.svg",
138139
"front_end/Images/experiment.svg",
139140
"front_end/Images/extension.svg",

config/gni/devtools_image_files.gni

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ devtools_svg_sources = [
140140
"empty.svg",
141141
"errorWave.svg",
142142
"exclamation.svg",
143+
"expand.svg",
143144
"experiment-check.svg",
144145
"experiment.svg",
145146
"extension.svg",

front_end/Images/src/expand.svg

Lines changed: 1 addition & 0 deletions
Loading

front_end/panels/console/ConsoleView.test.ts

Lines changed: 215 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,21 @@ describeWithMockConnection('ConsoleView', () => {
155155
target.model(SDK.RuntimeModel.RuntimeModel), Protocol.Log.LogEntrySource.Javascript, level, message, {type});
156156
}
157157

158+
let globalMessageTimestamp = 0;
159+
160+
function addMessage(
161+
consoleModel: SDK.ConsoleModel.ConsoleModel,
162+
target: SDK.Target.Target,
163+
message: string,
164+
type: SDK.ConsoleModel.MessageType,
165+
level: Protocol.Log.LogEntryLevel,
166+
timestamp?: number,
167+
) {
168+
const consoleMessage = createConsoleMessage(target, message, type, level);
169+
consoleMessage.timestamp = timestamp ?? ++globalMessageTimestamp;
170+
consoleModel.addMessage(consoleMessage);
171+
}
172+
158173
it('can save to file', async () => {
159174
const tabTarget = createTarget({type: SDK.Target.Type.TAB});
160175
createTarget({parentTarget: tabTarget, subtype: 'prerender'});
@@ -526,13 +541,6 @@ describeWithMockConnection('ConsoleView', () => {
526541
}
527542
});
528543

529-
function addMessage(
530-
message: string, type: Protocol.Runtime.ConsoleAPICalledEventType, level: Protocol.Log.LogEntryLevel) {
531-
const consoleMessage = createConsoleMessage(target, message, type, level);
532-
consoleMessage.timestamp = ++messageTimestamp;
533-
consoleModel!.addMessage(consoleMessage);
534-
}
535-
536544
for (const level
537545
of [Protocol.Log.LogEntryLevel.Error,
538546
Protocol.Log.LogEntryLevel.Warning,
@@ -548,9 +556,14 @@ describeWithMockConnection('ConsoleView', () => {
548556
renderElementIntoDOM(consoleView);
549557

550558
addMessage(
551-
'group', Protocol.Runtime.ConsoleAPICalledEventType.StartGroupCollapsed, Protocol.Log.LogEntryLevel.Info);
552-
addMessage('message', Protocol.Runtime.ConsoleAPICalledEventType.Log, level);
553-
addMessage('', Protocol.Runtime.ConsoleAPICalledEventType.EndGroup, Protocol.Log.LogEntryLevel.Info);
559+
consoleModel!, target, 'group', Protocol.Runtime.ConsoleAPICalledEventType.StartGroupCollapsed,
560+
Protocol.Log.LogEntryLevel.Info, ++messageTimestamp);
561+
addMessage(
562+
consoleModel!, target, 'message', Protocol.Runtime.ConsoleAPICalledEventType.Log, level,
563+
++messageTimestamp);
564+
addMessage(
565+
consoleModel!, target, '', Protocol.Runtime.ConsoleAPICalledEventType.EndGroup,
566+
Protocol.Log.LogEntryLevel.Info, ++messageTimestamp);
554567

555568
const messages = await getConsoleMessages();
556569
assert.include(messages, 'group');
@@ -565,9 +578,15 @@ describeWithMockConnection('ConsoleView', () => {
565578
consoleView.markAsRoot();
566579
renderElementIntoDOM(consoleView);
567580

568-
addMessage('group', Protocol.Runtime.ConsoleAPICalledEventType.StartGroup, Protocol.Log.LogEntryLevel.Info);
569-
addMessage('message', Protocol.Runtime.ConsoleAPICalledEventType.Log, level);
570-
addMessage('', Protocol.Runtime.ConsoleAPICalledEventType.EndGroup, Protocol.Log.LogEntryLevel.Info);
581+
addMessage(
582+
consoleModel!, target, 'group', Protocol.Runtime.ConsoleAPICalledEventType.StartGroup,
583+
Protocol.Log.LogEntryLevel.Info, ++messageTimestamp);
584+
addMessage(
585+
consoleModel!, target, 'message', Protocol.Runtime.ConsoleAPICalledEventType.Log, level,
586+
++messageTimestamp);
587+
addMessage(
588+
consoleModel!, target, '', Protocol.Runtime.ConsoleAPICalledEventType.EndGroup,
589+
Protocol.Log.LogEntryLevel.Info, ++messageTimestamp);
571590

572591
const messages = await getConsoleMessages();
573592
assert.include(messages, 'group');
@@ -583,9 +602,15 @@ describeWithMockConnection('ConsoleView', () => {
583602
consoleView.markAsRoot();
584603
renderElementIntoDOM(consoleView);
585604

586-
addMessage('group', Protocol.Runtime.ConsoleAPICalledEventType.StartGroup, Protocol.Log.LogEntryLevel.Info);
587-
addMessage('message', Protocol.Runtime.ConsoleAPICalledEventType.Log, Protocol.Log.LogEntryLevel.Error);
588-
addMessage('', Protocol.Runtime.ConsoleAPICalledEventType.EndGroup, Protocol.Log.LogEntryLevel.Info);
605+
addMessage(
606+
consoleModel!, target, 'group', Protocol.Runtime.ConsoleAPICalledEventType.StartGroup,
607+
Protocol.Log.LogEntryLevel.Info, ++messageTimestamp);
608+
addMessage(
609+
consoleModel!, target, 'message', Protocol.Runtime.ConsoleAPICalledEventType.Log,
610+
Protocol.Log.LogEntryLevel.Error, ++messageTimestamp);
611+
addMessage(
612+
consoleModel!, target, '', Protocol.Runtime.ConsoleAPICalledEventType.EndGroup,
613+
Protocol.Log.LogEntryLevel.Info, ++messageTimestamp);
589614

590615
const messages = await getConsoleMessages();
591616
assert.notInclude(messages, 'group');
@@ -603,11 +628,21 @@ describeWithMockConnection('ConsoleView', () => {
603628
console.groupEnd() // B
604629
console.groupEnd() // A
605630
*/
606-
addMessage('A', Protocol.Runtime.ConsoleAPICalledEventType.StartGroup, Protocol.Log.LogEntryLevel.Info);
607-
addMessage('B', Protocol.Runtime.ConsoleAPICalledEventType.StartGroup, Protocol.Log.LogEntryLevel.Info);
608-
addMessage('C', Protocol.Runtime.ConsoleAPICalledEventType.Log, Protocol.Log.LogEntryLevel.Info);
609-
addMessage('', Protocol.Runtime.ConsoleAPICalledEventType.EndGroup, Protocol.Log.LogEntryLevel.Info);
610-
addMessage('', Protocol.Runtime.ConsoleAPICalledEventType.EndGroup, Protocol.Log.LogEntryLevel.Info);
631+
addMessage(
632+
consoleModel!, target, 'A', Protocol.Runtime.ConsoleAPICalledEventType.StartGroup,
633+
Protocol.Log.LogEntryLevel.Info, ++messageTimestamp);
634+
addMessage(
635+
consoleModel!, target, 'B', Protocol.Runtime.ConsoleAPICalledEventType.StartGroup,
636+
Protocol.Log.LogEntryLevel.Info, ++messageTimestamp);
637+
addMessage(
638+
consoleModel!, target, 'C', Protocol.Runtime.ConsoleAPICalledEventType.Log, Protocol.Log.LogEntryLevel.Info,
639+
++messageTimestamp);
640+
addMessage(
641+
consoleModel!, target, '', Protocol.Runtime.ConsoleAPICalledEventType.EndGroup,
642+
Protocol.Log.LogEntryLevel.Info, ++messageTimestamp);
643+
addMessage(
644+
consoleModel!, target, '', Protocol.Runtime.ConsoleAPICalledEventType.EndGroup,
645+
Protocol.Log.LogEntryLevel.Info, ++messageTimestamp);
611646

612647
let messages = await getConsoleMessages();
613648
assert.include(messages, 'A', 'A should be visible');
@@ -625,4 +660,163 @@ describeWithMockConnection('ConsoleView', () => {
625660
assert.notInclude(messages, 'C', 'C should be hidden after collapsing parent A');
626661
});
627662
});
663+
664+
describe('collapse all and expand all', () => {
665+
let target: ReturnType<typeof createTarget>;
666+
let consoleModel: SDK.ConsoleModel.ConsoleModel|null;
667+
668+
beforeEach(() => {
669+
target = createTarget();
670+
SDK.TargetManager.TargetManager.instance().setScopeTarget(target);
671+
consoleModel = target.model(SDK.ConsoleModel.ConsoleModel);
672+
assert.exists(consoleModel);
673+
consoleView.markAsRoot();
674+
renderElementIntoDOM(consoleView);
675+
});
676+
677+
it('collapseAll collapses expanded groups', async () => {
678+
addMessage(
679+
consoleModel!, target, 'group 1', Protocol.Runtime.ConsoleAPICalledEventType.StartGroup,
680+
Protocol.Log.LogEntryLevel.Info);
681+
addMessage(
682+
consoleModel!, target, 'inner message 1', Protocol.Runtime.ConsoleAPICalledEventType.Log,
683+
Protocol.Log.LogEntryLevel.Info);
684+
addMessage(
685+
consoleModel!, target, '', Protocol.Runtime.ConsoleAPICalledEventType.EndGroup,
686+
Protocol.Log.LogEntryLevel.Info);
687+
addMessage(
688+
consoleModel!, target, 'group 2', Protocol.Runtime.ConsoleAPICalledEventType.StartGroup,
689+
Protocol.Log.LogEntryLevel.Info);
690+
addMessage(
691+
consoleModel!, target, 'inner message 2', Protocol.Runtime.ConsoleAPICalledEventType.Log,
692+
Protocol.Log.LogEntryLevel.Info);
693+
addMessage(
694+
consoleModel!, target, '', Protocol.Runtime.ConsoleAPICalledEventType.EndGroup,
695+
Protocol.Log.LogEntryLevel.Info);
696+
await consoleView.getScheduledRefreshPromiseForTest();
697+
698+
// Both groups are expanded by default, so all group headers and messages are visible.
699+
assert.strictEqual(consoleView.itemCount(), 4);
700+
701+
consoleView.collapseAll();
702+
703+
// After collapsing, only the two group headers should be visible.
704+
assert.strictEqual(consoleView.itemCount(), 2);
705+
});
706+
707+
it('expandAll expands collapsed groups', async () => {
708+
addMessage(
709+
consoleModel!, target, 'group 1', Protocol.Runtime.ConsoleAPICalledEventType.StartGroupCollapsed,
710+
Protocol.Log.LogEntryLevel.Info);
711+
addMessage(
712+
consoleModel!, target, 'inner message 1', Protocol.Runtime.ConsoleAPICalledEventType.Log,
713+
Protocol.Log.LogEntryLevel.Info);
714+
addMessage(
715+
consoleModel!, target, '', Protocol.Runtime.ConsoleAPICalledEventType.EndGroup,
716+
Protocol.Log.LogEntryLevel.Info);
717+
addMessage(
718+
consoleModel!, target, 'group 2', Protocol.Runtime.ConsoleAPICalledEventType.StartGroupCollapsed,
719+
Protocol.Log.LogEntryLevel.Info);
720+
addMessage(
721+
consoleModel!, target, 'inner message 2', Protocol.Runtime.ConsoleAPICalledEventType.Log,
722+
Protocol.Log.LogEntryLevel.Info);
723+
addMessage(
724+
consoleModel!, target, '', Protocol.Runtime.ConsoleAPICalledEventType.EndGroup,
725+
Protocol.Log.LogEntryLevel.Info);
726+
await consoleView.getScheduledRefreshPromiseForTest();
727+
728+
// Both groups are collapsed by default, so only group headers are visible.
729+
assert.strictEqual(consoleView.itemCount(), 2);
730+
731+
consoleView.expandAll();
732+
733+
// After expanding, all group headers and messages are visible.
734+
assert.strictEqual(consoleView.itemCount(), 4);
735+
});
736+
737+
it('collapseAll then expandAll round-trips groups correctly', async () => {
738+
addMessage(
739+
consoleModel!, target, 'expanded group', Protocol.Runtime.ConsoleAPICalledEventType.StartGroup,
740+
Protocol.Log.LogEntryLevel.Info);
741+
addMessage(
742+
consoleModel!, target, 'expanded message', Protocol.Runtime.ConsoleAPICalledEventType.Log,
743+
Protocol.Log.LogEntryLevel.Info);
744+
addMessage(
745+
consoleModel!, target, '', Protocol.Runtime.ConsoleAPICalledEventType.EndGroup,
746+
Protocol.Log.LogEntryLevel.Info);
747+
addMessage(
748+
consoleModel!, target, 'collapsed group', Protocol.Runtime.ConsoleAPICalledEventType.StartGroupCollapsed,
749+
Protocol.Log.LogEntryLevel.Info);
750+
addMessage(
751+
consoleModel!, target, 'collapsed message', Protocol.Runtime.ConsoleAPICalledEventType.Log,
752+
Protocol.Log.LogEntryLevel.Info);
753+
addMessage(
754+
consoleModel!, target, '', Protocol.Runtime.ConsoleAPICalledEventType.EndGroup,
755+
Protocol.Log.LogEntryLevel.Info);
756+
await consoleView.getScheduledRefreshPromiseForTest();
757+
758+
// Mixed state: one expanded group and one collapsed group.
759+
assert.strictEqual(consoleView.itemCount(), 3);
760+
761+
consoleView.collapseAll();
762+
assert.strictEqual(consoleView.itemCount(), 2);
763+
764+
consoleView.expandAll();
765+
assert.strictEqual(consoleView.itemCount(), 4);
766+
});
767+
768+
it('collapseAll collapses nested groups', async () => {
769+
addMessage(
770+
consoleModel!, target, 'outer', Protocol.Runtime.ConsoleAPICalledEventType.StartGroup,
771+
Protocol.Log.LogEntryLevel.Info);
772+
addMessage(
773+
consoleModel!, target, 'inner', Protocol.Runtime.ConsoleAPICalledEventType.StartGroup,
774+
Protocol.Log.LogEntryLevel.Info);
775+
addMessage(
776+
consoleModel!, target, 'deep message', Protocol.Runtime.ConsoleAPICalledEventType.Log,
777+
Protocol.Log.LogEntryLevel.Info);
778+
addMessage(
779+
consoleModel!, target, '', Protocol.Runtime.ConsoleAPICalledEventType.EndGroup,
780+
Protocol.Log.LogEntryLevel.Info);
781+
addMessage(
782+
consoleModel!, target, '', Protocol.Runtime.ConsoleAPICalledEventType.EndGroup,
783+
Protocol.Log.LogEntryLevel.Info);
784+
await consoleView.getScheduledRefreshPromiseForTest();
785+
786+
// All three are visible: outer, inner, deep message.
787+
assert.strictEqual(consoleView.itemCount(), 3);
788+
789+
consoleView.collapseAll();
790+
791+
// After collapse, only outer is visible.
792+
assert.strictEqual(consoleView.itemCount(), 1);
793+
});
794+
795+
it('expandAll expands nested groups', async () => {
796+
addMessage(
797+
consoleModel!, target, 'outer', Protocol.Runtime.ConsoleAPICalledEventType.StartGroupCollapsed,
798+
Protocol.Log.LogEntryLevel.Info);
799+
addMessage(
800+
consoleModel!, target, 'inner', Protocol.Runtime.ConsoleAPICalledEventType.StartGroupCollapsed,
801+
Protocol.Log.LogEntryLevel.Info);
802+
addMessage(
803+
consoleModel!, target, 'deep message', Protocol.Runtime.ConsoleAPICalledEventType.Log,
804+
Protocol.Log.LogEntryLevel.Info);
805+
addMessage(
806+
consoleModel!, target, '', Protocol.Runtime.ConsoleAPICalledEventType.EndGroup,
807+
Protocol.Log.LogEntryLevel.Info);
808+
addMessage(
809+
consoleModel!, target, '', Protocol.Runtime.ConsoleAPICalledEventType.EndGroup,
810+
Protocol.Log.LogEntryLevel.Info);
811+
await consoleView.getScheduledRefreshPromiseForTest();
812+
813+
// All collapsed, only outer visible.
814+
assert.strictEqual(consoleView.itemCount(), 1);
815+
816+
consoleView.expandAll();
817+
818+
// After expanding, all three are visible.
819+
assert.strictEqual(consoleView.itemCount(), 3);
820+
});
821+
});
628822
});

0 commit comments

Comments
 (0)