opticedge-cloud-utils 1.1.13 → 1.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,149 +1,149 @@
1
- import {
2
- connectToMongo3,
3
- getDb3,
4
- getCollection3,
5
- __mongoClients,
6
- __connectPromises,
7
- connectToMongoWithUri3
8
- } from '../../src/db/mongo3'
9
- import { MongoClient, Db } from 'mongodb'
10
- import * as secretsModule from '../../src/secrets'
11
-
12
- jest.mock('mongodb')
13
- jest.mock('../../src/secrets')
14
-
15
- const mockDb = {
16
- collection: jest.fn()
17
- } as unknown as Db
18
-
19
- const mockConnect = jest.fn()
20
- const mockClient = {
21
- connect: mockConnect,
22
- db: jest.fn().mockReturnValue(mockDb)
23
- } as unknown as MongoClient
24
-
25
- beforeEach(() => {
26
- jest.clearAllMocks()
27
- __mongoClients.clear()
28
- __connectPromises.clear()
29
- ;(secretsModule.getSecret as jest.Mock).mockResolvedValue('mongodb://mock-uri')
30
- ;(MongoClient as unknown as jest.Mock).mockImplementation(() => mockClient)
31
- })
32
-
33
- describe('MongoClientManager (multi-cluster)', () => {
34
- const clusterASecret = 'clusterA-uri-secret'
35
- const clusterBSecret = 'clusterB-uri-secret'
36
-
37
- it('should connect and cache client for a single cluster', async () => {
38
- await connectToMongo3('test-project', clusterASecret)
39
-
40
- expect(secretsModule.getSecret).toHaveBeenCalledWith('test-project', clusterASecret)
41
- expect(mockConnect).toHaveBeenCalled()
42
-
43
- const db = getDb3(clusterASecret, 'test-db')
44
- expect(mockClient.db).toHaveBeenCalledWith('test-db')
45
- expect(db).toBe(mockDb)
46
- })
47
-
48
- it('should reuse client if already connected', async () => {
49
- await connectToMongo3('test-project', clusterASecret)
50
- await connectToMongo3('test-project', clusterASecret)
51
-
52
- // getSecret and connect should only happen once
53
- expect(secretsModule.getSecret).toHaveBeenCalledTimes(1)
54
- expect(mockConnect).toHaveBeenCalledTimes(1)
55
- })
56
-
57
- it('should connect and cache separate clients for multiple clusters', async () => {
58
- // Mock different URIs for 2 clusters
59
- ;(secretsModule.getSecret as jest.Mock)
60
- .mockResolvedValueOnce('mongodb://mock-uri-A')
61
- .mockResolvedValueOnce('mongodb://mock-uri-B')
62
-
63
- await connectToMongo3('test-project', clusterASecret)
64
- await connectToMongo3('test-project', clusterBSecret)
65
-
66
- // Should call getSecret + connect twice (for 2 clusters)
67
- expect(secretsModule.getSecret).toHaveBeenCalledTimes(2)
68
- expect(secretsModule.getSecret).toHaveBeenCalledWith('test-project', clusterASecret)
69
- expect(secretsModule.getSecret).toHaveBeenCalledWith('test-project', clusterBSecret)
70
- expect(mockConnect).toHaveBeenCalledTimes(2)
71
- })
72
-
73
- it('should return a collection when client is initialized', async () => {
74
- await connectToMongo3('test-project', clusterASecret)
75
-
76
- getCollection3(clusterASecret, 'test-db', 'users')
77
-
78
- expect(mockClient.db).toHaveBeenCalledWith('test-db')
79
- expect(mockDb.collection).toHaveBeenCalledWith('users')
80
- })
81
-
82
- it('should throw error if client not initialized (getDb)', () => {
83
- jest.isolateModules(() => {
84
- // eslint-disable-next-line @typescript-eslint/no-require-imports
85
- const { getDb3 } = require('../../src/db/mongo3')
86
- expect(() => getDb3('unknown-uri-secret', 'some-db')).toThrow(
87
- 'Mongo client for secret "unknown-uri-secret" not initialized'
88
- )
89
- })
90
- })
91
-
92
- it('should throw error if client not initialized (getCollection)', () => {
93
- jest.isolateModules(() => {
94
- // eslint-disable-next-line @typescript-eslint/no-require-imports
95
- const { getCollection3 } = require('../../src/db/mongo3')
96
- expect(() => getCollection3('unknown-uri-secret', 'some-db', 'users')).toThrow(
97
- 'Mongo client for secret "unknown-uri-secret" not initialized'
98
- )
99
- })
100
- })
101
- })
102
-
103
- describe('MongoClientManager (multi-cluster) 2', () => {
104
- const clusterAUri = 'clusterA-uri'
105
- const clusterBUri = 'clusterB-uri'
106
-
107
- it('should connect and cache client for a single cluster', async () => {
108
- jest.isolateModules(async () => {
109
- // eslint-disable-next-line @typescript-eslint/no-require-imports
110
- const { connectToMongoWithUri3, getDb3 } = require('../../src/db/mongo3')
111
- await connectToMongoWithUri3(clusterAUri)
112
-
113
- expect(mockConnect).toHaveBeenCalled()
114
-
115
- const db = getDb3(clusterAUri, 'test-db')
116
- expect(mockClient.db).toHaveBeenCalledWith('test-db')
117
- expect(db).toBe(mockDb)
118
- })
119
- })
120
-
121
- it('should reuse client if already connected', async () => {
122
- jest.isolateModules(async () => {
123
- // eslint-disable-next-line @typescript-eslint/no-require-imports
124
- const { connectToMongoWithUri3 } = require('../../src/db/mongo3')
125
- await connectToMongoWithUri3(clusterAUri)
126
- await connectToMongoWithUri3(clusterAUri)
127
- expect(mockConnect).toHaveBeenCalledTimes(1)
128
- })
129
- })
130
-
131
- it('should connect and cache separate clients for multiple clusters', async () => {
132
- jest.isolateModules(async () => {
133
- // eslint-disable-next-line @typescript-eslint/no-require-imports
134
- const { connectToMongoWithUri3 } = require('../../src/db/mongo3')
135
- await connectToMongoWithUri3(clusterAUri)
136
- await connectToMongoWithUri3(clusterBUri)
137
- expect(mockConnect).toHaveBeenCalledTimes(2)
138
- })
139
- })
140
-
141
- it('should return a collection when client is initialized', async () => {
142
- await connectToMongoWithUri3(clusterAUri)
143
-
144
- getCollection3(clusterAUri, 'test-db', 'users')
145
-
146
- expect(mockClient.db).toHaveBeenCalledWith('test-db')
147
- expect(mockDb.collection).toHaveBeenCalledWith('users')
148
- })
149
- })
1
+ import {
2
+ connectToMongo3,
3
+ getDb3,
4
+ getCollection3,
5
+ __mongoClients,
6
+ __connectPromises,
7
+ connectToMongoWithUri3
8
+ } from '../../src/db/mongo3'
9
+ import { MongoClient, Db } from 'mongodb'
10
+ import * as secretsModule from '../../src/secrets'
11
+
12
+ jest.mock('mongodb')
13
+ jest.mock('../../src/secrets')
14
+
15
+ const mockDb = {
16
+ collection: jest.fn()
17
+ } as unknown as Db
18
+
19
+ const mockConnect = jest.fn()
20
+ const mockClient = {
21
+ connect: mockConnect,
22
+ db: jest.fn().mockReturnValue(mockDb)
23
+ } as unknown as MongoClient
24
+
25
+ beforeEach(() => {
26
+ jest.clearAllMocks()
27
+ __mongoClients.clear()
28
+ __connectPromises.clear()
29
+ ;(secretsModule.getSecret as jest.Mock).mockResolvedValue('mongodb://mock-uri')
30
+ ;(MongoClient as unknown as jest.Mock).mockImplementation(() => mockClient)
31
+ })
32
+
33
+ describe('MongoClientManager (multi-cluster)', () => {
34
+ const clusterASecret = 'clusterA-uri-secret'
35
+ const clusterBSecret = 'clusterB-uri-secret'
36
+
37
+ it('should connect and cache client for a single cluster', async () => {
38
+ await connectToMongo3('test-project', clusterASecret)
39
+
40
+ expect(secretsModule.getSecret).toHaveBeenCalledWith('test-project', clusterASecret)
41
+ expect(mockConnect).toHaveBeenCalled()
42
+
43
+ const db = getDb3(clusterASecret, 'test-db')
44
+ expect(mockClient.db).toHaveBeenCalledWith('test-db')
45
+ expect(db).toBe(mockDb)
46
+ })
47
+
48
+ it('should reuse client if already connected', async () => {
49
+ await connectToMongo3('test-project', clusterASecret)
50
+ await connectToMongo3('test-project', clusterASecret)
51
+
52
+ // getSecret and connect should only happen once
53
+ expect(secretsModule.getSecret).toHaveBeenCalledTimes(1)
54
+ expect(mockConnect).toHaveBeenCalledTimes(1)
55
+ })
56
+
57
+ it('should connect and cache separate clients for multiple clusters', async () => {
58
+ // Mock different URIs for 2 clusters
59
+ ;(secretsModule.getSecret as jest.Mock)
60
+ .mockResolvedValueOnce('mongodb://mock-uri-A')
61
+ .mockResolvedValueOnce('mongodb://mock-uri-B')
62
+
63
+ await connectToMongo3('test-project', clusterASecret)
64
+ await connectToMongo3('test-project', clusterBSecret)
65
+
66
+ // Should call getSecret + connect twice (for 2 clusters)
67
+ expect(secretsModule.getSecret).toHaveBeenCalledTimes(2)
68
+ expect(secretsModule.getSecret).toHaveBeenCalledWith('test-project', clusterASecret)
69
+ expect(secretsModule.getSecret).toHaveBeenCalledWith('test-project', clusterBSecret)
70
+ expect(mockConnect).toHaveBeenCalledTimes(2)
71
+ })
72
+
73
+ it('should return a collection when client is initialized', async () => {
74
+ await connectToMongo3('test-project', clusterASecret)
75
+
76
+ getCollection3(clusterASecret, 'test-db', 'users')
77
+
78
+ expect(mockClient.db).toHaveBeenCalledWith('test-db')
79
+ expect(mockDb.collection).toHaveBeenCalledWith('users')
80
+ })
81
+
82
+ it('should throw error if client not initialized (getDb)', () => {
83
+ jest.isolateModules(() => {
84
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
85
+ const { getDb3 } = require('../../src/db/mongo3')
86
+ expect(() => getDb3('unknown-uri-secret', 'some-db')).toThrow(
87
+ 'Mongo client for secret "unknown-uri-secret" not initialized'
88
+ )
89
+ })
90
+ })
91
+
92
+ it('should throw error if client not initialized (getCollection)', () => {
93
+ jest.isolateModules(() => {
94
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
95
+ const { getCollection3 } = require('../../src/db/mongo3')
96
+ expect(() => getCollection3('unknown-uri-secret', 'some-db', 'users')).toThrow(
97
+ 'Mongo client for secret "unknown-uri-secret" not initialized'
98
+ )
99
+ })
100
+ })
101
+ })
102
+
103
+ describe('MongoClientManager (multi-cluster) 2', () => {
104
+ const clusterAUri = 'clusterA-uri'
105
+ const clusterBUri = 'clusterB-uri'
106
+
107
+ it('should connect and cache client for a single cluster', async () => {
108
+ jest.isolateModules(async () => {
109
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
110
+ const { connectToMongoWithUri3, getDb3 } = require('../../src/db/mongo3')
111
+ await connectToMongoWithUri3(clusterAUri)
112
+
113
+ expect(mockConnect).toHaveBeenCalled()
114
+
115
+ const db = getDb3(clusterAUri, 'test-db')
116
+ expect(mockClient.db).toHaveBeenCalledWith('test-db')
117
+ expect(db).toBe(mockDb)
118
+ })
119
+ })
120
+
121
+ it('should reuse client if already connected', async () => {
122
+ jest.isolateModules(async () => {
123
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
124
+ const { connectToMongoWithUri3 } = require('../../src/db/mongo3')
125
+ await connectToMongoWithUri3(clusterAUri)
126
+ await connectToMongoWithUri3(clusterAUri)
127
+ expect(mockConnect).toHaveBeenCalledTimes(1)
128
+ })
129
+ })
130
+
131
+ it('should connect and cache separate clients for multiple clusters', async () => {
132
+ jest.isolateModules(async () => {
133
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
134
+ const { connectToMongoWithUri3 } = require('../../src/db/mongo3')
135
+ await connectToMongoWithUri3(clusterAUri)
136
+ await connectToMongoWithUri3(clusterBUri)
137
+ expect(mockConnect).toHaveBeenCalledTimes(2)
138
+ })
139
+ })
140
+
141
+ it('should return a collection when client is initialized', async () => {
142
+ await connectToMongoWithUri3(clusterAUri)
143
+
144
+ getCollection3(clusterAUri, 'test-db', 'users')
145
+
146
+ expect(mockClient.db).toHaveBeenCalledWith('test-db')
147
+ expect(mockDb.collection).toHaveBeenCalledWith('users')
148
+ })
149
+ })
package/tests/env.test.ts CHANGED
@@ -1,18 +1,18 @@
1
- import { getEnv } from '../src/env'
2
-
3
- describe('getEnv', () => {
4
- it('returns the value of an existing env var', () => {
5
- process.env.TEST_KEY = 'test-value'
6
- expect(getEnv('TEST_KEY')).toBe('test-value')
7
- })
8
-
9
- it('returns fallback if env var is not set', () => {
10
- delete process.env.OPTIONAL_KEY
11
- expect(getEnv('OPTIONAL_KEY', 'default')).toBe('default')
12
- })
13
-
14
- it('throws error if env var is not set and no fallback provided', () => {
15
- delete process.env.MISSING_KEY
16
- expect(() => getEnv('MISSING_KEY')).toThrow('Missing env var MISSING_KEY')
17
- })
18
- })
1
+ import { getEnv } from '../src/env'
2
+
3
+ describe('getEnv', () => {
4
+ it('returns the value of an existing env var', () => {
5
+ process.env.TEST_KEY = 'test-value'
6
+ expect(getEnv('TEST_KEY')).toBe('test-value')
7
+ })
8
+
9
+ it('returns fallback if env var is not set', () => {
10
+ delete process.env.OPTIONAL_KEY
11
+ expect(getEnv('OPTIONAL_KEY', 'default')).toBe('default')
12
+ })
13
+
14
+ it('throws error if env var is not set and no fallback provided', () => {
15
+ delete process.env.MISSING_KEY
16
+ expect(() => getEnv('MISSING_KEY')).toThrow('Missing env var MISSING_KEY')
17
+ })
18
+ })
@@ -1,26 +1,26 @@
1
- import { toNumber } from '../src'
2
-
3
- describe('toNumber', () => {
4
- it('returns the same number when input is a finite number', () => {
5
- expect(toNumber(123)).toBe(123)
6
- expect(toNumber(0)).toBe(0)
7
- })
8
-
9
- it('returns number when input is a numeric string', () => {
10
- expect(toNumber('456')).toBe(456)
11
- })
12
-
13
- it('returns null for non-numeric strings', () => {
14
- expect(toNumber('abc')).toBeNull()
15
- expect(toNumber('123abc')).toBeNull()
16
- expect(toNumber('')).toBeNull()
17
- })
18
-
19
- it('returns null for non-numbers', () => {
20
- expect(toNumber(NaN)).toBeNull()
21
- expect(toNumber(Infinity)).toBeNull()
22
- expect(toNumber(undefined)).toBeNull()
23
- expect(toNumber(null)).toBeNull()
24
- expect(toNumber({})).toBeNull()
25
- })
26
- })
1
+ import { toNumber } from '../src'
2
+
3
+ describe('toNumber', () => {
4
+ it('returns the same number when input is a finite number', () => {
5
+ expect(toNumber(123)).toBe(123)
6
+ expect(toNumber(0)).toBe(0)
7
+ })
8
+
9
+ it('returns number when input is a numeric string', () => {
10
+ expect(toNumber('456')).toBe(456)
11
+ })
12
+
13
+ it('returns null for non-numeric strings', () => {
14
+ expect(toNumber('abc')).toBeNull()
15
+ expect(toNumber('123abc')).toBeNull()
16
+ expect(toNumber('')).toBeNull()
17
+ })
18
+
19
+ it('returns null for non-numbers', () => {
20
+ expect(toNumber(NaN)).toBeNull()
21
+ expect(toNumber(Infinity)).toBeNull()
22
+ expect(toNumber(undefined)).toBeNull()
23
+ expect(toNumber(null)).toBeNull()
24
+ expect(toNumber({})).toBeNull()
25
+ })
26
+ })
@@ -1,69 +1,69 @@
1
- // tests/regex.test.ts
2
- import { escapeForRegex } from '../src/regex'
3
-
4
- describe('escapeForRegex', () => {
5
- it('escapes regex special characters (including backslash)', () => {
6
- const input = 'Pikachu.$^*+?()[]{}|\\'
7
- const expected = 'Pikachu\\.\\$\\^\\*\\+\\?\\(\\)\\[\\]\\{\\}\\|\\\\'
8
- expect(escapeForRegex(input)).toBe(expected)
9
- })
10
-
11
- it('replaces whitespace runs with \\s+ and escapes other metachars', () => {
12
- const input = 'Charizard (Holo Rare)' // multiple spaces inside
13
- const expected = 'Charizard\\s+\\(Holo\\s+Rare\\)'
14
- expect(escapeForRegex(input)).toBe(expected)
15
- })
16
-
17
- it('leaves plain alphanumerics unchanged', () => {
18
- const input = 'Charmander123'
19
- expect(escapeForRegex(input)).toBe('Charmander123')
20
- })
21
-
22
- it('converts tabs and single spaces to \\s+ and escapes dots', () => {
23
- const input = 'Lt. Surge\tPikachu'
24
- const expected = 'Lt\\.\\s+Surge\\s+Pikachu'
25
- expect(escapeForRegex(input)).toBe(expected)
26
- })
27
-
28
- it('truncates input when maxLength is passed', () => {
29
- const long = 'a'.repeat(200)
30
- // override maxLength to 50 for this test
31
- expect(escapeForRegex(long, 50)).toBe('a'.repeat(50))
32
- })
33
-
34
- it('applies default cap of 100 characters when input is longer and contains no metachars', () => {
35
- const long = 'b'.repeat(150)
36
- const out = escapeForRegex(long) // default cap = 100
37
- expect(out).toBe('b'.repeat(100))
38
- expect(out.length).toBe(100)
39
- })
40
-
41
- it('handles empty string', () => {
42
- expect(escapeForRegex('')).toBe('')
43
- })
44
-
45
- // -----------------------------
46
- // NEW: coverage for safeStr branch
47
- // -----------------------------
48
- it('handles undefined input (covers input ?? "")', () => {
49
- // call with undefined; TypeScript may complain so cast to any in test
50
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
51
- expect(escapeForRegex(undefined as any)).toBe('')
52
- })
53
-
54
- it('handles null input (covers input ?? "")', () => {
55
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
56
- expect(escapeForRegex(null as any)).toBe('')
57
- })
58
-
59
- it('coerces non-string input to string and escapes metachars if present', () => {
60
- // number becomes "42"
61
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
62
- expect(escapeForRegex(42 as any)).toBe('42')
63
-
64
- // object coerces to "[object Object]" and special chars will be escaped if present
65
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
- const objInput = { toString: () => 'X(1) Y' } as any
67
- expect(escapeForRegex(objInput)).toBe('X\\(1\\)\\s+Y')
68
- })
69
- })
1
+ // tests/regex.test.ts
2
+ import { escapeForRegex } from '../src/regex'
3
+
4
+ describe('escapeForRegex', () => {
5
+ it('escapes regex special characters (including backslash)', () => {
6
+ const input = 'Pikachu.$^*+?()[]{}|\\'
7
+ const expected = 'Pikachu\\.\\$\\^\\*\\+\\?\\(\\)\\[\\]\\{\\}\\|\\\\'
8
+ expect(escapeForRegex(input)).toBe(expected)
9
+ })
10
+
11
+ it('replaces whitespace runs with \\s+ and escapes other metachars', () => {
12
+ const input = 'Charizard (Holo Rare)' // multiple spaces inside
13
+ const expected = 'Charizard\\s+\\(Holo\\s+Rare\\)'
14
+ expect(escapeForRegex(input)).toBe(expected)
15
+ })
16
+
17
+ it('leaves plain alphanumerics unchanged', () => {
18
+ const input = 'Charmander123'
19
+ expect(escapeForRegex(input)).toBe('Charmander123')
20
+ })
21
+
22
+ it('converts tabs and single spaces to \\s+ and escapes dots', () => {
23
+ const input = 'Lt. Surge\tPikachu'
24
+ const expected = 'Lt\\.\\s+Surge\\s+Pikachu'
25
+ expect(escapeForRegex(input)).toBe(expected)
26
+ })
27
+
28
+ it('truncates input when maxLength is passed', () => {
29
+ const long = 'a'.repeat(200)
30
+ // override maxLength to 50 for this test
31
+ expect(escapeForRegex(long, 50)).toBe('a'.repeat(50))
32
+ })
33
+
34
+ it('applies default cap of 100 characters when input is longer and contains no metachars', () => {
35
+ const long = 'b'.repeat(150)
36
+ const out = escapeForRegex(long) // default cap = 100
37
+ expect(out).toBe('b'.repeat(100))
38
+ expect(out.length).toBe(100)
39
+ })
40
+
41
+ it('handles empty string', () => {
42
+ expect(escapeForRegex('')).toBe('')
43
+ })
44
+
45
+ // -----------------------------
46
+ // NEW: coverage for safeStr branch
47
+ // -----------------------------
48
+ it('handles undefined input (covers input ?? "")', () => {
49
+ // call with undefined; TypeScript may complain so cast to any in test
50
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
51
+ expect(escapeForRegex(undefined as any)).toBe('')
52
+ })
53
+
54
+ it('handles null input (covers input ?? "")', () => {
55
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
56
+ expect(escapeForRegex(null as any)).toBe('')
57
+ })
58
+
59
+ it('coerces non-string input to string and escapes metachars if present', () => {
60
+ // number becomes "42"
61
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
62
+ expect(escapeForRegex(42 as any)).toBe('42')
63
+
64
+ // object coerces to "[object Object]" and special chars will be escaped if present
65
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
+ const objInput = { toString: () => 'X(1) Y' } as any
67
+ expect(escapeForRegex(objInput)).toBe('X\\(1\\)\\s+Y')
68
+ })
69
+ })