How to detect "Uncaught (in promise) TypeError" in Playwright? - playwright

I'm using Playwright to test my TypeScript webapp, and I want to ensure no errors are logged to the console. (I want my tests to fail if an error occurs.)
To do so, based on this post, I use the following code:
import { test as base, expect } from '#playwright/test';
export const test = base.extend({
page: async ({ baseURL, page }, use) => {
const messages: string[] = [];
page.on('console', (msg) => {
// Ignore regular log messages; we are only interested in errors.
if (msg.type() === 'error') {
messages.push(`[${msg.type()}] ${msg.text()}`);
}
});
await use(page);
expect(messages).toStrictEqual([]);
},
});
export default test;
This code will correctly cause the test to fail if console.error is used in the app.
However, Uncaught (in promise) TypeError is ignored by this check; the test completes successfully even though the following message is logged to the console:
ion-refresher.js:526 Uncaught (in promise) TypeError: ee.componentOnReady is not a function
at _class._callee8$ (ion-refresher.js:526:21)
at tryCatch (regeneratorRuntime.js:86:17)
at Generator._invoke (regeneratorRuntime.js:66:24)
at Generator.next (regeneratorRuntime.js:117:21)
at asyncGeneratorStep (asyncToGenerator.js:3:20)
at _next (asyncToGenerator.js:25:9)
at asyncToGenerator.js:32:7
at new Promise (<anonymous>)
at _class.<anonymous> (asyncToGenerator.js:21:12)
at _class.connectedCallback (ion-refresher.js:187:51)
I want to catch this kind of error (Uncaught (in promise) TypeError) automatically when running my Playwright tests because it should never occur. How can I do that?
(I tried removing the msg.type() === 'error' check from my code, but that didn't help-- Uncaught (in promise) TypeError do not show up as console errors in Playwright, so where are they?)

Based on the comment from #stefan judis, I was able to capture this error by checking for page errors in addition to console errors.
Here's the final code:
import { test as base, expect } from '#playwright/test';
export const test = base.extend({
page: async ({ baseURL, page }, use) => {
const messages: string[] = [];
page.on('console', (msg) => {
// Ignore regular log messages; we are only interested in errors.
if (msg.type() === 'error') {
messages.push(`[${msg.type()}] ${msg.text()}`);
}
});
// Uncaught (in promise) TypeError + friends are page errors.
page.on('pageerror', (error) => {
messages.push(`[${error.name}] ${error.message}`);
});
await use(page);
expect(messages).toStrictEqual([]);
},
});
export default test;

Related

Electron ipcRenderer.sendSync() returning undefined

I'm writing an app with the electron-react-boilerplate framework.
I've been following a tutorial here: https://riptutorial.com/electron/example/19713/synchronous-ipc-communication
In my renderer process I have:
let a = window.electron.ipcRenderer.sendSync('LIST', []);
console.log(a);
and in my main process:
ipcMain.on('LIST', (event) => {
event.returnValue = 'test';
});
However the value 'a' is undefined when it is logged. What am I doing wrong?
I realised what I did wrong.
In preload.ts I exposed the function sendSync like below:
sendSync(channel: Channels, args: unknown[]) {
ipcRenderer.sendSync(channel, args);
},
...this didn't return anything, hence the undefined. I should have done:
sendSync(channel: Channels, args: unknown[]) {
return ipcRenderer.sendSync(channel, args);
},
Now it returns as expected!

Electron ipcMain how to gracefully handle throwing an error

In Electron if I throw an error anywhere on the backend it goes to a custom window. Trying to find a way to catch that to push to a custom area in my app I've found that I can detect the process with process.on('uncaughtException'). However I'm stuck trying to run a sender to send either the error or the report. What I've tried:
ipcMain.on('main', async (e, data) => {
try {
await someModule(data)
process.on('uncaughtException', err => e.sender.send('error', err.message))
return e.sender.send('audit', 'No issues found')
} catch (err) {
console.log(err)
}
})
module.js:
module.export = data => {
throw Error('this is a test')
}
In the above I'm sending both get both errorandaudit` to renderer. I've researched for a way to pass 'uncaughtException' to a ternary but I'm not able to find any docs on how to condition for 'uncaughtException' but I did try:
process.on('uncaughtException', err => {
if (err) return e.sender.send('error', err.message)
return e.sender.send('audit', 'test complete')
})
and the above only works if an error is present, research:
Catch all uncaughtException for Node js app
Nodejs uncaught exception handling
Node.js Uncaught Exception - Passing more details
In Electron how can I intercept the error to pass it to renderer from main without throwing the default error window?
If you use ipcMain.handle you will be able to handle errors in the renderer process like this
// Main process
ipcMain.handle('my-invokable-ipc', async (event, data) => {
await someModule(data)
return 'No issues found'
})
// Renderer process
async () => {
try {
const result = await ipcRenderer.invoke('my-invokable-ipc', data)
console.log(result) // 'No issues found' if someModule did not throw an error
} catch (err) {
// you can handle someModule errors here
}
}
Update: An issue with this approach is that the error emitted to the renderer process is serialized and it gets printed even though it's handled with a try/catch.
To fix this, you can also handle the errors in the main process
// Main process
ipcMain.handle('my-invokable-ipc', async (event, data) => {
try {
await someModule(data)
return 'No issues found'
} catch (err) {
// handle someModule errors and notify renderer process
// return err.message or any other way you see fit
}
})
// Renderer process
async () => {
const result = await ipcRenderer.invoke('my-invokable-ipc', data)
console.log(result) // 'No issues found' if someModule did not throw an error
}

rollup.js: How to disable output?

I'm trying to use the rollup JS API. rollup.rollup doesn't require me to specify the output option but it appears rollup.watch does for some reason.
Here's what I've got:
#!/usr/bin/env node
import * as rollup from 'rollup';
async function main() {
const watcher = rollup.watch({
input: 'src/main.ts',
// output: {
// dir: 'dist'
// }
})
watcher.on('event', event => {
console.log(event);
})
}
main().catch(err => {
console.error(err);
process.exit(1);
})
It's saying:
{
code: 'ERROR',
error: Error: You must specify "output.file" or "output.dir" for the build.
at error (file:///somepath/screeps/node_modules/rollup/dist/es/shared/rollup.js:10380:30
)
at Object.write (file:///somepath/screeps/node_modules/rollup/dist/es/shared/rollup.js:1
8594:24)
at file:///somepath/screeps/node_modules/rollup/dist/es/shared/watch.js:7083:86
at Array.map (<anonymous>)
at Task.run (file:///somepath/screeps/node_modules/rollup/dist/es/shared/watch.js:7083:6
3)
at async Watcher.run (file:///somepath/screeps/node_modules/rollup/dist/es/shared/watch.
js:7003:17) {
code: 'MISSING_OPTION'
}
}
I should be able to get what I need out of the event emitter though -- I don't want to write it to disk. How do I disable that?
Turns out there's a watch.skipWrite option.

OData success message even though no new entry?

I have an SAPUI5 application which is deployed to ABAP server and accessible with Fiori Launchpad. I use this app to create a new interaction (OData Service CUAN_IMPORT_SRV) in Hybris Marketing. My problem is that even though the OData call created no new entry (because such entry already exists), I get the success message. When I add invalid data to the upload data, I get the error message.
This is my code:
var oModel = new sap.ui.model.odata.v2.ODataModel("https://hostname:port/sap/opu/odata/sap/CUAN_IMPORT_SRV/", true);
var oData = { some json... }
oModel.create("/ImportHeaders", oData, {
success: function() {
sap.m.MessageBox.success("Interaction successfully created!", {
title: "Success"
});
},
error: function() {
sap.m.MessageBox.error("Interaction could not be created.", {
title: "Error"
});
}
});
When I run /n/iwfnd/traces it is marked as "successful execution" (even though no new entry was created).
How can it be that the success message appears even though no new entry was created? How can I avoid that?
First thing is to add your business error in the ABAP backend:
DATA:
lt_bapi_return type table of bapiret2,
lo_message_container type ref to /iwbep/if_v4_message_container.
#Error handling
if lt_bapi_return is not initial.
#check if an error message is in lt_bapi_return
loop at lt_bapi_return into ls_bapi_return.
if ls_bapi_return-type = 'E'.
lo_message_container = io_response->get_message_container( ).
loop at lt_bapi_return into ls_bapi_return.
lo_message_container->add_t100(
exporting
iv_msg_type = ls_bapi_return-type
iv_msg_id = ls_bapi_return-id
iv_msg_number = ls_bapi_return-number
iv_msg_v1 = ls_bapi_return-message_v1
iv_msg_v2 = ls_bapi_return-message_v2
iv_msg_v3 = ls_bapi_return-message_v3
iv_msg_v4 = ls_bapi_return-message_v4 ).
endloop.
"raise exception
raise exception type zcx_e2e001_odata_v4_so
exporting
message_container = lo_message_container.
endif.
endloop.
endif.
And at UI:
error: function(response) {
//response will have message details
//each message can have business text, technical info, error code.
sap.m.MessageBox.error("Interaction could not be created.", {
title: "Error"
});
}
You can add this part of code to every redefined method..
better is create a util method and reuse.

Exception ETIMEDOUT in node.js

I write application for iOS, which uses Socket.IO. Sometimes my server JS-script falls with this error:
events.js:85
throw er; // Unhandled 'error' event
^
Error: connect ETIMEDOUT
at exports._errnoException (util.js:746:11)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:983:19)
What I know is:
Script workes fine when I use only application for Android. That app uses Socket.IO for Android
Script workes fine when I use only web-client (yeap, with socket.IO)
Script startes to fall when I use iOS app.
Crash happens not always and not right away. Script falls after 5-10 minutes after connection and may crash, but may not.
So, I think the problem is in server library for socket.io, but exception fires only when iOS-client connecting.
How can I handle this exception?
UPDATE
There is problem was in the OAuth module on my node.js-server, which tried to check app token but had timeout to vk.com
I've edited vkapi module in my node.js server by adding "on" event for "https.get" function:
Was:
https.get(options, function(res) {
var apiResponse = new String();
res.setEncoding('utf8');
res.on('data', function(chunk) {
apiResponse += chunk;
});
res.on('end', function() {
var o = JSON.parse(apiResponse);
if (o.error) { self.emit('appServerTokenNotReady', o);
} else {
self.token = o.access_token;
self.emit('appServerTokenReady');
}
});
});
Now:
https.get(options, function(res) {
var apiResponse = new String();
res.setEncoding('utf8');
res.on('data', function(chunk) {
apiResponse += chunk;
});
res.on('end', function() {
var o = JSON.parse(apiResponse);
if (o.error) { self.emit('appServerTokenNotReady', o);
} else {
self.token = o.access_token;
self.emit('appServerTokenReady');
}
});
}).on('error', function(e) {
console.log('HTTPS error');
});
In general, you can handle these kinds of async errors by listening for the error event on whatever (e.g. request, connection, etc.) object.
The error event is special in that if there are currently no event handlers for it when it is emitted, the error will be thrown instead.

Resources