| // Copyright 2017 The Chromium Authors. All | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | /** | 
 |  * @fileoverview using private properties isn't a Closure violation in tests. | 
 |  * @suppress {accessControls} | 
 |  */ | 
 |  | 
 | /** | 
 |  * @param jsCoveragePerBlock - Collect per Block coverage if `true`, per function coverage otherwise. | 
 |  * @return {!Promise} | 
 |  */ | 
 | CoverageTestRunner.startCoverage = async function(jsCoveragePerBlock) { | 
 |   UI.viewManager.showView('coverage'); | 
 |   const coverageView = self.runtime.sharedInstance(Coverage.CoverageView); | 
 |   await coverageView._startRecording({reload: false, jsCoveragePerBlock}); | 
 | }; | 
 |  | 
 | /** | 
 |  * @return {!Promise} | 
 |  */ | 
 | CoverageTestRunner.stopCoverage = function() { | 
 |   const coverageView = self.runtime.sharedInstance(Coverage.CoverageView); | 
 |   return coverageView.stopRecording(); | 
 | }; | 
 |  | 
 | /** | 
 |  * @return {!Promise} | 
 |  */ | 
 | CoverageTestRunner.suspendCoverageModel = async function() { | 
 |   const coverageView = self.runtime.sharedInstance(Coverage.CoverageView); | 
 |   await coverageView._model.preSuspendModel(); | 
 |   await coverageView._model.suspendModel(); | 
 | }; | 
 |  | 
 | /** | 
 |  * @return {!Promise} | 
 |  */ | 
 | CoverageTestRunner.resumeCoverageModel = async function() { | 
 |   const coverageView = self.runtime.sharedInstance(Coverage.CoverageView); | 
 |   await coverageView._model.resumeModel(); | 
 |   await coverageView._model.postResumeModel(); | 
 | }; | 
 |  | 
 | /** | 
 |  * @return {!Promise} | 
 |  */ | 
 | CoverageTestRunner.pollCoverage = async function() { | 
 |   const coverageView = self.runtime.sharedInstance(Coverage.CoverageView); | 
 |   // Make sure not to have two instances of _pollAndCallback running at the same time. | 
 |   await coverageView._model._currentPollPromise; | 
 |   return coverageView._model._pollAndCallback(); | 
 | }; | 
 |  | 
 | /** | 
 |  * @return {!Promise<Coverage.CoverageModel>} | 
 |  */ | 
 | CoverageTestRunner.getCoverageModel = function() { | 
 |   const coverageView = self.runtime.sharedInstance(Coverage.CoverageView); | 
 |   return coverageView._model; | 
 | }; | 
 |  | 
 | /** | 
 |  * @return {!Promise<string>} | 
 |  */ | 
 | CoverageTestRunner.exportReport = async function() { | 
 |   const coverageView = self.runtime.sharedInstance(Coverage.CoverageView); | 
 |   let data; | 
 |   await coverageView._model.exportReport({write: d => data = d, close: _ => 0}); | 
 |   return data; | 
 | }; | 
 |  | 
 | /** | 
 |  * @return {!Promise<!SourceFrame.SourceFrame>} | 
 |  */ | 
 | CoverageTestRunner.sourceDecorated = async function(source) { | 
 |   await UI.inspectorView.showPanel('sources'); | 
 |   const decoratePromise = TestRunner.addSnifferPromise(Coverage.CoverageView.LineDecorator.prototype, '_innerDecorate'); | 
 |   const sourceFrame = await SourcesTestRunner.showScriptSourcePromise(source); | 
 |   await decoratePromise; | 
 |   return sourceFrame; | 
 | }; | 
 |  | 
 | CoverageTestRunner.dumpDecorations = async function(source) { | 
 |   const sourceFrame = await CoverageTestRunner.sourceDecorated(source); | 
 |   CoverageTestRunner.dumpDecorationsInSourceFrame(sourceFrame); | 
 | }; | 
 |  | 
 | /** | 
 |  * @return {?DataGrid.DataGridNode} | 
 |  */ | 
 | CoverageTestRunner.findCoverageNodeForURL = function(url) { | 
 |   const coverageListView = self.runtime.sharedInstance(Coverage.CoverageView)._listView; | 
 |   const rootNode = coverageListView._dataGrid.rootNode(); | 
 |  | 
 |   for (const child of rootNode.children) { | 
 |     if (child._coverageInfo.url().endsWith(url)) { | 
 |       return child; | 
 |     } | 
 |   } | 
 |  | 
 |   return null; | 
 | }; | 
 |  | 
 | CoverageTestRunner.dumpDecorationsInSourceFrame = function(sourceFrame) { | 
 |   const markerMap = new Map([['used', '+'], ['unused', '-']]); | 
 |   const codeMirror = sourceFrame.textEditor.codeMirror(); | 
 |  | 
 |   for (let line = 0; line < codeMirror.lineCount(); ++line) { | 
 |     const text = codeMirror.getLine(line); | 
 |     let markerType = ' '; | 
 |     const lineInfo = codeMirror.lineInfo(line); | 
 |  | 
 |     if (!lineInfo) { | 
 |       continue; | 
 |     } | 
 |  | 
 |     const gutterElement = lineInfo.gutterMarkers && lineInfo.gutterMarkers['CodeMirror-gutter-coverage']; | 
 |  | 
 |     if (gutterElement) { | 
 |       const markerClass = /^text-editor-coverage-(\w*)-marker$/.exec(gutterElement.classList)[1]; | 
 |       markerType = markerMap.get(markerClass) || gutterElement.classList; | 
 |     } | 
 |  | 
 |     TestRunner.addResult(`${line}: ${markerType} ${text}`); | 
 |   } | 
 | }; | 
 |  | 
 | CoverageTestRunner.dumpCoverageListView = function() { | 
 |   const coverageListView = self.runtime.sharedInstance(Coverage.CoverageView)._listView; | 
 |   const dataGrid = coverageListView._dataGrid; | 
 |   dataGrid.updateInstantly(); | 
 |  | 
 |   for (const child of dataGrid.rootNode().children) { | 
 |     const data = child._coverageInfo; | 
 |     const url = TestRunner.formatters.formatAsURL(data.url()); | 
 |  | 
 |     if (url.startsWith('test://')) { | 
 |       continue; | 
 |     } | 
 |  | 
 |     const type = Coverage.CoverageListView._typeToString(data.type()); | 
 |     TestRunner.addResult(`${url} ${type} used: ${data.usedSize()} unused: ${data.unusedSize()} total: ${data.size()}`); | 
 |   } | 
 | }; |