@hubspot/cli 7.7.35-experimental.0 → 7.8.0-beta.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 +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 +0 -3
- 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 +16 -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 +7 -12
- 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 +4 -2
- 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__/logs.test.js +1 -4
- package/commands/project/__tests__/migrate.test.js +6 -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.js +4 -8
- package/commands/project/cloneApp.js +14 -19
- package/commands/project/create.js +2 -9
- package/commands/project/deploy.js +5 -5
- package/commands/project/dev/deprecatedFlow.js +7 -16
- package/commands/project/dev/index.js +16 -13
- package/commands/project/dev/unifiedFlow.js +8 -4
- package/commands/project/download.js +10 -14
- package/commands/project/installDeps.js +8 -9
- package/commands/project/listBuilds.js +12 -21
- package/commands/project/logs.js +21 -24
- package/commands/project/migrate.js +41 -13
- 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 +2 -3
- package/commands/sandbox/__tests__/create.test.js +5 -5
- package/commands/sandbox/create.js +22 -32
- package/commands/sandbox/delete.js +35 -63
- 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/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/lang/en.d.ts +317 -98
- package/lang/en.js +312 -96
- package/lang/en.lyaml +2 -2
- package/lib/__tests__/buildAccount.test.js +2 -1
- 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 +5 -80
- package/lib/app/migrate_legacy.js +20 -24
- package/lib/buildAccount.js +25 -57
- package/lib/commonOpts.d.ts +1 -1
- package/lib/commonOpts.js +25 -22
- package/lib/configOptions.js +7 -0
- package/lib/constants.d.ts +13 -0
- package/lib/constants.js +17 -0
- 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 +10 -17
- 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.d.ts +1 -0
- 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 +78 -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 +2 -0
- package/lib/projects/__tests__/LocalDevProcess.test.js +227 -16
- package/lib/projects/__tests__/LocalDevWebsocketServer.test.js +86 -60
- package/lib/projects/__tests__/deploy.test.js +71 -6
- 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__/v3AddComponent.test.js +4 -4
- package/lib/projects/create/__tests__/legacy.test.js +5 -5
- package/lib/projects/create/__tests__/v3.test.js +80 -5
- package/lib/projects/create/index.js +2 -2
- package/lib/projects/create/legacy.js +2 -2
- package/lib/projects/create/v3.js +10 -8
- package/lib/projects/localDev/AppDevModeInterface.d.ts +2 -0
- package/lib/projects/localDev/AppDevModeInterface.js +21 -12
- package/lib/projects/localDev/LocalDevLogger.d.ts +4 -0
- package/lib/projects/localDev/LocalDevLogger.js +27 -6
- package/lib/projects/localDev/LocalDevManager.js +4 -5
- package/lib/projects/localDev/LocalDevProcess.d.ts +7 -5
- package/lib/projects/localDev/LocalDevProcess.js +90 -19
- package/lib/projects/localDev/LocalDevState.d.ts +9 -8
- package/lib/projects/localDev/LocalDevState.js +18 -17
- package/lib/projects/localDev/LocalDevWebsocketServer.d.ts +2 -1
- package/lib/projects/localDev/LocalDevWebsocketServer.js +62 -33
- package/lib/projects/localDev/helpers/project.d.ts +1 -0
- package/lib/projects/localDev/helpers/project.js +42 -1
- package/lib/projects/localDev/localDevWebsocketServerUtils.d.ts +4 -0
- package/lib/projects/localDev/localDevWebsocketServerUtils.js +10 -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/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/personalAccessKeyPrompt.js +3 -3
- package/lib/prompts/previewPrompt.js +6 -6
- package/lib/prompts/projectAddPrompt.js +8 -1
- 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.js +38 -37
- package/lib/ui/serverlessFunctionLogs.js +9 -7
- package/lib/ui/uiMessages.d.ts +68 -0
- package/lib/ui/uiMessages.js +71 -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__/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 +4 -4
- 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/middleware/__test__/utils.test.d.ts → commands/project/__tests__/validate.test.d.ts} +0 -0
|
@@ -1,7 +1,10 @@
|
|
|
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
10
|
import DevServerManagerV2 from '../localDev/DevServerManagerV2.js';
|
|
@@ -19,7 +22,10 @@ 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
30
|
vi.mock('../localDev/DevServerManagerV2');
|
|
25
31
|
// Tests for LocalDevProcess and LocalDevState
|
|
@@ -37,11 +43,35 @@ 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
|
+
},
|
|
71
|
+
},
|
|
41
72
|
initialProjectNodes: {},
|
|
42
73
|
initialProjectProfileData: {},
|
|
43
74
|
env: ENVIRONMENTS.PROD,
|
|
44
|
-
projectName: 'test-project',
|
|
45
75
|
};
|
|
46
76
|
beforeEach(() => {
|
|
47
77
|
vi.clearAllMocks();
|
|
@@ -62,6 +92,9 @@ describe('LocalDevProcess', () => {
|
|
|
62
92
|
uploadSuccess: vi.fn(),
|
|
63
93
|
fileChangeError: vi.fn(),
|
|
64
94
|
uploadWarning: vi.fn(),
|
|
95
|
+
deployInitiated: vi.fn(),
|
|
96
|
+
deployError: vi.fn(),
|
|
97
|
+
deploySuccess: vi.fn(),
|
|
65
98
|
};
|
|
66
99
|
mockDevServerManager = {
|
|
67
100
|
setup: vi.fn().mockResolvedValue(undefined),
|
|
@@ -72,6 +105,8 @@ describe('LocalDevProcess', () => {
|
|
|
72
105
|
// Mock constructors
|
|
73
106
|
LocalDevLogger.mockImplementation(() => mockLocalDevLogger);
|
|
74
107
|
DevServerManagerV2.mockImplementation(() => mockDevServerManager);
|
|
108
|
+
// Mock external functions
|
|
109
|
+
isHubSpotHttpError.mockReturnValue(false);
|
|
75
110
|
// Create process instance
|
|
76
111
|
process = new LocalDevProcess(mockOptions);
|
|
77
112
|
// Mock process.exit
|
|
@@ -141,9 +176,14 @@ describe('LocalDevProcess', () => {
|
|
|
141
176
|
handleProjectUpload.mockResolvedValue({
|
|
142
177
|
uploadError: new Error('Upload failed'),
|
|
143
178
|
});
|
|
144
|
-
const
|
|
179
|
+
const result = await process.uploadProject();
|
|
145
180
|
expect(mockLocalDevLogger.uploadError).toHaveBeenCalledWith(new Error('Upload failed'));
|
|
146
|
-
expect(
|
|
181
|
+
expect(result).toEqual({
|
|
182
|
+
uploadSuccess: false,
|
|
183
|
+
buildSuccess: false,
|
|
184
|
+
deploySuccess: false,
|
|
185
|
+
deployId: undefined,
|
|
186
|
+
});
|
|
147
187
|
});
|
|
148
188
|
it('should handle successful upload', async () => {
|
|
149
189
|
await process.handleConfigFileChange();
|
|
@@ -152,38 +192,120 @@ describe('LocalDevProcess', () => {
|
|
|
152
192
|
});
|
|
153
193
|
handleProjectUpload.mockResolvedValue({
|
|
154
194
|
uploadError: null,
|
|
195
|
+
result: {
|
|
196
|
+
deployResult: {
|
|
197
|
+
id: 'deploy-123',
|
|
198
|
+
deployId: 123,
|
|
199
|
+
status: 'SUCCESS',
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
fetchProject.mockResolvedValue({
|
|
204
|
+
data: {
|
|
205
|
+
id: 789,
|
|
206
|
+
name: 'test-project',
|
|
207
|
+
portalId: 123,
|
|
208
|
+
createdAt: 0,
|
|
209
|
+
deletedAt: 0,
|
|
210
|
+
isLocked: false,
|
|
211
|
+
updatedAt: 0,
|
|
212
|
+
latestBuild: { id: 'build-1', status: 'SUCCESS' },
|
|
213
|
+
deployedBuild: { id: 'build-1', status: 'SUCCESS' },
|
|
214
|
+
},
|
|
155
215
|
});
|
|
156
|
-
const
|
|
216
|
+
const result = await process.uploadProject();
|
|
217
|
+
expect(fetchProject).toHaveBeenCalledWith(mockOptions.targetProjectAccountId, mockOptions.projectConfig.name);
|
|
157
218
|
expect(mockLocalDevLogger.uploadSuccess).toHaveBeenCalled();
|
|
158
219
|
// @ts-expect-error accessing private property for testing
|
|
159
220
|
expect(process.state.uploadWarnings.size).toBe(0);
|
|
160
|
-
expect(
|
|
221
|
+
expect(result).toEqual({
|
|
222
|
+
uploadSuccess: true,
|
|
223
|
+
buildSuccess: true,
|
|
224
|
+
deploySuccess: true,
|
|
225
|
+
deployId: 123,
|
|
226
|
+
});
|
|
161
227
|
});
|
|
162
|
-
it('should reset projectNodesAtLastUpload', async () => {
|
|
163
|
-
const
|
|
164
|
-
|
|
228
|
+
it('should reset projectNodesAtLastUpload if deploy is successful', async () => {
|
|
229
|
+
const mockInitialNodes = {
|
|
230
|
+
node1: {
|
|
231
|
+
uid: 'node1',
|
|
232
|
+
componentType: 'APP',
|
|
233
|
+
localDev: {
|
|
234
|
+
componentRoot: '/test/path',
|
|
235
|
+
componentConfigPath: '/test/path/config.json',
|
|
236
|
+
configUpdatedSinceLastUpload: false,
|
|
237
|
+
},
|
|
238
|
+
componentDeps: {},
|
|
239
|
+
metaFilePath: '/test/path',
|
|
240
|
+
config: { name: 'Node 1' },
|
|
241
|
+
files: [],
|
|
242
|
+
},
|
|
243
|
+
};
|
|
244
|
+
const mockNewNodes = {
|
|
245
|
+
node1: {
|
|
246
|
+
uid: 'node2',
|
|
247
|
+
componentType: 'APP',
|
|
248
|
+
localDev: {
|
|
249
|
+
componentRoot: '/test/path',
|
|
250
|
+
componentConfigPath: '/test/path/config.json',
|
|
251
|
+
configUpdatedSinceLastUpload: false,
|
|
252
|
+
},
|
|
253
|
+
componentDeps: {},
|
|
254
|
+
metaFilePath: '/test/path',
|
|
255
|
+
config: { name: 'Node 2' },
|
|
256
|
+
files: [],
|
|
257
|
+
},
|
|
258
|
+
};
|
|
165
259
|
// @ts-expect-error accessing private property for testing
|
|
166
|
-
process.state.
|
|
260
|
+
process.state.projectNodesAtLastDeploy = mockInitialNodes;
|
|
167
261
|
getProjectConfig.mockResolvedValue({
|
|
168
262
|
projectConfig: mockOptions.projectConfig,
|
|
169
263
|
});
|
|
170
264
|
handleProjectUpload.mockResolvedValue({
|
|
171
265
|
uploadError: null,
|
|
266
|
+
result: {
|
|
267
|
+
deployResult: {
|
|
268
|
+
id: 'deploy-123',
|
|
269
|
+
deployId: 456,
|
|
270
|
+
status: 'SUCCESS',
|
|
271
|
+
},
|
|
272
|
+
},
|
|
172
273
|
});
|
|
173
274
|
translateForLocalDev.mockResolvedValue({
|
|
174
|
-
intermediateNodesIndexedByUid:
|
|
275
|
+
intermediateNodesIndexedByUid: mockNewNodes,
|
|
175
276
|
});
|
|
176
|
-
|
|
177
|
-
|
|
277
|
+
fetchProject.mockResolvedValue({
|
|
278
|
+
data: {
|
|
279
|
+
id: 789,
|
|
280
|
+
name: 'test-project',
|
|
281
|
+
portalId: 123,
|
|
282
|
+
createdAt: 0,
|
|
283
|
+
deletedAt: 0,
|
|
284
|
+
isLocked: false,
|
|
285
|
+
updatedAt: 0,
|
|
286
|
+
latestBuild: { id: 'build-1', status: 'SUCCESS' },
|
|
287
|
+
deployedBuild: { id: 'build-1', status: 'SUCCESS' },
|
|
288
|
+
},
|
|
289
|
+
});
|
|
290
|
+
const result = await process.uploadProject();
|
|
291
|
+
// Verify translateForLocalDev was called during updateProjectNodesAfterDeploy
|
|
178
292
|
expect(translateForLocalDev).toHaveBeenCalledWith({
|
|
179
293
|
projectSourceDir: path.join(mockOptions.projectDir, mockOptions.projectConfig.srcDir),
|
|
180
294
|
platformVersion: mockOptions.projectConfig.platformVersion,
|
|
181
295
|
accountId: mockOptions.targetProjectAccountId,
|
|
182
|
-
}, {
|
|
296
|
+
}, {
|
|
297
|
+
profile: undefined,
|
|
298
|
+
projectNodesAtLastUpload: undefined,
|
|
299
|
+
});
|
|
183
300
|
// Verify projectNodesAtLastUpload was reset to the new nodes
|
|
184
301
|
// @ts-expect-error accessing private property for testing
|
|
185
|
-
expect(process.state.
|
|
186
|
-
expect(
|
|
302
|
+
expect(process.state.projectNodesAtLastDeploy).toEqual(mockNewNodes);
|
|
303
|
+
expect(result).toEqual({
|
|
304
|
+
uploadSuccess: true,
|
|
305
|
+
buildSuccess: true,
|
|
306
|
+
deploySuccess: true,
|
|
307
|
+
deployId: 456,
|
|
308
|
+
});
|
|
187
309
|
});
|
|
188
310
|
});
|
|
189
311
|
describe('handleFileChange()', () => {
|
|
@@ -252,4 +374,93 @@ describe('LocalDevProcess', () => {
|
|
|
252
374
|
expect(listener).toHaveBeenCalledTimes(1);
|
|
253
375
|
});
|
|
254
376
|
});
|
|
377
|
+
describe('deployLatestBuild()', () => {
|
|
378
|
+
beforeEach(() => {
|
|
379
|
+
vi.clearAllMocks();
|
|
380
|
+
});
|
|
381
|
+
it('should successfully deploy latest build', async () => {
|
|
382
|
+
const mockDeploy = {
|
|
383
|
+
deployId: 456,
|
|
384
|
+
buildId: 123,
|
|
385
|
+
status: 'SUCCESS',
|
|
386
|
+
enqueuedAt: '2023-01-01T00:00:00Z',
|
|
387
|
+
startedAt: '2023-01-01T00:01:00Z',
|
|
388
|
+
finishedAt: '2023-01-01T00:05:00Z',
|
|
389
|
+
portalId: 123,
|
|
390
|
+
projectName: 'test-project',
|
|
391
|
+
userId: 789,
|
|
392
|
+
source: 'HUBSPOT_USER',
|
|
393
|
+
subdeployStatuses: [],
|
|
394
|
+
};
|
|
395
|
+
handleProjectDeploy.mockResolvedValue(mockDeploy);
|
|
396
|
+
const result = await process.deployLatestBuild();
|
|
397
|
+
expect(mockLocalDevLogger.deployInitiated).toHaveBeenCalled();
|
|
398
|
+
expect(handleProjectDeploy).toHaveBeenCalledWith(123, // targetProjectAccountId
|
|
399
|
+
'test-project', // projectName
|
|
400
|
+
123, // buildId
|
|
401
|
+
true, // useV3Api
|
|
402
|
+
false // force
|
|
403
|
+
);
|
|
404
|
+
expect(mockLocalDevLogger.deploySuccess).toHaveBeenCalled();
|
|
405
|
+
expect(result).toEqual({
|
|
406
|
+
success: true,
|
|
407
|
+
deployId: 456,
|
|
408
|
+
});
|
|
409
|
+
});
|
|
410
|
+
it('should deploy with force parameter', async () => {
|
|
411
|
+
const mockDeploy = {
|
|
412
|
+
deployId: 456,
|
|
413
|
+
buildId: 123,
|
|
414
|
+
status: 'SUCCESS',
|
|
415
|
+
enqueuedAt: '2023-01-01T00:00:00Z',
|
|
416
|
+
startedAt: '2023-01-01T00:01:00Z',
|
|
417
|
+
finishedAt: '2023-01-01T00:05:00Z',
|
|
418
|
+
portalId: 123,
|
|
419
|
+
projectName: 'test-project',
|
|
420
|
+
userId: 789,
|
|
421
|
+
source: 'HUBSPOT_USER',
|
|
422
|
+
subdeployStatuses: [],
|
|
423
|
+
};
|
|
424
|
+
handleProjectDeploy.mockResolvedValue(mockDeploy);
|
|
425
|
+
const result = await process.deployLatestBuild(true);
|
|
426
|
+
expect(handleProjectDeploy).toHaveBeenCalledWith(123, // targetProjectAccountId
|
|
427
|
+
'test-project', // projectName
|
|
428
|
+
123, // buildId
|
|
429
|
+
true, // useV3Api
|
|
430
|
+
true // force
|
|
431
|
+
);
|
|
432
|
+
expect(result).toEqual({
|
|
433
|
+
success: true,
|
|
434
|
+
deployId: 456,
|
|
435
|
+
});
|
|
436
|
+
});
|
|
437
|
+
it('should return error when no build exists', async () => {
|
|
438
|
+
// Create a process without latestBuild
|
|
439
|
+
const optionsWithoutBuild = {
|
|
440
|
+
...mockOptions,
|
|
441
|
+
projectData: {
|
|
442
|
+
...mockOptions.projectData,
|
|
443
|
+
latestBuild: undefined,
|
|
444
|
+
},
|
|
445
|
+
};
|
|
446
|
+
const processWithoutBuild = new LocalDevProcess(optionsWithoutBuild);
|
|
447
|
+
const result = await processWithoutBuild.deployLatestBuild();
|
|
448
|
+
expect(mockLocalDevLogger.deployInitiated).toHaveBeenCalled();
|
|
449
|
+
expect(mockLocalDevLogger.deployError).toHaveBeenCalledWith('Error deploying project. No build was found to deploy.');
|
|
450
|
+
expect(result).toEqual({
|
|
451
|
+
success: false,
|
|
452
|
+
});
|
|
453
|
+
expect(handleProjectDeploy).not.toHaveBeenCalled();
|
|
454
|
+
});
|
|
455
|
+
it('should handle deploy failure when no deploy object returned', async () => {
|
|
456
|
+
handleProjectDeploy.mockResolvedValue(undefined);
|
|
457
|
+
const result = await process.deployLatestBuild();
|
|
458
|
+
expect(mockLocalDevLogger.deployInitiated).toHaveBeenCalled();
|
|
459
|
+
expect(handleProjectDeploy).toHaveBeenCalled();
|
|
460
|
+
expect(result).toEqual({
|
|
461
|
+
success: false,
|
|
462
|
+
});
|
|
463
|
+
expect(mockLocalDevLogger.deploySuccess).not.toHaveBeenCalled();
|
|
464
|
+
});
|
|
465
|
+
});
|
|
255
466
|
});
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { WebSocketServer } from 'ws';
|
|
2
2
|
import { isPortManagerServerRunning, requestPorts, } from '@hubspot/local-dev-lib/portManager';
|
|
3
|
-
import {
|
|
3
|
+
import { uiLogger } from '../../ui/logger.js';
|
|
4
4
|
import { LOCAL_DEV_UI_MESSAGE_RECEIVE_TYPES, LOCAL_DEV_UI_MESSAGE_SEND_TYPES, LOCAL_DEV_SERVER_MESSAGE_TYPES, } from '../../constants.js';
|
|
5
5
|
import LocalDevWebsocketServer from '../localDev/LocalDevWebsocketServer.js';
|
|
6
6
|
import { lib } from '../../../lang/en.js';
|
|
7
7
|
vi.mock('ws');
|
|
8
8
|
vi.mock('@hubspot/local-dev-lib/portManager');
|
|
9
|
-
vi.mock('
|
|
9
|
+
vi.mock('../../ui/logger.js');
|
|
10
10
|
describe('LocalDevWebsocketServer', () => {
|
|
11
11
|
let mockLocalDevProcess;
|
|
12
12
|
let mockWebSocket;
|
|
@@ -30,8 +30,16 @@ describe('LocalDevWebsocketServer', () => {
|
|
|
30
30
|
mockLocalDevProcess = {
|
|
31
31
|
addStateListener: vi.fn(),
|
|
32
32
|
removeStateListener: vi.fn(),
|
|
33
|
-
uploadProject: vi.fn(),
|
|
33
|
+
uploadProject: vi.fn().mockResolvedValue({}),
|
|
34
34
|
sendDevServerMessage: vi.fn(),
|
|
35
|
+
projectData: {
|
|
36
|
+
name: 'test-project',
|
|
37
|
+
id: 123,
|
|
38
|
+
latestBuild: { id: 'build-1', status: 'SUCCESS' },
|
|
39
|
+
deployedBuild: { id: 'build-1', status: 'SUCCESS' },
|
|
40
|
+
},
|
|
41
|
+
targetProjectAccountId: 456,
|
|
42
|
+
targetTestingAccountId: 789,
|
|
35
43
|
};
|
|
36
44
|
// Mock WebSocketServer constructor
|
|
37
45
|
WebSocketServer.mockImplementation(() => mockWebSocketServer);
|
|
@@ -51,39 +59,68 @@ describe('LocalDevWebsocketServer', () => {
|
|
|
51
59
|
await server.start();
|
|
52
60
|
expect(WebSocketServer).toHaveBeenCalledWith({ port: 1234 });
|
|
53
61
|
expect(mockWebSocketServer.on).toHaveBeenCalledWith('connection', expect.any(Function));
|
|
54
|
-
expect(
|
|
62
|
+
expect(uiLogger.log).toHaveBeenCalled();
|
|
55
63
|
});
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
'
|
|
64
|
+
describe('valid origins', () => {
|
|
65
|
+
const validOrigins = [
|
|
66
|
+
'https://app.hubspot.com',
|
|
67
|
+
'https://app.hubspotqa.com',
|
|
68
|
+
'https://local.hubspot.com',
|
|
69
|
+
'https://local.hubspotqa.com',
|
|
70
|
+
'https://app-na2.hubspot.com',
|
|
71
|
+
'https://app-na2.hubspotqa.com',
|
|
72
|
+
'https://app-na3.hubspot.com',
|
|
73
|
+
'https://app-na3.hubspotqa.com',
|
|
74
|
+
'https://app-ap1.hubspot.com',
|
|
75
|
+
'https://app-ap1.hubspotqa.com',
|
|
76
|
+
'https://app-eu1.hubspot.com',
|
|
77
|
+
'https://app-eu1.hubspotqa.com',
|
|
78
|
+
];
|
|
79
|
+
validOrigins.forEach(origin => {
|
|
80
|
+
it(`should accept connection from ${origin}`, async () => {
|
|
81
|
+
isPortManagerServerRunning.mockResolvedValue(true);
|
|
82
|
+
requestPorts.mockResolvedValue({
|
|
83
|
+
'local-dev-ui-websocket-server': 1234,
|
|
84
|
+
});
|
|
85
|
+
await server.start();
|
|
86
|
+
// Get the connection callback
|
|
87
|
+
const connectionCallback = mockWebSocketServer.on.mock
|
|
88
|
+
.calls[0][1];
|
|
89
|
+
// Simulate connection from valid origin
|
|
90
|
+
connectionCallback(mockWebSocket, {
|
|
91
|
+
headers: { origin },
|
|
92
|
+
});
|
|
93
|
+
expect(mockWebSocket.on).toHaveBeenCalledWith('message', expect.any(Function));
|
|
94
|
+
expect(mockLocalDevProcess.addStateListener).toHaveBeenCalledWith('projectNodes', expect.any(Function));
|
|
95
|
+
expect(mockWebSocket.close).not.toHaveBeenCalled();
|
|
96
|
+
});
|
|
60
97
|
});
|
|
61
|
-
await server.start();
|
|
62
|
-
// Get the connection callback
|
|
63
|
-
const connectionCallback = mockWebSocketServer.on.mock.calls[0][1];
|
|
64
|
-
// Simulate connection from valid origin
|
|
65
|
-
connectionCallback(mockWebSocket, {
|
|
66
|
-
headers: { origin: 'https://app.hubspot.com' },
|
|
67
|
-
});
|
|
68
|
-
expect(mockWebSocket.on).toHaveBeenCalledWith('message', expect.any(Function));
|
|
69
|
-
expect(mockLocalDevProcess.addStateListener).toHaveBeenCalledWith('projectNodes', expect.any(Function));
|
|
70
|
-
expect(mockWebSocket.close).not.toHaveBeenCalled();
|
|
71
98
|
});
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
'
|
|
99
|
+
describe('invalid origins', () => {
|
|
100
|
+
const invalidOrigins = [
|
|
101
|
+
'https://malicious-site.com',
|
|
102
|
+
'https://app.malicious-site.com',
|
|
103
|
+
'https://app.hubspot.com.evil.com',
|
|
104
|
+
];
|
|
105
|
+
invalidOrigins.forEach(origin => {
|
|
106
|
+
it(`should reject connection from "${origin}"`, async () => {
|
|
107
|
+
isPortManagerServerRunning.mockResolvedValue(true);
|
|
108
|
+
requestPorts.mockResolvedValue({
|
|
109
|
+
'local-dev-ui-websocket-server': 1234,
|
|
110
|
+
});
|
|
111
|
+
await server.start();
|
|
112
|
+
// Get the connection callback
|
|
113
|
+
const connectionCallback = mockWebSocketServer.on.mock
|
|
114
|
+
.calls[0][1];
|
|
115
|
+
// Simulate connection from invalid origin
|
|
116
|
+
connectionCallback(mockWebSocket, {
|
|
117
|
+
headers: { origin },
|
|
118
|
+
});
|
|
119
|
+
expect(mockWebSocket.close).toHaveBeenCalledWith(1008, lib.LocalDevWebsocketServer.errors.originNotAllowed(origin));
|
|
120
|
+
expect(mockWebSocket.on).not.toHaveBeenCalled();
|
|
121
|
+
expect(mockLocalDevProcess.addStateListener).not.toHaveBeenCalled();
|
|
122
|
+
});
|
|
76
123
|
});
|
|
77
|
-
await server.start();
|
|
78
|
-
// Get the connection callback
|
|
79
|
-
const connectionCallback = mockWebSocketServer.on.mock.calls[0][1];
|
|
80
|
-
// Simulate connection from invalid origin
|
|
81
|
-
connectionCallback(mockWebSocket, {
|
|
82
|
-
headers: { origin: 'https://malicious-site.com' },
|
|
83
|
-
});
|
|
84
|
-
expect(mockWebSocket.close).toHaveBeenCalledWith(1008, lib.LocalDevWebsocketServer.errors.originNotAllowed('https://malicious-site.com'));
|
|
85
|
-
expect(mockWebSocket.on).not.toHaveBeenCalled();
|
|
86
|
-
expect(mockLocalDevProcess.addStateListener).not.toHaveBeenCalled();
|
|
87
124
|
});
|
|
88
125
|
it('should reject connection with no origin header', async () => {
|
|
89
126
|
isPortManagerServerRunning.mockResolvedValue(true);
|
|
@@ -111,7 +148,7 @@ describe('LocalDevWebsocketServer', () => {
|
|
|
111
148
|
const connectionCallback = mockWebSocketServer.on.mock.calls[0][1];
|
|
112
149
|
// Simulate connection from valid origin
|
|
113
150
|
connectionCallback(mockWebSocket, {
|
|
114
|
-
headers: { origin: 'https://app.hubspot.com' },
|
|
151
|
+
headers: { origin: 'https://app-na3.hubspot.com' },
|
|
115
152
|
});
|
|
116
153
|
expect(mockLocalDevProcess.sendDevServerMessage).toHaveBeenCalledWith(LOCAL_DEV_SERVER_MESSAGE_TYPES.WEBSOCKET_SERVER_CONNECTED);
|
|
117
154
|
});
|
|
@@ -140,7 +177,7 @@ describe('LocalDevWebsocketServer', () => {
|
|
|
140
177
|
const messageCallback = mockWebSocket.on.mock.calls[0][1];
|
|
141
178
|
const message = {};
|
|
142
179
|
messageCallback(JSON.stringify(message));
|
|
143
|
-
expect(
|
|
180
|
+
expect(uiLogger.error).toHaveBeenCalled();
|
|
144
181
|
});
|
|
145
182
|
it('should log error for unknown message type', () => {
|
|
146
183
|
const messageCallback = mockWebSocket.on.mock.calls[0][1];
|
|
@@ -148,13 +185,13 @@ describe('LocalDevWebsocketServer', () => {
|
|
|
148
185
|
type: 'UNKNOWN_TYPE',
|
|
149
186
|
};
|
|
150
187
|
messageCallback(JSON.stringify(message));
|
|
151
|
-
expect(
|
|
188
|
+
expect(uiLogger.error).toHaveBeenCalled();
|
|
152
189
|
});
|
|
153
190
|
it('should log error for invalid JSON', () => {
|
|
154
191
|
const messageCallback = mockWebSocket.on.mock.calls[0][1];
|
|
155
192
|
const invalidJson = 'invalid json';
|
|
156
193
|
messageCallback(invalidJson);
|
|
157
|
-
expect(
|
|
194
|
+
expect(uiLogger.error).toHaveBeenCalled();
|
|
158
195
|
});
|
|
159
196
|
});
|
|
160
197
|
describe('shutdown()', () => {
|
|
@@ -205,7 +242,7 @@ describe('LocalDevWebsocketServer', () => {
|
|
|
205
242
|
headers: { origin: 'https://app.hubspot.com' },
|
|
206
243
|
});
|
|
207
244
|
connectionCallback(mockWebSocket2, {
|
|
208
|
-
headers: { origin: 'https://app.hubspotqa.com' },
|
|
245
|
+
headers: { origin: 'https://app-na2.hubspotqa.com' },
|
|
209
246
|
});
|
|
210
247
|
connectionCallback(mockWebSocket3, {
|
|
211
248
|
headers: { origin: 'https://local.hubspot.com' },
|
|
@@ -225,29 +262,12 @@ describe('LocalDevWebsocketServer', () => {
|
|
|
225
262
|
expect(mockWebSocket3.close).not.toHaveBeenCalled();
|
|
226
263
|
});
|
|
227
264
|
it('should send project data to each connection independently', () => {
|
|
228
|
-
// Setup mock project data properties as getters
|
|
229
|
-
Object.defineProperty(mockLocalDevProcess, 'projectName', {
|
|
230
|
-
get: () => 'test-project',
|
|
231
|
-
configurable: true,
|
|
232
|
-
});
|
|
233
|
-
Object.defineProperty(mockLocalDevProcess, 'projectId', {
|
|
234
|
-
get: () => 123,
|
|
235
|
-
configurable: true,
|
|
236
|
-
});
|
|
237
|
-
Object.defineProperty(mockLocalDevProcess, 'targetProjectAccountId', {
|
|
238
|
-
get: () => 456,
|
|
239
|
-
configurable: true,
|
|
240
|
-
});
|
|
241
|
-
Object.defineProperty(mockLocalDevProcess, 'targetTestingAccountId', {
|
|
242
|
-
get: () => 789,
|
|
243
|
-
configurable: true,
|
|
244
|
-
});
|
|
245
265
|
// Establish multiple connections
|
|
246
266
|
connectionCallback(mockWebSocket1, {
|
|
247
267
|
headers: { origin: 'https://app.hubspot.com' },
|
|
248
268
|
});
|
|
249
269
|
connectionCallback(mockWebSocket2, {
|
|
250
|
-
headers: { origin: 'https://app.hubspotqa.com' },
|
|
270
|
+
headers: { origin: 'https://app-eu1.hubspotqa.com' },
|
|
251
271
|
});
|
|
252
272
|
// Each websocket should receive project data
|
|
253
273
|
expect(mockWebSocket1.send).toHaveBeenCalledWith(JSON.stringify({
|
|
@@ -255,6 +275,8 @@ describe('LocalDevWebsocketServer', () => {
|
|
|
255
275
|
data: {
|
|
256
276
|
projectName: 'test-project',
|
|
257
277
|
projectId: 123,
|
|
278
|
+
latestBuild: { id: 'build-1', status: 'SUCCESS' },
|
|
279
|
+
deployedBuild: { id: 'build-1', status: 'SUCCESS' },
|
|
258
280
|
targetProjectAccountId: 456,
|
|
259
281
|
targetTestingAccountId: 789,
|
|
260
282
|
},
|
|
@@ -264,6 +286,8 @@ describe('LocalDevWebsocketServer', () => {
|
|
|
264
286
|
data: {
|
|
265
287
|
projectName: 'test-project',
|
|
266
288
|
projectId: 123,
|
|
289
|
+
latestBuild: { id: 'build-1', status: 'SUCCESS' },
|
|
290
|
+
deployedBuild: { id: 'build-1', status: 'SUCCESS' },
|
|
267
291
|
targetProjectAccountId: 456,
|
|
268
292
|
targetTestingAccountId: 789,
|
|
269
293
|
},
|
|
@@ -275,7 +299,7 @@ describe('LocalDevWebsocketServer', () => {
|
|
|
275
299
|
headers: { origin: 'https://app.hubspot.com' },
|
|
276
300
|
});
|
|
277
301
|
connectionCallback(mockWebSocket2, {
|
|
278
|
-
headers: { origin: 'https://app.hubspotqa.com' },
|
|
302
|
+
headers: { origin: 'https://app-ap1.hubspotqa.com' },
|
|
279
303
|
});
|
|
280
304
|
// Get all the close callbacks for both connections (there should be 2 per connection)
|
|
281
305
|
const closeCallbacks1 = mockWebSocket1.on.mock.calls
|
|
@@ -284,11 +308,11 @@ describe('LocalDevWebsocketServer', () => {
|
|
|
284
308
|
const closeCallbacks2 = mockWebSocket2.on.mock.calls
|
|
285
309
|
.filter(call => call[0] === 'close')
|
|
286
310
|
.map(call => call[1]);
|
|
287
|
-
expect(closeCallbacks1).toHaveLength(3); // projectNodes and
|
|
288
|
-
expect(closeCallbacks2).toHaveLength(3); // projectNodes and
|
|
311
|
+
expect(closeCallbacks1).toHaveLength(3); // projectNodes, appData, and uploadWarnings listeners
|
|
312
|
+
expect(closeCallbacks2).toHaveLength(3); // projectNodes, appData, and uploadWarnings listeners
|
|
289
313
|
// Simulate first connection closing (call all close callbacks)
|
|
290
314
|
closeCallbacks1.forEach(callback => callback());
|
|
291
|
-
// Should have removed listeners for first connection (
|
|
315
|
+
// Should have removed listeners for first connection (3 listeners: projectNodes, appData, and uploadWarnings)
|
|
292
316
|
expect(mockLocalDevProcess.removeStateListener).toHaveBeenCalledTimes(3);
|
|
293
317
|
// Simulate second connection closing
|
|
294
318
|
closeCallbacks2.forEach(callback => callback());
|
|
@@ -301,7 +325,7 @@ describe('LocalDevWebsocketServer', () => {
|
|
|
301
325
|
headers: { origin: 'https://app.hubspot.com' },
|
|
302
326
|
});
|
|
303
327
|
connectionCallback(mockWebSocket2, {
|
|
304
|
-
headers: { origin: 'https://
|
|
328
|
+
headers: { origin: 'https://local.hubspotqa.com' },
|
|
305
329
|
});
|
|
306
330
|
// Get the projectNodes listeners that were registered
|
|
307
331
|
const projectNodesListeners = mockLocalDevProcess.addStateListener.mock.calls
|
|
@@ -317,6 +341,8 @@ describe('LocalDevWebsocketServer', () => {
|
|
|
317
341
|
componentRoot: '/test/path',
|
|
318
342
|
componentConfigPath: '/test/path/config.json',
|
|
319
343
|
configUpdatedSinceLastUpload: false,
|
|
344
|
+
removed: false,
|
|
345
|
+
parsingErrors: [],
|
|
320
346
|
},
|
|
321
347
|
componentDeps: {},
|
|
322
348
|
metaFilePath: '/test/path',
|