Skip to content

Commit 7301a36

Browse files
authored
Verify .vscode folder will be created automatically when extension is activated (#2411)
1 parent acccf52 commit 7301a36

File tree

10 files changed

+167
-91
lines changed

10 files changed

+167
-91
lines changed

test/smoke/suites/activation.test.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,13 @@ export function startExtensionActivationTests(): void {
1616
}
1717

1818
async function dispose() {
19-
try {
20-
if (this.currentTest?.state === "failed") {
21-
SmokeTestLogger.info("Test failed, taking screenshot ...");
22-
await screenshots.takeScreenshots(
23-
this.currentTest.parent?.title || "Others",
24-
this.currentTest.title.replace(/\s+/g, "_"),
25-
);
26-
}
27-
} catch (error) {
28-
// Log error when screenshot get error, but not throw exception
29-
SmokeTestLogger.log(`Error with taking screenshot: ${error}`);
19+
if (this.currentTest?.state === "failed") {
20+
SmokeTestLogger.info("Test failed, taking screenshot ...");
21+
await screenshots.takeScreenshots(
22+
this.currentTest.parent?.title || "Others",
23+
this.currentTest.title.replace(/\s+/g, "_"),
24+
);
3025
}
31-
3226
try {
3327
SmokeTestLogger.info(`Dispose test: "${this.currentTest.title}" ...`);
3428
if (app) {

test/smoke/suites/commands.test.ts

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { app, screenshots } from "./main";
77
import * as assert from "assert";
88
import { ElementHelper } from "./helper/elementHelper";
99
import { Element } from "./helper/constants";
10+
import { ComponentHelper } from "./helper/componentHelper";
1011

1112
export function startCommandPaletteTests(): void {
1213
describe("CommandPaletteTest", () => {
@@ -16,19 +17,13 @@ export function startCommandPaletteTests(): void {
1617
}
1718

1819
async function dispose() {
19-
try {
20-
if (this.currentTest?.state === "failed") {
21-
SmokeTestLogger.info("Test failed, taking screenshot ...");
22-
await screenshots.takeScreenshots(
23-
this.currentTest.parent?.title || "Others",
24-
this.currentTest.title.replace(/\s+/g, "_"),
25-
);
26-
}
27-
} catch (error) {
28-
// Log error when screenshot get error, but not throw exception
29-
SmokeTestLogger.log(`Error with taking screenshot: ${error}`);
20+
if (this.currentTest?.state === "failed") {
21+
SmokeTestLogger.info("Test failed, taking screenshot ...");
22+
await screenshots.takeScreenshots(
23+
this.currentTest.parent?.title || "Others",
24+
this.currentTest.title.replace(/\s+/g, "_"),
25+
);
3026
}
31-
3227
try {
3328
SmokeTestLogger.info(`Dispose test: "${this.currentTest.title}" ...`);
3429
if (app) {
@@ -45,7 +40,7 @@ export function startCommandPaletteTests(): void {
4540
const text = "React Native: Start Packager";
4641
await initApp();
4742

48-
await ElementHelper.openCommandPalette();
43+
await ComponentHelper.openCommandPalette();
4944
await ElementHelper.WaitElementClassNameVisible(Element.commandPaletteClassName, 5000);
5045

5146
await ElementHelper.inputText(text);
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for details.
3+
4+
import { Page } from "playwright";
5+
import { SmokeTestLogger } from "./helper/smokeTestLogger";
6+
import { app, screenshots } from "./main";
7+
import { CommonHelper } from "./helper/commonHelper";
8+
import { ComponentHelper } from "./helper/componentHelper";
9+
import assert = require("assert");
10+
11+
export function startFileExplorerTests(): void {
12+
describe("FileExplorerTest", () => {
13+
async function initApp(): Promise<Page> {
14+
await app.launch();
15+
return app.getMainPage();
16+
}
17+
18+
async function dispose() {
19+
if (this.currentTest?.state === "failed") {
20+
SmokeTestLogger.info("Test failed, taking screenshot ...");
21+
await screenshots.takeScreenshots(
22+
this.currentTest.parent?.title || "Others",
23+
this.currentTest.title.replace(/\s+/g, "_"),
24+
);
25+
}
26+
try {
27+
SmokeTestLogger.info(`Dispose test: "${this.currentTest.title}" ...`);
28+
if (app) {
29+
await app.close();
30+
}
31+
} catch (error) {
32+
SmokeTestLogger.error(`Error while dispose: ${error}`);
33+
}
34+
}
35+
36+
afterEach(dispose);
37+
38+
it("Verify .vscode folder will be created when extension is activated", async () => {
39+
const projectName = "sampleReactNativeProject";
40+
const folderName = ".vscode";
41+
await CommonHelper.findAndDeleteVSCodeSettingsDirectory(projectName);
42+
43+
await initApp();
44+
45+
await ComponentHelper.openFileExplorer();
46+
const folder = await ComponentHelper.WaitFileVisibleInFileExplorer(folderName);
47+
48+
assert.notStrictEqual(folder, null);
49+
});
50+
});
51+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import * as fs from "fs";
2+
import * as rimraf from "rimraf";
3+
import * as path from "path";
4+
import { SmokeTestLogger } from "./smokeTestLogger";
5+
6+
export class CommonHelper {
7+
public static async findAndDeleteDirectory(projectPath: string): Promise<void> {
8+
const isExisting = await this.isDirectoryExisting(projectPath);
9+
if (isExisting) {
10+
try {
11+
rimraf.sync(projectPath);
12+
SmokeTestLogger.log(`Complete to delete target dir: ${projectPath}`);
13+
} catch (error) {
14+
throw new Error(`Fail to delete target dir: ${projectPath}`);
15+
}
16+
}
17+
}
18+
19+
public static async isDirectoryExisting(projectPath: string): Promise<boolean> {
20+
if (fs.existsSync(projectPath)) {
21+
SmokeTestLogger.log(`Target dir is existing: ${projectPath}`);
22+
return true;
23+
} else {
24+
SmokeTestLogger.log(`Target dir is not existing: ${projectPath}`);
25+
return false;
26+
}
27+
}
28+
29+
public static async findAndDeleteVSCodeSettingsDirectory(projectName: string): Promise<void> {
30+
const projectPath = path.join(__dirname, "..", "..", "resources", projectName, ".vscode");
31+
await this.findAndDeleteDirectory(projectPath);
32+
}
33+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { ElementHandle, Page } from "playwright";
2+
import { app } from "../main";
3+
import { ElementHelper } from "./elementHelper";
4+
import { Element } from "./constants";
5+
import { SmokeTestLogger } from "./smokeTestLogger";
6+
7+
export class ComponentHelper {
8+
static setPage(): Page {
9+
const application = app;
10+
return application.getMainPage();
11+
}
12+
13+
public static async openCommandPalette() {
14+
const cmdKey = process.platform === "darwin" ? "Meta" : "Control";
15+
await ElementHelper.sendKeys(`${cmdKey}+Shift+P`);
16+
}
17+
18+
public static async openFileExplorer() {
19+
try {
20+
await ElementHelper.WaitElementSelectorVisible(`[id="${Element.fileExplorerViewId}"]`);
21+
SmokeTestLogger.log("File explorer view is already opened.");
22+
} catch {
23+
const explorerIcon = await ElementHelper.WaitElementSelectorVisible(
24+
Element.fileExplorerIconSelector,
25+
);
26+
explorerIcon.click();
27+
await ElementHelper.WaitElementSelectorVisible(
28+
`[id="${Element.fileExplorerViewId}"]`,
29+
2000,
30+
);
31+
}
32+
}
33+
34+
public static async WaitFileVisibleInFileExplorer(
35+
fileName: string,
36+
): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
37+
try {
38+
return await ElementHelper.WaitElementSelectorVisible(
39+
`[aria-label="${fileName}"]`,
40+
2000,
41+
);
42+
} catch {
43+
return null;
44+
}
45+
}
46+
}

test/smoke/suites/helper/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ export class Element {
77
public static vscodeWorkbenchClassName = "monaco-workbench";
88
public static commandPaletteClassName = "quick-input-widget";
99
public static commandPaletteFocusedItemSelector = "#quickInput_list .monaco-list-row.focused";
10+
public static fileExplorerIconSelector = ".action-label.codicon.codicon-explorer-view-icon";
11+
public static fileExplorerViewId = "workbench.view.explorer";
1012
}

test/smoke/suites/helper/elementHelper.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,33 @@ export class ElementHelper {
77
return application.getMainPage();
88
}
99

10-
public static async openCommandPalette() {
11-
const cmdKey = process.platform === "darwin" ? "Meta" : "Control";
12-
await this.setPage().keyboard.press(`${cmdKey}+Shift+P`);
13-
}
14-
1510
public static async inputText(input: string) {
1611
await this.setPage().keyboard.type(input);
1712
}
1813

14+
public static async sendKeys(keys: string) {
15+
await this.setPage().keyboard.press(keys);
16+
}
17+
1918
public static async WaitElementClassNameVisible(
2019
className: string,
21-
timeout: number,
20+
timeout: number = 1000,
2221
): Promise<ElementHandle<SVGElement | HTMLElement>> {
2322
const element = await this.setPage().waitForSelector(`.${className}`, { timeout: timeout });
2423
return element;
2524
}
2625

2726
public static async WaitElementIdVisible(
2827
id: string,
29-
timeout: number,
28+
timeout: number = 1000,
3029
): Promise<ElementHandle<SVGElement | HTMLElement>> {
3130
const element = await this.setPage().waitForSelector(`#${id}`, { timeout: timeout });
3231
return element;
3332
}
3433

3534
public static async WaitElementSelectorVisible(
3635
selector: string,
37-
timeout: number,
36+
timeout: number = 1000,
3837
): Promise<ElementHandle<SVGElement | HTMLElement>> {
3938
const element = await this.setPage().waitForSelector(selector, { timeout: timeout });
4039
return element;

test/smoke/suites/helper/screenshot.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as fs from "fs";
22
import * as mkdirp from "mkdirp";
33
import * as path from "path";
44
import { app } from "../main";
5+
import { SmokeTestLogger } from "./smokeTestLogger";
56

67
export class Screenshots {
78
private application = app;
@@ -30,12 +31,17 @@ export class Screenshots {
3031
}
3132

3233
async takeScreenshots(suiteName: string, fileName: string): Promise<void> {
33-
const platform = await this.prepareScreenshotFolderForPlatform();
34+
try {
35+
const platform = await this.prepareScreenshotFolderForPlatform();
3436

35-
const mainPage = this.application.getMainPage();
36-
await mainPage.screenshot({
37-
path: `screenshots/${platform}/${suiteName}/${fileName}.jpg`,
38-
fullPage: true,
39-
});
37+
const mainPage = this.application.getMainPage();
38+
await mainPage.screenshot({
39+
path: `screenshots/${platform}/${suiteName}/${fileName}.jpg`,
40+
fullPage: true,
41+
});
42+
} catch (error) {
43+
// Log error when screenshot get error, but not throw exception
44+
SmokeTestLogger.log(`Error with taking screenshot: ${error}`);
45+
}
4046
}
4147
}

test/smoke/suites/helper/utilities.ts

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -182,58 +182,6 @@ export function findStringInFile(filePath: string, strToFind: string): boolean {
182182
return false;
183183
}
184184

185-
export async function findStringInFileWithTimeout(
186-
filePath: string,
187-
strToFind: string,
188-
timeout?: number,
189-
): Promise<boolean> {
190-
const condition = () => findStringInFile(filePath, strToFind);
191-
return waitUntil(condition, timeout, 3000);
192-
}
193-
194-
export function retrieveStringsFromLogFile(
195-
filePath: string,
196-
pattern: RegExp,
197-
): RegExpMatchArray | null {
198-
if (fs.existsSync(filePath)) {
199-
const content = fs.readFileSync(filePath).toString().trim();
200-
return content.match(pattern);
201-
}
202-
return null;
203-
}
204-
205-
export async function retrieveStringsFromLogFileWithTimeout(
206-
filePath: string,
207-
pattern: RegExp,
208-
timeout?: number,
209-
): Promise<RegExpMatchArray | null> {
210-
let result: RegExpMatchArray | null = null;
211-
const condition = () => {
212-
result = retrieveStringsFromLogFile(filePath, pattern);
213-
return !!result;
214-
};
215-
await waitUntil(condition, timeout, 3000);
216-
return result;
217-
}
218-
219-
export function objectsContains(object: any, subObject: any): boolean {
220-
for (let i = 0; i < Object.keys(subObject).length; i++) {
221-
const key = Object.keys(subObject)[i];
222-
if (typeof subObject[key] === "object" && subObject[key] !== null) {
223-
if (typeof object[key] === "object" && object[key] !== null) {
224-
if (!objectsContains(object[key], subObject[key])) {
225-
return false;
226-
}
227-
} else {
228-
return false;
229-
}
230-
} else if (subObject[key] !== object[key]) {
231-
return false;
232-
}
233-
}
234-
return true;
235-
}
236-
237185
export function waitUntil(
238186
condition: () => boolean,
239187
timeout: number = 30000,

test/smoke/suites/smoke.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import { startExtensionActivationTests } from "./activation.test";
55
import { startCommandPaletteTests } from "./commands.test";
6+
import { startFileExplorerTests } from "./fileExplorer.test";
67
import { SmokeTestLogger } from "./helper/smokeTestLogger";
78
import { smokeTestFail } from "./helper/utilities";
89

@@ -26,5 +27,6 @@ export function startSmokeTests(setup: () => Promise<void>, cleanUp: () => Promi
2627
startExtensionActivationTests();
2728

2829
startCommandPaletteTests();
30+
startFileExplorerTests();
2931
});
3032
}

0 commit comments

Comments
 (0)