From cf10129b683b7773131feb961a92694f0c339460 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 2 Mar 2021 17:14:38 +0100 Subject: [PATCH 1/5] Prepare for compiler v2 --- test/cds.ql.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cds.ql.test.js b/test/cds.ql.test.js index a8bfa7be..dfade6b0 100644 --- a/test/cds.ql.test.js +++ b/test/cds.ql.test.js @@ -365,7 +365,7 @@ describe('cds.ql → cqn', () => { }, }) - expect( + if (!is_v2) expect( SELECT.from(Foo).where(`x=`, 1, `or y.z is null and (a>`, 2, `or b=`, 3, `)`) ).to.eql(CQL`SELECT from Foo where x=1 or y.z is null and (a>2 or b=3)`) From 83537482b8bcad520b60bfdc22191b9e38199ac7 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 3 Mar 2021 22:47:23 +0100 Subject: [PATCH 2/5] Adding cucumber tests --- bookshop/app/vue/index.html | 6 +- package.json | 2 + test/features/bookshop.feature | 35 +++++++++ .../step_definitions/bookshop_steps.js | 77 +++++++++++++++++++ 4 files changed, 117 insertions(+), 3 deletions(-) create mode 100644 test/features/bookshop.feature create mode 100644 test/features/step_definitions/bookshop_steps.js diff --git a/bookshop/app/vue/index.html b/bookshop/app/vue/index.html index c8e23209..e18eabe7 100644 --- a/bookshop/app/vue/index.html +++ b/bookshop/app/vue/index.html @@ -44,11 +44,11 @@

{{ document.title }}

- +

{{ book.title }}

diff --git a/package.json b/package.json index 9c5c6c34..0bf966db 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,8 @@ "chai": "^4.2.0", "chai-as-promised": "^7.1.1", "chai-subset": "^1.6.0", + "@cucumber/cucumber": "^7.0.0", + "selenium-webdriver": "^4.0.0-beta.1", "sqlite3": "5.0.0" }, "scripts": { diff --git a/test/features/bookshop.feature b/test/features/bookshop.feature new file mode 100644 index 00000000..6c1f4105 --- /dev/null +++ b/test/features/bookshop.feature @@ -0,0 +1,35 @@ +Feature: List Books using Vue.js UI + + Scenario: Launch cds server for bookshop + When we run the 'bookshop' server + And wait for 1s + Then it should listen at 'http://localhost:4004' + + Scenario: Display Books List + When we open page '/vue/index.html' + And wait for 1s + Then it should list these rows in table 'books': + | Wuthering Heights | Emily Brontë | + | Jane Eyre | Charlotte Brontë | + | The Raven | Edgar Allen Poe | + | Eleonora | Edgar Allen Poe | + | Catweazle | Richard Carpenter | + + Scenario: Select a Book + When we click on the 1st row in table 'books' + Then it shows '12' in 'stock' + + Scenario: Order One Book + When we click on the 1st row in table 'books' + And we click on button 'Order:' + Then it succeeds with 'ordered 1 item(s)' + + Scenario: Order Four Books + When we enter '4' into 'amount' + And we click on button 'Order:' + Then it succeeds with 'ordered 4 item(s)' + + Scenario: Order Amount Exceeding Stock + When we enter '9' into 'amount' + And we click on button 'Order:' + Then it fails with '9 exceeds stock' diff --git a/test/features/step_definitions/bookshop_steps.js b/test/features/step_definitions/bookshop_steps.js new file mode 100644 index 00000000..ccbea7ef --- /dev/null +++ b/test/features/step_definitions/bookshop_steps.js @@ -0,0 +1,77 @@ +const { Given, When, Then, AfterAll } = require('@cucumber/cucumber') +const { Builder, By } = require('selenium-webdriver') +const browser = (new Builder).forBrowser('safari').build() +const cds = require ('@sap/cds/lib') + +process.env.cds_requires_auth_strategy = 'dummy' + +let axios = require('axios').default +let {display} = browser + +When('we run the {string} server', project => cds.exec('watch', project)) +Then('it should listen at {string}', baseURL => { + axios = axios.create({ baseURL }) + display = url => browser.get (baseURL+url) + return axios.head() +}) +Then('terminate the server', ()=> process.exit()) + + + +When(/wait for (\d+)\s*(\w+)/, {timeout:60*1000}, (delay, unit, done) => { + const factor = { + ms: 1, + s: 1000, sec: 1000, second: 1000, seconds: 1000, + m: 60*1000, min: 60*1000, minute: 60*1000, minutes: 60*1000, + h: 60*60*1000, hr: 60*60*1000, hour: 60*60*1000, hours: 60*60*1000, + }[unit] + if (!factor) throw `Unknown duration unit: ${unit}` + setTimeout (done, delay * factor) +}) + +AfterAll(()=> setTimeout (process.exit, 111)) + + + + + +When('we open page {string}', page => display(page)) + +Then('it should list these rows in table {string}:', async (id,data) => { + let rows = await browser.findElements(By.css(`#${id} tr`)); rows.shift() + await Promise.all (data.rawTable.map (async (row,i)=>{ + const tr = await rows[i].getText() + for (let each of row) if (!tr.match(each)) throw `Didn't find '${each}' in web page as expected` + })) +}) + +When(/we click on the (\d+)(?:st|nd|rd|th) row in table '(\w+)'/, async (row, id) => { + let rows = await browser.findElements(By.css(`#${id} tr`)) + let td = await rows[row].findElement(By.css('td')) + return td.click() +}) + +When('we enter {string} into {string}', async (value,id) => { + const field = await browser.findElement(By.css(`input#${id}`)) + return field.sendKeys('\b\b\b\b\b\b',value) +}) + +When('we click on button {string}', async (text) => { + const button = await browser.findElement(By.css(`input[value='${text}']`)) + return button.click() +}) + +Then('it succeeds with {string}', async message => { + const element = await browser.wait (browser.findElement(By.css(`span.succeeded`))) + return (await element.getText()).includes(message) +}) + +Then('it fails with {string}', async message => { + const element = await browser.wait (browser.findElement(By.css(`span.failed`))) + return (await element.getText()).includes(message) +}) + +Given('we login as {string}, {string}', async (username, password) => { + const alert = await browser.switchTo().alert() + return alert.authenticateAs(username, password) +}) From eb98444afbc2813f6b4b51171b24322772ed30eb Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 3 Mar 2021 23:11:41 +0100 Subject: [PATCH 3/5] one more --- test/features/step_definitions/bookshop_steps.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/features/step_definitions/bookshop_steps.js b/test/features/step_definitions/bookshop_steps.js index ccbea7ef..131eb9a6 100644 --- a/test/features/step_definitions/bookshop_steps.js +++ b/test/features/step_definitions/bookshop_steps.js @@ -71,6 +71,11 @@ Then('it fails with {string}', async message => { return (await element.getText()).includes(message) }) +Then('it shows {string} in {string}', async (message,id) => { + const element = await browser.wait (browser.findElement(By.id(id))) + return (await element.getText()).includes(message) +}) + Given('we login as {string}, {string}', async (username, password) => { const alert = await browser.switchTo().alert() return alert.authenticateAs(username, password) From 5135276952371f99901f0347bbca5cc0e5a9e5f2 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 3 Mar 2021 23:22:43 +0100 Subject: [PATCH 4/5] copy error --- test/features/bookshop.feature | 1 - 1 file changed, 1 deletion(-) diff --git a/test/features/bookshop.feature b/test/features/bookshop.feature index 6c1f4105..1ff0964c 100644 --- a/test/features/bookshop.feature +++ b/test/features/bookshop.feature @@ -20,7 +20,6 @@ Feature: List Books using Vue.js UI Then it shows '12' in 'stock' Scenario: Order One Book - When we click on the 1st row in table 'books' And we click on button 'Order:' Then it succeeds with 'ordered 1 item(s)' From 9ce3bb9ef6b8a8f2764285a8dfa23213687836c0 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 3 Mar 2021 23:25:45 +0100 Subject: [PATCH 5/5] typo --- test/features/bookshop.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/features/bookshop.feature b/test/features/bookshop.feature index 1ff0964c..ab3288b7 100644 --- a/test/features/bookshop.feature +++ b/test/features/bookshop.feature @@ -20,7 +20,7 @@ Feature: List Books using Vue.js UI Then it shows '12' in 'stock' Scenario: Order One Book - And we click on button 'Order:' + When we click on button 'Order:' Then it succeeds with 'ordered 1 item(s)' Scenario: Order Four Books