codify-plugin-test 0.0.2 → 0.0.4
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.d.ts +3 -1
- package/dist/plugin-tester.js +35 -4
- package/dist/plugin-tester.js.map +1 -1
- package/package.json +1 -1
- package/src/plugin-tester.ts +52 -8
- package/test/plugin-tester.test.ts +56 -4
- package/test/test-plugin.ts +25 -0
package/dist/plugin-tester.d.ts
CHANGED
|
@@ -4,10 +4,12 @@ import { ChildProcess } from 'node:child_process';
|
|
|
4
4
|
export declare class PluginTester {
|
|
5
5
|
childProcess: ChildProcess;
|
|
6
6
|
constructor(pluginPath: string);
|
|
7
|
-
|
|
7
|
+
fullTest(configs: ResourceConfig[], assertPlans?: (plans: PlanResponseData[]) => void): Promise<void>;
|
|
8
|
+
uninstall(configs: ResourceConfig[]): Promise<void>;
|
|
8
9
|
initialize(): Promise<InitializeResponseData>;
|
|
9
10
|
validate(data: ValidateRequestData): Promise<ValidateResponseData>;
|
|
10
11
|
plan(data: PlanRequestData): Promise<PlanResponseData>;
|
|
11
12
|
apply(data: ApplyRequestData): Promise<void>;
|
|
13
|
+
kill(): void;
|
|
12
14
|
private handleSudoRequests;
|
|
13
15
|
}
|
package/dist/plugin-tester.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import Ajv2020 from 'ajv/dist/2020.js';
|
|
2
|
-
import { IpcMessageSchema, MessageCmd, ResourceOperation, SpawnStatus, SudoRequestDataSchema } from 'codify-schemas';
|
|
2
|
+
import { IpcMessageSchema, MessageCmd, ParameterOperation, ResourceOperation, SpawnStatus, SudoRequestDataSchema } from 'codify-schemas';
|
|
3
3
|
import { fork, spawn } from 'node:child_process';
|
|
4
|
-
import { CodifyTestUtils } from './test-utils.js';
|
|
5
4
|
import path from 'node:path';
|
|
5
|
+
import { CodifyTestUtils } from './test-utils.js';
|
|
6
6
|
const ajv = new Ajv2020.default({
|
|
7
7
|
strict: true
|
|
8
8
|
});
|
|
@@ -21,7 +21,7 @@ export class PluginTester {
|
|
|
21
21
|
});
|
|
22
22
|
this.handleSudoRequests(this.childProcess);
|
|
23
23
|
}
|
|
24
|
-
async
|
|
24
|
+
async fullTest(configs, assertPlans) {
|
|
25
25
|
const initializeResult = await this.initialize();
|
|
26
26
|
const unsupportedConfigs = configs.filter((c) => !initializeResult.resourceDefinitions.some((rd) => rd.type === c.type));
|
|
27
27
|
if (unsupportedConfigs.length > 0) {
|
|
@@ -36,6 +36,9 @@ export class PluginTester {
|
|
|
36
36
|
for (const config of configs) {
|
|
37
37
|
plans.push(await this.plan(config));
|
|
38
38
|
}
|
|
39
|
+
if (assertPlans) {
|
|
40
|
+
assertPlans(plans);
|
|
41
|
+
}
|
|
39
42
|
for (const plan of plans) {
|
|
40
43
|
await this.apply({
|
|
41
44
|
planId: plan.planId
|
|
@@ -48,7 +51,32 @@ export class PluginTester {
|
|
|
48
51
|
const unsuccessfulPlans = validationPlans.filter((p) => p.operation !== ResourceOperation.NOOP);
|
|
49
52
|
if (unsuccessfulPlans.length > 0) {
|
|
50
53
|
throw new Error(`The following applies were not successful. Re-running plan shows that the resources did not return no-op but instead returned:
|
|
51
|
-
|
|
54
|
+
${JSON.stringify(unsuccessfulPlans, null, 2)}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async uninstall(configs) {
|
|
58
|
+
for (const config of configs) {
|
|
59
|
+
const { dependsOn, name, type, ...parameters } = config;
|
|
60
|
+
await this.apply({
|
|
61
|
+
plan: {
|
|
62
|
+
operation: ResourceOperation.DESTROY,
|
|
63
|
+
parameters: Object.entries(parameters).map(([key, value]) => ({
|
|
64
|
+
name: key,
|
|
65
|
+
newValue: null,
|
|
66
|
+
operation: ParameterOperation.REMOVE,
|
|
67
|
+
previousValue: value,
|
|
68
|
+
})),
|
|
69
|
+
resourceType: type,
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
const validationPlan = await this.plan(config);
|
|
73
|
+
if (validationPlan.operation !== ResourceOperation.CREATE) {
|
|
74
|
+
throw new Error(`Resource ${type} was not successfully destroyed.
|
|
75
|
+
Validation plan shows:
|
|
76
|
+
${JSON.stringify(validationPlan, null, 2)}
|
|
77
|
+
Previous config:
|
|
78
|
+
${JSON.stringify(config, null, 2)}`);
|
|
79
|
+
}
|
|
52
80
|
}
|
|
53
81
|
}
|
|
54
82
|
async initialize() {
|
|
@@ -75,6 +103,9 @@ export class PluginTester {
|
|
|
75
103
|
data,
|
|
76
104
|
});
|
|
77
105
|
}
|
|
106
|
+
kill() {
|
|
107
|
+
this.childProcess.kill();
|
|
108
|
+
}
|
|
78
109
|
handleSudoRequests(process) {
|
|
79
110
|
process.on('message', async (message) => {
|
|
80
111
|
if (!ipcMessageValidator(message)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-tester.js","sourceRoot":"","sources":["../src/plugin-tester.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,kBAAkB,CAAC;AACvC,OAAO,
|
|
1
|
+
{"version":3,"file":"plugin-tester.js","sourceRoot":"","sources":["../src/plugin-tester.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/plugin-tester.ts
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
import Ajv2020 from 'ajv/dist/2020.js';
|
|
2
2
|
import {
|
|
3
|
-
ApplyRequestData,
|
|
3
|
+
ApplyRequestData,
|
|
4
|
+
InitializeResponseData,
|
|
5
|
+
IpcMessageSchema,
|
|
4
6
|
MessageCmd,
|
|
7
|
+
ParameterOperation,
|
|
5
8
|
PlanRequestData,
|
|
6
|
-
PlanResponseData,
|
|
9
|
+
PlanResponseData,
|
|
10
|
+
ResourceConfig,
|
|
11
|
+
ResourceOperation,
|
|
7
12
|
SpawnStatus,
|
|
8
|
-
SudoRequestData,
|
|
13
|
+
SudoRequestData,
|
|
14
|
+
SudoRequestDataSchema,
|
|
15
|
+
ValidateRequestData,
|
|
16
|
+
ValidateResponseData
|
|
9
17
|
} from 'codify-schemas';
|
|
10
18
|
import { ChildProcess, SpawnOptions, fork, spawn } from 'node:child_process';
|
|
19
|
+
import path from 'node:path';
|
|
11
20
|
|
|
12
21
|
import { CodifyTestUtils } from './test-utils.js';
|
|
13
|
-
import path from 'node:path';
|
|
14
22
|
|
|
15
23
|
const ajv = new Ajv2020.default({
|
|
16
24
|
strict: true
|
|
@@ -45,7 +53,7 @@ export class PluginTester {
|
|
|
45
53
|
this.handleSudoRequests(this.childProcess);
|
|
46
54
|
}
|
|
47
55
|
|
|
48
|
-
async
|
|
56
|
+
async fullTest(configs: ResourceConfig[], assertPlans?: (plans: PlanResponseData[]) => void): Promise<void> {
|
|
49
57
|
const initializeResult = await this.initialize();
|
|
50
58
|
|
|
51
59
|
const unsupportedConfigs = configs.filter((c) =>
|
|
@@ -67,6 +75,10 @@ export class PluginTester {
|
|
|
67
75
|
plans.push(await this.plan(config));
|
|
68
76
|
}
|
|
69
77
|
|
|
78
|
+
if (assertPlans) {
|
|
79
|
+
assertPlans(plans);
|
|
80
|
+
}
|
|
81
|
+
|
|
70
82
|
for (const plan of plans) {
|
|
71
83
|
await this.apply({
|
|
72
84
|
planId: plan.planId
|
|
@@ -82,11 +94,41 @@ export class PluginTester {
|
|
|
82
94
|
const unsuccessfulPlans = validationPlans.filter((p) => p.operation !== ResourceOperation.NOOP);
|
|
83
95
|
if (unsuccessfulPlans.length > 0) {
|
|
84
96
|
throw new Error(`The following applies were not successful. Re-running plan shows that the resources did not return no-op but instead returned:
|
|
85
|
-
|
|
97
|
+
${JSON.stringify(unsuccessfulPlans, null, 2)}`
|
|
86
98
|
)
|
|
87
99
|
}
|
|
88
100
|
}
|
|
89
101
|
|
|
102
|
+
async uninstall(configs: ResourceConfig[]) {
|
|
103
|
+
for (const config of configs) {
|
|
104
|
+
const { dependsOn, name, type, ...parameters } = config
|
|
105
|
+
|
|
106
|
+
await this.apply({
|
|
107
|
+
plan: {
|
|
108
|
+
operation: ResourceOperation.DESTROY,
|
|
109
|
+
parameters: Object.entries(parameters).map(([key, value]) => ({
|
|
110
|
+
name: key,
|
|
111
|
+
newValue: null,
|
|
112
|
+
operation: ParameterOperation.REMOVE,
|
|
113
|
+
previousValue: value,
|
|
114
|
+
})),
|
|
115
|
+
resourceType: type,
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Validate that the destroy was successful
|
|
120
|
+
const validationPlan = await this.plan(config);
|
|
121
|
+
if (validationPlan.operation !== ResourceOperation.CREATE) {
|
|
122
|
+
throw new Error(`Resource ${type} was not successfully destroyed.
|
|
123
|
+
Validation plan shows:
|
|
124
|
+
${JSON.stringify(validationPlan, null, 2)}
|
|
125
|
+
Previous config:
|
|
126
|
+
${JSON.stringify(config, null, 2)}`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
90
132
|
async initialize(): Promise<InitializeResponseData> {
|
|
91
133
|
return CodifyTestUtils.sendMessageAndAwaitResponse(this.childProcess, {
|
|
92
134
|
cmd: 'initialize',
|
|
@@ -114,6 +156,10 @@ export class PluginTester {
|
|
|
114
156
|
data,
|
|
115
157
|
});
|
|
116
158
|
}
|
|
159
|
+
|
|
160
|
+
kill() {
|
|
161
|
+
this.childProcess.kill();
|
|
162
|
+
}
|
|
117
163
|
|
|
118
164
|
private handleSudoRequests(process: ChildProcess) {
|
|
119
165
|
// Listen for incoming sudo incoming sudo requests
|
|
@@ -152,8 +198,6 @@ type CodifySpawnOptions = {
|
|
|
152
198
|
*
|
|
153
199
|
* @param cmd Command to run. Ex: `rm -rf`
|
|
154
200
|
* @param opts Options for spawn
|
|
155
|
-
* @param secureMode Secure mode for sudo
|
|
156
|
-
* @param pluginName Optional plugin name so that stdout and stderr can be piped
|
|
157
201
|
*
|
|
158
202
|
* @see promiseSpawn
|
|
159
203
|
* @see spawn
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { PluginTester } from '../src/
|
|
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';
|
|
5
|
-
import { ParameterOperation } from 'codify-schemas';
|
|
6
5
|
|
|
7
6
|
describe('Plugin tester integration tests', () => {
|
|
8
7
|
it('Can instantiate a plugin', async () => {
|
|
@@ -13,7 +12,7 @@ describe('Plugin tester integration tests', () => {
|
|
|
13
12
|
expect(plugin.childProcess.stderr).to.not.be.undefined;
|
|
14
13
|
expect(plugin.childProcess.channel).to.not.be.undefined;
|
|
15
14
|
|
|
16
|
-
await plugin.initialize(
|
|
15
|
+
await plugin.initialize();
|
|
17
16
|
})
|
|
18
17
|
|
|
19
18
|
it('Can validate a config', async () => {
|
|
@@ -97,7 +96,7 @@ describe('Plugin tester integration tests', () => {
|
|
|
97
96
|
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
|
|
98
97
|
|
|
99
98
|
// No expect needed here. This passes if it doesn't throw.
|
|
100
|
-
await plugin.
|
|
99
|
+
await plugin.fullTest([{
|
|
101
100
|
type: 'test',
|
|
102
101
|
propA: 'a',
|
|
103
102
|
propB: 10,
|
|
@@ -109,4 +108,57 @@ describe('Plugin tester integration tests', () => {
|
|
|
109
108
|
propC: 'c',
|
|
110
109
|
}]);
|
|
111
110
|
})
|
|
111
|
+
|
|
112
|
+
it('Full test supports plan assertions to ensure the generated plan is correct', async () => {
|
|
113
|
+
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
|
|
114
|
+
|
|
115
|
+
// No expect needed here. This passes if it doesn't throw.
|
|
116
|
+
await plugin.fullTest([{
|
|
117
|
+
type: 'test',
|
|
118
|
+
propA: 'a',
|
|
119
|
+
propB: 10,
|
|
120
|
+
propC: 'c',
|
|
121
|
+
}, {
|
|
122
|
+
type: 'test',
|
|
123
|
+
propA: 'a',
|
|
124
|
+
propB: 10,
|
|
125
|
+
propC: 'c',
|
|
126
|
+
}], (plans) => {
|
|
127
|
+
expect(plans[0]).toMatchObject({
|
|
128
|
+
planId: expect.any(String),
|
|
129
|
+
operation: ResourceOperation.NOOP,
|
|
130
|
+
resourceType: 'test',
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
expect(plans[1]).toMatchObject({
|
|
134
|
+
planId: expect.any(String),
|
|
135
|
+
operation: ResourceOperation.NOOP,
|
|
136
|
+
resourceType: 'test',
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
it('Has helpers that can uninstall a resource', async () => {
|
|
142
|
+
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
|
|
143
|
+
|
|
144
|
+
// No expect needed here. This passes if it doesn't throw.
|
|
145
|
+
await plugin.uninstall([{
|
|
146
|
+
type: 'test-uninstall',
|
|
147
|
+
propA: 'a',
|
|
148
|
+
propB: 10,
|
|
149
|
+
propC: 'c',
|
|
150
|
+
}]);
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
it('Has helpers that can uninstall a resource (errors out when unsuccessful)', async () => {
|
|
154
|
+
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
|
|
155
|
+
|
|
156
|
+
// No expect needed here. This passes if it doesn't throw.
|
|
157
|
+
expect(async () => plugin.uninstall([{
|
|
158
|
+
type: 'test',
|
|
159
|
+
propA: 'a',
|
|
160
|
+
propB: 10,
|
|
161
|
+
propC: 'c',
|
|
162
|
+
}])).rejects.toThrowError();
|
|
163
|
+
})
|
|
112
164
|
})
|
package/test/test-plugin.ts
CHANGED
|
@@ -37,12 +37,37 @@ export class TestResource extends Resource<TestConfig> {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
export class TestUninstallResource extends Resource<TestConfig> {
|
|
41
|
+
constructor() {
|
|
42
|
+
super({
|
|
43
|
+
type: 'test-uninstall'
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async applyCreate(plan: Plan<TestConfig>): Promise<void> {}
|
|
48
|
+
|
|
49
|
+
async applyDestroy(plan: Plan<TestConfig>): Promise<void> {}
|
|
50
|
+
|
|
51
|
+
async refresh(keys: Map<string, unknown>): Promise<Partial<TestConfig> | null> {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async validateResource(config: unknown): Promise<ValidationResult> {
|
|
56
|
+
return {
|
|
57
|
+
isValid: true
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
40
62
|
function buildPlugin(): Plugin {
|
|
41
63
|
const resourceMap = new Map();
|
|
42
64
|
|
|
43
65
|
const testResource = new TestResource();
|
|
44
66
|
resourceMap.set(testResource.typeId, testResource);
|
|
45
67
|
|
|
68
|
+
const testUninstallResource = new TestUninstallResource();
|
|
69
|
+
resourceMap.set(testUninstallResource.typeId, testUninstallResource);
|
|
70
|
+
|
|
46
71
|
return new Plugin('test', resourceMap);
|
|
47
72
|
}
|
|
48
73
|
|