@hubspot/cli 7.10.0-beta.1 → 7.10.0-experimental.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.
- package/bin/cli.js +5 -4
- package/commands/__tests__/getStarted.test.js +10 -0
- package/commands/__tests__/project.test.js +3 -0
- package/commands/account/__tests__/rename.test.js +10 -3
- package/commands/account/auth.js +10 -14
- package/commands/account/clean.js +11 -19
- package/commands/account/createOverride.js +15 -11
- package/commands/account/info.js +8 -5
- package/commands/account/list.js +15 -19
- package/commands/account/remove.js +23 -22
- package/commands/account/removeOverride.js +6 -6
- package/commands/account/rename.js +2 -2
- package/commands/account/use.js +19 -8
- package/commands/app/__tests__/migrate.test.js +8 -4
- package/commands/app/migrate.js +2 -2
- package/commands/auth.js +18 -14
- package/commands/config/migrate.js +5 -5
- package/commands/customObject/createSchema.js +2 -3
- package/commands/customObject/updateSchema.js +2 -3
- package/commands/getStarted.js +2 -3
- package/commands/hubdb/__tests__/list.test.js +1 -0
- package/commands/hubdb/list.js +2 -2
- package/commands/init.js +36 -32
- package/commands/project/__tests__/deploy.test.js +10 -5
- package/commands/project/__tests__/devUnifiedFlow.test.js +6 -4
- package/commands/project/__tests__/lint.test.js +709 -0
- package/commands/project/__tests__/logs.test.js +4 -0
- package/commands/project/__tests__/validate.test.js +2 -2
- package/commands/project/cloneApp.js +2 -2
- package/commands/project/deploy.js +2 -2
- package/commands/project/dev/deprecatedFlow.js +4 -5
- package/commands/project/dev/index.js +6 -3
- package/commands/project/dev/unifiedFlow.js +4 -5
- package/commands/project/lint.d.ts +6 -0
- package/commands/project/lint.js +178 -0
- package/commands/project/logs.js +2 -3
- package/commands/project/profile/add.js +6 -7
- package/commands/project/profile/delete.js +2 -2
- package/commands/project/upload.js +2 -2
- package/commands/project/validate.js +2 -2
- package/commands/project.js +2 -0
- package/commands/sandbox/__tests__/create.test.js +14 -5
- package/commands/sandbox/create.js +4 -5
- package/commands/sandbox/delete.js +23 -20
- package/commands/testAccount/__tests__/create.test.js +5 -5
- package/commands/testAccount/create.js +2 -2
- package/commands/testAccount/delete.js +9 -8
- package/lang/en.d.ts +40 -6
- package/lang/en.js +54 -14
- package/lib/__tests__/buildAccount.test.js +22 -30
- package/lib/__tests__/commonOpts.test.js +9 -13
- package/lib/__tests__/developerTestAccounts.test.js +29 -17
- package/lib/__tests__/importData.test.js +20 -10
- package/lib/__tests__/oauth.test.js +19 -8
- package/lib/__tests__/sandboxSync.test.js +33 -11
- package/lib/__tests__/sandboxes.test.js +30 -19
- package/lib/__tests__/usageTracking.test.js +10 -10
- package/lib/__tests__/validation.test.js +32 -32
- package/lib/accountTypes.d.ts +9 -9
- package/lib/accountTypes.js +2 -4
- package/lib/app/__tests__/migrate.test.js +15 -0
- package/lib/app/__tests__/migrate_legacy.test.js +9 -0
- package/lib/app/migrate_legacy.d.ts +2 -2
- package/lib/buildAccount.d.ts +4 -4
- package/lib/buildAccount.js +7 -14
- package/lib/commonOpts.js +3 -3
- package/lib/configMigrate.d.ts +2 -2
- package/lib/configMigrate.js +42 -18
- package/lib/configOptions.js +3 -2
- package/lib/developerTestAccounts.d.ts +3 -3
- package/lib/developerTestAccounts.js +4 -7
- package/lib/doctor/DiagnosticInfoBuilder.d.ts +1 -1
- package/lib/doctor/DiagnosticInfoBuilder.js +9 -6
- package/lib/doctor/Doctor.js +4 -3
- package/lib/doctor/__tests__/Diagnosis.test.js +4 -3
- package/lib/doctor/__tests__/DiagnosticInfoBuilder.test.js +17 -9
- package/lib/doctor/__tests__/Doctor.test.js +14 -0
- package/lib/importData.js +8 -7
- package/lib/links.js +5 -5
- package/lib/middleware/{__test__ → __tests__}/commandTargetingUtils.test.js +3 -3
- package/lib/middleware/{__test__ → __tests__}/configMiddleware.test.js +23 -22
- package/lib/middleware/{__test__ → __tests__}/gitMiddleware.test.js +9 -7
- package/lib/middleware/autoUpdateMiddleware.js +12 -4
- package/lib/middleware/commandTargetingUtils.js +3 -2
- package/lib/middleware/configMiddleware.d.ts +6 -1
- package/lib/middleware/configMiddleware.js +36 -15
- package/lib/middleware/gitMiddleware.js +8 -4
- package/lib/oauth.d.ts +2 -2
- package/lib/oauth.js +8 -10
- package/lib/projects/__tests__/AppDevModeInterface.test.js +17 -6
- package/lib/projects/__tests__/DevServerManager.test.js +1 -0
- package/lib/projects/__tests__/LocalDevProcess.test.js +1 -0
- package/lib/projects/__tests__/components.test.js +1 -1
- package/lib/projects/__tests__/deploy.test.js +1 -0
- package/lib/projects/__tests__/uieLinting.test.js +640 -0
- package/lib/projects/components.js +1 -1
- package/lib/projects/create/__tests__/v2.test.js +11 -0
- package/lib/projects/localDev/AppDevModeInterface.js +2 -2
- package/lib/projects/localDev/DevServerManager_DEPRECATED.js +2 -2
- package/lib/projects/localDev/DevSessionManager.d.ts +17 -0
- package/lib/projects/localDev/DevSessionManager.js +56 -0
- package/lib/projects/localDev/LocalDevLogger.d.ts +3 -0
- package/lib/projects/localDev/LocalDevLogger.js +13 -4
- package/lib/projects/localDev/LocalDevManager_DEPRECATED.js +3 -3
- package/lib/projects/localDev/LocalDevProcess.d.ts +1 -0
- package/lib/projects/localDev/LocalDevProcess.js +12 -1
- package/lib/projects/localDev/LocalDevState.d.ts +3 -0
- package/lib/projects/localDev/LocalDevState.js +9 -0
- package/lib/projects/localDev/helpers/account.d.ts +10 -10
- package/lib/projects/localDev/helpers/account.js +6 -11
- package/lib/projects/localDev/helpers/devSessionsApi.d.ts +9 -0
- package/lib/projects/localDev/helpers/devSessionsApi.js +19 -0
- package/lib/projects/uieLinting.d.ts +33 -0
- package/lib/projects/uieLinting.js +222 -0
- package/lib/projects/urls.js +5 -6
- package/lib/prompts/__tests__/downloadProjectPrompt.test.js +7 -5
- package/lib/prompts/accountNamePrompt.js +3 -3
- package/lib/prompts/accountsPrompt.d.ts +1 -1
- package/lib/prompts/accountsPrompt.js +6 -7
- package/lib/prompts/confirmImportDataPrompt.js +2 -2
- package/lib/prompts/downloadProjectPrompt.d.ts +1 -0
- package/lib/prompts/downloadProjectPrompt.js +5 -2
- package/lib/prompts/importDataTestAccountSelectPrompt.js +4 -5
- package/lib/prompts/personalAccessKeyPrompt.js +2 -2
- package/lib/prompts/projectDevTargetAccountPrompt.d.ts +3 -3
- package/lib/prompts/projectDevTargetAccountPrompt.js +5 -7
- package/lib/prompts/sandboxesPrompt.js +7 -8
- package/lib/prompts/setAsDefaultAccountPrompt.js +7 -6
- package/lib/sandboxSync.d.ts +2 -2
- package/lib/sandboxSync.js +3 -9
- package/lib/sandboxes.d.ts +4 -4
- package/lib/sandboxes.js +6 -11
- package/lib/serverlessLogs.js +2 -2
- package/lib/theme/__tests__/migrate.test.js +15 -0
- package/lib/ui/index.js +6 -3
- package/lib/usageTracking.js +15 -8
- package/lib/validation.js +13 -11
- package/mcp-server/tools/cms/HsCreateFunctionTool.js +4 -2
- package/mcp-server/tools/cms/HsCreateModuleTool.js +4 -2
- package/mcp-server/tools/cms/HsCreateTemplateTool.js +4 -2
- package/mcp-server/tools/cms/HsFunctionLogsTool.js +4 -2
- package/mcp-server/tools/cms/HsListFunctionsTool.js +3 -1
- package/mcp-server/tools/cms/HsListTool.js +3 -1
- package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.js +1 -0
- package/mcp-server/tools/index.js +4 -0
- package/mcp-server/tools/project/AddFeatureToProjectTool.js +4 -2
- package/mcp-server/tools/project/CreateProjectTool.js +4 -2
- package/mcp-server/tools/project/CreateTestAccountTool.js +42 -19
- package/mcp-server/tools/project/DeployProjectTool.js +3 -1
- package/mcp-server/tools/project/DocFetchTool.js +6 -4
- package/mcp-server/tools/project/DocsSearchTool.d.ts +1 -1
- package/mcp-server/tools/project/DocsSearchTool.js +10 -8
- package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.d.ts +1 -1
- package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +9 -7
- package/mcp-server/tools/project/GetApplicationInfoTool.js +8 -6
- package/mcp-server/tools/project/GetBuildLogsTool.d.ts +26 -0
- package/mcp-server/tools/project/GetBuildLogsTool.js +125 -0
- package/mcp-server/tools/project/GetBuildStatusTool.d.ts +26 -0
- package/mcp-server/tools/project/GetBuildStatusTool.js +166 -0
- package/mcp-server/tools/project/GetConfigValuesTool.d.ts +1 -1
- package/mcp-server/tools/project/GetConfigValuesTool.js +9 -7
- package/mcp-server/tools/project/GuidedWalkthroughTool.d.ts +1 -1
- package/mcp-server/tools/project/GuidedWalkthroughTool.js +5 -3
- package/mcp-server/tools/project/UploadProjectTools.js +3 -1
- package/mcp-server/tools/project/ValidateProjectTool.js +4 -2
- package/mcp-server/tools/project/__tests__/CreateTestAccountTool.test.js +226 -3
- package/mcp-server/tools/project/__tests__/DocFetchTool.test.js +5 -1
- package/mcp-server/tools/project/__tests__/DocsSearchTool.test.js +23 -11
- package/mcp-server/tools/project/__tests__/GetApiUsagePatternsByAppIdTool.test.js +7 -5
- package/mcp-server/tools/project/__tests__/GetApplicationInfoTool.test.js +7 -5
- package/mcp-server/tools/project/__tests__/GetBuildLogsTool.test.d.ts +1 -0
- package/mcp-server/tools/project/__tests__/GetBuildLogsTool.test.js +305 -0
- package/mcp-server/tools/project/__tests__/GetBuildStatusTool.test.d.ts +1 -0
- package/mcp-server/tools/project/__tests__/GetBuildStatusTool.test.js +240 -0
- package/mcp-server/tools/project/__tests__/GetConfigValuesTool.test.js +8 -6
- package/mcp-server/utils/__tests__/content.test.js +21 -20
- package/mcp-server/utils/__tests__/feedbackTracking.test.js +34 -28
- package/mcp-server/utils/config.d.ts +1 -0
- package/mcp-server/utils/config.js +10 -0
- package/mcp-server/utils/content.d.ts +1 -1
- package/mcp-server/utils/content.js +2 -2
- package/mcp-server/utils/feedbackTracking.d.ts +1 -1
- package/mcp-server/utils/feedbackTracking.js +3 -3
- package/mcp-server/utils/toolUsageTracking.js +4 -3
- package/package.json +8 -7
- package/types/LocalDev.d.ts +1 -0
- package/lib/middleware/__test__/notificationsMiddleware.test.js +0 -8
- package/lib/middleware/notificationsMiddleware.d.ts +0 -1
- package/lib/middleware/notificationsMiddleware.js +0 -28
- package/mcp-server/utils/__tests__/cliConfig.test.js +0 -110
- package/mcp-server/utils/cliConfig.d.ts +0 -1
- package/mcp-server/utils/cliConfig.js +0 -12
- /package/{lib/middleware/__test__/commandTargetingUtils.test.d.ts → commands/project/__tests__/lint.test.d.ts} +0 -0
- /package/lib/middleware/{__test__/configMiddleware.test.d.ts → __tests__/commandTargetingUtils.test.d.ts} +0 -0
- /package/lib/middleware/{__test__/gitMiddleware.test.d.ts → __tests__/configMiddleware.test.d.ts} +0 -0
- /package/lib/middleware/{__test__/notificationsMiddleware.test.d.ts → __tests__/gitMiddleware.test.d.ts} +0 -0
- /package/lib/middleware/{__test__ → __tests__}/requestMiddleware.test.d.ts +0 -0
- /package/lib/middleware/{__test__ → __tests__}/requestMiddleware.test.js +0 -0
- /package/lib/middleware/{__test__ → __tests__}/yargsChecksMiddleware.test.d.ts +0 -0
- /package/lib/middleware/{__test__ → __tests__}/yargsChecksMiddleware.test.js +0 -0
- /package/{mcp-server/utils/__tests__/cliConfig.test.d.ts → lib/projects/__tests__/uieLinting.test.d.ts} +0 -0
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { CMS_PUBLISH_MODE, DEFAULT_CMS_PUBLISH_MODE, } from '@hubspot/local-dev-lib/constants/files';
|
|
2
|
-
import {
|
|
2
|
+
import { getConfig, getConfigAccountById } from '@hubspot/local-dev-lib/config';
|
|
3
3
|
import { getCmsPublishMode } from '../commonOpts.js';
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const mockedLoadConfigFromEnvironment = loadConfigFromEnvironment;
|
|
4
|
+
const mockedGetConfigAccountById = getConfigAccountById;
|
|
5
|
+
const mockedGetConfig = getConfig;
|
|
7
6
|
function buildArguments(args) {
|
|
8
7
|
return {
|
|
9
8
|
_: [],
|
|
@@ -42,8 +41,8 @@ describe('lib/commonOpts', () => {
|
|
|
42
41
|
describe('cms publish mode option precedence', () => {
|
|
43
42
|
describe('1. --cmsPublishMode', () => {
|
|
44
43
|
it('should return the cms publish mode specified by the command option if present.', () => {
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
mockedGetConfig.mockReturnValue(configWithDefaultCmsPublishMode);
|
|
45
|
+
mockedGetConfigAccountById.mockReturnValue(devAccountConfig);
|
|
47
46
|
expect(getCmsPublishMode(buildArguments({
|
|
48
47
|
cmsPublishMode: CMS_PUBLISH_MODE.draft,
|
|
49
48
|
}))).toBe(CMS_PUBLISH_MODE.draft);
|
|
@@ -54,9 +53,8 @@ describe('lib/commonOpts', () => {
|
|
|
54
53
|
});
|
|
55
54
|
describe('2. hubspot.config.yml -> config.accounts[x].defaultCmsPublishMode', () => {
|
|
56
55
|
it('should return the defaultCmsPublishMode specified by the account specific config if present.', () => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
mockedLoadConfigFromEnvironment.mockReturnValue(undefined);
|
|
56
|
+
mockedGetConfig.mockReturnValue(configWithDefaultCmsPublishMode);
|
|
57
|
+
mockedGetConfigAccountById.mockReturnValue(devAccountConfig);
|
|
60
58
|
expect(getCmsPublishMode(buildArguments({
|
|
61
59
|
account: accounts.DEV,
|
|
62
60
|
}))).toBe(CMS_PUBLISH_MODE.draft);
|
|
@@ -64,9 +62,8 @@ describe('lib/commonOpts', () => {
|
|
|
64
62
|
});
|
|
65
63
|
describe('3. hubspot.config.yml -> config.defaultCmsPublishMode', () => {
|
|
66
64
|
it('should return the defaultCmsPublishMode specified by the config if present.', () => {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
mockedLoadConfigFromEnvironment.mockReturnValue(undefined);
|
|
65
|
+
mockedGetConfig.mockReturnValue(configWithDefaultCmsPublishMode);
|
|
66
|
+
mockedGetConfigAccountById.mockReturnValue(prodAccountConfig);
|
|
70
67
|
expect(getCmsPublishMode(buildArguments({
|
|
71
68
|
account: accounts.PROD,
|
|
72
69
|
}))).toBe(CMS_PUBLISH_MODE.draft);
|
|
@@ -74,7 +71,6 @@ describe('lib/commonOpts', () => {
|
|
|
74
71
|
});
|
|
75
72
|
describe('4. DEFAULT_CMS_PUBLISH_MODE', () => {
|
|
76
73
|
it('should return the defaultCmsPubishMode specified by the config if present.', () => {
|
|
77
|
-
mockedLoadConfigFromEnvironment.mockReturnValue(undefined);
|
|
78
74
|
expect(getCmsPublishMode(buildArguments({
|
|
79
75
|
account: 'xxxxx',
|
|
80
76
|
}))).toBe(DEFAULT_CMS_PUBLISH_MODE);
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getAllConfigAccounts, getConfigAccountIfExists, getConfigAccountById, } from '@hubspot/local-dev-lib/config';
|
|
2
2
|
import { uiLogger } from '../ui/logger.js';
|
|
3
3
|
import { HUBSPOT_ACCOUNT_TYPES } from '@hubspot/local-dev-lib/constants/config';
|
|
4
4
|
import { fetchDeveloperTestAccounts } from '@hubspot/local-dev-lib/api/developerTestAccounts';
|
|
5
5
|
import { mockHubSpotHttpError } from '../testUtils.js';
|
|
6
6
|
import * as errorHandlers from '../errorHandlers/index.js';
|
|
7
7
|
import { getHasDevTestAccounts, handleDeveloperTestAccountCreateError, validateDevTestAccountUsageLimits, } from '../developerTestAccounts.js';
|
|
8
|
+
import { logError } from '../errorHandlers/index.js';
|
|
8
9
|
vi.mock('@hubspot/local-dev-lib/config');
|
|
9
10
|
vi.mock('../ui/logger.js');
|
|
10
11
|
vi.mock('@hubspot/local-dev-lib/api/developerTestAccounts');
|
|
11
12
|
vi.mock('../errorHandlers');
|
|
12
|
-
const
|
|
13
|
-
const
|
|
13
|
+
const mockedGetConfigAccountIfExists = getConfigAccountIfExists;
|
|
14
|
+
const mockedGetAllConfigAccounts = getAllConfigAccounts;
|
|
15
|
+
const mockedGetConfigAccountById = getConfigAccountById;
|
|
14
16
|
const mockedFetchDeveloperTestAccounts = fetchDeveloperTestAccounts;
|
|
15
17
|
const APP_DEVELOPER_ACCOUNT_1 = {
|
|
16
18
|
name: 'app-developer-1',
|
|
@@ -33,41 +35,43 @@ const accounts = [
|
|
|
33
35
|
parentAccountId: APP_DEVELOPER_ACCOUNT_1.accountId,
|
|
34
36
|
accountType: HUBSPOT_ACCOUNT_TYPES.DEVELOPER_TEST,
|
|
35
37
|
env: 'prod',
|
|
38
|
+
authType: 'personalaccesskey',
|
|
36
39
|
},
|
|
37
40
|
];
|
|
38
41
|
describe('lib/developerTestAccounts', () => {
|
|
39
42
|
describe('getHasDevTestAccounts()', () => {
|
|
40
43
|
it('should return true if there are developer test accounts associated with the account', () => {
|
|
41
|
-
|
|
42
|
-
mockedGetConfigAccounts.mockReturnValueOnce(accounts);
|
|
44
|
+
mockedGetAllConfigAccounts.mockReturnValueOnce(accounts);
|
|
43
45
|
const result = getHasDevTestAccounts(APP_DEVELOPER_ACCOUNT_1);
|
|
44
46
|
expect(result).toBe(true);
|
|
45
47
|
});
|
|
46
48
|
it('should return false if there are no developer test accounts associated with the account', () => {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
+
mockedGetConfigAccountIfExists.mockReturnValueOnce(APP_DEVELOPER_ACCOUNT_2);
|
|
50
|
+
mockedGetAllConfigAccounts.mockReturnValueOnce(accounts);
|
|
49
51
|
const result = getHasDevTestAccounts(APP_DEVELOPER_ACCOUNT_2);
|
|
50
52
|
expect(result).toBe(false);
|
|
51
53
|
});
|
|
52
54
|
it('should return false if there are no accounts configured', () => {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
mockedGetConfigAccountIfExists.mockReturnValueOnce(APP_DEVELOPER_ACCOUNT_1);
|
|
56
|
+
mockedGetAllConfigAccounts.mockReturnValueOnce(undefined);
|
|
55
57
|
const result = getHasDevTestAccounts(APP_DEVELOPER_ACCOUNT_1);
|
|
56
58
|
expect(result).toBe(false);
|
|
57
59
|
});
|
|
58
60
|
});
|
|
59
61
|
describe('validateDevTestAccountUsageLimits()', () => {
|
|
60
62
|
afterEach(() => {
|
|
61
|
-
|
|
63
|
+
mockedGetConfigAccountIfExists.mockRestore();
|
|
62
64
|
mockedFetchDeveloperTestAccounts.mockRestore();
|
|
63
65
|
});
|
|
64
66
|
it('should return null if the account id is not found', async () => {
|
|
65
|
-
|
|
67
|
+
mockedFetchDeveloperTestAccounts.mockResolvedValueOnce({
|
|
68
|
+
data: null,
|
|
69
|
+
});
|
|
66
70
|
const result = await validateDevTestAccountUsageLimits(APP_DEVELOPER_ACCOUNT_1);
|
|
67
71
|
expect(result).toBe(null);
|
|
68
72
|
});
|
|
69
73
|
it('should return null if there is no developer test account data', async () => {
|
|
70
|
-
|
|
74
|
+
mockedGetConfigAccountIfExists.mockReturnValueOnce(APP_DEVELOPER_ACCOUNT_1);
|
|
71
75
|
mockedFetchDeveloperTestAccounts.mockResolvedValueOnce({
|
|
72
76
|
data: null,
|
|
73
77
|
});
|
|
@@ -75,7 +79,7 @@ describe('lib/developerTestAccounts', () => {
|
|
|
75
79
|
expect(result).toBe(null);
|
|
76
80
|
});
|
|
77
81
|
it('should return the test account data if the account has not reached the limit', async () => {
|
|
78
|
-
|
|
82
|
+
mockedGetConfigAccountIfExists.mockReturnValueOnce(APP_DEVELOPER_ACCOUNT_1);
|
|
79
83
|
const testAccountData = {
|
|
80
84
|
maxTestPortals: 10,
|
|
81
85
|
results: [],
|
|
@@ -87,7 +91,7 @@ describe('lib/developerTestAccounts', () => {
|
|
|
87
91
|
expect(result).toEqual(expect.objectContaining(testAccountData));
|
|
88
92
|
});
|
|
89
93
|
it('should throw an error if the account has reached the limit', async () => {
|
|
90
|
-
|
|
94
|
+
mockedGetConfigAccountIfExists.mockReturnValueOnce(APP_DEVELOPER_ACCOUNT_1);
|
|
91
95
|
mockedFetchDeveloperTestAccounts.mockResolvedValueOnce({
|
|
92
96
|
data: {
|
|
93
97
|
maxTestPortals: 0,
|
|
@@ -103,6 +107,14 @@ describe('lib/developerTestAccounts', () => {
|
|
|
103
107
|
beforeEach(() => {
|
|
104
108
|
loggerErrorSpy = vi.spyOn(uiLogger, 'error');
|
|
105
109
|
logErrorSpy = vi.spyOn(errorHandlers, 'logError');
|
|
110
|
+
// Mock account config for uiAccountDescription calls
|
|
111
|
+
mockedGetConfigAccountById.mockReturnValue({
|
|
112
|
+
accountId: APP_DEVELOPER_ACCOUNT_1.accountId,
|
|
113
|
+
name: 'Test Account',
|
|
114
|
+
authType: 'personalaccesskey',
|
|
115
|
+
personalAccessKey: 'test-key',
|
|
116
|
+
env: 'prod',
|
|
117
|
+
});
|
|
106
118
|
});
|
|
107
119
|
afterEach(() => {
|
|
108
120
|
loggerErrorSpy.mockRestore();
|
|
@@ -117,7 +129,7 @@ describe('lib/developerTestAccounts', () => {
|
|
|
117
129
|
},
|
|
118
130
|
});
|
|
119
131
|
expect(() => handleDeveloperTestAccountCreateError(missingScopesError, APP_DEVELOPER_ACCOUNT_1.accountId, 'prod', 10)).toThrow('Missing scopes error');
|
|
120
|
-
expect(
|
|
132
|
+
expect(uiLogger.error).toHaveBeenCalled();
|
|
121
133
|
});
|
|
122
134
|
it('should log and throw an error if the account is missing the required scopes', () => {
|
|
123
135
|
const portalLimitReachedError = mockHubSpotHttpError('Portal limit reached error', {
|
|
@@ -128,7 +140,7 @@ describe('lib/developerTestAccounts', () => {
|
|
|
128
140
|
},
|
|
129
141
|
});
|
|
130
142
|
expect(() => handleDeveloperTestAccountCreateError(portalLimitReachedError, APP_DEVELOPER_ACCOUNT_1.accountId, 'prod', 10)).toThrow('Portal limit reached error');
|
|
131
|
-
expect(
|
|
143
|
+
expect(uiLogger.error).toHaveBeenCalled();
|
|
132
144
|
});
|
|
133
145
|
it('should log a generic error message for an unknown error type', () => {
|
|
134
146
|
const someUnknownError = mockHubSpotHttpError('Some unknown error', {
|
|
@@ -139,7 +151,7 @@ describe('lib/developerTestAccounts', () => {
|
|
|
139
151
|
},
|
|
140
152
|
});
|
|
141
153
|
expect(() => handleDeveloperTestAccountCreateError(someUnknownError, APP_DEVELOPER_ACCOUNT_1.accountId, 'prod', 10)).toThrow('Some unknown error');
|
|
142
|
-
expect(
|
|
154
|
+
expect(logError).toHaveBeenCalled();
|
|
143
155
|
});
|
|
144
156
|
});
|
|
145
157
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { uiLogger } from '../ui/logger.js';
|
|
2
2
|
import { createImport } from '@hubspot/local-dev-lib/api/crm';
|
|
3
|
-
import {
|
|
3
|
+
import { getConfigAccountById, getConfigAccountIfExists, } from '@hubspot/local-dev-lib/config';
|
|
4
4
|
import { handleImportData, handleTargetTestAccountSelectionFlow, } from '../importData.js';
|
|
5
5
|
import { lib } from '../../lang/en.js';
|
|
6
6
|
import { isDeveloperTestAccount, isStandardAccount, isAppDeveloperAccount, } from '../accountTypes.js';
|
|
@@ -13,8 +13,8 @@ vi.mock('../prompts/importDataTestAccountSelectPrompt');
|
|
|
13
13
|
describe('lib/importData', () => {
|
|
14
14
|
const mockUiLogger = vi.mocked(uiLogger);
|
|
15
15
|
const mockCreateImport = vi.mocked(createImport);
|
|
16
|
-
const
|
|
17
|
-
const
|
|
16
|
+
const mockGetConfigAccountById = vi.mocked(getConfigAccountById);
|
|
17
|
+
const mockGetConfigAccountIfExists = vi.mocked(getConfigAccountIfExists);
|
|
18
18
|
const mockIsDeveloperTestAccount = vi.mocked(isDeveloperTestAccount);
|
|
19
19
|
const mockIsStandardAccount = vi.mocked(isStandardAccount);
|
|
20
20
|
const mockIsAppDeveloperAccount = vi.mocked(isAppDeveloperAccount);
|
|
@@ -24,8 +24,8 @@ describe('lib/importData', () => {
|
|
|
24
24
|
mockUiLogger.success.mockReset();
|
|
25
25
|
mockUiLogger.error.mockReset();
|
|
26
26
|
mockCreateImport.mockReset();
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
mockGetConfigAccountById.mockReset();
|
|
28
|
+
mockGetConfigAccountIfExists.mockReset();
|
|
29
29
|
mockIsDeveloperTestAccount.mockReset();
|
|
30
30
|
mockIsStandardAccount.mockReset();
|
|
31
31
|
mockIsAppDeveloperAccount.mockReset();
|
|
@@ -56,32 +56,42 @@ describe('lib/importData', () => {
|
|
|
56
56
|
const userProvidedAccountId = '1234';
|
|
57
57
|
const derivedAccountId = 123456789;
|
|
58
58
|
it('should error if the userProvidedAccountId is not the right account type', async () => {
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
mockGetConfigAccountIfExists.mockReturnValue({
|
|
60
|
+
accountId: 1234,
|
|
61
|
+
});
|
|
61
62
|
mockIsDeveloperTestAccount.mockReturnValue(false);
|
|
62
63
|
await expect(handleTargetTestAccountSelectionFlow(derivedAccountId, userProvidedAccountId)).rejects.toThrow(lib.importData.errors.notDeveloperTestAccount);
|
|
63
64
|
});
|
|
64
65
|
it('should error if the derivedAccountId belongs to the wrong account type', async () => {
|
|
65
|
-
|
|
66
|
+
mockGetConfigAccountIfExists.mockReturnValue({
|
|
67
|
+
accountId: derivedAccountId,
|
|
68
|
+
});
|
|
69
|
+
mockGetConfigAccountById.mockReturnValue({
|
|
70
|
+
accountId: derivedAccountId,
|
|
71
|
+
});
|
|
66
72
|
mockIsDeveloperTestAccount.mockReturnValue(false);
|
|
67
73
|
mockIsStandardAccount.mockReturnValue(false);
|
|
68
74
|
mockIsAppDeveloperAccount.mockReturnValue(false);
|
|
69
75
|
await expect(handleTargetTestAccountSelectionFlow(derivedAccountId, undefined)).rejects.toThrow(lib.importData.errors.incorrectAccountType(derivedAccountId));
|
|
70
76
|
});
|
|
71
77
|
it('should return the derivedAccountId if it is a developer test account', async () => {
|
|
72
|
-
mockGetAccountConfig.mockReturnValue({});
|
|
73
78
|
mockIsDeveloperTestAccount.mockReturnValue(true);
|
|
79
|
+
mockGetConfigAccountById.mockReturnValue({
|
|
80
|
+
accountId: derivedAccountId,
|
|
81
|
+
});
|
|
74
82
|
const result = await handleTargetTestAccountSelectionFlow(derivedAccountId, undefined);
|
|
75
83
|
expect(result).toBe(derivedAccountId);
|
|
76
84
|
});
|
|
77
85
|
it('should return the result of the importDataTestAccountSelectPrompt if the derivedAccountId is a standard or app developer account', async () => {
|
|
78
|
-
mockGetAccountConfig.mockReturnValue({});
|
|
79
86
|
mockIsDeveloperTestAccount.mockReturnValue(false);
|
|
80
87
|
mockIsStandardAccount.mockReturnValue(true);
|
|
81
88
|
mockIsAppDeveloperAccount.mockReturnValue(true);
|
|
82
89
|
mockImportDataTestAccountSelectPrompt.mockResolvedValue({
|
|
83
90
|
selectedAccountId: 890223,
|
|
84
91
|
});
|
|
92
|
+
mockGetConfigAccountById.mockReturnValue({
|
|
93
|
+
accountId: derivedAccountId,
|
|
94
|
+
});
|
|
85
95
|
const result = await handleTargetTestAccountSelectionFlow(derivedAccountId, undefined);
|
|
86
96
|
expect(result).toBe(890223);
|
|
87
97
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
2
|
import open from 'open';
|
|
3
3
|
import { OAuth2Manager } from '@hubspot/local-dev-lib/models/OAuth2Manager';
|
|
4
|
-
import {
|
|
4
|
+
import { getConfigAccountById } from '@hubspot/local-dev-lib/config';
|
|
5
5
|
import { addOauthToAccountConfig } from '@hubspot/local-dev-lib/oauth';
|
|
6
6
|
import { uiLogger } from '../ui/logger.js';
|
|
7
7
|
import { ENVIRONMENTS } from '@hubspot/local-dev-lib/constants/environments';
|
|
@@ -15,18 +15,22 @@ vi.mock('@hubspot/local-dev-lib/oauth');
|
|
|
15
15
|
vi.mock('../ui/logger.js');
|
|
16
16
|
const mockedExpress = express;
|
|
17
17
|
const mockedOAuth2Manager = OAuth2Manager;
|
|
18
|
-
const
|
|
18
|
+
const mockedGetConfigAccountById = getConfigAccountById;
|
|
19
19
|
describe('lib/oauth', () => {
|
|
20
20
|
const mockExpressReq = {
|
|
21
21
|
query: { code: 'test-auth-code' },
|
|
22
22
|
};
|
|
23
23
|
const mockExpressResp = { send: vi.fn() };
|
|
24
24
|
const mockAccountConfig = {
|
|
25
|
+
name: 'test-account',
|
|
25
26
|
accountId: 123,
|
|
26
|
-
|
|
27
|
-
clientSecret: 'test-client-secret',
|
|
28
|
-
scopes: ['test-scope'],
|
|
27
|
+
authType: 'oauth2',
|
|
29
28
|
env: ENVIRONMENTS.PROD,
|
|
29
|
+
auth: {
|
|
30
|
+
clientId: 'test-client-id',
|
|
31
|
+
clientSecret: 'test-client-secret',
|
|
32
|
+
scopes: ['test-scope'],
|
|
33
|
+
},
|
|
30
34
|
};
|
|
31
35
|
beforeEach(() => {
|
|
32
36
|
mockedExpress.mockReturnValue({
|
|
@@ -49,7 +53,7 @@ describe('lib/oauth', () => {
|
|
|
49
53
|
exchangeForTokens: vi.fn().mockResolvedValue({}),
|
|
50
54
|
};
|
|
51
55
|
mockedOAuth2Manager.mockImplementation(() => mockOAuth2Manager);
|
|
52
|
-
|
|
56
|
+
mockedGetConfigAccountById.mockReturnValue({
|
|
53
57
|
env: ENVIRONMENTS.PROD,
|
|
54
58
|
});
|
|
55
59
|
await authenticateWithOauth(mockAccountConfig);
|
|
@@ -66,7 +70,10 @@ describe('lib/oauth', () => {
|
|
|
66
70
|
it('should handle missing clientId', async () => {
|
|
67
71
|
const invalidConfig = {
|
|
68
72
|
...mockAccountConfig,
|
|
69
|
-
|
|
73
|
+
auth: {
|
|
74
|
+
...mockAccountConfig.auth,
|
|
75
|
+
clientId: undefined,
|
|
76
|
+
},
|
|
70
77
|
};
|
|
71
78
|
mockedOAuth2Manager.mockImplementation(() => ({
|
|
72
79
|
account: invalidConfig,
|
|
@@ -74,6 +81,7 @@ describe('lib/oauth', () => {
|
|
|
74
81
|
const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {
|
|
75
82
|
throw new Error('exit');
|
|
76
83
|
});
|
|
84
|
+
// @ts-expect-error Testing invalid config
|
|
77
85
|
await expect(authenticateWithOauth(invalidConfig)).rejects.toThrow('exit');
|
|
78
86
|
expect(uiLogger.error).toHaveBeenCalled();
|
|
79
87
|
expect(exitSpy).toHaveBeenCalled();
|
|
@@ -82,7 +90,10 @@ describe('lib/oauth', () => {
|
|
|
82
90
|
it('should use default scopes when none provided', async () => {
|
|
83
91
|
const configWithoutScopes = {
|
|
84
92
|
...mockAccountConfig,
|
|
85
|
-
|
|
93
|
+
auth: {
|
|
94
|
+
...mockAccountConfig.auth,
|
|
95
|
+
scopes: [],
|
|
96
|
+
},
|
|
86
97
|
};
|
|
87
98
|
const mockOAuth2Manager = {
|
|
88
99
|
account: configWithoutScopes,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { uiLogger } from '../ui/logger.js';
|
|
2
2
|
import { initiateSync } from '@hubspot/local-dev-lib/api/sandboxSync';
|
|
3
|
-
import {
|
|
3
|
+
import { getConfigAccountIfExists, getConfigAccountById, } from '@hubspot/local-dev-lib/config';
|
|
4
4
|
import { HUBSPOT_ACCOUNT_TYPES } from '@hubspot/local-dev-lib/constants/config';
|
|
5
5
|
import { mockHubSpotHttpError } from '../testUtils.js';
|
|
6
6
|
import { getAvailableSyncTypes } from '../sandboxes.js';
|
|
@@ -13,7 +13,8 @@ vi.mock('../sandboxes');
|
|
|
13
13
|
vi.mock('../ui/SpinniesManager');
|
|
14
14
|
const mockedUiLogger = uiLogger;
|
|
15
15
|
const mockedInitiateSync = initiateSync;
|
|
16
|
-
const
|
|
16
|
+
const mockedGetConfigAccountIfExists = getConfigAccountIfExists;
|
|
17
|
+
const mockedGetConfigAccountById = getConfigAccountById;
|
|
17
18
|
const mockedGetAvailableSyncTypes = getAvailableSyncTypes;
|
|
18
19
|
const mockedSpinniesInit = SpinniesManager.init;
|
|
19
20
|
const mockedSpinniesAdd = SpinniesManager.add;
|
|
@@ -23,22 +24,45 @@ describe('lib/sandboxSync', () => {
|
|
|
23
24
|
const mockEnv = 'qa';
|
|
24
25
|
const mockParentAccount = {
|
|
25
26
|
name: 'Parent Account',
|
|
26
|
-
|
|
27
|
+
accountId: 123,
|
|
27
28
|
accountType: HUBSPOT_ACCOUNT_TYPES.STANDARD_SANDBOX,
|
|
28
29
|
env: mockEnv,
|
|
30
|
+
authType: 'personalaccesskey',
|
|
29
31
|
};
|
|
30
32
|
const mockChildAccount = {
|
|
31
33
|
name: 'Child Account',
|
|
32
|
-
|
|
34
|
+
accountId: 456,
|
|
33
35
|
accountType: HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX,
|
|
34
36
|
env: mockEnv,
|
|
37
|
+
authType: 'personalaccesskey',
|
|
38
|
+
};
|
|
39
|
+
const mockChildAccountWithMissingId = {
|
|
40
|
+
name: 'Child Account',
|
|
41
|
+
accountType: HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX,
|
|
42
|
+
env: mockEnv,
|
|
43
|
+
authType: 'personalaccesskey',
|
|
35
44
|
};
|
|
36
45
|
const mockSyncTasks = [{ type: 'mock-sync-type' }];
|
|
37
46
|
beforeEach(() => {
|
|
38
|
-
|
|
39
|
-
.mockReturnValueOnce(mockChildAccount
|
|
40
|
-
.mockReturnValueOnce(mockParentAccount
|
|
47
|
+
mockedGetConfigAccountIfExists
|
|
48
|
+
.mockReturnValueOnce(mockChildAccount)
|
|
49
|
+
.mockReturnValueOnce(mockParentAccount);
|
|
41
50
|
mockedGetAvailableSyncTypes.mockResolvedValue(mockSyncTasks);
|
|
51
|
+
// Mock SpinniesManager methods to prevent spinner errors
|
|
52
|
+
mockedSpinniesInit.mockImplementation(() => { });
|
|
53
|
+
mockedSpinniesAdd.mockImplementation(() => { });
|
|
54
|
+
mockedSpinniesSucceed.mockImplementation(() => { });
|
|
55
|
+
mockedSpinniesFail.mockImplementation(() => { });
|
|
56
|
+
// Mock account config for uiAccountDescription calls
|
|
57
|
+
mockedGetConfigAccountById.mockImplementation(accountId => {
|
|
58
|
+
if (accountId === mockChildAccount.accountId) {
|
|
59
|
+
return mockChildAccount;
|
|
60
|
+
}
|
|
61
|
+
if (accountId === mockParentAccount.accountId) {
|
|
62
|
+
return mockParentAccount;
|
|
63
|
+
}
|
|
64
|
+
return undefined; // Don't throw, just return undefined for unknown accounts
|
|
65
|
+
});
|
|
42
66
|
});
|
|
43
67
|
describe('syncSandbox()', () => {
|
|
44
68
|
it('successfully syncs a sandbox with provided sync tasks', async () => {
|
|
@@ -46,7 +70,7 @@ describe('lib/sandboxSync', () => {
|
|
|
46
70
|
await syncSandbox(mockChildAccount, mockParentAccount, mockEnv, mockSyncTasks);
|
|
47
71
|
expect(mockedSpinniesInit).toHaveBeenCalled();
|
|
48
72
|
expect(mockedSpinniesAdd).toHaveBeenCalled();
|
|
49
|
-
expect(mockedInitiateSync).toHaveBeenCalledWith(mockParentAccount.
|
|
73
|
+
expect(mockedInitiateSync).toHaveBeenCalledWith(mockParentAccount.accountId, mockChildAccount.accountId, mockSyncTasks, mockChildAccount.accountId);
|
|
50
74
|
expect(mockedSpinniesSucceed).toHaveBeenCalled();
|
|
51
75
|
});
|
|
52
76
|
it('fetches sync types when no tasks are provided', async () => {
|
|
@@ -57,10 +81,8 @@ describe('lib/sandboxSync', () => {
|
|
|
57
81
|
expect(mockedInitiateSync).toHaveBeenCalled();
|
|
58
82
|
});
|
|
59
83
|
it('throws error when account IDs are missing', async () => {
|
|
60
|
-
mockedGetAccountId.mockReset();
|
|
61
|
-
mockedGetAccountId.mockReturnValue(null);
|
|
62
84
|
const errorRegex = new RegExp(`because your account has been removed from`);
|
|
63
|
-
await expect(syncSandbox(
|
|
85
|
+
await expect(syncSandbox(mockChildAccountWithMissingId, mockParentAccount, mockEnv, mockSyncTasks)).rejects.toThrow(errorRegex);
|
|
64
86
|
});
|
|
65
87
|
it('handles sync in progress error', async () => {
|
|
66
88
|
const error = mockHubSpotHttpError('', {
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
import { uiLogger } from '../ui/logger.js';
|
|
2
2
|
import { getSandboxUsageLimits } from '@hubspot/local-dev-lib/api/sandboxHubs';
|
|
3
3
|
import { fetchTypes } from '@hubspot/local-dev-lib/api/sandboxSync';
|
|
4
|
-
import {
|
|
4
|
+
import { getAllConfigAccounts, getConfigAccountIfExists, } from '@hubspot/local-dev-lib/config';
|
|
5
5
|
import { HUBSPOT_ACCOUNT_TYPES } from '@hubspot/local-dev-lib/constants/config';
|
|
6
6
|
import { mockHubSpotHttpError } from '../testUtils.js';
|
|
7
7
|
import { getSandboxTypeAsString, getHasSandboxesByType, getAvailableSyncTypes, validateSandboxUsageLimits, handleSandboxCreateError, } from '../sandboxes.js';
|
|
8
|
+
import { isMissingScopeError, isSpecifiedError, } from '@hubspot/local-dev-lib/errors/index';
|
|
8
9
|
vi.mock('../ui/logger.js');
|
|
9
10
|
vi.mock('@hubspot/local-dev-lib/api/sandboxHubs');
|
|
10
11
|
vi.mock('@hubspot/local-dev-lib/api/sandboxSync');
|
|
11
12
|
vi.mock('@hubspot/local-dev-lib/config');
|
|
12
|
-
|
|
13
|
+
vi.mock('@hubspot/local-dev-lib/errors/index');
|
|
14
|
+
const mockedGetConfigAccountIfExists = getConfigAccountIfExists;
|
|
13
15
|
const mockedGetSandboxUsageLimits = getSandboxUsageLimits;
|
|
14
16
|
const mockedFetchTypes = fetchTypes;
|
|
15
|
-
const
|
|
17
|
+
const mockedGetAllConfigAccounts = getAllConfigAccounts;
|
|
16
18
|
const mockedUiLogger = uiLogger;
|
|
19
|
+
const mockedIsMissingScopeError = isMissingScopeError;
|
|
20
|
+
const mockedIsSpecifiedError = isSpecifiedError;
|
|
17
21
|
describe('lib/sandboxes', () => {
|
|
18
22
|
describe('getSandboxTypeAsString()', () => {
|
|
19
23
|
it('returns "development" for development sandbox type', () => {
|
|
@@ -29,14 +33,13 @@ describe('lib/sandboxes', () => {
|
|
|
29
33
|
describe('getHasSandboxesByType()', () => {
|
|
30
34
|
const mockParentAccount = {
|
|
31
35
|
name: 'Parent Account',
|
|
32
|
-
|
|
33
|
-
authType: undefined,
|
|
36
|
+
accountId: 123,
|
|
34
37
|
accountType: HUBSPOT_ACCOUNT_TYPES.STANDARD_SANDBOX,
|
|
35
38
|
env: 'qa',
|
|
36
39
|
};
|
|
37
40
|
it('returns true when sandbox of specified type exists', () => {
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
mockedGetConfigAccountIfExists.mockReturnValue(mockParentAccount);
|
|
42
|
+
mockedGetAllConfigAccounts.mockReturnValue([
|
|
40
43
|
mockParentAccount,
|
|
41
44
|
{
|
|
42
45
|
...mockParentAccount,
|
|
@@ -47,25 +50,25 @@ describe('lib/sandboxes', () => {
|
|
|
47
50
|
expect(getHasSandboxesByType(mockParentAccount, HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX)).toBe(true);
|
|
48
51
|
});
|
|
49
52
|
it('returns false when no sandbox of specified type exists', () => {
|
|
50
|
-
|
|
53
|
+
mockedGetAllConfigAccounts.mockReturnValue([mockParentAccount]);
|
|
51
54
|
expect(getHasSandboxesByType(mockParentAccount, HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX)).toBe(false);
|
|
52
55
|
});
|
|
53
56
|
});
|
|
54
57
|
describe('getAvailableSyncTypes()', () => {
|
|
55
58
|
const mockParentAccount = {
|
|
56
59
|
name: 'Parent Account',
|
|
57
|
-
|
|
60
|
+
accountId: 123,
|
|
58
61
|
env: 'qa',
|
|
59
62
|
};
|
|
60
63
|
const mockChildAccount = {
|
|
61
64
|
...mockParentAccount,
|
|
62
|
-
|
|
65
|
+
accountId: 456,
|
|
63
66
|
};
|
|
64
67
|
it('returns available sync types when fetch is successful', async () => {
|
|
65
68
|
const mockSyncTypes = [{ name: 'type1' }, { name: 'type2' }];
|
|
66
|
-
|
|
67
|
-
.mockReturnValue(mockParentAccount.
|
|
68
|
-
.mockReturnValue(mockChildAccount.
|
|
69
|
+
mockedGetConfigAccountIfExists
|
|
70
|
+
.mockReturnValue(mockParentAccount.accountId)
|
|
71
|
+
.mockReturnValue(mockChildAccount.accountId);
|
|
69
72
|
mockedFetchTypes.mockResolvedValue({
|
|
70
73
|
data: { results: mockSyncTypes },
|
|
71
74
|
});
|
|
@@ -80,12 +83,11 @@ describe('lib/sandboxes', () => {
|
|
|
80
83
|
describe('validateSandboxUsageLimits()', () => {
|
|
81
84
|
const mockAccount = {
|
|
82
85
|
name: 'Test Account',
|
|
83
|
-
|
|
84
|
-
authType: undefined,
|
|
86
|
+
accountId: 123,
|
|
85
87
|
env: 'qa',
|
|
86
88
|
};
|
|
87
89
|
it('validates successfully when limits are not reached', async () => {
|
|
88
|
-
|
|
90
|
+
mockedGetConfigAccountIfExists.mockReturnValue(mockAccount.accountId);
|
|
89
91
|
mockedGetSandboxUsageLimits.mockResolvedValue({
|
|
90
92
|
data: {
|
|
91
93
|
usage: { DEVELOPER: { available: 1, limit: 3 } },
|
|
@@ -94,8 +96,8 @@ describe('lib/sandboxes', () => {
|
|
|
94
96
|
await expect(validateSandboxUsageLimits(mockAccount, HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX, 'qa')).resolves.not.toThrow();
|
|
95
97
|
});
|
|
96
98
|
it('throws error when development sandbox limit is reached', async () => {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
+
mockedGetConfigAccountIfExists.mockReturnValue(mockAccount.accountId);
|
|
100
|
+
mockedGetAllConfigAccounts.mockReturnValue([]);
|
|
99
101
|
mockedGetSandboxUsageLimits.mockResolvedValue({
|
|
100
102
|
data: {
|
|
101
103
|
usage: { DEVELOPER: { available: 0, limit: 1 } },
|
|
@@ -116,6 +118,9 @@ describe('lib/sandboxes', () => {
|
|
|
116
118
|
category: 'MISSING_SCOPES',
|
|
117
119
|
},
|
|
118
120
|
});
|
|
121
|
+
// Mock the error checking function to return true for missing scope error
|
|
122
|
+
mockedIsMissingScopeError.mockReturnValue(true);
|
|
123
|
+
mockedIsSpecifiedError.mockReturnValue(false);
|
|
119
124
|
expect(() => handleSandboxCreateError(error, mockEnv, mockName, mockAccountId)).toThrow(error);
|
|
120
125
|
expect(mockedUiLogger.error).toHaveBeenCalledWith(expect.stringMatching(/The personal access key you provided doesn't include sandbox permissions/));
|
|
121
126
|
expect(mockedUiLogger.info).toHaveBeenCalledWith(expect.stringMatching(/To update CLI permissions for/));
|
|
@@ -128,6 +133,9 @@ describe('lib/sandboxes', () => {
|
|
|
128
133
|
subCategory: 'SandboxErrors.USER_ACCESS_NOT_ALLOWED',
|
|
129
134
|
},
|
|
130
135
|
});
|
|
136
|
+
// Mock the error checking function to return true for this error type
|
|
137
|
+
mockedIsMissingScopeError.mockReturnValue(false);
|
|
138
|
+
mockedIsSpecifiedError.mockReturnValue(true);
|
|
131
139
|
expect(() => handleSandboxCreateError(error, mockEnv, mockName, mockAccountId)).toThrow(error);
|
|
132
140
|
expect(mockedUiLogger.error).toHaveBeenCalledWith(expect.stringMatching(/your permission set doesn't allow you to create the sandbox/));
|
|
133
141
|
});
|
|
@@ -139,8 +147,11 @@ describe('lib/sandboxes', () => {
|
|
|
139
147
|
subCategory: 'SandboxErrors.DEVELOPMENT_SANDBOX_ACCESS_NOT_ALLOWED',
|
|
140
148
|
},
|
|
141
149
|
});
|
|
150
|
+
// Mock the error checking function to return true for this error type
|
|
151
|
+
mockedIsMissingScopeError.mockReturnValue(false);
|
|
152
|
+
mockedIsSpecifiedError.mockReturnValue(true);
|
|
142
153
|
expect(() => handleSandboxCreateError(error, mockEnv, mockName, mockAccountId)).toThrow(error);
|
|
143
|
-
expect(mockedUiLogger.error).toHaveBeenCalledWith(expect.stringMatching(/
|
|
154
|
+
expect(mockedUiLogger.error).toHaveBeenCalledWith(expect.stringMatching(/Couldn't create.*because your account has been removed from.*or your permission set doesn't allow you to create/));
|
|
144
155
|
});
|
|
145
156
|
});
|
|
146
157
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { trackUsage } from '@hubspot/local-dev-lib/trackUsage';
|
|
2
|
-
import {
|
|
2
|
+
import { getConfig, getConfigAccountById } from '@hubspot/local-dev-lib/config';
|
|
3
3
|
import { API_KEY_AUTH_METHOD } from '@hubspot/local-dev-lib/constants/auth';
|
|
4
4
|
import { uiLogger } from '../ui/logger.js';
|
|
5
5
|
import { trackCommandUsage, trackHelpUsage, trackConvertFieldsUsage, trackAuthAction, trackCommandMetadataUsage, } from '../usageTracking.js';
|
|
@@ -9,14 +9,14 @@ vi.mock('@hubspot/local-dev-lib/trackUsage');
|
|
|
9
9
|
vi.mock('@hubspot/local-dev-lib/config');
|
|
10
10
|
vi.mock('../ui/logger.js');
|
|
11
11
|
const mockedTrackUsage = trackUsage;
|
|
12
|
-
const
|
|
13
|
-
const
|
|
12
|
+
const mockedGetConfig = getConfig;
|
|
13
|
+
const mockedGetConfigAccountById = getConfigAccountById;
|
|
14
14
|
const mockedUiLogger = uiLogger;
|
|
15
15
|
describe('lib/usageTracking', () => {
|
|
16
16
|
const mockPlatform = 'darwin';
|
|
17
17
|
const mockNodeVersion = 'v16.14.0';
|
|
18
18
|
beforeEach(() => {
|
|
19
|
-
|
|
19
|
+
mockedGetConfig.mockReturnValue({ allowUsageTracking: true });
|
|
20
20
|
Object.defineProperty(process, 'platform', { value: mockPlatform });
|
|
21
21
|
Object.defineProperty(process, 'version', { value: mockNodeVersion });
|
|
22
22
|
});
|
|
@@ -24,7 +24,7 @@ describe('lib/usageTracking', () => {
|
|
|
24
24
|
const mockCommand = 'test-command';
|
|
25
25
|
const mockAccountId = 123;
|
|
26
26
|
it('should not track when tracking is disabled', async () => {
|
|
27
|
-
|
|
27
|
+
mockedGetConfig.mockReturnValue({ allowUsageTracking: false });
|
|
28
28
|
await trackCommandUsage(mockCommand);
|
|
29
29
|
expect(mockedTrackUsage).not.toHaveBeenCalled();
|
|
30
30
|
});
|
|
@@ -41,7 +41,7 @@ describe('lib/usageTracking', () => {
|
|
|
41
41
|
}), mockAccountId);
|
|
42
42
|
});
|
|
43
43
|
it('should track command usage with custom auth type', async () => {
|
|
44
|
-
|
|
44
|
+
mockedGetConfigAccountById.mockReturnValue({ authType: 'oauth2' });
|
|
45
45
|
await trackCommandUsage(mockCommand, {}, mockAccountId);
|
|
46
46
|
expect(mockedTrackUsage).toHaveBeenCalledWith('cli-interaction', 'INTERACTION', expect.objectContaining({
|
|
47
47
|
authType: 'oauth2',
|
|
@@ -59,7 +59,7 @@ describe('lib/usageTracking', () => {
|
|
|
59
59
|
describe('trackHelpUsage()', () => {
|
|
60
60
|
const mockCommand = 'help-command';
|
|
61
61
|
it('should not track when tracking is disabled', async () => {
|
|
62
|
-
|
|
62
|
+
mockedGetConfig.mockReturnValue({ allowUsageTracking: false });
|
|
63
63
|
await trackHelpUsage(mockCommand);
|
|
64
64
|
expect(mockedTrackUsage).not.toHaveBeenCalled();
|
|
65
65
|
});
|
|
@@ -82,7 +82,7 @@ describe('lib/usageTracking', () => {
|
|
|
82
82
|
describe('trackConvertFieldsUsage()', () => {
|
|
83
83
|
const mockCommand = 'convert-fields-command';
|
|
84
84
|
it('should not track when tracking is disabled', async () => {
|
|
85
|
-
|
|
85
|
+
mockedGetConfig.mockReturnValue({ allowUsageTracking: false });
|
|
86
86
|
await trackConvertFieldsUsage(mockCommand);
|
|
87
87
|
expect(mockedTrackUsage).not.toHaveBeenCalled();
|
|
88
88
|
});
|
|
@@ -104,7 +104,7 @@ describe('lib/usageTracking', () => {
|
|
|
104
104
|
const mockStep = 'init';
|
|
105
105
|
const mockAccountId = 123;
|
|
106
106
|
it('should not track when tracking is disabled', async () => {
|
|
107
|
-
|
|
107
|
+
mockedGetConfig.mockReturnValue({ allowUsageTracking: false });
|
|
108
108
|
await trackAuthAction(mockCommand, mockAuthType, mockStep, mockAccountId);
|
|
109
109
|
expect(mockedTrackUsage).not.toHaveBeenCalled();
|
|
110
110
|
});
|
|
@@ -127,7 +127,7 @@ describe('lib/usageTracking', () => {
|
|
|
127
127
|
const mockMeta = { assetType: 'test-asset' };
|
|
128
128
|
const mockAccountId = 123;
|
|
129
129
|
it('should not track when tracking is disabled', async () => {
|
|
130
|
-
|
|
130
|
+
mockedGetConfig.mockReturnValue({ allowUsageTracking: false });
|
|
131
131
|
await trackCommandMetadataUsage(mockCommand, mockMeta, mockAccountId);
|
|
132
132
|
expect(mockedTrackUsage).not.toHaveBeenCalled();
|
|
133
133
|
});
|