@nooks-ai/nooks-zoominfo-api-auth-client 1.0.2 → 1.1.0

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.
@@ -0,0 +1,19 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ strategy:
11
+ matrix:
12
+ node-version: [20, 22, 24]
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-node@v4
16
+ with:
17
+ node-version: ${{ matrix.node-version }}
18
+ - run: npm i
19
+ - run: npm test
package/index.test.js ADDED
@@ -0,0 +1,99 @@
1
+ const axios = require('axios');
2
+ const rs = require('jsrsasign');
3
+
4
+ jest.mock('axios');
5
+ jest.mock('jsrsasign');
6
+
7
+ const { getAccessTokenViaPKI, getAccessTokenViaBasicAuth } = require('./index');
8
+
9
+ const AUTH_URL = 'https://api.zoominfo.com/authenticate';
10
+
11
+ describe('getAccessTokenViaBasicAuth', () => {
12
+ afterEach(() => jest.resetAllMocks());
13
+
14
+ it('sends username and password and returns the JWT', async () => {
15
+ axios.post.mockResolvedValue({ data: { jwt: 'test-token-123' } });
16
+
17
+ const token = await getAccessTokenViaBasicAuth('user@example.com', 'pass123');
18
+
19
+ expect(axios.post).toHaveBeenCalledWith(AUTH_URL, {
20
+ username: 'user@example.com',
21
+ password: 'pass123',
22
+ });
23
+ expect(token).toBe('test-token-123');
24
+ });
25
+
26
+ it('returns the error when the request fails', async () => {
27
+ const err = new Error('Network error');
28
+ axios.post.mockRejectedValue(err);
29
+
30
+ const result = await getAccessTokenViaBasicAuth('user@example.com', 'pass123');
31
+
32
+ expect(result).toBe(err);
33
+ });
34
+ });
35
+
36
+ describe('getAccessTokenViaPKI', () => {
37
+ afterEach(() => jest.resetAllMocks());
38
+
39
+ it('signs a JWT and sends it as a Bearer token', async () => {
40
+ rs.jws = { JWS: { sign: jest.fn().mockReturnValue('signed-jwt') } };
41
+ axios.post.mockResolvedValue({ data: { jwt: 'access-token-456' } });
42
+
43
+ const token = await getAccessTokenViaPKI('user@example.com', 'client-id', 'private-key');
44
+
45
+ // Verify JWS.sign was called with RS256
46
+ expect(rs.jws.JWS.sign).toHaveBeenCalledWith(
47
+ 'RS256',
48
+ expect.any(String),
49
+ expect.any(String),
50
+ 'private-key'
51
+ );
52
+
53
+ // Verify the JWT payload contains expected fields
54
+ const payloadArg = JSON.parse(rs.jws.JWS.sign.mock.calls[0][2]);
55
+ expect(payloadArg).toMatchObject({
56
+ aud: 'enterprise_api',
57
+ iss: 'zoominfo-api-auth-client-nodejs',
58
+ username: 'user@example.com',
59
+ client_id: 'client-id',
60
+ });
61
+ expect(payloadArg.iat).toBeDefined();
62
+ expect(payloadArg.exp).toBeDefined();
63
+ expect(payloadArg.exp).toBeGreaterThan(payloadArg.iat);
64
+
65
+ // Verify axios was called with the signed JWT
66
+ expect(axios.post).toHaveBeenCalledWith(
67
+ AUTH_URL,
68
+ {},
69
+ { headers: { Authorization: 'Bearer signed-jwt' } }
70
+ );
71
+ expect(token).toBe('access-token-456');
72
+ });
73
+
74
+ it('returns the error when the request fails', async () => {
75
+ rs.jws = { JWS: { sign: jest.fn().mockReturnValue('signed-jwt') } };
76
+ const err = new Error('Auth failed');
77
+ axios.post.mockRejectedValue(err);
78
+
79
+ const result = await getAccessTokenViaPKI('user@example.com', 'client-id', 'private-key');
80
+
81
+ expect(result).toBe(err);
82
+ });
83
+
84
+ it('sets iat to ~60 seconds before now and exp to ~4 minutes after iat', async () => {
85
+ rs.jws = { JWS: { sign: jest.fn().mockReturnValue('signed-jwt') } };
86
+ axios.post.mockResolvedValue({ data: { jwt: 'token' } });
87
+
88
+ const before = Math.floor(Date.now() / 1000);
89
+ await getAccessTokenViaPKI('user@example.com', 'client-id', 'private-key');
90
+ const after = Math.floor(Date.now() / 1000);
91
+
92
+ const payload = JSON.parse(rs.jws.JWS.sign.mock.calls[0][2]);
93
+ // iat should be roughly now - 60
94
+ expect(payload.iat).toBeGreaterThanOrEqual(before - 61);
95
+ expect(payload.iat).toBeLessThanOrEqual(after - 59);
96
+ // exp should be iat + 5 minutes (300s)
97
+ expect(payload.exp - payload.iat).toBe(300);
98
+ });
99
+ });
package/package.json CHANGED
@@ -1,16 +1,18 @@
1
1
  {
2
2
  "name": "@nooks-ai/nooks-zoominfo-api-auth-client",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "Zoominfo API Authentication Client (Nooks fork)",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "test": "echo \"Error: no test specified\" && exit 1"
7
+ "test": "jest"
8
8
  },
9
9
  "author": "Nooks",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
- "axios": "^0.30.0",
13
- "jsrsasign": "^10.2.0"
12
+ "axios": "^1.12.2",
13
+ "jsrsasign": "^11.1.1"
14
14
  },
15
- "devDependencies": {}
15
+ "devDependencies": {
16
+ "jest": "^30.3.0"
17
+ }
16
18
  }