From ecfc03a2d2095f827736ae1e63809ebe85eb5540 Mon Sep 17 00:00:00 2001 From: mgechev Date: Wed, 28 Apr 2021 15:50:06 -0700 Subject: [PATCH] feat(devtools): don't show comment nodes by default --- cypress/integration/comment-nodes.e2e.js | 22 +++ .../devtools-tabs.component.html | 10 ++ .../devtools-tabs/devtools-tabs.component.ts | 1 + .../directive-explorer.component.html | 1 + .../directive-explorer.component.ts | 16 +-- .../component-data-source.spec.ts | 129 ++++++++++++++++++ .../directive-forest/component-data-source.ts | 11 +- .../directive-forest.component.ts | 9 +- 8 files changed, 188 insertions(+), 11 deletions(-) create mode 100644 cypress/integration/comment-nodes.e2e.js create mode 100644 projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-forest/component-data-source.spec.ts diff --git a/cypress/integration/comment-nodes.e2e.js b/cypress/integration/comment-nodes.e2e.js new file mode 100644 index 00000000000..c379b0333df --- /dev/null +++ b/cypress/integration/comment-nodes.e2e.js @@ -0,0 +1,22 @@ +function showComments() { + cy.get( + '#nav-buttons > button.mat-focus-indicator.mat-menu-trigger.mat-icon-button.mat-button-base.mat-primary' + ).click(); + cy.get('#mat-slide-toggle-3 > label > div').click(); +} + +describe('Comment nodes', () => { + beforeEach(() => { + cy.visit('/'); + }); + + it('should not find any comment nodes by default', () => { + const nodes = cy.$$('.tree-node:contains("#comment")'); + expect(nodes.length).to.eql(0); + }); + + it('should find comment nodes when the setting is enabled', () => { + showComments(); + cy.get('.tree-wrapper').find('.tree-node:contains("#comment")').its('length').should('not.eq', 0); + }); +}); diff --git a/projects/ng-devtools/src/lib/devtools-tabs/devtools-tabs.component.html b/projects/ng-devtools/src/lib/devtools-tabs/devtools-tabs.component.html index 7a28438d8bc..d705b943c72 100644 --- a/projects/ng-devtools/src/lib/devtools-tabs/devtools-tabs.component.html +++ b/projects/ng-devtools/src/lib/devtools-tabs/devtools-tabs.component.html @@ -25,6 +25,7 @@
@@ -46,4 +47,13 @@ > Dark Mode +
+
+ + Show comment nodes + diff --git a/projects/ng-devtools/src/lib/devtools-tabs/devtools-tabs.component.ts b/projects/ng-devtools/src/lib/devtools-tabs/devtools-tabs.component.ts index 97b6410281b..8d89e678de0 100644 --- a/projects/ng-devtools/src/lib/devtools-tabs/devtools-tabs.component.ts +++ b/projects/ng-devtools/src/lib/devtools-tabs/devtools-tabs.component.ts @@ -23,6 +23,7 @@ export class DevToolsTabsComponent implements OnInit, OnDestroy, AfterViewInit { inspectorRunning = false; routerTreeEnabled = false; + showCommentNodes = false; private _currentThemeSubscription: Subscription; currentTheme: Theme; diff --git a/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-explorer.component.html b/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-explorer.component.html index 9dd39a91480..9c8ffdba6f8 100644 --- a/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-explorer.component.html +++ b/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-explorer.component.html @@ -11,6 +11,7 @@ (toggleInspector)="toggleInspector.emit()" [forest]="forest" [currentSelectedElement]="currentSelectedElement" + [showCommentNodes]="showCommentNodes" > diff --git a/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-explorer.component.ts b/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-explorer.component.ts index c7cf93849a8..d8da234c125 100644 --- a/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-explorer.component.ts +++ b/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-explorer.component.ts @@ -3,6 +3,7 @@ import { Component, ElementRef, EventEmitter, + Input, NgZone, OnDestroy, OnInit, @@ -58,14 +59,18 @@ const sameDirectives = (a: IndexedNode, b: IndexedNode) => { ], }) export class DirectiveExplorerComponent implements OnInit, OnDestroy { + @Input() showCommentNodes = false; @Output() toggleInspector = new EventEmitter(); + @ViewChild(DirectiveForestComponent) directiveForest: DirectiveForestComponent; + @ViewChild(BreadcrumbsComponent) breadcrumbs: BreadcrumbsComponent; + @ViewChild(SplitComponent, { static: true, read: ElementRef }) splitElementRef: ElementRef; + @ViewChild('directiveForestSplitArea', { static: true, read: ElementRef }) directiveForestSplitArea: ElementRef; + currentSelectedElement: IndexedNode | null = null; forest: DevToolsNode[]; splitDirection: 'horizontal' | 'vertical' = 'horizontal'; - - @ViewChild(SplitComponent, { static: true, read: ElementRef }) splitElementRef: ElementRef; - @ViewChild('directiveForestSplitArea', { static: true, read: ElementRef }) directiveForestSplitArea: ElementRef; + parents: FlatNode[] | null = null; private _resizeObserver = new ResizeObserver((entries) => this._ngZone.run(() => { @@ -86,11 +91,6 @@ export class DirectiveExplorerComponent implements OnInit, OnDestroy { private _clickedElement: IndexedNode | null = null; private _refreshRetryTimeout: any = null; - parents: FlatNode[] | null = null; - - @ViewChild(DirectiveForestComponent) directiveForest: DirectiveForestComponent; - @ViewChild(BreadcrumbsComponent) breadcrumbs: BreadcrumbsComponent; - constructor( private _appOperations: ApplicationOperations, private _messageBus: MessageBus, diff --git a/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-forest/component-data-source.spec.ts b/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-forest/component-data-source.spec.ts new file mode 100644 index 00000000000..ad3ee213b2b --- /dev/null +++ b/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-forest/component-data-source.spec.ts @@ -0,0 +1,129 @@ +import { FlatTreeControl } from '@angular/cdk/tree'; +import { ComponentDataSource, FlatNode } from './component-data-source'; +import { DevToolsNode } from 'protocol'; + +const tree1: DevToolsNode = { + element: 'app', + directives: [ + { + id: 1, + name: 'foo', + }, + ], + component: null, + children: [ + { + children: [], + component: { + id: 2, + isElement: false, + name: 'bar', + }, + directives: [], + element: 'bar', + nativeElement: document.createElement('bar'), + }, + ], + nativeElement: document.createElement('foo'), +}; + +const tree2: DevToolsNode = { + element: 'app', + directives: [ + { + id: 1, + name: 'foo', + }, + ], + component: null, + children: [ + { + children: [], + component: { + id: 2, + isElement: false, + name: 'bar', + }, + directives: [], + element: 'bar', + nativeElement: document.createElement('bar'), + }, + { + children: [], + component: { + id: 3, + isElement: false, + name: 'qux', + }, + directives: [], + element: 'qux', + nativeElement: document.createElement('qux'), + }, + ], + nativeElement: document.createElement('foo'), +}; + +const tree3: DevToolsNode = { + element: 'app', + directives: [ + { + id: 1, + name: 'foo', + }, + ], + component: null, + children: [ + { + children: [], + component: { + id: 2, + isElement: false, + name: 'bar', + }, + directives: [], + element: '#comment', + nativeElement: document.createComment('bar'), + }, + { + children: [], + component: { + id: 3, + isElement: false, + name: 'qux', + }, + directives: [], + element: '#comment', + nativeElement: document.createComment('bar'), + }, + ], + nativeElement: document.createElement('foo'), +}; + +describe('ComponentDataSource', () => { + let dataSource: ComponentDataSource; + const treeControl = new FlatTreeControl( + (node) => node.level, + (node) => node.expandable + ); + + beforeEach(() => (dataSource = new ComponentDataSource(treeControl))); + + it('should return new and old items', () => { + const result = dataSource.update([tree1], true); + expect(result.movedItems.length).toBe(0); + expect(result.newItems.length).toBe(2); + + const updatedResult = dataSource.update([tree2], true); + expect(updatedResult.movedItems.length).toBe(0); + expect(updatedResult.removedItems.length).toBe(0); + expect(updatedResult.newItems.length).toBe(1); + expect(updatedResult.newItems[0].name).toBe('qux'); + }); + + it('should not return comment nodes when not requested', () => { + const result = dataSource.update([tree3], false); + expect(result.movedItems.length).toBe(0); + expect(result.newItems.length).toBe(1); + expect(result.newItems[0].name).toBe('app'); + }); +}); diff --git a/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-forest/component-data-source.ts b/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-forest/component-data-source.ts index 3ab9134db21..886ebae6b4d 100644 --- a/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-forest/component-data-source.ts +++ b/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-forest/component-data-source.ts @@ -84,13 +84,20 @@ export class ComponentDataSource extends DataSource { return this._nodeToFlat.get(indexedNode); } - update(forest: DevToolsNode[]): { newItems: FlatNode[]; movedItems: FlatNode[]; removedItems: FlatNode[] } { + update( + forest: DevToolsNode[], + showCommentNodes: boolean + ): { newItems: FlatNode[]; movedItems: FlatNode[]; removedItems: FlatNode[] } { if (!forest) { return { newItems: [], movedItems: [], removedItems: [] }; } const indexedForest = indexForest(forest); - const flattenedCollection = this._treeFlattener.flattenNodes(indexedForest) as FlatNode[]; + let flattenedCollection = this._treeFlattener.flattenNodes(indexedForest) as FlatNode[]; + + if (!showCommentNodes) { + flattenedCollection = flattenedCollection.filter((node) => node.original.element !== '#comment'); + } this.data.forEach((i) => (i.newItem = false)); diff --git a/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-forest/directive-forest.component.ts b/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-forest/directive-forest.component.ts index 44433f726ae..5990b2819dd 100644 --- a/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-forest/directive-forest.component.ts +++ b/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-forest/directive-forest.component.ts @@ -27,6 +27,7 @@ import { Subscription } from 'rxjs'; }) export class DirectiveForestComponent implements OnInit, OnDestroy { @Input() set forest(forest: DevToolsNode[]) { + this._latestForest = forest; const result = this._updateForest(forest); const changed = result.movedItems.length || result.newItems.length || result.removedItems.length; if (this.currentSelectedElement && changed) { @@ -34,6 +35,10 @@ export class DirectiveForestComponent implements OnInit, OnDestroy { } } @Input() currentSelectedElement: IndexedNode; + @Input() set showCommentNodes(show: boolean) { + this._showCommentNodes = show; + this.forest = this._latestForest; + } @Output() selectNode = new EventEmitter(); @Output() selectDomElement = new EventEmitter(); @@ -52,6 +57,8 @@ export class DirectiveForestComponent implements OnInit, OnDestroy { private _highlightIDinTreeFromElement: number | null = null; private _tabUpdateSubscription: Subscription; + private _showCommentNodes = false; + private _latestForest: DevToolsNode[]; set highlightIDinTreeFromElement(id: number | null) { this._highlightIDinTreeFromElement = id; @@ -169,7 +176,7 @@ export class DirectiveForestComponent implements OnInit, OnDestroy { private _updateForest( forest: DevToolsNode[] ): { newItems: FlatNode[]; movedItems: FlatNode[]; removedItems: FlatNode[] } { - const result = this.dataSource.update(forest); + const result = this.dataSource.update(forest, this._showCommentNodes); if (!this._initialized && forest && forest.length) { this.treeControl.expandAll(); this._initialized = true;