feat(webpack): default tsconfig.json if not found

This commit is contained in:
Igor Randjelovic
2022-02-18 15:17:06 +01:00
parent 4fa51b6064
commit 48c51f6163
14 changed files with 934 additions and 44 deletions

View File

@ -97,6 +97,8 @@ exports[`base configuration for android 1`] = `
{ {
loader: 'ts-loader', loader: 'ts-loader',
options: { options: {
configFile: '__jest__/node_modules/@nativescript/webpack/dist/stubs/tsconfig.default.json',
context: '__jest__',
transpileOnly: true, transpileOnly: true,
allowTsInNodeModules: true, allowTsInNodeModules: true,
compilerOptions: { compilerOptions: {
@ -230,6 +232,8 @@ exports[`base configuration for android 1`] = `
{ {
async: false, async: false,
typescript: { typescript: {
configFile: '__jest__/node_modules/@nativescript/webpack/dist/stubs/tsconfig.default.json',
context: '__jest__',
memoryLimit: 4096 memoryLimit: 4096
} }
} }
@ -417,6 +421,8 @@ exports[`base configuration for ios 1`] = `
{ {
loader: 'ts-loader', loader: 'ts-loader',
options: { options: {
configFile: '__jest__/node_modules/@nativescript/webpack/dist/stubs/tsconfig.default.json',
context: '__jest__',
transpileOnly: true, transpileOnly: true,
allowTsInNodeModules: true, allowTsInNodeModules: true,
compilerOptions: { compilerOptions: {
@ -550,6 +556,8 @@ exports[`base configuration for ios 1`] = `
{ {
async: false, async: false,
typescript: { typescript: {
configFile: '__jest__/node_modules/@nativescript/webpack/dist/stubs/tsconfig.default.json',
context: '__jest__',
memoryLimit: 4096 memoryLimit: 4096
} }
} }

View File

@ -97,6 +97,8 @@ exports[`javascript configuration for android 1`] = `
{ {
loader: 'ts-loader', loader: 'ts-loader',
options: { options: {
configFile: '__jest__/node_modules/@nativescript/webpack/dist/stubs/tsconfig.default.json',
context: '__jest__',
transpileOnly: true, transpileOnly: true,
allowTsInNodeModules: true, allowTsInNodeModules: true,
compilerOptions: { compilerOptions: {
@ -230,6 +232,8 @@ exports[`javascript configuration for android 1`] = `
{ {
async: false, async: false,
typescript: { typescript: {
configFile: '__jest__/node_modules/@nativescript/webpack/dist/stubs/tsconfig.default.json',
context: '__jest__',
memoryLimit: 4096 memoryLimit: 4096
} }
} }
@ -426,6 +430,8 @@ exports[`javascript configuration for ios 1`] = `
{ {
loader: 'ts-loader', loader: 'ts-loader',
options: { options: {
configFile: '__jest__/node_modules/@nativescript/webpack/dist/stubs/tsconfig.default.json',
context: '__jest__',
transpileOnly: true, transpileOnly: true,
allowTsInNodeModules: true, allowTsInNodeModules: true,
compilerOptions: { compilerOptions: {
@ -559,6 +565,8 @@ exports[`javascript configuration for ios 1`] = `
{ {
async: false, async: false,
typescript: { typescript: {
configFile: '__jest__/node_modules/@nativescript/webpack/dist/stubs/tsconfig.default.json',
context: '__jest__',
memoryLimit: 4096 memoryLimit: 4096
} }
} }

View File

@ -1,6 +1,723 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`vue configuration for android 1`] = ` exports[`vue configuration for android 1`] = `
"{
mode: 'development',
externals: [
'package.json',
'~/package.json'
],
externalsPresets: {
node: false
},
devtool: 'inline-source-map',
target: 'node',
watchOptions: {
ignored: [
'__jest__/platforms/**',
'__jest__/App_Resources/**'
]
},
ignoreWarnings: [
/System.import\\\\(\\\\) is deprecated/
],
output: {
path: '__jest__/platforms/android/app/src/main/assets/app',
pathinfo: false,
publicPath: '',
libraryTarget: 'commonjs',
globalObject: 'global',
clean: true
},
resolve: {
symlinks: true,
alias: {
'~': '__jest__/src',
'@': '__jest__/src',
vue: 'nativescript-vue'
},
extensions: [
'.android.vue',
'.vue',
'.android.ts',
'.ts',
'.android.js',
'.js',
'.android.mjs',
'.mjs',
'.android.css',
'.css',
'.android.scss',
'.scss',
'.android.json',
'.json'
],
modules: [
'__jest__/node_modules',
'node_modules'
]
},
resolveLoader: {
modules: [
'__jest__/node_modules/@nativescript/webpack/dist/loaders',
'__jest__/node_modules',
'node_modules'
]
},
module: {
rules: [
/* config.module.rule('bundle') */
{
enforce: 'post',
test: '__jest__/src/app.js',
use: [
/* config.module.rule('bundle').use('app-css-loader') */
{
loader: 'app-css-loader',
options: {
platform: 'android'
}
}
]
},
/* config.module.rule('workers') */
{
test: /\\\\.(mjs|js|ts)$/,
use: [
/* config.module.rule('workers').use('nativescript-worker-loader') */
{
loader: 'nativescript-worker-loader'
}
]
},
/* config.module.rule('ts') */
{
test: [
/\\\\.ts$/
],
use: [
/* config.module.rule('ts').use('ts-loader') */
{
loader: 'ts-loader',
options: {
configFile: '__jest__/node_modules/@nativescript/webpack/dist/stubs/tsconfig.default.json',
context: '__jest__',
transpileOnly: true,
allowTsInNodeModules: true,
compilerOptions: {
sourceMap: true,
declaration: false
},
getCustomTransformers: function () { /* omitted long function */ },
appendTsSuffixTo: [
'\\\\\\\\.vue$'
]
}
}
]
},
/* config.module.rule('js') */
{
test: /\\\\.js$/,
exclude: [
/node_modules/
]
},
/* config.module.rule('xml') */
{
test: /\\\\.xml$/,
use: [
/* config.module.rule('xml').use('xml-namespace-loader') */
{
loader: 'xml-namespace-loader'
}
]
},
/* config.module.rule('css') */
{
test: /\\\\.css$/,
use: [
/* config.module.rule('css').use('apply-css-loader') */
{
loader: 'apply-css-loader'
},
/* config.module.rule('css').use('css2json-loader') */
{
loader: 'css2json-loader'
},
/* config.module.rule('css').use('vue-css-loader') */
{
loader: 'vue-loader/lib/loaders/stylePostLoader.js'
},
/* config.module.rule('css').use('postcss-loader') */
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
[
'postcss-import',
{
resolve: function () { /* omitted long function */ }
}
]
]
}
}
}
]
},
/* config.module.rule('scss') */
{
test: /\\\\.scss$/,
use: [
/* config.module.rule('scss').use('apply-css-loader') */
{
loader: 'apply-css-loader'
},
/* config.module.rule('scss').use('css2json-loader') */
{
loader: 'css2json-loader'
},
/* config.module.rule('scss').use('vue-css-loader') */
{
loader: 'vue-loader/lib/loaders/stylePostLoader.js'
},
/* config.module.rule('scss').use('postcss-loader') */
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
[
'postcss-import',
{
resolve: function () { /* omitted long function */ }
}
]
]
}
}
},
/* config.module.rule('scss').use('sass-loader') */
{
loader: 'sass-loader'
}
]
},
/* config.module.rule('vue') */
{
test: /\\\\.vue$/,
use: [
/* config.module.rule('vue').use('vue-loader') */
{
loader: 'vue-loader',
options: {
compiler: {
compile: function () { /* omitted long function */ },
compileToFunctions: function () { /* omitted long function */ },
parseComponent: function () { /* omitted long function */ },
registerElement: function () { /* omitted long function */ }
}
}
}
]
}
]
},
optimization: {
runtimeChunk: 'single',
splitChunks: {
cacheGroups: {
defaultVendor: {
test: /[\\\\\\\\/]node_modules[\\\\\\\\/]/,
priority: -10,
name: 'vendor',
chunks: 'all'
}
}
},
minimizer: [
/* config.optimization.minimizer('TerserPlugin') */
new TerserPlugin(
{
terserOptions: {
compress: {
collapse_vars: false,
sequences: false,
keep_infinity: true,
drop_console: false,
global_defs: {
__UGLIFIED__: true
}
},
keep_fnames: true,
keep_classnames: true
}
}
)
]
},
plugins: [
/* config.plugin('VueLoaderPlugin') */
new VueLoaderPlugin(),
/* config.plugin('ForkTsCheckerWebpackPlugin') */
new ForkTsCheckerWebpackPlugin(
{
async: false,
typescript: {
configFile: '__jest__/node_modules/@nativescript/webpack/dist/stubs/tsconfig.default.json',
context: '__jest__',
memoryLimit: 4096,
extensions: {
vue: {
enabled: true,
compiler: 'nativescript-vue-template-compiler'
}
}
}
}
),
/* config.plugin('PlatformSuffixPlugin') */
new PlatformSuffixPlugin(
{
platform: 'android'
}
),
/* config.plugin('ContextExclusionPlugin|App_Resources') */
new ContextExclusionPlugin(
/(.*)App_Resources(.*)/
),
/* config.plugin('ContextExclusionPlugin|Other_Platforms') */
new ContextExclusionPlugin(
/\\\\.(ios)\\\\.(\\\\w+)$/
),
/* config.plugin('DefinePlugin') */
new DefinePlugin(
{
__DEV__: true,
__NS_WEBPACK__: true,
__NS_ENV_VERBOSE__: false,
__NS_DEV_HOST_IPS__: '[\\"127.0.0.1\\",\\"192.168.0.10\\"]',
__CSS_PARSER__: '\\"css-tree\\"',
__UI_USE_XML_PARSER__: true,
__UI_USE_EXTERNAL_RENDERER__: false,
__ANDROID__: true,
__IOS__: false,
'global.isAndroid': true,
'global.isIOS': false,
process: 'global.process'
}
),
/* config.plugin('CopyWebpackPlugin') */
new CopyPlugin(
{
patterns: [
{
from: 'assets/**',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false,
ignore: []
}
},
{
from: 'fonts/**',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false,
ignore: []
}
},
{
from: '**/*.+(jpg|png)',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false,
ignore: []
}
}
]
}
),
/* config.plugin('WatchStatePlugin') */
new WatchStatePlugin()
],
entry: {
bundle: [
'@nativescript/core/globals/index',
'@nativescript/core/bundle-entry-points',
'__jest__/src/app.js',
'@nativescript/core/ui/frame',
'@nativescript/core/ui/frame/activity'
]
}
}"
`;
exports[`vue configuration for ios 1`] = `
"{
mode: 'development',
externals: [
'package.json',
'~/package.json'
],
externalsPresets: {
node: false
},
devtool: 'inline-source-map',
target: 'node',
watchOptions: {
ignored: [
'__jest__/platforms/**',
'__jest__/App_Resources/**'
]
},
ignoreWarnings: [
/System.import\\\\(\\\\) is deprecated/
],
output: {
path: '__jest__/platforms/ios/jest/app',
pathinfo: false,
publicPath: '',
libraryTarget: 'commonjs',
globalObject: 'global',
clean: true
},
resolve: {
symlinks: true,
alias: {
'~': '__jest__/src',
'@': '__jest__/src',
vue: 'nativescript-vue'
},
extensions: [
'.ios.vue',
'.vue',
'.ios.ts',
'.ts',
'.ios.js',
'.js',
'.ios.mjs',
'.mjs',
'.ios.css',
'.css',
'.ios.scss',
'.scss',
'.ios.json',
'.json'
],
modules: [
'__jest__/node_modules',
'node_modules'
]
},
resolveLoader: {
modules: [
'__jest__/node_modules/@nativescript/webpack/dist/loaders',
'__jest__/node_modules',
'node_modules'
]
},
module: {
rules: [
/* config.module.rule('bundle') */
{
enforce: 'post',
test: '__jest__/src/app.js',
use: [
/* config.module.rule('bundle').use('app-css-loader') */
{
loader: 'app-css-loader',
options: {
platform: 'ios'
}
}
]
},
/* config.module.rule('workers') */
{
test: /\\\\.(mjs|js|ts)$/,
use: [
/* config.module.rule('workers').use('nativescript-worker-loader') */
{
loader: 'nativescript-worker-loader'
}
]
},
/* config.module.rule('ts') */
{
test: [
/\\\\.ts$/
],
use: [
/* config.module.rule('ts').use('ts-loader') */
{
loader: 'ts-loader',
options: {
configFile: '__jest__/node_modules/@nativescript/webpack/dist/stubs/tsconfig.default.json',
context: '__jest__',
transpileOnly: true,
allowTsInNodeModules: true,
compilerOptions: {
sourceMap: true,
declaration: false
},
getCustomTransformers: function () { /* omitted long function */ },
appendTsSuffixTo: [
'\\\\\\\\.vue$'
]
}
}
]
},
/* config.module.rule('js') */
{
test: /\\\\.js$/,
exclude: [
/node_modules/
]
},
/* config.module.rule('xml') */
{
test: /\\\\.xml$/,
use: [
/* config.module.rule('xml').use('xml-namespace-loader') */
{
loader: 'xml-namespace-loader'
}
]
},
/* config.module.rule('css') */
{
test: /\\\\.css$/,
use: [
/* config.module.rule('css').use('apply-css-loader') */
{
loader: 'apply-css-loader'
},
/* config.module.rule('css').use('css2json-loader') */
{
loader: 'css2json-loader'
},
/* config.module.rule('css').use('vue-css-loader') */
{
loader: 'vue-loader/lib/loaders/stylePostLoader.js'
},
/* config.module.rule('css').use('postcss-loader') */
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
[
'postcss-import',
{
resolve: function () { /* omitted long function */ }
}
]
]
}
}
}
]
},
/* config.module.rule('scss') */
{
test: /\\\\.scss$/,
use: [
/* config.module.rule('scss').use('apply-css-loader') */
{
loader: 'apply-css-loader'
},
/* config.module.rule('scss').use('css2json-loader') */
{
loader: 'css2json-loader'
},
/* config.module.rule('scss').use('vue-css-loader') */
{
loader: 'vue-loader/lib/loaders/stylePostLoader.js'
},
/* config.module.rule('scss').use('postcss-loader') */
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
[
'postcss-import',
{
resolve: function () { /* omitted long function */ }
}
]
]
}
}
},
/* config.module.rule('scss').use('sass-loader') */
{
loader: 'sass-loader'
}
]
},
/* config.module.rule('vue') */
{
test: /\\\\.vue$/,
use: [
/* config.module.rule('vue').use('vue-loader') */
{
loader: 'vue-loader',
options: {
compiler: {
compile: function () { /* omitted long function */ },
compileToFunctions: function () { /* omitted long function */ },
parseComponent: function () { /* omitted long function */ },
registerElement: function () { /* omitted long function */ }
}
}
}
]
}
]
},
optimization: {
runtimeChunk: 'single',
splitChunks: {
cacheGroups: {
defaultVendor: {
test: /[\\\\\\\\/]node_modules[\\\\\\\\/]/,
priority: -10,
name: 'vendor',
chunks: 'all'
}
}
},
minimizer: [
/* config.optimization.minimizer('TerserPlugin') */
new TerserPlugin(
{
terserOptions: {
compress: {
collapse_vars: true,
sequences: true,
keep_infinity: true,
drop_console: false,
global_defs: {
__UGLIFIED__: true
}
},
keep_fnames: true,
keep_classnames: true
}
}
)
]
},
plugins: [
/* config.plugin('VueLoaderPlugin') */
new VueLoaderPlugin(),
/* config.plugin('ForkTsCheckerWebpackPlugin') */
new ForkTsCheckerWebpackPlugin(
{
async: false,
typescript: {
configFile: '__jest__/node_modules/@nativescript/webpack/dist/stubs/tsconfig.default.json',
context: '__jest__',
memoryLimit: 4096,
extensions: {
vue: {
enabled: true,
compiler: 'nativescript-vue-template-compiler'
}
}
}
}
),
/* config.plugin('PlatformSuffixPlugin') */
new PlatformSuffixPlugin(
{
platform: 'ios'
}
),
/* config.plugin('ContextExclusionPlugin|App_Resources') */
new ContextExclusionPlugin(
/(.*)App_Resources(.*)/
),
/* config.plugin('ContextExclusionPlugin|Other_Platforms') */
new ContextExclusionPlugin(
/\\\\.(android)\\\\.(\\\\w+)$/
),
/* config.plugin('DefinePlugin') */
new DefinePlugin(
{
__DEV__: true,
__NS_WEBPACK__: true,
__NS_ENV_VERBOSE__: false,
__NS_DEV_HOST_IPS__: '[\\"127.0.0.1\\",\\"192.168.0.10\\"]',
__CSS_PARSER__: '\\"css-tree\\"',
__UI_USE_XML_PARSER__: true,
__UI_USE_EXTERNAL_RENDERER__: false,
__ANDROID__: false,
__IOS__: true,
'global.isAndroid': false,
'global.isIOS': true,
process: 'global.process'
}
),
/* config.plugin('CopyWebpackPlugin') */
new CopyPlugin(
{
patterns: [
{
from: 'assets/**',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false,
ignore: []
}
},
{
from: 'fonts/**',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false,
ignore: []
}
},
{
from: '**/*.+(jpg|png)',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false,
ignore: []
}
}
]
}
),
/* config.plugin('WatchStatePlugin') */
new WatchStatePlugin()
],
entry: {
bundle: [
'@nativescript/core/globals/index',
'@nativescript/core/bundle-entry-points',
'__jest__/src/app.js'
],
'tns_modules/inspector_modules': [
'@nativescript/core/inspector_modules'
]
}
}"
`;
exports[`vue configuration with typescript for android 1`] = `
"{ "{
mode: 'development', mode: 'development',
externals: [ externals: [
@ -354,7 +1071,7 @@ exports[`vue configuration for android 1`] = `
}" }"
`; `;
exports[`vue configuration for ios 1`] = ` exports[`vue configuration with typescript for ios 1`] = `
"{ "{
mode: 'development', mode: 'development',
externals: [ externals: [

View File

@ -1,5 +1,12 @@
import Config from 'webpack-chain'; import Config from 'webpack-chain';
import {
addMockFile,
mockExistsSync,
restoreExistsSync,
setHasTSConfig,
} from '../../scripts/jest.utils';
import { default as angular } from '../../src/configuration/angular'; import { default as angular } from '../../src/configuration/angular';
import { init } from '../../src'; import { init } from '../../src';
@ -22,29 +29,14 @@ jest.mock(
describe('angular configuration', () => { describe('angular configuration', () => {
const platforms = ['ios', 'android']; const platforms = ['ios', 'android'];
let fsExistsSyncSpy: jest.SpiedFunction<any>;
let polyfillsPath: string | boolean = false;
beforeAll(() => { beforeAll(() => {
const fs = require('fs'); mockExistsSync();
const original = fs.existsSync; setHasTSConfig(true);
fsExistsSyncSpy = jest.spyOn(fs, 'existsSync');
fsExistsSyncSpy.mockImplementation((path) => {
if (path === '__jest__/tsconfig.json') {
return true;
}
if (polyfillsPath && path === polyfillsPath) {
return true;
}
return original.call(fs, path);
});
}); });
afterAll(() => { afterAll(() => {
fsExistsSyncSpy.mockRestore(); restoreExistsSync();
}); });
for (let platform of platforms) { for (let platform of platforms) {
@ -56,25 +48,27 @@ describe('angular configuration', () => {
}); });
it(`loads polyfills.${platform}.ts into the bundle entry if it exists `, () => { it(`loads polyfills.${platform}.ts into the bundle entry if it exists `, () => {
polyfillsPath = `__jest__/src/polyfills.${platform}.ts`; const cleanupMockFile = addMockFile(
`__jest__/src/polyfills.${platform}.ts`
);
init({ init({
[platform]: true, [platform]: true,
}); });
expect(angular(new Config()).entry('bundle').values()).toMatchSnapshot(); expect(angular(new Config()).entry('bundle').values()).toMatchSnapshot();
polyfillsPath = false; cleanupMockFile();
}); });
} }
it(`loads polyfills.ts into the bundle entry if it exists `, () => { it(`loads polyfills.ts into the bundle entry if it exists `, () => {
polyfillsPath = `__jest__/src/polyfills.ts`; const cleanupMockFile = addMockFile(`__jest__/src/polyfills.ts`);
init({ init({
ios: true, ios: true,
}); });
expect(angular(new Config()).entry('bundle').values()).toMatchSnapshot(); expect(angular(new Config()).entry('bundle').values()).toMatchSnapshot();
polyfillsPath = false; cleanupMockFile();
}); });
}); });

View File

@ -1,6 +1,13 @@
import Config from 'webpack-chain'; import Config from 'webpack-chain';
import fs from 'fs'; import fs from 'fs';
import {
mockExistsSync,
restoreExistsSync,
addMockFile,
fsExistsSyncSpy,
} from '../../scripts/jest.utils';
import base from '../../src/configuration/base'; import base from '../../src/configuration/base';
import { init } from '../../src'; import { init } from '../../src';
import { applyFileReplacements } from '../../src/helpers/fileReplacements'; import { applyFileReplacements } from '../../src/helpers/fileReplacements';
@ -9,6 +16,18 @@ import { additionalCopyRules } from '../../src/helpers/copyRules';
describe('base configuration', () => { describe('base configuration', () => {
const platforms = ['ios', 'android']; const platforms = ['ios', 'android'];
beforeAll(() => {
mockExistsSync();
});
beforeEach(() => {
fsExistsSyncSpy.mockClear();
});
afterAll(() => {
restoreExistsSync();
});
for (let platform of platforms) { for (let platform of platforms) {
it(`for ${platform}`, () => { it(`for ${platform}`, () => {
init({ init({
@ -31,8 +50,7 @@ describe('base configuration', () => {
}); });
it('supports dotenv', () => { it('supports dotenv', () => {
const fsSpy = jest.spyOn(fs, 'existsSync'); const cleanupMockFile = addMockFile('__jest__/.env');
fsSpy.mockReturnValue(true);
init({ init({
ios: true, ios: true,
@ -45,12 +63,11 @@ describe('base configuration', () => {
return args; return args;
}); });
fsSpy.mockRestore(); cleanupMockFile();
}); });
it('supports env specific dotenv', () => { it('supports env specific dotenv', () => {
const fsSpy = jest.spyOn(fs, 'existsSync'); const cleanupMockFile = addMockFile('__jest__/.env.prod');
fsSpy.mockReturnValue(true);
init({ init({
ios: true, ios: true,
@ -58,19 +75,18 @@ describe('base configuration', () => {
}); });
const config = base(new Config()); const config = base(new Config());
expect(fsSpy).toHaveBeenCalledWith('__jest__/.env.prod'); expect(fsExistsSyncSpy).toHaveBeenCalledWith('__jest__/.env.prod');
expect(fsSpy).toHaveBeenCalledTimes(1);
expect(config.plugin('DotEnvPlugin')).toBeDefined(); expect(config.plugin('DotEnvPlugin')).toBeDefined();
config.plugin('DotEnvPlugin').tap((args) => { config.plugin('DotEnvPlugin').tap((args) => {
expect(args[0].path).toEqual('__jest__/.env.prod'); expect(args[0].path).toEqual('__jest__/.env.prod');
return args; return args;
}); });
fsSpy.mockRestore();
cleanupMockFile();
}); });
it('falls back to default .env', () => { it('falls back to default .env', () => {
const fsSpy = jest.spyOn(fs, 'existsSync'); const cleanupMockFile = addMockFile('__jest__/.env');
fsSpy.mockReturnValueOnce(false).mockReturnValueOnce(true);
init({ init({
ios: true, ios: true,
@ -78,15 +94,16 @@ describe('base configuration', () => {
}); });
const config = base(new Config()); const config = base(new Config());
expect(fsSpy).toHaveBeenCalledWith('__jest__/.env.prod'); expect(fsExistsSyncSpy).toHaveBeenCalledWith('__jest__/.env.prod');
expect(fsSpy).toHaveBeenCalledWith('__jest__/.env'); expect(fsExistsSyncSpy).toHaveBeenCalledWith('__jest__/.env');
expect(fsSpy).toHaveBeenCalledTimes(2);
expect(config.plugin('DotEnvPlugin')).toBeDefined(); expect(config.plugin('DotEnvPlugin')).toBeDefined();
config.plugin('DotEnvPlugin').tap((args) => { config.plugin('DotEnvPlugin').tap((args) => {
expect(args[0].path).toEqual('__jest__/.env'); expect(args[0].path).toEqual('__jest__/.env');
return args; return args;
}); });
fsSpy.mockRestore();
cleanupMockFile();
}); });
it('applies file replacements', () => { it('applies file replacements', () => {

View File

@ -1,11 +1,26 @@
import Config from 'webpack-chain'; import Config from 'webpack-chain';
import {
mockExistsSync,
restoreExistsSync,
setHasTSConfig,
} from '../../scripts/jest.utils';
import react from '../../src/configuration/react'; import react from '../../src/configuration/react';
import { init } from '../../src'; import { init } from '../../src';
describe('react configuration', () => { describe('react configuration', () => {
const platforms = ['ios', 'android']; const platforms = ['ios', 'android'];
beforeAll(() => {
mockExistsSync();
setHasTSConfig(true);
});
afterAll(() => {
restoreExistsSync();
});
for (let platform of platforms) { for (let platform of platforms) {
describe(`> ${platform} >`, () => { describe(`> ${platform} >`, () => {
it(`base config`, () => { it(`base config`, () => {

View File

@ -1,5 +1,11 @@
import Config from 'webpack-chain'; import Config from 'webpack-chain';
import {
mockExistsSync,
restoreExistsSync,
setHasTSConfig,
} from '../../scripts/jest.utils';
import svelte from '../../src/configuration/svelte'; import svelte from '../../src/configuration/svelte';
import { init } from '../../src'; import { init } from '../../src';
@ -8,6 +14,15 @@ jest.mock('__jest__/svelte.config.js', () => {}, { virtual: true });
describe('svelte configuration', () => { describe('svelte configuration', () => {
const platforms = ['ios', 'android']; const platforms = ['ios', 'android'];
beforeAll(() => {
mockExistsSync();
setHasTSConfig(true);
});
afterAll(() => {
restoreExistsSync();
});
for (let platform of platforms) { for (let platform of platforms) {
it(`for ${platform}`, () => { it(`for ${platform}`, () => {
init({ init({

View File

@ -1,11 +1,26 @@
import Config from 'webpack-chain'; import Config from 'webpack-chain';
import {
mockExistsSync,
restoreExistsSync,
setHasTSConfig,
} from '../../scripts/jest.utils';
import typescript from '../../src/configuration/typescript'; import typescript from '../../src/configuration/typescript';
import { init } from '../../src'; import { init } from '../../src';
describe('typescript configuration', () => { describe('typescript configuration', () => {
const platforms = ['ios', 'android']; const platforms = ['ios', 'android'];
beforeAll(() => {
mockExistsSync();
setHasTSConfig(true);
});
afterAll(() => {
restoreExistsSync();
});
for (let platform of platforms) { for (let platform of platforms) {
it(`for ${platform}`, () => { it(`for ${platform}`, () => {
init({ init({

View File

@ -1,11 +1,25 @@
import Config from 'webpack-chain'; import Config from 'webpack-chain';
import {
mockExistsSync,
restoreExistsSync,
setHasTSConfig,
} from '../../scripts/jest.utils';
import vue from '../../src/configuration/vue'; import vue from '../../src/configuration/vue';
import { init } from '../../src'; import { init } from '../../src';
describe('vue configuration', () => { describe('vue configuration', () => {
const platforms = ['ios', 'android']; const platforms = ['ios', 'android'];
beforeAll(() => {
mockExistsSync();
});
afterAll(() => {
restoreExistsSync();
});
for (let platform of platforms) { for (let platform of platforms) {
it(`for ${platform}`, () => { it(`for ${platform}`, () => {
init({ init({
@ -14,4 +28,23 @@ describe('vue configuration', () => {
expect(vue(new Config()).toString()).toMatchSnapshot(); expect(vue(new Config()).toString()).toMatchSnapshot();
}); });
} }
describe('with typescript', () => {
beforeAll(() => {
setHasTSConfig(true);
});
afterAll(() => {
setHasTSConfig(false);
});
for (let platform of platforms) {
it(`for ${platform}`, () => {
init({
[platform]: true,
});
expect(vue(new Config()).toString()).toMatchSnapshot();
});
}
});
}); });

View File

@ -0,0 +1,41 @@
let mockedPaths = new Set([]);
export let fsExistsSyncSpy: jest.SpiedFunction<any>;
export function mockExistsSync() {
const fs = require('fs');
const original = fs.existsSync;
fsExistsSyncSpy = jest.spyOn(fs, 'existsSync');
fsExistsSyncSpy.mockImplementation((path) => {
if (mockedPaths.has(path)) {
return true;
}
return original.call(fs, path);
});
}
export function restoreExistsSync() {
if (fsExistsSyncSpy) {
fsExistsSyncSpy.mockRestore();
}
}
export function setHasTSConfig(value: boolean = true) {
if (value) {
mockedPaths.add('__jest__/tsconfig.json');
return;
}
mockedPaths.delete('__jest__/tsconfig.json');
}
export function addMockFile(path: string) {
mockedPaths.add(path);
return () => {
mockedPaths.delete(path);
};
}

View File

@ -15,7 +15,7 @@ import { PlatformSuffixPlugin } from '../plugins/PlatformSuffixPlugin';
import { applyFileReplacements } from '../helpers/fileReplacements'; import { applyFileReplacements } from '../helpers/fileReplacements';
import { addCopyRule, applyCopyRules } from '../helpers/copyRules'; import { addCopyRule, applyCopyRules } from '../helpers/copyRules';
import { WatchStatePlugin } from '../plugins/WatchStatePlugin'; import { WatchStatePlugin } from '../plugins/WatchStatePlugin';
import { getProjectFilePath } from '../helpers/project'; import { getProjectFilePath, getProjectRootPath } from '../helpers/project';
import { hasDependency } from '../helpers/dependencies'; import { hasDependency } from '../helpers/dependencies';
import { applyDotEnvPlugin } from '../helpers/dotEnv'; import { applyDotEnvPlugin } from '../helpers/dotEnv';
import { env as _env, IWebpackEnv } from '../index'; import { env as _env, IWebpackEnv } from '../index';
@ -229,6 +229,16 @@ export default function (config: Config, env: IWebpackEnv = _env): Config {
.use('nativescript-worker-loader') .use('nativescript-worker-loader')
.loader('nativescript-worker-loader'); .loader('nativescript-worker-loader');
const hasTSConfig = existsSync(getProjectFilePath('tsconfig.json'));
let tsDefaultOptions = {};
if (!hasTSConfig) {
tsDefaultOptions = {
configFile: resolve(__dirname, '../stubs/tsconfig.default.json'),
context: getProjectRootPath(),
};
}
// set up ts support // set up ts support
config.module config.module
.rule('ts') .rule('ts')
@ -236,9 +246,7 @@ export default function (config: Config, env: IWebpackEnv = _env): Config {
.use('ts-loader') .use('ts-loader')
.loader('ts-loader') .loader('ts-loader')
.options({ .options({
// todo: perhaps we can provide a default tsconfig ...tsDefaultOptions,
// and use that if the project doesn't have one?
// configFile: '',
transpileOnly: true, transpileOnly: true,
allowTsInNodeModules: true, allowTsInNodeModules: true,
compilerOptions: { compilerOptions: {
@ -260,6 +268,7 @@ export default function (config: Config, env: IWebpackEnv = _env): Config {
{ {
async: !!env.watch, async: !!env.watch,
typescript: { typescript: {
...tsDefaultOptions,
memoryLimit: 4096, memoryLimit: 4096,
}, },
}, },

View File

@ -62,7 +62,7 @@ export default function (config: Config, env: IWebpackEnv = _env): Config {
}); });
}); });
config.when(hasDependency('typescript'), (config) => { config.when(config.plugins.has('ForkTsCheckerWebpackPlugin'), (config) => {
config.plugin('ForkTsCheckerWebpackPlugin').tap((args) => { config.plugin('ForkTsCheckerWebpackPlugin').tap((args) => {
args[0] = merge(args[0], { args[0] = merge(args[0], {
typescript: { typescript: {

View File

@ -8,5 +8,3 @@ module.exports = (env) => {
return webpack.resolveConfig(); return webpack.resolveConfig();
}; };

View File

@ -0,0 +1,20 @@
{
"compilerOptions": {
"module": "esnext",
"target": "es2017",
"moduleResolution": "node",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"noEmitHelpers": true,
"noEmitOnError": true,
"skipLibCheck": true,
"lib": ["es2017", "dom"],
"baseUrl": ".",
"paths": {
"~/*": ["app/*"],
"@/*": ["app/*"]
}
},
"include": ["./**/*"],
"exclude": ["node_modules", "platforms"]
}