Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: migrate jest-resolve-dependencies to TypeScript #7922

Merged
merged 7 commits into from Feb 19, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -46,6 +46,7 @@
- `[@jest/core]` Create new package, which is `jest-cli` minus `yargs` and `prompts` ([#7696](https://github.com/facebook/jest/pull/7696))
- `[@jest/transform]`: Migrate to TypeScript ([#7918](https://github.com/facebook/jest/pull/7918))
- `[docs]` Add missing import to docs ([#7928](https://github.com/facebook/jest/pull/7928))
- `[jest-resolve-dependencies]`: Migrate to TypeScript ([#7922](https://github.com/facebook/jest/pull/7922))

### Performance

Expand Down
10 changes: 10 additions & 0 deletions packages/jest-resolve-dependencies/package.json
Expand Up @@ -8,10 +8,20 @@
},
"license": "MIT",
"main": "build/index.js",
"types": "build/index.d.ts",
"dependencies": {
"@jest/types": "^24.1.0",
"jest-regex-util": "^24.0.0",
"jest-snapshot": "^24.1.0"
},
"devDependencies": {
"jest-haste-map": "^24.0.0",
"jest-resolve": "^24.1.0"
},
"peerDependencies": {
"jest-haste-map": "^24.0.0",
"jest-resolve": "^24.1.0"
},
"engines": {
"node": ">= 6"
},
Expand Down
Expand Up @@ -7,37 +7,42 @@
*/
'use strict';
jeysal marked this conversation as resolved.
Show resolved Hide resolved

const path = require('path');
const {normalize} = require('jest-config');
const {buildSnapshotResolver} = require('jest-snapshot');
const DependencyResolver = require('../index');
import {tmpdir} from 'os';
import path from 'path';
import {Config} from '@jest/types';
import {buildSnapshotResolver} from 'jest-snapshot';
import {makeProjectConfig} from '../../../../TestUtils';

import DependencyResolver from '../index';

const maxWorkers = 1;
let dependencyResolver;
let dependencyResolver: DependencyResolver;
let Runtime;
let config;
const cases = {
let config: Config.ProjectConfig;
const cases: {[key: string]: jest.Mock} = {
fancyCondition: jest.fn(path => path.length > 10),
testRegex: jest.fn(path => /.test.js$/.test(path)),
};
const filter = path => Object.keys(cases).every(key => cases[key](path));
const filter = (path: Config.Path) =>
Object.keys(cases).every(key => cases[key](path));

beforeEach(() => {
Runtime = require('jest-runtime');
jeysal marked this conversation as resolved.
Show resolved Hide resolved
config = normalize(
{
rootDir: '.',
roots: ['./packages/jest-resolve-dependencies'],
},
{},
).options;
return Runtime.createContext(config, {maxWorkers}).then(hasteMap => {
dependencyResolver = new DependencyResolver(
hasteMap.resolver,
hasteMap.hasteFS,
buildSnapshotResolver(config),
);
config = makeProjectConfig({
cacheDirectory: path.resolve(tmpdir(), 'jest-resolve-dependencies-test'),
moduleDirectories: ['node_modules'],
rootDir: '.',
roots: ['./packages/jest-resolve-dependencies'],
});
return Runtime.createContext(config, {maxWorkers, watchman: false}).then(
(hasteMap: any) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could type as HasteMap, but doesn't matter in a test

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that's what I meant in #7922 (comment), would prefer to do it in another PR though since I expect it to become rather big

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good!

dependencyResolver = new DependencyResolver(
hasteMap.resolver,
hasteMap.hasteFS,
buildSnapshotResolver(config),
);
},
);
});

test('resolves no dependencies for non-existent path', () => {
Expand Down
Expand Up @@ -3,18 +3,11 @@
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

import type {HasteFS} from 'types/HasteMap';
import type {Path} from 'types/Config';
import type {
Resolver,
ResolveModuleConfig,
ResolvedModule,
} from 'types/Resolve';
import type {SnapshotResolver} from 'types/SnapshotResolver';
import {Config, Resolve, Snapshot} from '@jest/types';
import {FS as HasteFS} from 'jest-haste-map';
import Resolver from 'jest-resolve';
import {isSnapshotPath} from 'jest-snapshot';

/**
Expand All @@ -24,25 +17,28 @@ import {isSnapshotPath} from 'jest-snapshot';
class DependencyResolver {
_hasteFS: HasteFS;
jeysal marked this conversation as resolved.
Show resolved Hide resolved
_resolver: Resolver;
_snapshotResolver: SnapshotResolver;
_snapshotResolver: Snapshot.SnapshotResolver;

constructor(
resolver: Resolver,
hasteFS: HasteFS,
snapshotResolver: SnapshotResolver,
snapshotResolver: Snapshot.SnapshotResolver,
) {
this._resolver = resolver;
this._hasteFS = hasteFS;
this._snapshotResolver = snapshotResolver;
}

resolve(file: Path, options?: ResolveModuleConfig): Array<Path> {
resolve(
file: Config.Path,
options?: Resolve.ResolveModuleConfig,
): Array<Config.Path> {
const dependencies = this._hasteFS.getDependencies(file);
if (!dependencies) {
return [];
}

return dependencies.reduce((acc, dependency) => {
return dependencies.reduce<Array<Config.Path>>((acc, dependency) => {
if (this._resolver.isCoreModule(dependency)) {
return acc;
}
Expand All @@ -66,23 +62,27 @@ class DependencyResolver {
}

resolveInverseModuleMap(
paths: Set<Path>,
filter: (file: Path) => boolean,
options?: ResolveModuleConfig,
): Array<ResolvedModule> {
paths: Set<Config.Path>,
filter: (file: Config.Path) => boolean,
options?: Resolve.ResolveModuleConfig,
): Array<Resolve.ResolvedModule> {
if (!paths.size) {
return [];
}

const collectModules = (related, moduleMap, changed) => {
const collectModules = (
related: Set<Config.Path>,
moduleMap: Array<Resolve.ResolvedModule>,
changed: Set<Config.Path>,
) => {
const visitedModules = new Set();
const result: Array<ResolvedModule> = [];
const result: Array<Resolve.ResolvedModule> = [];
while (changed.size) {
changed = new Set(
moduleMap.reduce((acc, module) => {
moduleMap.reduce<Array<Config.Path>>((acc, module) => {
if (
visitedModules.has(module.file) ||
!module.dependencies.some(dep => dep && changed.has(dep))
!module.dependencies.some(dep => changed.has(dep))
jeysal marked this conversation as resolved.
Show resolved Hide resolved
) {
return acc;
}
Expand All @@ -98,11 +98,13 @@ class DependencyResolver {
}, []),
);
}
return result.concat(Array.from(related).map(file => ({file})));
return result.concat(
Array.from(related).map(file => ({dependencies: [], file})),
jeysal marked this conversation as resolved.
Show resolved Hide resolved
);
};

const relatedPaths = new Set<Path>();
const changed = new Set();
const relatedPaths = new Set<Config.Path>();
const changed: Set<Config.Path> = new Set();
for (const path of paths) {
if (this._hasteFS.exists(path)) {
const modulePath = isSnapshotPath(path)
Expand All @@ -114,7 +116,7 @@ class DependencyResolver {
}
}
}
const modules = [];
const modules: Array<Resolve.ResolvedModule> = [];
for (const file of this._hasteFS.getAbsoluteFileIterator()) {
modules.push({
dependencies: this.resolve(file, options),
Expand All @@ -125,14 +127,14 @@ class DependencyResolver {
}

resolveInverse(
paths: Set<Path>,
filter: (file: Path) => boolean,
options?: ResolveModuleConfig,
): Array<Path> {
paths: Set<Config.Path>,
filter: (file: Config.Path) => boolean,
options?: Resolve.ResolveModuleConfig,
): Array<Config.Path> {
return this.resolveInverseModuleMap(paths, filter, options).map(
module => module.file,
);
}
}

module.exports = DependencyResolver;
export = DependencyResolver;
12 changes: 12 additions & 0 deletions packages/jest-resolve-dependencies/tsconfig.json
@@ -0,0 +1,12 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "build"
},
"references": [
{"path": "../jest-regex-util"},
{"path": "../jest-snapshot"},
{"path": "../jest-types"}
]
}
11 changes: 3 additions & 8 deletions packages/jest-resolve/src/index.ts
Expand Up @@ -6,7 +6,7 @@
*/

import path from 'path';
import {Config} from '@jest/types';
import {Config, Resolve} from '@jest/types';
import {ModuleMap} from 'jest-haste-map';
import {sync as realpath} from 'realpath-native';
import chalk from 'chalk';
Expand All @@ -15,11 +15,6 @@ import isBuiltinModule from './isBuiltinModule';
import defaultResolver from './defaultResolver';
import {ResolverConfig} from './types';

type ResolveModuleConfig = {
skipNodeResolution?: boolean;
paths?: Config.Path[];
};

type FindNodeModuleConfig = {
basedir: Config.Path;
browser?: boolean;
Expand Down Expand Up @@ -102,7 +97,7 @@ class Resolver {
resolveModuleFromDirIfExists(
dirname: Config.Path,
moduleName: string,
options?: ResolveModuleConfig,
options?: Resolve.ResolveModuleConfig,
): Config.Path | null {
const paths = (options && options.paths) || this._options.modulePaths;
const moduleDirectory = this._options.moduleDirectories;
Expand Down Expand Up @@ -185,7 +180,7 @@ class Resolver {
resolveModule(
from: Config.Path,
moduleName: string,
options?: ResolveModuleConfig,
options?: Resolve.ResolveModuleConfig,
): Config.Path {
const dirname = path.dirname(from);
const module = this.resolveModuleFromDirIfExists(
Expand Down
17 changes: 17 additions & 0 deletions packages/jest-types/src/Resolve.ts
@@ -0,0 +1,17 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import {Path} from './Config';

export type ResolveModuleConfig = {
skipNodeResolution?: boolean;
paths?: Path[];
};
export type ResolvedModule = {
file: Path;
dependencies: Path[];
};
14 changes: 14 additions & 0 deletions packages/jest-types/src/Snapshot.ts
@@ -0,0 +1,14 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import {Path} from './Config';

export type SnapshotResolver = {
jeysal marked this conversation as resolved.
Show resolved Hide resolved
testPathForConsistencyCheck: string;
resolveSnapshotPath(testPath: Path, extension?: string): Path;
resolveTestPath(snapshotPath: Path, extension?: string): Path;
};
20 changes: 16 additions & 4 deletions packages/jest-types/src/index.ts
Expand Up @@ -7,10 +7,22 @@

import * as Config from './Config';
import * as Console from './Console';
import * as SourceMaps from './SourceMaps';
import * as TestResult from './TestResult';
import * as Matchers from './Matchers';
import * as Mocks from './Mocks';
import * as PrettyFormat from './PrettyFormat';
import * as Matchers from './Matchers';
import * as Resolve from './Resolve';
import * as Snapshot from './Snapshot';
import * as SourceMaps from './SourceMaps';
import * as TestResult from './TestResult';

export {Config, Console, SourceMaps, TestResult, Mocks, PrettyFormat, Matchers};
export {
Config,
Console,
Matchers,
Mocks,
PrettyFormat,
Resolve,
Snapshot,
SourceMaps,
TestResult,
};