@wp-tester/config 0.0.1
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/README.md +18 -0
- package/dist/auto-mount.d.ts +11 -0
- package/dist/auto-mount.d.ts.map +1 -0
- package/dist/auto-mount.js +31 -0
- package/dist/auto-mount.js.map +1 -0
- package/dist/config.d.ts +41 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +213 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/options/index.d.ts +38 -0
- package/dist/options/index.d.ts.map +1 -0
- package/dist/options/index.js +23 -0
- package/dist/options/index.js.map +1 -0
- package/dist/options/phpunit-detect.d.ts +43 -0
- package/dist/options/phpunit-detect.d.ts.map +1 -0
- package/dist/options/phpunit-detect.js +94 -0
- package/dist/options/phpunit-detect.js.map +1 -0
- package/dist/options/phpunit.d.ts +12 -0
- package/dist/options/phpunit.d.ts.map +1 -0
- package/dist/options/phpunit.js +307 -0
- package/dist/options/phpunit.js.map +1 -0
- package/dist/options/project-root.d.ts +4 -0
- package/dist/options/project-root.d.ts.map +1 -0
- package/dist/options/project-root.js +38 -0
- package/dist/options/project-root.js.map +1 -0
- package/dist/options/project-type-detect.d.ts +27 -0
- package/dist/options/project-type-detect.d.ts.map +1 -0
- package/dist/options/project-type-detect.js +71 -0
- package/dist/options/project-type-detect.js.map +1 -0
- package/dist/options/project-type.d.ts +7 -0
- package/dist/options/project-type.d.ts.map +1 -0
- package/dist/options/project-type.js +50 -0
- package/dist/options/project-type.js.map +1 -0
- package/dist/options/smoke-tests.d.ts +4 -0
- package/dist/options/smoke-tests.d.ts.map +1 -0
- package/dist/options/smoke-tests.js +80 -0
- package/dist/options/smoke-tests.js.map +1 -0
- package/dist/path-mappers.d.ts +26 -0
- package/dist/path-mappers.d.ts.map +1 -0
- package/dist/path-mappers.js +32 -0
- package/dist/path-mappers.js.map +1 -0
- package/dist/resolved-types.d.ts +69 -0
- package/dist/resolved-types.d.ts.map +1 -0
- package/dist/resolved-types.js +2 -0
- package/dist/resolved-types.js.map +1 -0
- package/dist/schema.json +3443 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/wp-tester-config.d.ts +171 -0
- package/dist/wp-tester-config.d.ts.map +1 -0
- package/dist/wp-tester-config.js +2 -0
- package/dist/wp-tester-config.js.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import * as clack from "@clack/prompts";
|
|
2
|
+
import { getProjectDir } from "../config.js";
|
|
3
|
+
import { findPhpUnitConfig, findPhpUnitExecutable, findPhpUnitBootstrap, } from "./phpunit-detect.js";
|
|
4
|
+
import { access } from "fs/promises";
|
|
5
|
+
import { join, relative } from "path";
|
|
6
|
+
/**
|
|
7
|
+
* Prompt user to select PHPUnit test mode
|
|
8
|
+
* @returns Selected test mode ("unit" or "integration"), or null if cancelled
|
|
9
|
+
*/
|
|
10
|
+
async function promptForTestMode() {
|
|
11
|
+
const testModeAnswer = await clack.select({
|
|
12
|
+
message: "What type of PHPUnit tests will you run?",
|
|
13
|
+
options: [
|
|
14
|
+
{
|
|
15
|
+
value: "unit",
|
|
16
|
+
label: "Unit tests (without WordPress)",
|
|
17
|
+
hint: "Fast tests for isolated PHP logic, pure functions, classes without WordPress dependencies"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
value: "integration",
|
|
21
|
+
label: "Integration tests (with WordPress)",
|
|
22
|
+
hint: "Tests that interact with WordPress APIs, hooks, database, plugins/themes"
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
initialValue: "unit"
|
|
26
|
+
});
|
|
27
|
+
if (clack.isCancel(testModeAnswer)) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
return testModeAnswer;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Validate that a file path exists
|
|
34
|
+
*/
|
|
35
|
+
async function validatePath(basePath, relativePath) {
|
|
36
|
+
try {
|
|
37
|
+
const fullPath = join(basePath, relativePath);
|
|
38
|
+
await access(fullPath);
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Collect manual PHPUnit configuration from user input with validation
|
|
47
|
+
*/
|
|
48
|
+
async function collectManualPHPUnitConfig(config, projectHostPath) {
|
|
49
|
+
// Get PHPUnit executable path with validation
|
|
50
|
+
let phpunitPath;
|
|
51
|
+
while (true) {
|
|
52
|
+
const input = await clack.text({
|
|
53
|
+
message: "Path to PHPUnit executable (relative to project root):",
|
|
54
|
+
initialValue: config.tests?.phpunit?.phpunitPath || "vendor/bin/phpunit",
|
|
55
|
+
validate: (value) => {
|
|
56
|
+
if (!value || value.trim() === "") {
|
|
57
|
+
return "PHPUnit path is required";
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
if (clack.isCancel(input)) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
const trimmed = input.trim();
|
|
65
|
+
const exists = await validatePath(projectHostPath, trimmed);
|
|
66
|
+
if (exists) {
|
|
67
|
+
phpunitPath = trimmed;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
clack.log.error(`File not found: ${trimmed}`);
|
|
71
|
+
}
|
|
72
|
+
// Get PHPUnit config file path with validation
|
|
73
|
+
let configPath;
|
|
74
|
+
while (true) {
|
|
75
|
+
const input = await clack.text({
|
|
76
|
+
message: "Path to PHPUnit config file (relative to project root):",
|
|
77
|
+
initialValue: config.tests?.phpunit?.configPath || "phpunit.xml.dist",
|
|
78
|
+
validate: (value) => {
|
|
79
|
+
if (!value || value.trim() === "") {
|
|
80
|
+
return "Config path is required";
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
if (clack.isCancel(input)) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
const trimmed = input.trim();
|
|
88
|
+
const exists = await validatePath(projectHostPath, trimmed);
|
|
89
|
+
if (exists) {
|
|
90
|
+
configPath = trimmed;
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
clack.log.error(`File not found: ${trimmed}`);
|
|
94
|
+
}
|
|
95
|
+
// Get optional bootstrap path
|
|
96
|
+
let bootstrapPath;
|
|
97
|
+
while (true) {
|
|
98
|
+
const input = await clack.text({
|
|
99
|
+
message: "Path to PHPUnit bootstrap file (optional, relative to project root):",
|
|
100
|
+
initialValue: config.tests?.phpunit?.bootstrapPath || "",
|
|
101
|
+
placeholder: "tests/bootstrap.php (leave empty to skip)",
|
|
102
|
+
});
|
|
103
|
+
if (clack.isCancel(input)) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
// Safely handle undefined/non-string input for optional field
|
|
107
|
+
const trimmed = input && typeof input === "string" ? input.trim() : "";
|
|
108
|
+
if (!trimmed) {
|
|
109
|
+
// Empty is okay for optional field
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
const exists = await validatePath(projectHostPath, trimmed);
|
|
113
|
+
if (exists) {
|
|
114
|
+
bootstrapPath = trimmed;
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
clack.log.error(`File not found: ${trimmed}. Leave empty to skip or provide a valid path.`);
|
|
118
|
+
}
|
|
119
|
+
// Prompt for test mode
|
|
120
|
+
const testMode = await promptForTestMode();
|
|
121
|
+
if (testMode === null) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
const result = {
|
|
125
|
+
phpunitPath,
|
|
126
|
+
configPath,
|
|
127
|
+
testMode: testMode,
|
|
128
|
+
};
|
|
129
|
+
// Only add bootstrapPath if provided
|
|
130
|
+
if (bootstrapPath) {
|
|
131
|
+
result.bootstrapPath = bootstrapPath;
|
|
132
|
+
}
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Handle full detection (both config and executable found)
|
|
137
|
+
*/
|
|
138
|
+
async function handleFullDetection(config, projectHostPath, configFile, executable, bootstrap) {
|
|
139
|
+
// Convert to relative paths
|
|
140
|
+
const relativeConfig = relative(projectHostPath, configFile);
|
|
141
|
+
const relativeExecutable = relative(projectHostPath, executable);
|
|
142
|
+
const relativeBootstrap = bootstrap ? relative(projectHostPath, bootstrap) : null;
|
|
143
|
+
// Display detected configuration
|
|
144
|
+
const configNote = `PHPUnit executable: ${relativeExecutable}\n` +
|
|
145
|
+
`Config file: ${relativeConfig}` +
|
|
146
|
+
(relativeBootstrap ? `\nBootstrap file: ${relativeBootstrap}` : "");
|
|
147
|
+
clack.note(configNote, "Detected PHPUnit Configuration");
|
|
148
|
+
// Ask user to confirm or customize
|
|
149
|
+
const action = await clack.select({
|
|
150
|
+
message: "PHPUnit tests detected. What would you like to do?",
|
|
151
|
+
options: [
|
|
152
|
+
{ value: "use", label: "Use detected configuration" },
|
|
153
|
+
{ value: "customize", label: "Customize configuration" },
|
|
154
|
+
{ value: "skip", label: "Skip PHPUnit tests" },
|
|
155
|
+
],
|
|
156
|
+
initialValue: "use",
|
|
157
|
+
});
|
|
158
|
+
if (clack.isCancel(action)) {
|
|
159
|
+
clack.cancel("Setup cancelled.");
|
|
160
|
+
process.exit(0);
|
|
161
|
+
}
|
|
162
|
+
if (action === "skip") {
|
|
163
|
+
return config;
|
|
164
|
+
}
|
|
165
|
+
let finalConfig;
|
|
166
|
+
if (action === "customize") {
|
|
167
|
+
const customConfig = await collectManualPHPUnitConfig(config, projectHostPath);
|
|
168
|
+
if (!customConfig) {
|
|
169
|
+
clack.cancel("Setup cancelled.");
|
|
170
|
+
process.exit(0);
|
|
171
|
+
}
|
|
172
|
+
finalConfig = customConfig;
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
// Prompt for test mode even when using detected config
|
|
176
|
+
const testMode = await promptForTestMode();
|
|
177
|
+
if (testMode === null) {
|
|
178
|
+
clack.cancel("Setup cancelled.");
|
|
179
|
+
process.exit(0);
|
|
180
|
+
}
|
|
181
|
+
finalConfig = {
|
|
182
|
+
phpunitPath: relativeExecutable,
|
|
183
|
+
configPath: relativeConfig,
|
|
184
|
+
testMode: testMode,
|
|
185
|
+
...(relativeBootstrap && { bootstrapPath: relativeBootstrap }),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
...config,
|
|
190
|
+
tests: {
|
|
191
|
+
...config.tests,
|
|
192
|
+
phpunit: finalConfig,
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Handle partial detection (config found but executable missing)
|
|
198
|
+
*/
|
|
199
|
+
async function handlePartialDetection(config, projectHostPath, configFile) {
|
|
200
|
+
const relativeConfig = relative(projectHostPath, configFile);
|
|
201
|
+
while (true) {
|
|
202
|
+
const message = `Found ${relativeConfig} but PHPUnit executable not found at vendor/bin/phpunit.\n` +
|
|
203
|
+
`You may need to run 'composer install' first.`;
|
|
204
|
+
clack.note(message, "Partial PHPUnit Detection");
|
|
205
|
+
const action = await clack.select({
|
|
206
|
+
message: "What would you like to do?",
|
|
207
|
+
options: [
|
|
208
|
+
{ value: "retry", label: "I've installed it, try again" },
|
|
209
|
+
{ value: "custom", label: "Specify custom path" },
|
|
210
|
+
{ value: "skip", label: "Skip for now" },
|
|
211
|
+
],
|
|
212
|
+
initialValue: "retry",
|
|
213
|
+
});
|
|
214
|
+
if (clack.isCancel(action)) {
|
|
215
|
+
clack.cancel("Setup cancelled.");
|
|
216
|
+
process.exit(0);
|
|
217
|
+
}
|
|
218
|
+
if (action === "skip") {
|
|
219
|
+
return config;
|
|
220
|
+
}
|
|
221
|
+
if (action === "custom") {
|
|
222
|
+
const customConfig = await collectManualPHPUnitConfig(config, projectHostPath);
|
|
223
|
+
if (!customConfig) {
|
|
224
|
+
clack.cancel("Setup cancelled.");
|
|
225
|
+
process.exit(0);
|
|
226
|
+
}
|
|
227
|
+
return {
|
|
228
|
+
...config,
|
|
229
|
+
tests: {
|
|
230
|
+
...config.tests,
|
|
231
|
+
phpunit: customConfig,
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
// action === "retry" - re-run detection
|
|
236
|
+
const executable = await findPhpUnitExecutable(projectHostPath);
|
|
237
|
+
if (executable) {
|
|
238
|
+
// Success! Now we have both config and executable
|
|
239
|
+
const bootstrap = await findPhpUnitBootstrap(projectHostPath);
|
|
240
|
+
return handleFullDetection(config, projectHostPath, configFile, executable, bootstrap);
|
|
241
|
+
}
|
|
242
|
+
// Still not found, loop will continue
|
|
243
|
+
clack.log.error("PHPUnit executable still not found. Please install PHPUnit or specify a custom path.");
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Handle no detection (neither config nor executable found)
|
|
248
|
+
*/
|
|
249
|
+
async function handleNoDetection(config, projectHostPath, promptIfNotDetected) {
|
|
250
|
+
if (!promptIfNotDetected) {
|
|
251
|
+
// Skip silently during initial setup
|
|
252
|
+
return config;
|
|
253
|
+
}
|
|
254
|
+
const configureManually = await clack.confirm({
|
|
255
|
+
message: "PHPUnit not detected. Would you like to configure it manually?",
|
|
256
|
+
initialValue: false,
|
|
257
|
+
});
|
|
258
|
+
if (clack.isCancel(configureManually)) {
|
|
259
|
+
clack.cancel("Setup cancelled.");
|
|
260
|
+
process.exit(0);
|
|
261
|
+
}
|
|
262
|
+
if (!configureManually) {
|
|
263
|
+
return config;
|
|
264
|
+
}
|
|
265
|
+
const manualConfig = await collectManualPHPUnitConfig(config, projectHostPath);
|
|
266
|
+
if (!manualConfig) {
|
|
267
|
+
clack.cancel("Setup cancelled.");
|
|
268
|
+
process.exit(0);
|
|
269
|
+
}
|
|
270
|
+
return {
|
|
271
|
+
...config,
|
|
272
|
+
tests: {
|
|
273
|
+
...config.tests,
|
|
274
|
+
phpunit: manualConfig,
|
|
275
|
+
},
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* PHPUnit config option
|
|
280
|
+
* Detects PHPUnit tests and asks user if they want to run them
|
|
281
|
+
* @param config - Current configuration
|
|
282
|
+
* @param context - Optional context object with configPath and other options
|
|
283
|
+
*/
|
|
284
|
+
export async function phpunitOption(config, context) {
|
|
285
|
+
const promptIfNotDetected = context?.promptIfNotDetected ?? false;
|
|
286
|
+
const configPath = context?.configPath;
|
|
287
|
+
// Get the project root directory using the config helper
|
|
288
|
+
const projectHostPath = getProjectDir(config, configPath);
|
|
289
|
+
// Run individual detections for granular feedback
|
|
290
|
+
const configFile = await findPhpUnitConfig(projectHostPath);
|
|
291
|
+
const executable = await findPhpUnitExecutable(projectHostPath);
|
|
292
|
+
// Handle different detection states
|
|
293
|
+
if (configFile && executable) {
|
|
294
|
+
// Full detection - both found
|
|
295
|
+
const bootstrap = await findPhpUnitBootstrap(projectHostPath);
|
|
296
|
+
return handleFullDetection(config, projectHostPath, configFile, executable, bootstrap);
|
|
297
|
+
}
|
|
298
|
+
else if (configFile && !executable) {
|
|
299
|
+
// Partial detection - config found but executable missing
|
|
300
|
+
return handlePartialDetection(config, projectHostPath, configFile);
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
// No detection - neither found (or unusual case: executable but no config)
|
|
304
|
+
return handleNoDetection(config, projectHostPath, promptIfNotDetected);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
//# sourceMappingURL=phpunit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phpunit.js","sourceRoot":"","sources":["../../src/options/phpunit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { WPTesterConfig } from '../types.js';
|
|
2
|
+
export declare function validatePath(value: string | undefined): string | undefined;
|
|
3
|
+
export declare function projectRootOption(config: WPTesterConfig): Promise<WPTesterConfig>;
|
|
4
|
+
//# sourceMappingURL=project-root.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-root.d.ts","sourceRoot":"","sources":["../../src/options/project-root.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAK/C,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAe1E;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,cAAc,CAAC,CAwBzB"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as clack from '@clack/prompts';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
export function validatePath(value) {
|
|
5
|
+
// Allow empty value - will be replaced with cwd
|
|
6
|
+
if (!value || value.trim().length === 0) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
const resolvedPath = path.isAbsolute(value)
|
|
10
|
+
? value
|
|
11
|
+
: path.resolve(process.cwd(), value);
|
|
12
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
13
|
+
return 'Directory does not exist';
|
|
14
|
+
}
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
export async function projectRootOption(config) {
|
|
18
|
+
const cwd = process.cwd();
|
|
19
|
+
// Single input step: user can press Enter to confirm cwd or type a new path
|
|
20
|
+
const rootPath = await clack.text({
|
|
21
|
+
message: 'Where is your project located? (Press Enter to use current directory)',
|
|
22
|
+
placeholder: cwd,
|
|
23
|
+
initialValue: '',
|
|
24
|
+
validate: validatePath,
|
|
25
|
+
});
|
|
26
|
+
if (clack.isCancel(rootPath)) {
|
|
27
|
+
clack.cancel('Setup cancelled.');
|
|
28
|
+
process.exit(0);
|
|
29
|
+
}
|
|
30
|
+
// If empty (user pressed Enter), use '.' to represent current directory
|
|
31
|
+
const finalPath = !rootPath || rootPath.trim() === '' ? '.' : rootPath;
|
|
32
|
+
// Store the path (using '.' for current directory)
|
|
33
|
+
return {
|
|
34
|
+
...config,
|
|
35
|
+
projectHostPath: finalPath,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=project-root.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-root.js","sourceRoot":"","sources":["../../src/options/project-root.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB,MAAM,UAAU,YAAY,CAAC,KAAyB;IACpD,gDAAgD;IAChD,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;QACzC,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;IAEvC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACjC,OAAO,0BAA0B,CAAC;IACpC,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAsB;IAEtB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAE1B,4EAA4E;IAC5E,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC;QAChC,OAAO,EAAE,uEAAuE;QAChF,WAAW,EAAE,GAAG;QAChB,YAAY,EAAE,EAAE;QAChB,QAAQ,EAAE,YAAY;KACvB,CAAC,CAAC;IAEH,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,wEAAwE;IACxE,MAAM,SAAS,GAAG,CAAC,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;IAEvE,mDAAmD;IACnD,OAAO;QACL,GAAG,MAAM;QACT,eAAe,EAAE,SAAS;KAC3B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type ProjectType = 'plugin' | 'theme' | 'wp-content' | 'wordpress-install' | 'unknown';
|
|
2
|
+
/**
|
|
3
|
+
* Check if directory contains a full WordPress installation
|
|
4
|
+
* (wp-admin, wp-includes, and wp-content directories)
|
|
5
|
+
*/
|
|
6
|
+
export declare function containsFullWordPressInstallation(path: string): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Check if directory contains wp-content subdirectories
|
|
9
|
+
* (themes, plugins, mu-plugins, or uploads)
|
|
10
|
+
*/
|
|
11
|
+
export declare function containsWpContentDirectories(path: string): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Check if directory is a WordPress theme
|
|
14
|
+
* (contains style.css with Theme Name header)
|
|
15
|
+
*/
|
|
16
|
+
export declare function isThemeDirectory(path: string): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Check if directory is a WordPress plugin
|
|
19
|
+
* (contains PHP file with Plugin Name header)
|
|
20
|
+
*/
|
|
21
|
+
export declare function isPluginFilename(path: string): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Detect WordPress project type based on directory contents
|
|
24
|
+
* Priority order matches WordPress Playground CLI logic
|
|
25
|
+
*/
|
|
26
|
+
export declare function detectProjectType(path: string): ProjectType;
|
|
27
|
+
//# sourceMappingURL=project-type-detect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-type-detect.d.ts","sourceRoot":"","sources":["../../src/options/project-type-detect.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,OAAO,GAAG,YAAY,GAAG,mBAAmB,GAAG,SAAS,CAAC;AAE9F;;;GAGG;AACH,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOvE;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAQlE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAQtD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAUtD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAM3D"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// TODO: Replace these copied functions with imports from @wp-playground/cli/mounts
|
|
2
|
+
// once that package exports them properly.
|
|
3
|
+
// These functions are copied from:
|
|
4
|
+
// https://github.com/WordPress/wordpress-playground/blob/trunk/packages/playground/cli/src/mounts.ts
|
|
5
|
+
import { readdirSync, readFileSync } from 'fs';
|
|
6
|
+
import { join } from 'path';
|
|
7
|
+
/**
|
|
8
|
+
* Check if directory contains a full WordPress installation
|
|
9
|
+
* (wp-admin, wp-includes, and wp-content directories)
|
|
10
|
+
*/
|
|
11
|
+
export function containsFullWordPressInstallation(path) {
|
|
12
|
+
const files = readdirSync(path);
|
|
13
|
+
return (files.includes('wp-admin') &&
|
|
14
|
+
files.includes('wp-includes') &&
|
|
15
|
+
files.includes('wp-content'));
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Check if directory contains wp-content subdirectories
|
|
19
|
+
* (themes, plugins, mu-plugins, or uploads)
|
|
20
|
+
*/
|
|
21
|
+
export function containsWpContentDirectories(path) {
|
|
22
|
+
const files = readdirSync(path);
|
|
23
|
+
return (files.includes('themes') ||
|
|
24
|
+
files.includes('plugins') ||
|
|
25
|
+
files.includes('mu-plugins') ||
|
|
26
|
+
files.includes('uploads'));
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Check if directory is a WordPress theme
|
|
30
|
+
* (contains style.css with Theme Name header)
|
|
31
|
+
*/
|
|
32
|
+
export function isThemeDirectory(path) {
|
|
33
|
+
const files = readdirSync(path);
|
|
34
|
+
if (!files.includes('style.css')) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
const styleCssContent = readFileSync(join(path, 'style.css'), 'utf8');
|
|
38
|
+
const themeNameRegex = /^(?:[ \t]*<\?php)?[ \t/*#@]*Theme Name:(.*)$/im;
|
|
39
|
+
return !!themeNameRegex.exec(styleCssContent);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Check if directory is a WordPress plugin
|
|
43
|
+
* (contains PHP file with Plugin Name header)
|
|
44
|
+
*/
|
|
45
|
+
export function isPluginFilename(path) {
|
|
46
|
+
const files = readdirSync(path);
|
|
47
|
+
const pluginNameRegex = /^(?:[ \t]*<\?php)?[ \t/*#@]*Plugin Name:(.*)$/im;
|
|
48
|
+
const pluginNameMatch = files
|
|
49
|
+
.filter((file) => file.endsWith('.php'))
|
|
50
|
+
.find((file) => {
|
|
51
|
+
const fileContent = readFileSync(join(path, file), 'utf8');
|
|
52
|
+
return !!pluginNameRegex.exec(fileContent);
|
|
53
|
+
});
|
|
54
|
+
return !!pluginNameMatch;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Detect WordPress project type based on directory contents
|
|
58
|
+
* Priority order matches WordPress Playground CLI logic
|
|
59
|
+
*/
|
|
60
|
+
export function detectProjectType(path) {
|
|
61
|
+
if (isPluginFilename(path))
|
|
62
|
+
return 'plugin';
|
|
63
|
+
if (isThemeDirectory(path))
|
|
64
|
+
return 'theme';
|
|
65
|
+
if (containsWpContentDirectories(path))
|
|
66
|
+
return 'wp-content';
|
|
67
|
+
if (containsFullWordPressInstallation(path))
|
|
68
|
+
return 'wordpress-install';
|
|
69
|
+
return 'unknown';
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=project-type-detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-type-detect.js","sourceRoot":"","sources":["../../src/options/project-type-detect.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,2CAA2C;AAC3C,mCAAmC;AACnC,qGAAqG;AAErG,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B;;;GAGG;AACH,MAAM,UAAU,iCAAiC,CAAC,IAAY;IAC5D,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAChC,OAAO,CACL,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC1B,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC;QAC7B,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,CAC7B,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,4BAA4B,CAAC,IAAY;IACvD,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAChC,OAAO,CACL,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACxB,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC;QACzB,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC;QAC5B,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAC1B,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,eAAe,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC;IACtE,MAAM,cAAc,GAAG,gDAAgD,CAAC;IACxE,OAAO,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAChD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,eAAe,GAAG,iDAAiD,CAAC;IAC1E,MAAM,eAAe,GAAG,KAAK;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;SACvC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;QACb,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;QAC3D,OAAO,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IACL,OAAO,CAAC,CAAC,eAAe,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,IAAI,gBAAgB,CAAC,IAAI,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC5C,IAAI,gBAAgB,CAAC,IAAI,CAAC;QAAE,OAAO,OAAO,CAAC;IAC3C,IAAI,4BAA4B,CAAC,IAAI,CAAC;QAAE,OAAO,YAAY,CAAC;IAC5D,IAAI,iCAAiC,CAAC,IAAI,CAAC;QAAE,OAAO,mBAAmB,CAAC;IACxE,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { WPTesterConfig } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Project type detection option
|
|
4
|
+
* Detects WordPress project type and asks user to confirm
|
|
5
|
+
*/
|
|
6
|
+
export declare function projectTypeOption(config: WPTesterConfig): Promise<WPTesterConfig>;
|
|
7
|
+
//# sourceMappingURL=project-type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-type.d.ts","sourceRoot":"","sources":["../../src/options/project-type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAK/C;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,cAAc,CAAC,CAkDzB"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as clack from "@clack/prompts";
|
|
2
|
+
import { getProjectDir } from "../config.js";
|
|
3
|
+
import { detectProjectType } from "./project-type-detect.js";
|
|
4
|
+
/**
|
|
5
|
+
* Project type detection option
|
|
6
|
+
* Detects WordPress project type and asks user to confirm
|
|
7
|
+
*/
|
|
8
|
+
export async function projectTypeOption(config) {
|
|
9
|
+
// Get the project root directory using the config helper
|
|
10
|
+
const projectHostPath = getProjectDir(config);
|
|
11
|
+
// Detect project type
|
|
12
|
+
const detectedType = detectProjectType(projectHostPath);
|
|
13
|
+
// Ask for confirmation with the detected type in the question
|
|
14
|
+
const message = detectedType === 'unknown'
|
|
15
|
+
? "We couldn't detect your project type. Continue with setup anyway?"
|
|
16
|
+
: `Is this project a ${detectedType}?`;
|
|
17
|
+
const isCorrect = await clack.confirm({
|
|
18
|
+
message,
|
|
19
|
+
initialValue: true,
|
|
20
|
+
});
|
|
21
|
+
// Handle cancel
|
|
22
|
+
if (clack.isCancel(isCorrect)) {
|
|
23
|
+
clack.cancel("Setup cancelled.");
|
|
24
|
+
process.exit(0);
|
|
25
|
+
}
|
|
26
|
+
let finalType = detectedType;
|
|
27
|
+
// If not correct, show selection menu
|
|
28
|
+
if (!isCorrect) {
|
|
29
|
+
const selectedType = await clack.select({
|
|
30
|
+
message: "Select project type:",
|
|
31
|
+
options: [
|
|
32
|
+
{ value: 'plugin', label: 'plugin' },
|
|
33
|
+
{ value: 'theme', label: 'theme' },
|
|
34
|
+
{ value: 'unknown', label: 'other' },
|
|
35
|
+
],
|
|
36
|
+
});
|
|
37
|
+
// Handle cancel
|
|
38
|
+
if (clack.isCancel(selectedType)) {
|
|
39
|
+
clack.cancel("Setup cancelled.");
|
|
40
|
+
process.exit(0);
|
|
41
|
+
}
|
|
42
|
+
finalType = selectedType;
|
|
43
|
+
}
|
|
44
|
+
// Return config with project type
|
|
45
|
+
return {
|
|
46
|
+
...config,
|
|
47
|
+
projectType: finalType,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=project-type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-type.js","sourceRoot":"","sources":["../../src/options/project-type.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAoB,MAAM,uBAAuB,CAAC;AAE5E;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAsB;IAEtB,yDAAyD;IACzD,MAAM,eAAe,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAE9C,sBAAsB;IACtB,MAAM,YAAY,GAAG,iBAAiB,CAAC,eAAe,CAAC,CAAC;IAExD,8DAA8D;IAC9D,MAAM,OAAO,GAAG,YAAY,KAAK,SAAS;QACxC,CAAC,CAAC,mEAAmE;QACrE,CAAC,CAAC,qBAAqB,YAAY,GAAG,CAAC;IAEzC,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC;QACpC,OAAO;QACP,YAAY,EAAE,IAAI;KACnB,CAAC,CAAC;IAEH,gBAAgB;IAChB,IAAI,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,SAAS,GAAgB,YAAY,CAAC;IAE1C,sCAAsC;IACtC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,YAAY,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC;YACtC,OAAO,EAAE,sBAAsB;YAC/B,OAAO,EAAE;gBACP,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;gBACpC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;gBAClC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE;aACrC;SACF,CAAC,CAAC;QAEH,gBAAgB;QAChB,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YACjC,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,SAAS,GAAG,YAA2B,CAAC;IAC1C,CAAC;IAED,kCAAkC;IAClC,OAAO;QACL,GAAG,MAAM;QACT,WAAW,EAAE,SAAS;KACvB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smoke-tests.d.ts","sourceRoot":"","sources":["../../src/options/smoke-tests.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAS,MAAM,UAAU,CAAC;AAItD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQ9D;AAED,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,cAAc,CAAC,CAkFzB"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import * as clack from '@clack/prompts';
|
|
2
|
+
import { getProjectDir } from '../config.js';
|
|
3
|
+
export function validateSlug(value) {
|
|
4
|
+
if (!value || value.trim().length === 0) {
|
|
5
|
+
return 'Slug cannot be empty';
|
|
6
|
+
}
|
|
7
|
+
if (/\s/.test(value)) {
|
|
8
|
+
return 'Slug must be a single word (no spaces)';
|
|
9
|
+
}
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
export async function smokeTestsOption(config) {
|
|
13
|
+
const tests = {};
|
|
14
|
+
// Get default slug from project directory name
|
|
15
|
+
const projectHostPath = getProjectDir(config);
|
|
16
|
+
const defaultSlug = projectHostPath.split('/').pop() || '';
|
|
17
|
+
// Ask about WordPress smoke tests
|
|
18
|
+
const runWpTests = await clack.confirm({
|
|
19
|
+
message: "Do you want to run WordPress smoke tests?",
|
|
20
|
+
initialValue: true,
|
|
21
|
+
});
|
|
22
|
+
if (clack.isCancel(runWpTests)) {
|
|
23
|
+
clack.cancel("Setup cancelled.");
|
|
24
|
+
process.exit(0);
|
|
25
|
+
}
|
|
26
|
+
if (runWpTests) {
|
|
27
|
+
tests.wp = true;
|
|
28
|
+
}
|
|
29
|
+
// Ask about plugin tests if project type is plugin
|
|
30
|
+
if (config.projectType === 'plugin') {
|
|
31
|
+
const runPluginTests = await clack.confirm({
|
|
32
|
+
message: "Do you want to run Plugin smoke tests?",
|
|
33
|
+
initialValue: true,
|
|
34
|
+
});
|
|
35
|
+
if (clack.isCancel(runPluginTests)) {
|
|
36
|
+
clack.cancel("Setup cancelled.");
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
if (runPluginTests) {
|
|
40
|
+
const pluginSlug = await clack.text({
|
|
41
|
+
message: "Enter the plugin slug:",
|
|
42
|
+
initialValue: defaultSlug,
|
|
43
|
+
validate: validateSlug,
|
|
44
|
+
});
|
|
45
|
+
if (clack.isCancel(pluginSlug)) {
|
|
46
|
+
clack.cancel("Setup cancelled.");
|
|
47
|
+
process.exit(0);
|
|
48
|
+
}
|
|
49
|
+
tests.plugin = pluginSlug;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Ask about theme tests if project type is theme
|
|
53
|
+
if (config.projectType === 'theme') {
|
|
54
|
+
const runThemeTests = await clack.confirm({
|
|
55
|
+
message: "Do you want to run Theme smoke tests?",
|
|
56
|
+
initialValue: true,
|
|
57
|
+
});
|
|
58
|
+
if (clack.isCancel(runThemeTests)) {
|
|
59
|
+
clack.cancel("Setup cancelled.");
|
|
60
|
+
process.exit(0);
|
|
61
|
+
}
|
|
62
|
+
if (runThemeTests) {
|
|
63
|
+
const themeSlug = await clack.text({
|
|
64
|
+
message: "Enter the theme slug:",
|
|
65
|
+
initialValue: defaultSlug,
|
|
66
|
+
validate: validateSlug,
|
|
67
|
+
});
|
|
68
|
+
if (clack.isCancel(themeSlug)) {
|
|
69
|
+
clack.cancel("Setup cancelled.");
|
|
70
|
+
process.exit(0);
|
|
71
|
+
}
|
|
72
|
+
tests.theme = themeSlug;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
...config,
|
|
77
|
+
tests,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=smoke-tests.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smoke-tests.js","sourceRoot":"","sources":["../../src/options/smoke-tests.ts"],"names":[],"mappings":"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"}
|