Skip to content

Commit

Permalink
feat(matcher): i18n, ancestor, descendant, sibling, labelFor
Browse files Browse the repository at this point in the history
* feat(devtools): add DEBUG flag with auto open dev tools

* feat(#129): i18n text matcher

* revert: auto-open-dev-tools

* feat(128): add test for descendant matcher

* refactor: matcher test to a separate file

* feat(matchers): add new matcher types

* feat(matcher): ancestor and labelFor

* fix(matcher): ancestor

* fix(matcher): interactable

* feat(matcher): prep for matcher with constructor

* fix(matcher): update siblings matcher and test with todo

* fix: rm double ancestor

* fix: createMatcher

* fix: matcher test

* fix: rm siblings matcher

* feat(combobox): two matcher examples for combobox #121

* docs: github issue

* feat(test): separated wdio and wdi5 test

* fix(wdio): rm test for wdio id selector

* fix: revert searchfield test

* fix(searchfield): rm searchfield

Co-authored-by: dominik.feininger <[email protected]>
Co-authored-by: Simon Coen <[email protected]>
  • Loading branch information
3 people authored Mar 18, 2022
1 parent 6c92004 commit 1fd328c
Show file tree
Hide file tree
Showing 8 changed files with 262 additions and 17 deletions.
34 changes: 32 additions & 2 deletions client-side-js/injectUI5.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,20 @@ async function clientSide_injectUI5(config, waitForUI5Timeout) {
// known side effect this call triggers the back to node scope, the other sap.ui.require continue to run in background in browser scope
done(true)
})

// make sure the resources are required
// TODO: "sap/ui/test/matchers/Sibling",
sap.ui.require(
[
"sap/ui/test/matchers/BindingPath",
"sap/ui/test/matchers/I18NText",
"sap/ui/test/matchers/Properties",
"sap/ui/test/matchers/Ancestor",
"sap/ui/test/matchers/LabelFor"
"sap/ui/test/matchers/LabelFor",
"sap/ui/test/matchers/Descendant",
"sap/ui/test/matchers/Interactable"
],
(BindingPath, I18NText, Properties, Ancestor, LabelFor) => {
(BindingPath, I18NText, Properties, Ancestor, LabelFor, Descendant, Interactable) => {
/**
* used to dynamically create new control matchers when searching for elements
*/
Expand Down Expand Up @@ -129,6 +133,32 @@ async function clientSide_injectUI5(config, waitForUI5Timeout) {
}
}

/*
oSelector.matchers = []
// since for these matcher a constructor call is neccessary
if (oSelector.sibling && oSelector.sibling.options) {
// don't construct matcher if not needed
const options = oSelector.sibling.options
delete oSelector.sibling.options
oSelector.matchers.push(new Sibling(oSelector.sibling, options))
delete oSelector.sibling
}
if (oSelector.descendant && (typeof oSelector.descendant.bDirect !== 'undefined')) {
// don't construct matcher if not needed
const bDirect = oSelector.descendant.bDirect
delete oSelector.descendant.bDirect
oSelector.matchers.push(new Descendant(oSelector.descendant, !!bDirect))
delete oSelector.descendant
}
if (oSelector.ancestor && (typeof oSelector.ancestor.bDirect !== 'undefined')) {
// don't construct matcher if not needed
const bDirect = oSelector.ancestor.bDirect
delete oSelector.ancestor.bDirect
oSelector.matchers.push(new Ancestor(oSelector.ancestor, !!bDirect))
delete oSelector.ancestor
}
*/
return oSelector
}

Expand Down
2 changes: 2 additions & 0 deletions examples/ui5-js-app/webapp/controller/Main.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ sap.ui.define(
checkbox: false,
barcode: ""
}
// TODO:
// searchValue: "search Value"

let testModel = new JSONModel(jData)
this.getView().setModel(testModel, "testModel")
Expand Down
1 change: 1 addition & 0 deletions examples/ui5-js-app/webapp/i18n/i18n.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ appDescription=App Description

###

startPage.userButton.text=User Test Text
startPage.navButton.text=to Other view
startPage.currentUI5.text=most current UI5 version available
startPage.title.text=UI5 demo
Expand Down
21 changes: 17 additions & 4 deletions examples/ui5-js-app/webapp/test/e2e/basic.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe("ui5 basic", () => {
})

// #118
it("should use a control selector with dots and colons", async () => {
it("should use a control selector with dots and colons (wdi5)", async () => {
const selector = {
selector: {
id: "Title::NoAction.h1",
Expand All @@ -21,14 +21,16 @@ describe("ui5 basic", () => {

// ui5
const titleWUi5 = await browser.asControl(selector).getText()
expect(titleWUi5).toEqual("UI5 demo")
})

// #118
/* it("should use a control selector with dots and colons (wdio)", async () => {
// working webdriver example with xpath id selector
const titleElement = await $('//*[@id="container-Sample---Main--Title::NoAction.h1"]')
const titleWwdio = await titleElement.getText()

expect(titleWUi5).toEqual("UI5 demo")
expect(titleWwdio).toEqual("UI5 demo")
})
}) */

it("check for invalid control selector", async () => {
const selector1 = {
Expand All @@ -48,4 +50,15 @@ describe("ui5 basic", () => {
expect(invalidControl1).toContain("ERROR")
expect(invalidControl2).toContain("ERROR")
})

/* it("check for Searchfield Properties", async () => {
const searchFieldSelector = {
selector: {
id: "idSearchfield",
viewName: "test.Sample.view.Main"
}
}
expect(await browser.asControl(searchFieldSelector).getValue()).toEqual("search Value")
}) */
})
171 changes: 171 additions & 0 deletions examples/ui5-js-app/webapp/test/e2e/matcher.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
const Main = require("./pageObjects/Main")

describe("ui5 matcher tests", () => {
before(async () => {
await Main.open()
})

it("check i18nText Button matcher", async () => {
const i18nSelector = {
selector: {
i18NText: {
propertyName: "text",
key: "startPage.navButton.text"
},
controlType: "sap.m.Button",
viewName: "test.Sample.view.Main"
}
}

const button = await browser.asControl(i18nSelector)
const buttonText = await button.getText()
expect(buttonText).toEqual("to Other view")
})

it("check i18nText matcher user button", async () => {
const i18nSelector = {
selector: {
i18NText: {
propertyName: "text",
key: "startPage.userButton.text"
},
controlType: "sap.m.Button",
viewName: "test.Sample.view.Main"
}
}

const button = await browser.asControl(i18nSelector)
const buttonText = await button.getText()
expect(buttonText).toEqual("User Test Text")
})

it("check descendant matcher for panel", async () => {
const descendantSelector = {
selector: {
controlType: "sap.m.Panel",
descendant: {
viewName: "test.Sample.view.Main",
controlType: "sap.m.Title",
properties: {
text: "Custom Toolbar with a header text"
}
}
}
}

const panel = await browser.asControl(descendantSelector)

const sPanelText = await panel.getHeaderText()
expect(sPanelText).toEqual("Header Text")

const bPanelExpandable = await panel.getExpandable()
expect(bPanelExpandable).toEqual(true)
})

it("check labelFor matcher ", async () => {
const labelForSelector = {
selector: {
controlType: "sap.m.DateTimePicker",
labelFor: {
text: "labelFor DateTimePicker"
}
}
}

const datePicker = await browser.asControl(labelForSelector)

const sDatePickerPlaceholder = await datePicker.getPlaceholder()
expect(sDatePickerPlaceholder).toEqual("Enter Date ...")
})

it("check anchestor matcher", async () => {
const ancestorSelector = {
selector: {
controlType: "sap.m.Title",
ancestor: {
viewName: "test.Sample.view.Main",
controlType: "sap.m.Panel"
}
}
}

const title = await browser.asControl(ancestorSelector)

const sTitleText = await title.getText()
expect(sTitleText).toEqual("Custom Toolbar with a header text")
})

it("check siblings matcher first Occurance", async () => {
const siblingsSelector = {
selector: {
controlType: "sap.m.Button",
sibling: {
viewName: "test.Sample.view.Main",
controlType: "sap.m.Button",
properties: {
text: "open Barcodescanner"
}
}
}
}

const button = await browser.asControl(siblingsSelector)

const sButtonText = await button.getText()
expect(sButtonText).toEqual("to Other view")
})

// TODO: ciblings matacher with options parameter
it.skip("check siblings matcher next Occurance", async () => {
const siblingsSelector = {
selector: {
controlType: "sap.m.Button",
sibling: {
viewName: "test.Sample.view.Main",
controlType: "sap.m.Button",
properties: {
text: "open Barcodescanner"
},
options: {
next: true
}
}
}
}

const button = await browser.asControl(siblingsSelector)

const sButtonText = await button.getText()
expect(sButtonText).toEqual("open Dialog")
})

it("check interactable matcher", async () => {
const interactableSelector = {
selector: {
controlType: "sap.m.Button",
interactable: true,
visible: true
}
}

const button = await browser.asControl(interactableSelector)

const sButtonStatus = await button.getEnabled()
expect(sButtonStatus).toBeTruthy()
})

// #131
/* it("check for Searchfield Properties", async () => {
const searchFieldSelector = {
selector: {
// id: "idSearchfield",
viewName: "test.Sample.view.Main",
interactable: true,
visible: true,
controlType: "sap.m.SearchField"
}
}
expect(await browser.asControl(searchFieldSelector).getValue()).toEqual("search Value")
}) */
})
8 changes: 7 additions & 1 deletion examples/ui5-js-app/webapp/view/Main.view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,15 @@
id="NavFwdButton"
text="{i18n>startPage.navButton.text}"
press="navFwd" />
<Button icon="sap-icon://user-edit"
id="user-test-button"
text="{i18n>startPage.userButton.text}"/>
<Button text="IA Sync"
press="onPress" />
<Text text="{i18n>startPage.text.username}" />
<Input id="mainUserInput"
value="{/Customers('TRAIH')/ContactName}" />
<Panel expandable="true">
<Panel expandable="true" headerText="Header Text">
<headerToolbar>
<OverflowToolbar>
<Title text="Custom Toolbar with a header text" />
Expand All @@ -41,6 +44,7 @@
<Text text="Lorem ipsum dolor st amet" />
</content>
</Panel>
<Label labelFor="idDateTime" text="labelFor DateTimePicker"/>
<DateTimePicker id="idDateTime"
placeholder="Enter Date ..." />
<Button text="{testModel>/buttonText}"
Expand All @@ -62,6 +66,8 @@
<Button text="open Dialog"
press="openDialog"
id="openDialogButton" />
<!-- TODO -->
<!-- <SearchField id="idSearchfield" value="{testModel>/searchValue}"/> -->
</VBox>
</content>
</Page>
Expand Down
22 changes: 14 additions & 8 deletions src/lib/wdi5-bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,16 @@ export async function checkForUI5Page() {
* @returns wdio_ui5_key
*/
function _createWdioUI5KeyFromSelector(selector: wdi5Selector): string {
const orEmpty = (string) => string || "-"
const orEmpty = (string) => string || ""

const _selector = selector.selector
const wdi5_ui5_key = `${orEmpty(_selector.id)}_${orEmpty(_selector.viewName)}_${orEmpty(
const wdi5_ui5_key = `${orEmpty(_selector.id)}${orEmpty(_selector.viewName)}${orEmpty(
_selector.controlType
)}_${orEmpty(JSON.stringify(_selector.bindingPath))}_${orEmpty(JSON.stringify(_selector.I18NText))}_${orEmpty(
_selector.labelFor
)}_${orEmpty(JSON.stringify(_selector.properties))}`.replace(/[^0-9a-zA-Z]+/, "")
)}${orEmpty(JSON.stringify(_selector.bindingPath))}${orEmpty(JSON.stringify(_selector.i18NText))}${orEmpty(
JSON.stringify(_selector.descendant)
)}${orEmpty(JSON.stringify(_selector.labelFor))}${orEmpty(JSON.stringify(_selector.properties))}${orEmpty(
JSON.stringify(_selector.ancestor)
)}`.replace(/[^0-9a-zA-Z]+/, "")

return wdi5_ui5_key
}
Expand All @@ -160,14 +162,18 @@ function _verifySelector(wdi5Selector: wdi5Selector) {
wdi5Selector.selector.hasOwnProperty("viewName") ||
wdi5Selector.selector.hasOwnProperty("bindingPath") ||
wdi5Selector.selector.hasOwnProperty("controlType") ||
wdi5Selector.selector.hasOwnProperty("I18NText") ||
wdi5Selector.selector.hasOwnProperty("i18NText") ||
wdi5Selector.selector.hasOwnProperty("labelFor") ||
wdi5Selector.selector.hasOwnProperty("properties")
wdi5Selector.selector.hasOwnProperty("descendant") ||
wdi5Selector.selector.hasOwnProperty("ancestor") ||
wdi5Selector.selector.hasOwnProperty("properties") ||
wdi5Selector.selector.hasOwnProperty("sibling") ||
wdi5Selector.selector.hasOwnProperty("interactable")
) {
return true
}
Logger.error(
"Specified selector is not valid. Please use at least one of: 'id, viewName, bindingPath, controlType, I18NText, labelFor, properties' -> abort"
"Specified selector is not valid. Please use at least one of: 'id, viewName, bindingPath, controlType, i18NText, labelFor, ancestor, properties, descendant, sibling, interactable' -> abort"
)
return false
}
Expand Down
Loading

0 comments on commit 1fd328c

Please sign in to comment.