Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/core-browser/src/layout/layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export class ComponentRegistryImpl implements ComponentRegistry {
this.config.layoutConfig[location] = targetLocation;
}
if (targetLocation.modules.indexOf(key) > -1) {
getDebugLogger().warn(`${location}位置已存在${key}模块`);
getDebugLogger().warn(`A ${key} module already exists on the ${location}`);
return;
}
targetLocation.modules.push(key);
Expand Down
2 changes: 1 addition & 1 deletion packages/explorer/src/browser/explorer-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { ComponentContribution, ComponentRegistry } from '@opensumi/ide-core-bro
export { EXPLORER_CONTAINER_ID };

@Domain(ClientAppContribution, ComponentContribution)
export class ExplorerContribution implements ComponentContribution {
export class ExplorerContribution implements ClientAppContribution, ComponentContribution {
@Autowired(IExtensionsPointService)
protected readonly extensionsPointService: IExtensionsPointService;

Expand Down
15 changes: 14 additions & 1 deletion tools/playwright/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Page } from '@playwright/test';

import { Disposable } from '@opensumi/ide-utils';

import { IComponentEditorInfo } from './component-editor';
import { OpenSumiEditor } from './editor';
import { OpenSumiExplorerView } from './explorer-view';
import { OpenSumiMenubar } from './menubar';
Expand Down Expand Up @@ -101,7 +102,7 @@ export class OpenSumiApp extends Disposable {
}

async openEditor<T extends OpenSumiEditor>(
EditorConstruction: new (app: OpenSumiApp, element: OpenSumiTreeNode) => T,
EditorConstruction: new (app: OpenSumiApp, element?: OpenSumiTreeNode) => T,
explorer: OpenSumiExplorerView,
filePath: string,
preview = true,
Expand All @@ -115,6 +116,18 @@ export class OpenSumiApp extends Disposable {
return editor;
}

// use for component editors
async openComponentEditor<T extends OpenSumiEditor>(
EditorConstruction: new (app: OpenSumiApp, info: IComponentEditorInfo) => T,
path: string,
name: string,
containerSelector: string,
) {
const editor = new EditorConstruction(this, { path, name, containerSelector });
await editor.open();
return editor;
}

async waitForInitialized(): Promise<void> {
// custom app initialize process.
// empty by default
Expand Down
64 changes: 64 additions & 0 deletions tools/playwright/src/component-editor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { OpenSumiApp } from './app';
import { OpenSumiContextMenu } from './context-menu';
import { OpenSumiEditor } from './editor';
import { isElementVisible } from './utils';

export interface IComponentEditorInfo {
path: string;
name: string;
containerSelector: string;
}

export class OpenSumiComponentEditor extends OpenSumiEditor {
constructor(app: OpenSumiApp, private readonly info: IComponentEditorInfo) {
super(app);
}

async openTabContextMenu() {
const view = await this.getTab();
if (!view) {
return;
}
return OpenSumiContextMenu.open(this.app, async () => view);
}

async close() {
const contextMenu = await this.openTabContextMenu();
await contextMenu?.isOpen();
const close = await contextMenu?.menuItemByName('Close');
await close?.click();
}

async getTab() {
const tabsItems = await (await this.getTabElement())?.$$("[class*='kt_editor_tab___']");

if (!tabsItems) {
return;
}

for (const item of tabsItems) {
const uri = await item.getAttribute('data-uri');
if (uri?.includes(this.info.path)) {
return item;
}
}
}

async getContainer() {
return await super.getContainer(this.info.containerSelector);
}

async isVisible() {
const container = await this.getContainer();
if (!container) {
return false;
}
return await isElementVisible(Promise.resolve(container));
}

async open() {
const tab = await this.getTab();
await tab?.click();
return this;
}
}
14 changes: 11 additions & 3 deletions tools/playwright/src/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { OpenSumiExplorerFileStatNode } from './explorer-view';
import { OpenSumiView } from './view';

export class OpenSumiEditor extends OpenSumiView {
constructor(app: OpenSumiApp, private readonly filestatElement: OpenSumiExplorerFileStatNode) {
constructor(app: OpenSumiApp, private readonly filestatElement?: OpenSumiExplorerFileStatNode) {
super(app, {
tabSelector: `#${OPENSUMI_VIEW_CONTAINERS.EDITOR_TABS}`,
viewSelector: `#${OPENSUMI_VIEW_CONTAINERS.EDITOR}`,
Expand All @@ -13,7 +13,7 @@ export class OpenSumiEditor extends OpenSumiView {
}

async getTab() {
const path = (await this.filestatElement.getFsPath()) || '';
const path = (await this.filestatElement?.getFsPath()) || '';
const tabsItems = await (await this.getTabElement())?.$$("[class*='kt_editor_tab___']");

if (!tabsItems) {
Expand All @@ -28,12 +28,20 @@ export class OpenSumiEditor extends OpenSumiView {
}
}

async getContainer(selector?: string) {
if (!selector) {
return;
}
const container = await (await this.getViewElement())?.$(selector);
return container;
}

async getCurrentTab() {
return await (await this.getTabElement())?.waitForSelector("[class*='kt_editor_tab_current___']");
}

async open(preview?: boolean) {
await this.filestatElement.open(preview);
await this.filestatElement?.open(preview);
// waiting editor render, it maybe fail while opening a large file.
await this.app.page.waitForTimeout(1000);
return this;
Expand Down
2 changes: 1 addition & 1 deletion tools/playwright/src/menu-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class OpenSumiMenuItem {

async click() {
const action = await this.element.waitForSelector("[class*='menuAction__']");
action.click({ position: { x: 10, y: 10 } });
await action?.click({ position: { x: 10, y: 10 } });
}

async hover(): Promise<void> {
Expand Down
118 changes: 118 additions & 0 deletions tools/playwright/src/tests/keymaps.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import path from 'path';

import { expect } from '@playwright/test';

import { OpenSumiApp } from '../app';
import { OpenSumiComponentEditor } from '../component-editor';
import { OPENSUMI_VIEW_CONTAINERS } from '../constans';
import { OpenSumiContextMenu } from '../context-menu';
import { OpenSumiExplorerView } from '../explorer-view';
import { OpenSumiTextEditor } from '../text-editor';
import { keypressWithCmdCtrl } from '../utils';
import { OpenSumiWorkspace } from '../workspace';

import test, { page } from './hooks';

let app: OpenSumiApp;
let explorer: OpenSumiExplorerView;
let workspace: OpenSumiWorkspace;

test.describe('OpenSumi Keyboard Shortcuts', () => {
test.beforeAll(async () => {
workspace = new OpenSumiWorkspace([path.resolve('./src/tests/workspaces/default')]);
app = await OpenSumiApp.load(page, workspace);
explorer = await app.open(OpenSumiExplorerView);
explorer.initFileTreeView(workspace.workspace.displayName);
});

test.afterAll(() => {
app.dispose();
});

const openKeymapsView = async () => {
const leftTabbar = await app.page.waitForSelector(`#${OPENSUMI_VIEW_CONTAINERS.LEFT_TABBAR}`);
const settingsButton = await leftTabbar.$('[class*="titleActions___"] span');
await settingsButton?.click();
const menu = new OpenSumiContextMenu(app);
await menu.clickMenuItem('Keyboard Shortcut');
};

test('open Keyboard Settings by keybinding', async () => {
await explorer.fileTreeView.focus();
await app.page.keyboard.press(keypressWithCmdCtrl('KeyK'), { delay: 200 });
await app.page.keyboard.press(keypressWithCmdCtrl('KeyS'), { delay: 200 });
const editor = await app.openComponentEditor(
OpenSumiComponentEditor,
'keymaps:/',
'Keyboard Shortcuts',
"[class*='keybinding_container___']",
);
expect(await editor.isVisible()).toBeTruthy();
await editor.close();
await app.page.waitForTimeout(1000);
expect(await editor.isVisible()).toBeFalsy();
});

test('open Keyboard Settings by settings button', async () => {
await openKeymapsView();
const editor = await app.openComponentEditor(
OpenSumiComponentEditor,
'keymaps:/',
'Keyboard Shortcuts',
"[class*='keybinding_container___']",
);
expect(await editor.isVisible()).toBeTruthy();
await editor.close();
});

test("change 'Save Current File' keybinding to 'CMD+SHIFT+S'", async () => {
await openKeymapsView();
const editor = await app.openComponentEditor(
OpenSumiComponentEditor,
'keymaps:/',
'Keyboard Shortcuts',
"[class*='keybinding_container___']",
);
expect(await editor.isVisible()).toBeTruthy();
const searchArea = await (await editor.getContainer())?.$('[class*="search_input___"]');
const keyboardButton = await searchArea?.$('[class*="search_inline_action___"] span');
const searchInput = await searchArea?.$('.kt-input-box input');
await keyboardButton?.click();
await searchInput?.focus();
// type 'CMD+S' to filter 'Save Current File' command
await app.page.keyboard.press(keypressWithCmdCtrl('KeyS'), { delay: 200 });

const items = (await (await editor.getContainer())?.$$('[class*="keybinding_list_item__"]')) || [];
let saveFileItem;
for (const item of items) {
const command_name = await (await item.$('[class*="command_name___"]'))?.textContent();
if (command_name === 'Save Current File') {
saveFileItem = item;
break;
}
}
expect(saveFileItem).toBeDefined();
await saveFileItem?.hover();
const edit = await saveFileItem.$('[title="Edit"]');
await edit?.click();
await app.page.keyboard.press(keypressWithCmdCtrl('Shift+KeyS'), { delay: 200 });
await app.page.keyboard.press('Enter');
// varified file save keybinding
const textEditor = await app.openEditor(OpenSumiTextEditor, explorer, 'editor.js');
await textEditor.addTextToNewLineAfterLineByLineNumber(
1,
`const a = 'a';
console.log(a);`,
);
let isDirty = await textEditor.isDirty();
expect(isDirty).toBeTruthy();
await app.page.keyboard.press(keypressWithCmdCtrl('KeyS'), { delay: 200 });
await app.page.waitForTimeout(1000);
isDirty = await textEditor.isDirty();
expect(isDirty).toBeTruthy();
await app.page.keyboard.press(keypressWithCmdCtrl('Shift+KeyS'), { delay: 200 });
await app.page.waitForTimeout(1000);
isDirty = await textEditor.isDirty();
expect(isDirty).toBeFalsy();
});
});
9 changes: 3 additions & 6 deletions tools/playwright/src/text-editor.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { ElementHandle } from '@playwright/test';

import { isMacintosh, isWindows } from '@opensumi/ide-utils';

import { OpenSumiContextMenu } from './context-menu';
import { OpenSumiEditor } from './editor';
import { keypressWithCmdCtrl } from './utils';

export class OpenSumiTextEditor extends OpenSumiEditor {
async openLineContextMenuByLineNumber(lineNumber: number) {
Expand Down Expand Up @@ -161,11 +160,10 @@ export class OpenSumiTextEditor extends OpenSumiEditor {
}

async pasteContentAfterLineByLineNumber(lineNumber: number): Promise<void> {
const modifier = isMacintosh ? 'Meta' : isWindows ? 'Ctrl' : 'Control';
const existingLine = await this.lineByLineNumber(lineNumber);
await this.placeCursorInLine(existingLine);
await this.page.keyboard.press('End');
await this.page.keyboard.press(`${modifier}+KeyV`);
await this.page.keyboard.press(keypressWithCmdCtrl('KeyV'));
}

protected async lineContainingText(text: string): Promise<ElementHandle<SVGElement | HTMLElement> | undefined> {
Expand Down Expand Up @@ -203,9 +201,8 @@ export class OpenSumiTextEditor extends OpenSumiEditor {
async clearContent() {
const line = await this.lineByLineNumber(1);
await line?.click();
const modifier = isMacintosh ? 'Meta' : isWindows ? 'Ctrl' : 'Control';
await this.placeCursorInLine(line);
await this.page.keyboard.press(`${modifier}+KeyA`);
await this.page.keyboard.press(keypressWithCmdCtrl('KeyA'));
await this.page.keyboard.press('Delete');
}
}
1 change: 1 addition & 0 deletions tools/playwright/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './element';
export * from './key';
6 changes: 6 additions & 0 deletions tools/playwright/src/utils/key.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { isMacintosh, isWindows } from '@opensumi/ide-utils';

export const keypressWithCmdCtrl = (key: string) => {
const modifier = isMacintosh ? 'Meta' : isWindows ? 'Ctrl' : 'Control';
return `${modifier}+${key}`;
};