Skip to content
Open
Show file tree
Hide file tree
Changes from all 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 .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "monthly"
cooldown:
default-days: 2
allow:
- dependency-type: "production"

- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
cooldown:
default-days: 2
2 changes: 1 addition & 1 deletion examples/ui5-js-app/jsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"@openui5/types",
"@wdio/globals/types",
"@wdio/mocha-framework",
"wdio-ui5-service/dist/cjs",
"wdio-ui5-service",
"expect-webdriverio"
]
}
Expand Down
7 changes: 7 additions & 0 deletions examples/ui5-js-app/webapp/controller/Main.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ sap.ui.define(
onSearch(oEvent) {
this.getView().byId("idSearchResult").setText(oEvent.getSource().getValue())
},
onKeepFocusInputChange(oEvent) {
this.getView().byId("idKeepFocusResult").setText(oEvent.getSource().getValue())
},
onClearTextInputChange(oEvent) {
console.log(oEvent.getSource().getValue())
this.getView().byId("idClearTextResult").setText(oEvent.getSource().getValue())
},
onTest(oEvent) {
this.onBoo(oEvent)
},
Expand Down
65 changes: 65 additions & 0 deletions examples/ui5-js-app/webapp/test/e2e/allControlsInteraction.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const Main = require("./pageObjects/Main")

describe("allControls interaction", () => {
before(async () => {
await Main.open()
})

it("should press a specific button from allControls", async () => {
const selector = {
selector: {
controlType: "sap.m.Button",
viewName: "test.Sample.view.Main",
interaction: "root"
}
}

const buttons = await browser.allControls(selector)
// Find the button with a specific ID among all buttons

let targetButton
for (const btn of buttons) {
const id = await btn.getId()
if (id.includes("idIaSync")) {
targetButton = btn
break
}
}

expect(targetButton).toBeDefined()
// The fix ensures that .press() uses the specific ID of this control instance
await targetButton.press()

// Verification: we can check if the button is still there or some other state
// In Main.controller.js, onPress shows a MessageToast.
// Hard to verify MessageToast without further setup, but we can at least ensure the call doesn't fail
// and targets the right element.
expect(await targetButton.getVisible()).toBeTruthy()
})

it("should enter text into a specific input from allControls", async () => {
const selector = {
selector: {
controlType: "sap.m.Input",
viewName: "test.Sample.view.Main",
interaction: "root"
}
}

const inputs = await browser.allControls(selector)
let targetInput
for (const input of inputs) {
const id = await input.getId()
if (id.includes("mainUserInput")) {
targetInput = input
break
}
}

expect(targetInput).toBeDefined()
const testText = "Typed from allControls"
await targetInput.enterText(testText)

expect(await targetInput.getValue()).toEqual(testText)
})
})
27 changes: 27 additions & 0 deletions examples/ui5-js-app/webapp/test/e2e/allControlsPress.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const Other = require("./pageObjects/Other")

describe("ui5 basic, press all buttons", () => {
before(async () => {
await Other.open()
})

it("test with pressing multiple checkboxes", async () => {
const selector = {
selector: {
controlType: "sap.m.CheckBox",
viewName: "test.Sample.view.Other",
interaction: "press"
}
}
const checkboxList = await browser.allControls(selector)

expect(checkboxList.length).toEqual(9)

for await (let checkbox of checkboxList) {
const selectedBeforePress = await checkbox.getSelected()
await checkbox.press()
const selectedAfterPress = await checkbox.getSelected()
expect(selectedAfterPress).toEqual(!selectedBeforePress)
}
})
})
95 changes: 95 additions & 0 deletions examples/ui5-js-app/webapp/test/e2e/ancestor-descendant.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
const Main = require("./pageObjects/Main")

describe("ancestor and descendant selector resolution", () => {
before(async () => {
await Main.open()
})

it("should find a control using an ancestor selector (asControl)", async () => {
const selector = {
selector: {
controlType: "sap.m.Title",
ancestor: {
controlType: "sap.m.Panel",
properties: {
headerText: "Header Text"
}
}
}
}
const title = await browser.asControl(selector)
expect(await title.getText()).toBe("Custom Toolbar with a header text")
})

it("should find a control using a descendant selector (asControl)", async () => {
const selector = {
selector: {
controlType: "sap.m.Panel",
descendant: {
controlType: "sap.m.Title",
properties: {
text: "Custom Toolbar with a header text"
}
}
}
}
const panel = await browser.asControl(selector)
expect(await panel.getHeaderText()).toBe("Header Text")
})

it("should find all controls using an ancestor selector (allControls)", async () => {
const selector = {
wdio_ui5_key: "allButtonsWithAncestor",
selector: {
controlType: "sap.m.Button",
ancestor: {
id: "page",
viewName: "test.Sample.view.Main"
}
}
}
const buttons = await browser.allControls(selector)
expect(Array.isArray(buttons)).toBe(true)
expect(buttons.length).toBe(9)
})

it("should find all controls using a descendant selector (allControls)", async () => {
const selector = {
wdio_ui5_key: "allPanelsWithDescendant",
selector: {
controlType: "sap.m.Panel",
descendant: {
controlType: "sap.m.Title",
properties: {
text: "Custom Toolbar with a header text"
}
}
}
}
const panels = await browser.allControls(selector)
expect(Array.isArray(panels)).toBe(true)
expect(panels.length).toBe(1)
expect(await panels[0].getHeaderText()).toBe("Header Text")
})

it("should find a control using nested ancestor/descendant selectors", async () => {
// Find the Title inside the Panel, which is inside the Page
const selector = {
selector: {
controlType: "sap.m.Title",
properties: {
text: "Custom Toolbar with a header text"
},
ancestor: {
controlType: "sap.m.Panel",
ancestor: {
id: "page",
viewName: "test.Sample.view.Main"
}
}
}
}
const title = await browser.asControl(selector)
expect(await title.getText()).toBe("Custom Toolbar with a header text")
})
})
154 changes: 154 additions & 0 deletions examples/ui5-js-app/webapp/test/e2e/interaction.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,158 @@ describe("interaction + binding", () => {

expect(await ui5Input.getProperty("value")).toEqual(inputText)
})

it("enterText() with pressEnterKey:true triggers search event", async () => {
const searchFieldSelector = {
selector: {
id: "idSearchfield",
viewName: viewName,
interaction: "focus"
}
}
const searchResultSelector = {
selector: {
id: "idSearchResult",
viewName: viewName
}
}

const searchTerm = "Alice"
const searchField = await browser.asControl(searchFieldSelector)
await searchField.enterText(searchTerm, { pressEnterKey: true })

const searchResult = await browser.asControl(searchResultSelector)
expect(await searchResult.getProperty("text")).toEqual(searchTerm)
})

it("enterText() with pressEnterKey:false does not trigger search event", async () => {
const searchFieldSelector = {
selector: {
id: "idSearchfield",
viewName: viewName
}
}
const searchResultSelector = {
selector: {
id: "idSearchResult",
viewName: viewName
}
}

// capture the current search result before typing (set by the previous test)
const searchResult = await browser.asControl(searchResultSelector)
const previousResult = await searchResult.getProperty("text")

const searchTerm = "Charlie"
const searchField = await browser.asControl(searchFieldSelector)
// pressEnterKey:false — text is entered but Enter is not pressed, so onSearch is not fired
await searchField.enterText(searchTerm, { pressEnterKey: false, keepFocus: true })

// result text must remain unchanged since the search event was not triggered
expect(await searchResult.getProperty("text")).toEqual(previousResult)
})

it("enterText() with keepFocus:false blurs the input and triggers change event", async () => {
const inputSelector = {
selector: {
id: "idKeepFocusInput",
viewName: viewName,
interaction: "focus"
}
}
const resultSelector = {
selector: {
id: "idKeepFocusResult",
viewName: viewName
}
}

const inputText = "keep focus off"
const input = await browser.asControl(inputSelector)
// keepFocus:false (default) — focus is removed after enterText, which fires the change event
await input.enterText(inputText, { keepFocus: false })

const result = await browser.asControl(resultSelector)
expect(await result.getProperty("text")).toEqual(inputText)
})

it("enterText() with keepFocus:true retains focus and does not trigger change event", async () => {
const inputSelector = {
selector: {
id: "idKeepFocusInput",
viewName: viewName,
interaction: "focus"
}
}
const resultSelector = {
selector: {
id: "idKeepFocusResult",
viewName: viewName
}
}

// capture current result (set by previous test)
const result = await browser.asControl(resultSelector)
const previousResult = await result.getProperty("text")

const inputText = "keep focus on"
const input = await browser.asControl(inputSelector)
// keepFocus:true — focus is retained after enterText, so no blur occurs and change event does not fire
await input.enterText(inputText, { keepFocus: true })

// result text must remain unchanged since the change event was not triggered
expect(await result.getProperty("text")).toEqual(previousResult)
})

it("enterText() with clearTextFirst:true replaces existing input value", async () => {
const inputSelector = {
selector: {
id: "idClearTextInput",
viewName: viewName,
interaction: "focus"
}
}
const resultSelector = {
selector: {
id: "idClearTextResult",
viewName: viewName
}
}

const appendedText = " World"
const input = await browser.asControl(inputSelector)
// clearTextFirst:true (default) — existing "Hello" is cleared before typing, so only appended text remains
await input.enterText(appendedText, { clearTextFirst: true })

const result = await browser.asControl(resultSelector)
expect(await result.getProperty("text")).toEqual(appendedText)
})

it.skip("enterText() with clearTextFirst:false appends to existing input value", async () => {
// TODO: perhaps capture UI5 event in a browser.execute command to ensure whether this has been triggered
const inputSelector = {
selector: {
id: "idClearTextInput",
viewName: viewName,
interaction: "focus"
}
}
const resultSelector = {
selector: {
id: "idClearTextResult",
viewName: viewName
}
}

const initialText = "Hello"
const appendedText = " World"
// restore a known value first (clearTextFirst:true so we start clean)
const input = await browser.asControl(inputSelector)
await input.enterText(initialText, { clearTextFirst: true })
// clearTextFirst:false — existing "Hello" is kept and new text is appended after it
await input.enterText(appendedText, { clearTextFirst: false })

const result = await browser.asControl(resultSelector)
expect(await result.getProperty("text")).toEqual(initialText + appendedText)
})
})
3 changes: 2 additions & 1 deletion examples/ui5-js-app/webapp/test/e2e/press.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ describe("custom wdi5 press event", async () => {
id: "container-Sample---Main--idDateTime-icon"
}
})
await element.fireEvent("press")
// await element.fireEvent("press")
await element.press()

startDate.setDate(startDate.getDate() + 1) // add one day to the start date
const tomorrowSuffix = startDate.toJSON().substring(0, 10).replaceAll("-", "")
Expand Down
Loading
Loading