forked from devcontainers/cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
test.ts
119 lines (108 loc) · 5.27 KB
/
test.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import { Argv } from 'yargs';
import { CLIHost, getCLIHost } from '../../spec-common/cliHost';
import { loadNativeModule } from '../../spec-common/commonUtils';
import { LogLevel, mapLogLevel } from '../../spec-utils/log';
import { getPackageConfig, PackageConfiguration } from '../../spec-utils/product';
import { UnpackArgv } from '../devContainersSpecCLI';
import { doFeaturesTestCommand } from './testCommandImpl';
// -- 'features test' command
export function featuresTestOptions(y: Argv) {
return y
.options({
'project-folder': { type: 'string', alias: 'p', default: '.', description: 'Path to folder containing \'src\' and \'test\' sub-folders. This is likely the git root of the project.' },
'features': { array: true, alias: 'f', describe: 'Feature(s) to test as space-separated parameters. Omit to run all tests. Cannot be combined with \'--global-scenarios-only\'.' },
'filter': { type: 'string', describe: 'Filter current tests to only run scenarios containing this string. Cannot be combined with \'--skip-scenarios\'.' },
'global-scenarios-only': { type: 'boolean', default: false, description: 'Run only scenario tests under \'tests/_global\' . Cannot be combined with \'-f\'.' },
'skip-scenarios': { type: 'boolean', default: false, description: 'Skip all \'scenario\' style tests. Cannot be combined with \'--global--scenarios-only\'.' },
'skip-autogenerated': { type: 'boolean', default: false, description: 'Skip all \'autogenerated\' style tests.' },
'base-image': { type: 'string', alias: 'i', default: 'ubuntu:focal', description: 'Base Image. Not used for scenarios.' }, // TODO: Optionally replace 'scenario' configs with this value?
'remote-user': { type: 'string', alias: 'u', describe: 'Remote user. Not used for scenarios.', }, // TODO: Optionally replace 'scenario' configs with this value?
'log-level': { choices: ['info' as 'info', 'debug' as 'debug', 'trace' as 'trace'], default: 'info' as 'info', description: 'Log level.' },
'skip-image-metadata': { type: 'boolean', default: false, description: 'Skip applying image metadata to the resultant test image. Image metadata is potentially appended to base images built with the dev container CLI' },
'quiet': { type: 'boolean', alias: 'q', default: false, description: 'Quiets output' },
})
// DEPRECATED: Positional arguments don't play nice with the variadic/array --features option.
// Pass target directory with '--project-folder' instead.
// This will still continue to work, but any value provided by --project-folder will be preferred.
// Omitting both will default to the current working directory.
.deprecateOption('target', 'Use --project-folder instead')
.positional('target', { type: 'string', default: '.', description: 'Path to folder containing \'src\' and \'test\' sub-folders.', })
// Validation
.check(argv => {
if (argv['global-scenarios-only'] && argv['features']) {
throw new Error('Cannot combine --global-scenarios-only and --features');
}
if (argv['skip-scenarios'] && argv['global-scenarios-only']) {
throw new Error('Cannot combine --skip-scenarios and --global-scenarios-only');
}
if (argv['filter-scenarios'] && argv['skip-scenarios']) {
throw new Error('Cannot combine --filter-scenarios and --skip-scenarios');
}
return true;
});
}
export type FeaturesTestArgs = UnpackArgv<ReturnType<typeof featuresTestOptions>>;
export interface FeaturesTestCommandInput {
cliHost: CLIHost;
pkg: PackageConfiguration;
baseImage: string;
collectionFolder: string;
features?: string[];
filter: string | undefined;
globalScenariosOnly: boolean;
skipScenarios: boolean;
skipAutogenerated: boolean;
remoteUser: string | undefined;
quiet: boolean;
skipImageMetadata: boolean;
logLevel: LogLevel;
disposables: (() => Promise<unknown> | undefined)[];
}
export function featuresTestHandler(args: FeaturesTestArgs) {
(async () => await featuresTest(args))().catch(console.error);
}
async function featuresTest({
'base-image': baseImage,
'target': collectionFolder_deprecated,
'project-folder': collectionFolder,
features,
filter,
'global-scenarios-only': globalScenariosOnly,
'skip-scenarios': skipScenarios,
'skip-autogenerated': skipAutogenerated,
'remote-user': remoteUser,
quiet,
'skip-image-metadata': skipImageMetadata,
'log-level': inputLogLevel,
}: FeaturesTestArgs) {
const disposables: (() => Promise<unknown> | undefined)[] = [];
const dispose = async () => {
await Promise.all(disposables.map(d => d()));
};
const cwd = process.cwd();
const cliHost = await getCLIHost(cwd, loadNativeModule);
const pkg = getPackageConfig();
const logLevel = mapLogLevel(inputLogLevel);
// Prefer the new --project-folder option over the deprecated positional argument.
const targetProject = collectionFolder !== '.' ? collectionFolder : collectionFolder_deprecated;
const args: FeaturesTestCommandInput = {
baseImage,
cliHost,
logLevel,
quiet,
pkg,
collectionFolder: cliHost.path.resolve(targetProject),
features: features ? (Array.isArray(features) ? features as string[] : [features]) : undefined,
filter,
globalScenariosOnly,
skipScenarios,
skipAutogenerated,
remoteUser,
skipImageMetadata,
disposables
};
const exitCode = await doFeaturesTestCommand(args);
await dispose();
process.exit(exitCode);
}
// -- End: 'features test' command