Skip to content

Commit f31472a

Browse files
committed
Add uninstall method to PluginTester + tests.
1 parent ca74dcc commit f31472a

6 files changed

Lines changed: 114 additions & 25 deletions

File tree

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "codify-plugin-test",
3-
"version": "0.0.0",
3+
"version": "0.0.3",
44
"description": "",
55
"main": "dist/index.js",
66
"typings": "dist/index.d.ts",
@@ -28,7 +28,7 @@
2828
"tsx": "^4.7.3",
2929
"typescript": "^5",
3030
"vitest": "^1.4.0",
31-
"codify-plugin-lib": "../codify-plugin-lib"
31+
"codify-plugin-lib": "1.0.59"
3232
},
3333
"engines": {
3434
"node": ">=18.0.0"

src/plugin-tester.ts

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
import Ajv2020 from 'ajv/dist/2020.js';
22
import {
3-
ApplyRequestData, InitializeResponseData, IpcMessageSchema,
3+
ApplyRequestData,
4+
InitializeResponseData,
5+
IpcMessageSchema,
46
MessageCmd,
7+
ParameterOperation,
58
PlanRequestData,
6-
PlanResponseData, ResourceConfig, ResourceOperation,
9+
PlanResponseData,
10+
ResourceConfig,
11+
ResourceOperation,
712
SpawnStatus,
8-
SudoRequestData, SudoRequestDataSchema, ValidateRequestData, ValidateResponseData
13+
SudoRequestData,
14+
SudoRequestDataSchema,
15+
ValidateRequestData,
16+
ValidateResponseData
917
} from 'codify-schemas';
10-
import { ChildProcess, SpawnOptions, fork, spawn } from 'node:child_process';
18+
import { ChildProcess, fork, spawn, SpawnOptions } from 'node:child_process';
1119

1220
import { CodifyTestUtils } from './test-utils.js';
1321
import path from 'node:path';
@@ -45,7 +53,7 @@ export class PluginTester {
4553
this.handleSudoRequests(this.childProcess);
4654
}
4755

48-
async test(configs: ResourceConfig[]): Promise<void> {
56+
async fullTest(configs: ResourceConfig[]): Promise<void> {
4957
const initializeResult = await this.initialize();
5058

5159
const unsupportedConfigs = configs.filter((c) =>
@@ -81,7 +89,39 @@ export class PluginTester {
8189

8290
const unsuccessfulPlans = validationPlans.filter((p) => p.operation !== ResourceOperation.NOOP);
8391
if (unsuccessfulPlans.length > 0) {
84-
throw new Error(`The following applies were not successful.\n ${JSON.stringify(unsuccessfulPlans, null, 2)}`)
92+
throw new Error(`The following applies were not successful. Re-running plan shows that the resources did not return no-op but instead returned:
93+
${JSON.stringify(unsuccessfulPlans, null, 2)}`
94+
)
95+
}
96+
}
97+
98+
async uninstall(configs: ResourceConfig[]) {
99+
for (const config of configs) {
100+
const { type, dependsOn, name, ...parameters } = config
101+
102+
await this.apply({
103+
plan: {
104+
operation: ResourceOperation.DESTROY,
105+
resourceType: config.type,
106+
parameters: Object.entries(parameters).map(([key, value]) => ({
107+
name: key,
108+
previousValue: value,
109+
newValue: null,
110+
operation: ParameterOperation.REMOVE,
111+
})),
112+
}
113+
});
114+
115+
// Validate that the destroy was successful
116+
const validationPlan = await this.plan(config);
117+
if (validationPlan.operation !== ResourceOperation.CREATE) {
118+
throw new Error(`Resource ${config.type} was not successfully destroyed.
119+
Validation plan shows:
120+
${JSON.stringify(validationPlan, null, 2)}
121+
Previous config:
122+
${JSON.stringify(config, null, 2)}`
123+
);
124+
}
85125
}
86126
}
87127

test/plugin-tester.test.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ describe('Plugin tester integration tests', () => {
9797
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
9898

9999
// No expect needed here. This passes if it doesn't throw.
100-
await plugin.test([{
100+
await plugin.fullTest([{
101101
type: 'test',
102102
propA: 'a',
103103
propB: 10,
@@ -109,4 +109,28 @@ describe('Plugin tester integration tests', () => {
109109
propC: 'c',
110110
}]);
111111
})
112+
113+
it('Has helpers that can uninstall a resource', async () => {
114+
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
115+
116+
// No expect needed here. This passes if it doesn't throw.
117+
await plugin.uninstall([{
118+
type: 'test-uninstall',
119+
propA: 'a',
120+
propB: 10,
121+
propC: 'c',
122+
}]);
123+
})
124+
125+
it('Has helpers that can uninstall a resource (errors out when unsuccessful)', async () => {
126+
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
127+
128+
// No expect needed here. This passes if it doesn't throw.
129+
expect(async () => plugin.uninstall([{
130+
type: 'test',
131+
propA: 'a',
132+
propB: 10,
133+
propC: 'c',
134+
}])).rejects.toThrowError();
135+
})
112136
})

test/test-plugin.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,37 @@ export class TestResource extends Resource<TestConfig> {
3737
}
3838
}
3939

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+
4062
function buildPlugin(): Plugin {
4163
const resourceMap = new Map();
4264

4365
const testResource = new TestResource();
4466
resourceMap.set(testResource.typeId, testResource);
4567

68+
const testUninstallResource = new TestUninstallResource();
69+
resourceMap.set(testUninstallResource.typeId, testUninstallResource);
70+
4671
return new Plugin('test', resourceMap);
4772
}
4873

tsconfig.json

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
11
{
22
"compilerOptions": {
3-
"declaration": true,
43
"module": "NodeNext",
5-
"moduleResolution": "Node16",
4+
"moduleResolution": "NodeNext",
5+
"sourceMap": true,
66
"esModuleInterop": true,
77
"resolveJsonModule": true,
8-
"jsx": "react",
9-
"outDir": "dist",
8+
"alwaysStrict": true,
9+
"noImplicitAny": true,
10+
"removeComments": true,
11+
"strictNullChecks": true,
12+
"declaration": true,
13+
"emitDecoratorMetadata": true,
14+
"experimentalDecorators": true,
1015
"rootDir": "src",
11-
"strict": true,
12-
"target": "es2022"
16+
"outDir": "./dist"
1317
},
14-
"include": [
15-
"src/**/*"
16-
],
1718
"exclude": [
18-
"src/**/*.test.ts",
19-
"node_modules"
19+
"node_modules",
20+
"src/**/*.test.ts"
2021
],
21-
"ts-node": {
22-
"esm": true
23-
}
22+
"include": [
23+
"src/**/*.ts"
24+
]
2425
}

tsconfig.test.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
},
66
"include": [
77
"src/**/*.test.ts",
8-
"test/**/*.test.ts",
9-
"test/**/*.integration-test.ts"
8+
"test/**/*.test.ts"
109
]
1110
}

0 commit comments

Comments
 (0)