UNPKG

@salesforce/salesforcedx-vscode-test-tools

Version:
202 lines 10.6 kB
"use strict"; /* * Copyright (c) 2025, salesforce.com, inc. * All rights reserved. * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.selectOutputChannel = selectOutputChannel; exports.getOutputViewText = getOutputViewText; exports.verifyOutputPanelText = verifyOutputPanelText; exports.attemptToFindOutputPanelText = attemptToFindOutputPanelText; exports.getOperationTime = getOperationTime; exports.clearOutputView = clearOutputView; const miscellaneous_1 = require("../core/miscellaneous"); const notifications_1 = require("./notifications"); const commandPrompt_1 = require("./commandPrompt"); const vscode_extension_tester_1 = require("vscode-extension-tester"); const chai_1 = require("chai"); const retryUtils_1 = require("../retryUtils"); async function selectOutputChannel(name) { // Wait for all notifications to go away. If there is a notification that is overlapping and hiding the Output channel's // dropdown menu, calling select.click() doesn't work, so dismiss all notifications first before clicking the dropdown // menu and opening it. await (0, notifications_1.dismissAllNotifications)(); // Find the given channel in the Output view const outputView = await new vscode_extension_tester_1.BottomBarPanel().openOutputView(); await (0, miscellaneous_1.pause)(miscellaneous_1.Duration.seconds(1)); if (!!name) { await outputView.selectChannel(name); } return outputView; } async function getOutputViewText(outputChannelName = '') { // Set the output channel, but only if the value is passed in. const outputView = await selectOutputChannel(outputChannelName); // Set focus to the contents in the Output panel. await (0, commandPrompt_1.executeQuickPick)('Output: Focus on Output View', miscellaneous_1.Duration.seconds(2)); try { return await outputView.getText(); } catch (error) { // Fallback when outputView.getText() fails (0, miscellaneous_1.log)(`outputView.getText() failed, trying fallback selector: ${error.message}`); const clipboard = (await Promise.resolve().then(() => __importStar(require('clipboardy')))).default; let originalClipboard = ''; try { originalClipboard = clipboard.readSync(); } catch (clipboardError) { // workaround issue when clipboard is empty } try { // Try to find the textarea using the fallback selector const textarea = await outputView.findElement(vscode_extension_tester_1.By.css('.inputarea.monaco-mouse-cursor-text, .inputarea textarea, .monaco-editor textarea')); // Select all text and copy to clipboard await textarea.sendKeys(vscode_extension_tester_1.Key.chord(process.platform === 'darwin' ? vscode_extension_tester_1.Key.META : vscode_extension_tester_1.Key.CONTROL, 'a')); await textarea.sendKeys(vscode_extension_tester_1.Key.chord(process.platform === 'darwin' ? vscode_extension_tester_1.Key.META : vscode_extension_tester_1.Key.CONTROL, 'c')); const text = clipboard.readSync(); // Restore original clipboard content if (originalClipboard.length > 0) { clipboard.writeSync(originalClipboard); } return text; } catch (fallbackError) { (0, miscellaneous_1.log)(`Fallback getText also failed: ${fallbackError.message}`); // If fallback also fails, rethrow the original error throw error; } } } /** * Verifies that the output panel contains all expected text snippets. * * @param {string} outputPanelText - The output panel text as a string that needs to be verified. * @param {string[]} expectedTexts - An array of strings representing the expected text snippets that should be present in the output panel. * * @example * await verifyOutputPanelText( * testResult, * [ * '=== Test Summary', * 'Outcome Passed', * 'Tests Ran 1', * 'Pass Rate 100%', * 'TEST NAME', * 'ExampleTest1 Pass', * 'Ended SFDX: Run Apex Tests' * ] * ); */ async function verifyOutputPanelText(outputPanelText, expectedTexts) { (0, miscellaneous_1.log)(`verifyOutputPanelText() - ${outputPanelText}`); for (const expectedText of expectedTexts) { (0, miscellaneous_1.log)(`Expected text:\n ${expectedText}`); (0, chai_1.expect)(outputPanelText).to.include(expectedText); } } // If found, this function returns the entire text that's in the Output panel. async function attemptToFindOutputPanelText(outputChannelName, searchString, attempts = 10) { (0, miscellaneous_1.log)(`attemptToFindOutputPanelText in channel "${outputChannelName}: with string "${searchString}"`); return await (0, retryUtils_1.retryOperation)(async () => { const outputViewText = await getOutputViewText(outputChannelName); (0, miscellaneous_1.log)(`outputViewText:\n ${outputViewText}`); if (outputViewText.includes(searchString)) { return outputViewText; } await (0, miscellaneous_1.pause)(miscellaneous_1.Duration.seconds(2)); throw new Error(`Failed to find output panel text: ${searchString} in ${outputChannelName} on attempt ${attempts}`); }, attempts, 'Failed to find output panel text'); } async function getOperationTime(outputText) { const tRegex = /((?<hours>\d+):(?<minutes>\d+):(?<seconds>\d+)(?<secondFraction>\.\d+))/g; let matches; const times = []; while ((matches = tRegex.exec(outputText)) !== null) { if (matches.groups) { const { hours, minutes, seconds, secondFraction } = matches.groups; const time = new Date(1970, 0, 1, Number(hours), Number(minutes), Number(seconds), Number(secondFraction) * 1000); times.push(time); } } if (times.length < 2) { return 'Insufficient timestamps found.'; } const [startTime, endTime] = times; let diff = endTime.getTime() - startTime.getTime(); const hours = Math.floor(diff / 3600000); // 1000 * 60 * 60 diff %= 3600000; const minutes = Math.floor(diff / 60000); // 1000 * 60 diff %= 60000; const seconds = Math.floor(diff / 1000); const milliseconds = diff % 1000; return `${formatTimeComponent(hours)}:${formatTimeComponent(minutes)}:${formatTimeComponent(seconds)}.${formatTimeComponent(milliseconds, 3)}`; } async function clearOutputView(wait = miscellaneous_1.Duration.seconds(1)) { if (process.platform === 'linux') { // In Linux, clear the output by clicking the "Clear Output" button in the Output Tab // Use retry logic with longer wait for Linux due to timing issues (0, miscellaneous_1.log)('clearOutputView() - Linux: Attempting to find and click clear button with retries'); await (0, retryUtils_1.retryOperation)(async () => { (0, miscellaneous_1.log)('clearOutputView() - Linux: Looking for clear button...'); const outputView = await new vscode_extension_tester_1.BottomBarPanel().openOutputView(); // Wait a bit longer for UI to be ready on Linux await (0, miscellaneous_1.pause)(miscellaneous_1.Duration.seconds(2)); const clearButton = await outputView.findElement(vscode_extension_tester_1.By.className('codicon-clear-all')); (0, miscellaneous_1.log)('clearOutputView() - Linux: Clear button found, attempting to click'); // Try multiple click methods for better Linux compatibility try { await outputView.getDriver().executeScript('arguments[0].click();', clearButton); (0, miscellaneous_1.log)('clearOutputView() - Linux: Click via executeScript successful'); } catch (scriptError) { (0, miscellaneous_1.log)(`clearOutputView() - Linux: executeScript failed, trying direct click: ${scriptError}`); await clearButton.click(); (0, miscellaneous_1.log)('clearOutputView() - Linux: Direct click successful'); } // Wait a moment to ensure the action completes await (0, miscellaneous_1.pause)(miscellaneous_1.Duration.seconds(1)); // Verify the output was actually cleared by checking if there's minimal content const outputText = await outputView.getText(); if (outputText.trim().length > 100) { (0, miscellaneous_1.log)(`clearOutputView() - Linux: Output not cleared (${outputText.length} chars), retrying...`); throw new Error('Output view was not cleared successfully'); } (0, miscellaneous_1.log)('clearOutputView() - Linux: Output cleared successfully'); }, 3, 'Failed to clear output view on Linux after retries'); } else { // In Mac and Windows, clear the output by calling the "View: Clear Output" command in the command palette (0, miscellaneous_1.log)('clearOutputView() - Mac/Windows: Using command palette to clear output'); await (0, commandPrompt_1.executeQuickPick)('View: Clear Output', wait); } } function formatTimeComponent(component, padLength = 2) { return component.toString().padStart(padLength, '0'); } //# sourceMappingURL=outputView.js.map