Skip to content

Commit

Permalink
AAP-34645: Add “Generate a Playbook” Button to Side Panel
Browse files Browse the repository at this point in the history
  • Loading branch information
manstis committed Dec 9, 2024
1 parent 20dd4df commit 95350a8
Show file tree
Hide file tree
Showing 3 changed files with 289 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/features/lightspeed/utils/explorerView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ export function getWebviewContentWithActiveSession(
"style.css",
]);
const nonce = getNonce();
const generateForm = `<div class="button-container">
<form id="playbook-generation-form">
<vscode-button id="lightspeed-explorer-playbook-generation-submit" class="lightspeedExplorerButton">Generate a playbook</vscode-button>
<script type="module" nonce="${nonce}" src="${webviewUri}"></script>
</form>
</div>`;
const explainForm = `<div class="button-container">
<form id="playbook-explanation-form">
<vscode-button id="lightspeed-explorer-playbook-explanation-submit" class="lightspeedExplorerButton" ${
Expand Down Expand Up @@ -97,6 +103,7 @@ export function getWebviewContentWithActiveSession(
<body>
<div id="lightspeedExplorerView">
${content}
${generateForm}
${explainForm}
</div>
</body>
Expand All @@ -120,6 +127,9 @@ export function setWebviewMessageListener(
case "connect":
commands.executeCommand("ansible.lightspeed.oauth");
return;
case "generate":
commands.executeCommand("ansible.lightspeed.playbookGeneration");
return;
case "explain":
commands.executeCommand("ansible.lightspeed.playbookExplanation");
return;
Expand Down
8 changes: 8 additions & 0 deletions src/webview/apps/lightspeed/explorer/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ function setListener(id: string, func: any) {

function main() {
setListener("lightspeed-explorer-connect", lightspeedConnect);
setListener(
"lightspeed-explorer-playbook-generation-submit",
lightspeedExplorerPlaybookGeneration,
);
setListener(
"lightspeed-explorer-playbook-explanation-submit",
lightspeedExplorerPlaybookExplanation,
Expand All @@ -29,6 +33,10 @@ function lightspeedConnect() {
vscode.postMessage({ command: "connect" });
}

function lightspeedExplorerPlaybookGeneration() {
vscode.postMessage({ command: "generate" });
}

function lightspeedExplorerPlaybookExplanation() {
vscode.postMessage({ command: "explain" });
}
271 changes: 271 additions & 0 deletions test/ui-test/lightspeedUiTestExplorer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
import {
ActionsControl,
ActivityBar,
By,
ContextMenu,
EditorView,
InputBox,
ModalDialog,
SideBarView,
VSBrowser,
ViewControl,
ViewSection,
WebView,
WebviewView,
Workbench,
} from "vscode-extension-tester";
import {
getFixturePath,
expectNotification,
getModalDialogAndMessage,
getWebviewByLocator,
sleep,
updateSettings,
workbenchExecuteCommand,
} from "./uiTestHelper";
import { WizardGenerationActionType } from "../../src/definitions/lightspeed";
import { PlaybookGenerationActionEvent } from "../../src/interfaces/lightspeed";
import { expect } from "chai";
import axios from "axios";

export function lightspeedUIExplorerTest(): void {
describe("Test Lightspeed Explorer features", () => {
let workbench: Workbench;
let explorerView: WebviewView;
let modalDialog: ModalDialog;
let dialogMessage: string;
let sideBar: SideBarView;
let view: ViewControl;
let adtView: ViewSection;

before(async () => {
// Enable Lightspeed and open Ansible Light view on sidebar
workbench = new Workbench();
const settingsEditor = await workbench.openSettings();
await updateSettings(settingsEditor, "ansible.lightspeed.enabled", true);
await updateSettings(
settingsEditor,
"ansible.lightspeed.URL",
process.env.TEST_LIGHTSPEED_URL,
);
await updateSettings(
settingsEditor,
"ansible.lightspeed.suggestions.enabled",
true,
);
// Close settings and other open editors (if any)
await new EditorView().closeAllEditors();

// Set "UI Test" option for mock server
await axios.post(
`${process.env.TEST_LIGHTSPEED_URL}/__debug__/options`,
["--ui-test"],
{ headers: { "Content-Type": "application/json" } },
);
});

after(async function () {
if (explorerView) {
await explorerView.switchBack();
}
const settingsEditor = await workbench.openSettings();
await updateSettings(settingsEditor, "ansible.lightspeed.enabled", false);
await updateSettings(settingsEditor, "ansible.lightspeed.URL", "");
await updateSettings(
settingsEditor,
"ansible.lightspeed.suggestions.enabled",
false,
);
// Close settings and other open editors (if any)
await new EditorView().closeAllEditors();

// Clear "UI Test" option for mock server
await axios.post(
`${process.env.TEST_LIGHTSPEED_URL}/__debug__/options`,
[],
{ headers: { "Content-Type": "application/json" } },
);
});

it("Focus on Ansible Lightspeed View", async () => {
view = (await new ActivityBar().getViewControl("Ansible")) as ViewControl;
sideBar = await view.openView();

adtView = await sideBar
.getContent()
.getSection("Ansible Development Tools");
adtView.collapse();

await sleep(3000);
explorerView = new WebviewView();
expect(explorerView, "explorerView should not be undefined").not.to.be
.undefined;
});

it("Click Connect button Ansible Lightspeed webview", async () => {
await explorerView.switchToFrame(5000);

const connectButton = await explorerView.findWebElement(
By.id("lightspeed-explorer-connect"),
);
expect(connectButton).not.to.be.undefined;
if (connectButton) {
await connectButton.click();
}
await explorerView.switchBack();
});

it("Click Allow to use Lightspeed", async () => {
// Click Allow to use Lightspeed
const { dialog, message } = await getModalDialogAndMessage(true);
expect(message).equals(
"The extension 'Ansible' wants to sign in using Ansible Lightspeed.",
);
await dialog.pushButton("Allow");
});

it("Verify a modal dialog pops up", async () => {
const { dialog, message } = await getModalDialogAndMessage();
expect(dialog).not.to.be.undefined;
expect(message).not.to.be.undefined;
modalDialog = dialog;
dialogMessage = message;
});

it("Click Open if a dialog shows up for opening the external website", async () => {
// If the dialog to open the external website is not suppressed, click Open
if (dialogMessage === "Do you want Code to open the external website?") {
await modalDialog.pushButton("Configure Trusted Domains");
const input = await InputBox.create();
input.confirm();

const d = await getModalDialogAndMessage();
modalDialog = d.dialog;
dialogMessage = d.message;
}
});

it("Click Open to open the callback URI", async () => {
// Click Open to allow Ansible extension to open the callback URI
expect(dialogMessage).equals(
"Allow 'Ansible' extension to open this URI?",
);
await modalDialog.pushButton("Open");
await sleep(2000);
});

it("Verify Ansible Lightspeed Generate Playbook button", async () => {
await explorerView.switchToFrame(2000);

const generatePlaybookButton = await explorerView.findWebElement(
By.id("lightspeed-explorer-playbook-generation-submit"),
);
expect(generatePlaybookButton).not.to.be.undefined;

// Open playbook generation webview.
await generatePlaybookButton.click();
await sleep(2000);

// Locate the playbook explanation webview
await explorerView.switchBack();
const webView = await getWebviewByLocator(
By.xpath("//*[text()='Create a playbook with Ansible Lightspeed']"),
);
expect(webView, "webView should not be undefined").not.to.be.undefined;

await webView.switchBack();
await workbenchExecuteCommand("View: Close All Editor Groups");

/* verify generated events */
const expected = [
[WizardGenerationActionType.OPEN, undefined, 1],
[WizardGenerationActionType.CLOSE_CANCEL, 1, undefined],
];
const res = await axios.get(
`${process.env.TEST_LIGHTSPEED_URL}/__debug__/feedbacks`,
);
expect(res.data.feedbacks.length).equals(expected.length);
for (let i = 0; i < expected.length; i++) {
const evt: PlaybookGenerationActionEvent =
res.data.feedbacks[i].playbookGenerationAction;
expect(evt.action).equals(expected[i][0]);
expect(evt.fromPage).equals(expected[i][1]);
expect(evt.toPage).equals(expected[i][2]);
}
});

it("Verify Ansible Lightspeed Explain Playbook button", async () => {
const folder = "lightspeed";
const file = "playbook_4.yml";
const filePath = getFixturePath(folder, file);

// Open file in the editor
await VSBrowser.instance.openResources(filePath);

await explorerView.switchToFrame(2000);

const explainPlaybookButton = await explorerView.findWebElement(
By.id("lightspeed-explorer-playbook-explanation-submit"),
);
expect(explainPlaybookButton).not.to.be.undefined;

// Open playbook explanation webview.
await explainPlaybookButton.click();
await sleep(2000);

// Locate the playbook explanation webview
await explorerView.switchBack();
let webView = (await new EditorView().openEditor(
"Explanation",
1,
)) as WebView;
expect(webView, "webView should not be undefined").not.to.be.undefined;
webView = await getWebviewByLocator(
By.xpath("//div[@class='playbookGeneration']"),
);
await webView.findWebElement(
By.xpath("//h2[contains(text(), 'Playbook Overview and Structure')]"),
);

await webView.switchBack();
await workbenchExecuteCommand("View: Close All Editor Groups");

/* verify generated events */
const res = await axios.get(
`${process.env.TEST_LIGHTSPEED_URL}/__debug__/feedbacks`,
);
expect(res.data.feedbacks.length).equals(1);
});

it("Sign out using Accounts global action", async () => {
workbench = new Workbench();
const activityBar = new ActivityBar();
const actions = (await activityBar.getGlobalAction(
"Accounts",
)) as ActionsControl;
expect(actions).not.to.be.undefined;
await actions.click();
const menus = await workbench.findElements(By.className("context-view"));
expect(menus.length).greaterThan(0);
const menu = new ContextMenu(workbench);
expect(menu).not.to.be.undefined;
if (menu) {
await menu.select(
"EXTERNAL_USERNAME (licensed) (Ansible Lightspeed)",
"Sign Out",
);
}
});

it("Click Sign Out button on the modal dialog", async () => {
const dialog = new ModalDialog();
expect(dialog).not.to.be.undefined;
await dialog.pushButton("Sign Out");
});

it("Verify the notification message", async () => {
await sleep(1000);
await expectNotification("Successfully signed out.");
});
});
}

0 comments on commit 95350a8

Please sign in to comment.