I am trying to figure out how to write "this line of code has to produce an exception" in one of my test cases for qml. What I am doing essentially is
TextField{
id: defaultLineEdit
onTextChanged: { throw "test";}
}
then in my test code:
function test_exception(){
try {
defaultLineEdit.text = "text";
}
catch(e){
console.log("caught exception");
}
}
The problem is - I have verified that the exception is thrown on text changed, but I never enter the catch branch somehow. What is happening here?
Related
I'm working on this and can't think of a way to handle the error thrown by renderer2.selectRootElement.
This is what my function looks like:
private doSomeAnimation(){
const modalWrapper = this.renderer2.selectRootElement('.modal-wrapper', true);//It fails here
// finally do something with modalWrapper
this.renderer2.addClass(modalWrapper, 'fade-out');
}
and if I open the console I see this error:
global-angular-error-handler.service.ts:49 Error: The selector ".modal-wrapper" did not match any elements
at DefaultDomRenderer2.selectRootElement (dom_renderer.ts:146)
at BaseAnimationRenderer.selectRootElement (animation_renderer.ts:156)
at DebugRenderer2.selectRootElement (services.ts:762)
at ModalComponent.animateClosing (modal.component.ts:39)
....
I also looked at the Docs for Renderer2 and selectRootElement looks like this
selectRootElement(selectOrNode: string|any):any{
let el: any = typeof selectOrNode === 'string'? document.querySelector(selectOrNode) : selectOrNode;
if(!el){
throw new Error(`The selector "${selectorOrNode}" did not match any elements`);
}
el.textContent = '';
return el;
}
As you can see my code fails in line number 1 of my function, so my question is how to NOT show any error in the console if there wasn't any match. I mean how to not show this message in the console
"The selector ".modal-wrapper" did not match any elements"
Can someone help me or point me in the right direction? Thanks a lot in advance!
You could wrap the call into a try/catch
let modalWrapper;
try {
modalWrapper = this.renderer2.selectRootElement('.modal-wrapper', true);
} catch (e) {
// do what you need to do with the exception here.
return;
}
I've been writing simple web-frontend for application with kotlin-js and faced with a problem of exception handling.
As I see, there is no API to get exception stacktrace: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html
Is it so?
If it is, may be anyone know some library or snippets to get stacktrace out of Throwable object?
Currently, I've got some workaround for this:
import kotlin.browser.window
fun main() {
window.onload = {
try {
throw RuntimeException()
} catch (e: Throwable) {
console.log(e)
throw e
}
}
}
Console output is:
Object {
"message_8yp7un$_0": null,
"cause_th0jdv$_0": null,
"stack": "captureStack#http://localhost:9080/js/kotlin.js:1767:27\nException#http://localhost:9080/js/kotlin.js:3244:14\nRuntimeException#http://localhost:9080/js/kotlin.js:3255:17\nRuntimeException_init#http://localhost:9080/js/kotlin.js:3261:24\nmain$lambda#http://localhost:9080/js/web-client.js:34:13\n",
"name": "RuntimeException"
}
Here, console.log(Throwable) exposes underlying JavaScript object properties, and there is stack one, but it points to JavaScript code, that is hard to use without source mapping back to kotlin.
UPD: it seems like stack is not standard exception property, but common one for modern browsers.
Since Kotlin 1.4 the stdlib contains two extensions for this exact purpose
fun Throwable.stackTraceToString()
fun Throwable.printStackTrace()
Using these we can write
window.onload = {
try {
throw RuntimeException()
} catch (e: Throwable) {
e.printStackTrace()
}
}
Just change your console.log to console.error
import kotlin.browser.window
fun main() {
window.onload = {
try {
throw RuntimeException()
} catch (e: Throwable) {
console.error(e) // change here
throw e
}
}
}
Not perfect, not standard, but it works.
It also handles the source map in Firefox, so I get proper file names and line numbers:
try {
throw IllegalStateException("ops...")
}
catch (ex : Throwable) {
val stack = ex.asDynamic().stack
if (stack is String) {
val error = js("Error()")
error.name = ex.toString().substringBefore(':')
error.message = ex.message?.substringAfter(':')
error.stack = stack
console.error(error)
} else {
console.log(ex)
}
}
Some of you made some awesome javascript courses which I follow eagerly in the adventure to become a better developer.
One of these courses was about EcmaScript6 const and let variables and the Try and Catch statement. So as a curious junior developer I tried it myself by declaring an arrow function in a constant and trying to change the constant:
const userValidation = (userValid) => userValid == true ? "You may enter" : "You may not enter, sorry.";
try {
var userValidation = function(userID) {
//Execute some code which ofcourse will never execute
}
}
catch(err) {
console.log("Woops, something went wrong.");
}
console.log(userValidation(false));
The behaviour which I expected was the error message: "Woops, something went wrong." because I already declared the constant "UserValidation". But that was not what was happening, instead the console just gave the error and dies:
What am I doing wrong?
try, catch statements are used to catch runtime errors, but this SyntaxError is detected while the Javascript is being parsed, before it is run. This is because you are not reassigning the (const) variable here but redefining it with a different identifier (var). If the code were
const userValidation = (userValid) => userValid == true ? "You may enter" : "You may not enter, sorry.";
try {
userValidation = function(userID) {
//Execute some code which ofcourse will never execute
}
}
catch(err) {
console.log("Woops, something went wrong.");
}
without the var identifier, then this would become a runtime error. The code would be attempting reassign the const variable and your catch statement would execute.
I have some JSON data inside of an HTML data element:
<div id="ps-data" data-ps="
{
"teacherId": 12345678
},
"></div>
I parse it using jQuery's parseJSON function, but if I pass it invalid JSON, I get a SyntaxError exception. In QUnit, this shows up as a global failure, but I'd like it to fail in one of my test cases. What's the best way to do so?
My parsing code looks like:
$.parseJSON($('#ps-data').data().ps);
You could do something like this:
var exeptionReached = false;
try {
$.parseJSON($('#ps-data').data().ps);
} catch(e) {
exceptionReached = true;
}
console.log(exceptionReached); //will be true if `parseJSON()` threw an exception
Use qunit to assert exception was reached... or you can save something from the exception object if you want to assume something specific about it, for example:
var ex;
try {
$.parseJSON($('#ps-data').data().ps);
} catch(e) {
ex = e;
}
console.log(ex.message); // something like "Unexpected token ,"
You'll want to check that ex is defined before accessing properties of course. I think you should be able to see how you can test whether or not an exception happened and how to test specifics about that exception if you want... but let me know if you have any extra questions.
JSFiddle example
Here's the full example of what I'm doing based on smerny's answer.
function testParse() {
var exceptionMsg;
try {
var data = $j.parseJSON($j('#ps-data').data().ps);
} catch (e) {
exceptionMsg = e.message;
}
return exceptionMsg;
}
strictEqual(testParse(), undefined, 'ps data parses with no exceptions');
This will show me the exception message when it fails.
Short version
Trying to write a debug command that returns the call stack, minus the current position. I thought I'd use:
try {
throw new Error(options["msg"])
} catch (e) {
e.stack.shift;
throw (e);
}
but I don't know how to do it exactly. apparently I can't just e.stack.shift like that. Also that always makes it an Uncaught Error — but these should just be debug messages.
Long version
I decided I needed a debug library for my content scripts. Here it is:
debug.js
var debugKeys = {
"level": ["off", "event", "function", "timeouts"],
"detail": ["minimal", "detailed"]
};
var debugState = { "level": "off", "detail": "minimal" };
function debug(options) {
if ("level" in options) {
if (verifyDebugValue("level", options["level"]) == false)
return
}
if ("detail" in options) {
if (verifyDebugValue("detail", options["detail"]) == false)
return
}
console.log(options["msg"]);
}
function verifyDebugValue(lval, rval){
var state = 10; // sufficiently high
for (k in debugKeys[lval]) {
if (debugKeys[lval][k] == rval) {
return true;
}
if (debugKeys[lval][k] == debugState[lval]) { // rval was greater than debug key
return false;
}
}
}
When you using it, you can change the debugState in the code to suit your needs. it is still a work in progress but it works just fine.
To use it from another content script, just load it in the manifest like:
manifest.json
"content_scripts": [
{
"js": ["debug.js", "foobar.js"],
}
],
and then call it like:
debug({"level": "timeouts", "msg": "foobar.js waitOnElement() timeout"});
which generates:
foobar.js waitOnElement() timeout debug.js:17
And there is my problem. At the moment, it is using the console log and so all the debug statements come from the same debug.js line. I'd rather return the calling context. I imagine I need something like:
try {
throw new Error(options["msg"])
} catch (e) {
e.stack.shift;
throw (e);
}
but I don't know how to do it exactly. apparently I can't just e.stack.shift like that. Also that always makes it an Uncaught Error — but these should just be debug messages.
You can't avoid mentioning the line in your debug.js, because either using throw (...) or console.log/error(...) your debug.js will be issuing the command.
What you can do, is have some try-catch blocks in your code, then in the catch block pass the error object to your debug function, which will handle it according to its debugState.
In any case, it is not quite clear how you are using your debug library (and why you need to remove the last call from the stack-trace, but you could try something like this:
Split the stack-trace (which is actually a multiline string) into lines.
Isolate the first line (corresponding to the last call) that is not part of the error's message.
Put together a new stack-trace, with the removed line.
E.g.:
function removeLastFromStack(stack, errMsg) {
var firstLines = 'Error: ' + errMsg + '\n';
var restOfStack = stack
.substring(firstLines.length) // <-- skip the error's message
.split('\n') // <-- split into lines
.slice(1) // <-- "slice out" the first line
.join('\n'); // <-- put the rest back together
return firstLines + restOfStack;
}
function myDebug(err) {
/* Based on my `debugState` I should decide what to do with this error.
* E.g. I could ignore it, or print the message only,
* or print the full stack-trace, or alert the user, or whatever */
var oldStack = err.stack;
var newStack = removeLastFromStack(oldStack, err.message);
console.log(newStack);
//or: console.error(newStack);
}
/* Somewhere in your code */
function someFuncThatMayThrowAnErr(errMsg) {
throw new Error(errMsg);
}
try {
someFuncThatMayThrowAnErr('test');
} catch (err) {
myDebug(err);
}
...but I still don't see how removing the last call from the trace would be helpful