Skip to content

Commit c95d520

Browse files
committed
test: split util.spec.ts into separate spec files
1 parent f09d738 commit c95d520

5 files changed

Lines changed: 307 additions & 311 deletions

File tree

test/env-utils.spec.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import * as utils from '../packages/core/src';
2+
3+
describe('fromEnv', () => {
4+
const originalEnv = { ...process.env };
5+
6+
afterEach(() => {
7+
process.env = originalEnv;
8+
});
9+
10+
it('should read env vars without prefix (default)', () => {
11+
process.env['BASE_URL'] = 'https://example.com';
12+
process.env['UPLOAD_DIR'] = '/uploads';
13+
process.env['MAX_FILE_SIZE'] = '10MB';
14+
const result = utils.fromEnv();
15+
expect(result).toEqual({
16+
baseUrl: 'https://example.com',
17+
uploadDir: '/uploads',
18+
maxFileSize: '10MB'
19+
});
20+
});
21+
22+
it('should read custom prefix', () => {
23+
process.env['MY_APP_BASE_URL'] = 'https://custom.com';
24+
process.env['MY_APP_UPLOAD_DIR'] = '/data';
25+
const result = utils.fromEnv('MY_APP_');
26+
expect(result).toEqual({
27+
baseUrl: 'https://custom.com',
28+
uploadDir: '/data'
29+
});
30+
});
31+
32+
it('should return empty object when no env vars', () => {
33+
const result = utils.fromEnv();
34+
expect(result).toEqual({});
35+
});
36+
37+
it('should parse ALLOWED_MIME_TYPES as array', () => {
38+
process.env['ALLOWED_MIME_TYPES'] = 'image/png, image/jpeg , video/mp4';
39+
const result = utils.fromEnv();
40+
expect(result).toEqual({
41+
allowedMimeTypes: ['image/png', 'image/jpeg', 'video/mp4']
42+
});
43+
});
44+
});

test/fs-utils.spec.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import fs from 'fs';
2+
import { join } from 'path';
3+
import * as utils from '../packages/core/src';
4+
import { cleanup, testRoot } from './shared';
5+
6+
jest.mock('fs/promises');
7+
jest.mock('fs');
8+
9+
describe('fs utils', () => {
10+
const root = join(testRoot, 'fs-utils');
11+
const dir = join(root, '0', '1', '2');
12+
const filepath = join(dir, '3', 'file.ext');
13+
const filepath2 = join(dir, '3', 'fi le.ext.META');
14+
15+
beforeEach(async () => cleanup(root));
16+
17+
afterEach(async () => cleanup(root));
18+
19+
it('ensureDir(dir)', async () => {
20+
await utils.ensureDir(dir);
21+
expect(fs.existsSync(dir)).toBe(true);
22+
});
23+
24+
it('ensureFile(file)', async () => {
25+
const size = await utils.ensureFile(filepath);
26+
expect(fs.existsSync(filepath)).toBe(true);
27+
expect(size).toBe(0);
28+
});
29+
30+
it('ensureFile(file, overwrite)', async () => {
31+
const size = await utils.ensureFile(filepath, true);
32+
expect(fs.existsSync(filepath)).toBe(true);
33+
expect(size).toBe(0);
34+
});
35+
36+
it('getFiles(full path)', async () => {
37+
await utils.ensureFile(filepath);
38+
await utils.ensureFile(`${filepath}.ext`);
39+
await utils.ensureFile(filepath2);
40+
await utils.ensureFile(`${filepath2}.ext`);
41+
await expect(utils.getFiles(filepath)).resolves.toHaveLength(2);
42+
await expect(utils.getFiles(filepath2)).resolves.toHaveLength(2);
43+
});
44+
45+
it('getFiles(prefix)', async () => {
46+
await utils.ensureFile(filepath);
47+
await utils.ensureFile(filepath2);
48+
await expect(utils.getFiles(`${testRoot}/fs-`)).resolves.toHaveLength(2);
49+
await expect(utils.getFiles(`${testRoot}\\fs-`)).resolves.toHaveLength(2);
50+
await expect(utils.getFiles(`${testRoot}\\fs_`)).resolves.toHaveLength(0);
51+
await expect(utils.getFiles(`${testRoot}/fs_`)).resolves.toHaveLength(0);
52+
});
53+
54+
it('getFiles(directory)', async () => {
55+
await utils.ensureFile(filepath);
56+
await utils.ensureFile(filepath2);
57+
await expect(utils.getFiles(testRoot)).resolves.toHaveLength(2);
58+
});
59+
60+
it('getFiles(deep directory)', async () => {
61+
await utils.ensureFile(filepath);
62+
await utils.ensureFile(filepath2);
63+
await expect(utils.getFiles(dir)).resolves.toHaveLength(2);
64+
});
65+
66+
it('getFiles(not existing)', async () => {
67+
await utils.ensureFile(filepath);
68+
await expect(utils.getFiles('not exist')).resolves.toHaveLength(0);
69+
});
70+
71+
it('removeFile(path)', async () => {
72+
await utils.ensureFile(filepath);
73+
await utils.removeFile(filepath);
74+
expect(fs.existsSync(filepath)).toBe(false);
75+
});
76+
77+
it('removeFile(not exist)', async () => {
78+
await utils.removeFile(filepath);
79+
expect(fs.existsSync(filepath)).toBe(false);
80+
});
81+
82+
it('getWriteStream(path, 0)', async () => {
83+
await utils.ensureFile(filepath);
84+
const stream = utils.getWriteStream(filepath, 0);
85+
stream.close();
86+
expect(stream).toBeInstanceOf(fs.WriteStream);
87+
});
88+
});

test/http-utils.spec.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { IncomingMessage } from 'http';
2+
import * as utils from '../packages/core/src';
3+
4+
describe('http utils', () => {
5+
const mime = 'application/vnd+json';
6+
const req = { headers: { 'content-type': mime } } as IncomingMessage;
7+
8+
it('typeis()', () => {
9+
expect(utils.typeis({ headers: {} } as IncomingMessage, ['json'])).toBe(false);
10+
expect(utils.typeis(req, ['html'])).toBe(false);
11+
expect(utils.typeis(req, ['json'])).toBe(mime);
12+
});
13+
14+
it('typeis.is()', () => {
15+
expect(utils.typeis.is(mime, ['application/vnd+json'])).toBe(mime);
16+
expect(utils.typeis.is(mime, ['vnd+json'])).toBe(mime);
17+
expect(utils.typeis.is(mime, ['application/*'])).toBe(mime);
18+
expect(utils.typeis.is(mime, ['json', 'xml'])).toBe(mime);
19+
expect(utils.typeis.is(mime, ['*/*'])).toBe(mime);
20+
});
21+
22+
it('typeis.hasBody()', () => {
23+
expect(utils.typeis.hasBody({ headers: {} } as IncomingMessage)).toBe(false);
24+
expect(utils.typeis.hasBody({ headers: { 'content-length': '0' } } as IncomingMessage)).toBe(0);
25+
expect(utils.typeis.hasBody({ headers: { 'content-length': '1' } } as IncomingMessage)).toBe(1);
26+
});
27+
28+
it('getHeader(not exist)', () => {
29+
expect(utils.getHeader(req, 'not exist')).toBe('');
30+
});
31+
32+
it('getHeader(single)', () => {
33+
req.headers = { head: 'value' };
34+
expect(utils.getHeader(req, 'head')).toBe('value');
35+
});
36+
37+
it('getHeader(array)', () => {
38+
req.headers = { head: ['value1', 'value2 '] };
39+
expect(utils.getHeader(req, 'head')).toBe('value2');
40+
});
41+
42+
it('getHeader(multiple)', () => {
43+
req.headers = { head: 'value1 ,value2' };
44+
expect(utils.getHeader(req, 'head')).toBe('value2');
45+
});
46+
47+
it('getHeader(multiple, all)', () => {
48+
req.headers = { head: 'value1,value2 ' };
49+
expect(utils.getHeader(req, 'head', true)).toBe('value1,value2');
50+
});
51+
52+
it('getBaseUrl(no-host)', () => {
53+
expect(utils.getBaseUrl(req)).toBe('');
54+
});
55+
56+
it('getBaseUrl(no-proto)', () => {
57+
req.headers = { host: 'example' };
58+
expect(utils.getBaseUrl(req)).toBe('//example');
59+
});
60+
61+
it('getBaseUrl(absolute)', () => {
62+
req.headers = { host: 'example:4443', 'x-forwarded-proto': 'https' };
63+
expect(utils.getBaseUrl(req)).toBe('https://example:4443');
64+
});
65+
});

test/primitives.spec.ts

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import * as utils from '../packages/core/src';
2+
3+
describe('primitives', () => {
4+
it('fnv', () => {
5+
expect(utils.fnv('123456')).toBe('9995b6aa');
6+
expect(utils.fnv('спутник')).toBe('5e1edd8c');
7+
});
8+
9+
it('fnv64', () => {
10+
expect(utils.fnv64('123456')).toBe('f6e3ed7e0e67290a');
11+
expect(utils.fnv64('спутник')).toBe('6251be44251f6e2c');
12+
});
13+
14+
it('pick', () => {
15+
expect(utils.pick({ test: 'test', rest: 'rest' }, ['test'])).toMatchObject({
16+
test: 'test'
17+
});
18+
});
19+
20+
it('isEqual', () => {
21+
expect(utils.isEqual({ a: 1, b: 2 }, undefined)).toBe(false);
22+
expect(utils.isEqual(undefined, undefined)).toBe(false);
23+
expect(utils.isEqual({ a: 1, b: 2 }, { a: 1, b: 2 })).toBe(true);
24+
expect(utils.isEqual({ a: 1, b: 2, c: 3 }, { a: 1, b: 2 })).toBe(false);
25+
expect(utils.isEqual({ a: 1, b: 2, c: 3 }, { a: 1, b: 2 }, 'c')).toBe(true);
26+
expect(utils.isEqual({ a: 1, b: 2, c: { k: 3 } }, { a: 1, b: 2, c: { k: 3 } })).toBe(true);
27+
expect(utils.isEqual({ a: 1, b: 2, c: { k: 3 } }, { a: 1, b: 2, c: { k: 4 } })).toBe(false);
28+
expect(utils.isEqual({ a: 1, b: 2 }, { b: 2, a: 1 })).toBe(true);
29+
});
30+
31+
it('memoize', () => {
32+
const md5Cached = utils.memoize(utils.md5);
33+
const fnvCached = utils.memoize(utils.fnv);
34+
expect(md5Cached('123456')).toBe('e10adc3949ba59abbe56e057f20f883e');
35+
expect(fnvCached('123456')).toBe('9995b6aa');
36+
});
37+
38+
it('extendObject', () => {
39+
expect(utils.extendObject<object>({ a: 1 }, { a: { b: 1 }, c: null })).toEqual({
40+
a: { b: 1 },
41+
c: null
42+
});
43+
expect(utils.extendObject<object>({ a: 1, c: [4] }, { a: { b: 1 }, c: [1, 2, 3] })).toEqual({
44+
a: { b: 1 },
45+
c: [1, 2, 3]
46+
});
47+
});
48+
49+
describe('Duration Conversion', () => {
50+
const durationToMs = utils.durationToMs;
51+
52+
it('should convert ms', () => {
53+
expect(durationToMs('500')).toBe(500);
54+
});
55+
56+
it('should convert single unit durations', () => {
57+
expect(durationToMs('5s')).toBe(5000);
58+
expect(durationToMs('10m')).toBe(600000);
59+
expect(durationToMs('2h')).toBe(7200000);
60+
expect(durationToMs('3d')).toBe(259200000);
61+
});
62+
63+
it('should convert multiple unit durations', () => {
64+
expect(durationToMs('1h 30m')).toBe(5400000);
65+
expect(durationToMs('2d 4h 30m')).toBe(189000000);
66+
expect(durationToMs('1w 2d 3h')).toBe(788400000);
67+
});
68+
69+
it('should handle full word units', () => {
70+
expect(durationToMs('5 seconds')).toBe(5000);
71+
expect(durationToMs('2 hours')).toBe(7200000);
72+
expect(durationToMs('1 day 12 hours')).toBe(129600000);
73+
});
74+
75+
it('should throw error for invalid units', () => {
76+
expect(() => durationToMs('5x')).toThrow('Invalid time unit: x');
77+
expect(() => durationToMs('10 invalid')).toThrow('Invalid time unit: invalid');
78+
});
79+
80+
it('should throw error for invalid format', () => {
81+
expect(() => durationToMs('abc')).toThrow('Invalid duration format');
82+
expect(() => durationToMs('')).toThrow('Invalid duration format');
83+
});
84+
85+
it('should throw error for excessive input length', () => {
86+
const longInput = '1s '.repeat(17);
87+
expect(() => durationToMs(longInput)).toThrow('Input string exceeds maximum length');
88+
});
89+
90+
it('should convert to milliseconds', () => {
91+
const toMilliseconds = utils.toMilliseconds;
92+
expect(toMilliseconds(0)).toBe(0);
93+
expect(toMilliseconds('0')).toBe(0);
94+
expect(toMilliseconds(1500)).toBe(1500);
95+
expect(toMilliseconds('5s')).toBe(5000);
96+
expect(toMilliseconds(undefined)).toBeUndefined();
97+
expect(toMilliseconds('')).toBeUndefined();
98+
});
99+
100+
it('should convert to seconds', () => {
101+
const toSeconds = utils.toSeconds;
102+
expect(toSeconds(0)).toBe(0);
103+
expect(toSeconds('0')).toBe(0);
104+
expect(toSeconds(1500)).toBe(1);
105+
expect(toSeconds('5s')).toBe(5);
106+
expect(toSeconds(undefined)).toBeUndefined();
107+
expect(toSeconds('')).toBeUndefined();
108+
});
109+
});
110+
});

0 commit comments

Comments
 (0)