From a45d79e8e800d1fd5d3a6614c2db8e5f8da6ce72 Mon Sep 17 00:00:00 2001 From: Dmitriynj Date: Wed, 23 Dec 2020 11:43:55 +0300 Subject: [PATCH] change tests --- package.json | 4 +- test/chinook.test.js | 440 ++++++++++++++++++++++++++++++++++++++ test/data/chinook.mock.js | 108 ++++++++++ 3 files changed, 550 insertions(+), 2 deletions(-) create mode 100644 test/chinook.test.js create mode 100644 test/data/chinook.mock.js diff --git a/package.json b/package.json index 21fbea51..cfe83d7f 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,9 @@ "repository": "https://github.com/sap-samples/cloud-cap-samples.git", "author": "daniel.hutzel@sap.com", "dependencies": { - "@capire/bookshop": "./bookshop", + "@capire/bookshop": "./books", "@capire/common": "./common", - "@capire/fiori": "./fiori", + "@capire/fiori": "./bookstore", "@capire/hello": "./hello", "@capire/media": "./media", "@capire/orders": "./orders", diff --git a/test/chinook.test.js b/test/chinook.test.js new file mode 100644 index 00000000..a0629548 --- /dev/null +++ b/test/chinook.test.js @@ -0,0 +1,440 @@ +const { GET, POST, expect } = require("../test").run("chinook"); +const cds = require("@sap/cds/lib"); +const { + FIRST_TRACK, + SECOND_CUSTOMER, + FOURTH_MARKED_TRACK_FOR_SECOND_CUSTOMER, + SECOND_CUSTOMER_INVOICES, +} = require("./data/chinook.mock"); + +const DEFAULT_AXIOS_CONFIG = { + headers: { "content-type": "application/json" }, +}; + +async function resetStore() { + const targetCSNModel = await cds.load(["db", "srv"]); + const model = cds.reflect(targetCSNModel); + cds.db = await cds.deploy(model).to("db"); +} + +describe("Media Store services", () => { + const CURRENT_CUSTOMER_DATA = { + ID: 2, + email: "leonekohler@surfeu.de", + password: "some", + roles: ["customer"], + }; + const CURRENT_EMPLOYEE_DATA = { + ID: 4, + email: "margaret@chinookcorp.com", + password: "some", + roles: ["employee"], + }; + let customerAccessToken; + let employeeAccessToken; + + before("login user", async () => { + customerLoginResponse = await POST( + "/users/login", + { + email: CURRENT_CUSTOMER_DATA.email, + password: CURRENT_CUSTOMER_DATA.password, + }, + DEFAULT_AXIOS_CONFIG + ); + customerAccessToken = customerLoginResponse.data.accessToken; + + employeeLoginResponse = await POST( + "/users/login", + { + email: CURRENT_EMPLOYEE_DATA.email, + password: CURRENT_EMPLOYEE_DATA.password, + }, + DEFAULT_AXIOS_CONFIG + ); + employeeAccessToken = employeeLoginResponse.data.accessToken; + }); + + it("should bootstrap services successfully", () => { + const { + BrowseTracks, + BrowseInvoices, + ManageStore, + Users, + db, + } = cds.services; + const { Tracks } = BrowseTracks.entities; + + expect(BrowseTracks).not.to.be.undefined; + expect(BrowseInvoices).not.to.be.undefined; + expect(ManageStore).not.to.be.undefined; + expect(Users).not.to.be.undefined; + expect(db).not.to.be.undefined; + expect(Tracks).not.to.be.undefined; + }); + + describe("Users", () => { + function compareAuthData(actualAuthData) { + expect(actualAuthData).not.to.be.undefined; + expect(actualAuthData).to.have.own.property("accessToken"); + expect(actualAuthData).to.have.own.property("refreshToken"); + expect(actualAuthData).to.have.own.property("ID"); + expect(actualAuthData).to.have.own.property("email"); + expect(actualAuthData).to.have.own.property("roles"); + expect(actualAuthData.ID).to.equal(CURRENT_CUSTOMER_DATA.ID); + expect(actualAuthData.email).to.equal(CURRENT_CUSTOMER_DATA.email); + expect(actualAuthData.roles).to.deep.equal(CURRENT_CUSTOMER_DATA.roles); + } + + it("should login user successfully", async () => { + const { data: actualData } = customerLoginResponse; + + compareAuthData(actualData); + }); + + it("shouldn't login customer with invalid credentials", async () => { + try { + await POST( + "/users/login", + { + email: CURRENT_CUSTOMER_DATA.email, + password: "some-invalid-password", + }, + DEFAULT_AXIOS_CONFIG + ); + } catch (error) { + expect(error.message).to.equal("401 - Unauthorized"); + } + }); + + it("should refresh tokens successfully", async () => { + const { + data: { refreshToken }, + } = customerLoginResponse; + const { data: actualRefreshTokensData } = await POST( + "/users/refreshTokens", + { + refreshToken, + }, + DEFAULT_AXIOS_CONFIG + ); + + compareAuthData(actualRefreshTokensData); + }); + + it("shouldn't refresh tokens due to invalid provided one", async () => { + try { + await POST( + "/users/refreshTokens", + { + refreshToken: "some-invalid-refresh-token", + }, + DEFAULT_AXIOS_CONFIG + ); + } catch (error) { + expect(error.message).to.equal("401 - Unauthorized"); + } + }); + + it("current customer should retrieve his data", async () => { + const { data: actualData } = await GET( + `/users/Customers(${CURRENT_CUSTOMER_DATA.ID})`, + { + headers: { + authorization: "Basic " + customerAccessToken, + }, + } + ); + expect(actualData).not.to.be.undefined; + expect(actualData).to.deep.equal(SECOND_CUSTOMER); + }); + + it("current employee shouldn't have access to customer data", async () => { + const someCustomerID = 15; + + try { + await GET(`/users/Customers(${someCustomerID})`, { + headers: { + authorization: "Basic " + employeeAccessToken, + }, + }); + } catch (error) { + expect(error.message).to.equal("403 - Forbidden"); + } + }); + + it("current customer shouldn't retrieve his data without provided access token", async () => { + try { + await GET(`/users/Customers(11)`, DEFAULT_AXIOS_CONFIG); + } catch (error) { + expect(error.message).to.equal("401 - Unauthorized"); + } + }); + + it("current customer shouldn't retrieve another customer data", async () => { + try { + await GET(`/users/Customers(11)`, { + headers: { + authorization: "Basic " + customerAccessToken, + }, + }); + } catch (error) { + expect(error.message).to.equal("404 - Not Found"); + } + }); + }); + + describe("BrowseTracks", () => { + it("should return track with ID eq 1", async () => { + const { data } = await GET( + "/browse-tracks/Tracks(1)?$expand=genre,album($expand=artist)" + ); + expect(data).to.eql(FIRST_TRACK); + }); + + it("should return track with ID eq 4 for second customer", async () => { + const { data } = await GET("/browse-tracks/MarkedTracks(4)", { + headers: { + authorization: "Basic " + customerAccessToken, + }, + }); + + expect(data).to.eql(FOURTH_MARKED_TRACK_FOR_SECOND_CUSTOMER); + }); + }); + + describe("BrowseInvoices", () => { + const NEW_INVOICE_ID = 413; + const CANCELLED_STATUS = -1; + + async function getAllCustomerInvoices() { + const { data } = await GET("/browse-invoices/Invoices", { + headers: { + authorization: "Basic " + customerAccessToken, + }, + }); + return data; + } + + async function createInvoice(tracks) { + await POST( + "/browse-invoices/invoice", + { tracks }, + { + headers: { + ...DEFAULT_AXIOS_CONFIG.headers, + authorization: "Basic " + customerAccessToken, + }, + } + ); + } + + it("should return all invoices only for current customer", async () => { + const data = await getAllCustomerInvoices(); + + expect(data).to.eql(SECOND_CUSTOMER_INVOICES); + }); + + it("should create invoice for current customer", async () => { + const beforeData = await getAllCustomerInvoices(); + expect(beforeData.value.length).to.equal( + SECOND_CUSTOMER_INVOICES.value.length + ); + + await createInvoice([{ ID: 3 }]); + + const afterData = await getAllCustomerInvoices(); + expect(afterData.value.length).to.equal( + SECOND_CUSTOMER_INVOICES.value.length + 1 + ); + }); + + it("should not create invoice due to current customer already owns some of provided tracks", async () => { + const ALREADY_OWNED_TRACK_ID = 4; + + try { + await createInvoice([{ ID: ALREADY_OWNED_TRACK_ID }]); + } catch (error) { + expect(error.message).to.equal( + "400 - Invoice contains already owned values" + ); + } + }); + + it("should cancel invoice for current customer", async () => { + await resetStore(); + await createInvoice([{ ID: 3 }]); + + const beforeData = await getAllCustomerInvoices(); + expect(beforeData.value.length).to.equal( + SECOND_CUSTOMER_INVOICES.value.length + 1 + ); + + await POST( + "/browse-invoices/cancelInvoice", + { ID: NEW_INVOICE_ID }, + { + headers: { + ...DEFAULT_AXIOS_CONFIG.headers, + authorization: "Basic " + customerAccessToken, + }, + } + ); + + const afterData = await getAllCustomerInvoices(); + expect(afterData.value[afterData.value.length - 1].status).to.equal( + CANCELLED_STATUS + ); + }); + + it("should not cancel invoice due to leverage time has expired", async () => { + await resetStore(); + const beforeData = await getAllCustomerInvoices(); + expect(beforeData.value.length).to.equal( + SECOND_CUSTOMER_INVOICES.value.length + ); + + try { + await POST( + "/browse-invoices/cancelInvoice", + { ID: 12 }, + { + headers: { + ...DEFAULT_AXIOS_CONFIG.headers, + authorization: "Basic " + customerAccessToken, + }, + } + ); + } catch (error) { + expect(error.message).to.equal("400 - Leverage time was expired"); + } + }); + + it("should not cancel invoice due to invoice with such ID si not belongs to current customer", async () => { + const NOT_OWNED_INVOICE_ID = 146; + + try { + await POST( + "/browse-invoices/cancelInvoice", + { ID: NOT_OWNED_INVOICE_ID }, + { + headers: { + ...DEFAULT_AXIOS_CONFIG.headers, + authorization: "Basic " + customerAccessToken, + }, + } + ); + } catch (error) { + expect(error.message).to.equal( + "404 - Seems like you are not owning this invoice or it is not exists" + ); + } + }); + }); + + describe("ManageStore", () => { + const NEW_TRACK_ID = 3504; + const newTrack = { + name: "Some track", + composer: "Some composer", + album: { ID: 14 }, + genre: { ID: 15 }, + unitPrice: "18.33", + }; + + async function createTrack(newTrack) { + await POST("/manage-store/Tracks", newTrack, { + headers: { + authorization: "Basic " + employeeAccessToken, + "content-type": "application/json;IEEE754Compatible=true", + }, + }); + } + + async function getTrack(ID) { + return await GET(`/browse-tracks/Tracks(${ID})`); + } + + it("should create new track", async () => { + await createTrack(newTrack); + const { data: createdTrack } = await getTrack(NEW_TRACK_ID); + + expect(createdTrack).to.deep.equal({ + "@odata.context": "$metadata#Tracks/$entity", + ID: NEW_TRACK_ID, + name: "Some track", + composer: "Some composer", + unitPrice: 18.33, + album_ID: 14, + genre_ID: 15, + }); + }); + + it("customer should can create track", async () => { + try { + await POST("/manage-store/Tracks", newTrack, { + headers: { + authorization: "Basic " + customerAccessToken, + "content-type": "application/json;IEEE754Compatible=true", + }, + }); + } catch (error) { + expect(error.message).to.equal("403 - Forbidden"); + } + }); + + it("should create new artist", async () => { + const NEW_ARTIST_ID = 276; + + await POST( + "/manage-store/Artists", + { name: "some" }, + { + headers: { + authorization: "Basic " + employeeAccessToken, + ...DEFAULT_AXIOS_CONFIG.headers, + }, + } + ); + + const { data } = await GET(`/manage-store/Artists(${NEW_ARTIST_ID})`, { + headers: { + authorization: "Basic " + employeeAccessToken, + }, + }); + + expect({ + ID: NEW_ARTIST_ID, + name: "some", + "@odata.context": "$metadata#Artists/$entity", + }).to.deep.equal(data); + }); + + it("should create new artist", async () => { + const NEW_ALBUM_ID = 349; + + await POST( + "/manage-store/Albums", + { title: "some", artist: { ID: 235 } }, + { + headers: { + authorization: "Basic " + employeeAccessToken, + ...DEFAULT_AXIOS_CONFIG.headers, + }, + } + ); + + const { data } = await GET(`/manage-store/Albums(${NEW_ALBUM_ID})`, { + headers: { + authorization: "Basic " + employeeAccessToken, + }, + }); + expect({ + ID: NEW_ALBUM_ID, + title: "some", + artist_ID: 235, + "@odata.context": "$metadata#Albums/$entity", + }).to.deep.equal(data); + }); + }); +}); diff --git a/test/data/chinook.mock.js b/test/data/chinook.mock.js new file mode 100644 index 00000000..cc1168dc --- /dev/null +++ b/test/data/chinook.mock.js @@ -0,0 +1,108 @@ +const FIRST_TRACK = { + "@odata.context": "$metadata#Tracks(genre(),album(artist()))/$entity", + ID: 1, + name: "For Those About To Rock (We Salute You)", + composer: "Angus Young, Malcolm Young, Brian Johnson", + unitPrice: 0.99, + album_ID: 1, + genre_ID: 1, + album: { + ID: 1, + title: "For Those About To Rock We Salute You", + artist_ID: 1, + artist: { + ID: 1, + name: "AC/DC", + }, + }, + genre: { + ID: 1, + name: "Rock", + }, +}; + +const SECOND_CUSTOMER = { + "@odata.context": "$metadata#Customers/$entity", + ID: 2, + lastName: "Köhler", + firstName: "Leonie", + city: "Stuttgart", + address: "Theodor-Heuss-Straße 34", + country: "Germany", + phone: "+49 0711 2842222", + email: "leonekohler@surfeu.de", +}; + +const FOURTH_MARKED_TRACK_FOR_SECOND_CUSTOMER = { + "@odata.context": "$metadata#MarkedTracks/$entity", + ID: 4, + name: "Restless and Wild", + composer: + "F. Baltes, R.A. Smith-Diesel, S. Kaufman, U. Dirkscneider & W. Hoffman", + unitPrice: 0.99, + alreadyOrdered: true, + album_ID: 3, + genre_ID: 1, +}; + +const SECOND_CUSTOMER_INVOICES = { + "@odata.context": "$metadata#Invoices", + value: [ + { + ID: 1, + invoiceDate: "2008-12-31T22:00:00Z", + total: 1.98, + status: 1, + customer_ID: 2, + }, + { + ID: 12, + invoiceDate: "2009-02-10T22:00:00Z", + total: 13.86, + status: 1, + customer_ID: 2, + }, + { + ID: 67, + invoiceDate: "2009-10-11T21:00:00Z", + total: 8.91, + status: 1, + customer_ID: 2, + }, + { + ID: 196, + invoiceDate: "2011-05-18T21:00:00Z", + total: 1.98, + status: 1, + customer_ID: 2, + }, + { + ID: 219, + invoiceDate: "2011-08-20T21:00:00Z", + total: 3.96, + status: 1, + customer_ID: 2, + }, + { + ID: 241, + invoiceDate: "2011-11-22T21:00:00Z", + total: 5.94, + status: 1, + customer_ID: 2, + }, + { + ID: 293, + invoiceDate: "2012-07-12T21:00:00Z", + total: 0.99, + status: 1, + customer_ID: 2, + }, + ], +}; + +module.exports = { + FIRST_TRACK, + SECOND_CUSTOMER, + FOURTH_MARKED_TRACK_FOR_SECOND_CUSTOMER, + SECOND_CUSTOMER_INVOICES, +};