Typescript, Karma ve Webpack'i tarayıcıda test çalıştıracak şekilde nasıl yapılandırılır
Phaser3 ile bir oyun geliştiriyorum ve oyunumun bazı bileşenleri için testler eklemek istediğime karar verdim.
Ana araçlarım olarak Typescript 3.3 ve webpack 4 kullanıyorum. Bazı testlerin Phaser oyun kütüphanesine bağlı olabileceği tarayıcıda testleri çalıştırmak istiyorum. Daha önce Angular.js uygulamalarını test etmek için Karma+Jasmine kullanmıştım, bu yüzden bunu kullanmaya karar verdim.
Biraz kurulumdan sonra testleri çalıştırmayı başardım ama nedense test dosyaları diğer modülleri içe aktaramaz, bunun yerine hata veriyor
Compiled with warnings.
ℹ 「wdm」: Compiling...
✖ 「wdm」:
ERROR in ./src/test/core/EntityFactory.spec.ts
Module not found: Error: Can't resolve './foo' in '<path to the project>/src/test/core'
@ ./src/test/core/EntityFactory.spec.ts 1:0-26
ℹ 「wdm」: Failed to compile.
Module not found: Error: Can't resolve './foo' in '/<path to the project>/src/test/core'
Bahsedilen /test/core dizini, EntityFactory.spec.ts ve foo.ts dosyalarını içeriyor. İçe aktarma, test paketi içinde şöyle yazılmıştır:
import thing from './foo';
Aşağıda benim karma yapılandırma dosyam ve kullandığı webpack yapılandırması bulunmaktadır:
// Karma configuration
// Generated on Sun Mar 17 2019 17:03:14 GMT+0200 (EET)
const webpackConfig = require('./webpack.config').test;
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'**/*.spec.ts'
// each file acts as entry point for the webpack configuration
],
mime: {
"text/x-typescript": ["ts", "tsx"],
},
// list of files / patterns to exclude
exclude: [
// '**/*.spec.ts'
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
// add webpack as preprocessor
'**/*.spec.ts': [ 'webpack' ],
},
webpack: webpackConfig,
webpackMiddleware: {
// webpack-dev-middleware configuration
// i. e.
stats: 'errors-only'
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity
})
}
Ve Webpack yapılandırması:
const baseConfig = {
entry: './src/index.ts',
mode: 'development',
output: {
path: path.resolve(__dirname, 'build'),
publicPath: '/',
chunkFilename: '[name].js',
filename: '[name].js'
},
resolve: {
extensions: ['.ts', '.tsx', '.js']
},
// Source maps support ('inline-source-map' also works)
devtool: 'source-map',
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader'
},
{
test: /\.js$/,
use: ['source-map-loader'],
enforce: 'pre'
}
]
},
optimization: {
runtimeChunk: {
name: 'manifest'
},
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
chunks: 'initial'
}
}
}
},
plugins: [
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, 'assets'),
to: path.resolve(__dirname, 'build', 'assets')
}
]),
new webpack.DefinePlugin({
CANVAS_RENDERER: JSON.stringify(true),
WEBGL_RENDERER: JSON.stringify(true)
}),
new MiniHtmlWebpackPlugin({
context: {
title: 'Phaser game'
},
// FIXME: CSS-loader and default minithmlwebpack template would probably handle this better
template: ({js, title, publicPath } ) =>
`
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>${title}</title>
<style type = "text/css">
body {
padding: 0;
margin: 0;
}
canvas {
display:block;
margin: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
</head>
<body>
${generateJSReferences(js, publicPath)}
</body>
</html>
`
})
]
};
function getTestConfig() {
const config = _.cloneDeep(baseConfig);
delete config.entry;
return config;
}
getTestConfig() fonksiyonu baseConfig’i biraz değiştirir ve sonucu Karma konfigürasyonuna aktarır.
Son olarak, orada yardımcı olabilecek bir şey olup olmadığını görmek için geliştirme bağımlılıkları:
"devDependencies": {
"@types/jasmine": "^3.3.10",
"browser-sync": "^2.26.3",
"browser-sync-webpack-plugin": "^2.2.2",
"copy-webpack-plugin": "^4.6.0",
"jasmine": "^3.3.1",
"karma": "^4.0.1",
"karma-chrome-launcher": "^2.2.0",
"karma-jasmine": "^2.0.1",
"karma-webpack": "^3.0.5",
"mini-html-webpack-plugin": "^0.2.3",
"prettier": "^1.16.4",
"source-map-loader": "^0.2.4",
"ts-loader": "^5.3.3",
"tslint": "^5.12.1",
"tslint-config-prettier": "^1.18.0",
"typescript": "^3.3",
"webpack": "^4.29.3",
"webpack-cli": "^3.2.3",
"webpack-dev-server": "^3.1.14"
},
Peki benim sorum şu, neden testler test edilmesini istediğim modülleri içe aktarabiliyor gibi görünmüyor? Sorun Webpack, Karma mı yoksa Typescript'te mi?
Cevap #1
Bu, Typescript'in dahil etmeye çalıştığınız modülü (foo) derlemediği anlamına geliyor gibi görünüyor. Hatanın tekrarını sağlayan küçük bir test durumu hazırlamak yardımcı olur, ancak test edebilmek istediğiniz tüm kodları içerdiğinden emin olmak için tsconfig.json dosyanızı kontrol etmelisiniz.
Uygulamanın ana giriş noktasını (files: ["src/index.ts"]) ve tüm testleri (include: ["src/**/*.spec.ts"]) kapsayan ayrı bir tsconfig.test.json dosyam var. Bu yolu tercih ederseniz, ortak seçenekler için bir tsconfig.base.json oluşturup, bunu hem üretim tsconfig.json dosyanıza hem de test dosyanıza dahil edebilirsiniz. Ardından Webpack konfigürasyonunuzu doğru dosyayı gösterecek şekilde ayarlamanız gerekir, örneğin
{
test: /\.tsx?$/,
use: {
loader: 'ts-loader',
options: {
configFile: 'tsconfig.test.json',
}
}
},
Varsayılan olarak configFile'ı tsconfig.json olarak ayarlayabilirsiniz, sonra getTestConfig() fonksiyonunuz bunu karma-webpack tarafından kullanılmak üzere değiştirebilir.
