Skip to content

Commit bfe16eb

Browse files
committed
feat: Updated to latest schema and library. Adds support for requestId and new pty
1 parent 7027c5a commit bfe16eb

5 files changed

Lines changed: 101 additions & 129 deletions

File tree

package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "codify-plugin-test",
3-
"version": "0.0.26",
3+
"version": "0.0.31",
44
"description": "",
55
"main": "dist/index.js",
66
"typings": "dist/index.d.ts",
@@ -15,10 +15,11 @@
1515
"dependencies": {
1616
"ajv": "^8.12.0",
1717
"ajv-formats": "^3.0.1",
18-
"codify-schemas": "1.0.52",
18+
"codify-schemas": "1.0.54",
1919
"lodash.matches": "^4.6.0",
2020
"lodash.differencewith": "4.5.0",
21-
"lodash.unionby": "^4.8.0"
21+
"lodash.unionby": "^4.8.0",
22+
"nanoid": "^5.0.9"
2223
},
2324
"devDependencies": {
2425
"@oclif/prettier-config": "^0.2.1",
@@ -34,7 +35,7 @@
3435
"tsx": "^4.7.3",
3536
"typescript": "^5",
3637
"vitest": "^1.4.0",
37-
"codify-plugin-lib": "1.0.106"
38+
"codify-plugin-lib": "1.0.117"
3839
},
3940
"engines": {
4041
"node": ">=18.0.0"

src/plugin-tester.ts

Lines changed: 11 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
ImportResponseData,
66
InitializeResponseData,
77
IpcMessageSchema,
8+
IpcMessageV2,
89
MessageCmd,
910
PlanRequestData,
1011
PlanResponseData,
@@ -16,9 +17,10 @@ import {
1617
ValidateRequestData,
1718
ValidateResponseData
1819
} from 'codify-schemas';
20+
import unionBy from 'lodash.unionby';
21+
import { nanoid } from 'nanoid';
1922
import { ChildProcess, SpawnOptions, fork, spawn } from 'node:child_process';
2023
import path from 'node:path';
21-
import unionBy from 'lodash.unionby';
2224

2325
import { CodifyTestUtils } from './test-utils.js';
2426

@@ -108,23 +110,6 @@ export class PluginTester {
108110
});
109111
}
110112

111-
// Check that all applys were successful by re-planning
112-
const validationPlans = [];
113-
for (const config of configs) {
114-
validationPlans.push(await this.plan({
115-
desired: config,
116-
isStateful: false,
117-
state: undefined,
118-
}));
119-
}
120-
121-
const unsuccessfulPlans = validationPlans.filter((p) => p.operation !== ResourceOperation.NOOP);
122-
if (unsuccessfulPlans.length > 0) {
123-
throw new Error(`The following applies were not successful. Re-running plan shows that the resources did not return no-op but instead returned:
124-
${JSON.stringify(unsuccessfulPlans, null, 2)}`
125-
)
126-
}
127-
128113
if (options?.validateApply) {
129114
await options.validateApply(plans);
130115
}
@@ -211,21 +196,6 @@ ${JSON.stringify(modifyPlans, null, 2)}`)
211196
});
212197
}
213198

214-
// Validate that the destroy was successful
215-
for (const config of configs) {
216-
const validationPlan = await this.plan({
217-
desired: config,
218-
isStateful: true,
219-
state: undefined
220-
})
221-
if (validationPlan.operation !== ResourceOperation.CREATE) {
222-
throw new Error(`Resource was not successfully destroyed.
223-
Validation plan shows:
224-
${JSON.stringify(validationPlan, null, 2)}
225-
`);
226-
}
227-
}
228-
229199
if (options?.validateDestroy) {
230200
await options.validateDestroy(plans);
231201
}
@@ -235,34 +205,39 @@ ${JSON.stringify(validationPlan, null, 2)}
235205
return CodifyTestUtils.sendMessageAndAwaitResponse(this.childProcess, {
236206
cmd: 'initialize',
237207
data: {},
208+
requestId: nanoid(6),
238209
});
239210
}
240211

241212
async validate(data: ValidateRequestData): Promise<ValidateResponseData> {
242213
return CodifyTestUtils.sendMessageAndAwaitResponse(this.childProcess, {
243214
cmd: 'validate',
244215
data,
216+
requestId: nanoid(6),
245217
});
246218
}
247219

248220
async plan(data: PlanRequestData): Promise<PlanResponseData> {
249221
return CodifyTestUtils.sendMessageAndAwaitResponse(this.childProcess, {
250222
cmd: 'plan',
251223
data,
224+
requestId: nanoid(6),
252225
});
253226
}
254227

255228
async apply(data: ApplyRequestData): Promise<void> {
256229
return CodifyTestUtils.sendMessageAndAwaitResponse(this.childProcess, {
257230
cmd: 'apply',
258231
data,
232+
requestId: nanoid(6),
259233
});
260234
}
261235

262236
async import(data: ImportRequestData): Promise<ImportResponseData> {
263237
return CodifyTestUtils.sendMessageAndAwaitResponse(this.childProcess, {
264238
cmd: 'import',
265239
data,
240+
requestId: nanoid(6),
266241
});
267242
}
268243

@@ -278,7 +253,7 @@ ${JSON.stringify(validationPlan, null, 2)}
278253
}
279254

280255
if (message.cmd === MessageCmd.SUDO_REQUEST) {
281-
const { data } = message;
256+
const { data, requestId } = message;
282257
if (!sudoRequestValidator(data)) {
283258
throw new Error(`Invalid sudo request from plugin. ${JSON.stringify(sudoRequestValidator.errors, null, 2)}`);
284259
}
@@ -288,9 +263,10 @@ ${JSON.stringify(validationPlan, null, 2)}
288263
console.log(`Running command with sudo: 'sudo ${command}'`)
289264
const result = await sudoSpawn(command, options);
290265

291-
process.send({
266+
process.send(<IpcMessageV2>{
292267
cmd: MessageCmd.SUDO_REQUEST + '_Response',
293268
data: result,
269+
requestId,
294270
})
295271
}
296272
})

src/test-utils.test.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Readable } from 'stream';
44
import { CodifyTestUtils } from './test-utils.js';
55
import { describe, expect, it, vi } from 'vitest';
66
import { MessageStatus } from 'codify-schemas';
7+
import { nanoid } from 'nanoid';
78

89
describe('Test Utils tests', async () => {
910

@@ -19,54 +20,57 @@ describe('Test Utils tests', async () => {
1920
it('Sends the message that was passed in', async () => {
2021
const process = mockChildProcess();
2122
const sendMock = vi.spyOn(process, 'send');
23+
const requestId = nanoid(6);
2224

23-
CodifyTestUtils.sendMessageAndAwaitResponse(process, { cmd: 'message', data: 'data' })
25+
CodifyTestUtils.sendMessageAndAwaitResponse(process, { cmd: 'message', data: 'data', requestId })
2426

2527
expect(sendMock.mock.calls.length).to.eq(1);
26-
expect(sendMock.mock.calls[0][0]).to.deep.eq({ cmd: 'message', data: 'data' });
28+
expect(sendMock.mock.calls[0][0]).to.deep.eq({ cmd: 'message', data: 'data', requestId });
2729
})
2830

2931
it('Send a message and receives a response from a plugin (success)', async () => {
3032
const process = mockChildProcess();
33+
const requestId = nanoid(6);
3134

3235
const result = await Promise.all([
3336
(async () => {
3437
await sleep(30);
3538
// Note that the response must end in _Response. In accordance to the message schema rules.
36-
process.emit('message', { cmd: 'message_Response', status: MessageStatus.SUCCESS, data: 'data' })
39+
process.emit('message', { cmd: 'message_Response', status: MessageStatus.SUCCESS, data: 'data', requestId })
3740
})(),
38-
CodifyTestUtils.sendMessageAndAwaitResponse(process, { cmd: 'message', data: 'data' }),
41+
CodifyTestUtils.sendMessageAndAwaitResponse(process, { cmd: 'message', data: 'data', requestId }),
3942
]);
4043

4144
expect(result[1]).to.eq('data')
4245
});
4346

4447
it('Send a message and can handle errors', async () => {
4548
const process = mockChildProcess();
49+
const requestId = nanoid(6);
4650

4751
expect(async () => Promise.all([
4852
(async () => {
4953
await sleep(30);
5054
// Note that the response must end in _Response. In accordance to the message schema rules.
51-
process.emit('message', { cmd: 'message_Response', status: MessageStatus.ERROR, data: 'error message' })
55+
process.emit('message', { cmd: 'message_Response', status: MessageStatus.ERROR, data: 'error message', requestId })
5256
})(),
53-
CodifyTestUtils.sendMessageAndAwaitResponse(process, { cmd: 'message', data: 'data' }),
57+
CodifyTestUtils.sendMessageAndAwaitResponse(process, { cmd: 'message', data: 'data', requestId }),
5458
])).rejects.toThrowError(new Error('error message'))
5559
});
5660

5761
it('Ignores other IPC messages', async () => {
5862
const process = mockChildProcess();
5963

64+
const requestId = nanoid(6);
65+
6066
const result = await Promise.all([
6167
(async () => {
6268
await sleep(30);
63-
process.emit('message', { cmd: 'randomMessage1', status: MessageStatus.SUCCESS, data: 'message1' })
64-
process.emit('message', { cmd: 'randomMessage2', status: MessageStatus.SUCCESS, data: 'message2' })
65-
66-
67-
process.emit('message', { cmd: 'message_Response', status: MessageStatus.SUCCESS, data: 'data' })
69+
process.emit('message', { cmd: 'randomMessage1', status: MessageStatus.SUCCESS, data: 'message1', requestId: nanoid(6) })
70+
process.emit('message', { cmd: 'randomMessage2', status: MessageStatus.SUCCESS, data: 'message2', requestId: nanoid(6) })
71+
process.emit('message', { cmd: 'message_Response', status: MessageStatus.SUCCESS, data: 'data', requestId })
6872
})(),
69-
CodifyTestUtils.sendMessageAndAwaitResponse(process, { cmd: 'message', data: 'data' }),
73+
CodifyTestUtils.sendMessageAndAwaitResponse(process, { cmd: 'message', data: 'data', requestId }),
7074
]);
7175

7276
// Only the final _Response message should be returned.

src/test-utils.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Ajv from 'ajv';
2-
import { IpcMessage, IpcMessageSchema, MessageStatus } from 'codify-schemas';
2+
import { IpcMessageSchema, IpcMessageV2, MessageStatus } from 'codify-schemas';
33
import { ChildProcess } from 'node:child_process';
44

55
const ajv = new Ajv.default({
@@ -8,15 +8,15 @@ const ajv = new Ajv.default({
88
const ipcMessageValidator = ajv.compile(IpcMessageSchema);
99

1010
export const CodifyTestUtils = {
11-
sendMessageAndAwaitResponse(process: ChildProcess, message: IpcMessage): Promise<any> {
11+
sendMessageAndAwaitResponse(process: ChildProcess, message: IpcMessageV2): Promise<any> {
1212
return new Promise((resolve, reject) => {
13-
process.on('message', (response: IpcMessage) => {
13+
process.on('message', (response: IpcMessageV2) => {
1414
if (!ipcMessageValidator(response)) {
1515
throw new Error(`Invalid message from plugin. ${JSON.stringify(message, null, 2)}`);
1616
}
1717

1818
// Wait for the message response. Other messages such as sudoRequest may be sent before the response returns
19-
if (response.cmd === message.cmd + '_Response') {
19+
if (response.requestId === message.requestId) {
2020
if (response.status === MessageStatus.SUCCESS) {
2121
resolve(response.data)
2222
} else {

0 commit comments

Comments
 (0)