1*61c4878aSAndroid Build Coastguard Worker// Copyright 2024 The Pigweed Authors 2*61c4878aSAndroid Build Coastguard Worker// 3*61c4878aSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); you may not 4*61c4878aSAndroid Build Coastguard Worker// use this file except in compliance with the License. You may obtain a copy of 5*61c4878aSAndroid Build Coastguard Worker// the License at 6*61c4878aSAndroid Build Coastguard Worker// 7*61c4878aSAndroid Build Coastguard Worker// https://www.apache.org/licenses/LICENSE-2.0 8*61c4878aSAndroid Build Coastguard Worker// 9*61c4878aSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*61c4878aSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11*61c4878aSAndroid Build Coastguard Worker// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12*61c4878aSAndroid Build Coastguard Worker// License for the specific language governing permissions and limitations under 13*61c4878aSAndroid Build Coastguard Worker// the License. 14*61c4878aSAndroid Build Coastguard Worker 15*61c4878aSAndroid Build Coastguard Workerimport { MockLogSource } from '../src/custom/mock-log-source'; 16*61c4878aSAndroid Build Coastguard Workerimport { createLogViewer } from '../src/createLogViewer'; 17*61c4878aSAndroid Build Coastguard Workerimport { expect } from '@open-wc/testing'; 18*61c4878aSAndroid Build Coastguard Workerimport { LocalStateStorage, StateService } from '../src/shared/state'; 19*61c4878aSAndroid Build Coastguard Workerimport { NodeType, Orientation, ViewNode } from '../src/shared/view-node'; 20*61c4878aSAndroid Build Coastguard Worker 21*61c4878aSAndroid Build Coastguard Workerfunction setUpLogViewer() { 22*61c4878aSAndroid Build Coastguard Worker const mockLogSource = new MockLogSource(); 23*61c4878aSAndroid Build Coastguard Worker const destroyLogViewer = createLogViewer(mockLogSource, document.body); 24*61c4878aSAndroid Build Coastguard Worker const logViewer = document.querySelector('log-viewer'); 25*61c4878aSAndroid Build Coastguard Worker return { mockLogSource, destroyLogViewer, logViewer }; 26*61c4878aSAndroid Build Coastguard Worker} 27*61c4878aSAndroid Build Coastguard Worker 28*61c4878aSAndroid Build Coastguard Worker// Handle benign ResizeObserver error caused by custom log viewer initialization 29*61c4878aSAndroid Build Coastguard Worker// See: https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#observation_errors 30*61c4878aSAndroid Build Coastguard Workerfunction handleResizeObserverError() { 31*61c4878aSAndroid Build Coastguard Worker const e = window.onerror; 32*61c4878aSAndroid Build Coastguard Worker window.onerror = function (err) { 33*61c4878aSAndroid Build Coastguard Worker if ( 34*61c4878aSAndroid Build Coastguard Worker err === 'ResizeObserver loop completed with undelivered notifications.' 35*61c4878aSAndroid Build Coastguard Worker ) { 36*61c4878aSAndroid Build Coastguard Worker console.warn( 37*61c4878aSAndroid Build Coastguard Worker 'Ignored: ResizeObserver loop completed with undelivered notifications.', 38*61c4878aSAndroid Build Coastguard Worker ); 39*61c4878aSAndroid Build Coastguard Worker return false; 40*61c4878aSAndroid Build Coastguard Worker } else { 41*61c4878aSAndroid Build Coastguard Worker return e(...arguments); 42*61c4878aSAndroid Build Coastguard Worker } 43*61c4878aSAndroid Build Coastguard Worker }; 44*61c4878aSAndroid Build Coastguard Worker} 45*61c4878aSAndroid Build Coastguard Worker 46*61c4878aSAndroid Build Coastguard Workerdescribe('log-view-controls', () => { 47*61c4878aSAndroid Build Coastguard Worker let mockLogSource; 48*61c4878aSAndroid Build Coastguard Worker let destroyLogViewer; 49*61c4878aSAndroid Build Coastguard Worker let logViewer; 50*61c4878aSAndroid Build Coastguard Worker let mockColumnData; 51*61c4878aSAndroid Build Coastguard Worker let mockState; 52*61c4878aSAndroid Build Coastguard Worker let stateService; 53*61c4878aSAndroid Build Coastguard Worker 54*61c4878aSAndroid Build Coastguard Worker before(() => { 55*61c4878aSAndroid Build Coastguard Worker mockColumnData = [ 56*61c4878aSAndroid Build Coastguard Worker { 57*61c4878aSAndroid Build Coastguard Worker fieldName: 'test', 58*61c4878aSAndroid Build Coastguard Worker characterLength: 0, 59*61c4878aSAndroid Build Coastguard Worker manualWidth: null, 60*61c4878aSAndroid Build Coastguard Worker isVisible: false, 61*61c4878aSAndroid Build Coastguard Worker }, 62*61c4878aSAndroid Build Coastguard Worker { 63*61c4878aSAndroid Build Coastguard Worker fieldName: 'foo', 64*61c4878aSAndroid Build Coastguard Worker characterLength: 0, 65*61c4878aSAndroid Build Coastguard Worker manualWidth: null, 66*61c4878aSAndroid Build Coastguard Worker isVisible: true, 67*61c4878aSAndroid Build Coastguard Worker }, 68*61c4878aSAndroid Build Coastguard Worker { 69*61c4878aSAndroid Build Coastguard Worker fieldName: 'bar', 70*61c4878aSAndroid Build Coastguard Worker characterLength: 0, 71*61c4878aSAndroid Build Coastguard Worker manualWidth: null, 72*61c4878aSAndroid Build Coastguard Worker isVisible: false, 73*61c4878aSAndroid Build Coastguard Worker }, 74*61c4878aSAndroid Build Coastguard Worker ]; 75*61c4878aSAndroid Build Coastguard Worker mockState = { 76*61c4878aSAndroid Build Coastguard Worker rootNode: new ViewNode({ 77*61c4878aSAndroid Build Coastguard Worker type: NodeType.Split, 78*61c4878aSAndroid Build Coastguard Worker orientation: Orientation.Horizontal, 79*61c4878aSAndroid Build Coastguard Worker children: [ 80*61c4878aSAndroid Build Coastguard Worker new ViewNode({ 81*61c4878aSAndroid Build Coastguard Worker searchText: 'hello', 82*61c4878aSAndroid Build Coastguard Worker logViewId: 'child-node-1', 83*61c4878aSAndroid Build Coastguard Worker type: NodeType.View, 84*61c4878aSAndroid Build Coastguard Worker columnData: mockColumnData, 85*61c4878aSAndroid Build Coastguard Worker }), 86*61c4878aSAndroid Build Coastguard Worker new ViewNode({ 87*61c4878aSAndroid Build Coastguard Worker searchText: 'world', 88*61c4878aSAndroid Build Coastguard Worker logViewId: 'child-node-2', 89*61c4878aSAndroid Build Coastguard Worker type: NodeType.View, 90*61c4878aSAndroid Build Coastguard Worker columnData: mockColumnData, 91*61c4878aSAndroid Build Coastguard Worker }), 92*61c4878aSAndroid Build Coastguard Worker ], 93*61c4878aSAndroid Build Coastguard Worker }), 94*61c4878aSAndroid Build Coastguard Worker }; 95*61c4878aSAndroid Build Coastguard Worker 96*61c4878aSAndroid Build Coastguard Worker stateService = new StateService(new LocalStateStorage()); 97*61c4878aSAndroid Build Coastguard Worker stateService.saveState(mockState); 98*61c4878aSAndroid Build Coastguard Worker handleResizeObserverError(); 99*61c4878aSAndroid Build Coastguard Worker }); 100*61c4878aSAndroid Build Coastguard Worker 101*61c4878aSAndroid Build Coastguard Worker after(() => { 102*61c4878aSAndroid Build Coastguard Worker window.localStorage.clear(); 103*61c4878aSAndroid Build Coastguard Worker mockLogSource.stop(); 104*61c4878aSAndroid Build Coastguard Worker destroyLogViewer(); 105*61c4878aSAndroid Build Coastguard Worker }); 106*61c4878aSAndroid Build Coastguard Worker 107*61c4878aSAndroid Build Coastguard Worker describe('state', () => { 108*61c4878aSAndroid Build Coastguard Worker it('should populate search field value on component load', async () => { 109*61c4878aSAndroid Build Coastguard Worker ({ mockLogSource, destroyLogViewer, logViewer } = setUpLogViewer()); 110*61c4878aSAndroid Build Coastguard Worker const logViews = await getLogViews(); 111*61c4878aSAndroid Build Coastguard Worker const stateSearchString = 112*61c4878aSAndroid Build Coastguard Worker mockState.rootNode.children[0].logViewState.searchText; 113*61c4878aSAndroid Build Coastguard Worker const logControls = 114*61c4878aSAndroid Build Coastguard Worker logViews[0].shadowRoot.querySelector('log-view-controls'); 115*61c4878aSAndroid Build Coastguard Worker logControls.requestUpdate(); 116*61c4878aSAndroid Build Coastguard Worker const inputEl = logControls.shadowRoot.querySelector('.search-field'); 117*61c4878aSAndroid Build Coastguard Worker 118*61c4878aSAndroid Build Coastguard Worker await logViewer.updateComplete; 119*61c4878aSAndroid Build Coastguard Worker expect(inputEl.value).to.equal(stateSearchString); 120*61c4878aSAndroid Build Coastguard Worker }); 121*61c4878aSAndroid Build Coastguard Worker 122*61c4878aSAndroid Build Coastguard Worker it('should populate search field values for multiple log views on component load', async () => { 123*61c4878aSAndroid Build Coastguard Worker ({ mockLogSource, destroyLogViewer, logViewer } = setUpLogViewer()); 124*61c4878aSAndroid Build Coastguard Worker 125*61c4878aSAndroid Build Coastguard Worker const state = stateService.loadState(); 126*61c4878aSAndroid Build Coastguard Worker const logViews = await getLogViews(); 127*61c4878aSAndroid Build Coastguard Worker const searchInputs = []; 128*61c4878aSAndroid Build Coastguard Worker 129*61c4878aSAndroid Build Coastguard Worker logViews.forEach((logView) => { 130*61c4878aSAndroid Build Coastguard Worker const logControls = 131*61c4878aSAndroid Build Coastguard Worker logView.shadowRoot.querySelector('log-view-controls'); 132*61c4878aSAndroid Build Coastguard Worker const inputEl = logControls.shadowRoot.querySelector('.search-field'); 133*61c4878aSAndroid Build Coastguard Worker searchInputs.push(inputEl.value); 134*61c4878aSAndroid Build Coastguard Worker }); 135*61c4878aSAndroid Build Coastguard Worker 136*61c4878aSAndroid Build Coastguard Worker state.rootNode.children.forEach((childNode, index) => { 137*61c4878aSAndroid Build Coastguard Worker expect(childNode.logViewState.searchText).to.equal(searchInputs[index]); 138*61c4878aSAndroid Build Coastguard Worker }); 139*61c4878aSAndroid Build Coastguard Worker }); 140*61c4878aSAndroid Build Coastguard Worker 141*61c4878aSAndroid Build Coastguard Worker it('should recall table column visibility on component load', async () => { 142*61c4878aSAndroid Build Coastguard Worker ({ mockLogSource, destroyLogViewer, logViewer } = setUpLogViewer()); 143*61c4878aSAndroid Build Coastguard Worker 144*61c4878aSAndroid Build Coastguard Worker const state = stateService.loadState(); 145*61c4878aSAndroid Build Coastguard Worker const logViews = await getLogViews(); 146*61c4878aSAndroid Build Coastguard Worker const logControls = 147*61c4878aSAndroid Build Coastguard Worker logViews[0].shadowRoot.querySelector('log-view-controls'); 148*61c4878aSAndroid Build Coastguard Worker const colToggleMenu = logControls.shadowRoot 149*61c4878aSAndroid Build Coastguard Worker .querySelector('#col-toggle-menu') 150*61c4878aSAndroid Build Coastguard Worker .querySelectorAll('.item-checkbox'); 151*61c4878aSAndroid Build Coastguard Worker 152*61c4878aSAndroid Build Coastguard Worker colToggleMenu.forEach((field, index) => { 153*61c4878aSAndroid Build Coastguard Worker const columnData = state.rootNode.children[0].logViewState.columnData; 154*61c4878aSAndroid Build Coastguard Worker expect(field.checked).to.equal(columnData[index].isVisible); 155*61c4878aSAndroid Build Coastguard Worker }); 156*61c4878aSAndroid Build Coastguard Worker 157*61c4878aSAndroid Build Coastguard Worker const colToggleSubMenu = logControls.shadowRoot 158*61c4878aSAndroid Build Coastguard Worker .querySelector('#col-toggle-sub-menu') 159*61c4878aSAndroid Build Coastguard Worker .querySelectorAll('.item-checkbox'); 160*61c4878aSAndroid Build Coastguard Worker 161*61c4878aSAndroid Build Coastguard Worker colToggleSubMenu.forEach((field, index) => { 162*61c4878aSAndroid Build Coastguard Worker const columnData = state.rootNode.children[0].logViewState.columnData; 163*61c4878aSAndroid Build Coastguard Worker expect(field.checked).to.equal(columnData[index].isVisible); 164*61c4878aSAndroid Build Coastguard Worker }); 165*61c4878aSAndroid Build Coastguard Worker }); 166*61c4878aSAndroid Build Coastguard Worker 167*61c4878aSAndroid Build Coastguard Worker async function getLogViews() { 168*61c4878aSAndroid Build Coastguard Worker const logViewerEl = document.querySelector('log-viewer'); 169*61c4878aSAndroid Build Coastguard Worker await logViewerEl.updateComplete; 170*61c4878aSAndroid Build Coastguard Worker await new Promise((resolve) => setTimeout(resolve, 100)); 171*61c4878aSAndroid Build Coastguard Worker const logViews = logViewerEl.shadowRoot.querySelectorAll('log-view'); 172*61c4878aSAndroid Build Coastguard Worker return logViews; 173*61c4878aSAndroid Build Coastguard Worker } 174*61c4878aSAndroid Build Coastguard Worker }); 175*61c4878aSAndroid Build Coastguard Worker}); 176