Skip to content

Commit

Permalink
Merge pull request #464 from Aashish-Upadhyay-101/test-crypto-and-pos…
Browse files Browse the repository at this point in the history
…thog

unit tests for utils/posthog and utils/crypto
  • Loading branch information
dangtony98 authored Mar 29, 2023
2 parents 49a690b + 356f0ac commit 2a8a90c
Show file tree
Hide file tree
Showing 4 changed files with 281 additions and 6 deletions.
2 changes: 1 addition & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"lint-and-fix": "eslint . --ext .ts --fix",
"lint-staged": "lint-staged",
"pretest": "docker compose -f test-resources/docker-compose.test.yml up -d",
"test": "cross-env NODE_ENV=test jest --testTimeout=10000 --detectOpenHandles",
"test": "cross-env NODE_ENV=test jest --verbose --testTimeout=10000 --detectOpenHandles",
"test:ci": "npm test -- --watchAll=false --ci --reporters=default --reporters=jest-junit --reporters=github-actions --coverage --testLocationInResults --json --outputFile=coverage/report.json",
"posttest": "docker compose -f test-resources/docker-compose.test.yml down"
},
Expand Down
5 changes: 0 additions & 5 deletions backend/tests/example.test.ts

This file was deleted.

251 changes: 251 additions & 0 deletions backend/tests/utils/crypto.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
import { describe, test, expect } from '@jest/globals';
import {
decryptAsymmetric,
decryptSymmetric,
encryptAsymmetric,
encryptSymmetric
} from '../../src/utils/crypto';

describe('Crypto', () => {
describe('encryptAsymmetric', () => {
describe('given all valid publicKey, privateKey and plaintext', () => {
const publicKey = '6U5m6S5jlyazJ+R4z7Yf/Ah4th4JwKxDN8Wn7+upvzw=';
const privateKey = 'Z8W53YV+2ddjJCrFwzptjK96y2QsQI9oXuvfcx+qxz0=';
const plaintext = 'secret-message';

test('should encrypt plain text', () => {
const result = encryptAsymmetric({ plaintext, publicKey, privateKey });
expect(result.ciphertext).toBeDefined();
expect(result.nonce).toBeDefined();
});
});

describe('given empty/undefined publicKey', () => {
let publicKey: string;
const privateKey = 'Z8W53YV+2ddjJCrFwzptjK96y2QsQI9oXuvfcx+qxz0=';
const plaintext = 'secret-message';

test('should throw error if publicKey is undefined', () => {
expect(() => {
encryptAsymmetric({ plaintext, publicKey, privateKey });
}).toThrowError('Failed to perform asymmetric encryption');
});

test('should throw error if publicKey is empty string', () => {
publicKey = '';
expect(() => {
encryptAsymmetric({ plaintext, publicKey, privateKey });
}).toThrowError('Failed to perform asymmetric encryption');
});
});

describe('given empty/undefined privateKey', () => {
const publicKey = '6U5m6S5jlyazJ+R4z7Yf/Ah4th4JwKxDN8Wn7+upvzw=';
let privateKey: string;
const plaintext = 'secret-message';

test('should throw error if privateKey is undefined', () => {
expect(() => {
encryptAsymmetric({ plaintext, publicKey, privateKey });
}).toThrowError('Failed to perform asymmetric encryption');
});

test('should throw error if privateKey is empty string', () => {
privateKey = '';
expect(() => {
encryptAsymmetric({ plaintext, publicKey, privateKey });
}).toThrowError('Failed to perform asymmetric encryption');
});
});

describe('given undefined/invalid plaint text', () => {
const publicKey = '6U5m6S5jlyazJ+R4z7Yf/Ah4th4JwKxDN8Wn7+upvzw=';
const privateKey = 'Z8W53YV+2ddjJCrFwzptjK96y2QsQI9oXuvfcx+qxz0=';
let plaintext: string;

test('should throw error if plaintext is undefined', () => {
expect(() => {
encryptAsymmetric({ plaintext, publicKey, privateKey });
}).toThrowError('Failed to perform asymmetric encryption');
});

test('should encrypt plaintext containing special characters', () => {
plaintext = '131@#$%235!@#&*(&123sadfkjadjf';
const result = encryptAsymmetric({
plaintext,
publicKey,
privateKey
});
expect(result.ciphertext).toBeDefined();
expect(result.nonce).toBeDefined();
});
});
});

describe('decryptAsymmetric', () => {
describe('given all valid publicKey, privateKey and plaintext', () => {
const publicKey = '6U5m6S5jlyazJ+R4z7Yf/Ah4th4JwKxDN8Wn7+upvzw=';
const privateKey = 'Z8W53YV+2ddjJCrFwzptjK96y2QsQI9oXuvfcx+qxz0=';
const plaintext = 'secret-message';

test('should decrypt the encrypted plaintext', () => {
const encryptedResult = encryptAsymmetric({
plaintext,
publicKey,
privateKey
});
const ciphertext = encryptedResult.ciphertext;
const nonce = encryptedResult.nonce;

const decryptedResult = decryptAsymmetric({
ciphertext,
nonce,
publicKey,
privateKey
});

expect(decryptedResult).toBeDefined();
expect(decryptedResult).toEqual(plaintext);
});
});

describe('given ciphertext or nonce is modified before decrypt', () => {
const publicKey = '6U5m6S5jlyazJ+R4z7Yf/Ah4th4JwKxDN8Wn7+upvzw=';
const privateKey = 'Z8W53YV+2ddjJCrFwzptjK96y2QsQI9oXuvfcx+qxz0=';
const plaintext = 'secret-message';

test('should throw error if ciphertext is modified', () => {
const encryptedResult = encryptAsymmetric({
plaintext,
publicKey,
privateKey
});
const ciphertext = '=12adfJ@#52af1231=123'; // modified
const nonce = encryptedResult.nonce;

expect(() => {
decryptAsymmetric({
ciphertext,
nonce,
publicKey,
privateKey
});
}).toThrowError('Failed to perform asymmetric decryption');
});

test('should throw error if nonce is modified', () => {
const encryptedResult = encryptAsymmetric({
plaintext,
publicKey,
privateKey
});
const ciphertext = encryptedResult.ciphertext;
const nonce = '=12adfJ@#52af1231=123'; // modified

expect(() => {
decryptAsymmetric({
ciphertext,
nonce,
publicKey,
privateKey
});
}).toThrowError('Failed to perform asymmetric decryption');
});
});
});

describe('encryptSymmetric', () => {
let plaintext: string;
const key = '7e8ee7e5cc667b9c1829783ad31f36f4';

test('should encrypt plaintext with the given key', () => {
plaintext = 'secret-message';
const { ciphertext, iv, tag } = encryptSymmetric({ plaintext, key });
expect(ciphertext).toBeDefined();
expect(iv).toBeDefined();
expect(tag).toBeDefined();
});

test('should throw an error when plaintext is undefined', () => {
const invalidKey = 'invalid-key';
expect(() => {
encryptSymmetric({ plaintext, key: invalidKey });
}).toThrowError('Failed to perform symmetric encryption');
});

test('should throw an error when invalid key is provided', () => {
plaintext = 'secret-message';
const invalidKey = 'invalid-key';

expect(() => {
encryptSymmetric({ plaintext, key: invalidKey });
}).toThrowError('Failed to perform symmetric encryption');
});
});

describe('decryptSymmetric', () => {
const plaintext = 'secret-message';
const key = '7e8ee7e5cc667b9c1829783ad31f36f4';
const { ciphertext, iv, tag } = encryptSymmetric({ plaintext, key });

test('should decrypt encrypted plaintext', () => {
const result = decryptSymmetric({
ciphertext,
iv,
tag,
key
});

expect(result).toBeDefined();
expect(result).toEqual(plaintext);
});

test('should fail if ciphertext is modified', () => {
const modifieldCiphertext = 'abcdefghijklmnopqrstuvwxyz';
expect(() => {
decryptSymmetric({
ciphertext: modifieldCiphertext,
iv,
tag,
key
});
}).toThrowError('Failed to perform symmetric decryption');
});

test('should fail if iv is modified', () => {
const modifiedIv = 'abcdefghijklmnopqrstuvwxyz';
expect(() => {
decryptSymmetric({
ciphertext,
iv: modifiedIv,
tag,
key
});
}).toThrowError('Failed to perform symmetric decryption');
});

test('should fail if tag is modified', () => {
const modifiedTag = 'abcdefghijklmnopqrstuvwxyz';
expect(() => {
decryptSymmetric({
ciphertext,
iv,
tag: modifiedTag,
key
});
}).toThrowError('Failed to perform symmetric decryption');
});

test('should throw an error when decryption fails', () => {
const invalidKey = 'invalid-key';
expect(() => {
decryptSymmetric({
ciphertext,
iv,
tag,
key: invalidKey
});
}).toThrowError('Failed to perform symmetric decryption');
});
});
});
29 changes: 29 additions & 0 deletions backend/tests/utils/posthog.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { describe, test, expect } from '@jest/globals';
import { getChannelFromUserAgent } from '../../src/utils/posthog';

describe('posthog getChannelFromUserAgent', () => {
test("should return 'web' when userAgent includes 'mozilla'", () => {
const userAgent =
'Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.5563.115 Mobile Safari/537.36';
const channel = getChannelFromUserAgent(userAgent);
expect(channel).toBe('web');
});

test("should return 'cli'", () => {
const userAgent = 'cli';
const channel = getChannelFromUserAgent(userAgent);
expect(channel).toBe('cli');
});

test("should return 'k8-operator'", () => {
const userAgent = 'k8-operator';
const channel = getChannelFromUserAgent(userAgent);
expect(channel).toBe('k8-operator');
});

test('should return undefined if no userAgent', () => {
const userAgent = undefined;
const channel = getChannelFromUserAgent(userAgent);
expect(channel).toBe('other');
});
});

7 comments on commit 2a8a90c

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage report for backend

St.
Category Percentage Covered / Total
🟢 Statements 90.53% 86/95
🔴 Branches 25% 2/8
🔴 Functions 50% 3/6
🟢 Lines 92.39% 85/92

Test suite run success

24 tests passing in 2 suites.

Report generated by 🧪jest coverage report action from 2a8a90c

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage report for backend

St.
Category Percentage Covered / Total
🟢 Statements 90.53% 86/95
🔴 Branches 25% 2/8
🔴 Functions 50% 3/6
🟢 Lines 92.39% 85/92

Test suite run success

24 tests passing in 2 suites.

Report generated by 🧪jest coverage report action from 2a8a90c

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage report for backend

St.
Category Percentage Covered / Total
🟢 Statements 90.53% 86/95
🔴 Branches 25% 2/8
🔴 Functions 50% 3/6
🟢 Lines 92.39% 85/92

Test suite run success

24 tests passing in 2 suites.

Report generated by 🧪jest coverage report action from 2a8a90c

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage report for backend

St.
Category Percentage Covered / Total
🟢 Statements 90.53% 86/95
🔴 Branches 25% 2/8
🔴 Functions 50% 3/6
🟢 Lines 92.39% 85/92

Test suite run success

24 tests passing in 2 suites.

Report generated by 🧪jest coverage report action from 2a8a90c

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage report for backend

St.
Category Percentage Covered / Total
🟢 Statements 90.53% 86/95
🔴 Branches 25% 2/8
🔴 Functions 50% 3/6
🟢 Lines 92.39% 85/92

Test suite run success

24 tests passing in 2 suites.

Report generated by 🧪jest coverage report action from 2a8a90c

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage report for backend

St.
Category Percentage Covered / Total
🟢 Statements 90.63% 87/96
🔴 Branches 25% 2/8
🔴 Functions 50% 3/6
🟢 Lines 92.47% 86/93

Test suite run success

24 tests passing in 2 suites.

Report generated by 🧪jest coverage report action from 2a8a90c

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage report for backend

St.
Category Percentage Covered / Total
🟢 Statements 90.63% 87/96
🔴 Branches 25% 2/8
🔴 Functions 50% 3/6
🟢 Lines 92.47% 86/93

Test suite run success

24 tests passing in 2 suites.

Report generated by 🧪jest coverage report action from 2a8a90c

Please sign in to comment.