I'm having a testsuite which I'm now trying to test via CI. (Bamboo)
The problem is that this is fully functional on my local system, but wen I deploy it to the Bamboo server (which I cannot configure myself) the call npm --harmony test (--harmony to use const while use strict) fails.
Next, it returns the following errormessage
07-Oct-2016 16:37:03 07 10 2016 16:37:03.315:ERROR [preprocessor.rollup]: Could not resolve '../../services/apicaller.service' from /opt/bamboo-home/xml-data/build-dir/MCAE-MANCAVE-JOB1/src/pages/events/events.component.ts
07-Oct-2016 16:37:03 at /opt/bamboo-home/xml-data/build-dir/MCAE-MANCAVE-JOB1/config/karma-shim.ts
07-Oct-2016 16:37:03 Error: Could not resolve '../../services/apicaller.service' from /opt/bamboo-home/xml-data/build-dir/MCAE-MANCAVE-JOB1/src/pages/events/events.component.ts
07-Oct-2016 16:37:03 at Error (native)
07-Oct-2016 16:37:03 at /opt/bamboo-home/xml-data/build-dir/MCAE-MANCAVE-JOB1/node_modules/rollup-plugin-node-resolve/dist/rollup-plugin-node-resolve.cjs.js:78:21
07-Oct-2016 16:37:03 at /opt/bamboo-home/xml-data/build-dir/MCAE-MANCAVE-JOB1/node_modules/browser-resolve/index.js:265:24
07-Oct-2016 16:37:03 at /opt/bamboo-home/xml-data/build-dir/MCAE-MANCAVE-JOB1/node_modules/resolve/lib/async.js:55:18
07-Oct-2016 16:37:03 at load (/opt/bamboo-home/xml-data/build-dir/MCAE-MANCAVE-JOB1/node_modules/resolve/lib/async.js:69:43)
07-Oct-2016 16:37:03 at onex (/opt/bamboo-home/xml-data/build-dir/MCAE-MANCAVE-JOB1/node_modules/resolve/lib/async.js:92:31)
07-Oct-2016 16:37:03 at /opt/bamboo-home/xml-data/build-dir/MCAE-MANCAVE-JOB1/node_modules/resolve/lib/async.js:22:47
where ../../services/apicaller.service is an import statement in src/pages/events/events.component
Project structure (minified to match errormessage's scope)
src
|
--config
| |
| --karma.conf.js
| --karma-shim.ts
| --protractor.conf.js
| --rollup.config.js
|
--pages
| |
| --events
| |
| --events.component.ts
|
--services
|
--APICaller.service.ts
Karma.conf.js:
'use strict';
const path = require('path');
const ts = require('rollup-plugin-typescript');
const buble = require('rollup-plugin-buble');
const nodeResolve = require('rollup-plugin-node-resolve');
const angular = require('rollup-plugin-angular');
const commonjs = require('rollup-plugin-commonjs');
const alias = require('rollup-plugin-alias');
module.exports = function karmaConfig(config) {
var configuration = {
// base path that will be used to resolve all patterns (e.g. files, exclude)
basePath: '../',
frameworks: ['jasmine'],
plugins: [
require('karma-jasmine'),
require('karma-phantomjs-launcher'),
require('karma-rollup-plugin')
],
reporters: [
// // Reference: https://github.com/mlex/karma-spec-reporter
// // Set reporter to print detailed results to console
// 'spec',
// // Reference: https://github.com/karma-runner/karma-coverage
// // Output code coverage files
// 'coverage'
'progress'
],
// list of files / patterns to load in the browser we are building
// the config environment in ./karma-shim.js
files: [
'config/karma-shim.ts'
],
preprocessors: {
'config/karma-shim.ts': ['rollup']
},
rollupPreprocessor: {
context: 'this',
plugins: [
angular({
exclude: 'node_modules/**'
}),
ts({
typescript: require('../node_modules/typescript')
}),
alias({
'#angular/core/testing': path.resolve(__dirname, '../node_modules/#angular/core/testing/index.js'),
'#angular/platform-browser-dynamic/testing': path.resolve(__dirname, '../node_modules/#angular/platform-browser-dynamic/testing/index.js'),
'#angular/compiler/testing': path.resolve(__dirname, '../node_modules/#angular/compiler/testing/index.js'),
'#angular/platform-browser/testing': path.resolve(__dirname, '../node_modules/#angular/platform-browser/testing/index.js')
}),
commonjs(),
nodeResolve({ jsnext: true, main: true, browser: true }),
buble()
]
},
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['PhantomJS'],
// Continuous Integration mode if true, Karma captures browsers, runs the tests and exits
singleRun: true
};
// if(process.env.GITLAB_CI){
// //configuration.browsers = ['Chrome_travis_ci'];
// }
config.set(configuration);
};
Karma-shim.ts
declare var __karma__: any;
__karma__.loaded = () => { };
import 'core-js/client/shim';
import 'reflect-metadata';
import 'zone.js/dist/zone';
import 'zone.js/dist/long-stack-trace-zone';
import 'zone.js/dist/async-test';
import 'zone.js/dist/fake-async-test';
import 'zone.js/dist/sync-test';
import 'zone.js/dist/proxy';
import 'zone.js/dist/jasmine-patch';
import 'rxjs/Rx';
import { TestBed } from '#angular/core/testing';
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '#angular/platform-browser-dynamic/testing';
TestBed.initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
import '../src/pages/home/home.spec';
import '../src/pages/events/events.spec';
import '../src/pages/event-detail/event-detail.spec';
__karma__.start();
rollup.config.js
const rollupConfig = require('../node_modules/#ionic/app-scripts/config/rollup.config');
const replace = require('rollup-plugin-replace');
console.log('Editing default ionic configuration');
const nodeEnv = JSON.stringify(process.env.NODE_ENV) || 'development';
const apiUrl = JSON.stringify(process.env.API_URL) || '';
const platform = JSON.stringify(process.env.PLATFORM) || 'android';
rollupConfig.plugins.push(replace({
'process.env.NODE_ENV': nodeEnv,
'process.env.API_URL': apiUrl,
'process.env.PLATFORM': platform
}));
module.exports = rollupConfig;
I figured that Bamboo is case-sensitive. And since my APICaller doesn't follow the angular's kebab-case, Bamboo couldn't find the path.
Class was APICaller.service.ts and import was {..} from 'apicaller.service. Change to {..} from 'APICaller.service made it work
Related
I am having issues setting up Jest with typescript. I keep getting the same error no matter what settings I change in jest.config.js
Here are my config files
//jest.config.js
module.exports = {
collectCoverage: false,
moduleDirectories: ['node_modules', '<rootDir>/'],
moduleNameMapper: {
'^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy',
'^.+\\.(css|sass|scss)$': '<rootDir>/__mocks__/styleMock.js',
'^.+\\.(png|jpg|jpeg|gif|webp|avif|ico|bmp|svg)$/i': `<rootDir>/__mocks__/fileMock.js`,
// Handle module aliases
// Should also be updated in tsconfig.json
"#lib/*": ["<rootDir>/app/lib/*"]
},
preset: 'ts-jest',
testPathIgnorePatterns: ['<rootDir>/node_modules/', '<rootDir>/.next/'],
testEnvironment: 'node',
transform: {
"^.+\\.tsx?$": "ts-jest"
},
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts']
}
This is my jest.config.ts file
import '#testing-library/jest-dom/extend-expect'
This is my test file:
test("auth test", async () => {
const auth = await authenticate("invaild", "password")
expect(auth).toBe(false);
});
The error is thrown in the authenicate function from import PocketBase from "pocketbase";
This is the error produced:
SyntaxError: Unexpected token 'export'
4 | // This file sets up the connection to the database
5 |
> 6 | import PocketBase from "pocketbase";
| ^
7 |
8 | export function DBConnection(): PocketBase {
9 | if (process.env.DB_PORT === undefined) {
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1598:14)
Getting ReferenceError: You are trying to import a file after the Jest environment has been torn down From office/test/office.test.ts.
Used jest.useFakeTimers(); after imports, but the issue still exists. Is there any way to resolve it ?
Here is my jest.config.ts
import type { Config } from "#jest/types"
const config: Config.InitialOptions = {
transform: {
'^.+\\.tsx?$': 'ts-jest'
},
testRegex: '(/__test__/.*|(\\.|/)(test|spec))\\.[jt]sx?$',
moduleFileExtensions: [ 'js','ts'],
testEnvironment: "jest-environment-node",
fakeTimers: {
enableGlobally: true,
},
verbose: true
}
export default config
The test file office.test.ts
import {ApolloServer} from 'apollo-server'
import {expect,test,jest} from '#jest/globals';
import officeGql from '../controllers/controller'
jest.useFakeTimers();
test('Office Module Test', async () => {
let typeDefs = officeGql.types
let resolvers = officeGql.resolvers
let testServer = new ApolloServer({
typeDefs,
resolvers,
});
const response = await testServer.executeOperation({
query: `query offices(limit: $limit,offset: $offset){name, address}`,
variables: { limit: 10,offset:0 },
});
expect(response.data).toBeTruthy();
});
I am using Pino and Pino pretty packages for displaying loggers. I would like to write all log.info contents (called from multiple js files in the same project) into a common text file
logger.ts
import pinoCaller from 'pino-caller'
import pino from 'pino'
const job_name="job123"
const pinoPretty = pino(
{
prettyPrint: {
messageFormat: `{"job_name":${job_name}, "message":{msg}}`,
},
})
export log=pinoCaller(pinoPretty)
Is there anyway I can write all log.info content from multiple files to a common text file.
lets say I have following files:
file1.ts
import {log} from 'logger'
const calculatesum = (a:any,b:any)=>{
log.info('**********')
log.info('sum begins')
const sum=a+b;
log.info('sum is '+sum)
log.info('sum ends')
}
file2.ts
import {log} from 'logger'
const calculateproduct = (a:any,b:any)=>{
log.info('product begins')
const product=a*b;
log.info('product is '+product)
log.info('product ends')
log.info('**********')
}
output of text file should look like below:
***************
sum begins
sum is x
sum ends
product begins
product is y
product ends
***************
If you're using Pino v7.x or later, you can make use of Pino transports.
const pinoPretty = pino({
prettyPrint: {
messageFormat: `{"job_name":${job_name}, "message":{msg}}`,
},
transport: {
targets: [
{ level: 'info', target: 'pino/file', options: { destination: '/path/to/store/logs', mkdir: true } },
{ target: 'pino-pretty', options: { destination: '/dev/null' }
]
}
})
Alternatively you can use pino-tee. An example of how to do it:
const pino = require('pino')
const pinoTee = pino.transport({
target: 'pino-tee',
options: {
filters: {
info: 'info.log'
}
}
})
I'm trying to write a chrome extension. I've found a way to create multiple
pages and a background script, but the background script contains a hash and is
placed into the dist/assets folder. I would like to output just 'dist/background.js'. Alternatively (and maybe better) I would like to have my manifest updated to contain the actual script name with the hash.
Here's my vite.config.ts
import { defineConfig, BuildOptions } from 'vite'
import vue from '#vitejs/plugin-vue'
const { resolve } = require('path')
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
build: {
// lib: {
// entry: resolve(__dirname, 'background.ts'),
// name: 'background',
// fileName: format => `background.{format}.js`
// },
rollupOptions: {
// output: {
// format: 'cjs'
// },
input: {
main: resolve(__dirname, 'index.html'),
popup: resolve(__dirname, 'popup/index.html'),
options: resolve(__dirname, 'options/index.html'),
background: resolve(__dirname, 'background.ts'),
},
// output: {
// format: 'cjs'
// }
}
}
})
I've tried a few things and some are shown here commented out, but I couldn't get anything to work how I wanted. Finally I was able to get it to work if I create a separate vite.config.background.ts file:
import { defineConfig } from 'vite'
const { resolve } = require('path')
// https://vitejs.dev/config/
export default defineConfig({
build: {
emptyOutDir: false,
rollupOptions: {
input: resolve(__dirname, 'background.ts'),
output: {
format: "esm",
file: "dist/background.js",
dir: null,
}
}
}
})
And edit my build script to build it after the other config:
"build": "vue-tsc --noEmit && vite build && vite build --config vite.config.background.ts",
But is there any way to use just one file, or to generate the manifest and use the hashed
file name? Right now it is a static json file.
This is what I ended up doing which isn't optimal. It's just hard to believe that you can specify multiple inputs which produce multiple outputs, but not define output settings for each... Structure:
+-- dist (output directory)
+-- options (options page)
+-- popup (popup page)
+-- public (contents copied directly to dist
| +-- background.js (generated background script from '/background.ts')
| +-- manifest.json (extension manifest)
+-- scripts (scripts used in build)
| +-- watch.mjs (script for 'yarn watch')
+-- src (main page)
+-- background.ts
So manifest.json is in the public directory which is copied to the root of dist. And the background script build puts the output background.js in that folder too for the main build to copy as part of the 'main' page.
scripts/watch.mjs
import { createServer, build } from 'vite'
/**
* #type {(server: import('vite').ViteDevServer) => Promise<import('rollup').RollupWatcher>}
*/
function watchBackground(server) {
return build({
configFile: 'vite.config.background.ts',
mode: 'development',
build: {
watch: {},
},
})
}
/**
* #type {(server: import('vite').ViteDevServer) => Promise<import('rollup').RollupWatcher>}
*/
function watchMain(server) {
return build({
configFile: 'vite.config.ts',
mode: 'development',
build: {
watch: {},
},
})
}
// bootstrap
const server = await createServer({ configFile: 'vite.config.ts' })
await server.listen()
await watchBackground(server) // outputs to public/background.js, so run first
await watchMain(server)
vite.config.background.ts
import { defineConfig } from 'vite'
const { resolve } = require('path')
// https://vitejs.dev/config/
export default defineConfig({
build: {
emptyOutDir: false,
rollupOptions: {
input: resolve(__dirname, 'background.ts'),
output: {
format: "esm",
file: "public/background.js",
dir: null,
}
}
}
})
vite.config.ts
import { defineConfig, BuildOptions } from 'vite'
import vue from '#vitejs/plugin-vue'
const { resolve } = require('path')
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
popup: resolve(__dirname, 'popup/index.html'),
options: resolve(__dirname, 'options/index.html'),
},
}
}
})
Running multiple rollup builds with one vite build command is not supported but you can generate a manifest file directly from vite. To generate it simply set build.manifest to true (but I am not sure if this will contain everything that you need for a manifest file for a web plugin though).
For some reason most page refreshes re-request the bundle.js file and it takes about 10-15-20 seconds to download from localhost. This all from localhost, and the bundle.js file is about 1mb in size. The request for this file only seems to crawl, loading a few kilobytes at a time.
Some observations:
After some digging it seems to be stalling out on the initial call to the server from __webpack_hmr, but I'm not sure as this call happens after the call to bundle.js. Below is the log of the server request flow.
It is only slow on pages that have more than one or two components, ie. anything other than the homepage. This alludes to the idea that it might be related to the hot module reloading.
The homepage will still take > 5s (sometimes 10-20) just like the other pages, but if I refresh the page with Ctrl+R, it comes back nearly instantly. If I do an address-bar refresh, it takes longer. The other pages still take just as long no matter if I Ctrl+R or do an address-bar reload...
Update: I removed the hot module replacement, and it definitely seems to be the source of the issue, as the pages load instantly without it.
Request log:
-- Response time GET / = 609ms
--> GET / 200 647ms 2.55kb
<-- GET /main.aafc9fb7f6a0c7f127edb04734d29547.css
--> GET /main.aafc9fb7f6a0c7f127edb04734d29547.css 200 17ms 3.43kb
<-- /bundle.js
--> GET /bundle.js 200 18ms 1.29mb
<-- GET /__webpack_hmr
And then in the chrome console, for this request it shows:
Here's my setup:
Using Koa as the server environment (using streaming/chunking in initial response)
Using webpack with hot module reloading
Using Vue.js as a frontend framework, with server-side rendering
bundle.js is served through the typical serve-static package
bundle.js doesn't seem to be being cached at all. Why is this?
On the Koa side of things, I started with some boilerplate package to do all this server-side rendering and such. This has been happening since I started messing around with this setup, and webpack in general, so I'm trying to get to the bottom of it. It seems to be a little random, where sometimes it will come back in < 1s, but most times it takes 10+ seconds. Sometimes 30+ seconds?!
I've also tried to use different libraries to serve the static files, but they all seem to do this.
Here is my main webpack config ('webpack.client', extended below):
'use strict'
const path = require('path')
const webpack = require('webpack')
const AssetsPlugin = require('assets-webpack-plugin')
const assetsPluginInstance = new AssetsPlugin({path: path.join(process.cwd(), 'build')})
const postcss = [
require('precss')()
//require('autoprefixer')({browsers: ['last 2 versions']}),
]
module.exports = {
entry: [
'./src/client-entry.js'
],
output: {
path: path.join(process.cwd(), 'build'),
filename: 'bundle.js',
publicPath: '/'
},
resolve: {
extensions: ['', '.vue', '.js', '.json']
},
module: {
loaders: [
{
test: /\.vue$/,
loaders: ['vue']
},
{
test: /\.js$/,
loaders: ['babel'],
exclude: [/node_modules/]
},
{
test: /\.json$/,
loaders: ['json'],
exclude: [/node_modules/]
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'url?limit=10000&name=images/[hash].[ext]',
include: path.src,
},
{
test: /\.woff($|\?)|\.woff2($|\?)|\.ttf($|\?)|\.eot($|\?)|\.svg($|\?)/,
loader: 'url-loader',
include: path.src,
}
]
},
node: { net: 'empty', dns: 'empty' },
postcss,
vue: {
postcss,
loaders: {}
},
plugins: [
assetsPluginInstance
]
}
And also this (extends the previous):
'use strict'
const webpack = require('webpack')
const config = require('./webpack.client')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
config.entry.push('webpack-hot-middleware/client')
//config.devtool = 'inline-eval-cheap-source-map'
config.plugins = config.plugins.concat([
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new webpack.DefinePlugin({
'__DEV__': true,
'process.env.NODE_ENV': JSON.stringify('development')
}),
new ExtractTextPlugin('[name].[contenthash].css')
])
config.vue.loaders = {
postcss: ExtractTextPlugin.extract(
'vue-style-loader',
'css-loader?sourceMap'
),
css: ExtractTextPlugin.extract(
'vue-style-loader',
'css-loader?sourceMap'
)
}
module.exports = config
Here is my server index.js file for Koa:
import path from 'path'
import fs from 'fs'
import Koa from 'koa'
import convert from 'koa-convert'
//import serve from 'koa-static-server'
import serveStatic from 'koa-static'
import {PassThrough} from 'stream'
import {createBundleRenderer} from 'vue-server-renderer'
import serialize from 'serialize-javascript'
import MFS from 'memory-fs'
import assets from '../build/webpack-assets'
import cookie from 'koa-cookie'
let renderer
const createRenderer = fs => {
const bundlePath = path.resolve(process.cwd(), 'build/server-bundle.js')
return createBundleRenderer(fs.readFileSync(bundlePath, 'utf-8'))
}
const app = new Koa();
app.use(cookie());
if (process.env.NODE_ENV === 'development') {
// DEVELOPMENT, with hot reload
const webpack = require('webpack')
const webpackConfig = require('../config/webpack.client.dev')
const compiler = webpack(webpackConfig)
const devMiddleware = require('koa-webpack-dev-middleware')
const hotMiddleware = require('koa-webpack-hot-middleware')
app.use(convert(devMiddleware(compiler, {
publicPath: webpackConfig.output.publicPath,
stats: {
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}
})))
app.use(convert(hotMiddleware(compiler)))
// server renderer
const serverBundleConfig = require('../config/webpack.bundle')
const serverBundleCompiler = webpack(serverBundleConfig)
const mfs = new MFS()
serverBundleCompiler.outputFileSystem = mfs
serverBundleCompiler.watch({}, (err, stats) => {
if (err) throw err
stats = stats.toJson()
stats.errors.forEach(err => console.error(err))
stats.warnings.forEach(err => console.warn(err))
renderer = createRenderer(mfs)
})
}
else {
// PRODUCTION
// use nginx to serve static files in real
//app.use(convert(serve({rootDir: path.join(process.cwd(), 'build'), rootPath: '/static'})))
app.use(serveStatic(path.join(process.cwd(), 'build')));
renderer = createRenderer(fs)
}
app.use(ctx => {
var start = new Date;
ctx.type = 'text/html; charset=utf-8'
const context = {url: ctx.url}
const title = 'Tripora';
const stream = new PassThrough()
console.log("Checking if server-side cookie exists...");
// See if request sent over an authentication token in their cookies
if(ctx.cookie && ctx.cookie.token) {
console.log("Found cookie token.");
context.token = ctx.cookie.token;
}
stream.write(`<!DOCTYPE html><html style="min-height: 100%;"><head><meta charset="utf-8"/><title>${title}</title>${assets.main.css ? `<link rel="stylesheet" href="${assets.main.css}"/>` : ''}</head><body style="min-height: 100%;">`)
const renderStream = renderer.renderToStream(context)
let firstChunk = true
renderStream.on('data', chunk => {
// we tell the request to ignore files as an initial reuqest
var isPage = ctx.url.split(".").length == 1;
if (firstChunk && context.initialState && isPage) {
stream.write(`<script>window.__INITIAL_STATE__=${serialize(context.initialState, {isJSON: true})}</script>${chunk}`)
firstChunk = false
} else {
stream.write(chunk)
}
})
renderStream.on('end', () => {
stream.write(`<script src="${assets.main.js}"></script></body></html>`)
var ms = new Date - start;
//ctx.set('X-Response-Time', ms + 'ms');
console.log("-- Response time %s %s = %sms", ctx.method, ctx.originalUrl, ms);
ctx.res.end()
})
renderStream.on('error', err => {
console.log("ERROR", err.stack);
throw new Error(`something bad happened when renderToStream: ${err}`)
})
ctx.status = 200
ctx.body = stream
})
const port = process.env.NODE_PORT || 80
app.listen(port, () => {
console.log(`==> Listening at http://localhost:${port}`)
})
Anyone know why the HMR initial request would take so long, and seem to be so random (sometimes 5s, sometimes 30 seconds)? Techneregy.