Workstation hosted vscode extension not processing message from remote hosted extension - vscode-extensions

QV https://github.com/microsoft/vscode-remote-release/issues/7736
I have two extensions. One of them is of uiKind workspace and may run locally or remotely depending on the workspace, and the other is of uiKind ui and always runs locally.
The ui extension is responsible for spawning a browser on the user's workstation to load a URI provided by the argument of a command print.launchBrowser that it registers using vscode.commands.registerCommand
The workspace extension uses vscode.commands.executeCommand to invoke print.launchBrowser.
The point of this arrangement is to allow the browser to be launched on the workstation irrespective of whether the extension host is local or remote.
This should work. The following documentation explicitly says it works: https://code.visualstudio.com/api/advanced-topics/remote-extensions#communicating-between-extensions-using-commands
However, when I test it works only when both extensions run on the workstation.
Before anyone tells me to use vscode.env.openExternal(Uri) I am aware of this and am using it to launch the default browser, but this is no use for launching a non-default browser. Many of my users exploit the support for an alternate browser to use Chrome for printing while using a less invasive alternative as their daily drive.
What could cause this to fail? Here's the abovementioned documentation:
Some extensions return APIs as a part of their activation that are intended for use by other extensions (via vscode.extension.getExtension(extensionName).exports). While these will work if all extensions involved are on the same side (either all UI Extensions or all Workspace Extensions), these will not work between UI and Workspace Extensions.
Fortunately, VS Code automatically routes any executed commands to the correct extension regardless of its location. You can freely invoke any command (including those provided by other extensions) without worrying about impacts.
That's not ambiguous.
Since the code for the browser agent is very short I present it in its entirety.
import * as vscode from 'vscode';
import * as child_process from "child_process";
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.commands.registerCommand("print.launchBrowser", url => {
const browserPath = vscode.workspace.getConfiguration("print").browserPath;
child_process.exec(`${escapePath(browserPath)} ${url}`, (error: child_process.ExecException | null, stdout: string, stderr: string) => {
if (error || stderr) {
const err = error ? error.message : stderr;
if (!err.startsWith("[")) {
vscode.window.showErrorMessage(err);
}
}
});
}));
}
function escapePath(path: string) {
switch (process.platform) {
case "win32":
return path.includes('"') || !path.includes(" ") ? path : `"${path}"`;
default:
return path.replace(/ /g, "\\ ");
}
}
Code to call it is straightforward. Any extension containing the following should open a browser window and load the bing.com default page, although if you want to use the agent above you'll need to either supply the print.browserPath setting with a value containing the workstation path to a browser or put in such a path as a literal for testing purposes.
There aren't any tests for things like whether browserPath has a value that resolves to a file. That's all in the calling extension, which is designed to use the agent only when it runs in a remote workspace. The agent is essentially nothing but a platform independent remote procedure call.
vscode.commands.executeCommand("print.launchBrowser", "https://bing.com");
All this has been tested and failed on two separate computers and also with VS Code Insiders 1.75.0, which also resolves the question of whether I have a borked VS Code installation.

Related

Browser Stack Local Testing Parellel Test

I need to run my all test cases in parallel of 4 different browser.
On my chrome driver its work fine.
Problem arise when i try to run in parallel as local testing.
I get following error
com.browserstack.local.LocalException: *** Error: Either another browserstack local client is running on your machine or some server is listening on port 45691
I am using TestNG as my test runner.
It is too late but maybe it is good for other developers.
I do not know in which language you are programming but if you are using java and using the browserstack-local-java which has poor documentation :(
You need to add browserstack.localIdentifier = "specific id" to the capabilities when you create the WebDriver
At the same time when creating the com.browserstack.local.Local which calls ./BrowserStackLocal under the hood you need to specify an option called localIdentifier and it must have the same value as the browserstack.localIdentifier.
This is not documented but I tested it and it works and take a look on https://github.com/webdriverio/webdriverio/issues/2252
Code to start browserstack local before start of test.
I just use the current date-timestamp as my localIdentifier's value as it is unique every time i run it.
I have the following bit code in my configuration file
onPrepare: function (config, capabilities) {
console.log("Connecting local");
return new Promise(function (resolve, reject) {
exports.bs_local = new browserstack.Local();
exports.bs_local.start({ localIdentifier,'key': exports.config.key }, function (error) {
if (error) return reject(error);
console.log('Connected. Now testing...');
resolve();
});
});
},
I had hard time solving the issue[Error: Either another browserstack local client is running on your machine or some server is listening on port 45691] when running parallel tests.
So, I'm adding supporting details for those whore are using browserstack-local-java bindings.
Make sure you are using the correct key names in setting the local identifier for both Browserstack and Local connection.
String localIdentifier = "random string";
localConnectionOptions.put("localIdentifier", localIdentifier);
bsCapabilities.setCapability("browserstack.localIdentifier", localIdentifier);
For more details, refer to the Browserstack documentation.

How can I replace the server in Web Component Tester

I have a project set up based around the Polymer Starter Kit, which includes Web-Component-Tester
This project includes php server code which I would also like to test by writing tests to run in the browser which will utilise the PHP server code through Ajax Calls.
This implies replacing the server that Web Component Tester is using ONLY when testing server side code. I hope to make a separate gulp task for this.
Unfortunately, I don't understand the relationship between WCT, Selenium and what ever server is run currently. I can see that WCT command starts Selenium, but I can't find out what the web server is and how that is started. I suspect it is WCT, because there is configuration of the mapping of directories to urls, but other than that I haven't a clue, despite trying to read the code.
Can someone explain how I go about making it run its own server when testing the client, but relying on an already set up web server (nginx) when running the server. I can set nginx to run from local host, or an other domain if that is a way to choose a different configuration.
EDIT: I have now found that runner/webserver.js starts an express server, and that urls get mapped so the base directory for the test runner and the bower_components directory both get mapped to the /components url.
What is currently confusing me is in what circumstances this gets run. It appears that loading plugins somehow does it, but my understanding from reading the code for this is tenuous.
The answer is that web component tester itself has a comment in the runner/config.js file.
In wct-conf.js, you can use registerHooks key into the Object that gets returned to add a function that does
registerHooks: function(wct) {
wct.hook('prepare:webserver', function(app, done) {
var proxy = require('express-http-proxy');
app.use('/api',
proxy('pas.dev', {
forwardPath: function(req, res) {
return require('url').parse(req.url).path;
}
})
);
done();
});
This register hook function allows you to provide a route (/api in my case) which this proxies to a server which can run the php scripts.

Pass URL with Notifying

I am wondering if it possible to configure the remote notify option to pass a URL.
I see there is a function for onErrorRemoteDisableDenial. I tried to modify it, but it seems to disables the app. Even if i put code to continue, the next call to the backend does not work.
But what we are looking for is giving the user the option to update via URL, or just continue with the app version they currently have.
Using Worklight 6.1
There is a way to customize both Remote Disable and Remote Notify, but the downloadLink (the link that you've set in Worklight Console) is available only when setting Remote Disable, not Remote Notify. Only the message (the text set in Worklight Console) will be available.
You can customize the Remote Notify flow by using the following in main.js (outside of any function):
wl_remoteDisableChallengeHandler.handleChallenge = function(message,downloadLink) {
WL.SimpleDialog.show(
"New Version",
message,
[
{text: "Download", handler: function() {
// Maybe use WL.App.openURL(downloadLink) to go to the app store
}},
{text: "Close", handler: function() {
// Continue with the app
}}
]);
};
wl_remoteDisableChallengeHandler.handleChallenge overrides the default Remote Notify code path. wl_remoteDisableChallengeHandler.handleFailure will override the default Remote Disable code path (and this is another way to customize Remote Disable).
Edit: per the findings in the comments, in order to get both the message and downloadLink, you will first need to temporary set Remote Disable and then change to Remote Notify, this is a workaround because Remote Notify by default is not meant to also pass the downloadLink to the default provided dialog.
Note: Remote Notify is meant to be displayed only once per a message's life cycle, so after it was displayed - it will not be displayed again until a the message is set again in the console.
A way to get the code to work on each application launch is to clear the application's HTML local storage (at some point while the app is running), where a "flag" is stored to tell the application not to display the message again (I forgot its name, but you could print the contents of the local storage and debug that).
Sounds like a nice feature request: https://developer.ibm.com/mobilefirstplatform/help

MobileFirst JavaScript adapter load local config file

I am creating multiple applications which works the same. For every application I use an adapter which contains the same procedures, but perform the request to a different back end (same host, only different path).
The thing I would like is to add a configuration file (json / xml) to the adapters which I can load and fetch some information from such as the path so I know which back end I need to call. The configuration is now in top of the file, but in the future it would be lovely to be able to update the adapter without changing the configuration afterwards.
Is there a way to load a second file located in the same directory (as where the adapter xml and implementation file are)? I tried using XMLHttpRequest, but this doesn't work as it is unavailable. The code I tried, but couldn't test as the fifth line already breaks.
var config = null;
function loadConfiguration() {
var loader = new XMLHttpRequest();
loader.overrideMimeType('application/json');
loader.open('GET', 'config.json', false);
loader.onreadystatechange = function () {
// Only for async calls.
config = loader.responseText;
};
config = loader.send();
}
If there is a better way, I would love to hear it! We upgraded to MFPF 7.0 if there are any new possibilities.
You cannot do this with JavaScript adapters, however in MFPF 7.0 there is a new type of adapters: Java adapters. Using Java adapters you can achieve this.
The following blog post explains how you can provide a single adapter that will allow you to point to different hosts or differents paths in the same host, etc...
See here: Changing the adapter host at runtime

Kohana Auth Library Deployment

My Kohana app runs perfectly on my local machine.
When I deployed my app to a server (and adjust the config files appropriately), I can no longer log into the app.
I've traced through the app login routine on both my local version and the server version and they both agree with each other all the way through until you get to the auth.php controller logged_in() routine where suddenly, at line 140 - the is_object($this->user) test - the $user object no longer exists!?!?!?
The login() function call that calls the logged_in() function successfully passes the following test, which causes a redirect to the logged_in() function.
if(Auth::instance()->login($user, $post['password']))
Yes, the password and hash, etc all work perfectly.
Here is the offending code:
public function logged_in()
{
if ( ! is_object($this->user))
{
// No user is currently logged in
url::redirect('auth/login');
}
etc...
}
As the code is the same between my local installation and the server, I reckon it must be some server setting that is messing with me.
FYI: All the rest of the code works because I have a temporary backdoor available that allows me to use the application (view pages of tables, etc) without being logged in.
Any ideas?
I solved the problem (DUH!).
The answer was that the cookie.php config file had $config['domain'] = 'localhost'. Setting this to the actual domain that the app is installed in magically made my life happy again!
Thanks everyone for your help and interest.