@docupace/pipeline 1.0.77 → 1.0.78

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.
Files changed (69) hide show
  1. package/.prettierrc.cjs +12 -12
  2. package/README.md +135 -135
  3. package/bin/azuread_update_callbacks_for_app.sh +58 -58
  4. package/bin/next-changeset-validate.sh +8 -8
  5. package/bitbucket-pipelines.yml +59 -59
  6. package/eslint.config.js +49 -49
  7. package/jest.config.js +15 -15
  8. package/next/changeset.sh +75 -75
  9. package/next/copy.sh +34 -34
  10. package/next/deploy.sh +40 -40
  11. package/next/execute.sh +123 -123
  12. package/next/sonar.sh +23 -23
  13. package/package.json +1 -1
  14. package/src/auth0/alias.js +79 -79
  15. package/src/auth0/alias.test.js +172 -172
  16. package/src/auth0/cli.js +82 -82
  17. package/src/auth0/configure.js +902 -902
  18. package/src/auth0/configure.test.js +167 -167
  19. package/src/auth0/export.js +48 -48
  20. package/src/auth0/export.test.js +103 -103
  21. package/src/auth0/metadata.js +141 -141
  22. package/src/auth0/metadata.test.js +186 -186
  23. package/src/auth0/vault.js +60 -60
  24. package/src/auth0/vault.test.js +134 -134
  25. package/src/changeset/changelog-wiki.js +328 -328
  26. package/src/changeset/changeset-config.js +34 -34
  27. package/src/changeset/cli.js +237 -237
  28. package/src/changeset/create.js +215 -215
  29. package/src/changeset/package-util.js +87 -87
  30. package/src/changeset/util.js +43 -43
  31. package/src/changeset/validate.js +91 -91
  32. package/src/changeset/version.js +102 -102
  33. package/src/jenkins/setParams.groovy +58 -58
  34. package/src/lib/merge-driver.js +204 -204
  35. package/src/merge/cli-merge-all.js +507 -507
  36. package/src/merge/cli-merge.js +492 -492
  37. package/src/merge/cli-resolve.js +399 -399
  38. package/src/merge/cli.js +38 -38
  39. package/src/merge/merge-changelog.js +87 -87
  40. package/src/merge/merge-package.js +106 -106
  41. package/src/merge/merge-types.js +82 -82
  42. package/src/merge/pr.js +231 -231
  43. package/src/micro/deploy-microservice.js +153 -0
  44. package/src/micro/{ms-publish.js → publish-ms.js} +8 -6
  45. package/src/next/alias.js +53 -53
  46. package/src/next/apache.js +81 -81
  47. package/src/next/cli.js +10 -1
  48. package/src/next/config.js +137 -137
  49. package/src/next/connect.js +226 -226
  50. package/src/next/copy.js +61 -61
  51. package/src/next/deploy.js +633 -633
  52. package/src/next/git-to-semver.js +79 -79
  53. package/src/next/haproxy.js +76 -76
  54. package/src/next/jenkins.js +123 -123
  55. package/src/next/jira.js +84 -84
  56. package/src/next/logger.js +17 -17
  57. package/src/next/pipline.js +114 -114
  58. package/src/next/publish.js +71 -71
  59. package/src/next/pull.js +7 -7
  60. package/src/next/sonar.js +23 -23
  61. package/src/next/test.js +5 -5
  62. package/src/next/util.js +95 -93
  63. package/src/next/vault.js +45 -45
  64. package/terraform/apply.sh +37 -37
  65. package/terraform/init.sh +72 -72
  66. package/terraform/plan.sh +76 -76
  67. package/terraform/validate.sh +17 -17
  68. package/src/micro/cli.js +0 -71
  69. package/src/micro/ms-deploy.js +0 -271
@@ -1,167 +1,167 @@
1
- // @jest-environment node
2
- import { jest } from '@jest/globals';
3
-
4
- // ─── Mock All Required Modules ───────────────────────────────────────────────
5
-
6
- jest.unstable_mockModule('fs-extra', () => ({
7
- default: {
8
- promises: {
9
- mkdir: jest.fn(),
10
- },
11
- writeFile: jest.fn(),
12
- ensureDir: jest.fn(),
13
- },
14
- writeFile: jest.fn(),
15
- ensureDir: jest.fn(),
16
- }));
17
-
18
- jest.unstable_mockModule('axios', () => ({
19
- default: {
20
- post: jest.fn(),
21
- get: jest.fn(),
22
- },
23
- }));
24
-
25
- jest.unstable_mockModule('crypto', () => ({
26
- randomBytes: () => ({
27
- toString: () => 'mockBase64==',
28
- }),
29
- }));
30
-
31
- jest.unstable_mockModule('../next/deploy.js', () => ({
32
- cloneRepository: jest.fn(),
33
- cloneEnvRepository: jest.fn(),
34
- pushDeployConfig: jest.fn(),
35
- readDeployConfig: jest.fn(),
36
- }));
37
-
38
- jest.unstable_mockModule('./vault.js', () => ({
39
- getVaultSecrets: jest.fn(),
40
- updateVaultSecrets: jest.fn(),
41
- }));
42
-
43
- jest.unstable_mockModule('../next/config.js', () => ({
44
- coreSiteEnvMap: { dev: 'dev-env' },
45
- environmentConfig: {
46
- dev: {
47
- newUrl: (site) => `dev.${site}.com`,
48
- oldUrl: (site) => `legacy.${site}.com`,
49
- ccUrl: (site) => `cc.${site}.com`,
50
- docupaceHost: () => 'docupace.com',
51
- },
52
- },
53
- getVaultSecretsConfigs: jest.fn(),
54
- }));
55
-
56
- // ─── Global References ───────────────────────────────────────────────────────
57
-
58
- let fs, axios, deploy, vault, config;
59
- let getAuth0AuthToken, cleanAndWritePropertiesFile, updateCoreSiteConfig;
60
-
61
- const originalProcessExit = process.exit;
62
-
63
- beforeAll(async () => {
64
- // Mock process.exit to prevent killing the test runner
65
- process.exit = jest.fn();
66
-
67
- // Suppress noisy error output
68
- jest.spyOn(console, 'error').mockImplementation(() => {});
69
- jest.spyOn(console, 'log').mockImplementation(() => {});
70
-
71
- // Import after mocks
72
- ({ default: fs } = await import('fs-extra'));
73
- ({ default: axios } = await import('axios'));
74
- deploy = await import('../next/deploy.js');
75
- vault = await import('./vault.js');
76
- config = await import('../next/config.js');
77
-
78
- const mod = await import('./configure.js');
79
- ({ getAuth0AuthToken, cleanAndWritePropertiesFile, updateCoreSiteConfig } =
80
- mod);
81
- });
82
-
83
- afterAll(() => {
84
- // Restore
85
- process.exit = originalProcessExit;
86
- console.error.mockRestore();
87
- console.log.mockRestore();
88
- });
89
-
90
- // ─── Tests ───────────────────────────────────────────────────────────────────
91
-
92
- describe('Deployment Automation Module (ESM)', () => {
93
- describe('getAuth0AuthToken', () => {
94
- it('should return access token on success', async () => {
95
- axios.post.mockResolvedValue({ data: { access_token: 'mock-token' } });
96
- const token = await getAuth0AuthToken('auth.domain', 'cid', 'secret');
97
- expect(token).toBe('mock-token');
98
- });
99
-
100
- it('should return undefined on failure', async () => {
101
- axios.post.mockRejectedValue({ message: 'fail' });
102
- const token = await getAuth0AuthToken('auth.domain', 'cid', 'secret');
103
- expect(token).toBeUndefined();
104
- expect(console.error).toHaveBeenCalledWith(
105
- 'Error fetching Auth0 token:',
106
- 'fail',
107
- );
108
- });
109
- });
110
-
111
- describe('cleanAndWritePropertiesFile', () => {
112
- it('writes cleaned file content', async () => {
113
- fs.writeFile.mockResolvedValue();
114
- await cleanAndWritePropertiesFile('/tmp/test.properties', 'a=1\n\nb=2\n');
115
- expect(fs.writeFile).toHaveBeenCalledWith(
116
- '/tmp/test.properties',
117
- 'a=1\nb=2',
118
- 'utf8',
119
- );
120
- });
121
-
122
- it('calls process.exit on write error', async () => {
123
- fs.writeFile.mockRejectedValue(new Error('disk full'));
124
- await cleanAndWritePropertiesFile('/bad/path', 'x=y');
125
- expect(process.exit).toHaveBeenCalledWith(1);
126
- });
127
- });
128
-
129
- describe('updateCoreSiteConfig', () => {
130
- it('updates config when S3 is enabled', async () => {
131
- config.getVaultSecretsConfigs.mockReturnValue({
132
- awsSecretsPath: 'aws/path',
133
- });
134
-
135
- deploy.cloneRepository.mockResolvedValue('/repo/path');
136
-
137
- vault.getVaultSecrets.mockResolvedValue({
138
- AWS_ACCESS_KEY_ID: 'abc',
139
- AWS_SECRET_ACCESS_KEY: 'def',
140
- AWS_REGION: 'us-west-2',
141
- });
142
-
143
- fs.ensureDir.mockResolvedValue();
144
- fs.writeFile.mockResolvedValue();
145
- deploy.pushDeployConfig.mockResolvedValue();
146
-
147
- await updateCoreSiteConfig('mysite', 'dev', true, false);
148
-
149
- expect(fs.ensureDir).toHaveBeenCalledWith('/repo/path/MYSITE');
150
- expect(fs.writeFile).toHaveBeenCalled();
151
- expect(deploy.pushDeployConfig).toHaveBeenCalled();
152
- });
153
-
154
- it('calls process.exit if cloneRepository fails', async () => {
155
- config.getVaultSecretsConfigs.mockReturnValue({
156
- awsSecretsPath: 'aws/path',
157
- });
158
-
159
- deploy.cloneRepository.mockRejectedValue(new Error('bad clone'));
160
-
161
- await updateCoreSiteConfig('mysite', 'dev', true, false);
162
-
163
- expect(process.exit).toHaveBeenCalledWith(1);
164
- expect(console.error).toHaveBeenCalledWith('Error:', 'bad clone');
165
- });
166
- });
167
- });
1
+ // @jest-environment node
2
+ import { jest } from '@jest/globals';
3
+
4
+ // ─── Mock All Required Modules ───────────────────────────────────────────────
5
+
6
+ jest.unstable_mockModule('fs-extra', () => ({
7
+ default: {
8
+ promises: {
9
+ mkdir: jest.fn(),
10
+ },
11
+ writeFile: jest.fn(),
12
+ ensureDir: jest.fn(),
13
+ },
14
+ writeFile: jest.fn(),
15
+ ensureDir: jest.fn(),
16
+ }));
17
+
18
+ jest.unstable_mockModule('axios', () => ({
19
+ default: {
20
+ post: jest.fn(),
21
+ get: jest.fn(),
22
+ },
23
+ }));
24
+
25
+ jest.unstable_mockModule('crypto', () => ({
26
+ randomBytes: () => ({
27
+ toString: () => 'mockBase64==',
28
+ }),
29
+ }));
30
+
31
+ jest.unstable_mockModule('../next/deploy.js', () => ({
32
+ cloneRepository: jest.fn(),
33
+ cloneEnvRepository: jest.fn(),
34
+ pushDeployConfig: jest.fn(),
35
+ readDeployConfig: jest.fn(),
36
+ }));
37
+
38
+ jest.unstable_mockModule('./vault.js', () => ({
39
+ getVaultSecrets: jest.fn(),
40
+ updateVaultSecrets: jest.fn(),
41
+ }));
42
+
43
+ jest.unstable_mockModule('../next/config.js', () => ({
44
+ coreSiteEnvMap: { dev: 'dev-env' },
45
+ environmentConfig: {
46
+ dev: {
47
+ newUrl: (site) => `dev.${site}.com`,
48
+ oldUrl: (site) => `legacy.${site}.com`,
49
+ ccUrl: (site) => `cc.${site}.com`,
50
+ docupaceHost: () => 'docupace.com',
51
+ },
52
+ },
53
+ getVaultSecretsConfigs: jest.fn(),
54
+ }));
55
+
56
+ // ─── Global References ───────────────────────────────────────────────────────
57
+
58
+ let fs, axios, deploy, vault, config;
59
+ let getAuth0AuthToken, cleanAndWritePropertiesFile, updateCoreSiteConfig;
60
+
61
+ const originalProcessExit = process.exit;
62
+
63
+ beforeAll(async () => {
64
+ // Mock process.exit to prevent killing the test runner
65
+ process.exit = jest.fn();
66
+
67
+ // Suppress noisy error output
68
+ jest.spyOn(console, 'error').mockImplementation(() => {});
69
+ jest.spyOn(console, 'log').mockImplementation(() => {});
70
+
71
+ // Import after mocks
72
+ ({ default: fs } = await import('fs-extra'));
73
+ ({ default: axios } = await import('axios'));
74
+ deploy = await import('../next/deploy.js');
75
+ vault = await import('./vault.js');
76
+ config = await import('../next/config.js');
77
+
78
+ const mod = await import('./configure.js');
79
+ ({ getAuth0AuthToken, cleanAndWritePropertiesFile, updateCoreSiteConfig } =
80
+ mod);
81
+ });
82
+
83
+ afterAll(() => {
84
+ // Restore
85
+ process.exit = originalProcessExit;
86
+ console.error.mockRestore();
87
+ console.log.mockRestore();
88
+ });
89
+
90
+ // ─── Tests ───────────────────────────────────────────────────────────────────
91
+
92
+ describe('Deployment Automation Module (ESM)', () => {
93
+ describe('getAuth0AuthToken', () => {
94
+ it('should return access token on success', async () => {
95
+ axios.post.mockResolvedValue({ data: { access_token: 'mock-token' } });
96
+ const token = await getAuth0AuthToken('auth.domain', 'cid', 'secret');
97
+ expect(token).toBe('mock-token');
98
+ });
99
+
100
+ it('should return undefined on failure', async () => {
101
+ axios.post.mockRejectedValue({ message: 'fail' });
102
+ const token = await getAuth0AuthToken('auth.domain', 'cid', 'secret');
103
+ expect(token).toBeUndefined();
104
+ expect(console.error).toHaveBeenCalledWith(
105
+ 'Error fetching Auth0 token:',
106
+ 'fail',
107
+ );
108
+ });
109
+ });
110
+
111
+ describe('cleanAndWritePropertiesFile', () => {
112
+ it('writes cleaned file content', async () => {
113
+ fs.writeFile.mockResolvedValue();
114
+ await cleanAndWritePropertiesFile('/tmp/test.properties', 'a=1\n\nb=2\n');
115
+ expect(fs.writeFile).toHaveBeenCalledWith(
116
+ '/tmp/test.properties',
117
+ 'a=1\nb=2',
118
+ 'utf8',
119
+ );
120
+ });
121
+
122
+ it('calls process.exit on write error', async () => {
123
+ fs.writeFile.mockRejectedValue(new Error('disk full'));
124
+ await cleanAndWritePropertiesFile('/bad/path', 'x=y');
125
+ expect(process.exit).toHaveBeenCalledWith(1);
126
+ });
127
+ });
128
+
129
+ describe('updateCoreSiteConfig', () => {
130
+ it('updates config when S3 is enabled', async () => {
131
+ config.getVaultSecretsConfigs.mockReturnValue({
132
+ awsSecretsPath: 'aws/path',
133
+ });
134
+
135
+ deploy.cloneRepository.mockResolvedValue('/repo/path');
136
+
137
+ vault.getVaultSecrets.mockResolvedValue({
138
+ AWS_ACCESS_KEY_ID: 'abc',
139
+ AWS_SECRET_ACCESS_KEY: 'def',
140
+ AWS_REGION: 'us-west-2',
141
+ });
142
+
143
+ fs.ensureDir.mockResolvedValue();
144
+ fs.writeFile.mockResolvedValue();
145
+ deploy.pushDeployConfig.mockResolvedValue();
146
+
147
+ await updateCoreSiteConfig('mysite', 'dev', true, false);
148
+
149
+ expect(fs.ensureDir).toHaveBeenCalledWith('/repo/path/MYSITE');
150
+ expect(fs.writeFile).toHaveBeenCalled();
151
+ expect(deploy.pushDeployConfig).toHaveBeenCalled();
152
+ });
153
+
154
+ it('calls process.exit if cloneRepository fails', async () => {
155
+ config.getVaultSecretsConfigs.mockReturnValue({
156
+ awsSecretsPath: 'aws/path',
157
+ });
158
+
159
+ deploy.cloneRepository.mockRejectedValue(new Error('bad clone'));
160
+
161
+ await updateCoreSiteConfig('mysite', 'dev', true, false);
162
+
163
+ expect(process.exit).toHaveBeenCalledWith(1);
164
+ expect(console.error).toHaveBeenCalledWith('Error:', 'bad clone');
165
+ });
166
+ });
167
+ });
@@ -1,48 +1,48 @@
1
- import { getVaultSecrets } from './vault.js';
2
- import { getVaultSecretsConfigs } from '../next/config.js';
3
- import { dump } from 'auth0-deploy-cli';
4
-
5
- export async function exportConf(site, env, auth0Tenant) {
6
- try {
7
- console.log(
8
- `Exporting Auth0 configuration for site: ${site} and env: ${env}`,
9
- );
10
-
11
- const siteCommonSecretsPath =
12
- getVaultSecretsConfigs(site).siteCommonSecretsPath;
13
- console.log(`siteCommonSecretsPath => ${siteCommonSecretsPath}`);
14
- const siteCommonSecrets = await getVaultSecrets(siteCommonSecretsPath);
15
-
16
- let auth0Domain;
17
- if (auth0Tenant === '') {
18
- auth0Domain = `docupace-${env}-${site}.us.auth0.com`;
19
- } else {
20
- auth0Domain = `${auth0Tenant}.us.auth0.com`;
21
- }
22
- const auth0ClientId = siteCommonSecrets.AUTH0_CLIENT_ID;
23
- const auth0ClientSecret = siteCommonSecrets.AUTH0_CLIENT_SECRET;
24
-
25
- const config = {
26
- config: {
27
- AUTH0_DOMAIN: auth0Domain,
28
- AUTH0_CLIENT_ID: auth0ClientId,
29
- AUTH0_CLIENT_SECRET: auth0ClientSecret,
30
- },
31
- format: 'directory',
32
- output_folder: `./auth0-${site}-export`,
33
- export_ids: false,
34
- env: false,
35
- debug: true,
36
- };
37
-
38
- console.log(`Starting Auth0 ${site} configuration export...`);
39
- await dump(config);
40
- console.log(`Auth0 ${site} configuration export completed successfully!`);
41
- } catch (error) {
42
- console.error(
43
- `Error during Auth0 ${site} configuration export:`,
44
- error.message,
45
- );
46
- process.exit(1);
47
- }
48
- }
1
+ import { getVaultSecrets } from './vault.js';
2
+ import { getVaultSecretsConfigs } from '../next/config.js';
3
+ import { dump } from 'auth0-deploy-cli';
4
+
5
+ export async function exportConf(site, env, auth0Tenant) {
6
+ try {
7
+ console.log(
8
+ `Exporting Auth0 configuration for site: ${site} and env: ${env}`,
9
+ );
10
+
11
+ const siteCommonSecretsPath =
12
+ getVaultSecretsConfigs(site).siteCommonSecretsPath;
13
+ console.log(`siteCommonSecretsPath => ${siteCommonSecretsPath}`);
14
+ const siteCommonSecrets = await getVaultSecrets(siteCommonSecretsPath);
15
+
16
+ let auth0Domain;
17
+ if (auth0Tenant === '') {
18
+ auth0Domain = `docupace-${env}-${site}.us.auth0.com`;
19
+ } else {
20
+ auth0Domain = `${auth0Tenant}.us.auth0.com`;
21
+ }
22
+ const auth0ClientId = siteCommonSecrets.AUTH0_CLIENT_ID;
23
+ const auth0ClientSecret = siteCommonSecrets.AUTH0_CLIENT_SECRET;
24
+
25
+ const config = {
26
+ config: {
27
+ AUTH0_DOMAIN: auth0Domain,
28
+ AUTH0_CLIENT_ID: auth0ClientId,
29
+ AUTH0_CLIENT_SECRET: auth0ClientSecret,
30
+ },
31
+ format: 'directory',
32
+ output_folder: `./auth0-${site}-export`,
33
+ export_ids: false,
34
+ env: false,
35
+ debug: true,
36
+ };
37
+
38
+ console.log(`Starting Auth0 ${site} configuration export...`);
39
+ await dump(config);
40
+ console.log(`Auth0 ${site} configuration export completed successfully!`);
41
+ } catch (error) {
42
+ console.error(
43
+ `Error during Auth0 ${site} configuration export:`,
44
+ error.message,
45
+ );
46
+ process.exit(1);
47
+ }
48
+ }
@@ -1,103 +1,103 @@
1
- // exportConf.test.js
2
- import { jest } from '@jest/globals';
3
-
4
- // Mock modules using ESM-safe methods
5
- jest.unstable_mockModule('./vault.js', () => ({
6
- getVaultSecrets: jest.fn(),
7
- }));
8
-
9
- jest.unstable_mockModule('../next/config.js', () => ({
10
- getVaultSecretsConfigs: jest.fn(),
11
- }));
12
-
13
- jest.unstable_mockModule('auth0-deploy-cli', () => ({
14
- dump: jest.fn(),
15
- }));
16
-
17
- // Import the actual function and mocked dependencies after mocks are in place
18
- const { exportConf } = await import('./export.js');
19
- const { getVaultSecrets } = await import('./vault.js');
20
- const { getVaultSecretsConfigs } = await import('../next/config.js');
21
- const { dump } = await import('auth0-deploy-cli');
22
-
23
- describe('exportConf', () => {
24
- const site = 'example';
25
- const env = 'dev';
26
- const auth0Tenant = '';
27
-
28
- const mockSecrets = {
29
- AUTH0_CLIENT_ID: 'test-client-id',
30
- AUTH0_CLIENT_SECRET: 'test-client-secret',
31
- };
32
-
33
- const mockPath = 'vault/path/to/secrets';
34
-
35
- beforeEach(() => {
36
- jest.clearAllMocks();
37
-
38
- getVaultSecretsConfigs.mockReturnValue({
39
- siteCommonSecretsPath: mockPath,
40
- });
41
-
42
- getVaultSecrets.mockResolvedValue(mockSecrets);
43
-
44
- dump.mockResolvedValue(undefined);
45
- });
46
-
47
- it('should export Auth0 configuration with default tenant format', async () => {
48
- const logSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
49
- await exportConf(site, env, auth0Tenant);
50
-
51
- expect(getVaultSecretsConfigs).toHaveBeenCalledWith(site);
52
- expect(getVaultSecrets).toHaveBeenCalledWith(mockPath);
53
- expect(dump).toHaveBeenCalledWith(
54
- expect.objectContaining({
55
- config: {
56
- AUTH0_DOMAIN: 'docupace-dev-example.us.auth0.com',
57
- AUTH0_CLIENT_ID: 'test-client-id',
58
- AUTH0_CLIENT_SECRET: 'test-client-secret',
59
- },
60
- }),
61
- );
62
-
63
- logSpy.mockRestore();
64
- });
65
-
66
- it('should export Auth0 configuration with custom tenant', async () => {
67
- const customTenant = 'custom-tenant';
68
- await exportConf(site, env, customTenant);
69
-
70
- expect(dump).toHaveBeenCalledWith(
71
- expect.objectContaining({
72
- config: {
73
- AUTH0_DOMAIN: 'custom-tenant.us.auth0.com',
74
- AUTH0_CLIENT_ID: 'test-client-id',
75
- AUTH0_CLIENT_SECRET: 'test-client-secret',
76
- },
77
- }),
78
- );
79
- });
80
-
81
- it('should log error and exit process on failure', async () => {
82
- getVaultSecrets.mockRejectedValue(new Error('Vault error'));
83
-
84
- const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
85
- const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {
86
- throw new Error('process.exit');
87
- });
88
-
89
- await expect(exportConf(site, env, auth0Tenant)).rejects.toThrow(
90
- 'process.exit',
91
- );
92
-
93
- expect(errorSpy).toHaveBeenCalledWith(
94
- expect.stringContaining(
95
- 'Error during Auth0 example configuration export:',
96
- ),
97
- 'Vault error',
98
- );
99
-
100
- errorSpy.mockRestore();
101
- exitSpy.mockRestore();
102
- });
103
- });
1
+ // exportConf.test.js
2
+ import { jest } from '@jest/globals';
3
+
4
+ // Mock modules using ESM-safe methods
5
+ jest.unstable_mockModule('./vault.js', () => ({
6
+ getVaultSecrets: jest.fn(),
7
+ }));
8
+
9
+ jest.unstable_mockModule('../next/config.js', () => ({
10
+ getVaultSecretsConfigs: jest.fn(),
11
+ }));
12
+
13
+ jest.unstable_mockModule('auth0-deploy-cli', () => ({
14
+ dump: jest.fn(),
15
+ }));
16
+
17
+ // Import the actual function and mocked dependencies after mocks are in place
18
+ const { exportConf } = await import('./export.js');
19
+ const { getVaultSecrets } = await import('./vault.js');
20
+ const { getVaultSecretsConfigs } = await import('../next/config.js');
21
+ const { dump } = await import('auth0-deploy-cli');
22
+
23
+ describe('exportConf', () => {
24
+ const site = 'example';
25
+ const env = 'dev';
26
+ const auth0Tenant = '';
27
+
28
+ const mockSecrets = {
29
+ AUTH0_CLIENT_ID: 'test-client-id',
30
+ AUTH0_CLIENT_SECRET: 'test-client-secret',
31
+ };
32
+
33
+ const mockPath = 'vault/path/to/secrets';
34
+
35
+ beforeEach(() => {
36
+ jest.clearAllMocks();
37
+
38
+ getVaultSecretsConfigs.mockReturnValue({
39
+ siteCommonSecretsPath: mockPath,
40
+ });
41
+
42
+ getVaultSecrets.mockResolvedValue(mockSecrets);
43
+
44
+ dump.mockResolvedValue(undefined);
45
+ });
46
+
47
+ it('should export Auth0 configuration with default tenant format', async () => {
48
+ const logSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
49
+ await exportConf(site, env, auth0Tenant);
50
+
51
+ expect(getVaultSecretsConfigs).toHaveBeenCalledWith(site);
52
+ expect(getVaultSecrets).toHaveBeenCalledWith(mockPath);
53
+ expect(dump).toHaveBeenCalledWith(
54
+ expect.objectContaining({
55
+ config: {
56
+ AUTH0_DOMAIN: 'docupace-dev-example.us.auth0.com',
57
+ AUTH0_CLIENT_ID: 'test-client-id',
58
+ AUTH0_CLIENT_SECRET: 'test-client-secret',
59
+ },
60
+ }),
61
+ );
62
+
63
+ logSpy.mockRestore();
64
+ });
65
+
66
+ it('should export Auth0 configuration with custom tenant', async () => {
67
+ const customTenant = 'custom-tenant';
68
+ await exportConf(site, env, customTenant);
69
+
70
+ expect(dump).toHaveBeenCalledWith(
71
+ expect.objectContaining({
72
+ config: {
73
+ AUTH0_DOMAIN: 'custom-tenant.us.auth0.com',
74
+ AUTH0_CLIENT_ID: 'test-client-id',
75
+ AUTH0_CLIENT_SECRET: 'test-client-secret',
76
+ },
77
+ }),
78
+ );
79
+ });
80
+
81
+ it('should log error and exit process on failure', async () => {
82
+ getVaultSecrets.mockRejectedValue(new Error('Vault error'));
83
+
84
+ const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
85
+ const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {
86
+ throw new Error('process.exit');
87
+ });
88
+
89
+ await expect(exportConf(site, env, auth0Tenant)).rejects.toThrow(
90
+ 'process.exit',
91
+ );
92
+
93
+ expect(errorSpy).toHaveBeenCalledWith(
94
+ expect.stringContaining(
95
+ 'Error during Auth0 example configuration export:',
96
+ ),
97
+ 'Vault error',
98
+ );
99
+
100
+ errorSpy.mockRestore();
101
+ exitSpy.mockRestore();
102
+ });
103
+ });