Skip to content

Commit

Permalink
Tests (#101)
Browse files Browse the repository at this point in the history
Includes test scenarios for local with db and malware scanning as false:
1. Uploading a file and checking
2. Deleting a file and checking
  • Loading branch information
muskansethi1 authored Sep 9, 2024
2 parents b268f88 + d15a5b0 commit d698826
Show file tree
Hide file tree
Showing 16 changed files with 245 additions and 51 deletions.
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ jobs:
run: |
npm install
npm run lint
npm run test
- name: get-version
id: package-version
Expand Down
27 changes: 27 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: CI

on:
workflow_dispatch:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version: [20.x, 18.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- run: npm i -g @sap/cds-dk
- run: npm i
- run: cd tests/incidents-app && npm i
- run: cds v
- run: npm run test
2 changes: 1 addition & 1 deletion lib/basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ module.exports = class AttachmentsService extends cds.Service {

async getStatus(Attachments, key) {
const result = await SELECT.from(Attachments, key).columns('status')
return result.status
return result?.status;
}

async deleteInfectedAttachment(Attachments, key) {
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"srv"
],
"scripts": {
"lint": "npx eslint ."
"lint": "npx eslint .",
"test": "npx jest attachments.test.js"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.400.0",
Expand Down
7 changes: 7 additions & 0 deletions tests/incidents-app/db/attachments.cds
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

using { sap.capire.incidents as my } from './schema';
using { Attachments } from '@cap-js/attachments';

extend my.Incidents with {
attachments: Composition of many Attachments;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ID,customer_ID,city,postCode,streetAddress
17e00347-dc7e-4ca9-9c5d-06ccef69f064,1004155,Rome,00164,Piazza Adriana
d8e797d9-6507-4aaa-b43f-5d2301df5135,1004161,Munich,80809,Olympia Park
ff13d2fa-e00f-4ee5-951c-3303f490777b,1004100,Walldorf,69190,Dietmar-Hopp-Allee
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ID,firstName,lastName,email,phone
1004155,Daniel,Watts,[email protected],+44-555-123
1004161,Stormy,Weathers,[email protected],
1004100,Sunny,Sunshine,[email protected],+01-555-789
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ID,up__ID,timestamp,author,message
2b23bb4b-4ac7-4a24-ac02-aa10cabd842c,3b23bb4b-4ac7-4a24-ac02-aa10cabd842c,1995-12-17T03:24:00Z,Harry John,Can you please check if battery connections are fine?
2b23bb4b-4ac7-4a24-ac02-aa10cabd843c,3a4ede72-244a-4f5f-8efa-b17e032d01ee,1995-12-18T04:24:00Z,Emily Elizabeth,Can you please check if there are any loose connections?
9583f982-d7df-4aad-ab26-301d4a157cd7,3583f982-d7df-4aad-ab26-301d4a157cd7,2022-09-04T12:00:00Z,Sunny Sunshine,Please check why the solar panel is broken
9583f982-d7df-4aad-ab26-301d4a158cd7,3ccf474c-3881-44b7-99fb-59a2a4668418,2022-09-04T13:00:00Z,Bradley Flowers,What exactly is wrong?
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ID,customer_ID,title,urgency_code,status_code
3b23bb4b-4ac7-4a24-ac02-aa10cabd842c,1004155,Inverter not functional,H,C
3a4ede72-244a-4f5f-8efa-b17e032d01ee,1004161,No current on a sunny day,H,N
3ccf474c-3881-44b7-99fb-59a2a4668418,1004161,Strange noise when switching off Inverter,M,N
3583f982-d7df-4aad-ab26-301d4a157cd7,1004100,Solar panel broken,H,I
7 changes: 7 additions & 0 deletions tests/incidents-app/db/data/sap.capire.incidents-Status.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
code;descr;criticality
N;New;3
A;Assigned;2
I;In Process;2
H;On Hold;3
R;Resolved;2
C;Closed;4
4 changes: 4 additions & 0 deletions tests/incidents-app/db/data/sap.capire.incidents-Urgency.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
code;descr
H;High
M;Medium
L;Low
66 changes: 66 additions & 0 deletions tests/incidents-app/db/schema.cds
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using { cuid, managed, sap.common.CodeList } from '@sap/cds/common';

namespace sap.capire.incidents;

/**
* Customers using products sold by our company.
* Customers can create support Incidents.
*/
entity Customers : managed {
key ID : String;
firstName : String;
lastName : String;
name : String = firstName ||' '|| lastName;
email : EMailAddress;
phone : PhoneNumber;
creditCardNo : String(16) @assert.format: '^[1-9]\d{15}$';
addresses : Composition of many Addresses on addresses.customer = $self;
incidents : Association to many Incidents on incidents.customer = $self;
}

entity Addresses : cuid, managed {
customer : Association to Customers;
city : String;
postCode : String;
streetAddress : String;
}


/**
* Incidents created by Customers.
*/
entity Incidents : cuid, managed {
customer : Association to Customers;
title : String @title: 'Title';
urgency : Association to Urgency default 'M';
status : Association to Status default 'N';
conversation : Composition of many {
key ID : UUID;
timestamp : type of managed:createdAt;
author : type of managed:createdBy;
message : String;
};
}

entity Status : CodeList {
key code : String enum {
new = 'N';
assigned = 'A';
in_process = 'I';
on_hold = 'H';
resolved = 'R';
closed = 'C';
};
criticality : Integer;
}

entity Urgency : CodeList {
key code : String enum {
high = 'H';
medium = 'M';
low = 'L';
};
}

type EMailAddress : String;
type PhoneNumber : String;
33 changes: 33 additions & 0 deletions tests/incidents-app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "@capire/incidents",
"version": "1.0.0",
"dependencies": {
"@cap-js/attachments": "file:../../."
},
"cds": {
"requires": {
"auth": {
"[development]": {
"users": {
"alice": {
"roles": [
"support",
"admin"
]
},
"bob": {
"roles": [
"support"
]
}
}
}
},
"attachments": {
"kind": "db",
"scan": false
}
}
},
"private": true
}
21 changes: 21 additions & 0 deletions tests/incidents-app/srv/services.cds
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using { sap.capire.incidents as my } from '../db/schema';

/**
* Service used by support personell, i.e. the incidents' 'processors'.
*/
service ProcessorService {
entity Incidents as projection on my.Incidents;
entity Customers @readonly as projection on my.Customers;
}

/**
* Service used by administrators to manage customers and incidents.
*/
service AdminService {
entity Customers as projection on my.Customers;
entity Incidents as projection on my.Incidents;
}

annotate ProcessorService.Incidents with @odata.draft.enabled;
annotate ProcessorService with @(requires: 'support');
annotate AdminService with @(requires: 'admin');
32 changes: 32 additions & 0 deletions tests/incidents-app/srv/services.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const cds = require('@sap/cds')
const { SELECT } = cds.ql

class ProcessorService extends cds.ApplicationService {
/** Registering custom event handlers */
init() {
this.before('UPDATE', 'Incidents', req => this.onUpdate(req))
this.before(['CREATE', 'UPDATE'], 'Incidents', req => this.changeUrgencyDueToSubject(req.data))
return super.init()
}

changeUrgencyDueToSubject(data) {
if (data) {
const incidents = Array.isArray(data) ? data : [data]
incidents.forEach(incident => {
if (incident.title?.toLowerCase().includes('urgent')) {
incident.urgency = { code: 'H', descr: 'High' }
}
})
}
}

/** Custom Validation */
async onUpdate(req) {
const { status_code } = await SELECT.one(req.subject, i => i.status_code).where({ ID: req.data.ID })
if (status_code === 'C') {
return req.reject(`Can't modify a closed incident`)
}
}
}

module.exports = { ProcessorService }
75 changes: 26 additions & 49 deletions tests/integration/attachments.test.js
Original file line number Diff line number Diff line change
@@ -1,61 +1,29 @@
const cds = require("@sap/cds");
const incidentsApp = require("path").resolve(__dirname, "./../../xmpl");
const { expect, axios, GET, POST, DELETE } = cds.test(incidentsApp);
const path = require("path");
const app = path.resolve(__dirname, "../incidents-app");
const { expect, axios, GET, POST, DELETE } = cds.test(app);
const { RequestSend } = require("../utils/api");
const { createReadStream } = cds.utils.fs;
const { join } = cds.utils.path;

axios.defaults.auth = { username: "alice" };
jest.setTimeout(5 * 60 * 1000);

const utils = new RequestSend(POST);
let utils = null;
let sampleDocID = null;
let incidentID = null;

describe("Tests for mock data in xmpl attachments - in-memory db", () => {
beforeAll(() => {
sampleDocID = null;
incidentID = "3b23bb4b-4ac7-4a24-ac02-aa10cabd842c";
});

//Reading the attachment list and checking for content
it("Reading attachments list", async () => {
//read attachments list for Incident - Inverter not functional
try {
const response = await GET(
`odata/v4/processor/Incidents(ID=${incidentID},IsActiveEntity=true)/attachments`
);
//the mock data has two attachments in this incident
expect(response.status).to.equal(200);
expect(response.data.value.length).to.equal(2);
sampleDocID = response.data.value[0].ID;
//to make sure content is not read
expect(response.data.value[0].content).to.be.undefined;
} catch (err) {
expect(err).to.be.undefined;
}
});

//Reading the uploaded attachment content and that it exists
it("Reading the uploaded attachment document", async () => {
//checking the uploaded attachment document

try {
const response = await GET(
`odata/v4/processor/Incidents(ID=${incidentID},IsActiveEntity=true)/attachments(up__ID=${incidentID},ID=${sampleDocID},IsActiveEntity=true)/content`
);
expect(response.status).to.equal(200);
expect(response.data).to.not.be.undefined;
} catch (err) {
expect(err).to.be.undefined;
}
});
});
let db = null;

Check warning on line 15 in tests/integration/attachments.test.js

View workflow job for this annotation

GitHub Actions / lint

'db' is assigned a value but never used
let attachmentsService = null;

Check warning on line 16 in tests/integration/attachments.test.js

View workflow job for this annotation

GitHub Actions / lint

'attachmentsService' is assigned a value but never used

describe("Tests for uploading/deleting attachments through API calls - in-memory db", () => {
beforeAll(async () => {
cds.env.requires.db.kind = "sql";
cds.env.requires.attachments.kind = "db";
db = await cds.connect.to("sql:my.db");
attachmentsService = await cds.connect.to("attachments");
sampleDocID = null;
incidentID = "3ccf474c-3881-44b7-99fb-59a2a4668418";
utils = new RequestSend(POST);
});

//Draft mode uploading attachment
Expand Down Expand Up @@ -94,15 +62,12 @@ describe("Tests for uploading/deleting attachments through API calls - in-memory
const response = await GET(
`odata/v4/processor/Incidents(ID=${incidentID},IsActiveEntity=true)/attachments`
);
//the data should have two attachments
//the data should have only one attachment
expect(response.status).to.equal(200);
expect(response.data.value.length).to.equal(2);
expect(response.data.value.length).to.equal(1);
//to make sure content is not read
expect(response.data.value[0].content).to.be.undefined;
sampleDocID =
response.data.value[0].filename == "sample.pdf"
? response.data.value[0].ID
: response.data.value[1].ID;
sampleDocID = response.data.value[0].ID;
} catch (err) {
expect(err).to.be.undefined;
}
Expand Down Expand Up @@ -149,6 +114,18 @@ describe("Tests for uploading/deleting attachments through API calls - in-memory
expect(err).to.be.undefined;
}

//read attachments list for Incident
try {
const response = await GET(
`odata/v4/processor/Incidents(ID=${incidentID},IsActiveEntity=true)/attachments`
);
//the data should have no attachments
expect(response.status).to.equal(200);
expect(response.data.value.length).to.equal(0);
} catch (err) {
expect(err).to.be.undefined;
}

//content should not be there
try {
const response = await GET(

Check warning on line 131 in tests/integration/attachments.test.js

View workflow job for this annotation

GitHub Actions / lint

'response' is assigned a value but never used
Expand Down

0 comments on commit d698826

Please sign in to comment.