From cb71e2ed9b59dcd63082150554fbe9eedf1e9816 Mon Sep 17 00:00:00 2001 From: Dmitriynj Date: Mon, 14 Dec 2020 23:54:51 +0300 Subject: [PATCH] update tests --- media-store/package.json | 2 +- media-store/srv/user-service.js | 4 +- media-store/test/data/media-store.mock.js | 87 +++++++- media-store/test/media-store.test.js | 235 ++++++++++++++++++++-- media-store/test/test.http | 60 +++--- 5 files changed, 340 insertions(+), 48 deletions(-) diff --git a/media-store/package.json b/media-store/package.json index 8015f55f..fbfb9380 100644 --- a/media-store/package.json +++ b/media-store/package.json @@ -23,7 +23,7 @@ "scripts": { "start": "npx cds run", "deploy": "cds deploy --to sqlite:mychinook.db", - "test": "mocha test/media-store.test.js --verbose --timeout 10000" + "test": "npm run deploy && cd ../ && npm run jest" }, "cds": { "ACCESS_TOKEN_SECRET": "secret", diff --git a/media-store/srv/user-service.js b/media-store/srv/user-service.js index f5eb2fe1..75e3f7b0 100644 --- a/media-store/srv/user-service.js +++ b/media-store/srv/user-service.js @@ -43,10 +43,12 @@ module.exports = async function () { return Object.assign({}, userFromDb, { roles }); } + /** + * User can only update and read his data + */ this.before("UPDATE", "*", async (req) => { req.query = req.query.where({ ID: req.user.attr.ID }); }); - this.before("READ", "*", async (req) => { req.query = req.query.where({ ID: req.user.attr.ID }); }); diff --git a/media-store/test/data/media-store.mock.js b/media-store/test/data/media-store.mock.js index 03f1837a..2b342ab0 100644 --- a/media-store/test/data/media-store.mock.js +++ b/media-store/test/data/media-store.mock.js @@ -185,4 +185,89 @@ const ALL_ALBUMS_WITH_TRACKS_BY_ARTIST = { ], }; -module.exports = { FIRST_TRACK, ALL_ALBUMS_WITH_TRACKS_BY_ARTIST }; +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, + ALL_ALBUMS_WITH_TRACKS_BY_ARTIST, + SECOND_CUSTOMER, + FOURTH_MARKED_TRACK_FOR_SECOND_CUSTOMER, + SECOND_CUSTOMER_INVOICES, +}; diff --git a/media-store/test/media-store.test.js b/media-store/test/media-store.test.js index 82b4b2a1..6f426106 100644 --- a/media-store/test/media-store.test.js +++ b/media-store/test/media-store.test.js @@ -1,46 +1,247 @@ const { GET, POST, expect } = require("../../test").run("media-store"); const cds = require("@sap/cds/lib"); - -class MockedUser extends cds.User { - constructor(attr, roles, id) { - super({ attr, _roles: [...roles], id }); - } -} - const { FIRST_TRACK, ALL_ALBUMS_WITH_TRACKS_BY_ARTIST, + SECOND_CUSTOMER, + FOURTH_MARKED_TRACK_FOR_SECOND_CUSTOMER, + SECOND_CUSTOMER_INVOICES, } = require("./data/media-store.mock"); +const fs = require("fs"); + +const DEFAULT_CONFIG = { + headers: { "content-type": "application/json" }, +}; + describe("Media Store services", () => { - before("skipping auth", () => { - cds.User = cds.User.Privileged; // skip auth + 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_CONFIG + ); + customerAccessToken = customerLoginResponse.data.accessToken; + + employeeLoginResponse = await POST( + "/users/login", + { + email: CURRENT_EMPLOYEE_DATA.email, + password: CURRENT_EMPLOYEE_DATA.password, + }, + DEFAULT_CONFIG + ); + employeeAccessToken = employeeLoginResponse.data.accessToken; }); - it("should bootstrap the services successfully", () => { - const { BrowseTracks, db } = cds.services; + 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("Tracks", () => { + 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_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_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_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: { + ...DEFAULT_CONFIG.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: { + ...DEFAULT_CONFIG.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_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: { + ...DEFAULT_CONFIG.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: { + ...DEFAULT_CONFIG.headers, + authorization: "Basic " + customerAccessToken, + }, + }); + + expect(data).to.eql(FOURTH_MARKED_TRACK_FOR_SECOND_CUSTOMER); + }); }); - describe("Albums", () => { - it("should return all albums with tracks by artist", async () => { - const { data } = await GET( - `/browse-tracks/Albums?$filter=artist_ID eq 1&$expand=tracks` + describe("BrowseInvoices", () => { + async function getAllCustomerInvoices() { + const { data } = await GET("/browse-invoices/Invoices", { + headers: { + ...DEFAULT_CONFIG.headers, + authorization: "Basic " + customerAccessToken, + }, + }); + return data; + } + + 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 POST( + "/browse-invoices/invoice", + { tracks: [{ ID: 3 }] }, + { + headers: { + ...DEFAULT_CONFIG.headers, + authorization: "Basic " + customerAccessToken, + }, + } + ); + + const afterData = await getAllCustomerInvoices(); + expect(afterData.value.length).to.equal( + SECOND_CUSTOMER_INVOICES.value.length + 1 ); - expect(data).to.eql(ALL_ALBUMS_WITH_TRACKS_BY_ARTIST); }); }); }); diff --git a/media-store/test/test.http b/media-store/test/test.http index aab092f4..87b09cfd 100644 --- a/media-store/test/test.http +++ b/media-store/test/test.http @@ -4,29 +4,6 @@ @user-service = http://localhost:4004/users -### ------------------------------------------------------------------------ -## Browse Tracks service -### ------------------------------------------------------------------------ - -### ------------------------------------------------------------------------ -# Get browse-tracks-service -GET {{browse-tracks-service}} - -### ------------------------------------------------------------------------ -# Get $metadata document of browse-tracks-service -GET {{browse-tracks-service}}/$metadata - -### ------------------------------------------------------------------------ -# Get Trakcs -GET {{browse-tracks-service}}/Tracks - -### ------------------------------------------------------------------------ -# Get Albums by artist ID axpanding tracks and artist -GET {{browse-tracks-service}}/Albums -?$filter=artist_ID eq 1 -&$expand=tracks,artist - - ### ------------------------------------------------------------------------ ## Users service ### ------------------------------------------------------------------------ @@ -58,8 +35,8 @@ Content-Type: application/json ### ------------------------------------------------------------------------ # Get current customer data -GET {{user-service}}/Customers(2) -Authorization: Basic eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Imxlb25la29obGVyQHN1cmZldS5kZSIsIklEIjoyLCJyb2xlcyI6WyJjdXN0b21lciJdLCJpYXQiOjE2MDc0MzE5NTgsImV4cCI6MTYwNzQzMjU1OH0.2sP3epaEo8tpBJZ-PuJInuC36TOyMgL2W6QjNFGyhSs +GET {{user-service}}/Customers(1) +Authorization: Basic eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Imxlb25la29obGVyQHN1cmZldS5kZSIsIklEIjoyLCJyb2xlcyI6WyJjdXN0b21lciJdLCJpYXQiOjE2MDc5NTE2NDgsImV4cCI6MTYwNzk1MjI0OH0.4YqMxfY0KjOEA0iPvrZU5vfnsLcbFimxcamxgVxY4Ug ### ------------------------------------------------------------------------ # Get current employee data @@ -74,8 +51,7 @@ Authorization: Basic eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImFuZHJld0 ### ------------------------------------------------------------------------ # Get all current customer invoices GET {{browse-invoices-service}}/Invoices -Authorization: Basic eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Imxlb25la29obGVyQHN1cmZldS5kZSIsIklEIjoyLCJyb2xlcyI6WyJjdXN0b21lciJdLCJpYXQiOjE2MDc0MzE5NTgsImV4cCI6MTYwNzQzMjU1OH0.2sP3epaEo8tpBJZ-PuJInuC36TOyMgL2W6QjNFGyhSs - +Authorization: Basic eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Imxlb25la29obGVyQHN1cmZldS5kZSIsIklEIjoyLCJyb2xlcyI6WyJjdXN0b21lciJdLCJpYXQiOjE2MDc5Njg5ODIsImV4cCI6MTYwNzk2OTU4Mn0.Mq78megbpHa8ZyxhBPj7mwNs8Ttag6TeVekBKFDGR3w ### ------------------------------------------------------------------------ ## Manage store service @@ -89,4 +65,32 @@ Authorization: Basic eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImFuZHJld0 { "name": "some" -} \ No newline at end of file +} + + +### ------------------------------------------------------------------------ +## Browse Tracks service +### ------------------------------------------------------------------------ + +### ------------------------------------------------------------------------ +# Get browse-tracks-service +GET {{browse-tracks-service}} + +### ------------------------------------------------------------------------ +# Get $metadata document of browse-tracks-service +GET {{browse-tracks-service}}/$metadata + +### ------------------------------------------------------------------------ +# Get Trakcs +GET {{browse-tracks-service}}/Tracks + +### ------------------------------------------------------------------------ +# Get Albums by artist ID axpanding tracks and artist +GET {{browse-tracks-service}}/Albums +?$filter=artist_ID eq 1 +&$expand=tracks,artist + +### ------------------------------------------------------------------------ +# Get Marked Trakcs +GET {{browse-tracks-service}}/MarkedTracks +Authorization: Basic eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Imxlb25la29obGVyQHN1cmZldS5kZSIsIklEIjoyLCJyb2xlcyI6WyJjdXN0b21lciJdLCJpYXQiOjE2MDc5NjYxMTAsImV4cCI6MTYwNzk2NjcxMH0.VkxdhQth--kpxjb-X88N3H43kTtu5Uy0uVPsrQMx-ms \ No newline at end of file