@hubspot/cli 7.7.35-experimental.0 → 7.8.0-beta.1
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 +31 -25
- package/commands/__tests__/auth.test.js +5 -0
- package/commands/__tests__/doctor.test.js +16 -16
- package/commands/__tests__/getStarted.test.js +2 -2
- package/commands/__tests__/mcp.test.js +1 -1
- package/commands/__tests__/project.test.js +2 -3
- package/commands/account/auth.js +1 -0
- package/commands/account/clean.js +18 -27
- package/commands/account/createOverride.js +13 -31
- package/commands/account/info.js +20 -31
- package/commands/account/list.js +16 -22
- package/commands/account/remove.js +12 -20
- package/commands/account/removeOverride.js +11 -21
- package/commands/account/rename.js +6 -9
- package/commands/account/use.js +12 -26
- package/commands/account.js +2 -2
- package/commands/app/__tests__/migrate.test.js +5 -6
- package/commands/app/migrate.js +13 -19
- package/commands/app/secret/add.js +2 -1
- package/commands/app/secret/delete.js +2 -1
- package/commands/app/secret/list.js +2 -1
- package/commands/app/secret/update.js +2 -1
- package/commands/app/secret.js +2 -1
- package/commands/app.js +2 -2
- package/commands/auth.d.ts +1 -0
- package/commands/auth.js +17 -7
- package/commands/cms/convertFields.js +7 -9
- package/commands/cms/getReactModule.js +9 -14
- package/commands/cms/lighthouseScore.js +33 -36
- package/commands/cms.js +2 -2
- package/commands/completion.js +3 -3
- package/commands/config/set.d.ts +1 -1
- package/commands/config/set.js +64 -37
- package/commands/config.js +2 -2
- package/commands/create.js +2 -2
- package/commands/customObject/create.js +10 -12
- package/commands/customObject/schema/create.js +9 -11
- package/commands/customObject/schema/delete.js +16 -16
- package/commands/customObject/schema/fetch-all.js +12 -11
- package/commands/customObject/schema/fetch.js +15 -15
- package/commands/customObject/schema/list.js +4 -4
- package/commands/customObject/schema/update.js +13 -13
- package/commands/customObject/schema.js +2 -2
- package/commands/customObject.js +6 -7
- package/commands/doctor.js +8 -11
- package/commands/feedback.js +8 -13
- package/commands/fetch.js +8 -8
- package/commands/filemanager/fetch.js +7 -7
- package/commands/filemanager/upload.js +15 -34
- package/commands/filemanager.js +2 -2
- package/commands/function/deploy.js +11 -29
- package/commands/function/list.js +8 -8
- package/commands/function/server.js +9 -11
- package/commands/function.d.ts +1 -1
- package/commands/function.js +2 -2
- package/commands/getStarted.d.ts +0 -2
- package/commands/getStarted.js +4 -4
- package/commands/hubdb/clear.js +7 -15
- package/commands/hubdb/create.js +9 -15
- package/commands/hubdb/delete.js +8 -15
- package/commands/hubdb/fetch.js +6 -9
- package/commands/hubdb.d.ts +1 -1
- package/commands/hubdb.js +2 -2
- package/commands/init.js +2 -3
- package/commands/lint.js +16 -16
- package/commands/list.js +8 -14
- package/commands/logs.js +14 -20
- package/commands/mcp/__tests__/setup.test.js +2 -2
- package/commands/mcp/setup.js +11 -2
- package/commands/mcp.js +3 -3
- package/commands/mv.js +6 -17
- package/commands/open.js +5 -5
- package/commands/project/__tests__/add.test.js +15 -13
- package/commands/project/__tests__/create.test.js +6 -6
- package/commands/project/__tests__/deploy.test.js +3 -7
- package/commands/project/__tests__/devUnifiedFlow.test.js +2 -4
- package/commands/project/__tests__/installDeps.test.js +8 -8
- package/commands/project/__tests__/list.test.js +31 -0
- package/commands/project/__tests__/logs.test.js +1 -4
- package/commands/project/__tests__/migrate.test.js +7 -7
- package/commands/project/__tests__/migrateApp.test.js +3 -7
- package/commands/project/__tests__/profile.test.js +1 -1
- package/commands/project/__tests__/validate.test.js +98 -0
- package/commands/project/add.d.ts +2 -2
- package/commands/project/add.js +7 -10
- package/commands/project/cloneApp.js +14 -19
- package/commands/project/create.js +3 -10
- package/commands/project/deploy.js +5 -5
- package/commands/project/dev/deprecatedFlow.js +9 -18
- package/commands/project/dev/index.js +21 -18
- package/commands/project/dev/unifiedFlow.js +14 -7
- package/commands/project/download.js +15 -16
- package/commands/project/installDeps.d.ts +2 -2
- package/commands/project/installDeps.js +9 -9
- package/commands/project/list.d.ts +4 -0
- package/commands/project/list.js +62 -0
- package/commands/project/listBuilds.js +12 -21
- package/commands/project/logs.js +21 -24
- package/commands/project/migrate.js +46 -15
- package/commands/project/migrateApp.js +10 -17
- package/commands/project/open.js +6 -14
- package/commands/project/profile/add.js +3 -3
- package/commands/project/profile/delete.js +1 -2
- package/commands/project/profile.js +2 -3
- package/commands/project/upload.js +16 -25
- package/commands/project/validate.js +7 -7
- package/commands/project/watch.js +13 -22
- package/commands/project.js +4 -3
- package/commands/sandbox/__tests__/create.test.js +5 -5
- package/commands/sandbox/create.js +22 -32
- package/commands/sandbox/delete.js +39 -64
- package/commands/sandbox.js +2 -2
- package/commands/secret/addSecret.js +7 -17
- package/commands/secret/deleteSecret.js +10 -20
- package/commands/secret/listSecret.js +8 -10
- package/commands/secret/updateSecret.js +9 -17
- package/commands/secret.js +2 -2
- package/commands/testAccount/__tests__/delete.test.js +2 -4
- package/commands/testAccount/create.js +2 -2
- package/commands/testAccount/delete.d.ts +4 -3
- package/commands/testAccount/delete.js +155 -14
- package/commands/testAccount/importData.d.ts +1 -1
- package/commands/testAccount/importData.js +1 -1
- package/commands/testAccount.js +1 -1
- package/commands/theme/preview.js +1 -4
- package/lang/en.d.ts +364 -110
- package/lang/en.js +409 -158
- package/lang/en.lyaml +4 -4
- package/lib/__tests__/buildAccount.test.js +4 -3
- package/lib/__tests__/commonOpts.test.js +1 -1
- package/lib/__tests__/dependencyManagement.test.js +1 -1
- package/lib/__tests__/developerTestAccounts.test.js +3 -3
- package/lib/__tests__/npm.test.js +1 -1
- package/lib/__tests__/oauth.test.js +4 -4
- package/lib/__tests__/process.test.js +10 -5
- package/lib/__tests__/sandboxSync.test.js +8 -8
- package/lib/__tests__/sandboxes.test.js +8 -8
- package/lib/__tests__/serverlessLogs.test.js +1 -1
- package/lib/__tests__/usageTracking.test.js +5 -5
- package/lib/__tests__/validation.test.js +2 -1
- package/lib/__tests__/yargsUtils.test.js +83 -9
- package/lib/app/__tests__/migrate.test.js +19 -56
- package/lib/app/__tests__/migrate_legacy.test.js +1 -1
- package/lib/app/migrate.d.ts +2 -8
- package/lib/app/migrate.js +6 -81
- package/lib/app/migrate_legacy.js +20 -24
- package/lib/buildAccount.d.ts +2 -2
- package/lib/buildAccount.js +32 -64
- package/lib/commonOpts.d.ts +1 -1
- package/lib/commonOpts.js +25 -22
- package/lib/configMigrate.js +88 -9
- package/lib/configOptions.js +7 -0
- package/lib/constants.d.ts +21 -1
- package/lib/constants.js +25 -1
- package/lib/dependencyManagement.js +9 -27
- package/lib/developerTestAccounts.js +9 -23
- package/lib/doctor/Diagnosis.js +11 -23
- package/lib/doctor/DiagnosticInfoBuilder.js +12 -11
- package/lib/doctor/Doctor.js +42 -90
- package/lib/doctor/__tests__/Doctor.test.js +4 -4
- package/lib/errorHandlers/index.js +12 -20
- package/lib/errorHandlers/suppressError.js +11 -18
- package/lib/lang.js +6 -5
- package/lib/links.d.ts +1 -0
- package/lib/links.js +14 -7
- package/lib/mcp/setup.js +1 -1
- package/lib/middleware/__test__/commandTargetingUtils.test.js +99 -0
- package/lib/middleware/__test__/configMiddleware.test.js +11 -11
- package/lib/middleware/__test__/yargsChecksMiddleware.test.js +6 -8
- package/lib/middleware/commandTargetingUtils.d.ts +8 -0
- package/lib/middleware/commandTargetingUtils.js +74 -0
- package/lib/middleware/configMiddleware.d.ts +1 -1
- package/lib/middleware/configMiddleware.js +21 -81
- package/lib/middleware/fireAlarmMiddleware.js +15 -5
- package/lib/middleware/gitMiddleware.js +5 -1
- package/lib/middleware/notificationsMiddleware.js +5 -11
- package/lib/middleware/yargsChecksMiddleware.js +6 -9
- package/lib/npm.js +2 -2
- package/lib/oauth.js +5 -5
- package/lib/process.js +5 -4
- package/lib/projects/__tests__/AppDevModeInterface.test.js +87 -90
- package/lib/projects/__tests__/LocalDevProcess.test.js +231 -19
- package/lib/projects/__tests__/LocalDevWebsocketServer.test.js +89 -63
- package/lib/projects/__tests__/deploy.test.js +73 -8
- package/lib/projects/__tests__/localDevProjectHelpers.test.js +6 -2
- package/lib/projects/__tests__/platformVersion.test.js +8 -8
- package/lib/projects/__tests__/projects.test.js +12 -12
- package/lib/projects/__tests__/structure.test.js +3 -3
- package/lib/projects/__tests__/upload.test.d.ts +1 -0
- package/lib/projects/__tests__/upload.test.js +82 -0
- package/lib/projects/add/__tests__/legacyAddComponent.test.js +6 -6
- package/lib/projects/add/__tests__/v2AddComponent.test.d.ts +1 -0
- package/lib/projects/add/__tests__/{v3AddComponent.test.js → v2AddComponent.test.js} +39 -39
- package/lib/projects/add/{v3AddComponent.d.ts → v2AddComponent.d.ts} +1 -1
- package/lib/projects/add/{v3AddComponent.js → v2AddComponent.js} +5 -5
- package/lib/projects/create/__tests__/legacy.test.js +5 -5
- package/lib/projects/create/__tests__/v2.test.d.ts +1 -0
- package/lib/projects/create/__tests__/{v3.test.js → v2.test.js} +82 -7
- package/lib/projects/create/index.js +4 -4
- package/lib/projects/create/legacy.js +2 -2
- package/lib/projects/create/{v3.d.ts → v2.d.ts} +3 -3
- package/lib/projects/create/{v3.js → v2.js} +13 -11
- package/lib/projects/deploy.d.ts +1 -1
- package/lib/projects/deploy.js +2 -2
- package/lib/projects/localDev/AppDevModeInterface.d.ts +10 -1
- package/lib/projects/localDev/AppDevModeInterface.js +118 -89
- package/lib/projects/localDev/DevServerManager.d.ts +11 -29
- package/lib/projects/localDev/DevServerManager.js +19 -61
- package/lib/projects/localDev/DevServerManager_DEPRECATED.d.ts +40 -0
- package/lib/projects/localDev/DevServerManager_DEPRECATED.js +120 -0
- package/lib/projects/localDev/LocalDevLogger.d.ts +4 -0
- package/lib/projects/localDev/LocalDevLogger.js +27 -6
- package/lib/projects/localDev/{LocalDevManager.js → LocalDevManager_DEPRECATED.js} +10 -11
- package/lib/projects/localDev/LocalDevProcess.d.ts +7 -5
- package/lib/projects/localDev/LocalDevProcess.js +93 -21
- package/lib/projects/localDev/LocalDevState.d.ts +12 -8
- package/lib/projects/localDev/LocalDevState.js +27 -17
- package/lib/projects/localDev/LocalDevWebsocketServer.d.ts +6 -1
- package/lib/projects/localDev/LocalDevWebsocketServer.js +94 -33
- package/lib/projects/localDev/helpers/account.d.ts +1 -1
- package/lib/projects/localDev/helpers/account.js +2 -2
- package/lib/projects/localDev/helpers/project.d.ts +1 -0
- package/lib/projects/localDev/helpers/project.js +44 -4
- package/lib/projects/localDev/localDevWebsocketServerUtils.d.ts +7 -0
- package/lib/projects/localDev/localDevWebsocketServerUtils.js +19 -0
- package/lib/projects/platformVersion.d.ts +1 -1
- package/lib/projects/platformVersion.js +1 -1
- package/lib/projects/pollProjectBuildAndDeploy.js +4 -4
- package/lib/projects/structure.js +6 -6
- package/lib/projects/upload.d.ts +1 -1
- package/lib/projects/upload.js +17 -8
- package/lib/projects/urls.d.ts +0 -1
- package/lib/projects/urls.js +0 -3
- package/lib/prompts/__tests__/downloadProjectPrompt.test.js +1 -0
- package/lib/prompts/__tests__/projectAddPrompt.test.js +10 -10
- package/lib/prompts/accountNamePrompt.js +14 -19
- package/lib/prompts/accountsPrompt.js +2 -2
- package/lib/prompts/cmsFieldPrompt.js +2 -2
- package/lib/prompts/createApiSamplePrompt.js +5 -5
- package/lib/prompts/createDeveloperTestAccountConfigPrompt.js +10 -1
- package/lib/prompts/createFunctionPrompt.js +14 -14
- package/lib/prompts/createModulePrompt.js +9 -9
- package/lib/prompts/createTemplatePrompt.js +2 -2
- package/lib/prompts/downloadProjectPrompt.js +5 -8
- package/lib/prompts/installAppPrompt.d.ts +1 -6
- package/lib/prompts/installAppPrompt.js +1 -6
- package/lib/prompts/personalAccessKeyPrompt.js +3 -3
- package/lib/prompts/previewPrompt.js +6 -6
- package/lib/prompts/projectAddPrompt.d.ts +2 -2
- package/lib/prompts/projectAddPrompt.js +9 -2
- package/lib/prompts/projectDevTargetAccountPrompt.js +20 -32
- package/lib/prompts/projectNamePrompt.js +4 -8
- package/lib/prompts/projectsLogsPrompt.js +2 -4
- package/lib/prompts/promptUtils.js +30 -9
- package/lib/prompts/sandboxesPrompt.js +7 -7
- package/lib/prompts/secretPrompt.js +3 -3
- package/lib/prompts/selectAppPrompt.js +3 -3
- package/lib/prompts/selectHubDBTablePrompt.js +9 -13
- package/lib/prompts/selectProjectTemplatePrompt.js +2 -0
- package/lib/prompts/selectPublicAppForMigrationPrompt.js +15 -19
- package/lib/prompts/setAsDefaultAccountPrompt.js +4 -8
- package/lib/prompts/uploadPrompt.js +5 -5
- package/lib/sandboxSync.js +24 -41
- package/lib/sandboxes.js +19 -47
- package/lib/schema.js +3 -3
- package/lib/serverlessLogs.js +11 -13
- package/lib/theme/__tests__/migrate.test.d.ts +1 -0
- package/lib/theme/__tests__/migrate.test.js +233 -0
- package/lib/theme/migrate.d.ts +13 -0
- package/lib/theme/migrate.js +90 -0
- package/lib/ui/SpinniesManager.d.ts +2 -0
- package/lib/ui/SpinniesManager.js +7 -0
- package/lib/ui/boxen.js +1 -2
- package/lib/ui/git.js +13 -10
- package/lib/ui/index.d.ts +4 -0
- package/lib/ui/index.js +47 -38
- package/lib/ui/serverlessFunctionLogs.js +9 -7
- package/lib/ui/uiMessages.d.ts +72 -0
- package/lib/ui/uiMessages.js +75 -0
- package/lib/usageTracking.js +8 -8
- package/lib/validation.js +20 -23
- package/lib/yargsUtils.d.ts +1 -1
- package/lib/yargsUtils.js +12 -5
- package/mcp-server/tools/cms/HsCreateModuleTool.d.ts +2 -2
- package/mcp-server/tools/index.js +4 -0
- package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +2 -2
- package/mcp-server/tools/project/CreateProjectTool.d.ts +2 -2
- package/mcp-server/tools/project/DocsSearchTool.d.ts +4 -1
- package/mcp-server/tools/project/DocsSearchTool.js +5 -5
- package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.d.ts +23 -0
- package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +68 -0
- package/mcp-server/tools/project/GetApplicationInfoTool.d.ts +11 -0
- package/mcp-server/tools/project/GetApplicationInfoTool.js +49 -0
- package/mcp-server/tools/project/GetConfigValuesTool.d.ts +4 -1
- package/mcp-server/tools/project/GetConfigValuesTool.js +12 -6
- package/mcp-server/tools/project/GuidedWalkthroughTool.d.ts +2 -2
- package/mcp-server/tools/project/__tests__/CreateProjectTool.test.js +1 -1
- package/mcp-server/tools/project/__tests__/DocsSearchTool.test.js +12 -10
- package/mcp-server/tools/project/__tests__/GetApiUsagePatternsByAppIdTool.test.d.ts +1 -0
- package/mcp-server/tools/project/__tests__/GetApiUsagePatternsByAppIdTool.test.js +169 -0
- package/mcp-server/tools/project/__tests__/GetApplicationInfoTool.test.d.ts +1 -0
- package/mcp-server/tools/project/__tests__/GetApplicationInfoTool.test.js +115 -0
- package/mcp-server/tools/project/__tests__/GetConfigValuesTool.test.js +8 -7
- package/mcp-server/utils/__tests__/cliConfig.test.d.ts +1 -0
- package/mcp-server/utils/__tests__/cliConfig.test.js +110 -0
- package/mcp-server/utils/cliConfig.d.ts +1 -0
- package/mcp-server/utils/cliConfig.js +12 -0
- package/mcp-server/utils/toolUsageTracking.js +2 -2
- package/package.json +8 -7
- package/types/LocalDev.d.ts +19 -3
- package/ui/index.js +1 -1
- package/lib/middleware/__test__/utils.test.js +0 -51
- package/lib/middleware/utils.d.ts +0 -8
- package/lib/middleware/utils.js +0 -14
- package/lib/projects/localDev/DevServerManagerV2.d.ts +0 -22
- package/lib/projects/localDev/DevServerManagerV2.js +0 -81
- /package/{lib/middleware/__test__/utils.test.d.ts → commands/project/__tests__/list.test.d.ts} +0 -0
- /package/{lib/projects/add/__tests__/v3AddComponent.test.d.ts → commands/project/__tests__/validate.test.d.ts} +0 -0
- /package/lib/{projects/create/__tests__/v3.test.d.ts → middleware/__test__/commandTargetingUtils.test.d.ts} +0 -0
- /package/lib/projects/localDev/{LocalDevManager.d.ts → LocalDevManager_DEPRECATED.d.ts} +0 -0
|
@@ -11,7 +11,7 @@ vi.mock('@hubspot/ui-extensions-dev-server', () => {
|
|
|
11
11
|
};
|
|
12
12
|
});
|
|
13
13
|
import { fetchAppInstallationData } from '@hubspot/local-dev-lib/api/localDevAuth';
|
|
14
|
-
import {
|
|
14
|
+
import { fetchAppMetadataByUid, fetchPublicAppProductionInstallCounts, installStaticAuthAppOnTestAccount, } from '@hubspot/local-dev-lib/api/appsDev';
|
|
15
15
|
import { DevModeUnifiedInterface as UIEDevModeInterface } from '@hubspot/ui-extensions-dev-server';
|
|
16
16
|
import { requestPorts } from '@hubspot/local-dev-lib/portManager';
|
|
17
17
|
import { getAccountConfig } from '@hubspot/local-dev-lib/config';
|
|
@@ -67,6 +67,8 @@ describe('AppDevModeInterface', () => {
|
|
|
67
67
|
componentRoot: '/test/path',
|
|
68
68
|
componentConfigPath: '/test/path/config.json',
|
|
69
69
|
configUpdatedSinceLastUpload: false,
|
|
70
|
+
removed: false,
|
|
71
|
+
parsingErrors: [],
|
|
70
72
|
},
|
|
71
73
|
componentDeps: {},
|
|
72
74
|
metaFilePath: '/test/path',
|
|
@@ -107,8 +109,8 @@ describe('AppDevModeInterface', () => {
|
|
|
107
109
|
LocalDevState.mockImplementation(() => mockLocalDevState);
|
|
108
110
|
LocalDevLogger.mockImplementation(() => mockLocalDevLogger);
|
|
109
111
|
// Mock external dependencies
|
|
110
|
-
|
|
111
|
-
data:
|
|
112
|
+
fetchAppMetadataByUid.mockResolvedValue({
|
|
113
|
+
data: mockPublicApp,
|
|
112
114
|
});
|
|
113
115
|
fetchPublicAppProductionInstallCounts.mockResolvedValue({
|
|
114
116
|
data: { uniquePortalInstallCount: 5 },
|
|
@@ -127,7 +129,16 @@ describe('AppDevModeInterface', () => {
|
|
|
127
129
|
getOauthAppInstallUrl.mockReturnValue('http://oauth-install-url');
|
|
128
130
|
getStaticAuthAppInstallUrl.mockReturnValue('http://static-install-url');
|
|
129
131
|
installAppAutoPrompt.mockResolvedValue(true);
|
|
130
|
-
installAppBrowserPrompt.
|
|
132
|
+
installAppBrowserPrompt.mockImplementation(async () => {
|
|
133
|
+
setTimeout(() => {
|
|
134
|
+
const addListenerCall = mockLocalDevState.addListener.mock.calls.find(call => call[0] === 'devServerMessage');
|
|
135
|
+
if (addListenerCall) {
|
|
136
|
+
const callback = addListenerCall[1];
|
|
137
|
+
callback(LOCAL_DEV_SERVER_MESSAGE_TYPES.STATIC_AUTH_APP_INSTALL_SUCCESS);
|
|
138
|
+
}
|
|
139
|
+
}, 0);
|
|
140
|
+
return undefined;
|
|
141
|
+
});
|
|
131
142
|
confirmPrompt.mockResolvedValue(true);
|
|
132
143
|
installStaticAuthAppOnTestAccount.mockResolvedValue(undefined);
|
|
133
144
|
// Mock process.exit
|
|
@@ -189,12 +200,12 @@ describe('AppDevModeInterface', () => {
|
|
|
189
200
|
it('should return early if no app node exists', async () => {
|
|
190
201
|
mockLocalDevState.projectNodes = {};
|
|
191
202
|
await appDevModeInterface.setup({});
|
|
192
|
-
expect(
|
|
203
|
+
expect(fetchAppMetadataByUid).not.toHaveBeenCalled();
|
|
193
204
|
expect(UIEDevModeInterface.setup).not.toHaveBeenCalled();
|
|
194
205
|
});
|
|
195
206
|
it('should setup successfully with private app', async () => {
|
|
196
207
|
await appDevModeInterface.setup({});
|
|
197
|
-
expect(
|
|
208
|
+
expect(fetchAppMetadataByUid).toHaveBeenCalledWith('test-app-uid', 12345);
|
|
198
209
|
expect(fetchPublicAppProductionInstallCounts).toHaveBeenCalledWith(123, 12345);
|
|
199
210
|
expect(fetchAppInstallationData).toHaveBeenCalledWith(67890, 999, 'test-app-uid', ['test-scope'], []);
|
|
200
211
|
expect(UIEDevModeInterface.setup).toHaveBeenCalled();
|
|
@@ -240,21 +251,16 @@ describe('AppDevModeInterface', () => {
|
|
|
240
251
|
await newAppDevModeInterface.setup({});
|
|
241
252
|
expect(process.exit).toHaveBeenCalledWith(0);
|
|
242
253
|
});
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
// 123,
|
|
254
|
-
// 67890,
|
|
255
|
-
// [1, 2, 3]
|
|
256
|
-
// );
|
|
257
|
-
// });
|
|
254
|
+
it('should auto-install static auth app on test account', async () => {
|
|
255
|
+
fetchAppInstallationData.mockResolvedValue({
|
|
256
|
+
data: {
|
|
257
|
+
isInstalledWithScopeGroups: false,
|
|
258
|
+
previouslyAuthorizedScopeGroups: [],
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
await appDevModeInterface.setup({});
|
|
262
|
+
expect(installStaticAuthAppOnTestAccount).toHaveBeenCalledWith(123, 67890, [1, 2, 3]);
|
|
263
|
+
});
|
|
258
264
|
it('should open browser for OAuth app installation', async () => {
|
|
259
265
|
const oauthAppNode = {
|
|
260
266
|
...mockAppNode,
|
|
@@ -293,81 +299,47 @@ describe('AppDevModeInterface', () => {
|
|
|
293
299
|
},
|
|
294
300
|
});
|
|
295
301
|
await appDevModeInterface.setup({});
|
|
296
|
-
expect(installAppBrowserPrompt).toHaveBeenCalledWith('http://static-install-url', true
|
|
297
|
-
appUid: 'test-app-uid',
|
|
298
|
-
projectAccountId: 12345,
|
|
299
|
-
projectName: 'test-project',
|
|
300
|
-
testingAccountId: 67890,
|
|
301
|
-
});
|
|
302
|
+
expect(installAppBrowserPrompt).toHaveBeenCalledWith('http://static-install-url', true);
|
|
302
303
|
});
|
|
303
304
|
it('should handle errors during setup', async () => {
|
|
304
305
|
const error = new Error('Setup failed');
|
|
305
|
-
|
|
306
|
+
fetchAppMetadataByUid.mockRejectedValue(error);
|
|
306
307
|
await appDevModeInterface.setup({});
|
|
307
308
|
expect(logError).toHaveBeenCalledWith(error);
|
|
308
309
|
});
|
|
309
|
-
it('should exit if
|
|
310
|
-
// Set up conditions for
|
|
311
|
-
getAccountConfig.mockReturnValue(
|
|
312
|
-
|
|
313
|
-
fetchPublicAppsForPortal
|
|
314
|
-
.mockResolvedValueOnce({
|
|
315
|
-
data: { results: [mockPublicApp] },
|
|
316
|
-
})
|
|
317
|
-
// Second call for getAppInstallUrl fails (app not found)
|
|
318
|
-
.mockResolvedValueOnce({
|
|
319
|
-
data: { results: [] },
|
|
310
|
+
it('should exit if user declines auto-install', async () => {
|
|
311
|
+
// Set up conditions for automatic installation
|
|
312
|
+
getAccountConfig.mockReturnValue({
|
|
313
|
+
parentAccountId: 12345, // matches targetProjectAccountId
|
|
320
314
|
});
|
|
315
|
+
isDeveloperTestAccount.mockReturnValue(true);
|
|
321
316
|
fetchAppInstallationData.mockResolvedValue({
|
|
322
317
|
data: {
|
|
323
318
|
isInstalledWithScopeGroups: false,
|
|
324
319
|
previouslyAuthorizedScopeGroups: [],
|
|
325
320
|
},
|
|
326
321
|
});
|
|
322
|
+
installAppAutoPrompt.mockResolvedValue(false);
|
|
323
|
+
// Create a new instance to trigger the exit during setup
|
|
324
|
+
const newAppDevModeInterface = new AppDevModeInterface({
|
|
325
|
+
localDevState: mockLocalDevState,
|
|
326
|
+
localDevLogger: mockLocalDevLogger,
|
|
327
|
+
});
|
|
327
328
|
// The setup method catches the error, so we check that process.exit was called
|
|
329
|
+
await newAppDevModeInterface.setup({});
|
|
330
|
+
expect(process.exit).toHaveBeenCalledWith(0);
|
|
331
|
+
});
|
|
332
|
+
it('should fallback to browser install if auto-install fails', async () => {
|
|
333
|
+
fetchAppInstallationData.mockResolvedValue({
|
|
334
|
+
data: {
|
|
335
|
+
isInstalledWithScopeGroups: false,
|
|
336
|
+
previouslyAuthorizedScopeGroups: [],
|
|
337
|
+
},
|
|
338
|
+
});
|
|
339
|
+
installStaticAuthAppOnTestAccount.mockRejectedValue(new Error('Install failed'));
|
|
328
340
|
await appDevModeInterface.setup({});
|
|
329
|
-
expect(
|
|
330
|
-
});
|
|
331
|
-
// @TODO: Restore test account auto install functionality
|
|
332
|
-
// it('should exit if user declines auto-install', async () => {
|
|
333
|
-
// // Set up conditions for automatic installation
|
|
334
|
-
// (getAccountConfig as Mock).mockReturnValue({
|
|
335
|
-
// parentAccountId: 12345, // matches targetProjectAccountId
|
|
336
|
-
// });
|
|
337
|
-
// (isDeveloperTestAccount as Mock).mockReturnValue(true);
|
|
338
|
-
// (fetchAppInstallationData as Mock).mockResolvedValue({
|
|
339
|
-
// data: {
|
|
340
|
-
// isInstalledWithScopeGroups: false,
|
|
341
|
-
// previouslyAuthorizedScopeGroups: [],
|
|
342
|
-
// },
|
|
343
|
-
// });
|
|
344
|
-
// (installAppAutoPrompt as Mock).mockResolvedValue(false);
|
|
345
|
-
// // Create a new instance to trigger the exit during setup
|
|
346
|
-
// const newAppDevModeInterface = new AppDevModeInterface({
|
|
347
|
-
// localDevState: mockLocalDevState,
|
|
348
|
-
// localDevLogger: mockLocalDevLogger,
|
|
349
|
-
// });
|
|
350
|
-
// // The setup method catches the error, so we check that process.exit was called
|
|
351
|
-
// await newAppDevModeInterface.setup({});
|
|
352
|
-
// expect(process.exit).toHaveBeenCalledWith(0);
|
|
353
|
-
// });
|
|
354
|
-
// @TODO: Restore test account auto install functionality
|
|
355
|
-
// it('should fallback to browser install if auto-install fails', async () => {
|
|
356
|
-
// (fetchAppInstallationData as Mock).mockResolvedValue({
|
|
357
|
-
// data: {
|
|
358
|
-
// isInstalledWithScopeGroups: false,
|
|
359
|
-
// previouslyAuthorizedScopeGroups: [],
|
|
360
|
-
// },
|
|
361
|
-
// });
|
|
362
|
-
// (installStaticAuthAppOnTestAccount as Mock).mockRejectedValue(
|
|
363
|
-
// new Error('Install failed')
|
|
364
|
-
// );
|
|
365
|
-
// await appDevModeInterface.setup({});
|
|
366
|
-
// expect(installAppBrowserPrompt).toHaveBeenCalledWith(
|
|
367
|
-
// 'http://static-install-url',
|
|
368
|
-
// false
|
|
369
|
-
// );
|
|
370
|
-
// });
|
|
341
|
+
expect(installAppBrowserPrompt).toHaveBeenCalledWith('http://static-install-url', false);
|
|
342
|
+
});
|
|
371
343
|
});
|
|
372
344
|
describe('start()', () => {
|
|
373
345
|
it('should return early if no app node exists', async () => {
|
|
@@ -424,14 +396,21 @@ describe('AppDevModeInterface', () => {
|
|
|
424
396
|
// Reset mocks to ensure clean state
|
|
425
397
|
vi.clearAllMocks();
|
|
426
398
|
// Set up basic mocks
|
|
427
|
-
|
|
428
|
-
data:
|
|
399
|
+
fetchAppMetadataByUid.mockResolvedValue({
|
|
400
|
+
data: mockPublicApp,
|
|
429
401
|
});
|
|
430
402
|
fetchPublicAppProductionInstallCounts.mockResolvedValue({
|
|
431
403
|
data: { uniquePortalInstallCount: 5 },
|
|
432
404
|
});
|
|
433
405
|
getStaticAuthAppInstallUrl.mockReturnValue('http://static-install-url');
|
|
434
|
-
installAppBrowserPrompt.
|
|
406
|
+
installAppBrowserPrompt.mockImplementation(async () => {
|
|
407
|
+
const addListenerCall = mockLocalDevState.addListener.mock.calls.find(call => call[0] === 'devServerMessage');
|
|
408
|
+
if (addListenerCall) {
|
|
409
|
+
const callback = addListenerCall[1];
|
|
410
|
+
callback(LOCAL_DEV_SERVER_MESSAGE_TYPES.STATIC_AUTH_APP_INSTALL_SUCCESS);
|
|
411
|
+
}
|
|
412
|
+
return undefined;
|
|
413
|
+
});
|
|
435
414
|
// Reset the mock LocalDevState
|
|
436
415
|
mockLocalDevState.getAppDataByUid = vi.fn().mockReturnValue(mockAppData);
|
|
437
416
|
mockLocalDevState.setAppDataForUid = vi.fn();
|
|
@@ -457,14 +436,23 @@ describe('AppDevModeInterface', () => {
|
|
|
457
436
|
// Reset mocks to ensure clean state
|
|
458
437
|
vi.clearAllMocks();
|
|
459
438
|
// Set up basic mocks
|
|
460
|
-
|
|
461
|
-
data:
|
|
439
|
+
fetchAppMetadataByUid.mockResolvedValue({
|
|
440
|
+
data: mockPublicApp,
|
|
462
441
|
});
|
|
463
442
|
fetchPublicAppProductionInstallCounts.mockResolvedValue({
|
|
464
443
|
data: { uniquePortalInstallCount: 5 },
|
|
465
444
|
});
|
|
466
445
|
getOauthAppInstallUrl.mockReturnValue('http://oauth-install-url');
|
|
467
|
-
installAppBrowserPrompt.
|
|
446
|
+
installAppBrowserPrompt.mockImplementation(async () => {
|
|
447
|
+
setTimeout(() => {
|
|
448
|
+
const addListenerCall = mockLocalDevState.addListener.mock.calls.find(call => call[0] === 'devServerMessage');
|
|
449
|
+
if (addListenerCall) {
|
|
450
|
+
const callback = addListenerCall[1];
|
|
451
|
+
callback(LOCAL_DEV_SERVER_MESSAGE_TYPES.STATIC_AUTH_APP_INSTALL_SUCCESS);
|
|
452
|
+
}
|
|
453
|
+
}, 0);
|
|
454
|
+
return undefined;
|
|
455
|
+
});
|
|
468
456
|
// Reset the mock LocalDevState
|
|
469
457
|
mockLocalDevState.getAppDataByUid = vi.fn().mockReturnValue(mockAppData);
|
|
470
458
|
mockLocalDevState.setAppDataForUid = vi.fn();
|
|
@@ -501,14 +489,23 @@ describe('AppDevModeInterface', () => {
|
|
|
501
489
|
// Reset mocks to ensure clean state
|
|
502
490
|
vi.clearAllMocks();
|
|
503
491
|
// Set up basic mocks
|
|
504
|
-
|
|
505
|
-
data:
|
|
492
|
+
fetchAppMetadataByUid.mockResolvedValue({
|
|
493
|
+
data: mockPublicApp,
|
|
506
494
|
});
|
|
507
495
|
fetchPublicAppProductionInstallCounts.mockResolvedValue({
|
|
508
496
|
data: { uniquePortalInstallCount: 5 },
|
|
509
497
|
});
|
|
510
498
|
getStaticAuthAppInstallUrl.mockReturnValue('http://static-install-url');
|
|
511
|
-
installAppBrowserPrompt.
|
|
499
|
+
installAppBrowserPrompt.mockImplementation(async () => {
|
|
500
|
+
setTimeout(() => {
|
|
501
|
+
const addListenerCall = mockLocalDevState.addListener.mock.calls.find(call => call[0] === 'devServerMessage');
|
|
502
|
+
if (addListenerCall) {
|
|
503
|
+
const callback = addListenerCall[1];
|
|
504
|
+
callback(LOCAL_DEV_SERVER_MESSAGE_TYPES.STATIC_AUTH_APP_INSTALL_SUCCESS);
|
|
505
|
+
}
|
|
506
|
+
}, 0);
|
|
507
|
+
return undefined;
|
|
508
|
+
});
|
|
512
509
|
// Reset the mock LocalDevState
|
|
513
510
|
mockLocalDevState.getAppDataByUid = vi.fn().mockReturnValue(mockAppData);
|
|
514
511
|
mockLocalDevState.setAppDataForUid = vi.fn();
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import { translateForLocalDev } from '@hubspot/project-parsing-lib';
|
|
3
3
|
import { handleProjectUpload } from '../upload.js';
|
|
4
|
+
import { handleProjectDeploy } from '../deploy.js';
|
|
4
5
|
import { getProjectConfig } from '../config.js';
|
|
6
|
+
import { fetchProject } from '@hubspot/local-dev-lib/api/projects';
|
|
7
|
+
import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
|
|
5
8
|
import LocalDevProcess from '../localDev/LocalDevProcess.js';
|
|
6
9
|
import LocalDevLogger from '../localDev/LocalDevLogger.js';
|
|
7
|
-
import
|
|
10
|
+
import DevServerManager from '../localDev/DevServerManager.js';
|
|
8
11
|
import { ENVIRONMENTS } from '@hubspot/local-dev-lib/constants/environments';
|
|
9
12
|
import { vi } from 'vitest';
|
|
10
13
|
// Mock @hubspot/ui-extensions-dev-server
|
|
@@ -19,9 +22,12 @@ vi.mock('@hubspot/ui-extensions-dev-server', () => ({
|
|
|
19
22
|
vi.mock('open');
|
|
20
23
|
vi.mock('@hubspot/project-parsing-lib');
|
|
21
24
|
vi.mock('../upload');
|
|
25
|
+
vi.mock('../deploy');
|
|
22
26
|
vi.mock('../config');
|
|
27
|
+
vi.mock('@hubspot/local-dev-lib/api/projects');
|
|
28
|
+
vi.mock('@hubspot/local-dev-lib/errors/index');
|
|
23
29
|
vi.mock('../localDev/LocalDevLogger');
|
|
24
|
-
vi.mock('../localDev/
|
|
30
|
+
vi.mock('../localDev/DevServerManager');
|
|
25
31
|
// Tests for LocalDevProcess and LocalDevState
|
|
26
32
|
describe('LocalDevProcess', () => {
|
|
27
33
|
let mockLocalDevLogger;
|
|
@@ -37,11 +43,36 @@ describe('LocalDevProcess', () => {
|
|
|
37
43
|
projectConfig: mockProjectConfig,
|
|
38
44
|
targetProjectAccountId: 123,
|
|
39
45
|
targetTestingAccountId: 456,
|
|
40
|
-
|
|
46
|
+
projectData: {
|
|
47
|
+
id: 789,
|
|
48
|
+
name: 'test-project',
|
|
49
|
+
portalId: 123,
|
|
50
|
+
createdAt: 0,
|
|
51
|
+
deletedAt: 0,
|
|
52
|
+
isLocked: false,
|
|
53
|
+
updatedAt: 0,
|
|
54
|
+
latestBuild: {
|
|
55
|
+
activitySource: { type: 'HUBSPOT_USER', userId: 456 },
|
|
56
|
+
buildId: 123,
|
|
57
|
+
createdAt: '2023-01-01T00:00:00Z',
|
|
58
|
+
deployableState: 'DEPLOYABLE',
|
|
59
|
+
deployStatusTaskLocator: { id: 'task-123', links: [] },
|
|
60
|
+
enqueuedAt: '2023-01-01T00:00:00Z',
|
|
61
|
+
finishedAt: '2023-01-01T00:05:00Z',
|
|
62
|
+
isAutoDeployEnabled: false,
|
|
63
|
+
portalId: 123,
|
|
64
|
+
projectName: 'test-project',
|
|
65
|
+
startedAt: '2023-01-01T00:01:00Z',
|
|
66
|
+
status: 'SUCCESS',
|
|
67
|
+
subbuildStatuses: [],
|
|
68
|
+
uploadMessage: 'Build completed',
|
|
69
|
+
autoDeployId: 0,
|
|
70
|
+
platformVersion: '2025.2',
|
|
71
|
+
},
|
|
72
|
+
},
|
|
41
73
|
initialProjectNodes: {},
|
|
42
74
|
initialProjectProfileData: {},
|
|
43
75
|
env: ENVIRONMENTS.PROD,
|
|
44
|
-
projectName: 'test-project',
|
|
45
76
|
};
|
|
46
77
|
beforeEach(() => {
|
|
47
78
|
vi.clearAllMocks();
|
|
@@ -62,6 +93,9 @@ describe('LocalDevProcess', () => {
|
|
|
62
93
|
uploadSuccess: vi.fn(),
|
|
63
94
|
fileChangeError: vi.fn(),
|
|
64
95
|
uploadWarning: vi.fn(),
|
|
96
|
+
deployInitiated: vi.fn(),
|
|
97
|
+
deployError: vi.fn(),
|
|
98
|
+
deploySuccess: vi.fn(),
|
|
65
99
|
};
|
|
66
100
|
mockDevServerManager = {
|
|
67
101
|
setup: vi.fn().mockResolvedValue(undefined),
|
|
@@ -71,7 +105,9 @@ describe('LocalDevProcess', () => {
|
|
|
71
105
|
};
|
|
72
106
|
// Mock constructors
|
|
73
107
|
LocalDevLogger.mockImplementation(() => mockLocalDevLogger);
|
|
74
|
-
|
|
108
|
+
DevServerManager.mockImplementation(() => mockDevServerManager);
|
|
109
|
+
// Mock external functions
|
|
110
|
+
isHubSpotHttpError.mockReturnValue(false);
|
|
75
111
|
// Create process instance
|
|
76
112
|
process = new LocalDevProcess(mockOptions);
|
|
77
113
|
// Mock process.exit
|
|
@@ -141,9 +177,14 @@ describe('LocalDevProcess', () => {
|
|
|
141
177
|
handleProjectUpload.mockResolvedValue({
|
|
142
178
|
uploadError: new Error('Upload failed'),
|
|
143
179
|
});
|
|
144
|
-
const
|
|
180
|
+
const result = await process.uploadProject();
|
|
145
181
|
expect(mockLocalDevLogger.uploadError).toHaveBeenCalledWith(new Error('Upload failed'));
|
|
146
|
-
expect(
|
|
182
|
+
expect(result).toEqual({
|
|
183
|
+
uploadSuccess: false,
|
|
184
|
+
buildSuccess: false,
|
|
185
|
+
deploySuccess: false,
|
|
186
|
+
deployId: undefined,
|
|
187
|
+
});
|
|
147
188
|
});
|
|
148
189
|
it('should handle successful upload', async () => {
|
|
149
190
|
await process.handleConfigFileChange();
|
|
@@ -152,38 +193,120 @@ describe('LocalDevProcess', () => {
|
|
|
152
193
|
});
|
|
153
194
|
handleProjectUpload.mockResolvedValue({
|
|
154
195
|
uploadError: null,
|
|
196
|
+
result: {
|
|
197
|
+
deployResult: {
|
|
198
|
+
id: 'deploy-123',
|
|
199
|
+
deployId: 123,
|
|
200
|
+
status: 'SUCCESS',
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
fetchProject.mockResolvedValue({
|
|
205
|
+
data: {
|
|
206
|
+
id: 789,
|
|
207
|
+
name: 'test-project',
|
|
208
|
+
portalId: 123,
|
|
209
|
+
createdAt: 0,
|
|
210
|
+
deletedAt: 0,
|
|
211
|
+
isLocked: false,
|
|
212
|
+
updatedAt: 0,
|
|
213
|
+
latestBuild: { id: 'build-1', status: 'SUCCESS' },
|
|
214
|
+
deployedBuild: { id: 'build-1', status: 'SUCCESS' },
|
|
215
|
+
},
|
|
155
216
|
});
|
|
156
|
-
const
|
|
217
|
+
const result = await process.uploadProject();
|
|
218
|
+
expect(fetchProject).toHaveBeenCalledWith(mockOptions.targetProjectAccountId, mockOptions.projectConfig.name);
|
|
157
219
|
expect(mockLocalDevLogger.uploadSuccess).toHaveBeenCalled();
|
|
158
220
|
// @ts-expect-error accessing private property for testing
|
|
159
221
|
expect(process.state.uploadWarnings.size).toBe(0);
|
|
160
|
-
expect(
|
|
222
|
+
expect(result).toEqual({
|
|
223
|
+
uploadSuccess: true,
|
|
224
|
+
buildSuccess: true,
|
|
225
|
+
deploySuccess: true,
|
|
226
|
+
deployId: 123,
|
|
227
|
+
});
|
|
161
228
|
});
|
|
162
|
-
it('should reset projectNodesAtLastUpload', async () => {
|
|
163
|
-
const
|
|
164
|
-
|
|
229
|
+
it('should reset projectNodesAtLastUpload if deploy is successful', async () => {
|
|
230
|
+
const mockInitialNodes = {
|
|
231
|
+
node1: {
|
|
232
|
+
uid: 'node1',
|
|
233
|
+
componentType: 'APP',
|
|
234
|
+
localDev: {
|
|
235
|
+
componentRoot: '/test/path',
|
|
236
|
+
componentConfigPath: '/test/path/config.json',
|
|
237
|
+
configUpdatedSinceLastUpload: false,
|
|
238
|
+
},
|
|
239
|
+
componentDeps: {},
|
|
240
|
+
metaFilePath: '/test/path',
|
|
241
|
+
config: { name: 'Node 1' },
|
|
242
|
+
files: [],
|
|
243
|
+
},
|
|
244
|
+
};
|
|
245
|
+
const mockNewNodes = {
|
|
246
|
+
node1: {
|
|
247
|
+
uid: 'node2',
|
|
248
|
+
componentType: 'APP',
|
|
249
|
+
localDev: {
|
|
250
|
+
componentRoot: '/test/path',
|
|
251
|
+
componentConfigPath: '/test/path/config.json',
|
|
252
|
+
configUpdatedSinceLastUpload: false,
|
|
253
|
+
},
|
|
254
|
+
componentDeps: {},
|
|
255
|
+
metaFilePath: '/test/path',
|
|
256
|
+
config: { name: 'Node 2' },
|
|
257
|
+
files: [],
|
|
258
|
+
},
|
|
259
|
+
};
|
|
165
260
|
// @ts-expect-error accessing private property for testing
|
|
166
|
-
process.state.
|
|
261
|
+
process.state.projectNodesAtLastDeploy = mockInitialNodes;
|
|
167
262
|
getProjectConfig.mockResolvedValue({
|
|
168
263
|
projectConfig: mockOptions.projectConfig,
|
|
169
264
|
});
|
|
170
265
|
handleProjectUpload.mockResolvedValue({
|
|
171
266
|
uploadError: null,
|
|
267
|
+
result: {
|
|
268
|
+
deployResult: {
|
|
269
|
+
id: 'deploy-123',
|
|
270
|
+
deployId: 456,
|
|
271
|
+
status: 'SUCCESS',
|
|
272
|
+
},
|
|
273
|
+
},
|
|
172
274
|
});
|
|
173
275
|
translateForLocalDev.mockResolvedValue({
|
|
174
|
-
intermediateNodesIndexedByUid:
|
|
276
|
+
intermediateNodesIndexedByUid: mockNewNodes,
|
|
175
277
|
});
|
|
176
|
-
|
|
177
|
-
|
|
278
|
+
fetchProject.mockResolvedValue({
|
|
279
|
+
data: {
|
|
280
|
+
id: 789,
|
|
281
|
+
name: 'test-project',
|
|
282
|
+
portalId: 123,
|
|
283
|
+
createdAt: 0,
|
|
284
|
+
deletedAt: 0,
|
|
285
|
+
isLocked: false,
|
|
286
|
+
updatedAt: 0,
|
|
287
|
+
latestBuild: { id: 'build-1', status: 'SUCCESS' },
|
|
288
|
+
deployedBuild: { id: 'build-1', status: 'SUCCESS' },
|
|
289
|
+
},
|
|
290
|
+
});
|
|
291
|
+
const result = await process.uploadProject();
|
|
292
|
+
// Verify translateForLocalDev was called during updateProjectNodesAfterDeploy
|
|
178
293
|
expect(translateForLocalDev).toHaveBeenCalledWith({
|
|
179
294
|
projectSourceDir: path.join(mockOptions.projectDir, mockOptions.projectConfig.srcDir),
|
|
180
295
|
platformVersion: mockOptions.projectConfig.platformVersion,
|
|
181
296
|
accountId: mockOptions.targetProjectAccountId,
|
|
182
|
-
}, {
|
|
297
|
+
}, {
|
|
298
|
+
profile: undefined,
|
|
299
|
+
projectNodesAtLastUpload: undefined,
|
|
300
|
+
});
|
|
183
301
|
// Verify projectNodesAtLastUpload was reset to the new nodes
|
|
184
302
|
// @ts-expect-error accessing private property for testing
|
|
185
|
-
expect(process.state.
|
|
186
|
-
expect(
|
|
303
|
+
expect(process.state.projectNodesAtLastDeploy).toEqual(mockNewNodes);
|
|
304
|
+
expect(result).toEqual({
|
|
305
|
+
uploadSuccess: true,
|
|
306
|
+
buildSuccess: true,
|
|
307
|
+
deploySuccess: true,
|
|
308
|
+
deployId: 456,
|
|
309
|
+
});
|
|
187
310
|
});
|
|
188
311
|
});
|
|
189
312
|
describe('handleFileChange()', () => {
|
|
@@ -252,4 +375,93 @@ describe('LocalDevProcess', () => {
|
|
|
252
375
|
expect(listener).toHaveBeenCalledTimes(1);
|
|
253
376
|
});
|
|
254
377
|
});
|
|
378
|
+
describe('deployLatestBuild()', () => {
|
|
379
|
+
beforeEach(() => {
|
|
380
|
+
vi.clearAllMocks();
|
|
381
|
+
});
|
|
382
|
+
it('should successfully deploy latest build', async () => {
|
|
383
|
+
const mockDeploy = {
|
|
384
|
+
deployId: 456,
|
|
385
|
+
buildId: 123,
|
|
386
|
+
status: 'SUCCESS',
|
|
387
|
+
enqueuedAt: '2023-01-01T00:00:00Z',
|
|
388
|
+
startedAt: '2023-01-01T00:01:00Z',
|
|
389
|
+
finishedAt: '2023-01-01T00:05:00Z',
|
|
390
|
+
portalId: 123,
|
|
391
|
+
projectName: 'test-project',
|
|
392
|
+
userId: 789,
|
|
393
|
+
source: 'HUBSPOT_USER',
|
|
394
|
+
subdeployStatuses: [],
|
|
395
|
+
};
|
|
396
|
+
handleProjectDeploy.mockResolvedValue(mockDeploy);
|
|
397
|
+
const result = await process.deployLatestBuild();
|
|
398
|
+
expect(mockLocalDevLogger.deployInitiated).toHaveBeenCalled();
|
|
399
|
+
expect(handleProjectDeploy).toHaveBeenCalledWith(123, // targetProjectAccountId
|
|
400
|
+
'test-project', // projectName
|
|
401
|
+
123, // buildId
|
|
402
|
+
true, // useV2Api
|
|
403
|
+
false // force
|
|
404
|
+
);
|
|
405
|
+
expect(mockLocalDevLogger.deploySuccess).toHaveBeenCalled();
|
|
406
|
+
expect(result).toEqual({
|
|
407
|
+
success: true,
|
|
408
|
+
deployId: 456,
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
it('should deploy with force parameter', async () => {
|
|
412
|
+
const mockDeploy = {
|
|
413
|
+
deployId: 456,
|
|
414
|
+
buildId: 123,
|
|
415
|
+
status: 'SUCCESS',
|
|
416
|
+
enqueuedAt: '2023-01-01T00:00:00Z',
|
|
417
|
+
startedAt: '2023-01-01T00:01:00Z',
|
|
418
|
+
finishedAt: '2023-01-01T00:05:00Z',
|
|
419
|
+
portalId: 123,
|
|
420
|
+
projectName: 'test-project',
|
|
421
|
+
userId: 789,
|
|
422
|
+
source: 'HUBSPOT_USER',
|
|
423
|
+
subdeployStatuses: [],
|
|
424
|
+
};
|
|
425
|
+
handleProjectDeploy.mockResolvedValue(mockDeploy);
|
|
426
|
+
const result = await process.deployLatestBuild(true);
|
|
427
|
+
expect(handleProjectDeploy).toHaveBeenCalledWith(123, // targetProjectAccountId
|
|
428
|
+
'test-project', // projectName
|
|
429
|
+
123, // buildId
|
|
430
|
+
true, // useV2Api
|
|
431
|
+
true // force
|
|
432
|
+
);
|
|
433
|
+
expect(result).toEqual({
|
|
434
|
+
success: true,
|
|
435
|
+
deployId: 456,
|
|
436
|
+
});
|
|
437
|
+
});
|
|
438
|
+
it('should return error when no build exists', async () => {
|
|
439
|
+
// Create a process without latestBuild
|
|
440
|
+
const optionsWithoutBuild = {
|
|
441
|
+
...mockOptions,
|
|
442
|
+
projectData: {
|
|
443
|
+
...mockOptions.projectData,
|
|
444
|
+
latestBuild: undefined,
|
|
445
|
+
},
|
|
446
|
+
};
|
|
447
|
+
const processWithoutBuild = new LocalDevProcess(optionsWithoutBuild);
|
|
448
|
+
const result = await processWithoutBuild.deployLatestBuild();
|
|
449
|
+
expect(mockLocalDevLogger.deployInitiated).toHaveBeenCalled();
|
|
450
|
+
expect(mockLocalDevLogger.deployError).toHaveBeenCalledWith('Error deploying project. No build was found to deploy.');
|
|
451
|
+
expect(result).toEqual({
|
|
452
|
+
success: false,
|
|
453
|
+
});
|
|
454
|
+
expect(handleProjectDeploy).not.toHaveBeenCalled();
|
|
455
|
+
});
|
|
456
|
+
it('should handle deploy failure when no deploy object returned', async () => {
|
|
457
|
+
handleProjectDeploy.mockResolvedValue(undefined);
|
|
458
|
+
const result = await process.deployLatestBuild();
|
|
459
|
+
expect(mockLocalDevLogger.deployInitiated).toHaveBeenCalled();
|
|
460
|
+
expect(handleProjectDeploy).toHaveBeenCalled();
|
|
461
|
+
expect(result).toEqual({
|
|
462
|
+
success: false,
|
|
463
|
+
});
|
|
464
|
+
expect(mockLocalDevLogger.deploySuccess).not.toHaveBeenCalled();
|
|
465
|
+
});
|
|
466
|
+
});
|
|
255
467
|
});
|