@forwardimpact/libharness 0.1.6 → 0.1.8
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/fixture/index.js +1 -0
- package/fixture/pathway.js +293 -0
- package/mock/fs.js +112 -0
- package/mock/index.js +1 -0
- package/package.json +5 -2
package/fixture/index.js
CHANGED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pathway test fixtures for creating realistic test data
|
|
3
|
+
* Provides mock disciplines, levels, tracks, skills, and behaviours
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Creates a mock level definition
|
|
8
|
+
* @param {object} overrides - Properties to override
|
|
9
|
+
* @returns {object} Mock level
|
|
10
|
+
*/
|
|
11
|
+
export function createTestLevel(overrides = {}) {
|
|
12
|
+
return {
|
|
13
|
+
id: "mid",
|
|
14
|
+
name: "Mid-Level",
|
|
15
|
+
ordinalRank: 3,
|
|
16
|
+
professionalTitle: "Level III",
|
|
17
|
+
managementTitle: "Manager",
|
|
18
|
+
baseSkillProficiencies: {
|
|
19
|
+
primary: "working",
|
|
20
|
+
secondary: "foundational",
|
|
21
|
+
broad: "awareness",
|
|
22
|
+
},
|
|
23
|
+
baseBehaviourMaturity: "developing",
|
|
24
|
+
expectations: {},
|
|
25
|
+
...overrides,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Creates a set of mock levels spanning junior to senior
|
|
31
|
+
* @returns {object[]} Array of mock levels
|
|
32
|
+
*/
|
|
33
|
+
export function createTestLevels() {
|
|
34
|
+
return [
|
|
35
|
+
createTestLevel({
|
|
36
|
+
id: "junior",
|
|
37
|
+
name: "Junior",
|
|
38
|
+
ordinalRank: 1,
|
|
39
|
+
professionalTitle: "Level I",
|
|
40
|
+
managementTitle: "Team Lead",
|
|
41
|
+
baseSkillProficiencies: {
|
|
42
|
+
primary: "foundational",
|
|
43
|
+
secondary: "awareness",
|
|
44
|
+
broad: "awareness",
|
|
45
|
+
},
|
|
46
|
+
baseBehaviourMaturity: "emerging",
|
|
47
|
+
}),
|
|
48
|
+
createTestLevel({
|
|
49
|
+
id: "mid",
|
|
50
|
+
name: "Mid-Level",
|
|
51
|
+
ordinalRank: 3,
|
|
52
|
+
professionalTitle: "Level III",
|
|
53
|
+
managementTitle: "Manager",
|
|
54
|
+
baseSkillProficiencies: {
|
|
55
|
+
primary: "working",
|
|
56
|
+
secondary: "foundational",
|
|
57
|
+
broad: "awareness",
|
|
58
|
+
},
|
|
59
|
+
baseBehaviourMaturity: "developing",
|
|
60
|
+
}),
|
|
61
|
+
createTestLevel({
|
|
62
|
+
id: "senior",
|
|
63
|
+
name: "Senior",
|
|
64
|
+
ordinalRank: 5,
|
|
65
|
+
professionalTitle: "Senior",
|
|
66
|
+
managementTitle: "Senior Manager",
|
|
67
|
+
baseSkillProficiencies: {
|
|
68
|
+
primary: "practitioner",
|
|
69
|
+
secondary: "working",
|
|
70
|
+
broad: "foundational",
|
|
71
|
+
},
|
|
72
|
+
baseBehaviourMaturity: "practicing",
|
|
73
|
+
}),
|
|
74
|
+
createTestLevel({
|
|
75
|
+
id: "staff",
|
|
76
|
+
name: "Staff",
|
|
77
|
+
ordinalRank: 7,
|
|
78
|
+
professionalTitle: "Staff",
|
|
79
|
+
managementTitle: "Director",
|
|
80
|
+
baseSkillProficiencies: {
|
|
81
|
+
primary: "expert",
|
|
82
|
+
secondary: "practitioner",
|
|
83
|
+
broad: "working",
|
|
84
|
+
},
|
|
85
|
+
baseBehaviourMaturity: "role_modeling",
|
|
86
|
+
}),
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Creates a mock skill definition
|
|
92
|
+
* @param {object} overrides - Properties to override
|
|
93
|
+
* @returns {object} Mock skill
|
|
94
|
+
*/
|
|
95
|
+
export function createTestSkill(overrides = {}) {
|
|
96
|
+
return {
|
|
97
|
+
id: "test_skill",
|
|
98
|
+
name: "Test Skill",
|
|
99
|
+
capability: "delivery",
|
|
100
|
+
isHumanOnly: false,
|
|
101
|
+
proficiencyDescriptions: {
|
|
102
|
+
awareness: "Basic awareness",
|
|
103
|
+
foundational: "Foundational understanding",
|
|
104
|
+
working: "Working proficiency",
|
|
105
|
+
practitioner: "Practitioner level",
|
|
106
|
+
expert: "Expert level",
|
|
107
|
+
},
|
|
108
|
+
...overrides,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Creates a set of mock skills across capabilities
|
|
114
|
+
* @returns {object[]} Array of mock skills
|
|
115
|
+
*/
|
|
116
|
+
export function createTestSkills() {
|
|
117
|
+
return [
|
|
118
|
+
createTestSkill({
|
|
119
|
+
id: "coding",
|
|
120
|
+
name: "Coding",
|
|
121
|
+
capability: "delivery",
|
|
122
|
+
}),
|
|
123
|
+
createTestSkill({
|
|
124
|
+
id: "testing",
|
|
125
|
+
name: "Testing",
|
|
126
|
+
capability: "delivery",
|
|
127
|
+
}),
|
|
128
|
+
createTestSkill({
|
|
129
|
+
id: "architecture",
|
|
130
|
+
name: "Architecture",
|
|
131
|
+
capability: "scale",
|
|
132
|
+
}),
|
|
133
|
+
createTestSkill({
|
|
134
|
+
id: "observability",
|
|
135
|
+
name: "Observability",
|
|
136
|
+
capability: "scale",
|
|
137
|
+
}),
|
|
138
|
+
createTestSkill({
|
|
139
|
+
id: "ai_tools",
|
|
140
|
+
name: "AI Tools",
|
|
141
|
+
capability: "ai",
|
|
142
|
+
}),
|
|
143
|
+
createTestSkill({
|
|
144
|
+
id: "mentoring",
|
|
145
|
+
name: "Mentoring",
|
|
146
|
+
capability: "delivery",
|
|
147
|
+
isHumanOnly: true,
|
|
148
|
+
}),
|
|
149
|
+
];
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Creates a mock discipline definition
|
|
154
|
+
* @param {object} overrides - Properties to override
|
|
155
|
+
* @returns {object} Mock discipline
|
|
156
|
+
*/
|
|
157
|
+
export function createTestDiscipline(overrides = {}) {
|
|
158
|
+
return {
|
|
159
|
+
id: "software_engineering",
|
|
160
|
+
name: "Software Engineering",
|
|
161
|
+
roleTitle: "Software Engineer",
|
|
162
|
+
isProfessional: true,
|
|
163
|
+
isManagement: false,
|
|
164
|
+
coreSkills: ["coding", "testing"],
|
|
165
|
+
supportingSkills: ["architecture"],
|
|
166
|
+
broadSkills: ["observability"],
|
|
167
|
+
behaviourModifiers: {},
|
|
168
|
+
validTracks: [],
|
|
169
|
+
...overrides,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Creates a mock track definition
|
|
175
|
+
* @param {object} overrides - Properties to override
|
|
176
|
+
* @returns {object} Mock track
|
|
177
|
+
*/
|
|
178
|
+
export function createTestTrack(overrides = {}) {
|
|
179
|
+
return {
|
|
180
|
+
id: "platform",
|
|
181
|
+
name: "Platform",
|
|
182
|
+
skillModifiers: { scale: 1, delivery: -1 },
|
|
183
|
+
behaviourModifiers: {},
|
|
184
|
+
...overrides,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Creates a mock behaviour definition
|
|
190
|
+
* @param {object} overrides - Properties to override
|
|
191
|
+
* @returns {object} Mock behaviour
|
|
192
|
+
*/
|
|
193
|
+
export function createTestBehaviour(overrides = {}) {
|
|
194
|
+
return {
|
|
195
|
+
id: "collaboration",
|
|
196
|
+
name: "Collaboration",
|
|
197
|
+
maturityDescriptions: {
|
|
198
|
+
emerging: "Beginning to collaborate",
|
|
199
|
+
developing: "Developing collaboration",
|
|
200
|
+
practicing: "Practicing collaboration",
|
|
201
|
+
role_modeling: "Role modeling collaboration",
|
|
202
|
+
exemplifying: "Exemplifying collaboration",
|
|
203
|
+
},
|
|
204
|
+
...overrides,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Creates a set of mock behaviours
|
|
210
|
+
* @returns {object[]} Array of mock behaviours
|
|
211
|
+
*/
|
|
212
|
+
export function createTestBehaviours() {
|
|
213
|
+
return [
|
|
214
|
+
createTestBehaviour({ id: "collaboration", name: "Collaboration" }),
|
|
215
|
+
createTestBehaviour({ id: "communication", name: "Communication" }),
|
|
216
|
+
createTestBehaviour({ id: "leadership", name: "Leadership" }),
|
|
217
|
+
];
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Creates a mock capability definition
|
|
222
|
+
* @param {object} overrides - Properties to override
|
|
223
|
+
* @returns {object} Mock capability
|
|
224
|
+
*/
|
|
225
|
+
export function createTestCapability(overrides = {}) {
|
|
226
|
+
return {
|
|
227
|
+
id: "delivery",
|
|
228
|
+
name: "Delivery",
|
|
229
|
+
emojiIcon: "🚀",
|
|
230
|
+
ordinalRank: 1,
|
|
231
|
+
professionalResponsibilities: {
|
|
232
|
+
foundational: "Delivers assigned tasks",
|
|
233
|
+
working: "Delivers features independently",
|
|
234
|
+
practitioner: "Leads delivery across team",
|
|
235
|
+
expert: "Defines delivery strategy",
|
|
236
|
+
},
|
|
237
|
+
managementResponsibilities: {
|
|
238
|
+
foundational: "Manages delivery timelines",
|
|
239
|
+
working: "Owns team delivery",
|
|
240
|
+
practitioner: "Leads multi-team delivery",
|
|
241
|
+
expert: "Shapes delivery culture",
|
|
242
|
+
},
|
|
243
|
+
...overrides,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Creates a mock driver definition
|
|
249
|
+
* @param {object} overrides - Properties to override
|
|
250
|
+
* @returns {object} Mock driver
|
|
251
|
+
*/
|
|
252
|
+
export function createTestDriver(overrides = {}) {
|
|
253
|
+
return {
|
|
254
|
+
id: "velocity",
|
|
255
|
+
name: "Velocity",
|
|
256
|
+
contributingSkills: ["coding", "testing"],
|
|
257
|
+
contributingBehaviours: ["collaboration"],
|
|
258
|
+
...overrides,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Creates a mock skill matrix entry
|
|
264
|
+
* @param {object} overrides - Properties to override
|
|
265
|
+
* @returns {object} Mock skill matrix entry
|
|
266
|
+
*/
|
|
267
|
+
export function createTestSkillEntry(overrides = {}) {
|
|
268
|
+
return {
|
|
269
|
+
skillId: "coding",
|
|
270
|
+
skillName: "Coding",
|
|
271
|
+
capability: "delivery",
|
|
272
|
+
isHumanOnly: false,
|
|
273
|
+
type: "primary",
|
|
274
|
+
proficiency: "working",
|
|
275
|
+
proficiencyDescription: "Working proficiency",
|
|
276
|
+
...overrides,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Creates a mock behaviour profile entry
|
|
282
|
+
* @param {object} overrides - Properties to override
|
|
283
|
+
* @returns {object} Mock behaviour profile entry
|
|
284
|
+
*/
|
|
285
|
+
export function createTestBehaviourEntry(overrides = {}) {
|
|
286
|
+
return {
|
|
287
|
+
behaviourId: "collaboration",
|
|
288
|
+
behaviourName: "Collaboration",
|
|
289
|
+
maturity: "developing",
|
|
290
|
+
maturityDescription: "Developing collaboration",
|
|
291
|
+
...overrides,
|
|
292
|
+
};
|
|
293
|
+
}
|
package/mock/fs.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { mock } from "node:test";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates a mock filesystem backed by an in-memory Map
|
|
5
|
+
* @param {Object<string, string>} files - Initial file contents keyed by path
|
|
6
|
+
* @returns {object} Mock fs with readFile, writeFile, readdir, stat, mkdir, access, copyFile
|
|
7
|
+
*/
|
|
8
|
+
export function createMockFs(files = {}) {
|
|
9
|
+
const data = new Map(Object.entries(files));
|
|
10
|
+
const dirs = new Set();
|
|
11
|
+
|
|
12
|
+
// Auto-create parent directories for initial files
|
|
13
|
+
for (const path of data.keys()) {
|
|
14
|
+
const parts = path.split("/");
|
|
15
|
+
for (let i = 1; i < parts.length; i++) {
|
|
16
|
+
dirs.add(parts.slice(0, i).join("/"));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
data,
|
|
22
|
+
dirs,
|
|
23
|
+
readFile: mock.fn(async (path, encoding) => {
|
|
24
|
+
const content = data.get(path);
|
|
25
|
+
if (content === undefined) {
|
|
26
|
+
const err = new Error(
|
|
27
|
+
`ENOENT: no such file or directory, open '${path}'`,
|
|
28
|
+
);
|
|
29
|
+
err.code = "ENOENT";
|
|
30
|
+
throw err;
|
|
31
|
+
}
|
|
32
|
+
return encoding ? content : Buffer.from(content);
|
|
33
|
+
}),
|
|
34
|
+
writeFile: mock.fn(async (path, content) => {
|
|
35
|
+
data.set(
|
|
36
|
+
path,
|
|
37
|
+
typeof content === "string" ? content : content.toString(),
|
|
38
|
+
);
|
|
39
|
+
}),
|
|
40
|
+
readdir: mock.fn(async (path) => {
|
|
41
|
+
const entries = [];
|
|
42
|
+
const prefix = path.endsWith("/") ? path : `${path}/`;
|
|
43
|
+
for (const key of data.keys()) {
|
|
44
|
+
if (key.startsWith(prefix)) {
|
|
45
|
+
const rest = key.slice(prefix.length);
|
|
46
|
+
const name = rest.split("/")[0];
|
|
47
|
+
if (name && !entries.includes(name)) {
|
|
48
|
+
entries.push(name);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return entries;
|
|
53
|
+
}),
|
|
54
|
+
stat: mock.fn(async (path) => {
|
|
55
|
+
if (data.has(path)) {
|
|
56
|
+
return { isFile: () => true, isDirectory: () => false };
|
|
57
|
+
}
|
|
58
|
+
if (dirs.has(path)) {
|
|
59
|
+
return { isFile: () => false, isDirectory: () => true };
|
|
60
|
+
}
|
|
61
|
+
const err = new Error(
|
|
62
|
+
`ENOENT: no such file or directory, stat '${path}'`,
|
|
63
|
+
);
|
|
64
|
+
err.code = "ENOENT";
|
|
65
|
+
throw err;
|
|
66
|
+
}),
|
|
67
|
+
mkdir: mock.fn(async (path) => {
|
|
68
|
+
dirs.add(path);
|
|
69
|
+
}),
|
|
70
|
+
access: mock.fn(async (path) => {
|
|
71
|
+
if (!data.has(path) && !dirs.has(path)) {
|
|
72
|
+
const err = new Error(
|
|
73
|
+
`ENOENT: no such file or directory, access '${path}'`,
|
|
74
|
+
);
|
|
75
|
+
err.code = "ENOENT";
|
|
76
|
+
throw err;
|
|
77
|
+
}
|
|
78
|
+
}),
|
|
79
|
+
copyFile: mock.fn(async (src, dest) => {
|
|
80
|
+
const content = data.get(src);
|
|
81
|
+
if (content === undefined) {
|
|
82
|
+
const err = new Error(
|
|
83
|
+
`ENOENT: no such file or directory, copyFile '${src}'`,
|
|
84
|
+
);
|
|
85
|
+
err.code = "ENOENT";
|
|
86
|
+
throw err;
|
|
87
|
+
}
|
|
88
|
+
data.set(dest, content);
|
|
89
|
+
}),
|
|
90
|
+
existsSync: mock.fn((path) => data.has(path) || dirs.has(path)),
|
|
91
|
+
readFileSync: mock.fn((path, encoding) => {
|
|
92
|
+
const content = data.get(path);
|
|
93
|
+
if (content === undefined) {
|
|
94
|
+
const err = new Error(
|
|
95
|
+
`ENOENT: no such file or directory, open '${path}'`,
|
|
96
|
+
);
|
|
97
|
+
err.code = "ENOENT";
|
|
98
|
+
throw err;
|
|
99
|
+
}
|
|
100
|
+
return encoding ? content : Buffer.from(content);
|
|
101
|
+
}),
|
|
102
|
+
writeFileSync: mock.fn((path, content) => {
|
|
103
|
+
data.set(
|
|
104
|
+
path,
|
|
105
|
+
typeof content === "string" ? content : content.toString(),
|
|
106
|
+
);
|
|
107
|
+
}),
|
|
108
|
+
mkdirSync: mock.fn((path) => {
|
|
109
|
+
dirs.add(path);
|
|
110
|
+
}),
|
|
111
|
+
};
|
|
112
|
+
}
|
package/mock/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forwardimpact/libharness",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "Test harness and mock infrastructure for guide tests",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"README.md"
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
|
-
"test": "node --test test/*.test.js"
|
|
19
|
+
"test": "bun run node --test test/*.test.js"
|
|
20
20
|
},
|
|
21
21
|
"keywords": [
|
|
22
22
|
"test",
|
|
@@ -31,5 +31,8 @@
|
|
|
31
31
|
},
|
|
32
32
|
"publishConfig": {
|
|
33
33
|
"access": "public"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"bun": ">=1.2.0"
|
|
34
37
|
}
|
|
35
38
|
}
|