Skip to content
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions extester.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"$schema": "./node_modules/vscode-extension-tester/resources/extester.schema.json",
"setup": {
"extensionsDir": "./test-resources",
"packageOptions": {
"useYarn": true,
"dependencies": false
}
},
"run": {
"testFiles": ["out/**/*.test.js"],
"resources": ["./test Fixture with speci@l chars"],
"extensionsDir": "./test-resources",
"settings": "./it-tests/vscode-settings.json",
"customPageObjects": "./out/pageObjects/locators.js"
}
}
139 changes: 32 additions & 107 deletions it-tests/BasicFlow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { By, EditorView, until, VSBrowser, WebDriver, WebView, logging, InputBox } from 'vscode-extension-tester';
import { By, EditorView, until, VSBrowser, WebDriver, WebView, logging } from 'vscode-extension-tester';
import { assert } from 'chai';
import * as path from 'path';
import {
Expand All @@ -23,6 +23,7 @@ import {
openResourcesAndWaitForActivation,
workaroundToRedrawContextualMenu,
} from './Util';
import { KaotoCanvas, KaotoEditor, kaotoLocators, DataMapperEditor } from './pageObjects';
import { waitUntil } from 'async-wait-until';
import * as fs from 'fs-extra';

Expand Down Expand Up @@ -132,7 +133,7 @@ describe('Kaoto basic development flow', function () {
// TODO: Add a target xsd
// TODO: Map an element

await (await driver.findElement(By.css('a[data-testid="design-tab"]'))).click();
await KaotoEditor.clickDesignTab(driver);

const files = fs.readdirSync(workspaceFolder);
const xslFiles = files.filter((file) => file.endsWith('.xsl'));
Expand Down Expand Up @@ -175,90 +176,27 @@ describe('Kaoto basic development flow', function () {
});

async function addXsdForSource(driver: WebDriver, kaotoWebview: WebView) {
await driver.wait(
until.elementLocated(By.css('button[data-testid="attach-schema-sourceBody-Body-button"]')),
5000,
'Cannot find the button to attach the schema',
);
await (await driver.findElement(By.css('button[data-testid="attach-schema-sourceBody-Body-button"]'))).click();

await waitForXsdAttachModal(driver);
const schemaButton = await driver.findElement(By.xpath("//button[@data-testid='attach-schema-modal-btn-file']"));
await schemaButton.click();

await kaotoWebview.switchBack();
const xsdInputbox = await InputBox.create(10000);
await xsdInputbox.setText('shiporder.xsd');
try {
const checkboxes = await xsdInputbox.getCheckboxes();
if (checkboxes.length > 0) {
await checkboxes[0].select();
}
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
if (!/NoSuchElement/i.test(message) && !/checkbox/i.test(message)) {
throw error;
}
// Fallback for Kaoto <2.10.0 (no checkboxes)
}
await xsdInputbox.confirm();
await kaotoWebview.switchToFrame();

await waitForXsdAttachModal(driver);
const attachButton = await driver.findElement(By.xpath("//button[@data-testid='attach-schema-modal-btn-attach']"));
await attachButton.click();

await driver.wait(
until.elementLocated(
// Kaoto 2.6- using -field-, Kaoto 2.7+ using -fx-
By.xpath('//div[starts-with(@data-testid, "node-source-field-shiporder-")] | //div[starts-with(@data-testid, "node-source-fx-shiporder-")]'),
),
5000,
'Root of the imported xsd is not displayed in the UI',
);
}

async function waitForXsdAttachModal(driver: WebDriver, timeout: number = 3_000): Promise<void> {
await driver.wait(until.elementLocated(By.xpath("//div[@data-testid='attach-schema-modal']")), timeout, 'Cannot find XSD schema modal dialog');
await DataMapperEditor.attachXsdSchema(driver, kaotoWebview, 'sourceBody-Body', 'shiporder.xsd');
await DataMapperEditor.waitForSourceField(driver, 5_000);
}

async function openDataMapperEditor(driver: WebDriver) {
const kaotoNode = await driver.findElement(
By.css(
`g[data-testid^="custom-node__kaoto-datamapper"],g[data-testid="custom-node__route.from.steps.0.kaoto-datamapper"],g[data-testid="${DATA_TEST_ID_DATAMAPPERSTEP_2_5}"]`,
),
);
await kaotoNode.click();
await driver.wait(
until.elementLocated(By.css('button[title="Click to launch the Kaoto DataMapper editor"]')),
5000,
'Cannot find the button to open the datamapper',
);
await (await driver.findElement(By.css('button[title="Click to launch the Kaoto DataMapper editor"]'))).click();
const nodeSelector = `g[data-testid^="custom-node__kaoto-datamapper"],g[data-testid="custom-node__route.from.steps.0.kaoto-datamapper"],g[data-testid="${DATA_TEST_ID_DATAMAPPERSTEP_2_5}"]`;
await DataMapperEditor.openFromNode(driver, nodeSelector);
}

async function deleteDataMapperStep(driver: WebDriver, workspaceFolder: string, kaotoWebview: WebView) {
await checkStepWithTestIdOrNodeLabelPresent(driver, 'custom-node__kaoto-datamapper', 'kaoto-datamapper');

const kaotoNodeConfigured = await driver.findElement(
By.xpath(`//*[name()='g' and starts-with(@data-testid,'custom-node__kaoto-datamapper') or @data-nodelabel='kaoto-datamapper']`),
);
const kaotoNodeConfigured = await KaotoCanvas.findNodeByTestIdOrLabel(driver, 'custom-node__kaoto-datamapper', 'kaoto-datamapper');
await kaotoNodeConfigured.click();

await workaroundToRedrawContextualMenu(kaotoWebview);

await driver.wait(until.elementLocated(By.css("button[id='reset-view']")), 5000, 'Cannot find the reset view button');
await (await driver.findElement(By.css("button[id='reset-view']"))).click(); // reset view nodes position to see the delete button

await driver.wait(until.elementLocated(By.xpath("//div[@data-testid='step-toolbar']")), 5000, 'Cannot find the step toolbar');
await (await driver.findElement(By.css('button[data-testid="kaoto-datamapper|step-toolbar-button-delete"]'))).click();
await KaotoCanvas.resetView(driver, 5_000);
await KaotoCanvas.deleteStep(driver, 'kaoto-datamapper', 5_000);
await KaotoCanvas.confirmDeleteStepAndFile(driver, 5_000);

await driver.wait(
until.elementLocated(By.xpath("//div[@data-ouia-component-id='ActionConfirmationModal']")),
5000,
'Cannot find the modal to delete the data mapper step',
);
await (await driver.findElement(By.css('button[data-testid="action-confirmation-modal-btn-del-step-and-file"]'))).click();
await driver.wait(
async () => {
const filesAfterDeletion = fs.readdirSync(workspaceFolder);
Expand All @@ -271,63 +209,50 @@ async function deleteDataMapperStep(driver: WebDriver, workspaceFolder: string,
}

async function createNewRoute(driver: WebDriver) {
await (await driver.findElement(By.xpath("//button[@data-testid='dsl-list-btn']"))).click();
await KaotoCanvas.clickDslListButton(driver);
}

async function addAMQPStep(driver: WebDriver) {
const canvasNode = await KaotoCanvas.findTimerOrFromNode(driver);
await KaotoCanvas.openContextMenu(driver, canvasNode);
await KaotoCanvas.clickReplaceInContextMenu(driver);

await driver.wait(
until.elementLocated(By.css('g[data-testid^="custom-node__timer"],g[data-testid="custom-node__route.from"]')),
until.elementLocated(By.xpath(kaotoLocators.KaotoCatalog.tileHeaderByTestId('amqp'))),
5000,
'Cannot find the node for the timer',
'Cannot find the tile header for the AMQP step',
);

const canvasNode = await driver.findElement(By.css('g[data-testid^="custom-node__timer"],g[data-testid="custom-node__route.from"]'));
await driver.actions().contextClick(canvasNode).perform();

await driver.wait(until.elementLocated(By.className('pf-topology-context-menu__c-dropdown__menu')), 5000, 'Cannot find the context menu');
await (await driver.findElement(By.xpath("//\*[@data-testid='context-menu-item-replace']"))).click();

await driver.wait(until.elementLocated(By.xpath("//div[@data-testid='tile-header-amqp']")), 5000, 'Cannot find the tile header for the AMQP step');
await (await driver.findElement(By.xpath("//div[@data-testid='tile-header-amqp']"))).click();
await (await driver.findElement(By.xpath(kaotoLocators.KaotoCatalog.tileHeaderByTestId('amqp')))).click();
}

async function addDatamapperStep(driver: WebDriver, kaotoWebview: WebView) {
await driver.wait(
until.elementLocated(By.css('g[data-testid^="custom-node__log"],g[data-testid="custom-node__route.from.steps.0.log"]')),
5000,
'Cannot find the node for the log',
);

const canvasNode = await driver.findElement(By.css('g[data-testid^="custom-node__log"],g[data-testid="custom-node__route.from.steps.0.log"]'));
await driver.actions().contextClick(canvasNode).perform();
const canvasNode = await KaotoCanvas.findLogNode(driver);
await KaotoCanvas.openContextMenu(driver, canvasNode);

await workaroundToRedrawContextualMenu(kaotoWebview);

await driver.wait(until.elementLocated(By.className('pf-topology-context-menu__c-dropdown__menu')), 5000, 'Cannot find the context menu');
await (await driver.findElement(By.xpath("//*[@data-testid='context-menu-item-replace']"))).click();
await KaotoCanvas.clickReplaceInContextMenu(driver);

await driver.wait(until.elementLocated(By.xpath("//input[@placeholder='Filter by name, description or tag']")), 5000, 'Cannot find the filter input');
const filterInput = await driver.findElement(By.xpath("//input[@placeholder='Filter by name, description or tag']"));
await driver.wait(until.elementLocated(By.xpath(kaotoLocators.KaotoCatalog.filterInput)), 5000, 'Cannot find the filter input');
const filterInput = await driver.findElement(By.xpath(kaotoLocators.KaotoCatalog.filterInput));
await filterInput.sendKeys('datamapper');
await driver.wait(until.elementLocated(By.xpath("//div[@data-testid='tile-kaoto-datamapper']")), 5000, 'Cannot find the tile for the DataMapper step');

await (await driver.findElement(By.xpath("//div[@data-testid='tile-kaoto-datamapper']"))).click();
await driver.wait(
until.elementLocated(By.xpath(kaotoLocators.KaotoCatalog.tileHeaderByTestId('kaoto-datamapper'))),
5000,
'Cannot find the tile for the DataMapper step',
);
await (await driver.findElement(By.xpath(kaotoLocators.KaotoCatalog.tileHeaderByTestId('kaoto-datamapper')))).click();
}

/**
*
* @param driver
* @param testId used for Kaoto 2.3
* @param nodeLabel used for Kaoto 2.4
*/
async function checkStepWithTestIdOrNodeLabelPresent(driver: WebDriver, testId: string, nodeLabel: string) {
await driver.wait(until.elementLocated(By.xpath(`//*[name()='g' and starts-with(@data-testid,'${testId}') or @data-nodelabel='${nodeLabel}']`)), 5_000);
await KaotoCanvas.findNodeByTestIdOrLabel(driver, testId, nodeLabel);
}

async function checkIntegrationNameInTopBarLoaded(driver: WebDriver, name: string) {
await driver.wait(
until.elementLocated(By.xpath(`//span[@data-testid='flows-list-route-id' and contains(., '${name}')]`)),
5_000,
`Unable to locate integration name '${name} in top bar!'`,
);
await KaotoEditor.waitForIntegrationName(driver, name);
}
32 changes: 9 additions & 23 deletions it-tests/MavenDependencyUpdate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import {
import {
By,
EditorView,
until,
VSBrowser,
WebDriver,
Workbench,
Expand All @@ -38,6 +37,7 @@ import {
CheckboxSetting,
before,
} from 'vscode-extension-tester';
import { KaotoCanvas } from './pageObjects';
import { assert, expect } from 'chai';
import * as fs from 'fs';

Expand Down Expand Up @@ -250,26 +250,13 @@ describe('Maven dependency update pom.xml', function () {
* Add the SQL component step to the topology.
*/
async function addSqlComponentStep() {
// hover over edge to show add step button
const setBodyToLogEdge = await driver.findElement(By.css('g[data-id^="my-camel-quarkus-route|route.from.steps.0.setBody >>> route.from.steps.1.log"]'));
await driver.actions().move({ origin: setBodyToLogEdge, duration: 2_000 }).perform();

// click Add Step button
const addStepButton = await setBodyToLogEdge.findElement(By.className('custom-edge__add-step add-step-icon'));
// hover over edge to show add step button and click Add Step button
const edgeSelector = 'g[data-id^="my-camel-quarkus-route|route.from.steps.0.setBody >>> route.from.steps.1.log"]';
const addStepButton = await KaotoCanvas.getAddStepButton(driver, edgeSelector);
await addStepButton.click();

// add text into catalog filter
await driver.wait(until.elementLocated(By.className('pf-v6-c-text-input-group__text-input')), 5_000);
const textInput = await driver.findElement(By.className('pf-v6-c-text-input-group__text-input'));
await textInput.click();
await textInput.clear();
await textInput.sendKeys('sql');

await driver.wait(until.elementLocated(By.css('div[data-testid="tile-sql"]')), 5_000);

// select SQL component from catalog
const sqlComponent = await driver.findElement(By.css('div[data-testid="tile-sql"]'));
await sqlComponent.click();
// filter catalog and select SQL component
await KaotoCanvas.filterCatalogAndSelectTile(driver, 'sql', 'sql');
}

/**
Expand All @@ -282,14 +269,13 @@ describe('Maven dependency update pom.xml', function () {
).kaotoWebview;

// right click on SQL component node
const sqlComponent = await driver.findElement(By.css('g[data-nodelabel="sql"]'));
await driver.actions().contextClick(sqlComponent).perform();
const sqlNode = await driver.findElement(By.css('g[data-nodelabel="sql"]'));
await KaotoCanvas.openContextMenu(driver, sqlNode);

await workaroundToRedrawContextualMenu(kaotoWebview);

// click Delete button
const deleteButton = await driver.findElement(By.css('li[data-testid="context-menu-item-delete"]'));
await deleteButton.click();
await KaotoCanvas.clickDeleteInContextMenu(driver);

// save editor
await kaotoWebview.switchBack();
Expand Down
52 changes: 17 additions & 35 deletions it-tests/PropertyPanelLoading.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { By, EditorView, until, VSBrowser, WebDriver, WebView } from 'vscode-extension-tester';
import { EditorView, VSBrowser, WebDriver, WebView } from 'vscode-extension-tester';
import * as path from 'path';
import { openAndSwitchToKaotoFrame } from './Util';
import { clickWhenClickable, dismissHoverOverlay, openAndSwitchToKaotoFrame } from './Util';
import { KaotoCanvas, KaotoEditor } from './pageObjects';

describe('Property panel loading test', function () {
this.timeout(60_000);
Expand All @@ -31,44 +32,25 @@ describe('Property panel loading test', function () {
});

after(async function () {
await kaotoWebview.switchBack();

const editorView = new EditorView();
await editorView.closeAllEditors();
if (kaotoWebview) {
try {
await kaotoWebview.switchBack();
} catch {
// already on the VS Code frame — switchBack is a no-op in that case
}
}
await new EditorView().closeAllEditors();
});

it('Open "choice.camel.yaml" file and check property panel is loading and closing', async function () {
kaotoWebview = (await openAndSwitchToKaotoFrame(workspaceFolder, 'choice.camel.yaml', driver, true)).kaotoWebview;
const stepWhenXpath = By.xpath(
`//*[name()='g' and starts-with(@data-testid,'custom-node__when')]|//*[name()='foreignObject' and @data-nodelabel='when']/div/div`,
);
await driver.wait(until.elementLocated(stepWhenXpath), 5_000);
await (await driver.findElement(stepWhenXpath)).click();
await driver.wait(until.elementLocated(By.className('pf-v6-c-card')), 5_000);

const closeBtn = await driver.findElement(By.xpath("//button[@data-testid='close-side-bar']"));
await driver.wait(
async () => {
return (await closeBtn.isDisplayed()) && (await closeBtn.isEnabled());
},
5_000,
'Close button is not displayed!',
);

// It seems that the close button might not react if clicked too fast after being displayed
await driver.sleep(1_00);
const logNode = await KaotoCanvas.findNodeByInnerTestId(driver, 'route.from.steps.0.choice.when.0.steps.0.log');
await dismissHoverOverlay(driver);
await clickWhenClickable(driver, logNode);

await closeBtn.click();

await driver.sleep(1_000);

try {
await driver.wait(until.elementLocated(By.className('pf-v6-c-card')), 5_000);
throw new Error('Property panel was not closed!');
} catch (error) {
if (error instanceof Error && error.name !== 'TimeoutError') {
throw new Error(error.message);
}
}
await KaotoEditor.waitForPropertyPanel(driver);
await KaotoEditor.closePropertyPanel(driver);
await KaotoEditor.waitForPropertyPanelClosed(driver);
});
});
Loading
Loading