diff --git a/test/smoke/package.json b/test/smoke/package.json index 9ef1a50f778..c8b869205d4 100644 --- a/test/smoke/package.json +++ b/test/smoke/package.json @@ -13,12 +13,14 @@ "@types/webdriverio": "^4.6.1", "@types/electron": "~1.4.37", "@types/rimraf": "^0.0.28", + "@types/htmlparser2": "^3.7.29", "mocha": "^3.2.0", "spectron": "~3.6.4", "typescript": "^2.2.2", "rimraf": "^2.6.1", "commander": "^2.9.0", "simple-git": "^1.73.0", - "strip-json-comments": "^2.0.1" + "strip-json-comments": "^2.0.1", + "htmlparser2": "^3.9.2" } } diff --git a/test/smoke/src/areas/extensions.ts b/test/smoke/src/areas/extensions.ts index 4edec9d06ef..140b1d4d1a6 100644 --- a/test/smoke/src/areas/extensions.ts +++ b/test/smoke/src/areas/extensions.ts @@ -6,9 +6,12 @@ import { SpectronApplication } from '../spectron/application'; import { CommonActions } from "./common"; +var htmlparser = require('htmlparser2'); + export class Extensions { private readonly extensionsViewletSelector = 'div[id="workbench.view.extensions"]'; + private viewletExtensionIndex: number; constructor(private spectron: SpectronApplication, private common: CommonActions) { } @@ -27,12 +30,14 @@ export class Extensions { return this.spectron.client.keys(['NULL', 'Enter', 'NULL']); } - public installFirstResult(): Promise { - return this.spectron.client.click(`${this.extensionsViewletSelector} .monaco-list-rows>:nth-child(1) .extension .extension-action.install`); + public async installExtension(name: string): Promise { + const extensionListSelector = `${this.extensionsViewletSelector} .monaco-list-rows`; + this.viewletExtensionIndex = await this.getExtensionIndex(name, extensionListSelector); + return this.spectron.client.click(`${extensionListSelector}>:nth-child(${this.viewletExtensionIndex}) .extension .extension-action.install`); } - public getFirstReloadText(): Promise { - return this.spectron.waitFor(this.spectron.client.getText, `${this.extensionsViewletSelector} .monaco-list-rows>:nth-child(1) .extension .extension-action.reload`); + public getExtensionReloadText(): Promise { + return this.spectron.waitFor(this.spectron.client.getText, `${this.extensionsViewletSelector} .monaco-list-rows>:nth-child(${this.viewletExtensionIndex}) .extension .extension-action.reload`); } public async selectMinimalIconsTheme(): Promise { @@ -46,4 +51,44 @@ export class Extensions { public async verifyFolderIconAppearance(): Promise { return this.spectron.waitFor(this.spectron.client.getHTML, 'style[class="contributedIconTheme"]'); } + + private getExtensionIndex(name: string, extensionListSelector: string): Promise { + return new Promise(async (res, rej) => { + const html = await this.spectron.waitFor(this.spectron.client.getHTML, extensionListSelector); + let extensionIndex: number = 0; + let extension: boolean; + var domelems:string[] = []; + var parser = new htmlparser.Parser({ + onopentag: function (name, attribs) { + if (name === 'div' && attribs.class === 'extension') { + extensionIndex++; + extension = true; + } + if (extension) { + domelems.push(name); + } + }, + ontext: function (text) { + if (extension && text === name) { + parser.end(); + } + }, + onclosetag: function (name) { + if (extension) { + domelems.pop(); + } + if (extension && domelems.length === 0) { + extension = false; + } + }, + onend: function () { + if (extensionIndex === 0) { + rej(`${name} extension was not found.`); + } + res(extensionIndex); + } + }); + parser.write(html); + }); + } } \ No newline at end of file diff --git a/test/smoke/src/tests/extensions.ts b/test/smoke/src/tests/extensions.ts index b4514372569..37890208d6c 100644 --- a/test/smoke/src/tests/extensions.ts +++ b/test/smoke/src/tests/extensions.ts @@ -14,16 +14,17 @@ var dns = require('dns'); let app: SpectronApplication; let common: CommonActions; -export async function testExtensions() { - const network = await networkAttached(); - if (!network) { - return; - } +export function testExtensions() { context('Extensions', () => { let extensions: Extensions; beforeEach(async function () { + const network = await networkAttached(); + if (!network) { + return Promise.reject('There is no network connection for testing extensions.'); + } + app = new SpectronApplication(LATEST_PATH, this.currentTest.fullTitle(), (this.currentTest as any).currentRetry(), [WORKSPACE_PATH, `--extensions-dir=${EXTENSIONS_DIR}`]); common = new CommonActions(app); extensions = new Extensions(app, common); @@ -37,21 +38,23 @@ export async function testExtensions() { }); it(`installs 'vscode-icons' extension and verifies reload is prompted`, async function () { + const name = 'vscode-icons'; await extensions.openExtensionsViewlet(); - await extensions.searchForExtension('vscode-icons'); + await extensions.searchForExtension(name); await app.wait(); - await extensions.installFirstResult(); + await extensions.installExtension(name); await app.wait(); - assert.ok(await extensions.getFirstReloadText()); + assert.ok(await extensions.getExtensionReloadText(), 'Reload was not prompted after extension installation.'); }); it(`installs an extension and checks if it works on restart`, async function () { + const name = 'vscode-icons'; await extensions.openExtensionsViewlet(); - await extensions.searchForExtension('vscode-icons'); + await extensions.searchForExtension(name); await app.wait(); - await extensions.installFirstResult(); + await extensions.installExtension(name); await app.wait(); - await extensions.getFirstReloadText(); + await extensions.getExtensionReloadText(); await app.stop(); await app.wait(); // wait until all resources are released (e.g. locked local storage)