@hubspot/cli 7.10.0-beta.1 → 7.10.0-beta.2

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.
@@ -48,27 +48,27 @@ describe('commands/testAccount/create', () => {
48
48
  testAccountCreateCommand.builder(yargsMock);
49
49
  expect(yargsMock.option).toHaveBeenCalledWith('marketing-level', {
50
50
  type: 'string',
51
- description: 'Marketing Hub tier. Unprovided tiers default to ENTERPRISE. Choices: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
51
+ description: 'Marketing Hub tier. Options: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
52
52
  choices: ACCOUNT_LEVEL_CHOICES,
53
53
  });
54
54
  expect(yargsMock.option).toHaveBeenCalledWith('ops-level', {
55
55
  type: 'string',
56
- description: 'Operations Hub tier. Unprovided tiers default to ENTERPRISE. Choices: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
56
+ description: 'Operations Hub tier. Options: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
57
57
  choices: ACCOUNT_LEVEL_CHOICES,
58
58
  });
59
59
  expect(yargsMock.option).toHaveBeenCalledWith('service-level', {
60
60
  type: 'string',
61
- description: 'Service Hub tier. Unprovided tiers default to ENTERPRISE. Choices: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
61
+ description: 'Service Hub tier. Options: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
62
62
  choices: ACCOUNT_LEVEL_CHOICES,
63
63
  });
64
64
  expect(yargsMock.option).toHaveBeenCalledWith('sales-level', {
65
65
  type: 'string',
66
- description: 'Sales Hub tier. Unprovided tiers default to ENTERPRISE. Choices: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
66
+ description: 'Sales Hub tier. Options: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
67
67
  choices: ACCOUNT_LEVEL_CHOICES,
68
68
  });
69
69
  expect(yargsMock.option).toHaveBeenCalledWith('content-level', {
70
70
  type: 'string',
71
- description: 'CMS Hub tier. Unprovided tiers default to ENTERPRISE. Choices: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
71
+ description: 'CMS Hub tier. Options: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
72
72
  choices: ACCOUNT_LEVEL_CHOICES,
73
73
  });
74
74
  });
package/lang/en.js CHANGED
@@ -2121,11 +2121,11 @@ export const commands = {
2121
2121
  configPath: 'Path to config file (mutually exclusive with other flags)',
2122
2122
  accountName: 'Name for the test account',
2123
2123
  description: 'Description for the test account',
2124
- marketingLevel: 'Marketing Hub tier. Unprovided tiers default to ENTERPRISE. Choices: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
2125
- opsLevel: 'Operations Hub tier. Unprovided tiers default to ENTERPRISE. Choices: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
2126
- serviceLevel: 'Service Hub tier. Unprovided tiers default to ENTERPRISE. Choices: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
2127
- salesLevel: 'Sales Hub tier. Unprovided tiers default to ENTERPRISE. Choices: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
2128
- contentLevel: 'CMS Hub tier. Unprovided tiers default to ENTERPRISE. Choices: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
2124
+ marketingLevel: 'Marketing Hub tier. Options: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
2125
+ opsLevel: 'Operations Hub tier. Options: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
2126
+ serviceLevel: 'Service Hub tier. Options: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
2127
+ salesLevel: 'Sales Hub tier. Options: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
2128
+ contentLevel: 'CMS Hub tier. Options: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
2129
2129
  },
2130
2130
  example: (configPath) => `Create a test account from the config file at ${configPath}`,
2131
2131
  examples: {
@@ -341,7 +341,7 @@ describe('lib/projects/components', () => {
341
341
  // The differentiator is appended with a hyphen, so the final UID has a hyphen before the number
342
342
  expect(mockedFs.writeFileSync).toHaveBeenCalledWith('/path/to/component1.meta.json', JSON.stringify({
343
343
  type: 'card',
344
- uid: 'card_collision_project-2',
344
+ uid: 'card_collision_project_2',
345
345
  }, null, 2));
346
346
  });
347
347
  it('falls back to original uid when coerceToValidUid returns null', () => {
@@ -137,7 +137,7 @@ export function updateHsMetaFilesWithAutoGeneratedFields(projectName, hsMetaFile
137
137
  let differentiator = 1;
138
138
  while (existingUids.includes(uid)) {
139
139
  differentiator++;
140
- uid = `${getBaseUid()}-${differentiator}`;
140
+ uid = `${getBaseUid()}_${differentiator}`;
141
141
  }
142
142
  component.uid = uid;
143
143
  if (component.type === AppKey && component.config) {
@@ -6,6 +6,8 @@ import { formatTextContents, formatTextContent } from '../../utils/content.js';
6
6
  import { addFlag } from '../../utils/command.js';
7
7
  import { runCommandInDir } from '../../utils/project.js';
8
8
  import { ACCOUNT_LEVEL_CHOICES } from '../../../lib/constants.js';
9
+ import { getAccountIdFromCliConfig } from '../../utils/cliConfig.js';
10
+ import fs from 'fs';
9
11
  const inputSchema = {
10
12
  absoluteCurrentWorkingDirectory,
11
13
  configPath: z
@@ -29,7 +31,7 @@ const inputSchema = {
29
31
  description: z
30
32
  .string()
31
33
  .optional()
32
- .describe('Description for the test account. Optional.'),
34
+ .describe('Description for the test account. Required when not using configPath.'),
33
35
  marketingLevel: z
34
36
  .enum(ACCOUNT_LEVEL_CHOICES)
35
37
  .optional()
@@ -64,29 +66,40 @@ export class CreateTestAccountTool extends Tool {
64
66
  const content = [];
65
67
  // Use config file if provided (LLM should check for config first)
66
68
  if (configPath) {
69
+ let configJson;
70
+ try {
71
+ const config = fs.readFileSync(configPath, 'utf8');
72
+ configJson = JSON.parse(config);
73
+ }
74
+ catch (error) {
75
+ const errorMessage = error instanceof Error ? error.message : String(error);
76
+ return {
77
+ content: [
78
+ formatTextContent(`Failed to read or parse config file at "${configPath}": ${errorMessage}. Please ensure the file exists and contains valid JSON.`),
79
+ ],
80
+ };
81
+ }
82
+ if (configJson.accountName) {
83
+ const nameInConfig = getAccountIdFromCliConfig(absoluteCurrentWorkingDirectory, configJson.accountName);
84
+ if (nameInConfig) {
85
+ content.push(formatTextContent(`The account name "${configJson.accountName}" already exists in the CLI config. Please use a different name.`));
86
+ }
87
+ }
67
88
  command = addFlag(command, 'config-path', configPath);
68
89
  }
69
90
  // Use flags if name is provided (when no config used)
70
91
  else if (name) {
71
- command = addFlag(command, 'name', name);
72
- if (description) {
73
- command = addFlag(command, 'description', description);
74
- }
75
- if (marketingLevel) {
76
- command = addFlag(command, 'marketing-level', marketingLevel);
77
- }
78
- if (opsLevel) {
79
- command = addFlag(command, 'ops-level', opsLevel);
80
- }
81
- if (serviceLevel) {
82
- command = addFlag(command, 'service-level', serviceLevel);
83
- }
84
- if (salesLevel) {
85
- command = addFlag(command, 'sales-level', salesLevel);
86
- }
87
- if (contentLevel) {
88
- command = addFlag(command, 'content-level', contentLevel);
92
+ const nameInConfig = getAccountIdFromCliConfig(absoluteCurrentWorkingDirectory, name);
93
+ if (nameInConfig) {
94
+ content.push(formatTextContent(`The account name "${name}" already exists in the CLI config. Please use a different name.`));
89
95
  }
96
+ command = addFlag(command, 'name', name);
97
+ command = addFlag(command, 'description', description || name);
98
+ command = addFlag(command, 'marketing-level', marketingLevel || 'ENTERPRISE');
99
+ command = addFlag(command, 'ops-level', opsLevel || 'ENTERPRISE');
100
+ command = addFlag(command, 'service-level', serviceLevel || 'ENTERPRISE');
101
+ command = addFlag(command, 'sales-level', salesLevel || 'ENTERPRISE');
102
+ command = addFlag(command, 'content-level', contentLevel || 'ENTERPRISE');
90
103
  }
91
104
  else {
92
105
  content.push(formatTextContent(`Ask the user for the account config JSON path or the name of the test account to create.`));
@@ -119,7 +132,7 @@ export class CreateTestAccountTool extends Tool {
119
132
  '3. If no config file OR user declined:\n' +
120
133
  ' - Ask the user for ALL account details:\n' +
121
134
  ' * Account name (required)\n' +
122
- ' * Description (required)\n' +
135
+ ' * Description (optional, defaults to account name if not specified)\n' +
123
136
  ' * Hub tier levels for each hub (optional, default to ENTERPRISE if not specified)\n' +
124
137
  ' - Call this tool with name, description, and all tier level parameters\n' +
125
138
  ' - IMPORTANT: Always provide all parameters to ensure non-interactive execution\n\n' +
@@ -2,14 +2,17 @@ import { CreateTestAccountTool, } from '../CreateTestAccountTool.js';
2
2
  import { runCommandInDir } from '../../../utils/project.js';
3
3
  import { addFlag } from '../../../utils/command.js';
4
4
  import { mcpFeedbackRequest } from '../../../utils/feedbackTracking.js';
5
+ import fs from 'fs';
5
6
  vi.mock('@modelcontextprotocol/sdk/server/mcp.js');
6
7
  vi.mock('../../../utils/project');
7
8
  vi.mock('../../../utils/command');
8
9
  vi.mock('../../../utils/toolUsageTracking');
9
10
  vi.mock('../../../utils/feedbackTracking');
11
+ vi.mock('fs');
10
12
  const mockMcpFeedbackRequest = mcpFeedbackRequest;
11
13
  const mockRunCommandInDir = runCommandInDir;
12
14
  const mockAddFlag = addFlag;
15
+ const mockReadFileSync = fs.readFileSync;
13
16
  describe('mcp-server/tools/project/CreateTestAccountTool', () => {
14
17
  let mockMcpServer;
15
18
  let tool;
@@ -26,6 +29,12 @@ describe('mcp-server/tools/project/CreateTestAccountTool', () => {
26
29
  tool = new CreateTestAccountTool(mockMcpServer);
27
30
  // Mock addFlag to simulate command building
28
31
  mockAddFlag.mockImplementation((command, flag, value) => `${command} --${flag} "${value}"`);
32
+ // Mock fs.readFileSync for config file tests
33
+ mockReadFileSync.mockReturnValue(JSON.stringify({
34
+ accountName: 'TestAccountFromConfig',
35
+ description: 'Test description',
36
+ marketingLevel: 'PROFESSIONAL',
37
+ }));
29
38
  });
30
39
  describe('register', () => {
31
40
  it('should register tool with correct parameters', () => {
@@ -54,6 +63,12 @@ describe('mcp-server/tools/project/CreateTestAccountTool', () => {
54
63
  const baseInput = {
55
64
  absoluteCurrentWorkingDirectory: '/test/workspace',
56
65
  configPath: './test-account.json',
66
+ description: 'Test account',
67
+ marketingLevel: 'ENTERPRISE',
68
+ opsLevel: 'ENTERPRISE',
69
+ serviceLevel: 'ENTERPRISE',
70
+ salesLevel: 'ENTERPRISE',
71
+ contentLevel: 'ENTERPRISE',
57
72
  };
58
73
  it('should create test account with config path', async () => {
59
74
  mockRunCommandInDir.mockResolvedValue({
@@ -81,6 +96,12 @@ describe('mcp-server/tools/project/CreateTestAccountTool', () => {
81
96
  const input = {
82
97
  absoluteCurrentWorkingDirectory: '/test/workspace',
83
98
  configPath: '/absolute/path/to/config.json',
99
+ description: 'Test account',
100
+ marketingLevel: 'ENTERPRISE',
101
+ opsLevel: 'ENTERPRISE',
102
+ serviceLevel: 'ENTERPRISE',
103
+ salesLevel: 'ENTERPRISE',
104
+ contentLevel: 'ENTERPRISE',
84
105
  };
85
106
  await tool.handler(input);
86
107
  expect(mockAddFlag).toHaveBeenCalledWith('hs test-account create', 'config-path', '/absolute/path/to/config.json');
@@ -96,15 +117,57 @@ describe('mcp-server/tools/project/CreateTestAccountTool', () => {
96
117
  configPath: './test-account.json',
97
118
  name: 'FlagAccount',
98
119
  description: 'This should be ignored',
120
+ marketingLevel: 'ENTERPRISE',
121
+ opsLevel: 'ENTERPRISE',
122
+ serviceLevel: 'ENTERPRISE',
123
+ salesLevel: 'ENTERPRISE',
124
+ contentLevel: 'ENTERPRISE',
99
125
  };
100
126
  await tool.handler(input);
101
127
  expect(mockAddFlag).toHaveBeenCalledWith('hs test-account create', 'config-path', './test-account.json');
102
128
  // Should not call addFlag for name or description
103
129
  expect(mockAddFlag).not.toHaveBeenCalledWith(expect.anything(), 'name', expect.anything());
104
130
  });
131
+ it('should return helpful error when config file does not exist', async () => {
132
+ mockReadFileSync.mockImplementation(() => {
133
+ throw new Error("ENOENT: no such file or directory, open './missing-config.json'");
134
+ });
135
+ const input = {
136
+ absoluteCurrentWorkingDirectory: '/test/workspace',
137
+ configPath: './missing-config.json',
138
+ };
139
+ const result = await tool.handler(input);
140
+ expect(mockRunCommandInDir).not.toHaveBeenCalled();
141
+ expect(result).toEqual({
142
+ content: [
143
+ {
144
+ type: 'text',
145
+ text: expect.stringContaining('Failed to read or parse config file at "./missing-config.json"'),
146
+ },
147
+ ],
148
+ });
149
+ expect(result.content[0]).toHaveProperty('text', expect.stringContaining('Please ensure the file exists and contains valid JSON'));
150
+ });
151
+ it('should return helpful error when config file contains invalid JSON', async () => {
152
+ mockReadFileSync.mockReturnValue('{ invalid json }');
153
+ const input = {
154
+ absoluteCurrentWorkingDirectory: '/test/workspace',
155
+ configPath: './invalid-config.json',
156
+ };
157
+ const result = await tool.handler(input);
158
+ expect(mockRunCommandInDir).not.toHaveBeenCalled();
159
+ expect(result).toEqual({
160
+ content: [
161
+ {
162
+ type: 'text',
163
+ text: expect.stringContaining('Failed to read or parse config file at "./invalid-config.json"'),
164
+ },
165
+ ],
166
+ });
167
+ });
105
168
  });
106
169
  describe('flag-based approach', () => {
107
- it('should create test account with just account name', async () => {
170
+ it('should create test account with name and all defaults', async () => {
108
171
  mockRunCommandInDir.mockResolvedValue({
109
172
  stdout: 'Test account created successfully',
110
173
  stderr: '',
@@ -112,10 +175,30 @@ describe('mcp-server/tools/project/CreateTestAccountTool', () => {
112
175
  const input = {
113
176
  absoluteCurrentWorkingDirectory: '/test/workspace',
114
177
  name: 'MyTestAccount',
178
+ description: '',
179
+ marketingLevel: 'ENTERPRISE',
180
+ opsLevel: 'ENTERPRISE',
181
+ serviceLevel: 'ENTERPRISE',
182
+ salesLevel: 'ENTERPRISE',
183
+ contentLevel: 'ENTERPRISE',
115
184
  };
116
185
  await tool.handler(input);
117
186
  expect(mockAddFlag).toHaveBeenCalledWith('hs test-account create', 'name', 'MyTestAccount');
118
- expect(mockRunCommandInDir).toHaveBeenCalledWith('/test/workspace', 'hs test-account create --name "MyTestAccount"');
187
+ });
188
+ it('should add all flags with defaults when only name is provided', async () => {
189
+ mockRunCommandInDir.mockResolvedValue({
190
+ stdout: 'Test account created successfully',
191
+ stderr: '',
192
+ });
193
+ const input = {
194
+ absoluteCurrentWorkingDirectory: '/test/workspace',
195
+ name: 'MyTestAccount',
196
+ };
197
+ await tool.handler(input);
198
+ expect(mockAddFlag).toHaveBeenCalledWith('hs test-account create', 'name', 'MyTestAccount');
199
+ // Implementation uses name as fallback for description, and adds all hub levels with ENTERPRISE defaults
200
+ expect(mockAddFlag).toHaveBeenCalledTimes(7);
201
+ expect(mockRunCommandInDir).toHaveBeenCalled();
119
202
  });
120
203
  it('should create test account with account name and description', async () => {
121
204
  mockRunCommandInDir.mockResolvedValue({
@@ -126,6 +209,11 @@ describe('mcp-server/tools/project/CreateTestAccountTool', () => {
126
209
  absoluteCurrentWorkingDirectory: '/test/workspace',
127
210
  name: 'MyTestAccount',
128
211
  description: 'Test account for development',
212
+ marketingLevel: 'ENTERPRISE',
213
+ opsLevel: 'ENTERPRISE',
214
+ serviceLevel: 'ENTERPRISE',
215
+ salesLevel: 'ENTERPRISE',
216
+ contentLevel: 'ENTERPRISE',
129
217
  };
130
218
  await tool.handler(input);
131
219
  expect(mockAddFlag).toHaveBeenCalledWith('hs test-account create', 'name', 'MyTestAccount');
@@ -139,9 +227,12 @@ describe('mcp-server/tools/project/CreateTestAccountTool', () => {
139
227
  const input = {
140
228
  absoluteCurrentWorkingDirectory: '/test/workspace',
141
229
  name: 'MixedTierAccount',
230
+ description: 'Test account',
142
231
  marketingLevel: 'PROFESSIONAL',
143
232
  salesLevel: 'STARTER',
144
233
  contentLevel: 'FREE',
234
+ serviceLevel: 'ENTERPRISE',
235
+ opsLevel: 'ENTERPRISE',
145
236
  };
146
237
  await tool.handler(input);
147
238
  expect(mockAddFlag).toHaveBeenCalledWith('hs test-account create', 'name', 'MixedTierAccount');
@@ -174,10 +265,120 @@ describe('mcp-server/tools/project/CreateTestAccountTool', () => {
174
265
  expect(mockAddFlag).toHaveBeenCalledWith(expect.any(String), 'content-level', 'PROFESSIONAL');
175
266
  });
176
267
  });
268
+ describe('handler defaults', () => {
269
+ it('should use ENTERPRISE defaults for all hub levels when not specified', async () => {
270
+ mockRunCommandInDir.mockResolvedValue({
271
+ stdout: 'Test account created',
272
+ stderr: '',
273
+ });
274
+ const input = {
275
+ absoluteCurrentWorkingDirectory: '/test/workspace',
276
+ name: 'DefaultLevelsAccount',
277
+ description: '',
278
+ marketingLevel: 'ENTERPRISE',
279
+ opsLevel: 'ENTERPRISE',
280
+ serviceLevel: 'ENTERPRISE',
281
+ salesLevel: 'ENTERPRISE',
282
+ contentLevel: 'ENTERPRISE',
283
+ };
284
+ await tool.handler(input);
285
+ expect(mockAddFlag).toHaveBeenCalledWith('hs test-account create', 'name', 'DefaultLevelsAccount');
286
+ expect(mockAddFlag).toHaveBeenCalledWith(expect.any(String), 'marketing-level', 'ENTERPRISE');
287
+ expect(mockAddFlag).toHaveBeenCalledWith(expect.any(String), 'ops-level', 'ENTERPRISE');
288
+ expect(mockAddFlag).toHaveBeenCalledWith(expect.any(String), 'service-level', 'ENTERPRISE');
289
+ expect(mockAddFlag).toHaveBeenCalledWith(expect.any(String), 'sales-level', 'ENTERPRISE');
290
+ expect(mockAddFlag).toHaveBeenCalledWith(expect.any(String), 'content-level', 'ENTERPRISE');
291
+ });
292
+ it('should use name as fallback for description when description is empty', async () => {
293
+ mockRunCommandInDir.mockResolvedValue({
294
+ stdout: 'Test account created',
295
+ stderr: '',
296
+ });
297
+ const input = {
298
+ absoluteCurrentWorkingDirectory: '/test/workspace',
299
+ name: 'NoDescriptionAccount',
300
+ description: '',
301
+ marketingLevel: 'ENTERPRISE',
302
+ opsLevel: 'ENTERPRISE',
303
+ serviceLevel: 'ENTERPRISE',
304
+ salesLevel: 'ENTERPRISE',
305
+ contentLevel: 'ENTERPRISE',
306
+ };
307
+ await tool.handler(input);
308
+ expect(mockAddFlag).toHaveBeenCalledWith('hs test-account create', 'name', 'NoDescriptionAccount');
309
+ // Implementation uses name as fallback for description
310
+ expect(mockAddFlag).toHaveBeenCalledWith(expect.any(String), 'description', 'NoDescriptionAccount');
311
+ });
312
+ it('should use defaults for some hub levels while respecting explicit values', async () => {
313
+ mockRunCommandInDir.mockResolvedValue({
314
+ stdout: 'Test account created',
315
+ stderr: '',
316
+ });
317
+ const input = {
318
+ absoluteCurrentWorkingDirectory: '/test/workspace',
319
+ name: 'PartialLevelsAccount',
320
+ description: '',
321
+ marketingLevel: 'FREE',
322
+ salesLevel: 'STARTER',
323
+ opsLevel: 'ENTERPRISE',
324
+ serviceLevel: 'ENTERPRISE',
325
+ contentLevel: 'ENTERPRISE',
326
+ };
327
+ await tool.handler(input);
328
+ expect(mockAddFlag).toHaveBeenCalledWith('hs test-account create', 'name', 'PartialLevelsAccount');
329
+ expect(mockAddFlag).toHaveBeenCalledWith(expect.any(String), 'marketing-level', 'FREE');
330
+ expect(mockAddFlag).toHaveBeenCalledWith(expect.any(String), 'sales-level', 'STARTER');
331
+ expect(mockAddFlag).toHaveBeenCalledWith(expect.any(String), 'ops-level', 'ENTERPRISE');
332
+ expect(mockAddFlag).toHaveBeenCalledWith(expect.any(String), 'service-level', 'ENTERPRISE');
333
+ expect(mockAddFlag).toHaveBeenCalledWith(expect.any(String), 'content-level', 'ENTERPRISE');
334
+ });
335
+ it('should add all hub level flags when defaults are applied', async () => {
336
+ mockRunCommandInDir.mockResolvedValue({
337
+ stdout: 'Test account created with defaults',
338
+ stderr: '',
339
+ });
340
+ const input = {
341
+ absoluteCurrentWorkingDirectory: '/test/workspace',
342
+ name: 'MinimalAccount',
343
+ description: '',
344
+ marketingLevel: 'ENTERPRISE',
345
+ opsLevel: 'ENTERPRISE',
346
+ serviceLevel: 'ENTERPRISE',
347
+ salesLevel: 'ENTERPRISE',
348
+ contentLevel: 'ENTERPRISE',
349
+ };
350
+ const result = await tool.handler(input);
351
+ expect(mockRunCommandInDir).toHaveBeenCalled();
352
+ expect(mockAddFlag).toHaveBeenCalledTimes(7);
353
+ expect(result.content[0]).toEqual({
354
+ type: 'text',
355
+ text: 'Test account created with defaults',
356
+ });
357
+ });
358
+ it('should use ENTERPRISE defaults when values are undefined', async () => {
359
+ mockRunCommandInDir.mockResolvedValue({
360
+ stdout: 'Test account created',
361
+ stderr: '',
362
+ });
363
+ const input = {
364
+ absoluteCurrentWorkingDirectory: '/test/workspace',
365
+ name: 'BypassedDefaultsAccount',
366
+ };
367
+ await tool.handler(input);
368
+ expect(mockAddFlag).toHaveBeenCalledWith('hs test-account create', 'name', 'BypassedDefaultsAccount');
369
+ expect(mockAddFlag).toHaveBeenCalledTimes(7);
370
+ });
371
+ });
177
372
  describe('interactive mode', () => {
178
373
  it('should ask for parameters when neither config nor name provided', async () => {
179
374
  const input = {
180
375
  absoluteCurrentWorkingDirectory: '/test/workspace',
376
+ description: 'Test account',
377
+ marketingLevel: 'ENTERPRISE',
378
+ opsLevel: 'ENTERPRISE',
379
+ serviceLevel: 'ENTERPRISE',
380
+ salesLevel: 'ENTERPRISE',
381
+ contentLevel: 'ENTERPRISE',
181
382
  };
182
383
  const result = await tool.handler(input);
183
384
  // Should NOT run the command
@@ -202,6 +403,12 @@ describe('mcp-server/tools/project/CreateTestAccountTool', () => {
202
403
  const input = {
203
404
  absoluteCurrentWorkingDirectory: '/test/workspace',
204
405
  configPath: './test-account.json',
406
+ description: 'Test account',
407
+ marketingLevel: 'ENTERPRISE',
408
+ opsLevel: 'ENTERPRISE',
409
+ serviceLevel: 'ENTERPRISE',
410
+ salesLevel: 'ENTERPRISE',
411
+ contentLevel: 'ENTERPRISE',
205
412
  };
206
413
  const result = await tool.handler(input);
207
414
  expect(result).toEqual({
@@ -220,6 +427,12 @@ describe('mcp-server/tools/project/CreateTestAccountTool', () => {
220
427
  const input = {
221
428
  absoluteCurrentWorkingDirectory: '/test/workspace',
222
429
  configPath: './test-account.json',
430
+ description: 'Test account',
431
+ marketingLevel: 'ENTERPRISE',
432
+ opsLevel: 'ENTERPRISE',
433
+ serviceLevel: 'ENTERPRISE',
434
+ salesLevel: 'ENTERPRISE',
435
+ contentLevel: 'ENTERPRISE',
223
436
  };
224
437
  const result = await tool.handler(input);
225
438
  expect(result).toEqual({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/cli",
3
- "version": "7.10.0-beta.1",
3
+ "version": "7.10.0-beta.2",
4
4
  "description": "The official CLI for developing on HubSpot",
5
5
  "license": "Apache-2.0",
6
6
  "repository": "https://github.com/HubSpot/hubspot-cli",