Skip to content

Commit fb7dd55

Browse files
jdhuntingtonGeeWee
authored andcommittedMar 14, 2019
feat(config): specify package.json location (#823) (#1013)
* feat(config): specify package.json location (#823) * fix(docs): package.json config option (#823) Document the package.json config option.
1 parent 279edcd commit fb7dd55

File tree

7 files changed

+171
-9
lines changed

7 files changed

+171
-9
lines changed
 

‎docs/user/config/index.md

+2
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ All options have default values which should fit most of the projects. Click on
193193
| [**`diagnostics`**][diagnostics] | [Diagnostics related configuration.][diagnostics] | `boolean`\|`object` | `true` |
194194
| [**`babelConfig`**][babelConfig] | [Babel(Jest) related configuration.][babelConfig] | `boolean`\|`object` | _disabled_ |
195195
| [**`stringifyContentPathRegex`**][stringifyContentPathRegex] | [Files which will become modules returning self content.][stringifyContentPathRegex] | `string`\|`RegExp` | _disabled_ |
196+
| [**`packageJson`**][packageJson] | [Package metadata.][packageJson] | `string`\|`object`\|`boolean` | _auto_ |
196197

197198
### Upgrading
198199

@@ -222,3 +223,4 @@ npx ts-jest config:migrate package.json
222223
[diagnostics]: diagnostics
223224
[babelConfig]: babelConfig
224225
[stringifyContentPathRegex]: stringifyContentPathRegex
226+
[packageJson]: packageJson

‎docs/user/config/packageJson.md

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
title: packageJson Config option
3+
---
4+
5+
The `packageJson` option specifies the `package.json` file to use. An inline object may also be specified instead of a file path.
6+
7+
By default, the `package.json` file at the root of the project will be used. If it cannot be found, an empty project definition will be used instead.
8+
9+
### Examples
10+
11+
#### Path to a `packageJson` file
12+
13+
The path should be relative to the current working directory where you start Jest from. You can also use `<rootDir>` in the path to start from the project root dir.
14+
15+
<div class="row"><div class="col-md-6" markdown="block">
16+
17+
```js
18+
// jest.config.js
19+
module.exports = {
20+
// [...]
21+
globals: {
22+
'ts-jest': {
23+
packageJson: 'package.json'
24+
}
25+
}
26+
};
27+
```
28+
29+
</div><div class="col-md-6" markdown="block">
30+
31+
```js
32+
// OR from a non-trivial path
33+
// jest.config.js
34+
module.exports = {
35+
// [...]
36+
globals: {
37+
'ts-jest': {
38+
packageJson: '<rootDir>/../../shared/package.json'
39+
}
40+
}
41+
};
42+
```
43+
44+
</div></div>
45+
46+
#### Inline package metadata
47+
48+
<div class="row"><div class="col-md-12" markdown="block">
49+
50+
```js
51+
// jest.config.js
52+
module.exports = {
53+
// [...]
54+
globals: {
55+
'ts-jest': {
56+
packageJson: {
57+
"name": "my-project",
58+
"version": "1.0.0",
59+
"dependencies": {
60+
// [...]
61+
}
62+
}
63+
}
64+
}
65+
};
66+
```
67+
68+
</div></div>
69+

‎src/__helpers__/fakers.ts

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ export function tsJestConfig(options?: Partial<TsJestConfig>): TsJestConfig {
6060
transformers: [],
6161
babelConfig: undefined,
6262
tsConfig: undefined,
63+
packageJson: undefined,
6364
stringifyContentPathRegex: undefined,
6465
diagnostics: { ignoreCodes: [], pretty: false, throws: true },
6566
...options,

‎src/config/__snapshots__/config-set.spec.ts.snap

+4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ Object {
3232
"throws": true,
3333
},
3434
"isolatedModules": false,
35+
"packageJson": Object {
36+
"kind": "file",
37+
"value": undefined,
38+
},
3539
"stringifyContentPathRegex": undefined,
3640
"transformers": Array [],
3741
"tsConfig": Object {

‎src/config/config-set.spec.ts

+33-1
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,34 @@ describe('tsJest', () => {
103103
})
104104
}) // tsconfig
105105

106+
describe('packageJson', () => {
107+
it('should be correct for default value', () => {
108+
const EXPECTED = {
109+
kind: 'file',
110+
value: undefined,
111+
}
112+
expect(get().packageJson).toEqual(EXPECTED)
113+
})
114+
115+
it('should be correct for given file', () => {
116+
const FILE = 'bar/tsconfig.foo.json'
117+
const EXPECTED = {
118+
kind: 'file',
119+
value: defaultResolve(FILE),
120+
}
121+
expect(get({ packageJson: FILE }).packageJson).toEqual(EXPECTED)
122+
})
123+
124+
it('should be correct for inline config', () => {
125+
const CONFIG = { foo: 'bar' }
126+
const EXPECTED = {
127+
kind: 'inline',
128+
value: CONFIG,
129+
}
130+
expect(get({ packageJson: CONFIG as any }).packageJson).toEqual(EXPECTED)
131+
})
132+
}) // packageJson
133+
106134
describe('babelConfig', () => {
107135
it('should be correct for default value', () => {
108136
expect(get().babelConfig).toBeUndefined()
@@ -532,7 +560,7 @@ describe('cacheKey', () => {
532560
cs.jsonValue.value = val
533561
// digest is mocked in src/__mocks__/index.ts
534562
expect(cs.cacheKey).toMatchInlineSnapshot(
535-
'"{\\"digest\\":\\"a0d51ca854194df8191d0e65c0ca4730f510f332\\",\\"jest\\":{\\"__backported\\":true,\\"globals\\":{}},\\"projectDepVersions\\":{\\"dev\\":\\"1.2.5\\",\\"opt\\":\\"1.2.3\\",\\"peer\\":\\"1.2.4\\",\\"std\\":\\"1.2.6\\"},\\"transformers\\":[\\"hoisting-jest-mock@1\\"],\\"tsJest\\":{\\"compiler\\":\\"typescript\\",\\"diagnostics\\":{\\"ignoreCodes\\":[6059,18002,18003],\\"pretty\\":true,\\"throws\\":true},\\"isolatedModules\\":false,\\"transformers\\":[]},\\"tsconfig\\":{\\"declaration\\":false,\\"inlineSourceMap\\":false,\\"inlineSources\\":true,\\"module\\":1,\\"noEmit\\":false,\\"outDir\\":\\"$$ts-jest$$\\",\\"removeComments\\":false,\\"sourceMap\\":true,\\"target\\":1}}"',
563+
'"{\\"digest\\":\\"a0d51ca854194df8191d0e65c0ca4730f510f332\\",\\"jest\\":{\\"__backported\\":true,\\"globals\\":{}},\\"projectDepVersions\\":{\\"dev\\":\\"1.2.5\\",\\"opt\\":\\"1.2.3\\",\\"peer\\":\\"1.2.4\\",\\"std\\":\\"1.2.6\\"},\\"transformers\\":[\\"hoisting-jest-mock@1\\"],\\"tsJest\\":{\\"compiler\\":\\"typescript\\",\\"diagnostics\\":{\\"ignoreCodes\\":[6059,18002,18003],\\"pretty\\":true,\\"throws\\":true},\\"isolatedModules\\":false,\\"packageJson\\":{\\"kind\\":\\"file\\"},\\"transformers\\":[]},\\"tsconfig\\":{\\"declaration\\":false,\\"inlineSourceMap\\":false,\\"inlineSources\\":true,\\"module\\":1,\\"noEmit\\":false,\\"outDir\\":\\"$$ts-jest$$\\",\\"removeComments\\":false,\\"sourceMap\\":true,\\"target\\":1}}"',
536564
)
537565
})
538566
}) // cacheKey
@@ -579,6 +607,10 @@ Object {
579607
"throws": true,
580608
},
581609
"isolatedModules": false,
610+
"packageJson": Object {
611+
"kind": "file",
612+
"value": undefined,
613+
},
582614
"stringifyContentPathRegex": undefined,
583615
"transformers": Array [],
584616
"tsConfig": undefined,

‎src/config/config-set.ts

+44-8
Original file line numberDiff line numberDiff line change
@@ -114,18 +114,38 @@ const toDiagnosticCodeList = (items: any, into: number[] = []): number[] => {
114114
export class ConfigSet {
115115
@Memoize()
116116
get projectPackageJson(): Record<string, any> {
117+
const {
118+
tsJest: { packageJson },
119+
} = this
120+
121+
if (packageJson && packageJson.kind === 'inline') {
122+
return packageJson.value
123+
}
124+
125+
if (packageJson && packageJson.kind === 'file' && packageJson.value) {
126+
const path = this.resolvePath(packageJson.value)
127+
if (existsSync(path)) {
128+
return require(path)
129+
}
130+
this.logger.warn(Errors.UnableToFindProjectRoot)
131+
return {}
132+
}
133+
117134
const tsJestRoot = resolve(__dirname, '..', '..')
118135
let pkgPath = resolve(tsJestRoot, '..', '..', 'package.json')
119-
let exists = existsSync(pkgPath)
120-
if (!exists) {
121-
if (realpathSync(this.rootDir) === realpathSync(tsJestRoot)) {
122-
pkgPath = resolve(tsJestRoot, 'package.json')
123-
exists = true
124-
} else {
125-
this.logger.warn(Errors.UnableToFindProjectRoot)
136+
if (existsSync(pkgPath)) {
137+
return require(pkgPath)
138+
}
139+
140+
if (realpathSync(this.rootDir) === realpathSync(tsJestRoot)) {
141+
pkgPath = resolve(tsJestRoot, 'package.json')
142+
if (existsSync(pkgPath)) {
143+
return require(pkgPath)
126144
}
127145
}
128-
return exists ? require(pkgPath) : {}
146+
147+
this.logger.warn(Errors.UnableToFindProjectRoot)
148+
return {}
129149
}
130150

131151
@Memoize()
@@ -183,6 +203,21 @@ export class ConfigSet {
183203
}
184204
}
185205

206+
// packageJson
207+
const { packageJson: packageJsonOpt } = options
208+
let packageJson: TsJestConfig['packageJson']
209+
if (typeof packageJsonOpt === 'string' || packageJsonOpt == null || packageJsonOpt === true) {
210+
packageJson = {
211+
kind: 'file',
212+
value: typeof packageJsonOpt === 'string' ? this.resolvePath(packageJsonOpt) : undefined,
213+
}
214+
} else if (typeof packageJsonOpt === 'object') {
215+
packageJson = {
216+
kind: 'inline',
217+
value: packageJsonOpt,
218+
}
219+
}
220+
186221
// transformers
187222
const transformers = (options.astTransformers || []).map(mod => this.resolvePath(mod, { nodeResolve: true }))
188223

@@ -234,6 +269,7 @@ export class ConfigSet {
234269
// parsed options
235270
const res: TsJestConfig = {
236271
tsConfig,
272+
packageJson,
237273
babelConfig,
238274
diagnostics,
239275
isolatedModules: !!options.isolatedModules,

‎src/types.ts

+18
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ export interface TsJestGlobalOptions {
2121
*/
2222
tsConfig?: boolean | string | CompilerOptions
2323

24+
/**
25+
* packageJson. It can be:
26+
* - `true` (or `undefined`, it's the default): use default package.json file
27+
* - `path/to/package.json`: path to a specific package.json file (<rootDir> can be used)
28+
* - `{...}`: contents of a package.json
29+
*/
30+
packageJson?: boolean | string | object
31+
2432
/**
2533
* Whether to compile files as isolated modules (disables some features and type-checking, default to `false`):
2634
*/
@@ -93,10 +101,20 @@ interface TsJestConfig$babelConfig$inline {
93101
value: BabelConfig
94102
}
95103
type TsJestConfig$babelConfig = TsJestConfig$babelConfig$file | TsJestConfig$babelConfig$inline | undefined
104+
interface TsJestConfig$packageJson$file {
105+
kind: 'file'
106+
value: string | undefined
107+
}
108+
interface TsJestConfig$packageJson$inline {
109+
kind: 'inline'
110+
value: any
111+
}
112+
type TsJestConfig$packageJson = TsJestConfig$packageJson$file | TsJestConfig$packageJson$inline | undefined
96113
type TsJestConfig$stringifyContentPathRegex = string | undefined
97114

98115
export interface TsJestConfig {
99116
tsConfig: TsJestConfig$tsConfig
117+
packageJson: TsJestConfig$packageJson
100118
isolatedModules: boolean
101119
compiler: string
102120
diagnostics: TsJestConfig$diagnostics

0 commit comments

Comments
 (0)
Please sign in to comment.