From b7339bab6a2c288da4b1b08e813e3551279dce41 Mon Sep 17 00:00:00 2001 From: D050513 Date: Tue, 18 Jun 2024 14:23:23 +0200 Subject: [PATCH 1/5] accept:IEEE754Compatible=true by default --- test/odata.test.js | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/test/odata.test.js b/test/odata.test.js index f1c7562c..849c04b0 100644 --- a/test/odata.test.js +++ b/test/odata.test.js @@ -3,6 +3,7 @@ const { GET, POST, PATCH, axios, expect } = cds.test(__dirname+'/..') const EDIT = (url) => POST (url+'/TravelService.draftEdit',{}) const SAVE = (url) => POST (url+'/TravelService.draftActivate') axios.defaults.headers['content-type'] = 'application/json;IEEE754Compatible=true' // REVISIT: can be removed when @sap/cds 5.1.5 is released? +axios.defaults.headers.accept = 'application/json;IEEE754Compatible=true' //> for cds^7; decimals and int64s as strings with cds^8 to ensure precision axios.defaults.auth = { username: 'alice', password: 'admin' } describe ("Basic Querying", () => { @@ -43,7 +44,7 @@ describe ("Basic Querying", () => { describe('Basic OData', () => { it('serves $metadata documents in v4', async () => { - const { headers, status, data } = await GET `/processor/$metadata` + const { headers, status, data } = await GET(`/processor/$metadata`, { headers: { accept: 'application/xml' } }) expect(status).to.equal(200) expect(headers).to.contain({ // 'content-type': 'application/xml', //> fails with 'application/xml;charset=utf-8', which is set by express @@ -58,7 +59,7 @@ describe('Basic OData', () => { const { data } = await GET(`/processor/Travel?$filter=TravelUUID eq '00667221A8E4645C17002DF03754AB66'`) expect(data.value).to.containSubset([{ BeginDate: '2023-08-02', - BookingFee: 60, + BookingFee: '60', createdAt: expectedValue => /2023-07-16T18:42:07\.000(0000)?Z/.test(expectedValue), // timestamp precision increase with cds^7 createdBy: 'Hansmann', CurrencyCode_code: 'SGD', @@ -71,7 +72,7 @@ describe('Basic OData', () => { LastChangedBy: 'Deichgraeber', to_Agency_AgencyID: '070029', to_Customer_CustomerID: '000318', - TotalPrice: 23439, + TotalPrice: '23439', TravelID: 175, TravelStatus_code: 'A', TravelUUID: '00667221A8E4645C17002DF03754AB66' @@ -134,7 +135,7 @@ describe('Basic OData', () => { }) const { data: newTravel } = await SAVE (`/processor/Travel(TravelUUID='${newDraft.TravelUUID}',IsActiveEntity=false)`) - expect(newTravel).to.contain({ TravelID: 4134, TotalPrice: 11 }) + expect(newTravel).to.contain({ TravelID: 4134, TotalPrice: '11' }) }) it ('re-calculates totals after booking fee changed', async ()=>{ @@ -144,10 +145,7 @@ describe('Basic OData', () => { let Supplement = `/processor/BookingSupplement(BookSupplUUID='85D87221A8E4645C17002DF03754AB66',IsActiveEntity=false)` let { data:draft } = await EDIT (Travel4133) - expect(draft).to.containSubset({ - TotalPrice: 7375, - TravelID: 4133, - }) + expect(draft).to.containSubset({ TravelID: 4133, TotalPrice: '7375' }) // Ensure it is not in accepted state as that would disallow changing await POST (Draft +`/TravelService.rejectTravel`) @@ -155,19 +153,19 @@ describe('Basic OData', () => { // Change the Travel's Booking Fee await PATCH (Draft, { BookingFee: '120' }) - await expect_totals (7475) + await expect_totals ('7475') // Change a Booking's Flight Price await PATCH (Booking, { FlightPrice: '1657' }) - await expect_totals (5475) + await expect_totals ('5475') // Change a Supplements's Price await PATCH (Supplement, { Price: '220' }) - await expect_totals (5675) + await expect_totals ('5675') // Save Draft await SAVE (Draft) - await expect_totals (5675, 'IsActiveEntity=true') + await expect_totals ('5675', 'IsActiveEntity=true') async function expect_totals (expected, _active = 'IsActiveEntity=false') { let { data: { TotalPrice } } = await GET (`/processor/Travel(TravelUUID='76757221A8E4645C17002DF03754AB66',${_active})? @@ -179,26 +177,26 @@ describe('Basic OData', () => { it('deduct discount multiple times does not end up in error', async () => { const { data: res1 } = await GET `/processor/Travel(TravelUUID='52657221A8E4645C17002DF03754AB66',IsActiveEntity=true)` - expect(res1).to.contain({ TotalPrice: 900, BookingFee: 20 }) + expect(res1).to.contain({ TotalPrice: '900', BookingFee: '20' }) const { data: res2 } = await POST( `/processor/Travel(TravelUUID='52657221A8E4645C17002DF03754AB66',IsActiveEntity=true)/TravelService.deductDiscount`, { percent: 11 } ) - expect(res2).to.contain({ TotalPrice: 897.8, BookingFee: 17.8 }) + expect(res2).to.contain({ TotalPrice: '897.8', BookingFee: '17.8' }) const { data: res3 } = await POST( `/processor/Travel(TravelUUID='52657221A8E4645C17002DF03754AB66',IsActiveEntity=true)/TravelService.deductDiscount`, { percent: 11 } ) - expect(res3).to.contain({ TotalPrice: 895.842, BookingFee: 15.842 }) + expect(res3).to.contain({ TotalPrice: '895.842', BookingFee: '15.842' }) const { data: res4 } = await POST( `/processor/Travel(TravelUUID='52657221A8E4645C17002DF03754AB66',IsActiveEntity=true)/TravelService.deductDiscount`, { percent: 11 } ) // rounded to 3 decimals - expect(res4).to.contain({ TotalPrice: 894.099, BookingFee: 14.099 }) + expect(res4).to.contain({ TotalPrice: '894.099', BookingFee: '14.099' }) }) it('allows deducting discounts on drafts as well', async ()=>{ @@ -206,10 +204,10 @@ describe('Basic OData', () => { const Draft = `/processor/Travel(TravelUUID='93657221A8E4645C17002DF03754AB66',IsActiveEntity=false)` const { data:res0 } = await GET (Active) - expect(res0).to.contain({ TravelID:66, TotalPrice: 729, BookingFee: 10 }) + expect(res0).to.contain({ TravelID: 66, TotalPrice: '729', BookingFee: '10' }) const { data:res1 } = await EDIT (Active) - expect(res1).to.contain({ TotalPrice: 729, BookingFee: 10 }) + expect(res1).to.contain({ TotalPrice: '729', BookingFee: '10' }) // Change the Travel's dates to avoid validation errors const today = new Date().toISOString().split('T')[0] @@ -218,15 +216,15 @@ describe('Basic OData', () => { await PATCH (Draft, { EndDate: tomorrow }) const { data:res2 } = await POST (`${Draft}/TravelService.deductDiscount`, { percent: 50 }) - expect(res2).to.contain({ TotalPrice: 724, BookingFee: 5 }) + expect(res2).to.contain({ TotalPrice: '724', BookingFee: '5' }) const { data:res3 } = await GET (Draft) - expect(res3).to.contain({ TotalPrice: 724, BookingFee: 5 }) + expect(res3).to.contain({ TotalPrice: '724', BookingFee: '5' }) await SAVE (Draft) const { data:res4 } = await GET (Active) - expect(res4).to.contain({ TotalPrice: 724, BookingFee: 5 }) + expect(res4).to.contain({ TotalPrice: '724', BookingFee: '5' }) }) }) From e57320c3ca0ef4a9860566af9412e259742251f2 Mon Sep 17 00:00:00 2001 From: D050513 Date: Tue, 18 Jun 2024 14:31:04 +0200 Subject: [PATCH 2/5] accept: '*/*' for cds^7 --- test/odata.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/odata.test.js b/test/odata.test.js index 849c04b0..92a63de9 100644 --- a/test/odata.test.js +++ b/test/odata.test.js @@ -44,7 +44,7 @@ describe ("Basic Querying", () => { describe('Basic OData', () => { it('serves $metadata documents in v4', async () => { - const { headers, status, data } = await GET(`/processor/$metadata`, { headers: { accept: 'application/xml' } }) + const { headers, status, data } = await GET(`/processor/$metadata`, { headers: { accept: '*/*' } }) //> for cds^7 expect(status).to.equal(200) expect(headers).to.contain({ // 'content-type': 'application/xml', //> fails with 'application/xml;charset=utf-8', which is set by express @@ -101,7 +101,7 @@ describe('Basic OData', () => { }) it('supports $value requests', async () => { - const { data } = await GET `/processor/Travel(TravelUUID='52657221A8E4645C17002DF03754AB66',IsActiveEntity=true)/to_Customer/LastName/$value` + const { data } = await GET(`/processor/Travel(TravelUUID='52657221A8E4645C17002DF03754AB66',IsActiveEntity=true)/to_Customer/LastName/$value`, { headers: { accept: '*/*' } }) //> for cds^7 expect(data).to.equal('Prinz') }) From 403cacd328024dab07c5971eb2270f765ebefe45 Mon Sep 17 00:00:00 2001 From: sjvans <30337871+sjvans@users.noreply.github.com> Date: Tue, 18 Jun 2024 22:19:27 +0200 Subject: [PATCH 3/5] Apply suggestions from code review --- test/odata.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/odata.test.js b/test/odata.test.js index 92a63de9..c03802cf 100644 --- a/test/odata.test.js +++ b/test/odata.test.js @@ -44,7 +44,7 @@ describe ("Basic Querying", () => { describe('Basic OData', () => { it('serves $metadata documents in v4', async () => { - const { headers, status, data } = await GET(`/processor/$metadata`, { headers: { accept: '*/*' } }) //> for cds^7 + const { headers, status, data } = await GET(`/processor/$metadata`, { headers: { accept: 'application/xml' } }) expect(status).to.equal(200) expect(headers).to.contain({ // 'content-type': 'application/xml', //> fails with 'application/xml;charset=utf-8', which is set by express @@ -101,7 +101,7 @@ describe('Basic OData', () => { }) it('supports $value requests', async () => { - const { data } = await GET(`/processor/Travel(TravelUUID='52657221A8E4645C17002DF03754AB66',IsActiveEntity=true)/to_Customer/LastName/$value`, { headers: { accept: '*/*' } }) //> for cds^7 + const { data } = await GET(`/processor/Travel(TravelUUID='52657221A8E4645C17002DF03754AB66',IsActiveEntity=true)/to_Customer/LastName/$value`, { headers: { accept: 'text/plain' } }) expect(data).to.equal('Prinz') }) From a63558b297010694144b84a1a4b8dc4532d5cd95 Mon Sep 17 00:00:00 2001 From: Johannes Vogel <31311694+johannes-vogel@users.noreply.github.com> Date: Tue, 5 Nov 2024 16:10:47 +0100 Subject: [PATCH 4/5] Update package.json --- package.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index d97b887c..f661cec8 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,9 @@ "fiori": { "wrap_multiple_errors": false }, + "features": { + "ieee754compatible": true + }, "build": { "[node!]": { "target": "gen", @@ -122,4 +125,4 @@ "app/travel_processor", "app/travel_analytics" ] -} \ No newline at end of file +} From a09c298e4debc011de59bc14f96d7d96138c41b6 Mon Sep 17 00:00:00 2001 From: Johannes Vogel Date: Tue, 5 Nov 2024 16:16:24 +0100 Subject: [PATCH 5/5] decimal precision --- test/odata.test.js | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/test/odata.test.js b/test/odata.test.js index c03802cf..6a7b1946 100644 --- a/test/odata.test.js +++ b/test/odata.test.js @@ -59,7 +59,7 @@ describe('Basic OData', () => { const { data } = await GET(`/processor/Travel?$filter=TravelUUID eq '00667221A8E4645C17002DF03754AB66'`) expect(data.value).to.containSubset([{ BeginDate: '2023-08-02', - BookingFee: '60', + BookingFee: '60.000', createdAt: expectedValue => /2023-07-16T18:42:07\.000(0000)?Z/.test(expectedValue), // timestamp precision increase with cds^7 createdBy: 'Hansmann', CurrencyCode_code: 'SGD', @@ -72,7 +72,7 @@ describe('Basic OData', () => { LastChangedBy: 'Deichgraeber', to_Agency_AgencyID: '070029', to_Customer_CustomerID: '000318', - TotalPrice: '23439', + TotalPrice: '23439.000', TravelID: 175, TravelStatus_code: 'A', TravelUUID: '00667221A8E4645C17002DF03754AB66' @@ -135,7 +135,7 @@ describe('Basic OData', () => { }) const { data: newTravel } = await SAVE (`/processor/Travel(TravelUUID='${newDraft.TravelUUID}',IsActiveEntity=false)`) - expect(newTravel).to.contain({ TravelID: 4134, TotalPrice: '11' }) + expect(newTravel).to.contain({ TravelID: 4134, TotalPrice: '11.000' }) }) it ('re-calculates totals after booking fee changed', async ()=>{ @@ -145,7 +145,7 @@ describe('Basic OData', () => { let Supplement = `/processor/BookingSupplement(BookSupplUUID='85D87221A8E4645C17002DF03754AB66',IsActiveEntity=false)` let { data:draft } = await EDIT (Travel4133) - expect(draft).to.containSubset({ TravelID: 4133, TotalPrice: '7375' }) + expect(draft).to.containSubset({ TravelID: 4133, TotalPrice: '7375.000' }) // Ensure it is not in accepted state as that would disallow changing await POST (Draft +`/TravelService.rejectTravel`) @@ -153,19 +153,19 @@ describe('Basic OData', () => { // Change the Travel's Booking Fee await PATCH (Draft, { BookingFee: '120' }) - await expect_totals ('7475') + await expect_totals ('7475.000') // Change a Booking's Flight Price await PATCH (Booking, { FlightPrice: '1657' }) - await expect_totals ('5475') + await expect_totals ('5475.000') // Change a Supplements's Price await PATCH (Supplement, { Price: '220' }) - await expect_totals ('5675') + await expect_totals ('5675.000') // Save Draft await SAVE (Draft) - await expect_totals ('5675', 'IsActiveEntity=true') + await expect_totals ('5675.000', 'IsActiveEntity=true') async function expect_totals (expected, _active = 'IsActiveEntity=false') { let { data: { TotalPrice } } = await GET (`/processor/Travel(TravelUUID='76757221A8E4645C17002DF03754AB66',${_active})? @@ -177,13 +177,13 @@ describe('Basic OData', () => { it('deduct discount multiple times does not end up in error', async () => { const { data: res1 } = await GET `/processor/Travel(TravelUUID='52657221A8E4645C17002DF03754AB66',IsActiveEntity=true)` - expect(res1).to.contain({ TotalPrice: '900', BookingFee: '20' }) + expect(res1).to.contain({ TotalPrice: '900.000', BookingFee: '20.000' }) const { data: res2 } = await POST( `/processor/Travel(TravelUUID='52657221A8E4645C17002DF03754AB66',IsActiveEntity=true)/TravelService.deductDiscount`, { percent: 11 } ) - expect(res2).to.contain({ TotalPrice: '897.8', BookingFee: '17.8' }) + expect(res2).to.contain({ TotalPrice: '897.800', BookingFee: '17.800' }) const { data: res3 } = await POST( `/processor/Travel(TravelUUID='52657221A8E4645C17002DF03754AB66',IsActiveEntity=true)/TravelService.deductDiscount`, @@ -204,10 +204,10 @@ describe('Basic OData', () => { const Draft = `/processor/Travel(TravelUUID='93657221A8E4645C17002DF03754AB66',IsActiveEntity=false)` const { data:res0 } = await GET (Active) - expect(res0).to.contain({ TravelID: 66, TotalPrice: '729', BookingFee: '10' }) + expect(res0).to.contain({ TravelID: 66, TotalPrice: '729.000', BookingFee: '10.000' }) const { data:res1 } = await EDIT (Active) - expect(res1).to.contain({ TotalPrice: '729', BookingFee: '10' }) + expect(res1).to.contain({ TotalPrice: '729.000', BookingFee: '10.000' }) // Change the Travel's dates to avoid validation errors const today = new Date().toISOString().split('T')[0] @@ -216,15 +216,15 @@ describe('Basic OData', () => { await PATCH (Draft, { EndDate: tomorrow }) const { data:res2 } = await POST (`${Draft}/TravelService.deductDiscount`, { percent: 50 }) - expect(res2).to.contain({ TotalPrice: '724', BookingFee: '5' }) + expect(res2).to.contain({ TotalPrice: '724.000', BookingFee: '5.000' }) const { data:res3 } = await GET (Draft) - expect(res3).to.contain({ TotalPrice: '724', BookingFee: '5' }) + expect(res3).to.contain({ TotalPrice: '724.000', BookingFee: '5.000' }) await SAVE (Draft) const { data:res4 } = await GET (Active) - expect(res4).to.contain({ TotalPrice: '724', BookingFee: '5' }) + expect(res4).to.contain({ TotalPrice: '724.000', BookingFee: '5.000' }) }) })