basic test implemented

This commit is contained in:
Gianmarco Pettinato 2021-09-26 15:42:30 +02:00
parent 5cdb1e978d
commit 71d7c0531d
15 changed files with 10547 additions and 820 deletions

3
.babelrc Normal file
View File

@ -0,0 +1,3 @@
{
"presets": ["env"]
}

View File

@ -5,7 +5,8 @@
}, },
"extends": [ "extends": [
"eslint:recommended", "eslint:recommended",
"plugin:@typescript-eslint/recommended" "plugin:@typescript-eslint/recommended",
"plugin:ava/recommended"
], ],
"parser": "@typescript-eslint/parser", "parser": "@typescript-eslint/parser",
"parserOptions": { "parserOptions": {

File diff suppressed because one or more lines are too long

5
jest.config.js Normal file
View File

@ -0,0 +1,5 @@
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};

10857
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "jest --watchAll",
"start": "nodemon --exec \"npx ts-node\" ./src/server.ts" "start": "nodemon --exec \"npx ts-node\" ./src/server.ts"
}, },
"author": "", "author": "",
@ -17,18 +17,24 @@
"dcc-utils": "^0.2.0", "dcc-utils": "^0.2.0",
"express": "^4.17.1", "express": "^4.17.1",
"jsrsasign": "^10.4.0", "jsrsasign": "^10.4.0",
"nodemon": "^2.0.13", "mock-fs": "^5.1.1"
"typescript": "^4.4.3"
}, },
"devDependencies": { "devDependencies": {
"@types/express": "^4.17.13", "@types/express": "^4.17.13",
"@types/jest": "^27.0.2",
"@types/jsrsasign": "^8.0.13", "@types/jsrsasign": "^8.0.13",
"@types/node": "^16.9.6", "@types/node": "^16.9.6",
"@typescript-eslint/eslint-plugin": "^4.31.2", "@typescript-eslint/eslint-plugin": "^4.31.2",
"@typescript-eslint/parser": "^4.31.2", "@typescript-eslint/parser": "^4.31.2",
"babel-preset-env": "^1.7.0",
"eslint": "^7.32.0", "eslint": "^7.32.0",
"eslint-config-airbnb-base": "^14.2.1", "eslint-config-airbnb-base": "^14.2.1",
"eslint-plugin-ava": "^13.0.0",
"eslint-plugin-import": "^2.24.2", "eslint-plugin-import": "^2.24.2",
"ts-node": "^10.2.1" "jest": "^27.2.2",
"nodemon": "^2.0.13",
"ts-jest": "^27.0.5",
"ts-node": "^10.2.1",
"typescript": "^4.4.3"
} }
} }

View File

@ -1 +0,0 @@
{"rules":[{"name":"vaccine_end_day_complete","type":"EU/1/20/1525","value":"365"},{"name":"vaccine_start_day_complete","type":"EU/1/20/1525","value":"15"},{"name":"vaccine_end_day_not_complete","type":"EU/1/20/1525","value":"365"},{"name":"vaccine_start_day_not_complete","type":"EU/1/20/1525","value":"15"},{"name":"vaccine_end_day_complete","type":"EU/1/21/1529","value":"365"},{"name":"vaccine_start_day_complete","type":"EU/1/21/1529","value":"0"},{"name":"vaccine_end_day_not_complete","type":"EU/1/21/1529","value":"84"},{"name":"vaccine_start_day_not_complete","type":"EU/1/21/1529","value":"15"},{"name":"vaccine_end_day_complete","type":"EU/1/20/1507","value":"365"},{"name":"vaccine_start_day_complete","type":"EU/1/20/1507","value":"0"},{"name":"vaccine_end_day_not_complete","type":"EU/1/20/1507","value":"42"},{"name":"vaccine_start_day_not_complete","type":"EU/1/20/1507","value":"15"},{"name":"vaccine_end_day_complete","type":"EU/1/20/1528","value":"365"},{"name":"vaccine_start_day_complete","type":"EU/1/20/1528","value":"0"},{"name":"vaccine_end_day_not_complete","type":"EU/1/20/1528","value":"42"},{"name":"vaccine_start_day_not_complete","type":"EU/1/20/1528","value":"15"},{"name":"rapid_test_start_hours","type":"GENERIC","value":"0"},{"name":"rapid_test_end_hours","type":"GENERIC","value":"48"},{"name":"molecular_test_start_hours","type":"GENERIC","value":"0"},{"name":"molecular_test_end_hours","type":"GENERIC","value":"48"},{"name":"recovery_cert_start_day","type":"GENERIC","value":"0"},{"name":"recovery_cert_end_day","type":"GENERIC","value":"180"},{"name":"ios","type":"APP_MIN_VERSION","value":"1.1.0"},{"name":"android","type":"APP_MIN_VERSION","value":"1.1.0"}],"lastupdateDate":1632564259533}

View File

@ -0,0 +1,7 @@
describe('CertificateDownloader',()=>{
describe('getCertificates()',()=>{
it('placeholder',()=>{
expect(false).toBe(false);
});
});
});

View File

@ -27,11 +27,9 @@ export class CertificateDownloader{
} }
return this.certificatesCollection; return this.certificatesCollection;
} catch (error) { } catch (error) {
console.log(error); if(error.message == 'ENOENT: no such file or directory, open \'rules.json\''){
if(error.errno == -2){ await fs.writeFile(this.keyStorage,'{}');
await fs.writeFile(this.keyStorage,'{}'); return this.getCertificates();
} else {
console.log(error);
} }
} }
} }

View File

@ -0,0 +1,58 @@
import { RuleDownloader } from './RuleDownloader';
import mock from 'mock-fs';
import axios, { AxiosResponse } from 'axios';
jest.mock('axios');
const mockRules = [{'name':'vaccine_end_day_complete','type':'EU/1/20/1525','value':'365'},{'name':'vaccine_start_day_complete','type':'EU/1/20/1525','value':'15'},{'name':'vaccine_end_day_not_complete','type':'EU/1/20/1525','value':'365'},{'name':'vaccine_start_day_not_complete','type':'EU/1/20/1525','value':'15'},{'name':'vaccine_end_day_complete','type':'EU/1/21/1529','value':'365'},{'name':'vaccine_start_day_complete','type':'EU/1/21/1529','value':'0'},{'name':'vaccine_end_day_not_complete','type':'EU/1/21/1529','value':'84'},{'name':'vaccine_start_day_not_complete','type':'EU/1/21/1529','value':'15'},{'name':'vaccine_end_day_complete','type':'EU/1/20/1507','value':'365'},{'name':'vaccine_start_day_complete','type':'EU/1/20/1507','value':'0'},{'name':'vaccine_end_day_not_complete','type':'EU/1/20/1507','value':'42'},{'name':'vaccine_start_day_not_complete','type':'EU/1/20/1507','value':'15'},{'name':'vaccine_end_day_complete','type':'EU/1/20/1528','value':'365'},{'name':'vaccine_start_day_complete','type':'EU/1/20/1528','value':'0'},{'name':'vaccine_end_day_not_complete','type':'EU/1/20/1528','value':'42'},{'name':'vaccine_start_day_not_complete','type':'EU/1/20/1528','value':'15'},{'name':'rapid_test_start_hours','type':'GENERIC','value':'0'},{'name':'rapid_test_end_hours','type':'GENERIC','value':'48'},{'name':'molecular_test_start_hours','type':'GENERIC','value':'0'},{'name':'molecular_test_end_hours','type':'GENERIC','value':'48'},{'name':'recovery_cert_start_day','type':'GENERIC','value':'0'},{'name':'recovery_cert_end_day','type':'GENERIC','value':'180'},{'name':'ios','type':'APP_MIN_VERSION','value':'1.1.0'},{'name':'android','type':'APP_MIN_VERSION','value':'1.1.0'}];
const ruleDownloader = new RuleDownloader();
const mockedAxios = axios as jest.Mocked<typeof axios>;
const successResposnse: AxiosResponse = {
// data:[{'name':'vaccine_end_day_complete','type':'EU/1/20/1525','value':'365'},{'name':'vaccine_start_day_complete','type':'EU/1/20/1525','value':'15'},{'name':'vaccine_end_day_not_complete','type':'EU/1/20/1525','value':'365'},{'name':'vaccine_start_day_not_complete','type':'EU/1/20/1525','value':'15'},{'name':'vaccine_end_day_complete','type':'EU/1/21/1529','value':'365'},{'name':'vaccine_start_day_complete','type':'EU/1/21/1529','value':'0'},{'name':'vaccine_end_day_not_complete','type':'EU/1/21/1529','value':'84'},{'name':'vaccine_start_day_not_complete','type':'EU/1/21/1529','value':'15'},{'name':'vaccine_end_day_complete','type':'EU/1/20/1507','value':'365'},{'name':'vaccine_start_day_complete','type':'EU/1/20/1507','value':'0'},{'name':'vaccine_end_day_not_complete','type':'EU/1/20/1507','value':'42'},{'name':'vaccine_start_day_not_complete','type':'EU/1/20/1507','value':'15'},{'name':'vaccine_end_day_complete','type':'EU/1/20/1528','value':'365'},{'name':'vaccine_start_day_complete','type':'EU/1/20/1528','value':'0'},{'name':'vaccine_end_day_not_complete','type':'EU/1/20/1528','value':'42'},{'name':'vaccine_start_day_not_complete','type':'EU/1/20/1528','value':'15'},{'name':'rapid_test_start_hours','type':'GENERIC','value':'0'},{'name':'rapid_test_end_hours','type':'GENERIC','value':'48'},{'name':'molecular_test_start_hours','type':'GENERIC','value':'0'},{'name':'molecular_test_end_hours','type':'GENERIC','value':'48'},{'name':'recovery_cert_start_day','type':'GENERIC','value':'0'},{'name':'recovery_cert_end_day','type':'GENERIC','value':'180'},{'name':'ios','type':'APP_MIN_VERSION','value':'1.1.0'},{'name':'android','type':'APP_MIN_VERSION','value':'1.1.0'}],
data: mockRules,
status: 200,
statusText: 'OK',
headers:{
'Content-Type': 'application/json',
'Cache-control': 'private',
'Strict-Transport-Security': 'max-age=63072000; includeSubDomains; preload'
},
config: {}
};
describe('RuleDownloader', ()=>{
describe('getRules',()=>{
test('Testing getRules basic outcome: file loaded from local source and is still valid',async ()=>{
mock({
'./rules.json': Buffer.from(JSON.stringify({rules:mockRules,lastupdateDate:Date.now()}))
});
const rules = await ruleDownloader.getRules();
mock.restore();
expect(JSON.stringify(rules)).toBe(JSON.stringify(mockRules));
});
test('Testing getRules basic outcome: file loaded from local source and is still valid',async ()=>{
mockedAxios.get.mockResolvedValue(successResposnse);
const date = Date.now() - 86400010;
mock({
'./rules.json': Buffer.from(JSON.stringify({rules:mockRules,lastupdateDate:date}))
});
expect(axios.get).not.toHaveBeenCalled();
const rules = await ruleDownloader.getRules();
expect(axios.get).toHaveBeenCalled();
mock.restore();
expect(JSON.stringify(rules)).toBe(JSON.stringify(mockRules));
});
test('Testing getRules basic outcome: file loaded from local source and is still valid',async ()=>{
mock({});
try {
mockedAxios.get.mockResolvedValue(successResposnse);
const rules = await ruleDownloader.getRules();
mock.restore();
expect(JSON.stringify(rules)).toBe(JSON.stringify(mockRules));
} catch (error) {
console.log(error);
}
});
});
});

View File

@ -5,12 +5,8 @@ export class RuleDownloader {
static instance: RuleDownloader; static instance: RuleDownloader;
private readonly baseUrl = 'https://get.dgc.gov.it'; private readonly baseUrl = 'https://get.dgc.gov.it';
private readonly timeSpan = 86400000; private readonly timeSpan = 86400000;
// private readonly timeSpan = 1;
private readonly keyStorage = 'rules.json' private readonly keyStorage = 'rules.json'
// private readonly timeSpan = 1000;
public rules:unknown[] = [] public rules:unknown[] = []
// eslint-disable-next-line @typescript-eslint/no-empty-function
constructor(){}
public async getRules(): Promise<unknown[]> { public async getRules(): Promise<unknown[]> {
let data = '{}'; let data = '{}';
@ -26,11 +22,9 @@ export class RuleDownloader {
} }
return this.rules; return this.rules;
} catch (error) { } catch (error) {
console.log(error); if(error.message == 'ENOENT: no such file or directory, open \'rules.json\''){
if(error.code == 'ENONET'){ await fs.writeFile(this.keyStorage,'{}');
await fs.writeFile(this.keyStorage,'{}'); return this.getRules();
} else {
console.log(error);
} }
} }
} }
@ -42,7 +36,7 @@ export class RuleDownloader {
this.rules = jsonData; this.rules = jsonData;
// localStorage.setItem(this.keyStorage, JSON.stringify({rules:this.rules,lastupdateDate:Date.now()})); // localStorage.setItem(this.keyStorage, JSON.stringify({rules:this.rules,lastupdateDate:Date.now()}));
const file = await fs.open(this.keyStorage,'w'); const file = await fs.open(this.keyStorage,'w');
file.writeFile(JSON.stringify({rules:this.rules,lastupdateDate:Date.now()})); await file.writeFile(JSON.stringify({rules:this.rules,lastupdateDate:Date.now()}));
await file.close(); await file.close();
return jsonData; return jsonData;
} }

View File

@ -128,4 +128,5 @@ export class VaccineVerifier {
if(now.isAfter(endValidity)) return {valid:false, message:'Certificate not more valid', type:'test'}; if(now.isAfter(endValidity)) return {valid:false, message:'Certificate not more valid', type:'test'};
return {valid:true, message:'Certificate is valid', type:'test'}; return {valid:true, message:'Certificate is valid', type:'test'};
} }
} }

View File

@ -1,5 +1,5 @@
import { CertificateDownloader } from './CertificateDownloader'; import { CertificateDownloader } from '../SettingsDownloader/CertificateDownloader';
import { RuleDownloader } from './RuleDownloader'; import { RuleDownloader } from '../SettingsDownloader/RuleDownloader';
import { VaccineVerifier } from './VaccineVerifier'; import { VaccineVerifier } from './VaccineVerifier';
import {DCC} from 'dcc-utils'; import {DCC} from 'dcc-utils';
import jsrsasign from 'jsrsasign'; import jsrsasign from 'jsrsasign';

View File

@ -1,5 +1,5 @@
import { Request, Response } from 'express'; import { Request, Response } from 'express';
import Verifier from '../../utils/dgcVerifier/Verifier'; import Verifier from '../../Services/dgcVerifier/Verifier';
let verifier:Verifier; let verifier:Verifier;
Verifier.instanceVerifier().then((ver:Verifier)=>verifier=ver).catch(console.error); Verifier.instanceVerifier().then((ver:Verifier)=>verifier=ver).catch(console.error);

View File

@ -1,389 +0,0 @@
{
"country-2-codes": [
"AD",
"AE",
"AF",
"AG",
"AI",
"AL",
"AM",
"AO",
"AQ",
"AR",
"AS",
"AT",
"AU",
"AW",
"AX",
"AZ",
"BA",
"BB",
"BD",
"BE",
"BF",
"BG",
"BH",
"BI",
"BJ",
"BL",
"BM",
"BN",
"BO",
"BQ",
"BR",
"BS",
"BT",
"BV",
"BW",
"BY",
"BZ",
"CA",
"CC",
"CD",
"CF",
"CG",
"CH",
"CI",
"CK",
"CL",
"CM",
"CN",
"CO",
"CR",
"CU",
"CV",
"CW",
"CX",
"CY",
"CZ",
"DE",
"DJ",
"DK",
"DM",
"DO",
"DZ",
"EC",
"EE",
"EG",
"EH",
"ER",
"ES",
"ET",
"FI",
"FJ",
"FK",
"FM",
"FO",
"FR",
"GA",
"GB",
"GD",
"GE",
"GF",
"GG",
"GH",
"GI",
"GL",
"GM",
"GN",
"GP",
"GQ",
"GR",
"GS",
"GT",
"GU",
"GW",
"GY",
"HK",
"HM",
"HN",
"HR",
"HT",
"HU",
"ID",
"IE",
"IL",
"IM",
"IN",
"IO",
"IQ",
"IR",
"IS",
"IT",
"JE",
"JM",
"JO",
"JP",
"KE",
"KG",
"KH",
"KI",
"KM",
"KN",
"KP",
"KR",
"KW",
"KY",
"KZ",
"LA",
"LB",
"LC",
"LI",
"LK",
"LR",
"LS",
"LT",
"LU",
"LV",
"LY",
"MA",
"MC",
"MD",
"ME",
"MF",
"MG",
"MH",
"MK",
"ML",
"MM",
"MN",
"MO",
"MP",
"MQ",
"MR",
"MS",
"MT",
"MU",
"MV",
"MW",
"MX",
"MY",
"MZ",
"NA",
"NC",
"NE",
"NF",
"NG",
"NI",
"NL",
"NO",
"NP",
"NR",
"NU",
"NZ",
"OM",
"PA",
"PE",
"PF",
"PG",
"PH",
"PK",
"PL",
"PM",
"PN",
"PR",
"PS",
"PT",
"PW",
"PY",
"QA",
"RE",
"RO",
"RS",
"RU",
"RW",
"SA",
"SB",
"SC",
"SD",
"SE",
"SG",
"SH",
"SI",
"SJ",
"SK",
"SL",
"SM",
"SN",
"SO",
"SR",
"SS",
"ST",
"SV",
"SX",
"SY",
"SZ",
"TC",
"TD",
"TF",
"TG",
"TH",
"TJ",
"TK",
"TL",
"TM",
"TN",
"TO",
"TR",
"TT",
"TV",
"TW",
"TZ",
"UA",
"UG",
"UM",
"US",
"UY",
"UZ",
"VA",
"VC",
"VE",
"VG",
"VI",
"VN",
"VU",
"WF",
"WS",
"YE",
"YT",
"ZA",
"ZM",
"ZW"
],
"disease-agent-targeted": [
"840539006"
],
"covid-19-lab-test-manufacturer-and-name": [
"1065",
"1097",
"1114",
"1144",
"1162",
"1173",
"1180",
"1190",
"1199",
"1201",
"1215",
"1218",
"1223",
"1225",
"1232",
"1236",
"1242",
"1244",
"1253",
"1257",
"1263",
"1266",
"1267",
"1268",
"1271",
"1278",
"1295",
"1296",
"1304",
"1319",
"1331",
"1333",
"1341",
"1343",
"1360",
"1363",
"1365",
"1375",
"1392",
"1420",
"1437",
"1443",
"1456",
"1466",
"1468",
"1481",
"1484",
"1489",
"1490",
"1501",
"1574",
"1604",
"1606",
"1654",
"1736",
"1747",
"1763",
"1764",
"1767",
"1769",
"1815",
"1822",
"1833",
"1844",
"1870",
"1884",
"1906",
"1919",
"1934",
"2010",
"2017",
"2029",
"2074",
"2098",
"2101",
"2103",
"2104",
"2108",
"2109",
"2116",
"2128",
"2130",
"2139",
"2183",
"308",
"344",
"345",
"768"
],
"covid-19-lab-result": [
"260373001",
"260415000"
],
"covid-19-lab-test-type": [
"LP217198-3",
"LP6464-4"
],
"vaccines-covid-19-auth-holders": [
"Bharat-Biotech",
"Gamaleya-Research-Institute",
"ORG-100001417",
"ORG-100001699",
"ORG-100006270",
"ORG-100010771",
"ORG-100013793",
"ORG-100020693",
"ORG-100024420",
"ORG-100030215",
"ORG-100031184",
"ORG-100032020",
"Sinovac-Biotech",
"Vector-Institute"
],
"vaccines-covid-19-names": [
"BBIBP-CorV",
"CVnCoV",
"Convidecia",
"CoronaVac",
"Covaxin",
"EU/1/20/1507",
"EU/1/20/1525",
"EU/1/20/1528",
"EU/1/21/1529",
"EpiVacCorona",
"Inactivated-SARS-CoV-2-Vero-Cell",
"Sputnik-V"
],
"sct-vaccines-covid-19": [
"1119305005",
"1119349007",
"J07BX03"
]
}