codify-plugin-test 0.0.30 → 0.0.32
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/dist/plugin-tester.js +1 -37
- package/dist/plugin-tester.js.map +1 -1
- package/package.json +3 -3
- package/src/plugin-tester.ts +3 -46
- package/src/test-utils.test.ts +16 -12
- package/test/plugin-tester.test.ts +65 -74
package/dist/plugin-tester.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import Ajv from 'ajv';
|
|
2
2
|
import { IpcMessageSchema, MessageCmd, ResourceOperation, SpawnStatus, SudoRequestDataSchema } from 'codify-schemas';
|
|
3
3
|
import unionBy from 'lodash.unionby';
|
|
4
|
+
import { nanoid } from 'nanoid';
|
|
4
5
|
import { fork, spawn } from 'node:child_process';
|
|
5
6
|
import path from 'node:path';
|
|
6
7
|
import { CodifyTestUtils } from './test-utils.js';
|
|
7
|
-
import { nanoid } from 'nanoid';
|
|
8
8
|
const ajv = new Ajv.default({
|
|
9
9
|
strict: true
|
|
10
10
|
});
|
|
@@ -50,35 +50,13 @@ export class PluginTester {
|
|
|
50
50
|
planId: plan.planId
|
|
51
51
|
});
|
|
52
52
|
}
|
|
53
|
-
const validationPlans = [];
|
|
54
|
-
for (const config of configs) {
|
|
55
|
-
validationPlans.push(await this.plan({
|
|
56
|
-
desired: config,
|
|
57
|
-
isStateful: false,
|
|
58
|
-
state: undefined,
|
|
59
|
-
}));
|
|
60
|
-
}
|
|
61
|
-
const unsuccessfulPlans = validationPlans.filter((p) => p.operation !== ResourceOperation.NOOP);
|
|
62
|
-
if (unsuccessfulPlans.length > 0) {
|
|
63
|
-
throw new Error(`The following applies were not successful. Re-running plan shows that the resources did not return no-op but instead returned:
|
|
64
|
-
${JSON.stringify(unsuccessfulPlans, null, 2)}`);
|
|
65
|
-
}
|
|
66
53
|
if (options?.validateApply) {
|
|
67
54
|
await options.validateApply(plans);
|
|
68
55
|
}
|
|
69
56
|
const importResults = [];
|
|
70
|
-
const unsuccessfulImports = [];
|
|
71
57
|
for (const config of configs) {
|
|
72
58
|
const importResult = await this.import({ config });
|
|
73
59
|
importResults.push(importResult);
|
|
74
|
-
const validationPlan = await this.plan({ desired: importResult.result[0], isStateful: false, state: undefined });
|
|
75
|
-
if (validationPlan.operation !== ResourceOperation.NOOP) {
|
|
76
|
-
unsuccessfulImports.push(importResult);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
if (unsuccessfulImports.length > 0) {
|
|
80
|
-
throw new Error(`The following imports were not successful. The imports differed from the original.
|
|
81
|
-
${JSON.stringify(unsuccessfulImports, null, 2)}`);
|
|
82
60
|
}
|
|
83
61
|
if (options?.validateImport) {
|
|
84
62
|
await options.validateImport(importResults.map((r) => r.result[0]));
|
|
@@ -130,19 +108,6 @@ ${JSON.stringify(modifyPlans, null, 2)}`);
|
|
|
130
108
|
planId: plan.planId
|
|
131
109
|
});
|
|
132
110
|
}
|
|
133
|
-
for (const config of configs) {
|
|
134
|
-
const validationPlan = await this.plan({
|
|
135
|
-
desired: config,
|
|
136
|
-
isStateful: true,
|
|
137
|
-
state: undefined
|
|
138
|
-
});
|
|
139
|
-
if (validationPlan.operation !== ResourceOperation.CREATE) {
|
|
140
|
-
throw new Error(`Resource was not successfully destroyed.
|
|
141
|
-
Validation plan shows:
|
|
142
|
-
${JSON.stringify(validationPlan, null, 2)}
|
|
143
|
-
`);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
111
|
if (options?.validateDestroy) {
|
|
147
112
|
await options.validateDestroy(plans);
|
|
148
113
|
}
|
|
@@ -223,7 +188,6 @@ async function sudoSpawn(cmd, opts) {
|
|
|
223
188
|
return new Promise((resolve) => {
|
|
224
189
|
const output = [];
|
|
225
190
|
const _cmd = `sudo ${cmd}`;
|
|
226
|
-
console.log(`Running command with sudo: ${cmd}`);
|
|
227
191
|
const _process = spawn(`source ~/.zshrc; ${_cmd}`, [], {
|
|
228
192
|
...opts,
|
|
229
193
|
shell: 'zsh',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-tester.js","sourceRoot":"","sources":["../src/plugin-tester.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAKL,gBAAgB,
|
|
1
|
+
{"version":3,"file":"plugin-tester.js","sourceRoot":"","sources":["../src/plugin-tester.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAKL,gBAAgB,EAEhB,UAAU,EAIV,iBAAiB,EACjB,WAAW,EAEX,qBAAqB,EAGtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,OAAO,MAAM,gBAAgB,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAA8B,IAAI,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC7E,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC;IAC1B,MAAM,EAAE,IAAI;CACb,CAAC,CAAC;AACH,MAAM,mBAAmB,GAAG,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAC1D,MAAM,oBAAoB,GAAG,GAAG,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;AAGhE,MAAM,OAAO,YAAY;IACvB,YAAY,CAAc;IAO1B,YAAY,UAAkB;QAC5B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;QAC7E,CAAC;QAED,IAAI,CAAC,YAAY,GAAG,IAAI,CACtB,UAAU,EACV,EAAE,EACF;YAGE,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE;YACvB,QAAQ,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,gBAAgB,CAAC;SACpD,CACF,CAAA;QAED,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,QAAQ,CACZ,OAAyB,EACzB,OAUD;QACC,MAAM,EACJ,aAAa,GAAG,KAAK,GACtB,GAAG,OAAO,IAAI,EAAE,CAAA;QAEjB,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QAEjD,MAAM,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAG,EAAE,CAC/C,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC,CACvE,CAAA;QACD,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,iEAAiE,IAAI,CAAC,SAAS,CAAC,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC,yBAAyB,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAA;QAC1L,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QAElD,MAAM,cAAc,GAAG,QAAQ,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;QAC7E,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,6CAA6C,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAA;QACzG,CAAC;QAED,MAAM,KAAK,GAAG,EAAE,CAAC;QACjB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC;gBACzB,OAAO,EAAE,MAAM;gBACf,UAAU,EAAE,KAAK;gBACjB,KAAK,EAAE,SAAS;aACjB,CAAC,CAAC,CAAC;QACN,CAAC;QAED,IAAI,OAAO,EAAE,YAAY,EAAE,CAAC;YAC1B,MAAM,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACpC,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,IAAI,CAAC,KAAK,CAAC;gBACf,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CAAC;QACL,CAAC;QAED,IAAI,OAAO,EAAE,aAAa,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC;QAED,MAAM,aAAa,GAAG,EAAE,CAAC;QACzB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;YAClD,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACnC,CAAC;QAED,IAAI,OAAO,EAAE,cAAc,EAAE,CAAC;YAC5B,MAAM,OAAO,CAAC,cAAc,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACtE,CAAC;QAED,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC;YACxB,MAAM,WAAW,GAAG,EAAE,CAAC;YACvB,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,UAAU,CAAC,eAAe,EAAE,CAAC;gBACxD,WAAW,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC;oBAC/B,OAAO,EAAE,MAAM;oBACf,UAAU,EAAE,KAAK;oBACjB,KAAK,EAAE,SAAS;iBACjB,CAAC,CAAC,CAAC;YACN,CAAC;YAED,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC;gBACtE,MAAM,IAAI,KAAK,CAAC;EACtB,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAA;YACnC,CAAC;YAED,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;gBAC/B,MAAM,IAAI,CAAC,KAAK,CAAC;oBACf,MAAM,EAAE,IAAI,CAAC,MAAM;iBACpB,CAAC,CAAC;YACL,CAAC;YAED,IAAI,OAAO,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC;gBACtC,MAAM,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QAED,IAAI,CAAC,aAAa,EAAE,CAAC;YAEnB,MAAM,gBAAgB,GAAG,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;YACzD,MAAM,eAAe,GAAG,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,UAAU,EAAE,eAAe,IAAI,EAAE,CAAC,CAAA;YAE1F,MAAM,EAAE,GAAG,CAAC,MAAsB,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;YAE3F,MAAM,gBAAgB,GAAG,OAAO,CAAC,eAAe,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAC;YACxE,MAAM,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,OAAyB,EAAE,OAE1C;QACC,MAAM,KAAK,GAAG,EAAE,CAAC;QAEjB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC;gBACzB,OAAO,EAAE,SAAS;gBAClB,UAAU,EAAE,IAAI;gBAChB,KAAK,EAAE,MAAM;aACd,CAAC,CAAC,CAAA;QACL,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,SAAS,KAAK,iBAAiB,CAAC,OAAO,EAAE,CAAC;gBACjD,MAAM,IAAI,KAAK,CAAC,2EAA2E,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAA;YAC7H,CAAC;YAED,MAAM,IAAI,CAAC,KAAK,CAAC;gBACf,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CAAC;QACL,CAAC;QAED,IAAI,OAAO,EAAE,eAAe,EAAE,CAAC;YAC7B,MAAM,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,UAAU;QACd,OAAO,eAAe,CAAC,2BAA2B,CAAC,IAAI,CAAC,YAAY,EAAE;YACpE,GAAG,EAAE,YAAY;YACjB,IAAI,EAAE,EAAE;YACR,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;SACrB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAyB;QACtC,OAAO,eAAe,CAAC,2BAA2B,CAAC,IAAI,CAAC,YAAY,EAAE;YACpE,GAAG,EAAE,UAAU;YACf,IAAI;YACJ,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;SACrB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAqB;QAC9B,OAAO,eAAe,CAAC,2BAA2B,CAAC,IAAI,CAAC,YAAY,EAAE;YACpE,GAAG,EAAE,MAAM;YACX,IAAI;YACJ,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;SACrB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,IAAsB;QAChC,OAAO,eAAe,CAAC,2BAA2B,CAAC,IAAI,CAAC,YAAY,EAAE;YACpE,GAAG,EAAE,OAAO;YACZ,IAAI;YACJ,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;SACrB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAuB;QAClC,OAAO,eAAe,CAAC,2BAA2B,CAAC,IAAI,CAAC,YAAY,EAAE;YACpE,GAAG,EAAE,QAAQ;YACb,IAAI;YACJ,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;SACrB,CAAC,CAAC;IACL,CAAC;IAED,IAAI;QACF,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;IAC3B,CAAC;IAEO,kBAAkB,CAAC,OAAqB;QAE9C,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACtC,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC;gBAClC,MAAM,IAAI,KAAK,CAAC,gCAAgC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YACtF,CAAC;YAED,IAAI,OAAO,CAAC,GAAG,KAAK,UAAU,CAAC,YAAY,EAAE,CAAC;gBAC5C,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;gBACpC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC;oBAChC,MAAM,IAAI,KAAK,CAAC,qCAAqC,IAAI,CAAC,SAAS,CAAC,oBAAoB,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC/G,CAAC;gBAED,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,IAAkC,CAAC;gBAEhE,OAAO,CAAC,GAAG,CAAC,oCAAoC,OAAO,GAAG,CAAC,CAAA;gBAC3D,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAEjD,OAAO,CAAC,IAAI,CAAe;oBACzB,GAAG,EAAE,UAAU,CAAC,YAAY,GAAG,WAAW;oBAC1C,IAAI,EAAE,MAAM;oBACZ,SAAS;iBACV,CAAC,CAAA;YACJ,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAEO,iBAAiB,CAAC,OAAyB;QACjD,MAAM,gBAAgB,GAAG,IAAI,KAAK,EAAkB,CAAC;QAErD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACpD,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC3B,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;YAC/D,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC/B,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAA,CAAC,CAAC,CAAC,CAAC;YAC7E,CAAC;YAED,gBAAgB,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,CAAC;QAC5C,CAAC;QAED,OAAO,gBAAgB,CAAC;IAC1B,CAAC;CACF;AAkBD,KAAK,UAAU,SAAS,CACtB,GAAW,EACX,IAAwB;IAExB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,MAAM,IAAI,GAAG,QAAQ,GAAG,EAAE,CAAC;QAI3B,MAAM,QAAQ,GAAG,KAAK,CAAC,oBAAoB,IAAI,EAAE,EAAE,EAAE,EAAE;YACrD,GAAG,IAAI;YACP,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC;QAEH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAA;QACnC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAC3B,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAE3B,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAA;QAEF,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAA;QAEF,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAE5B,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAC5B,OAAO,CAAC;gBACN,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrB,MAAM,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK;aAC7D,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codify-plugin-test",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.32",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"ajv": "^8.12.0",
|
|
17
17
|
"ajv-formats": "^3.0.1",
|
|
18
|
-
"codify-schemas": "1.0.
|
|
18
|
+
"codify-schemas": "1.0.54",
|
|
19
19
|
"lodash.matches": "^4.6.0",
|
|
20
20
|
"lodash.differencewith": "4.5.0",
|
|
21
21
|
"lodash.unionby": "^4.8.0",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"tsx": "^4.7.3",
|
|
36
36
|
"typescript": "^5",
|
|
37
37
|
"vitest": "^1.4.0",
|
|
38
|
-
"codify-plugin-lib": "1.0.
|
|
38
|
+
"codify-plugin-lib": "1.0.117"
|
|
39
39
|
},
|
|
40
40
|
"engines": {
|
|
41
41
|
"node": ">=18.0.0"
|
package/src/plugin-tester.ts
CHANGED
|
@@ -4,7 +4,8 @@ import {
|
|
|
4
4
|
ImportRequestData,
|
|
5
5
|
ImportResponseData,
|
|
6
6
|
InitializeResponseData,
|
|
7
|
-
IpcMessageSchema,
|
|
7
|
+
IpcMessageSchema,
|
|
8
|
+
IpcMessageV2,
|
|
8
9
|
MessageCmd,
|
|
9
10
|
PlanRequestData,
|
|
10
11
|
PlanResponseData,
|
|
@@ -17,11 +18,11 @@ import {
|
|
|
17
18
|
ValidateResponseData
|
|
18
19
|
} from 'codify-schemas';
|
|
19
20
|
import unionBy from 'lodash.unionby';
|
|
21
|
+
import { nanoid } from 'nanoid';
|
|
20
22
|
import { ChildProcess, SpawnOptions, fork, spawn } from 'node:child_process';
|
|
21
23
|
import path from 'node:path';
|
|
22
24
|
|
|
23
25
|
import { CodifyTestUtils } from './test-utils.js';
|
|
24
|
-
import { nanoid } from 'nanoid';
|
|
25
26
|
|
|
26
27
|
const ajv = new Ajv.default({
|
|
27
28
|
strict: true
|
|
@@ -109,42 +110,14 @@ export class PluginTester {
|
|
|
109
110
|
});
|
|
110
111
|
}
|
|
111
112
|
|
|
112
|
-
// Check that all applys were successful by re-planning
|
|
113
|
-
const validationPlans = [];
|
|
114
|
-
for (const config of configs) {
|
|
115
|
-
validationPlans.push(await this.plan({
|
|
116
|
-
desired: config,
|
|
117
|
-
isStateful: false,
|
|
118
|
-
state: undefined,
|
|
119
|
-
}));
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const unsuccessfulPlans = validationPlans.filter((p) => p.operation !== ResourceOperation.NOOP);
|
|
123
|
-
if (unsuccessfulPlans.length > 0) {
|
|
124
|
-
throw new Error(`The following applies were not successful. Re-running plan shows that the resources did not return no-op but instead returned:
|
|
125
|
-
${JSON.stringify(unsuccessfulPlans, null, 2)}`
|
|
126
|
-
)
|
|
127
|
-
}
|
|
128
|
-
|
|
129
113
|
if (options?.validateApply) {
|
|
130
114
|
await options.validateApply(plans);
|
|
131
115
|
}
|
|
132
116
|
|
|
133
117
|
const importResults = [];
|
|
134
|
-
const unsuccessfulImports = [];
|
|
135
118
|
for (const config of configs) {
|
|
136
119
|
const importResult = await this.import({ config })
|
|
137
120
|
importResults.push(importResult);
|
|
138
|
-
|
|
139
|
-
const validationPlan = await this.plan({ desired: importResult.result[0], isStateful: false, state: undefined });
|
|
140
|
-
if (validationPlan.operation !== ResourceOperation.NOOP) {
|
|
141
|
-
unsuccessfulImports.push(importResult);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
if (unsuccessfulImports.length > 0) {
|
|
146
|
-
throw new Error(`The following imports were not successful. The imports differed from the original.
|
|
147
|
-
${JSON.stringify(unsuccessfulImports, null, 2)}`);
|
|
148
121
|
}
|
|
149
122
|
|
|
150
123
|
if (options?.validateImport) {
|
|
@@ -212,21 +185,6 @@ ${JSON.stringify(modifyPlans, null, 2)}`)
|
|
|
212
185
|
});
|
|
213
186
|
}
|
|
214
187
|
|
|
215
|
-
// Validate that the destroy was successful
|
|
216
|
-
for (const config of configs) {
|
|
217
|
-
const validationPlan = await this.plan({
|
|
218
|
-
desired: config,
|
|
219
|
-
isStateful: true,
|
|
220
|
-
state: undefined
|
|
221
|
-
})
|
|
222
|
-
if (validationPlan.operation !== ResourceOperation.CREATE) {
|
|
223
|
-
throw new Error(`Resource was not successfully destroyed.
|
|
224
|
-
Validation plan shows:
|
|
225
|
-
${JSON.stringify(validationPlan, null, 2)}
|
|
226
|
-
`);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
188
|
if (options?.validateDestroy) {
|
|
231
189
|
await options.validateDestroy(plans);
|
|
232
190
|
}
|
|
@@ -344,7 +302,6 @@ async function sudoSpawn(
|
|
|
344
302
|
const output: string[] = [];
|
|
345
303
|
|
|
346
304
|
const _cmd = `sudo ${cmd}`;
|
|
347
|
-
console.log(`Running command with sudo: ${cmd}`);
|
|
348
305
|
|
|
349
306
|
// Source start up shells to emulate a users environment vs. a non-interactive non-login shell script
|
|
350
307
|
// Ignore all stdin
|
package/src/test-utils.test.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { Readable } from 'stream';
|
|
|
4
4
|
import { CodifyTestUtils } from './test-utils.js';
|
|
5
5
|
import { describe, expect, it, vi } from 'vitest';
|
|
6
6
|
import { MessageStatus } from 'codify-schemas';
|
|
7
|
+
import { nanoid } from 'nanoid';
|
|
7
8
|
|
|
8
9
|
describe('Test Utils tests', async () => {
|
|
9
10
|
|
|
@@ -19,23 +20,25 @@ describe('Test Utils tests', async () => {
|
|
|
19
20
|
it('Sends the message that was passed in', async () => {
|
|
20
21
|
const process = mockChildProcess();
|
|
21
22
|
const sendMock = vi.spyOn(process, 'send');
|
|
23
|
+
const requestId = nanoid(6);
|
|
22
24
|
|
|
23
|
-
CodifyTestUtils.sendMessageAndAwaitResponse(process, { cmd: 'message', data: 'data' })
|
|
25
|
+
CodifyTestUtils.sendMessageAndAwaitResponse(process, { cmd: 'message', data: 'data', requestId })
|
|
24
26
|
|
|
25
27
|
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 });
|
|
27
29
|
})
|
|
28
30
|
|
|
29
31
|
it('Send a message and receives a response from a plugin (success)', async () => {
|
|
30
32
|
const process = mockChildProcess();
|
|
33
|
+
const requestId = nanoid(6);
|
|
31
34
|
|
|
32
35
|
const result = await Promise.all([
|
|
33
36
|
(async () => {
|
|
34
37
|
await sleep(30);
|
|
35
38
|
// 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 })
|
|
37
40
|
})(),
|
|
38
|
-
CodifyTestUtils.sendMessageAndAwaitResponse(process, { cmd: 'message', data: 'data' }),
|
|
41
|
+
CodifyTestUtils.sendMessageAndAwaitResponse(process, { cmd: 'message', data: 'data', requestId }),
|
|
39
42
|
]);
|
|
40
43
|
|
|
41
44
|
expect(result[1]).to.eq('data')
|
|
@@ -43,30 +46,31 @@ describe('Test Utils tests', async () => {
|
|
|
43
46
|
|
|
44
47
|
it('Send a message and can handle errors', async () => {
|
|
45
48
|
const process = mockChildProcess();
|
|
49
|
+
const requestId = nanoid(6);
|
|
46
50
|
|
|
47
51
|
expect(async () => Promise.all([
|
|
48
52
|
(async () => {
|
|
49
53
|
await sleep(30);
|
|
50
54
|
// 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 })
|
|
52
56
|
})(),
|
|
53
|
-
CodifyTestUtils.sendMessageAndAwaitResponse(process, { cmd: 'message', data: 'data' }),
|
|
57
|
+
CodifyTestUtils.sendMessageAndAwaitResponse(process, { cmd: 'message', data: 'data', requestId }),
|
|
54
58
|
])).rejects.toThrowError(new Error('error message'))
|
|
55
59
|
});
|
|
56
60
|
|
|
57
61
|
it('Ignores other IPC messages', async () => {
|
|
58
62
|
const process = mockChildProcess();
|
|
59
63
|
|
|
64
|
+
const requestId = nanoid(6);
|
|
65
|
+
|
|
60
66
|
const result = await Promise.all([
|
|
61
67
|
(async () => {
|
|
62
68
|
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 })
|
|
68
72
|
})(),
|
|
69
|
-
CodifyTestUtils.sendMessageAndAwaitResponse(process, { cmd: 'message', data: 'data' }),
|
|
73
|
+
CodifyTestUtils.sendMessageAndAwaitResponse(process, { cmd: 'message', data: 'data', requestId }),
|
|
70
74
|
]);
|
|
71
75
|
|
|
72
76
|
// Only the final _Response message should be returned.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
2
2
|
import { PluginTester } from '../src/index.js';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { ResourceOperation } from 'codify-schemas/src/types/index.js';
|
|
@@ -7,20 +7,35 @@ import differenceWith from 'lodash.differencewith';
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
describe('Plugin tester integration tests', () => {
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
let plugin: PluginTester;
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
|
|
13
|
+
})
|
|
12
14
|
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
plugin.kill();
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
it('Can instantiate a plugin', async () => {
|
|
13
20
|
expect(plugin.childProcess.pid).to.not.be.undefined;
|
|
14
21
|
expect(plugin.childProcess.stdout).to.not.be.undefined;
|
|
15
22
|
expect(plugin.childProcess.stderr).to.not.be.undefined;
|
|
16
23
|
expect(plugin.childProcess.channel).to.not.be.undefined;
|
|
17
24
|
|
|
18
|
-
await plugin.initialize();
|
|
25
|
+
const result = await plugin.initialize();
|
|
26
|
+
expect(result).toMatchObject({
|
|
27
|
+
resourceDefinitions: [
|
|
28
|
+
{ dependencies: [], type: 'test' },
|
|
29
|
+
{ dependencies: [], type: 'test2' },
|
|
30
|
+
{ dependencies: [], type: 'test-uninstall' },
|
|
31
|
+
{ dependencies: [], type: 'test-modify' },
|
|
32
|
+
{ dependencies: [], type: 'test-destroy' },
|
|
33
|
+
{ dependencies: [], type: 'test-destroy-2' }
|
|
34
|
+
]
|
|
35
|
+
})
|
|
19
36
|
})
|
|
20
37
|
|
|
21
38
|
it('Can validate a config', async () => {
|
|
22
|
-
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
|
|
23
|
-
|
|
24
39
|
const result = await plugin.validate({
|
|
25
40
|
configs: [{
|
|
26
41
|
type: 'test',
|
|
@@ -36,8 +51,6 @@ describe('Plugin tester integration tests', () => {
|
|
|
36
51
|
})
|
|
37
52
|
|
|
38
53
|
it('Can generate a plan', async () => {
|
|
39
|
-
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
|
|
40
|
-
|
|
41
54
|
const result = await plugin.plan({
|
|
42
55
|
desired: {
|
|
43
56
|
type: 'test',
|
|
@@ -57,8 +70,6 @@ describe('Plugin tester integration tests', () => {
|
|
|
57
70
|
})
|
|
58
71
|
|
|
59
72
|
it('Can generate a plan', async () => {
|
|
60
|
-
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
|
|
61
|
-
|
|
62
73
|
const result = await plugin.plan({
|
|
63
74
|
desired: {
|
|
64
75
|
type: 'test',
|
|
@@ -78,8 +89,6 @@ describe('Plugin tester integration tests', () => {
|
|
|
78
89
|
})
|
|
79
90
|
|
|
80
91
|
it('Can apply a plan', async () => {
|
|
81
|
-
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
|
|
82
|
-
|
|
83
92
|
const plan = await plugin.plan({
|
|
84
93
|
desired: {
|
|
85
94
|
type: 'test',
|
|
@@ -96,8 +105,6 @@ describe('Plugin tester integration tests', () => {
|
|
|
96
105
|
})
|
|
97
106
|
|
|
98
107
|
it('Handles errors that are thrown', async () => {
|
|
99
|
-
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
|
|
100
|
-
|
|
101
108
|
expect(async () => plugin.plan({
|
|
102
109
|
desired: {
|
|
103
110
|
type: 'test',
|
|
@@ -112,8 +119,6 @@ describe('Plugin tester integration tests', () => {
|
|
|
112
119
|
})
|
|
113
120
|
|
|
114
121
|
it('Has helpers that can test a resource', async () => {
|
|
115
|
-
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
|
|
116
|
-
|
|
117
122
|
// No expect needed here. This passes if it doesn't throw.
|
|
118
123
|
await plugin.fullTest([{
|
|
119
124
|
type: 'test',
|
|
@@ -131,8 +136,6 @@ describe('Plugin tester integration tests', () => {
|
|
|
131
136
|
})
|
|
132
137
|
|
|
133
138
|
it('Full test supports plan assertions to ensure the generated plan is correct', async () => {
|
|
134
|
-
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
|
|
135
|
-
|
|
136
139
|
// No expect needed here. This passes if it doesn't throw.
|
|
137
140
|
await plugin.fullTest([{
|
|
138
141
|
type: 'test',
|
|
@@ -163,8 +166,6 @@ describe('Plugin tester integration tests', () => {
|
|
|
163
166
|
})
|
|
164
167
|
|
|
165
168
|
it('Full test supports plan assertions to ensure the generated plan is correct (2)', async () => {
|
|
166
|
-
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
|
|
167
|
-
|
|
168
169
|
// No expect needed here. This passes if it doesn't throw.
|
|
169
170
|
await plugin.fullTest([{
|
|
170
171
|
type: 'test',
|
|
@@ -183,8 +184,6 @@ describe('Plugin tester integration tests', () => {
|
|
|
183
184
|
})
|
|
184
185
|
|
|
185
186
|
it('Full test supports plan assertions to ensure the generated plan is correct (3)', async () => {
|
|
186
|
-
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
|
|
187
|
-
|
|
188
187
|
console.log(differenceWith(['b', 'a'], ['a', 'b', 'c'], (a, b) => deepMatches(a)(b)).length === 0);
|
|
189
188
|
|
|
190
189
|
// No expect needed here. This passes if it doesn't throw.
|
|
@@ -198,8 +197,6 @@ describe('Plugin tester integration tests', () => {
|
|
|
198
197
|
})
|
|
199
198
|
|
|
200
199
|
it('Has helpers that can uninstall a resource', async () => {
|
|
201
|
-
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
|
|
202
|
-
|
|
203
200
|
// No expect needed here. This passes if it doesn't throw.
|
|
204
201
|
await plugin.uninstall([{
|
|
205
202
|
type: 'test-uninstall',
|
|
@@ -210,22 +207,20 @@ describe('Plugin tester integration tests', () => {
|
|
|
210
207
|
})
|
|
211
208
|
|
|
212
209
|
it('Has helpers that can uninstall a resource (errors out when unsuccessful)', async () => {
|
|
213
|
-
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
|
|
214
|
-
|
|
215
|
-
// No expect needed here. This passes if it doesn't throw.
|
|
216
|
-
expect(async () => plugin.uninstall([{
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
}])).rejects.toThrowError();
|
|
210
|
+
// const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
|
|
211
|
+
//
|
|
212
|
+
// // No expect needed here. This passes if it doesn't throw.
|
|
213
|
+
// await expect(async () => plugin.uninstall([{
|
|
214
|
+
// type: 'test',
|
|
215
|
+
// propA: 'a',
|
|
216
|
+
// propB: 10,
|
|
217
|
+
// propC: 'c',
|
|
218
|
+
// }])).rejects.toThrowError();
|
|
222
219
|
})
|
|
223
220
|
|
|
224
221
|
|
|
225
222
|
it('Can test modify', { timeout: 50000000 }, async () => {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
await plugin.fullTest([{
|
|
223
|
+
await expect(() => plugin.fullTest([{
|
|
229
224
|
type: 'test-modify',
|
|
230
225
|
propA: 'a',
|
|
231
226
|
propB: 10,
|
|
@@ -238,48 +233,46 @@ describe('Plugin tester integration tests', () => {
|
|
|
238
233
|
propB: 10,
|
|
239
234
|
}]
|
|
240
235
|
}
|
|
241
|
-
})
|
|
236
|
+
})).rejects.toThrowError();
|
|
242
237
|
})
|
|
243
238
|
|
|
244
239
|
it('Will call destory with the correct parameters (modify)', { timeout: 50000000 }, async () => {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
`
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
}
|
|
276
|
-
`
|
|
277
|
-
|
|
240
|
+
// const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
|
|
241
|
+
//
|
|
242
|
+
// await expect(async () => await plugin.fullTest([{
|
|
243
|
+
// type: 'test-modify',
|
|
244
|
+
// propA: 'a',
|
|
245
|
+
// propB: 10,
|
|
246
|
+
// }], {
|
|
247
|
+
// testModify: {
|
|
248
|
+
// modifiedConfigs: [{
|
|
249
|
+
// type: 'test-modify',
|
|
250
|
+
// propA: 'Modify',
|
|
251
|
+
// propB: 10,
|
|
252
|
+
// }]
|
|
253
|
+
// }
|
|
254
|
+
// })).rejects.toThrow(
|
|
255
|
+
// `
|
|
256
|
+
// "parameters": [
|
|
257
|
+
// {
|
|
258
|
+
// "name": "propA",
|
|
259
|
+
// "previousValue": "Modify__",
|
|
260
|
+
// "newValue": "Modify",
|
|
261
|
+
// "operation": "modify"
|
|
262
|
+
// },
|
|
263
|
+
// {
|
|
264
|
+
// "name": "propB",
|
|
265
|
+
// "previousValue": "10",
|
|
266
|
+
// "newValue": "10",
|
|
267
|
+
// "operation": "noop"
|
|
268
|
+
// }
|
|
269
|
+
// ]
|
|
270
|
+
// }
|
|
271
|
+
// `
|
|
272
|
+
// )
|
|
278
273
|
})
|
|
279
274
|
|
|
280
275
|
it('Works when uninstalling two resources', async () => {
|
|
281
|
-
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
|
|
282
|
-
|
|
283
276
|
await plugin.fullTest([{
|
|
284
277
|
type: 'test-destroy',
|
|
285
278
|
propA: 'a',
|
|
@@ -304,8 +297,6 @@ describe('Plugin tester integration tests', () => {
|
|
|
304
297
|
})
|
|
305
298
|
|
|
306
299
|
it('Can uninstall two resources with the same type', async () => {
|
|
307
|
-
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
|
|
308
|
-
|
|
309
300
|
await plugin.fullTest([{
|
|
310
301
|
type: 'test-destroy',
|
|
311
302
|
propA: 'a',
|