UNPKG

@salesforce/salesforcedx-vscode-test-tools

Version:
334 lines 16.3 kB
"use strict"; /* * Copyright (c) 2024, 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 */ Object.defineProperty(exports, "__esModule", { value: true }); exports.setSettingValue = void 0; exports.inWorkspaceSettings = inWorkspaceSettings; exports.inUserSettings = inUserSettings; exports.enableBooleanSetting = enableBooleanSetting; exports.disableBooleanSetting = disableBooleanSetting; exports.isBooleanSettingEnabled = isBooleanSettingEnabled; const vscode_extension_tester_1 = require("vscode-extension-tester"); const commandPrompt_1 = require("../ui-interaction/commandPrompt"); const miscellaneous_1 = require("../core/miscellaneous"); const workbench_1 = require("../ui-interaction/workbench"); /** * Finds a setting in VSCode settings UI and checks its value * @param id - The ID of the setting to find * @returns Object containing the setting and its current value * @throws Error if the setting cannot be found * @private */ async function findAndCheckSetting(id) { (0, miscellaneous_1.log)(`enter findAndCheckSetting for id: ${id}`); await (0, commandPrompt_1.executeQuickPick)('Preferences: Clear Settings Search Results', miscellaneous_1.Duration.seconds(2)); try { const input = await (0, workbench_1.getBrowser)().findElement(vscode_extension_tester_1.By.css('div.suggest-input-container')); await input.click(); const textArea = await (0, workbench_1.getBrowser)().findElement(vscode_extension_tester_1.By.css('textarea.inputarea.monaco-mouse-cursor-text')); await textArea.sendKeys(id); await (0, miscellaneous_1.pause)(miscellaneous_1.Duration.seconds(2)); let checkButton = null; let checkButtonValue = null; await (0, workbench_1.getBrowser)().wait(async () => { checkButton = (await (0, miscellaneous_1.findElementByText)('div', 'aria-label', id)); if (checkButton) { checkButtonValue = await checkButton.getAttribute('aria-checked'); (0, miscellaneous_1.log)(`found setting checkbox with value "${checkButtonValue}"`); return true; } return false; }, 5000, `Could not find setting with name: ${id}`); if (!checkButton) { throw new Error(`Could not find setting with name: ${id}`); } (0, miscellaneous_1.log)(`findAndCheckSetting result for ${id} found ${!!checkButton} value: ${checkButtonValue}`); return { checkButton, checkButtonValue }; } catch (error) { (0, miscellaneous_1.log)(`error in findAndCheckSetting for ${id}: ${error}`); (0, miscellaneous_1.log)(`trying to find setting by id: ${id}`); const settingsEditor = new vscode_extension_tester_1.SettingsEditor(); const setting = await settingsEditor.findSettingByID(id); (0, miscellaneous_1.log)(`found setting by id: ${id} ${setting}`); return { checkButton: setting, checkButtonValue: String(await setting.getValue()) }; } } /** * Opens the workspace settings editor */ async function inWorkspaceSettings() { await (0, commandPrompt_1.executeQuickPick)('Preferences: Open Workspace Settings', miscellaneous_1.Duration.seconds(5)); } /** * Opens the user settings editor */ async function inUserSettings() { await (0, commandPrompt_1.executeQuickPick)('Preferences: Open User Settings', miscellaneous_1.Duration.seconds(5)); } /** * Toggles a boolean setting to the specified state * @param id - The ID of the setting to toggle * @param finalState - The desired final state (true for enabled, false for disabled) * @param settingsType - Whether to modify user or workspace settings * @returns The final state of the setting after toggling * @private */ async function toggleBooleanSetting(id, finalState, settingsType) { const settingsFunction = settingsType === 'workspace' ? inWorkspaceSettings : inUserSettings; await settingsFunction(); let result = await findAndCheckSetting(id); if (finalState !== undefined) { if ((finalState && result.checkButtonValue === 'true') || (!finalState && result.checkButtonValue === 'false')) { return true; } } await result.checkButton.click(); result = await findAndCheckSetting(id); return result.checkButtonValue === 'true'; } /** * Enables a boolean setting * @param id - The ID of the setting to enable * @param settingsType - Whether to modify user or workspace settings, defaults to workspace * @returns True if the setting was successfully enabled */ async function enableBooleanSetting(id, settingsType = 'workspace') { (0, miscellaneous_1.log)(`enableBooleanSetting ${id}`); return toggleBooleanSetting(id, true, settingsType); } /** * Disables a boolean setting * @param id - The ID of the setting to disable * @param settingsType - Whether to modify user or workspace settings, defaults to workspace * @returns True if the setting was successfully disabled */ async function disableBooleanSetting(id, settingsType = 'workspace') { (0, miscellaneous_1.log)(`disableBooleanSetting ${id}`); return toggleBooleanSetting(id, false, settingsType); } /** * Checks if a boolean setting is enabled * @param id - The ID of the setting to check * @param settingsType - Whether to check user or workspace settings, defaults to workspace * @returns True if the setting is enabled, false otherwise */ async function isBooleanSettingEnabled(id, settingsType = 'workspace') { const settingsFunction = settingsType === 'workspace' ? inWorkspaceSettings : inUserSettings; await settingsFunction(); const { checkButtonValue } = await findAndCheckSetting(id); return checkButtonValue === 'true'; } /** * Sets the value of a specified setting in VSCode. * @param id - The unique identifier of the setting to be updated. * @param value - The new value to set for the specified setting. * @param isWorkspace - True if the setting is a workspace setting; false if it's a user setting. * @returns A promise that resolves when the setting value has been updated. */ const setSettingValue = async (id, value, isWorkspace) => { await (isWorkspace ? inWorkspaceSettings() : inUserSettings()); try { // Try the original implementation using RedHat page objects const settingsEditor = new vscode_extension_tester_1.SettingsEditor(); const logLevelSetting = await settingsEditor.findSettingByID(id); await logLevelSetting?.setValue(value); } catch (error) { // Fallback for VS Code 1.90.0+ where .native-edit-context selector doesn't exist (0, miscellaneous_1.log)(`Primary findSettingByID failed, using fallback implementation for VS Code 1.90.0+: ${error}`); try { const browser = (0, workbench_1.getBrowser)(); // Alternative selectors for the search input in newer VS Code versions const searchSelectors = [ '.inputarea.monaco-mouse-cursor-text', 'input[placeholder*="Search settings"]', ]; let searchInput; for (const selector of searchSelectors) { try { searchInput = await browser.findElement(vscode_extension_tester_1.By.css(selector)); break; } catch { // Try next selector } } if (!searchInput) { throw new Error('Could not find settings search input with any known selector'); } // Clear and search for the setting await searchInput.clear(); await searchInput.sendKeys(id); await (0, miscellaneous_1.pause)(miscellaneous_1.Duration.seconds(1)); // Find the setting by its title (last part of the ID) using robust approach const title = id.split('.').pop(); let settingElement; // Wait for settings to load and stabilize await (0, miscellaneous_1.pause)(miscellaneous_1.Duration.seconds(1)); // Try to find setting items using multiple selector approaches const itemSelectors = [ '.setting-item', '.settings-row-inner-container', '.setting-list-item', '[data-key]' ]; let items = []; for (const selector of itemSelectors) { try { items = await browser.findElements(vscode_extension_tester_1.By.css(selector)); if (items.length > 0) break; } catch { // Try next selector } } if (items.length === 0) { throw new Error('Could not find any setting items with known selectors'); } // Search through items to find the matching setting for (const item of items) { try { // Try to find the setting label/title within the item const labelSelectors = [ '.setting-item-label', '.setting-item-title', '.label-name', '.setting-key-label', '.monaco-label' ]; let itemTitle = ''; for (const labelSelector of labelSelectors) { try { const labelElement = await item.findElement(vscode_extension_tester_1.By.css(labelSelector)); itemTitle = await labelElement.getText(); if (itemTitle) break; } catch { // Try next selector } } // If no label found, try getting text content directly if (!itemTitle) { itemTitle = await item.getText(); } // Normalize text comparison like SettingsEditor.js does const normalizedTitle = title?.toLowerCase().replace(/\s/g, '').trim() || ''; const normalizedItemTitle = itemTitle.toLowerCase().replace(/\s/g, '').trim(); if (normalizedItemTitle.includes(normalizedTitle) || normalizedTitle.includes(normalizedItemTitle)) { settingElement = item; break; } } catch (err) { // Continue to next item } } if (!settingElement) { throw new Error(`Could not find setting element for: ${title}`); } // Find the input/control within the setting element and set the value const parent = await settingElement.findElement(vscode_extension_tester_1.By.xpath('..')); const settingContainer = await parent.findElement(vscode_extension_tester_1.By.xpath('..')); if (typeof value === 'boolean') { const checkbox = await settingContainer.findElement(vscode_extension_tester_1.By.css('input[type="checkbox"]')); const isChecked = await checkbox.isSelected(); if (isChecked !== value) { await checkbox.click(); } } else { // Try to find and handle different input types let inputHandled = false; // First, try to find a select element (dropdown) try { const selectElement = await settingContainer.findElement(vscode_extension_tester_1.By.css('select')); // For select elements, we need to find the option with the desired value const options = await selectElement.findElements(vscode_extension_tester_1.By.css('option')); for (const option of options) { const optionValue = await option.getAttribute('value'); const optionText = await option.getText(); // Match by value or text content if (optionValue === value.toString() || optionText === value.toString()) { await option.click(); inputHandled = true; break; } } if (!inputHandled) { // If no exact match found, try partial matching for (const option of options) { const optionValue = await option.getAttribute('value'); const optionText = await option.getText(); if (optionValue.toLowerCase().includes(value.toString().toLowerCase()) || optionText.toLowerCase().includes(value.toString().toLowerCase())) { await option.click(); inputHandled = true; break; } } } } catch { // Select element not found, continue to text input } // If no select element found or handled, try text input if (!inputHandled) { try { const textInput = await settingContainer.findElement(vscode_extension_tester_1.By.css('input[type="text"], textarea')); await textInput.clear(); await textInput.sendKeys(value.toString()); inputHandled = true; } catch { // Text input not found } } // If still not handled, try more input types if (!inputHandled) { try { const input = await settingContainer.findElement(vscode_extension_tester_1.By.css('input, textarea, select')); const inputType = await input.getTagName(); if (inputType === 'select') { // Handle select that wasn't caught above const options = await input.findElements(vscode_extension_tester_1.By.css('option')); for (const option of options) { const optionText = await option.getText(); if (optionText === value.toString()) { await option.click(); inputHandled = true; break; } } } else { // Handle other input types await input.clear(); await input.sendKeys(value.toString()); inputHandled = true; } } catch { // No input found } } if (!inputHandled) { throw new Error(`Could not find or handle input control for setting: ${title}`); } } (0, miscellaneous_1.log)(`Successfully set setting ${id} to ${value} using fallback implementation`); } catch (fallbackError) { (0, miscellaneous_1.log)(`Both primary and fallback implementations failed: ${fallbackError}`); throw new Error(`Failed to set setting ${id}: ${fallbackError}`); } } }; exports.setSettingValue = setSettingValue; //# sourceMappingURL=settings.js.map