Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hosted VS Code Web #85

Open
jan872 opened this issue Oct 20, 2023 · 6 comments
Open

Hosted VS Code Web #85

jan872 opened this issue Oct 20, 2023 · 6 comments
Labels
documentation Improvements or additions to documentation help wanted Extra attention is needed

Comments

@jan872
Copy link

jan872 commented Oct 20, 2023

I would like to run tests against a VS Code instances that is hosted in my cloud (similar to vscode.dev).
So it would be great, if I could stop the testrunner from starting vscode web locally, but rather point it towards my (already running) instance.
I did not find a way to do this, but there seemed to be some preparation in the code for this use case.

The variable _vscodeServerPort in VSCodeServiceLauncher is checked before starting the server:

      /**
         * no need to do any work if we already started the server
         */
        if (this._vscodeServerPort || !cap[VSCODE_CAPABILITY_KEY]) {
            return
        }

but _vscodeServerPort is never set anywhere.

So my proposal would be:

-- a/src/launcher.ts
+++ b/src/launcher.ts
@@ -56,6 +56,7 @@ export default class VSCodeServiceLauncher extends ChromedriverServiceLauncher {
     ) {
         super(_options, _capabilities, config)
         this._cachePath = this._options.cachePath || DEFAULT_CACHE_PATH
+        this._vscodeServerPort = this._capabilities[VSCODE_CAPABILITY_KEY]?.serverOptions?.port
         this._mapCapabilities = () => {}
     }

Is this viable?

@christian-bromann
Copy link
Contributor

@jan872 thanks for raising the issue. I think it makes total sense to also allow that.

How is the extension installed on the hosted VS Code instance?

Depending on this answer we need to decide what to do with the extensionPath option.

@jan872
Copy link
Author

jan872 commented Oct 20, 2023

I our case the extension is already installed - outside the actual test run. So I have no good idea what do with the extensionPath

@christian-bromann
Copy link
Contributor

I think in this case it doesn't really make sense to use the service because all the VS Code extension setup is not needed. You can just run a normal WebdriverIO session and only use the page objects. Would that work?

@jan872
Copy link
Author

jan872 commented Oct 20, 2023

Yes, that was my first thought. But I was not able to instantiate the page objects without properly starting wdio-vscode-service.
So a hint on how to do this would be greatly appreciated. Sorry, I am just not very well versed in javascript.

@christian-bromann
Copy link
Contributor

I am not sure when I get the time to look into this, therefor we greatly appreciate any contributions that help resolve the bug. While we understand that active contributors have their own priorities, we kindly request your assistance if you rely on this bug being fixed. We encourage you to take a look at our contribution guidelines or join our friendly Discord development server, where you can ask any questions you may have. Thank you for your support, and cheers!

@christian-bromann christian-bromann added the help wanted Extra attention is needed label Nov 28, 2023
@seanpoulter seanpoulter added the documentation Improvements or additions to documentation label Mar 6, 2024
@mprotasov
Copy link

I was able to run wdio tests for hosted VS Code instance (our target environment is coder/code-server) following @christian-bromann advice to use just page object, without vscode service

Since I need to run suites for both desktop and browser (hosted instance), I have two conf files - in my case wdio.conf.electron.ts and wdio.conf.browser.ts

wdio.conf.electron.ts is almost fully generated by cli (as described in docs), with capabilities and services for VS Code

capabilities: [{
    browserName: 'vscode',
    browserVersion: '1.87.2',
    'wdio:vscodeOptions': {
      extensionPath: extensionDir,
    }
  }],
  services: ['vscode'],

wdio.conf.browser.ts doesn't contain config for VS Code:

capabilities: [{
    browserName: 'chrome'
  }],
services: [],

Then, we need to initialize Workbench for hosted VS Code. I've placed that code in util function, which I call in before block (I use mocha)

Few notes:

  • wdio-vscode-service has function getLocators, but unfortunately it is not exported as public API, so I have to copy-paste it
  • In actual code I pass version in runnerEnv arguments from configuration, but for simplicity it is hardcoded here
  • Path of locators should be changed according to actual project structure
import fs from 'node:fs/promises';
import * as path from 'path';
import { VSCodeLocatorMap, Workbench } from 'wdio-vscode-service';
import { fileURLToPath } from 'url';
import { expect } from '@wdio/globals';

export function prepareBrowserForVSCode(): void {
  browser.getWorkbench = async () => {
    // In actual code I pass version in runnerEnv arguments from configuration, but for simplicity it is hardcoded here
    const vsCodeVersion = '1.87.2';
  
    // __dirname only works in CommonJS modules
    const dirname = path.dirname(fileURLToPath(import.meta.url));

    // Copied with small changes from https://github.com/webdriverio-community/wdio-vscode-service/blob/99fd9a5c32ef540c7778dbca92ad1e7335207975/src/utils.ts#L12
    const locatorFiles = (await fs.readdir(path.join(dirname, '..', 'node_modules', 'wdio-vscode-service', 'dist', 'locators'), { encoding: 'utf-8' }))
      .filter((filename) => filename.endsWith('.js') && !filename.endsWith('.d.ts'))
      .map((filename) => filename.slice(0, -3));

    const [major, minor] = vsCodeVersion.split('.');
    const sanitizedVersion = `${major}.${minor}.0`;

    const locatorFile = locatorFiles.find((f, i) => (
      f === sanitizedVersion
        || (locatorFiles[i + 1] && locatorFiles[i + 1] > sanitizedVersion)
    )) || locatorFiles[locatorFiles.length - 1];

    const locators = await (import(`file://${path.join(dirname, '..', 'node_modules', 'wdio-vscode-service', 'dist', 'locators')}/${locatorFile}.js`) as Promise<VSCodeLocatorMap>);
    return new Workbench(locators);
  };

  browser.getVSCodeChannel = () => Promise.resolve('vscode');
  browser.getVSCodeVersion = () => Promise.resolve(vsCodeVersion);
}}

Then, in suite

describe('Hosted Instance Suite', () => {
  before(() => {
    prepareBrowserForVSCode();
  });
  
  it('should use workbench with locators', async () => {
    // navigate to VS Code in browser, in my case it is located on localhost:8081
    await browser.url('localhost:8081');
	
    // wait for workbench to load
    await browser.waitUntil(async () => {
        const w = await browser.getWorkbench();
        return w;
    });
	
    // We can use it now
    const workbench = await browser.getWorkbench();
    const editor = workbench.getEditorView();
  });
});

I assume that it is not the cleanest solution, but it worked for me. Please, let me know if there is a way to do it better, I would be happy to get rid of 'hacks' :)

Hope it helps someone!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

4 participants