From f13793627d53d50652fa38c98f214e3486d01219 Mon Sep 17 00:00:00 2001 From: Shatakshi Mishra Date: Mon, 23 Dec 2024 13:10:18 +0530 Subject: [PATCH] Add a webview to scaffold plugins through creator add subcommand (#1729) * Add a webview to scaffold plugins through creator add subcommand * Add addPluginPageApp.ts entry in codecov.yml file * logs cleanup * no need of force and ANSIBLE_CREATOR_VERSION_MIN * try setting NODE_OPTIONS in ci.yaml * try setting NODE_OPTIONS in taskfile * Add NODE_OPTIONS env var in the package step * Fix linting errors and sort quicklintViews for add section * Test improvements in contentCreatorUiTest for plugin webview testing * remove NODE_OPTIONS from where that's not needed --------- Co-authored-by: Alison Hart --- .sonarcloud.properties | 2 + .vscodeignore | 2 + codecov.yml | 1 + media/contentCreator/addPluginPageStyle.css | 111 +++++ package.json | 4 + src/extension.ts | 11 + src/features/contentCreator/addPluginPage.ts | 383 ++++++++++++++++++ src/features/contentCreator/types.ts | 8 + src/features/quickLinks/quickLinksView.ts | 28 +- .../apps/contentCreator/addPluginPageApp.ts | 214 ++++++++++ test/ui-test/contentCreatorUiTest.ts | 77 ++++ webpack.config.ts | 14 + 12 files changed, 845 insertions(+), 10 deletions(-) create mode 100644 media/contentCreator/addPluginPageStyle.css create mode 100644 src/features/contentCreator/addPluginPage.ts create mode 100644 src/webview/apps/contentCreator/addPluginPageApp.ts diff --git a/.sonarcloud.properties b/.sonarcloud.properties index 7e381e6ce..842958769 100644 --- a/.sonarcloud.properties +++ b/.sonarcloud.properties @@ -5,4 +5,6 @@ sonar.cpd.exclusions=\ src/webview/apps/contentCreator/createSampleExecutionEnvPageApp.ts, \ src/features/contentCreator/createDevcontainerPage.ts, \ src/webview/apps/contentCreator/createDevcontainerPageApp.ts, \ + src/features/contentCreator/addPluginPage.ts, \ + src/webview/apps/contentCreator/addPluginPageApp.ts, \ test/ui-test/*.ts diff --git a/.vscodeignore b/.vscodeignore index e0eb04332..791c97d01 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -26,6 +26,7 @@ !media/contentCreator/createDevfilePageStyle.css !media/contentCreator/createSampleExecutionEnvPageStyle.css !media/contentCreator/createDevcontainerPageStyle.css +!media/contentCreator/addPluginPageStyle.css !media/contentCreator/welcomePageStyle.css !media/lightspeedExplorerView/style.css !media/quickLinks/lightspeed.png @@ -48,6 +49,7 @@ !out/client/webview/apps/contentCreator/createDevfilePageApp.js !out/client/webview/apps/contentCreator/createSampleExecutionEnvPageApp.js !out/client/webview/apps/contentCreator/createDevcontainerPageApp.js +!out/client/webview/apps/contentCreator/addPluginPageApp.js !out/client/webview/apps/quickLinks/quickLinksApp.js !out/client/webview/apps/welcomePage/welcomePageApp.js !out/server/src/server.js diff --git a/codecov.yml b/codecov.yml index cb0464fa4..4c2c7906a 100644 --- a/codecov.yml +++ b/codecov.yml @@ -21,5 +21,6 @@ ignore: - src/webview/apps/contentCreator/createDevfilePageApp.ts - src/webview/apps/contentCreator/createSampleExecutionEnvPageApp.ts - src/webview/apps/contentCreator/createDevcontainerPageApp.ts + - src/webview/apps/contentCreator/addPluginPageApp.ts - src/webview/apps/welcomePage/welcomePageApp.ts - src/webview/apps/quickLinks/quickLinksApp.ts diff --git a/media/contentCreator/addPluginPageStyle.css b/media/contentCreator/addPluginPageStyle.css new file mode 100644 index 000000000..49e4bed47 --- /dev/null +++ b/media/contentCreator/addPluginPageStyle.css @@ -0,0 +1,111 @@ +@import url(../baseStyles/baseFormStyle.css); + +.container { + display: flex; + flex-direction: column; +} + +.element { + margin-bottom: 14px; +} + +vscode-text-field { + margin-top: 6px; + margin-bottom: 6px; +} + +vscode-text-area { + margin-top: 6px; + margin-bottom: 6px; +} + +.plugin-name-div { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; +} + +#plugin-name { + width:49%; + display:inline-block; +} + +.plugin-type-div { + display: flex; /* Use flexbox */ + flex-direction: row; /* Arrange child elements vertically */ + margin-top: 12px; + margin-bottom: 30px; + width: 100%; +} + +.checkbox-div { + display: flex; /* Use flexbox */ + flex-direction: column; /* Arrange child elements vertically */ + margin-top: 22px; + margin-bottom: 10px; + width: 100%; +} + +.verbose-div { + display: flex; /* Use flexbox */ + flex-direction: row; /* Arrange child elements vertically */ + margin-top: 12px; + margin-bottom: 30px; + width: 100%; +} + +vscode-dropdown { + width: 200px; +} + +.full-collection-path { + display: flex; /* Use flexbox */ + flex-direction: row; /* Arrange child elements vertically */ + color: var(--vscode-descriptionForeground); +} + +.required-fields { + margin-top: 10px; + color: var(--vscode-descriptionForeground); +} + +.group-buttons { + display: flex; /* Use flexbox */ + flex-direction: row; /* Arrange child elements vertically */ +} + +.p-collection-name { + font-style: italic; +} + +vscode-button { + margin: 0px 3px; +} + +vscode-checkbox i { + color: var(--vscode-descriptionForeground); + font-size: small; +} + +#ade-docs-link { + margin-left: 30px; + font-style: italic; +} + +.dropdown-container { + box-sizing: border-box; + display: flex; + flex-flow: column nowrap; + align-items: flex-start; + justify-content: flex-start; +} + +.dropdown-container label { + display: block; + color: var(--vscode-foreground); + cursor: pointer; + font-size: var(--vscode-font-size); + line-height: normal; + margin-bottom: 2px; +} diff --git a/package.json b/package.json index 3c49dbb54..20024076e 100644 --- a/package.json +++ b/package.json @@ -358,6 +358,10 @@ "command": "ansible.content-creator.create-devcontainer", "title": "Ansible: Create a Devcontainer" }, + { + "command": "ansible.content-creator.add-plugin", + "title": "Ansible: Add a Plugin" + }, { "command": "ansible.content-creator.create", "title": "Ansible Content Creator: Create" diff --git a/src/extension.ts b/src/extension.ts index d1a27adcd..acf4f96c9 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -65,6 +65,7 @@ import { showPlaybookGenerationPage } from "./features/lightspeed/playbookGenera import { showRoleGenerationPage } from "./features/lightspeed/roleGeneration"; import { ExecException, execSync } from "child_process"; import { CreateAnsibleProject } from "./features/contentCreator/createAnsibleProjectPage"; +import { AddPlugin } from "./features/contentCreator/addPluginPage"; // import { LightspeedExplorerWebviewViewProvider } from "./features/lightspeed/explorerWebviewViewProvider"; import { LightspeedUser, @@ -572,6 +573,16 @@ export async function activate(context: ExtensionContext): Promise { ), ); + // open web-view for adding a plugin in an ansible collection + context.subscriptions.push( + vscode.commands.registerCommand( + "ansible.content-creator.add-plugin", + () => { + AddPlugin.render(context.extensionUri); + }, + ), + ); + // open ansible-creator create context.subscriptions.push( vscode.commands.registerCommand("ansible.content-creator.create", () => { diff --git a/src/features/contentCreator/addPluginPage.ts b/src/features/contentCreator/addPluginPage.ts new file mode 100644 index 000000000..9b9e9b7c7 --- /dev/null +++ b/src/features/contentCreator/addPluginPage.ts @@ -0,0 +1,383 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import * as vscode from "vscode"; +import * as os from "os"; +import { getUri } from "../utils/getUri"; +import { getNonce } from "../utils/getNonce"; +import { PluginFormInterface, PostMessageEvent } from "./types"; +import { withInterpreter } from "../utils/commandRunner"; +import { SettingsManager } from "../../settings"; +import { expandPath, runCommand } from "./utils"; + +export class AddPlugin { + public static currentPanel: AddPlugin | undefined; + private readonly _panel: vscode.WebviewPanel; + private _disposables: vscode.Disposable[] = []; + public static readonly viewType = "CreateProject"; + + private constructor(panel: vscode.WebviewPanel, extensionUri: vscode.Uri) { + this._panel = panel; + this._panel.webview.html = this._getWebviewContent( + this._panel.webview, + extensionUri, + ); + this._setWebviewMessageListener(this._panel.webview); + this._panel.onDidDispose( + () => { + this.dispose(); + }, + null, + this._disposables, + ); + } + + public static render(extensionUri: vscode.Uri) { + if (AddPlugin.currentPanel) { + AddPlugin.currentPanel._panel.reveal(vscode.ViewColumn.One); + } else { + const panel = vscode.window.createWebviewPanel( + "add-plugin", + "Add Plugin", + vscode.ViewColumn.One, + { + enableScripts: true, + localResourceRoots: [ + vscode.Uri.joinPath(extensionUri, "out"), + vscode.Uri.joinPath(extensionUri, "media"), + ], + enableCommandUris: true, + retainContextWhenHidden: true, + }, + ); + + AddPlugin.currentPanel = new AddPlugin(panel, extensionUri); + } + } + + public dispose() { + AddPlugin.currentPanel = undefined; + + this._panel.dispose(); + + while (this._disposables.length) { + const disposable = this._disposables.pop(); + if (disposable) { + disposable.dispose(); + } + } + } + + private _getWebviewContent( + webview: vscode.Webview, + extensionUri: vscode.Uri, + ) { + const webviewUri = getUri(webview, extensionUri, [ + "out", + "client", + "webview", + "apps", + "contentCreator", + "AddPluginPageApp.js", + ]); + + const nonce = getNonce(); + const styleUri = getUri(webview, extensionUri, [ + "media", + "contentCreator", + "AddPluginPageStyle.css", + ]); + + const codiconsUri = getUri(webview, extensionUri, [ + "media", + "codicons", + "codicon.css", + ]); + + const homeDir = os.homedir(); + + return /*html*/ ` + + + + + + + AAA + + + + + +
+

Add a plugin to an existing collection

+

Extending automation with python

+
+ +
+
+ + Collection root directory * +
+ + + +
+
+ +
+ Plugin name * +
+ +
+ +
+ +
+

Project path: 

+
+ +
+ +
+ +
+ Overwrite
Overwriting will replace an existing plugin with the same name if present in the collection.
+
+ +
+ + +   Clear All + + + +   Create + +
+ +
+ +
+ Logs + +
+ + +   Clear Logs + + + +   Open Plugin + +
+ +
+

Fields marked with an asterisk (*) are required

+
+ +
+
+ + + + + + `; + } + + private _setWebviewMessageListener(webview: vscode.Webview) { + webview.onDidReceiveMessage( + async (message: any) => { + const command = message.command; + let payload; + + switch (command) { + case "open-explorer": { + payload = message.payload; + const selectedUri = await this.openExplorerDialog( + payload.selectOption, + ); + webview.postMessage({ + command: "file-uri", + arguments: { selectedUri: selectedUri }, + } as PostMessageEvent); + return; + } + case "init-create": + payload = message.payload as PluginFormInterface; + await this.runAddCommand(payload, webview); + return; + + case "init-open-scaffolded-folder": + payload = message.payload; + await this.openFolderInWorkspace( + payload.projectUrl, + payload.pluginName, + payload.pluginType, + ); + return; + } + }, + undefined, + this._disposables, + ); + } + + public async getCreatorCommand( + pluginName: string, + pluginType: string, + url: string, + ): Promise { + let command = ""; + + command = `ansible-creator add plugin ${pluginType} ${pluginName} ${url} --no-ansi`; + return command; + } + + public async openExplorerDialog( + selectOption: string, + ): Promise { + const options: vscode.OpenDialogOptions = { + canSelectMany: false, + openLabel: "Select", + canSelectFiles: selectOption === "file", + canSelectFolders: selectOption === "folder", + defaultUri: vscode.Uri.parse(os.homedir()), + }; + + let selectedUri: string | undefined; + await vscode.window.showOpenDialog(options).then((fileUri) => { + if (fileUri && fileUri[0]) { + selectedUri = fileUri[0].fsPath; + } + }); + + return selectedUri; + } + + public async runAddCommand( + payload: PluginFormInterface, + webView: vscode.Webview, + ) { + const { pluginName, pluginType, collectionPath, verbosity, isOverwritten } = + payload; + + const destinationPathUrl = collectionPath + ? collectionPath + : `${os.homedir()}/.ansible/collections/ansible_collections`; + + let ansibleCreatorAddCommand = await this.getCreatorCommand( + pluginName, + pluginType, + destinationPathUrl, + ); + + if (isOverwritten) { + ansibleCreatorAddCommand += " --overwrite"; + } else { + ansibleCreatorAddCommand += " --no-overwrite"; + } + + switch (verbosity) { + case "Off": + ansibleCreatorAddCommand += ""; + break; + case "Low": + ansibleCreatorAddCommand += " -v"; + break; + case "Medium": + ansibleCreatorAddCommand += " -vv"; + break; + case "High": + ansibleCreatorAddCommand += " -vvv"; + break; + } + + console.debug("[ansible-creator] command: ", ansibleCreatorAddCommand); + + const extSettings = new SettingsManager(); + await extSettings.initialize(); + + const { command, env } = withInterpreter( + extSettings.settings, + ansibleCreatorAddCommand, + "", + ); + + let commandOutput = ""; + + // execute ansible-creator command + const ansibleCreatorExecutionResult = await runCommand(command, env); + commandOutput += `------------------------------------ ansible-creator logs ------------------------------------\n`; + commandOutput += ansibleCreatorExecutionResult.output; + const commandPassed = ansibleCreatorExecutionResult.status; + + await webView.postMessage({ + command: "execution-log", + arguments: { + commandOutput: commandOutput, + projectUrl: destinationPathUrl, + status: commandPassed, + }, + } as PostMessageEvent); + + if (commandPassed === "passed") { + const selection = await vscode.window.showInformationMessage( + `${pluginType} plugin '${pluginName}' added at: ${destinationPathUrl}/plugins`, + `Open plugin file ↗`, + ); + if (selection === "Open plugin file ↗") { + this.openFolderInWorkspace(destinationPathUrl, pluginName, pluginType); + } + } + } + + public async openFolderInWorkspace( + folderUrl: string, + pluginName: string, + pluginType: string, + ) { + const folderUri = vscode.Uri.parse(expandPath(folderUrl)); + + // add folder to a new workspace + // vscode.workspace.updateWorkspaceFolders(0, 1, { uri: folderUri }); + + if (vscode.workspace.workspaceFolders?.length === 0) { + vscode.workspace.updateWorkspaceFolders(0, null, { uri: folderUri }); + } else { + await vscode.commands.executeCommand("vscode.openFolder", folderUri, { + forceNewWindow: true, + }); + } + + // open the plugin file in the editor + const pluginFileUrl = `${folderUrl}/plugins/${pluginType}/${pluginName}.py`; + console.log(`[ansible-creator] Plugin file url: ${pluginFileUrl}`); + const parsedUrl = vscode.Uri.parse(`vscode://file${pluginFileUrl}`); + console.log(`[ansible-creator] Parsed galaxy file url: ${parsedUrl}`); + this.openFileInEditor(parsedUrl.toString()); + } + + public openFileInEditor(fileUrl: string) { + const updatedUrl = expandPath(fileUrl); + console.log(`[ansible-creator] Updated url: ${updatedUrl}`); + + vscode.commands.executeCommand("vscode.open", vscode.Uri.parse(updatedUrl)); + } +} diff --git a/src/features/contentCreator/types.ts b/src/features/contentCreator/types.ts index 4e657bbd9..925522932 100644 --- a/src/features/contentCreator/types.ts +++ b/src/features/contentCreator/types.ts @@ -42,6 +42,14 @@ export type DevcontainerFormInterface = { isOverwritten: boolean; }; +export type PluginFormInterface = { + pluginName: string; + pluginType: string; + collectionPath: string; + verbosity: string; + isOverwritten: boolean; +}; + export type PostMessageEvent = | { command: "ADEPresence"; diff --git a/src/features/quickLinks/quickLinksView.ts b/src/features/quickLinks/quickLinksView.ts index 6c009d935..78fa668ff 100644 --- a/src/features/quickLinks/quickLinksView.ts +++ b/src/features/quickLinks/quickLinksView.ts @@ -100,16 +100,9 @@ export function getWebviewQuickLinks(webview: Webview, extensionUri: Uri) {

Add resources to an existing Ansible project

- @@ -137,6 +130,21 @@ export function getWebviewQuickLinks(webview: Webview, extensionUri: Uri) { + + diff --git a/src/webview/apps/contentCreator/addPluginPageApp.ts b/src/webview/apps/contentCreator/addPluginPageApp.ts new file mode 100644 index 000000000..8056914ff --- /dev/null +++ b/src/webview/apps/contentCreator/addPluginPageApp.ts @@ -0,0 +1,214 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import { + allComponents, + Button, + Checkbox, + TextArea, + TextField, + provideVSCodeDesignSystem, + Dropdown, +} from "@vscode/webview-ui-toolkit"; +import { + PluginFormInterface, + PostMessageEvent, +} from "../../../features/contentCreator/types"; + +provideVSCodeDesignSystem().register(allComponents); + +const vscode = acquireVsCodeApi(); +window.addEventListener("load", main); + +let pluginNameTextField: TextField; +let pluginTypeDropdown: Dropdown; + +let collectionPathUrlTextField: TextField; +let folderExplorerButton: Button; + +let initCreateButton: Button; +let initClearButton: Button; + +let overwriteCheckbox: Checkbox; + +let verboseDropdown: Dropdown; + +let initCollectionPathDiv: HTMLElement | null; +let initCollectionPathElement: HTMLElement; + +let initLogsTextArea: TextArea; +let initClearLogsButton: Button; +let initOpenScaffoldedFolderButton: Button; + +let projectUrl = ""; + +function main() { + // elements for scaffolding ansible plugin interface + pluginNameTextField = document.getElementById("plugin-name") as TextField; + pluginTypeDropdown = document.getElementById("plugin-dropdown") as Dropdown; + + collectionPathUrlTextField = document.getElementById("path-url") as TextField; + folderExplorerButton = document.getElementById("folder-explorer") as Button; + + overwriteCheckbox = document.getElementById("overwrite-checkbox") as Checkbox; + + verboseDropdown = document.getElementById("verbosity-dropdown") as Dropdown; + initCreateButton = document.getElementById("create-button") as Button; + initClearButton = document.getElementById("clear-button") as Button; + + initLogsTextArea = document.getElementById("log-text-area") as TextArea; + initClearLogsButton = document.getElementById("clear-logs-button") as Button; + initOpenScaffoldedFolderButton = document.getElementById( + "open-folder-button", + ) as Button; + + pluginNameTextField.addEventListener("input", toggleCreateButton); + collectionPathUrlTextField.addEventListener("input", toggleCreateButton); + + folderExplorerButton.addEventListener("click", openExplorer); + + initCreateButton.addEventListener("click", handleInitCreateClick); + initCreateButton.disabled = true; + + initClearButton.addEventListener("click", handleInitClearClick); + + initClearLogsButton.addEventListener("click", handleInitClearLogsClick); + initOpenScaffoldedFolderButton.addEventListener( + "click", + handleInitOpenScaffoldedFolderClick, + ); + + initCollectionPathDiv = document.getElementById("full-collection-path"); + + initCollectionPathElement = document.createElement("p"); + initCollectionPathElement.innerHTML = collectionPathUrlTextField.placeholder; + initCollectionPathDiv?.appendChild(initCollectionPathElement); +} + +function openExplorer(event: any) { + const source = event.target.parentNode.id; + + let selectOption; + + if (source === "folder-explorer") { + selectOption = "folder"; + } else { + selectOption = "file"; + } + + vscode.postMessage({ + command: "open-explorer", + payload: { + selectOption: selectOption, + }, + }); + + window.addEventListener( + "message", + (event: MessageEvent) => { + const message = event.data; + + if (message.command === "file-uri") { + const selectedUri = message.arguments.selectedUri; + + if (selectedUri) { + if (source === "folder-explorer") { + collectionPathUrlTextField.value = selectedUri; + initCollectionPathElement.innerHTML = selectedUri; + } + } + } + }, + ); +} + +function handleInitClearClick() { + pluginNameTextField.value = ""; + pluginTypeDropdown.currentValue = "filter"; + collectionPathUrlTextField.value = ""; + + initCollectionPathElement.innerHTML = collectionPathUrlTextField.placeholder; + + overwriteCheckbox.checked = false; + verboseDropdown.currentValue = "Off"; + + initCreateButton.disabled = true; +} + +function toggleCreateButton() { + // update collection path

tag + if (!collectionPathUrlTextField.value.trim()) { + initCollectionPathElement.innerHTML = `${ + collectionPathUrlTextField.placeholder + }/plugins/${pluginTypeDropdown.currentValue.trim()}/${pluginNameTextField.value.trim()}`; + + if (!pluginNameTextField.value.trim()) { + initCollectionPathElement.innerHTML = + collectionPathUrlTextField.placeholder; + } + } else { + initCollectionPathElement.innerHTML = + collectionPathUrlTextField.value.trim(); + } + + if (pluginNameTextField.value.trim()) { + initCreateButton.disabled = false; + } else { + initCreateButton.disabled = true; + } +} + +function handleInitCreateClick() { + initCreateButton.disabled = true; + + vscode.postMessage({ + command: "init-create", + payload: { + pluginName: pluginNameTextField.value.trim(), + pluginType: pluginTypeDropdown.currentValue.trim(), + collectionPath: collectionPathUrlTextField.value.trim(), + verbosity: verboseDropdown.currentValue.trim(), + isOverwritten: overwriteCheckbox.checked, + } as PluginFormInterface, + }); + + window.addEventListener( + "message", + async (event: MessageEvent) => { + const message = event.data; + + switch (message.command) { + case "execution-log": + initLogsTextArea.value = message.arguments.commandOutput; + if ( + message.arguments.status && + message.arguments.status === "passed" + ) { + initOpenScaffoldedFolderButton.disabled = false; + } else { + initOpenScaffoldedFolderButton.disabled = true; + } + + projectUrl = message.arguments.projectUrl + ? message.arguments.projectUrl + : ""; + + initCreateButton.disabled = false; + + return; + } + }, + ); +} + +function handleInitClearLogsClick() { + initLogsTextArea.value = ""; +} + +function handleInitOpenScaffoldedFolderClick() { + vscode.postMessage({ + command: "init-open-scaffolded-folder", + payload: { + projectUrl: projectUrl, + }, + }); +} diff --git a/test/ui-test/contentCreatorUiTest.ts b/test/ui-test/contentCreatorUiTest.ts index bbe0d69db..1580c6224 100644 --- a/test/ui-test/contentCreatorUiTest.ts +++ b/test/ui-test/contentCreatorUiTest.ts @@ -180,3 +180,80 @@ describe("Test Ansible sample execution environment file scaffolding", () => { ); }); }); + +describe("Test collection plugins scaffolding", () => { + let createButton: WebElement; + let editorView: EditorView; + + async function testWebViewElements( + command: string, + editorTitle: string, + pluginName: string, + pluginType: string, + ) { + await workbenchExecuteCommand(command); + await sleep(10000); + + await new EditorView().openEditor(editorTitle); + const webview = await getWebviewByLocator( + By.xpath("//vscode-text-field[@id='path-url']"), + ); + + const collectionPathUrlTextField = await webview.findWebElement( + By.xpath("//vscode-text-field[@id='path-url']"), + ); + expect( + collectionPathUrlTextField, + "collectionPathUrlTextField should not be undefined", + ).not.to.be.undefined; + await collectionPathUrlTextField.sendKeys("~"); + + const pluginNameTextField = await webview.findWebElement( + By.xpath("//vscode-text-field[@id='plugin-name']"), + ); + expect(pluginNameTextField, "pluginNameTextField should not be undefined") + .not.to.be.undefined; + await pluginNameTextField.sendKeys(pluginName); + + const pluginTypeDropdown = await webview.findWebElement( + By.xpath("//vscode-dropdown[@id='plugin-dropdown']"), + ); + expect(pluginTypeDropdown, "pluginTypeDropdown should not be undefined").not + .to.be.undefined; + await pluginTypeDropdown.sendKeys(pluginType); + + const overwriteCheckbox = await webview.findWebElement( + By.xpath("//vscode-checkbox[@id='overwrite-checkbox']"), + ); + expect(overwriteCheckbox, "overwriteCheckbox should not be undefined").not + .to.be.undefined; + await overwriteCheckbox.click(); + + createButton = await webview.findWebElement( + By.xpath("//vscode-button[@id='create-button']"), + ); + expect(createButton, "createButton should not be undefined").not.to.be + .undefined; + + expect( + await createButton.isEnabled(), + "Create button should be enabled now", + ).to.be.true; + + await createButton.click(); + await webview.switchBack(); + editorView = new EditorView(); + if (editorView) { + await editorView.closeAllEditors(); + } + } + + it("Check add-plugin webview elements", async () => { + await testWebViewElements( + "Ansible: Add a Plugin", + "Add Plugin", + "test_plugin_name", + "lookup", + ); + }); +}); diff --git a/webpack.config.ts b/webpack.config.ts index f5025e256..beb13cf00 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -265,6 +265,19 @@ const createDevcontainerWebviewConfig = { }, }; +const addPluginWebviewConfig = { + ...config, + target: ["web", "es2020"], + entry: "./src/webview/apps/contentCreator/addPluginPageApp.ts", + experiments: { outputModule: true }, + output: { + path: path.resolve(__dirname, "out"), + filename: "./client/webview/apps/contentCreator/addPluginPageApp.js", + libraryTarget: "module", + chunkFormat: "module", + }, +}; + // eslint-disable-next-line @typescript-eslint/no-explicit-any module.exports = (_env: any, argv: { mode: string }) => { // Use non-bundled js for client/server in dev environment @@ -284,6 +297,7 @@ module.exports = (_env: any, argv: { mode: string }) => { createAnsibleProjectWebviewConfig, createDevfileWebviewConfig, createDevcontainerWebviewConfig, + addPluginWebviewConfig, quickLinksWebviewConfig, createSampleExecutionEnvWebviewConfig, ];