Skip to content

Commit

Permalink
fix(stryker init): update metadata for stryker init command (#1403)
Browse files Browse the repository at this point in the history
Make sure `stryker init` command resolves correct metadata
in order to correctly initialize the questionnaire and stryker.conf.js.

Fixes #1402
  • Loading branch information
nicojs authored and simondel committed Feb 13, 2019
1 parent a7922a4 commit 38f269b
Show file tree
Hide file tree
Showing 20 changed files with 107 additions and 100 deletions.
3 changes: 1 addition & 2 deletions packages/babel-transpiler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@
},
"keywords": [
"stryker",
"stryker-mutator-plugin",
"@stryker-mutator/transpiler-plugin",
"javascript",
"transpiler-plugin",
"babel"
],
"publishConfig": {
Expand Down
13 changes: 13 additions & 0 deletions packages/core/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,19 @@
"${workspaceRoot}/src/**/*.js"
]
},
{
"type": "node",
"request": "launch",
"name": "Index",
"program": "${workspaceRoot}/index.js",
"args": [
],
"internalConsoleOptions": "openOnSessionStart",
"outFiles": [
"${workspaceRoot}/test/**/*.js",
"${workspaceRoot}/src/**/*.js"
]
},
{
"type": "node",
"request": "launch",
Expand Down
45 changes: 20 additions & 25 deletions packages/core/src/initializer/NpmClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,13 @@ import { RestClient, IRestResponse } from 'typed-rest-client/RestClient';
import PromptOption from './PromptOption';
import { errorToString } from '@stryker-mutator/util';
import { tokens, commonTokens } from '@stryker-mutator/api/plugin';
import { initializerTokens, BASE_NPM_SEARCH, BASE_NPM_PACKAGE } from '.';
import { initializerTokens } from '.';
import { Logger } from '@stryker-mutator/api/logging';
import { PackageInfo } from './PackageInfo';

interface NpmSearchPackageInfo {
package: {
name: string;
keywords: string[];
};
}
interface NpmSearchResult {
total: number;
results: NpmSearchPackageInfo[];
results: { package: PackageInfo }[];
}

interface NpmPackage {
Expand All @@ -29,14 +24,14 @@ const getName = (packageName: string) => {

const mapSearchResultToPromptOption = (searchResults: NpmSearchResult): PromptOption[] => searchResults.results.map(result => ({
name: getName(result.package.name),
npm: result.package.name
pkg: result.package
}));

const handleResult = (from: string) => <T>(response: IRestResponse<T>): T => {
if (response.statusCode === 200 && response.result) {
return response.result;
} else {
throw new Error(`Query ${from} resulted in http status code: ${response.statusCode}.`);
throw new Error(`Path ${from} resulted in http status code: ${response.statusCode}.`);
}
};

Expand All @@ -50,12 +45,12 @@ export default class NpmClient {
}

public getTestRunnerOptions(): Promise<PromptOption[]> {
return this.search('/v2/search?q=keywords:stryker-mutator-plugin+test-runner-plugin')
return this.search('/v2/search?q=keywords:@stryker-mutator/test-runner-plugin')
.then(mapSearchResultToPromptOption);
}

public getTestFrameworkOptions(testRunnerFilter: string | null): Promise<PromptOption[]> {
return this.search('/v2/search?q=keywords:stryker-mutator-plugin+test-framework-plugin')
return this.search('/v2/search?q=keywords:@stryker-mutator/test-framework-plugin')
.then(searchResult => {
if (testRunnerFilter) {
searchResult.results = searchResult.results.filter(framework => framework.package.keywords.indexOf(testRunnerFilter) >= 0);
Expand All @@ -66,37 +61,37 @@ export default class NpmClient {
}

public getMutatorOptions(): Promise<PromptOption[]> {
return this.search('/v2/search?q=keywords:stryker-mutator-plugin+mutator-plugin')
return this.search('/v2/search?q=keywords:@stryker-mutator/mutator-plugin')
.then(mapSearchResultToPromptOption);
}

public getTranspilerOptions(): Promise<PromptOption[]> {
return this.search('/v2/search?q=keywords:stryker-mutator-plugin+transpiler-plugin')
return this.search('/v2/search?q=keywords:@stryker-mutator/transpiler-plugin')
.then(mapSearchResultToPromptOption);
}

public getTestReporterOptions(): Promise<PromptOption[]> {
return this.search(`/v2/search?q=keywords:stryker-mutator-plugin+reporter-plugin`)
return this.search(`/v2/search?q=keywords:@stryker-mutator/reporter-plugin`)
.then(mapSearchResultToPromptOption);
}

public getAdditionalConfig(packageName: string): Promise<object> {
return this.packageClient.get<NpmPackage>(`/${packageName}/latest`)
.then(handleResult(`${BASE_NPM_PACKAGE}/${packageName}`))
public getAdditionalConfig(pkg: PackageInfo): Promise<object> {
const path = `/${pkg.name}@${pkg.version}/package.json`;
return this.packageClient.get<NpmPackage>(path)
.then(handleResult(path))
.then(pkg => pkg.initStrykerConfig || {})
.catch(err => {
this.log.warn(`Could not fetch additional initialization config for dependency ${packageName}. You might need to configure it manually`, err);
this.log.warn(`Could not fetch additional initialization config for dependency ${pkg.name}. You might need to configure it manually`, err);
return {};
});
}

private search(query: string): Promise<NpmSearchResult> {
const call = BASE_NPM_SEARCH + query;
this.log.debug(`Searching: ${call}`);
return this.searchClient.get<NpmSearchResult>(query)
.then(handleResult(call))
private search(path: string): Promise<NpmSearchResult> {
this.log.debug(`Searching: ${path}`);
return this.searchClient.get<NpmSearchResult>(path)
.then(handleResult(path))
.catch(err => {
this.log.error(`Unable to reach ${BASE_NPM_SEARCH} (for query ${query}). Please check your internet connection.`, errorToString(err));
this.log.error(`Unable to reach npms.io (for query ${path}). Please check your internet connection.`, errorToString(err));
const result: NpmSearchResult = {
results: [],
total: 0
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/initializer/PackageInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface PackageInfo {
name: string;
keywords: string[];
version: string;
}
4 changes: 3 additions & 1 deletion packages/core/src/initializer/PromptOption.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { PackageInfo } from './PackageInfo';

interface PromptOption {
name: string;
npm: string | null;
pkg: PackageInfo | null;
}

export default PromptOption;
34 changes: 18 additions & 16 deletions packages/core/src/initializer/StrykerInitializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import CommandTestRunner from '../test-runner/CommandTestRunner';
import Preset from './presets/Preset';
import { initializerTokens } from '.';
import { tokens, commonTokens } from '@stryker-mutator/api/plugin';
import { PackageInfo } from './PackageInfo';

const enum PackageManager {
Npm = 'npm',
Expand Down Expand Up @@ -101,7 +102,7 @@ export default class StrykerInitializer {
selectedReporters,
selectedPackageManager,
await this.fetchAdditionalConfig(npmDependencies));
this.installNpmDependencies(npmDependencies, selectedPackageManager);
this.installNpmDependencies(npmDependencies.map(pkg => pkg.name), selectedPackageManager);
}

private async selectTestRunner(): Promise<PromptOption | null> {
Expand All @@ -120,26 +121,26 @@ export default class StrykerInitializer {
reporterOptions = await this.client.getTestReporterOptions();
reporterOptions.push({
name: 'clear-text',
npm: null
pkg: null
}, {
name: 'progress',
npm: null
pkg: null
}, {
name: 'dashboard',
npm: null
pkg: null
}
);
return this.inquirer.promptReporters(reporterOptions);
}

private async selectTestFramework(testRunnerOption: PromptOption): Promise<null | PromptOption> {
let selectedTestFramework: PromptOption | null = null;
const testFrameworkOptions = await this.client.getTestFrameworkOptions(testRunnerOption.npm);
const testFrameworkOptions = await this.client.getTestFrameworkOptions(testRunnerOption.pkg ? testRunnerOption.pkg.name : null);
if (testFrameworkOptions.length) {
this.log.debug(`Found test frameworks for ${testRunnerOption.name}: ${JSON.stringify(testFrameworkOptions)}`);
const none = {
const none: PromptOption = {
name: 'None/other',
npm: null
pkg: null
};
testFrameworkOptions.push(none);
selectedTestFramework = await this.inquirer.promptTestFrameworks(testFrameworkOptions);
Expand Down Expand Up @@ -179,18 +180,18 @@ export default class StrykerInitializer {
return this.inquirer.promptPackageManager([
{
name: PackageManager.Npm,
npm: null,
pkg: null
},
{
name: PackageManager.Yarn,
npm: null,
pkg: null
}
]);
}

private getSelectedNpmDependencies(selectedOptions: (PromptOption | null)[]) {
private getSelectedNpmDependencies(selectedOptions: (PromptOption | null)[]): PackageInfo[] {
return filterEmpty(filterEmpty(selectedOptions)
.map(option => option.npm));
.map(option => option.pkg));
}

/**
Expand All @@ -202,10 +203,11 @@ export default class StrykerInitializer {
return;
}

const dependencyArg = dependencies.join(' ');
this.out('Installing NPM dependencies...');
const cmd = selectedOption.name === PackageManager.Npm
? `npm i --save-dev ${dependencies.join(' ')}`
: `yarn add ${dependencies.join(' ')} --dev`;
? `npm i --save-dev ${dependencyArg}`
: `yarn add ${dependencyArg} --dev`;
this.out(cmd);
try {
child.execSync(cmd, { stdio: [0, 1, 2] });
Expand All @@ -214,8 +216,8 @@ export default class StrykerInitializer {
}
}

private async fetchAdditionalConfig(dependencies: string[]): Promise<object[]> {
return filterEmpty(await Promise.all(dependencies.map(dep =>
this.client.getAdditionalConfig(dep))));
private async fetchAdditionalConfig(dependencies: PackageInfo[]): Promise<object[]> {
return filterEmpty(await Promise.all(dependencies
.map(dep => this.client.getAdditionalConfig(dep))));
}
}
4 changes: 2 additions & 2 deletions packages/core/src/initializer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import strykerPresets from './StrykerPresets';
import StrykerConfigWriter from './StrykerConfigWriter';
import { StrykerInquirer } from './StrykerInquirer';

export const BASE_NPM_SEARCH = 'https://api.npms.io';
export const BASE_NPM_PACKAGE = 'https://registry.npmjs.org';
const BASE_NPM_SEARCH = 'https://api.npms.io';
const BASE_NPM_PACKAGE = 'https://www.unpkg.com';

export function initializerFactory(): StrykerInitializer {
return rootInjector
Expand Down

0 comments on commit 38f269b

Please sign in to comment.