feat: initial angular support + clean up tests

This commit is contained in:
Igor Randjelovic
2020-11-25 17:44:00 +01:00
committed by Nathan Walker
parent e8888719be
commit 523f6bbef2
17 changed files with 651 additions and 48 deletions

View File

@ -0,0 +1,468 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`angular configuration for android 1`] = `
"{
mode: 'development',
externals: [
'package.json',
'~/package.json'
],
devtool: 'inline-source-map',
target: 'node',
output: {
path: '__jest__/platforms/android/app/src/main/assets/app',
pathinfo: false,
publicPath: '',
libraryTarget: 'commonjs',
globalObject: 'global'
},
resolve: {
symlinks: true,
alias: {
'~': '<TODO>appFullPath',
'@': '<TODO>appFullPath'
},
extensions: [
'.android.ts',
'.ts',
'.android.js',
'.js',
'.android.css',
'.css',
'.android.scss',
'.scss',
'.android.json',
'.json'
]
},
resolveLoader: {
modules: [
'node_modules/@nativescript/webpack/dist/loaders',
'node_modules'
]
},
module: {
rules: [
/* config.module.rule('js') */
{
test: /\\\\.js$/,
exclude: [
/node_modules/
],
use: [
/* config.module.rule('js').use('babel-loader') */
{
loader: 'babel-loader',
options: {
generatorOpts: {
compact: false
}
}
}
]
},
/* 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('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('sass-loader') */
{
loader: 'sass-loader'
}
]
},
/* config.module.rule('angular') */
{
test: /(?:\\\\.ngfactory.js|\\\\.ngstyle\\\\.js|\\\\.ts)$/,
use: [
/* config.module.rule('angular').use('@ngtools/webpack') */
{
loader: '@ngtools/webpack'
}
]
},
/* config.module.rule('@angular/core') */
{
test: /[\\\\/\\\\\\\\]@angular[\\\\/\\\\\\\\]core[\\\\/\\\\\\\\].+\\\\.js$/,
parser: {
system: true
}
},
/* config.module.rule('html') */
{
test: /\\\\.html$/,
use: [
/* config.module.rule('html').use('raw-loader') */
{
loader: 'raw-loader'
}
]
}
]
},
optimization: {
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_fnames: true
}
}
)
]
},
plugins: [
/* config.plugin('ForkTsCheckerWebpackPlugin') */
new ForkTsCheckerWebpackPlugin(
{
typescript: {
memoryLimit: 4096
}
}
),
/* config.plugin('CleanWebpackPlugin') */
new CleanWebpackPlugin(
{
cleanOnceBeforeBuildPatterns: [
'__jest__/platforms/android/app/src/main/assets/app/**/*'
],
verbose: false
}
),
/* config.plugin('DefinePlugin') */
new DefinePlugin(
{
__DEV__: true,
__NS_WEBPACK__: true,
__CSS_PARSER__: '\\"css-tree\\"',
__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
}
},
{
from: 'fonts/**',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
}
},
{
from: '**/*.+(jpg|png)',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
}
}
]
}
),
/* config.plugin('WatchStatePlugin') */
new WatchStatePlugin(),
/* config.plugin('AngularCompilerPlugin') */
new AngularCompilerPlugin(
{
tsConfigPath: '__jest__/tsconfig.json',
mainPath: '__jest__/src/app.js',
platformTransformers: [
function () { /* omitted long function */ }
]
}
)
],
entry: {
bundle: [
'@nativescript/core/globals/index.js',
'__jest__/src/app.js'
]
}
}"
`;
exports[`angular configuration for ios 1`] = `
"{
mode: 'development',
externals: [
'package.json',
'~/package.json'
],
devtool: 'inline-source-map',
target: 'node',
output: {
path: '__jest__/platforms/ios/__jest__/app',
pathinfo: false,
publicPath: '',
libraryTarget: 'commonjs',
globalObject: 'global'
},
resolve: {
symlinks: true,
alias: {
'~': '<TODO>appFullPath',
'@': '<TODO>appFullPath'
},
extensions: [
'.ios.ts',
'.ts',
'.ios.js',
'.js',
'.ios.css',
'.css',
'.ios.scss',
'.scss',
'.ios.json',
'.json'
]
},
resolveLoader: {
modules: [
'node_modules/@nativescript/webpack/dist/loaders',
'node_modules'
]
},
module: {
rules: [
/* config.module.rule('js') */
{
test: /\\\\.js$/,
exclude: [
/node_modules/
],
use: [
/* config.module.rule('js').use('babel-loader') */
{
loader: 'babel-loader',
options: {
generatorOpts: {
compact: false
}
}
}
]
},
/* 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('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('sass-loader') */
{
loader: 'sass-loader'
}
]
},
/* config.module.rule('angular') */
{
test: /(?:\\\\.ngfactory.js|\\\\.ngstyle\\\\.js|\\\\.ts)$/,
use: [
/* config.module.rule('angular').use('@ngtools/webpack') */
{
loader: '@ngtools/webpack'
}
]
},
/* config.module.rule('@angular/core') */
{
test: /[\\\\/\\\\\\\\]@angular[\\\\/\\\\\\\\]core[\\\\/\\\\\\\\].+\\\\.js$/,
parser: {
system: true
}
},
/* config.module.rule('html') */
{
test: /\\\\.html$/,
use: [
/* config.module.rule('html').use('raw-loader') */
{
loader: 'raw-loader'
}
]
}
]
},
optimization: {
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_fnames: true
}
}
)
]
},
plugins: [
/* config.plugin('ForkTsCheckerWebpackPlugin') */
new ForkTsCheckerWebpackPlugin(
{
typescript: {
memoryLimit: 4096
}
}
),
/* config.plugin('CleanWebpackPlugin') */
new CleanWebpackPlugin(
{
cleanOnceBeforeBuildPatterns: [
'__jest__/platforms/ios/__jest__/app/**/*'
],
verbose: false
}
),
/* config.plugin('DefinePlugin') */
new DefinePlugin(
{
__DEV__: true,
__NS_WEBPACK__: true,
__CSS_PARSER__: '\\"css-tree\\"',
__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
}
},
{
from: 'fonts/**',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
}
},
{
from: '**/*.+(jpg|png)',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
}
}
]
}
),
/* config.plugin('WatchStatePlugin') */
new WatchStatePlugin(),
/* config.plugin('AngularCompilerPlugin') */
new AngularCompilerPlugin(
{
tsConfigPath: '__jest__/tsconfig.json',
mainPath: '__jest__/src/app.js',
platformTransformers: [
function () { /* omitted long function */ }
]
}
)
],
entry: {
bundle: [
'@nativescript/core/globals/index.js',
'__jest__/src/app.js'
],
'tns_modules/@nativescript/core/inspector_modules': [
'@nativescript/core/inspector_modules'
]
}
}"
`;

View File

@ -196,7 +196,7 @@ exports[`react configuration > android > adds ReactRefreshWebpackPlugin when HMR
patterns: [
{
from: 'assets/**',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -204,7 +204,7 @@ exports[`react configuration > android > adds ReactRefreshWebpackPlugin when HMR
},
{
from: 'fonts/**',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -212,7 +212,7 @@ exports[`react configuration > android > adds ReactRefreshWebpackPlugin when HMR
},
{
from: '**/*.+(jpg|png)',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -238,7 +238,7 @@ exports[`react configuration > android > adds ReactRefreshWebpackPlugin when HMR
entry: {
bundle: [
'@nativescript/core/globals/index.js',
'src/app.js'
'__jest__/src/app.js'
]
}
}"
@ -429,7 +429,7 @@ exports[`react configuration > android > base config 1`] = `
patterns: [
{
from: 'assets/**',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -437,7 +437,7 @@ exports[`react configuration > android > base config 1`] = `
},
{
from: 'fonts/**',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -445,7 +445,7 @@ exports[`react configuration > android > base config 1`] = `
},
{
from: '**/*.+(jpg|png)',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -460,7 +460,7 @@ exports[`react configuration > android > base config 1`] = `
entry: {
bundle: [
'@nativescript/core/globals/index.js',
'src/app.js'
'__jest__/src/app.js'
]
}
}"
@ -662,7 +662,7 @@ exports[`react configuration > ios > adds ReactRefreshWebpackPlugin when HMR ena
patterns: [
{
from: 'assets/**',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -670,7 +670,7 @@ exports[`react configuration > ios > adds ReactRefreshWebpackPlugin when HMR ena
},
{
from: 'fonts/**',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -678,7 +678,7 @@ exports[`react configuration > ios > adds ReactRefreshWebpackPlugin when HMR ena
},
{
from: '**/*.+(jpg|png)',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -704,7 +704,7 @@ exports[`react configuration > ios > adds ReactRefreshWebpackPlugin when HMR ena
entry: {
bundle: [
'@nativescript/core/globals/index.js',
'src/app.js'
'__jest__/src/app.js'
],
'tns_modules/@nativescript/core/inspector_modules': [
'@nativescript/core/inspector_modules'
@ -898,7 +898,7 @@ exports[`react configuration > ios > base config 1`] = `
patterns: [
{
from: 'assets/**',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -906,7 +906,7 @@ exports[`react configuration > ios > base config 1`] = `
},
{
from: 'fonts/**',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -914,7 +914,7 @@ exports[`react configuration > ios > base config 1`] = `
},
{
from: '**/*.+(jpg|png)',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -929,7 +929,7 @@ exports[`react configuration > ios > base config 1`] = `
entry: {
bundle: [
'@nativescript/core/globals/index.js',
'src/app.js'
'__jest__/src/app.js'
],
'tns_modules/@nativescript/core/inspector_modules': [
'@nativescript/core/inspector_modules'

View File

@ -209,7 +209,7 @@ exports[`svelte configuration for android 1`] = `
patterns: [
{
from: 'assets/**',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -217,7 +217,7 @@ exports[`svelte configuration for android 1`] = `
},
{
from: 'fonts/**',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -225,7 +225,7 @@ exports[`svelte configuration for android 1`] = `
},
{
from: '**/*.+(jpg|png)',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -240,7 +240,7 @@ exports[`svelte configuration for android 1`] = `
entry: {
bundle: [
'@nativescript/core/globals/index.js',
'src/app.js'
'__jest__/src/app.js'
]
}
}"
@ -455,7 +455,7 @@ exports[`svelte configuration for ios 1`] = `
patterns: [
{
from: 'assets/**',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -463,7 +463,7 @@ exports[`svelte configuration for ios 1`] = `
},
{
from: 'fonts/**',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -471,7 +471,7 @@ exports[`svelte configuration for ios 1`] = `
},
{
from: '**/*.+(jpg|png)',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -486,7 +486,7 @@ exports[`svelte configuration for ios 1`] = `
entry: {
bundle: [
'@nativescript/core/globals/index.js',
'src/app.js'
'__jest__/src/app.js'
],
'tns_modules/@nativescript/core/inspector_modules': [
'@nativescript/core/inspector_modules'

View File

@ -211,7 +211,7 @@ exports[`vue configuration for android 1`] = `
patterns: [
{
from: 'assets/**',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -219,7 +219,7 @@ exports[`vue configuration for android 1`] = `
},
{
from: 'fonts/**',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -227,7 +227,7 @@ exports[`vue configuration for android 1`] = `
},
{
from: '**/*.+(jpg|png)',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -242,7 +242,7 @@ exports[`vue configuration for android 1`] = `
entry: {
bundle: [
'@nativescript/core/globals/index.js',
'src/app.js'
'__jest__/src/app.js'
]
}
}"
@ -459,7 +459,7 @@ exports[`vue configuration for ios 1`] = `
patterns: [
{
from: 'assets/**',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -467,7 +467,7 @@ exports[`vue configuration for ios 1`] = `
},
{
from: 'fonts/**',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -475,7 +475,7 @@ exports[`vue configuration for ios 1`] = `
},
{
from: '**/*.+(jpg|png)',
context: 'src',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false
@ -490,7 +490,7 @@ exports[`vue configuration for ios 1`] = `
entry: {
bundle: [
'@nativescript/core/globals/index.js',
'src/app.js'
'__jest__/src/app.js'
],
'tns_modules/@nativescript/core/inspector_modules': [
'@nativescript/core/inspector_modules'

View File

@ -0,0 +1,28 @@
import Config from 'webpack-chain';
import angular from '../../src/configuration/angular';
import { init } from '../../src';
jest.mock(
'@ngtools/webpack',
() => {
class AngularCompilerPlugin {}
return {
AngularCompilerPlugin,
};
},
{ virtual: true }
);
describe.only('angular configuration', () => {
const platforms = ['ios', 'android'];
for (let platform of platforms) {
it(`for ${platform}`, () => {
init({
[platform]: true,
});
expect(angular(new Config()).toString()).toMatchSnapshot();
});
}
});

View File

@ -1,4 +1,3 @@
// @ts-ignore
import Config from 'webpack-chain';
import react from '../../src/configuration/react';
import { init } from '../../src';

View File

@ -1,8 +1,11 @@
// @ts-ignore
import Config from 'webpack-chain';
import svelte from '../../src/configuration/svelte';
import { init } from '../../src';
mockFile('./svelte.config.js', '');
// jest.mock('__jest__/svelte.config.js', () => {
// }, { virtual: true })
describe.only('svelte configuration', () => {
const platforms = ['ios', 'android'];

View File

@ -1,4 +1,3 @@
// @ts-ignore
import Config from 'webpack-chain';
import vue from '../../src/configuration/vue';
import { init } from '../../src';

View File

@ -6,5 +6,10 @@ module.exports = {
},
setupFiles: [
'<rootDir>/jest.setup.ts'
]
],
globals: {
'ts-jest': {
tsconfig: 'tsconfig.jest.json'
}
}
};

View File

@ -1,5 +1,15 @@
// define our global helpers
declare global {
function mockFile(path: string, content: string);
}
// enable TEST mode
global.__TEST__ = true;
// we are mocking the cwd for the tests, since webpack needs absolute paths
// and we don't want them in tests
import dedent from 'ts-dedent';
process.cwd = () => '__jest__';
// a virtual mock for package.json
@ -22,10 +32,51 @@ jest.mock('cosmiconfig', () => ({
},
}));
jest.mock('path', () => ({
...jest.requireActual('path'),
// we are mocking resolve to just simply join the paths for tests
resolve(...args) {
return args.join('/');
},
}));
jest.mock('path', () => {
const path = jest.requireActual('path');
return {
...path,
resolve(...args) {
if (args[0] === '__jest__') {
return path.join(...args);
}
const resolved = path.resolve(...args);
if (resolved.includes('__jest__')) {
const li = resolved.lastIndexOf('__jest__');
return resolved.substr(li);
}
return resolved;
},
};
});
const mockedFiles: { [path: string]: string } = {};
global.mockFile = function mockFile(path, content) {
const unionFS = require('unionfs').default;
const Volume = require('memfs').Volume;
// reset to fs
unionFS.reset();
// add mocked file
mockedFiles[path] = dedent(content);
// create new volume
const vol = Volume.fromJSON(mockedFiles, '__jest__');
// use the new volume
unionFS.use(vol as any);
};
jest.mock('fs', () => {
const fs = jest.requireActual('fs');
const unionFS = require('unionfs').default;
unionFS.reset = () => {
unionFS.fss = [fs];
};
return unionFS.use(fs);
});

View File

@ -28,6 +28,7 @@
"css-loader": "^5.0.1",
"fork-ts-checker-webpack-plugin": "^6.0.3",
"loader-utils": "^2.0.0",
"raw-loader": "^4.0.2",
"react-refresh": "^0.9.0",
"sass": "^1.29.0",
"sass-loader": "^10.1.0",
@ -50,9 +51,11 @@
"@types/loader-utils": "^2.0.1",
"@types/terser-webpack-plugin": "^5.0.2",
"jest": "^26.6.3",
"memfs": "^3.2.0",
"nativescript-vue-template-compiler": "^2.8.2",
"ts-jest": "^26.4.4",
"typescript": "^4.1.2"
"typescript": "^4.1.2",
"unionfs": "^4.4.0"
},
"peerDependencies": {
"nativescript-vue-template-compiler": "^2.8.1"

View File

@ -1,10 +1,48 @@
import Config from 'webpack-chain';
import path from 'path';
import { IWebpackEnv } from '../index';
import { getEntryPath, getProjectRootPath } from '../helpers/project';
import { env as _env, IWebpackEnv } from '../index';
import base from './base';
export default function (config: Config, env: IWebpackEnv): Config {
export default function (config: Config, env: IWebpackEnv = _env): Config {
base(config, env);
const tsConfigPath = path.join(getProjectRootPath(), 'tsconfig.json');
// remove default ts rule
config.module.rules.delete('ts');
config.module
.rule('angular')
.test(/(?:\.ngfactory.js|\.ngstyle\.js|\.ts)$/)
.use('@ngtools/webpack')
.loader('@ngtools/webpack');
config.module
.rule('@angular/core')
.test(/[\/\\]@angular[\/\\]core[\/\\].+\.js$/)
.parser({ system: true });
// set up html
config.module
.rule('html')
.test(/\.html$/)
.use('raw-loader')
.loader('raw-loader');
config.plugin('AngularCompilerPlugin').use(getAngularCompilerPlugin(), [
{
tsConfigPath,
mainPath: getEntryPath(),
platformTransformers: [require('../transformers/NativeClass').default],
},
]);
return config;
}
function getAngularCompilerPlugin() {
const { AngularCompilerPlugin } = require('@ngtools/webpack');
return AngularCompilerPlugin;
}

View File

@ -60,6 +60,8 @@ function getSvelteConfig(): { preprocess: any } | undefined {
});
return require(resolvedPath);
} catch (err) {
// todo: remove when jest supports mocking require.resolve
if (__TEST__) return;
error('Could not find svelte.config.js.', err);
}
}

1
packages/webpack5/src/globals.d.ts vendored Normal file
View File

@ -0,0 +1 @@
declare var __TEST__: boolean;

View File

@ -16,7 +16,7 @@ export function getAbsoluteDistPath() {
export function getEntryPath() {
const packageJson = getPackageJson();
return resolve(packageJson.main);
return resolve(getProjectRootPath(), packageJson.main);
}
export function getDistPath() {

View File

@ -59,8 +59,10 @@ export function useConfig(config: keyof typeof defaultConfigs | false) {
}
export function chainWebpack(
chainFn: (config: Config, env: IWebpackEnv) => any
chainFn: (config: Config, env: IWebpackEnv) => any,
options?: { last?: boolean }
) {
// todo: handle options.last by storing them in a separate array?
webpackChains.push(chainFn);
}

View File

@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"include": ["src", "__tests__", "jest.setup.ts"]
}