@squiz/dxp-cli-next 5.28.0-develop.1 → 5.28.0-develop.3

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.
@@ -15,7 +15,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  const commander_1 = require("commander");
16
16
  const chalk_1 = __importDefault(require("chalk"));
17
17
  const ora_1 = __importDefault(require("ora"));
18
- const fs_1 = __importDefault(require("fs"));
19
18
  const utils_1 = require("../utils");
20
19
  const createMigrationCommand = () => {
21
20
  const createCommand = new commander_1.Command('create')
@@ -25,28 +24,16 @@ const createMigrationCommand = () => {
25
24
  .addOption((0, utils_1.getParamOption)(utils_1.OptionName.PREVIEW_ASSET_ID))
26
25
  .addOption((0, utils_1.getParamOption)(utils_1.OptionName.MATRIX_URL))
27
26
  .addOption((0, utils_1.getParamOption)(utils_1.OptionName.TENANT, false))
28
- .argument('<exportPath>', 'Path to the export folder (e.g., ./export)')
29
27
  .configureOutput({
30
28
  outputError(str, write) {
31
29
  write(chalk_1.default.red(str));
32
30
  },
33
31
  })
34
- .action((exportPath, options) => __awaiter(void 0, void 0, void 0, function* () {
32
+ .action((options) => __awaiter(void 0, void 0, void 0, function* () {
35
33
  yield (0, utils_1.throwErrorIfNotLoggedIn)(createCommand);
36
- let spinner = (0, ora_1.default)('Validating export folder structure').start();
34
+ let spinner = (0, ora_1.default)('Creating migration').start();
37
35
  try {
38
- // Validate export folder structure
39
- (0, utils_1.validateExportFolder)(exportPath);
40
- spinner.succeed('Export folder structure validated');
41
- // Create tar file
42
- spinner = (0, ora_1.default)('Creating tar file from export folder').start();
43
- const tarFilePath = yield (0, utils_1.createTarFile)(exportPath);
44
- if (!tarFilePath) {
45
- throw new Error('Tar file creation failed');
46
- }
47
- spinner.succeed(`Tar file created: ${tarFilePath}`);
48
36
  // Create migration
49
- spinner = (0, ora_1.default)('Creating migration').start();
50
37
  const response = yield (0, utils_1.createMigration)(options);
51
38
  if (!response) {
52
39
  throw new Error('Migration creation failed');
@@ -54,14 +41,6 @@ const createMigrationCommand = () => {
54
41
  spinner.succeed('Migration created successfully');
55
42
  // Upload file to S3
56
43
  spinner = (0, ora_1.default)('Uploading file to S3').start();
57
- const uploadUrl = response.uploadUrl;
58
- const s3Url = yield (0, utils_1.uploadFileToS3)(uploadUrl, tarFilePath, options.tenant);
59
- if (!s3Url) {
60
- throw new Error('File upload failed');
61
- }
62
- spinner.succeed('File uploaded to S3');
63
- // Clean up tar file
64
- fs_1.default.unlinkSync(tarFilePath);
65
44
  spinner.succeed(`Successfully created migration: ${JSON.stringify({
66
45
  migrationId: response.assetMigration.migrationId,
67
46
  assetId: response.assetMigration.assetId,
@@ -38,17 +38,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
38
38
  const nock_1 = __importDefault(require("nock"));
39
39
  const create_1 = __importDefault(require("./create"));
40
40
  const utils = __importStar(require("../utils/common"));
41
- const ApplicationStore = __importStar(require("../../ApplicationStore"));
42
- const fs_1 = __importDefault(require("fs"));
43
41
  const createMigration = __importStar(require("../utils/createMigration"));
44
42
  jest.mock('../utils/common');
45
43
  jest.mock('../utils/createMigration');
46
- jest.mock('../../ApplicationStore');
47
- jest.mock('fs');
48
44
  const mockUtils = utils;
49
45
  const mockCreateMigration = createMigration;
50
- const mockApplicationStore = ApplicationStore;
51
- const mockFs = fs_1.default;
52
46
  describe('createMigrationCommand', () => {
53
47
  let logSpy;
54
48
  let mockCreateMigrationResponse;
@@ -57,12 +51,7 @@ describe('createMigrationCommand', () => {
57
51
  jest.clearAllMocks();
58
52
  jest.resetAllMocks();
59
53
  logSpy = jest.spyOn(console, 'log').mockImplementation(() => { });
60
- mockApplicationStore.getApplicationFile.mockResolvedValue('session-cookie');
61
54
  mockUtils.throwErrorIfNotLoggedIn.mockResolvedValue(undefined);
62
- mockCreateMigration.validateExportFolder.mockImplementation(() => { });
63
- mockCreateMigration.createTarFile.mockResolvedValue('/path/to/export_123.tar.gz');
64
- mockUtils.uploadFileToS3.mockResolvedValue('https://s3.amazonaws.com/uploaded-file');
65
- mockFs.unlinkSync.mockImplementation(() => { });
66
55
  mockCreateMigrationResponse = {
67
56
  assetMigration: {
68
57
  migrationId: 'migration-123',
@@ -95,23 +84,14 @@ describe('createMigrationCommand', () => {
95
84
  'preview-456',
96
85
  '--matrix-url',
97
86
  'https://matrix.example.com',
98
- '/path/to/export',
99
87
  ]);
100
88
  expect(mockUtils.throwErrorIfNotLoggedIn).toHaveBeenCalledWith(program);
101
- expect(mockCreateMigration.validateExportFolder).toHaveBeenCalledWith('/path/to/export');
102
- expect(mockCreateMigration.createTarFile).toHaveBeenCalledWith('/path/to/export');
103
89
  expect(mockCreateMigration.createMigration).toHaveBeenCalledWith({
104
90
  assetId: 'asset-123',
105
91
  previewAssetId: 'preview-456',
106
92
  matrixUrl: 'https://matrix.example.com',
107
93
  });
108
- expect(mockUtils.uploadFileToS3).toHaveBeenCalledWith('https://upload.s3.amazonaws.com', '/path/to/export_123.tar.gz', undefined);
109
- expect(mockFs.unlinkSync).toHaveBeenCalledWith('/path/to/export_123.tar.gz');
110
- expect(mockCreateMigration.validateExportFolder).toHaveBeenCalledTimes(1);
111
- expect(mockCreateMigration.createTarFile).toHaveBeenCalledTimes(1);
112
94
  expect(mockCreateMigration.createMigration).toHaveBeenCalledTimes(1);
113
- expect(mockUtils.uploadFileToS3).toHaveBeenCalledTimes(1);
114
- expect(mockFs.unlinkSync).toHaveBeenCalledTimes(1);
115
95
  expect(mockUtils.handleCommandError).not.toHaveBeenCalled();
116
96
  }));
117
97
  it('should create migration with tenant option', () => __awaiter(void 0, void 0, void 0, function* () {
@@ -127,7 +107,6 @@ describe('createMigrationCommand', () => {
127
107
  'https://matrix.example.com',
128
108
  '--tenant',
129
109
  'test-tenant',
130
- '/path/to/export',
131
110
  ]);
132
111
  expect(mockCreateMigration.createMigration).toHaveBeenCalledWith({
133
112
  assetId: 'asset-123',
@@ -135,7 +114,6 @@ describe('createMigrationCommand', () => {
135
114
  matrixUrl: 'https://matrix.example.com',
136
115
  tenant: 'test-tenant',
137
116
  });
138
- expect(mockUtils.uploadFileToS3).toHaveBeenCalledWith('https://upload.s3.amazonaws.com', '/path/to/export_123.tar.gz', 'test-tenant');
139
117
  }));
140
118
  it('should create migration with override URL when environment variable is set', () => __awaiter(void 0, void 0, void 0, function* () {
141
119
  const originalEnv = process.env.ENABLE_OVERRIDE_MIGRATION_URL;
@@ -152,7 +130,6 @@ describe('createMigrationCommand', () => {
152
130
  'https://matrix.example.com',
153
131
  '--overrideUrl',
154
132
  'https://custom.migration.url',
155
- '/path/to/export',
156
133
  ]);
157
134
  expect(mockCreateMigration.createMigration).toHaveBeenCalledWith({
158
135
  assetId: 'asset-123',
@@ -164,46 +141,9 @@ describe('createMigrationCommand', () => {
164
141
  }));
165
142
  });
166
143
  describe('error scenarios', () => {
167
- it('should handle validation error for export folder', () => __awaiter(void 0, void 0, void 0, function* () {
168
- const validationError = new Error('Export folder does not exist');
169
- mockCreateMigration.validateExportFolder.mockImplementation(() => {
170
- throw validationError;
171
- });
172
- mockUtils.handleCommandError.mockImplementation(() => { });
173
- const program = (0, create_1.default)();
174
- yield program.parseAsync([
175
- 'node',
176
- 'dxp-cli',
177
- '--asset-id',
178
- 'asset-123',
179
- '--preview-asset-id',
180
- 'preview-456',
181
- '--matrix-url',
182
- 'https://matrix.example.com',
183
- '/invalid/path',
184
- ]);
185
- expect(mockUtils.handleCommandError).toHaveBeenCalledWith(program, validationError);
186
- expect(mockCreateMigration.createTarFile).not.toHaveBeenCalled();
187
- }));
188
- it('should handle tar file creation failure', () => __awaiter(void 0, void 0, void 0, function* () {
189
- mockCreateMigration.createTarFile.mockResolvedValue(null);
190
- const program = (0, create_1.default)();
191
- yield program.parseAsync([
192
- 'node',
193
- 'dxp-cli',
194
- '--asset-id',
195
- 'asset-123',
196
- '--preview-asset-id',
197
- 'preview-456',
198
- '--matrix-url',
199
- 'https://matrix.example.com',
200
- '/path/to/export',
201
- ]);
202
- expect(mockCreateMigration.createMigration).not.toHaveBeenCalled();
203
- expect(mockUtils.uploadFileToS3).not.toHaveBeenCalled();
204
- }));
205
144
  it('should handle migration creation failure', () => __awaiter(void 0, void 0, void 0, function* () {
206
145
  mockCreateMigration.createMigration.mockResolvedValue(null);
146
+ mockUtils.handleCommandError.mockImplementation(() => { });
207
147
  const program = (0, create_1.default)();
208
148
  yield program.parseAsync([
209
149
  'node',
@@ -214,26 +154,8 @@ describe('createMigrationCommand', () => {
214
154
  'preview-456',
215
155
  '--matrix-url',
216
156
  'https://matrix.example.com',
217
- '/path/to/export',
218
- ]);
219
- expect(mockUtils.uploadFileToS3).not.toHaveBeenCalled();
220
- expect(mockFs.unlinkSync).not.toHaveBeenCalled();
221
- }));
222
- it('should handle S3 upload failure', () => __awaiter(void 0, void 0, void 0, function* () {
223
- mockUtils.uploadFileToS3.mockResolvedValue(null);
224
- const program = (0, create_1.default)();
225
- yield program.parseAsync([
226
- 'node',
227
- 'dxp-cli',
228
- '--asset-id',
229
- 'asset-123',
230
- '--preview-asset-id',
231
- 'preview-456',
232
- '--matrix-url',
233
- 'https://matrix.example.com',
234
- '/path/to/export',
235
157
  ]);
236
- expect(mockFs.unlinkSync).not.toHaveBeenCalled();
158
+ expect(mockUtils.handleCommandError).toHaveBeenCalledWith(program, new Error('Migration creation failed'));
237
159
  }));
238
160
  it('should handle migration API error', () => __awaiter(void 0, void 0, void 0, function* () {
239
161
  const apiError = new Error('Migration API failed');
@@ -249,7 +171,6 @@ describe('createMigrationCommand', () => {
249
171
  'preview-456',
250
172
  '--matrix-url',
251
173
  'https://matrix.example.com',
252
- '/path/to/export',
253
174
  ]);
254
175
  expect(mockUtils.handleCommandError).toHaveBeenCalledWith(program, apiError);
255
176
  }));
@@ -268,9 +189,8 @@ describe('createMigrationCommand', () => {
268
189
  'preview-456',
269
190
  '--matrix-url',
270
191
  'https://matrix.example.com',
271
- '/path/to/export',
272
192
  ])).rejects.toThrow('Not logged in');
273
- expect(mockCreateMigration.validateExportFolder).not.toHaveBeenCalled();
193
+ expect(mockCreateMigration.createMigration).not.toHaveBeenCalled();
274
194
  }));
275
195
  });
276
196
  describe('required options validation', () => {
@@ -284,7 +204,6 @@ describe('createMigrationCommand', () => {
284
204
  'preview-456',
285
205
  '--matrix-url',
286
206
  'https://matrix.example.com',
287
- '/path/to/export',
288
207
  ]);
289
208
  }).toThrow();
290
209
  });
@@ -298,7 +217,6 @@ describe('createMigrationCommand', () => {
298
217
  'asset-123',
299
218
  '--matrix-url',
300
219
  'https://matrix.example.com',
301
- '/path/to/export',
302
220
  ]);
303
221
  }).toThrow();
304
222
  });
@@ -312,22 +230,6 @@ describe('createMigrationCommand', () => {
312
230
  'asset-123',
313
231
  '--preview-asset-id',
314
232
  'preview-456',
315
- '/path/to/export',
316
- ]);
317
- }).toThrow();
318
- });
319
- it('should require exportPath argument', () => {
320
- const program = (0, create_1.default)().exitOverride();
321
- expect(() => {
322
- program.parse([
323
- 'node',
324
- 'dxp-cli',
325
- '--asset-id',
326
- 'asset-123',
327
- '--preview-asset-id',
328
- 'preview-456',
329
- '--matrix-url',
330
- 'https://matrix.example.com',
331
233
  ]);
332
234
  }).toThrow();
333
235
  });
@@ -351,7 +253,6 @@ describe('createMigrationCommand', () => {
351
253
  'https://matrix.example.com',
352
254
  '--tenant',
353
255
  'test-tenant',
354
- '/path/to/export',
355
256
  ]);
356
257
  const opts = program.opts();
357
258
  expect(opts.assetId).toBe('asset-123');
@@ -372,13 +273,8 @@ describe('createMigrationCommand', () => {
372
273
  'preview-456',
373
274
  '--matrix-url',
374
275
  'https://matrix.example.com',
375
- '/path/to/export',
376
276
  ]);
377
- expect(mockCreateMigration.validateExportFolder).toHaveBeenCalledWith('/path/to/export');
378
- expect(mockCreateMigration.createTarFile).toHaveBeenCalledWith('/path/to/export');
379
277
  expect(mockCreateMigration.createMigration).toHaveBeenCalled();
380
- expect(mockUtils.uploadFileToS3).toHaveBeenCalled();
381
- expect(mockFs.unlinkSync).toHaveBeenCalled();
382
278
  }));
383
279
  });
384
280
  });
@@ -45,6 +45,21 @@ const nextStageCommand = () => {
45
45
  const spinner = (0, ora_1.default)('Starting next stage').start();
46
46
  try {
47
47
  const { stageOptions: stageOptionsPath } = options, otherOptions = __rest(options, ["stageOptions"]);
48
+ const migration = yield (0, utils_1.getMigration)(otherOptions);
49
+ if (!migration) {
50
+ throw new Error('Migration not found');
51
+ }
52
+ const { stage, status, assetId } = migration;
53
+ const needsConfirmation = (stage === 'preview' && status === 'complete') ||
54
+ (stage === 'morph' && status === 'awaiting-confirmation');
55
+ if (needsConfirmation) {
56
+ spinner.stop();
57
+ const shouldProceed = yield (0, utils_1.promptForMorphConfirmation)(stage, status, assetId);
58
+ if (!shouldProceed) {
59
+ return;
60
+ }
61
+ spinner.start('Starting next stage');
62
+ }
48
63
  const stageOptions = (0, utils_1.loadStageOptionsFromFile)(stageOptionsPath);
49
64
  const response = yield (0, utils_1.nextStage)(Object.assign(Object.assign({}, otherOptions), (stageOptions && { stageOptions })));
50
65
  spinner.succeed(response.message);
@@ -40,11 +40,14 @@ const next_1 = __importDefault(require("./next"));
40
40
  const utils = __importStar(require("../utils/common"));
41
41
  const ApplicationStore = __importStar(require("../../ApplicationStore"));
42
42
  const nextStageModule = __importStar(require("../utils/nextStage"));
43
+ const getMigrationModule = __importStar(require("../utils/getMigration"));
43
44
  jest.mock('../utils/common');
44
45
  jest.mock('../utils/nextStage');
46
+ jest.mock('../utils/getMigration');
45
47
  jest.mock('../../ApplicationStore');
46
48
  const mockUtils = utils;
47
49
  const mockNextStage = nextStageModule;
50
+ const mockGetMigration = getMigrationModule;
48
51
  const mockApplicationStore = ApplicationStore;
49
52
  describe('nextStageCommand', () => {
50
53
  let logSpy;
@@ -60,6 +63,18 @@ describe('nextStageCommand', () => {
60
63
  message: 'Successfully started next stage',
61
64
  };
62
65
  mockNextStage.nextStage.mockResolvedValue(mockNextStageResponse);
66
+ mockGetMigration.getMigration.mockResolvedValue({
67
+ migrationId: 'migration-123',
68
+ assetId: 'asset-456',
69
+ stage: 'validation',
70
+ status: 'completed',
71
+ xmlFilePath: 'test.xml',
72
+ matrixUrl: 'http://test.com',
73
+ previewAssetId: 'preview-123',
74
+ created: 1234567890,
75
+ updated: 1234567890,
76
+ migrationIdAssetId: 'migration-123-asset-456',
77
+ });
63
78
  });
64
79
  afterEach(() => {
65
80
  logSpy.mockRestore();
@@ -77,6 +92,10 @@ describe('nextStageCommand', () => {
77
92
  'asset-456',
78
93
  ]);
79
94
  expect(mockUtils.throwErrorIfNotLoggedIn).toHaveBeenCalledWith(program);
95
+ expect(mockGetMigration.getMigration).toHaveBeenCalledWith({
96
+ migrationId: 'migration-123',
97
+ assetId: 'asset-456',
98
+ });
80
99
  expect(mockNextStage.nextStage).toHaveBeenCalledWith({
81
100
  migrationId: 'migration-123',
82
101
  assetId: 'asset-456',
@@ -97,6 +116,11 @@ describe('nextStageCommand', () => {
97
116
  '--tenant',
98
117
  'test-tenant',
99
118
  ]);
119
+ expect(mockGetMigration.getMigration).toHaveBeenCalledWith({
120
+ migrationId: 'migration-123',
121
+ assetId: 'asset-456',
122
+ tenant: 'test-tenant',
123
+ });
100
124
  expect(mockNextStage.nextStage).toHaveBeenCalledWith({
101
125
  migrationId: 'migration-123',
102
126
  assetId: 'asset-456',
@@ -116,6 +140,10 @@ describe('nextStageCommand', () => {
116
140
  '--stage-options',
117
141
  './src/__tests__/migration/stageOptionsInput.json',
118
142
  ]);
143
+ expect(mockGetMigration.getMigration).toHaveBeenCalledWith({
144
+ migrationId: 'migration-123',
145
+ assetId: 'asset-456',
146
+ });
119
147
  expect(mockNextStage.nextStage).toHaveBeenCalledWith({
120
148
  migrationId: 'migration-123',
121
149
  assetId: 'asset-456',
@@ -128,6 +156,22 @@ describe('nextStageCommand', () => {
128
156
  }));
129
157
  });
130
158
  describe('error scenarios', () => {
159
+ it('should handle getMigration error', () => __awaiter(void 0, void 0, void 0, function* () {
160
+ const migrationError = new Error('Failed to get migration: TypeError: Invalid URL');
161
+ mockGetMigration.getMigration.mockRejectedValue(migrationError);
162
+ mockUtils.handleCommandError.mockImplementation(() => { });
163
+ const program = (0, next_1.default)();
164
+ yield program.parseAsync([
165
+ 'node',
166
+ 'dxp-cli',
167
+ 'next',
168
+ '--migration-id',
169
+ 'migration-123',
170
+ '--asset-id',
171
+ 'asset-456',
172
+ ]);
173
+ expect(mockUtils.handleCommandError).toHaveBeenCalledWith(program, migrationError);
174
+ }));
131
175
  it('should handle nextStage API error', () => __awaiter(void 0, void 0, void 0, function* () {
132
176
  const apiError = new Error('Failed to start next stage');
133
177
  mockNextStage.nextStage.mockRejectedValue(apiError);
@@ -6,3 +6,4 @@ export * from './nextStage';
6
6
  export * from './setMigrationSettings';
7
7
  export * from './revertMigration';
8
8
  export * from './loadStageOptionsFromFile';
9
+ export * from './promptForMorphConfirmation';
@@ -22,3 +22,4 @@ __exportStar(require("./nextStage"), exports);
22
22
  __exportStar(require("./setMigrationSettings"), exports);
23
23
  __exportStar(require("./revertMigration"), exports);
24
24
  __exportStar(require("./loadStageOptionsFromFile"), exports);
25
+ __exportStar(require("./promptForMorphConfirmation"), exports);
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Prompts the user for confirmation when about to trigger morph stages.
3
+ * Returns true if user has chosen to confirm.
4
+ */
5
+ export declare function promptForMorphConfirmation(stage: string, status: string, assetId: string): Promise<boolean>;
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.promptForMorphConfirmation = void 0;
16
+ const chalk_1 = __importDefault(require("chalk"));
17
+ const inquirer_1 = __importDefault(require("inquirer"));
18
+ /**
19
+ * Prompts the user for confirmation when about to trigger morph stages.
20
+ * Returns true if user has chosen to confirm.
21
+ */
22
+ function promptForMorphConfirmation(stage, status, assetId) {
23
+ return __awaiter(this, void 0, void 0, function* () {
24
+ let message;
25
+ let abortMessage;
26
+ if (stage === 'preview' && status === 'complete') {
27
+ message = `You are about to morph the live asset (${assetId}). Do you wish to continue? [y/N]`;
28
+ abortMessage = 'Morph stage not run';
29
+ }
30
+ else if (stage === 'morph' && status === 'awaiting-confirmation') {
31
+ message = `You are about to permanently delete the standard page bodycopies for asset ${assetId}, please ensure that the client has confirmed the live asset is functioning as expected. This can NOT be undone. Do you wish to continue? [y/N]`;
32
+ abortMessage = 'Morph cleanup not run';
33
+ }
34
+ else {
35
+ return true;
36
+ }
37
+ const choice = yield inquirer_1.default.prompt([
38
+ {
39
+ type: 'list',
40
+ name: 'confirm',
41
+ message,
42
+ choices: [
43
+ { name: 'No', value: false },
44
+ { name: 'Yes', value: true },
45
+ ],
46
+ default: false, // Default answer is No
47
+ },
48
+ ]);
49
+ if (!choice.confirm) {
50
+ console.log(chalk_1.default.yellow(abortMessage));
51
+ }
52
+ return choice.confirm;
53
+ });
54
+ }
55
+ exports.promptForMorphConfirmation = promptForMorphConfirmation;
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const promptForMorphConfirmation_1 = require("./promptForMorphConfirmation");
16
+ const chalk_1 = __importDefault(require("chalk"));
17
+ jest.mock('inquirer', () => ({
18
+ prompt: jest.fn(),
19
+ }));
20
+ const mockConsoleLog = jest.spyOn(console, 'log').mockImplementation();
21
+ const mockPrompt = require('inquirer').prompt;
22
+ describe('promptForMorphConfirmation', () => {
23
+ beforeEach(() => {
24
+ jest.clearAllMocks();
25
+ });
26
+ afterAll(() => {
27
+ mockConsoleLog.mockRestore();
28
+ });
29
+ describe('Preview to Morph stage', () => {
30
+ it('should prompt for confirmation when stage is preview and status is complete', () => __awaiter(void 0, void 0, void 0, function* () {
31
+ mockPrompt.mockResolvedValue({ confirm: true });
32
+ const result = yield (0, promptForMorphConfirmation_1.promptForMorphConfirmation)('preview', 'complete', 'asset123');
33
+ expect(mockPrompt).toHaveBeenCalledWith([
34
+ {
35
+ type: 'list',
36
+ name: 'confirm',
37
+ message: 'You are about to morph the live asset (asset123). Do you wish to continue? [y/N]',
38
+ choices: [
39
+ { name: 'No', value: false },
40
+ { name: 'Yes', value: true },
41
+ ],
42
+ default: false,
43
+ },
44
+ ]);
45
+ expect(result).toBe(true);
46
+ expect(mockConsoleLog).not.toHaveBeenCalled();
47
+ }));
48
+ it('should return false and show abort message when user selects No for preview stage', () => __awaiter(void 0, void 0, void 0, function* () {
49
+ mockPrompt.mockResolvedValue({ confirm: false });
50
+ const result = yield (0, promptForMorphConfirmation_1.promptForMorphConfirmation)('preview', 'complete', 'asset456');
51
+ expect(result).toBe(false);
52
+ expect(mockConsoleLog).toHaveBeenCalledWith(chalk_1.default.yellow('Morph stage not run'));
53
+ }));
54
+ });
55
+ describe('Morph Cleanup stage', () => {
56
+ it('should prompt for confirmation when stage is morph and status is awaiting-confirmation', () => __awaiter(void 0, void 0, void 0, function* () {
57
+ mockPrompt.mockResolvedValue({ confirm: true });
58
+ const result = yield (0, promptForMorphConfirmation_1.promptForMorphConfirmation)('morph', 'awaiting-confirmation', 'asset789');
59
+ expect(mockPrompt).toHaveBeenCalledWith([
60
+ {
61
+ type: 'list',
62
+ name: 'confirm',
63
+ message: 'You are about to permanently delete the standard page bodycopies for asset asset789, please ensure that the client has confirmed the live asset is functioning as expected. This can NOT be undone. Do you wish to continue? [y/N]',
64
+ choices: [
65
+ { name: 'No', value: false },
66
+ { name: 'Yes', value: true },
67
+ ],
68
+ default: false,
69
+ },
70
+ ]);
71
+ expect(result).toBe(true);
72
+ expect(mockConsoleLog).not.toHaveBeenCalled();
73
+ }));
74
+ it('should return false and show abort message when user selects No for morph cleanup stage', () => __awaiter(void 0, void 0, void 0, function* () {
75
+ mockPrompt.mockResolvedValue({ confirm: false });
76
+ const result = yield (0, promptForMorphConfirmation_1.promptForMorphConfirmation)('morph', 'awaiting-confirmation', 'asset999');
77
+ expect(result).toBe(false);
78
+ expect(mockConsoleLog).toHaveBeenCalledWith(chalk_1.default.yellow('Morph cleanup not run'));
79
+ }));
80
+ });
81
+ describe('Other stages', () => {
82
+ it('should return true without prompting for preview stage with non-complete status', () => __awaiter(void 0, void 0, void 0, function* () {
83
+ const result = yield (0, promptForMorphConfirmation_1.promptForMorphConfirmation)('preview', 'running', 'asset123');
84
+ expect(result).toBe(true);
85
+ expect(mockPrompt).not.toHaveBeenCalled();
86
+ expect(mockConsoleLog).not.toHaveBeenCalled();
87
+ }));
88
+ it('should return true without prompting for other stages', () => __awaiter(void 0, void 0, void 0, function* () {
89
+ const result = yield (0, promptForMorphConfirmation_1.promptForMorphConfirmation)('export-to-json', 'complete', 'asset123');
90
+ expect(result).toBe(true);
91
+ expect(mockPrompt).not.toHaveBeenCalled();
92
+ expect(mockConsoleLog).not.toHaveBeenCalled();
93
+ }));
94
+ it('should return true without prompting for unknown stage and status combinations', () => __awaiter(void 0, void 0, void 0, function* () {
95
+ const result = yield (0, promptForMorphConfirmation_1.promptForMorphConfirmation)('unknown', 'unknown-status', 'asset123');
96
+ expect(result).toBe(true);
97
+ expect(mockPrompt).not.toHaveBeenCalled();
98
+ expect(mockConsoleLog).not.toHaveBeenCalled();
99
+ }));
100
+ });
101
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@squiz/dxp-cli-next",
3
- "version": "5.28.0-develop.1",
3
+ "version": "5.28.0-develop.3",
4
4
  "repository": {
5
5
  "url": "https://gitlab.squiz.net/dxp/dxp-cli-next"
6
6
  },