diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesClient.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesClient.kt index 4daa2aa5f5e95..c75145612f497 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesClient.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesClient.kt @@ -85,7 +85,7 @@ internal open class TCServiceMessagesClient( } } is TestSuiteFinished -> close(message.ts, getSuiteName(message)) - is Message -> regularText(message.text) + is Message -> printNonTestOutput(message.text, message.attributes["type"]) else -> Unit } @@ -115,7 +115,7 @@ internal open class TCServiceMessagesClient( afterMessage = false } - protected open fun printNonTestOutput(text: String) { + protected open fun printNonTestOutput(text: String, type: String? = null) { print(text) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesTestExecutor.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesTestExecutor.kt index 3aaa7231a3012..e53ed89fe7015 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesTestExecutor.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesTestExecutor.kt @@ -52,6 +52,7 @@ class TCServiceMessagesTestExecutor( spec.forkOptions.copyTo(exec) exec.args = spec.args exec.standardOutput = TCServiceMessageOutputStreamHandler(client, { spec.showSuppressedOutput() }, log) + exec.errorOutput = TCServiceMessageOutputStreamHandler(client, { spec.showSuppressedOutput() }, log) execHandle = exec.build() lateinit var result: ExecResult diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/JSServiceMessages.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/JSServiceMessages.kt index cf50186469672..b37fe91f33122 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/JSServiceMessages.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/JSServiceMessages.kt @@ -37,7 +37,7 @@ internal open class JSServiceMessagesClient( settings: TCServiceMessagesClientSettings, log: Logger ) : TCServiceMessagesClient(results, settings, log) { - override fun printNonTestOutput(text: String) { + override fun printNonTestOutput(text: String, type: String?) { if (log.isDebugEnabled) { log.debug(text) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KotlinKarma.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KotlinKarma.kt index e53e5cb3d233a..ce0cf15bdb40f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KotlinKarma.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KotlinKarma.kt @@ -200,6 +200,17 @@ class KotlinKarma(override val compilation: KotlinJsCompilation) : """.trimIndent() ) + //language=ES6 + it.appendln( + """ + // noinspection JSUnnecessarySemicolon + ;(function(config) { + const tcErrorPlugin = require('kotlin-test-js-runner/tc-log-error-webpack'); + config.plugins.push(new tcErrorPlugin(tcErrorPlugin)) + })(config); + """.trimIndent() + ) + it.appendln(" return config;") it.appendln("}") it.appendln() @@ -418,15 +429,17 @@ class KotlinKarma(override val compilation: KotlinJsCompilation) : private val failedBrowsers: MutableList = mutableListOf() - override fun printNonTestOutput(text: String) { + override fun printNonTestOutput(text: String, type: String?) { val value = text.trimEnd() progressLogger.progress(value) - parseConsole(value) + parseConsole(value, type) } - private fun parseConsole(text: String) { + private fun parseConsole(text: String, type: String?) { + val result = KARMA_MESSAGE.matchEntire(text) + if (result != null) { val (logLevel, message) = result.destructured @@ -445,8 +458,20 @@ class KotlinKarma(override val compilation: KotlinJsCompilation) : INFO, LOG -> log.info(nonColoredMessage) DEBUG -> log.debug(nonColoredMessage) } - } else { - super.printNonTestOutput(text) + + return + } + + val nonColoredText = text.clearAnsiColor() + + if (type == "error") { + log.error(nonColoredText) + return + } + + if (type == "warn") { + log.warn(nonColoredText) + return } } diff --git a/libraries/tools/kotlin-test-js-runner/rollup.config.js b/libraries/tools/kotlin-test-js-runner/rollup.config.js index 9b931bba5a48e..4c741cedd4465 100644 --- a/libraries/tools/kotlin-test-js-runner/rollup.config.js +++ b/libraries/tools/kotlin-test-js-runner/rollup.config.js @@ -59,6 +59,13 @@ export default [ format: 'cjs' } }, + { + input: './tc-log-error-webpack.js', + output: { + file: 'lib/tc-log-error-webpack.js', + format: 'cjs' + } + }, { input: './mocha-kotlin-reporter.js', external: ['path', 'util'], diff --git a/libraries/tools/kotlin-test-js-runner/src/teamcity-format.d.ts b/libraries/tools/kotlin-test-js-runner/src/teamcity-format.d.ts index b52574fbd41b6..b18922ca4bd50 100644 --- a/libraries/tools/kotlin-test-js-runner/src/teamcity-format.d.ts +++ b/libraries/tools/kotlin-test-js-runner/src/teamcity-format.d.ts @@ -18,4 +18,4 @@ export const MESSAGE: string export function tcEscape(str: string): string -export function formatMessage(...str: string[]): string \ No newline at end of file +export function formatMessage(type: string, ...str: string[]): string \ No newline at end of file diff --git a/libraries/tools/kotlin-test-js-runner/src/teamcity-format.js b/libraries/tools/kotlin-test-js-runner/src/teamcity-format.js index b9164ce95f987..8017062c203b8 100644 --- a/libraries/tools/kotlin-test-js-runner/src/teamcity-format.js +++ b/libraries/tools/kotlin-test-js-runner/src/teamcity-format.js @@ -17,6 +17,7 @@ export const BLOCK_OPENED = `##teamcity[blockOpened name='%s' flowId='%s']` export const BLOCK_CLOSED = `##teamcity[blockClosed name='%s' flowId='%s']` export const MESSAGE = `##teamcity[message text='%s']` +export const TYPED_MESSAGE = `##teamcity[message text='%s' type='%s']` /** * from teamcity-service-messages diff --git a/libraries/tools/kotlin-test-js-runner/tc-log-error-webpack.js b/libraries/tools/kotlin-test-js-runner/tc-log-error-webpack.js new file mode 100644 index 0000000000000..a7496a69b0027 --- /dev/null +++ b/libraries/tools/kotlin-test-js-runner/tc-log-error-webpack.js @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +'use strict'; + +import {formatMessage, TYPED_MESSAGE} from "./src/teamcity-format"; + +const ModuleNotFoundError = require("webpack/lib/ModuleNotFoundError") + +class TeamCityErrorPlugin { + apply(compiler) { + compiler.hooks.done.tap('TeamCityErrorPlugin', (stats) => { + stats.compilation.errors.forEach(error => { + if (error instanceof ModuleNotFoundError) { + error.dependencies.forEach(dependency => { + console.error(formatMessage(TYPED_MESSAGE, `Module '${dependency.request}' not found`, 'error')) + }) + return + } + + console.error(formatMessage(TYPED_MESSAGE, error.message, 'error')) + }) + + stats.compilation.warnings.forEach(warning => { + console.warn(formatMessage(TYPED_MESSAGE, warning.message, 'warn')) + }) + }); + } +} + +module.exports = TeamCityErrorPlugin; \ No newline at end of file