-
Notifications
You must be signed in to change notification settings - Fork 0
add create, delete book scenario #1
base: main
Are you sure you want to change the base?
Changes from 9 commits
6914427
78eeb21
1d49921
4089771
6cd69b4
fef6251
dfb5953
0461ef2
34de867
c571d3a
16264d8
69cb95c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
tmp | ||
# Logs | ||
logs | ||
*.log | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
async function goHome() { | ||
await browser.goTo('#Shell-home'); | ||
await browser.waitForUI5(); | ||
} | ||
|
||
async function pressTile(name) { | ||
const control = await browser.asControl({ | ||
selector: { | ||
controlType: "sap.m.GenericTile", | ||
properties: { | ||
header: name | ||
} | ||
} | ||
}); | ||
await control.press() | ||
} | ||
|
||
async function searchFor(text) { | ||
await browser.asControl({ | ||
selector: { | ||
controlType: "sap.m.SearchField", | ||
interaction: { | ||
idSuffix: "I" | ||
} | ||
} | ||
}).enterText(text) | ||
} | ||
|
||
async function performStandardAction( name ) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. whitespacing btw method and parenthesis → please introduce a formatter (e.g. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added prettier as suggested, eslint also |
||
const control = await browser.asControl({ | ||
selector: { | ||
controlType: "sap.m.Button", | ||
interactable: true, | ||
id: new RegExp(`.*\:\:StandardAction\:\:${name}\$`) | ||
} | ||
}); | ||
await control.press(); | ||
} | ||
|
||
async function setFieldValue( name, value ) { | ||
const control = await browser.asControl({ | ||
selector: { | ||
controlType: "sap.m.Input", | ||
interaction: "root", | ||
labelFor: { | ||
text: name | ||
} | ||
} | ||
}); | ||
await control.setValue(value); | ||
} | ||
|
||
async function openValueHelpForField( name ) { | ||
const control = await browser.asControl({ | ||
selector: { | ||
controlType: "sap.m.Input", | ||
labelFor: { | ||
text: name | ||
} | ||
} | ||
}); | ||
await control.press(); | ||
} | ||
|
||
async function _findTableWithTitle(title, controlType, opt={}) { | ||
let { searchOpenDialogs } = opt; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure about your intended usage of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. changed that: let it be const ;) |
||
return await browser.asControl({ | ||
selector: { | ||
controlType, | ||
searchOpenDialogs, | ||
interaction: "root", | ||
descendant: { | ||
controlType: "sap.m.Title", | ||
properties: { | ||
text: { | ||
regex: { | ||
source: `^${title}` | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}) | ||
} | ||
|
||
async function chooseRowInValueHelpDialogTable( tableTitle, rowNumber ) { | ||
let table = await _findTableWithTitle(tableTitle, "sap.ui.table.Table", {searchOpenDialogs:true}); | ||
//let rows = await table.getAggregation('rows'); | ||
//let cells = await rows[rowNumber].getAggregation('cells'); | ||
//let id = await cells[0].getId(); | ||
let id = await table.getId()+`-rows-row${rowNumber}-col0`; | ||
await tapOnId(id); | ||
} | ||
|
||
async function selectRowInTable( tableTitle, targetRow ) { | ||
let table = await _findTableWithTitle(tableTitle, "sap.m.Table"); | ||
let items = await table.getItems(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this has proven to be a potential drawback: if the table in question has There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added a comment |
||
let checkbox = await items[targetRow].getMultiSelectControl(); | ||
await checkbox.fireSelect({selected:true}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please refrain from using any There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. changed to press - worked fine |
||
} | ||
|
||
async function navigateBack() { | ||
const control = await browser.asControl({ | ||
selector: { | ||
controlType: 'sap.ushell.ui.shell.ShellHeadItem', | ||
interactable: true, | ||
id: 'backBtn' | ||
} | ||
}); | ||
await control.press(); | ||
} | ||
|
||
async function pressButtonInDialog( text ) { | ||
const control = await browser.asControl({ | ||
selector: { | ||
controlType: "sap.m.Button", | ||
searchOpenDialogs: true, | ||
interactable: true, | ||
properties: { | ||
text | ||
} | ||
} | ||
}); | ||
await control.press(); | ||
} | ||
|
||
async function tapOnId(id) { | ||
await browser.executeScript('$("#"+$.escapeSelector(arguments[0])).trigger("tap")',[id]); | ||
await browser.waitForUI5(); | ||
} | ||
|
||
module.exports = { | ||
goHome, | ||
pressTile, | ||
searchFor, | ||
performStandardAction, | ||
setFieldValue, | ||
openValueHelpForField, | ||
chooseRowInValueHelpDialogTable, | ||
selectRowInTable, | ||
navigateBack, | ||
pressButtonInDialog, | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"name": "wdi5-fe-selectors", | ||
"description": "wdi5 selectors for Fiori Elements", | ||
"version": "1.0.0", | ||
"main": "lib/index.js", | ||
"files": [ | ||
"lib" | ||
], | ||
"scripts": { | ||
"test": "bash ./test/testCAPBookshop.sh" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
const { wdi5 } = require('wdio-ui5-service'); | ||
const lib = require('wdi5-fe-selectors'); | ||
|
||
describe('samples', () => { | ||
|
||
it('should log', () => { | ||
const logger = wdi5.getLogger(); | ||
logger.log('hello world!'); | ||
}) | ||
|
||
it('go home', async () => { | ||
await lib.goHome(); | ||
await _sleep(2 * 1000) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure why this is actually required - I get that FE is slow in general (aka resource-intensive), but waiting 2 secs is just too long IMO. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed as it is not needed |
||
}) | ||
|
||
it('new book', async () => { | ||
await lib.goHome(); | ||
await lib.pressTile('Manage Books'); | ||
await lib.performStandardAction('Create'); | ||
await lib.setFieldValue('Title', 'WDI5'); | ||
await lib.openValueHelpForField('Author'); | ||
await lib.chooseRowInValueHelpDialogTable('Items', 1); | ||
await lib.performStandardAction('Save'); | ||
await lib.navigateBack(); | ||
await lib.searchFor('WDI5'); | ||
await _sleep(2 * 1000) | ||
}) | ||
|
||
it('delete book', async () => { | ||
await lib.goHome(); | ||
await lib.pressTile('Manage Books'); | ||
await lib.selectRowInTable('Books', 0 ); | ||
await lib.selectRowInTable('Books', 1 ); | ||
await lib.performStandardAction('Delete'); | ||
await lib.pressButtonInDialog('Delete'); | ||
await _sleep(2 * 1000) | ||
}) | ||
|
||
}) | ||
|
||
function _sleep(ms) { | ||
return new Promise((resolve) => { | ||
setTimeout(resolve, ms); | ||
}); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
#!/bin/env bash | ||
|
||
set -x | ||
set -e | ||
|
||
ROOT_DIR=`pwd` | ||
WORK_DIR=tmp/testCAPBookshop | ||
|
||
if [ -d ${WORK_DIR} ]; then | ||
|
||
cd ${WORK_DIR} | ||
cd service | ||
|
||
else | ||
|
||
mkdir -p ${WORK_DIR} | ||
cd ${WORK_DIR} | ||
|
||
npm init -y | ||
|
||
npm init -w dk -y | ||
npm add -w dk @sap/cds-dk | ||
|
||
npm init -w service -y | ||
|
||
cd service | ||
rm package.json | ||
|
||
npx cds init | ||
npx cds add sample | ||
|
||
npm add ${ROOT_DIR} || true | ||
|
||
npm init wdi5@latest | ||
|
||
fi | ||
|
||
rm webapp/test/e2e/*.js | ||
cp ${ROOT_DIR}/test/*.js webapp/test/e2e | ||
|
||
PORT=8080 ../node_modules/.bin/cds run & | ||
CDSPID=$! | ||
echo "Started process with PID ${CDSPID}" | ||
|
||
export wdi5_username="alice" | ||
export wdi5_password="" | ||
|
||
set +e | ||
|
||
npm run wdi5 | ||
#../node_modules/.bin/wdio run ./webapp/test/e2e/wdio.conf.js --headless | ||
RC=$? | ||
|
||
# clean up | ||
echo Terminate process with PID $CDSPID | ||
kill -s SIGUSR2 $CDSPID | ||
|
||
if [ $RC -ne 0 ]; then | ||
echo "Test failed, rc:${RC}" | ||
exit $RC | ||
else | ||
echo "Test succeeded, rc:${RC}" | ||
fi |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
let args = ["--window-size=1920,1080"]; | ||
|
||
if(process.argv.indexOf("--headless") > -1) | ||
args.push("--headless=new"); | ||
if(process.argv.indexOf("--debug") > -1) | ||
args.push("--auto-open-devtools-for-tabs"); | ||
|
||
exports.config = { | ||
specs: ["./**/*.test.js"], | ||
exclude: [ | ||
], | ||
maxInstances: 10, | ||
capabilities: [ | ||
{ | ||
maxInstances: 5, | ||
// | ||
browserName: "chrome", | ||
"goog:chromeOptions": { args }, | ||
acceptInsecureCerts: true, | ||
"wdi5:authentication": { | ||
provider: "BasicAuth", | ||
basicAuthUrls: [`http://localhost:8080/odata/v4/admin/Books`] | ||
} | ||
} | ||
], | ||
logLevel: "error", | ||
bail: 0, | ||
baseUrl: "http://localhost:8080/", | ||
waitforTimeout: 10000, | ||
connectionRetryTimeout: process.argv.indexOf("--debug") > -1 ? 1200000 : 120000, | ||
connectionRetryCount: 3, | ||
services: [ | ||
"ui5" | ||
], | ||
framework: "mocha", | ||
reporters: ["spec"], | ||
mochaOpts: { | ||
ui: "bdd", | ||
timeout: process.argv.indexOf("--debug") > -1 ? 600000 : 60000 | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where are
goTo
andwaitForUI5()
injected into the browser object?a comment here might help the inclined developer :)
plus: if this is primarily targeting
wdi5
, thewdi5.goTo()
seems more appropriate.plus: we should refrain from any manual
waitForXX
APIs and rather leave it to the test framework to sync app lifecyle with test lifecycle. E.g. withwdi5
, no waiting for any ops to finish is necessary as the underlying RecordReplay-API takes care of this and is accounted for inwdi5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
switched to wdi5.goTo()