304 lines
9.3 KiB
JavaScript
304 lines
9.3 KiB
JavaScript
import { start } from '@gitlab/web-ide';
|
|
import { GITLAB_WEB_IDE_FEEDBACK_ISSUE } from '~/ide/constants';
|
|
import { initGitlabWebIDE } from '~/ide/init_gitlab_web_ide';
|
|
import { handleTracking, handleUpdateUrl } from '~/ide/lib/gitlab_web_ide';
|
|
import Tracking from '~/tracking';
|
|
import { TEST_HOST } from 'helpers/test_constants';
|
|
import setWindowLocation from 'helpers/set_window_location_helper';
|
|
import { renderWebIdeError } from '~/ide/render_web_ide_error';
|
|
import { getMockCallbackUrl } from './helpers';
|
|
|
|
jest.mock('@gitlab/web-ide');
|
|
jest.mock('~/lib/utils/csrf', () => ({
|
|
token: 'mock-csrf-token',
|
|
headerKey: 'mock-csrf-header',
|
|
}));
|
|
jest.mock('~/tracking');
|
|
jest.mock('~/ide/render_web_ide_error');
|
|
|
|
const ROOT_ELEMENT_ID = 'ide';
|
|
const TEST_NONCE = 'test123nonce';
|
|
const TEST_USERNAME = 'lipsum';
|
|
const TEST_PROJECT_PATH = 'group1/project1';
|
|
const TEST_BRANCH_NAME = '12345-foo-patch';
|
|
const TEST_USER_PREFERENCES_PATH = '/user/preferences';
|
|
const TEST_GITLAB_WEB_IDE_PUBLIC_PATH = 'test/webpack/assets/gitlab-web-ide/public/path';
|
|
const TEST_FILE_PATH = 'foo/README.md';
|
|
const TEST_MR_ID = '7';
|
|
const TEST_MR_TARGET_PROJECT = 'gitlab-org/the-real-gitlab';
|
|
const TEST_SIGN_IN_PATH = 'sign-in';
|
|
const TEST_SIGN_OUT_PATH = 'sign-out';
|
|
const TEST_FORK_INFO = { fork_path: '/forky' };
|
|
const TEST_EXTENSIONS_GALLERY_SETTINGS = {
|
|
enabled: true,
|
|
vscode_settings: {
|
|
item_url: 'https://gitlab.test/vscode/marketplace/item/url',
|
|
service_url: 'https://gitlab.test/vscode/marketplace/service/url',
|
|
},
|
|
};
|
|
const TEST_EDITOR_FONT_SRC_URL = 'http://gitlab.test/assets/gitlab-mono/GitLabMono.woff2';
|
|
const TEST_EDITOR_FONT_FORMAT = 'woff2';
|
|
const TEST_EDITOR_FONT_FAMILY = 'GitLab Mono';
|
|
|
|
const TEST_OAUTH_CLIENT_ID = 'oauth-client-id-123abc';
|
|
const TEST_OAUTH_CALLBACK_URL = getMockCallbackUrl();
|
|
|
|
describe('ide/init_gitlab_web_ide', () => {
|
|
const createRootElement = () => {
|
|
const el = document.createElement('div');
|
|
|
|
el.id = ROOT_ELEMENT_ID;
|
|
// why: We'll test that this class is removed later
|
|
el.classList.add('test-class');
|
|
el.dataset.projectPath = TEST_PROJECT_PATH;
|
|
el.dataset.cspNonce = TEST_NONCE;
|
|
el.dataset.branchName = TEST_BRANCH_NAME;
|
|
el.dataset.userPreferencesPath = TEST_USER_PREFERENCES_PATH;
|
|
el.dataset.mergeRequest = TEST_MR_ID;
|
|
el.dataset.filePath = TEST_FILE_PATH;
|
|
el.dataset.editorFont = JSON.stringify({
|
|
fallback_font_family: 'monospace',
|
|
font_faces: [
|
|
{
|
|
family: TEST_EDITOR_FONT_FAMILY,
|
|
src: [
|
|
{
|
|
url: TEST_EDITOR_FONT_SRC_URL,
|
|
format: TEST_EDITOR_FONT_FORMAT,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
});
|
|
el.dataset.signInPath = TEST_SIGN_IN_PATH;
|
|
el.dataset.signOutPath = TEST_SIGN_OUT_PATH;
|
|
|
|
document.body.append(el);
|
|
};
|
|
const findRootElement = () => document.getElementById(ROOT_ELEMENT_ID);
|
|
const createSubject = () => initGitlabWebIDE(findRootElement());
|
|
|
|
beforeEach(() => {
|
|
gon.current_username = TEST_USERNAME;
|
|
gon.features = { webIdeLanguageServer: true };
|
|
process.env.GITLAB_WEB_IDE_PUBLIC_PATH = TEST_GITLAB_WEB_IDE_PUBLIC_PATH;
|
|
|
|
createRootElement();
|
|
});
|
|
|
|
afterEach(() => {
|
|
document.body.innerHTML = '';
|
|
});
|
|
|
|
describe('default', () => {
|
|
const telemetryEnabled = true;
|
|
|
|
beforeEach(() => {
|
|
Tracking.enabled.mockReturnValueOnce(telemetryEnabled);
|
|
|
|
createSubject();
|
|
});
|
|
|
|
it('calls start with element', () => {
|
|
expect(start).toHaveBeenCalledTimes(1);
|
|
expect(start).toHaveBeenCalledWith(findRootElement(), {
|
|
baseUrl: `${TEST_HOST}/${TEST_GITLAB_WEB_IDE_PUBLIC_PATH}`,
|
|
projectPath: TEST_PROJECT_PATH,
|
|
ref: TEST_BRANCH_NAME,
|
|
filePath: TEST_FILE_PATH,
|
|
mrId: TEST_MR_ID,
|
|
mrTargetProject: '',
|
|
forkInfo: null,
|
|
username: gon.current_username,
|
|
gitlabUrl: TEST_HOST,
|
|
nonce: TEST_NONCE,
|
|
httpHeaders: {
|
|
'mock-csrf-header': 'mock-csrf-token',
|
|
'X-Requested-With': 'XMLHttpRequest',
|
|
},
|
|
links: {
|
|
userPreferences: TEST_USER_PREFERENCES_PATH,
|
|
feedbackIssue: GITLAB_WEB_IDE_FEEDBACK_ISSUE,
|
|
signIn: TEST_SIGN_IN_PATH,
|
|
},
|
|
featureFlags: {
|
|
crossOriginExtensionHost: false,
|
|
languageServerWebIDE: gon.features.webIdeLanguageServer,
|
|
},
|
|
editorFont: {
|
|
fallbackFontFamily: 'monospace',
|
|
fontFaces: [
|
|
{
|
|
family: TEST_EDITOR_FONT_FAMILY,
|
|
src: [
|
|
{
|
|
url: TEST_EDITOR_FONT_SRC_URL,
|
|
format: TEST_EDITOR_FONT_FORMAT,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
handleTracking,
|
|
telemetryEnabled,
|
|
handleContextUpdate: handleUpdateUrl,
|
|
});
|
|
});
|
|
|
|
it('clears classes and data from root element', () => {
|
|
const rootEl = findRootElement();
|
|
|
|
// why: Snapshot to test that the element was cleaned including `test-class`
|
|
expect(rootEl.outerHTML).toBe(
|
|
'<div id="ide" class="gl-flex gl-justify-center gl-items-center gl-relative gl-h-full"></div>',
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('when URL has target_project in query params', () => {
|
|
beforeEach(() => {
|
|
setWindowLocation(
|
|
`https://example.com/-/ide?target_project=${encodeURIComponent(TEST_MR_TARGET_PROJECT)}`,
|
|
);
|
|
|
|
createSubject();
|
|
});
|
|
|
|
it('includes mrTargetProject', () => {
|
|
expect(start).toHaveBeenCalledWith(
|
|
findRootElement(),
|
|
expect.objectContaining({
|
|
mrTargetProject: TEST_MR_TARGET_PROJECT,
|
|
}),
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('when forkInfo is in dataset', () => {
|
|
beforeEach(() => {
|
|
findRootElement().dataset.forkInfo = JSON.stringify(TEST_FORK_INFO);
|
|
|
|
createSubject();
|
|
});
|
|
|
|
it('includes forkInfo', () => {
|
|
expect(start).toHaveBeenCalledWith(
|
|
findRootElement(),
|
|
expect.objectContaining({
|
|
forkInfo: TEST_FORK_INFO,
|
|
}),
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('when oauth info is in dataset', () => {
|
|
beforeEach(() => {
|
|
findRootElement().dataset.clientId = TEST_OAUTH_CLIENT_ID;
|
|
findRootElement().dataset.callbackUrls = [TEST_OAUTH_CALLBACK_URL];
|
|
|
|
createSubject();
|
|
});
|
|
|
|
it('calls start with element', () => {
|
|
expect(start).toHaveBeenCalledTimes(1);
|
|
expect(start).toHaveBeenCalledWith(
|
|
findRootElement(),
|
|
expect.objectContaining({
|
|
auth: {
|
|
type: 'oauth',
|
|
clientId: TEST_OAUTH_CLIENT_ID,
|
|
callbackUrl: TEST_OAUTH_CALLBACK_URL,
|
|
protectRefreshToken: true,
|
|
},
|
|
httpHeaders: undefined,
|
|
}),
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('on start error', () => {
|
|
const mockError = new Error('error');
|
|
|
|
beforeEach(() => {
|
|
jest.mocked(start).mockImplementationOnce(() => {
|
|
throw mockError;
|
|
});
|
|
|
|
createSubject();
|
|
});
|
|
|
|
it('shows alert', () => {
|
|
expect(start).toHaveBeenCalledTimes(1);
|
|
expect(renderWebIdeError).toHaveBeenCalledTimes(1);
|
|
expect(renderWebIdeError).toHaveBeenCalledWith({
|
|
error: mockError,
|
|
signOutPath: TEST_SIGN_OUT_PATH,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('when extensionsGallerySettings is in dataset', () => {
|
|
function setMockExtensionGallerySettingsDataset(
|
|
mockSettings = TEST_EXTENSIONS_GALLERY_SETTINGS,
|
|
) {
|
|
findRootElement().dataset.extensionsGallerySettings = JSON.stringify(mockSettings);
|
|
|
|
createSubject();
|
|
}
|
|
|
|
it('calls start with element and extensionsGallerySettings', () => {
|
|
setMockExtensionGallerySettingsDataset();
|
|
expect(start).toHaveBeenCalledTimes(1);
|
|
expect(start).toHaveBeenCalledWith(
|
|
findRootElement(),
|
|
expect.objectContaining({
|
|
extensionsGallerySettings: {
|
|
enabled: true,
|
|
vscodeSettings: {
|
|
itemUrl: 'https://gitlab.test/vscode/marketplace/item/url',
|
|
serviceUrl: 'https://gitlab.test/vscode/marketplace/service/url',
|
|
},
|
|
},
|
|
}),
|
|
);
|
|
});
|
|
|
|
it('calls start with element and crossOriginExtensionHost flag if extensionsGallerySettings is enabled', () => {
|
|
setMockExtensionGallerySettingsDataset();
|
|
expect(start).toHaveBeenCalledTimes(1);
|
|
expect(start).toHaveBeenCalledWith(
|
|
findRootElement(),
|
|
expect.objectContaining({
|
|
featureFlags: {
|
|
crossOriginExtensionHost: true,
|
|
languageServerWebIDE: gon.features.webIdeLanguageServer,
|
|
},
|
|
}),
|
|
);
|
|
});
|
|
|
|
it.each(['opt_in_unset', 'opt_in_disabled'])(
|
|
'calls start with element and crossOriginExtensionHost flag if extensionsGallerySettings reason is $reason',
|
|
(reason) => {
|
|
const TEST_EXTENSIONS_GALLERY_SETTINGS_WITH_REASON = {
|
|
...TEST_EXTENSIONS_GALLERY_SETTINGS,
|
|
enabled: false,
|
|
reason,
|
|
};
|
|
setMockExtensionGallerySettingsDataset(TEST_EXTENSIONS_GALLERY_SETTINGS_WITH_REASON);
|
|
|
|
expect(start).toHaveBeenCalledTimes(1);
|
|
expect(start).toHaveBeenCalledWith(
|
|
findRootElement(),
|
|
expect.objectContaining({
|
|
featureFlags: {
|
|
crossOriginExtensionHost: true,
|
|
languageServerWebIDE: gon.features.webIdeLanguageServer,
|
|
},
|
|
}),
|
|
);
|
|
},
|
|
);
|
|
});
|
|
});
|