Skip to content

Commit

Permalink
tests added
Browse files Browse the repository at this point in the history
  • Loading branch information
Dmytro27Ind committed Apr 2, 2024
1 parent 4386c19 commit 897bfbe
Show file tree
Hide file tree
Showing 8 changed files with 17,639 additions and 12,750 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,4 @@ Thumbs.db
/src/environments/environment.prod.ts
/src/environments/environment.ts
/src/environments/*
/folder-tree.txt
30,182 changes: 17,436 additions & 12,746 deletions package-lock.json

Large diffs are not rendered by default.

13 changes: 12 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,14 @@
"start-client": "npm run config-env -- --environment=dev && ng serve --port 4300 client",
"start-client-prod": "npm run config-env -- --environment=prod && ng serve client --configuration production",
"build-client": "npm run config-env -- --environment=prod && ng build --project=\"client\" --configuration production && npm run set-client-url",
"test": "ng test"
"test": "jest --coverage"
},
"jest": {
"preset": "jest-preset-angular",
"setupFilesAfterEnv": [
"<rootDir>/src/assets/scripts/setupJest.ts"
],
"testEnvironment": "<rootDir>/src/assets/scripts/CryptoEnvironment.ts"
},
"private": true,
"dependencies": {
Expand All @@ -26,11 +33,13 @@
"@angular/platform-browser": "^17.0.3",
"@angular/platform-browser-dynamic": "^17.0.3",
"@angular/router": "^17.0.3",
"@peculiar/webcrypto": "^1.4.6",
"angular-code-input": "^2.0.0",
"aws-amplify": "^6.0.5",
"cheerio": "^1.0.0-rc.12",
"cross-domain-storage": "^2.0.7",
"http-status-codes": "^2.3.0",
"jest-preset-angular": "^14.0.3",
"jszip": "^3.10.1",
"ngx-filesize": "^3.0.3",
"ngx-logger": "^5.0.12",
Expand All @@ -43,9 +52,11 @@
"@angular/cli": "^17.0.1",
"@angular/compiler-cli": "^17.0.3",
"@types/jasmine": "~4.3.0",
"@types/jest": "^29.5.12",
"autoprefixer": "^10.4.16",
"dotenv": "^16.3.1",
"jasmine-core": "~4.6.0",
"jest": "^29.7.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.0",
Expand Down
137 changes: 137 additions & 0 deletions projects/client/src/app/services/crypto.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import { TestBed, async } from '@angular/core/testing';
import { CryptoService } from './crypto.service';
import { CognitoService } from '../../../../shared';
import { AlertService } from '../../../../shared';

describe('CryptoService', () => {
let service: CryptoService;

beforeEach(async(() => {
TestBed.configureTestingModule({
providers: [
CryptoService,
{ provide: CognitoService, useValue: { currentUserId: async () => 'testUserId' } },
AlertService
]
}).compileComponents();
service = TestBed.inject(CryptoService);

// @ts-ignore
service.originalGetKey = service.getKey;
service.getKey = async (): Promise<CryptoKey> => {
const keyArray = service.hexStringToArrayBuffer('47fa4283484c4d66e4fb4b44085746646d520ec4cd94ee6e5b940c4b744424b5');
return await window.crypto.subtle.importKey(
'raw',
keyArray,
{name: 'AES-GCM'},
true,
['encrypt', 'decrypt']
);
};

const decodedIv = atob('kkzlj8k8WN8krKk8');
const decodedIvArray = decodedIv.split('').map(char => char.charCodeAt(0));

Object.defineProperty(service, 'iv', {
value: new Uint8Array(decodedIvArray),
writable: true
});

(window as any).URL.createObjectURL = () => {};
// @ts-ignore
(window as any).URL.revokeObjectURL = (url) => {};
}));

it('should be created', () => {
expect(service).toBeTruthy();
});

describe('encrypt and decrypt methods', () => {
it('encrypt and decrypt data', async () => {
const testData = new Uint8Array([1, 2, 3, 4, 5]);
const encryptedData = await service.encrypt(testData.buffer);
const decryptedData = await service.decrypt(encryptedData);

expect(decryptedData).toEqual(testData.buffer);
});
});

describe('encryptName and decryptName methods', () => {
it('encrypt and decrypt name', async () => {
const testName = 'John Doe';
const encryptedName = await service.encryptName(testName);
const decryptedName = await service.decryptName(encryptedName);

expect(decryptedName).toEqual(testName);
});
});

describe('encryptUrl and decryptUrl methods', () => {
it('encrypt and decrypt URL', async () => {
const testUrl = 'home/folder/test.txt';
const encryptedUrl = await service.encryptUrl(testUrl);
const decryptedUrl = await service.decryptUrl(encryptedUrl);

expect(decryptedUrl).toEqual(testUrl);
});
});

describe('isKeySet method', () => {
it('should return false if key is not set', () => {
localStorage.removeItem(service.getLocalstorageKey());
expect(service.isKeySet()).toBe(false);
});

it('should return true if key is set', () => {
localStorage.setItem(service.getLocalstorageKey(), 'testKey');
expect(service.isKeySet()).toBe(true);
localStorage.removeItem(service.getLocalstorageKey()); // Clean up
});
});

describe('removeLocalstorageKey method', () => {
it('should remove encryption key from localStorage', () => {
localStorage.setItem(service.getLocalstorageKey(), 'testKey');
service.removeLocalstorageKey();
expect(localStorage.getItem(service.getLocalstorageKey())).toBeNull();
});
});

describe('getKey method', () => {
it('should throw an error if key is not found in localStorage', async () => {
localStorage.removeItem(service.getLocalstorageKey());
// @ts-ignore
await expect(service.originalGetKey()).rejects.toThrowError('Key not found in localStorage');
});

it('should return a CryptoKey if key is found in localStorage', async () => {
const testKey = '47fa4283484c4d66e4fb4b44085746646d520ec4cd94ee6e5b940c4b744424b5'; // Test key
localStorage.setItem(service.getLocalstorageKey(), testKey);
const key = await service.getKey();
expect(key).toBeDefined();
localStorage.removeItem(service.getLocalstorageKey()); // Clean up
});
});

describe('generateKey method', () => {
it('should generate a new encryption key and store it in localStorage', async () => {
localStorage.removeItem(service.getLocalstorageKey());
await service.generateKey();
const key = localStorage.getItem(service.getLocalstorageKey());
expect(key).toBeTruthy();
localStorage.removeItem(service.getLocalstorageKey()); // Clean up
});
});

describe('selectKeyFromFile method', () => {
it('should read a key from file and store it in localStorage', async () => {
const testKey = '47fa4283484c4d66e4fb4b44085746646d520ec4cd94ee6e5b940c4b744424b5'; // Test key
const blob = new Blob([testKey], { type: 'text/plain' });
const file = new File([blob], 'testKey.txt');
await service.selectKeyFromFile(file);
const key = localStorage.getItem(service.getLocalstorageKey());
expect(key).toEqual(testKey);
localStorage.removeItem(service.getLocalstorageKey()); // Clean up
});
});
});
6 changes: 3 additions & 3 deletions projects/client/src/app/services/crypto.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,11 @@ export class CryptoService {
/**
* Removes the encryption key from localStorage.
*/
private getLocalstorageKey(): string {
getLocalstorageKey(): string {
return this.userId + '.CloudGuardKey';
}

private async importKey(keyArray: Uint8Array): Promise<CryptoKey> {
public async importKey(keyArray: Uint8Array): Promise<CryptoKey> {
try {
return await window.crypto.subtle.importKey(
'raw',
Expand All @@ -300,7 +300,7 @@ export class CryptoService {
}).join('');
}

private hexStringToArrayBuffer(hexString: string): Uint8Array {
public hexStringToArrayBuffer(hexString: string): Uint8Array {
const buffer = new Uint8Array(hexString.length / 2);
for (let i = 0; i < hexString.length; i += 2) {
buffer[i / 2] = parseInt(hexString.substring(i, i + 2), 16);
Expand Down
36 changes: 36 additions & 0 deletions src/assets/scripts/CryptoEnvironment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { Context } from 'vm';
import type { EnvironmentContext, JestEnvironmentConfig } from '@jest/environment';
import { Crypto } from '@peculiar/webcrypto';
import JsDomEnvironment from 'jest-environment-jsdom';

export class CryptoEnvironment extends JsDomEnvironment {
constructor({ globalConfig, projectConfig }: JestEnvironmentConfig, context: EnvironmentContext) {
const pcWithBuffer = {
...projectConfig,
globals: {
...projectConfig.globals,
Uint8Array,
},
};

super({ globalConfig, projectConfig: pcWithBuffer }, context);

Object.defineProperty(this.global, 'crypto', {
value: new Crypto(),
});
}

override async setup(): Promise<void> {
await super.setup();
}

override async teardown(): Promise<void> {
await super.teardown();
}

override getVmContext(): Context | null {
return super.getVmContext();
}
}

export default CryptoEnvironment;
4 changes: 4 additions & 0 deletions src/assets/scripts/setupJest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import 'jest-preset-angular/setup-jest';
import { TextEncoder, TextDecoder } from 'util';

Object.assign(global, { TextDecoder, TextEncoder });
10 changes: 10 additions & 0 deletions tsconfig.spec.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "ES2022",
"outDir": "./out-tsc/spec",
"types": ["jest", "node"]
},
"include": ["src/**/*.spec.ts"],
"exclude": ["node_modules"]
}

0 comments on commit 897bfbe

Please sign in to comment.