summaryrefslogtreecommitdiff
path: root/spec/frontend_integration/ide
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-11-30 11:02:35 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-11-30 11:02:35 +0000
commit434a0ce52d75e13d48eac9ce83774954c7c5d48d (patch)
treede3b7a7cf1ce8b07555f28df592297c76894c90f /spec/frontend_integration/ide
parent0a0d9493ca481c56b739a3df27c31262283150fe (diff)
downloadgitlab-ce-334008db1f1929c3ef362c64cee5e6e973bccd70.tar.gz
Add latest changes from gitlab-org/gitlab@13-7-stable-eev13.7.0-rc2
Diffstat (limited to 'spec/frontend_integration/ide')
-rw-r--r--spec/frontend_integration/ide/__snapshots__/ide_integration_spec.js.snap114
-rw-r--r--spec/frontend_integration/ide/helpers/ide_helper.js (renamed from spec/frontend_integration/ide/ide_helper.js)32
-rw-r--r--spec/frontend_integration/ide/helpers/mock_data.js12
-rw-r--r--spec/frontend_integration/ide/ide_integration_spec.js46
-rw-r--r--spec/frontend_integration/ide/user_opens_ide_spec.js163
5 files changed, 211 insertions, 156 deletions
diff --git a/spec/frontend_integration/ide/__snapshots__/ide_integration_spec.js.snap b/spec/frontend_integration/ide/__snapshots__/ide_integration_spec.js.snap
deleted file mode 100644
index 877cc78a111..00000000000
--- a/spec/frontend_integration/ide/__snapshots__/ide_integration_spec.js.snap
+++ /dev/null
@@ -1,114 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`WebIDE runs 1`] = `
-<div>
- <article
- class="ide position-relative d-flex flex-column align-items-stretch"
- >
- <div
- class="ide-view flex-grow d-flex"
- >
- <div
- class="gl-relative multi-file-commit-panel flex-column"
- style="width: 340px;"
- >
- <div
- class="multi-file-commit-panel-inner"
- data-testid="ide-side-bar-inner"
- >
- <div
- class="multi-file-loading-container"
- >
- <div
- class="animation-container"
- >
- <div
- class="skeleton-line-1"
- />
- <div
- class="skeleton-line-2"
- />
- <div
- class="skeleton-line-3"
- />
- </div>
- </div>
- <div
- class="multi-file-loading-container"
- >
- <div
- class="animation-container"
- >
- <div
- class="skeleton-line-1"
- />
- <div
- class="skeleton-line-2"
- />
- <div
- class="skeleton-line-3"
- />
- </div>
- </div>
- <div
- class="multi-file-loading-container"
- >
- <div
- class="animation-container"
- >
- <div
- class="skeleton-line-1"
- />
- <div
- class="skeleton-line-2"
- />
- <div
- class="skeleton-line-3"
- />
- </div>
- </div>
- </div>
- <div
- class="position-absolute position-top-0 position-bottom-0 drag-handle position-right-0"
- size="340"
- style="cursor: ew-resize;"
- />
- </div>
- <div
- class="multi-file-edit-pane"
- >
- <div
- class="ide-empty-state"
- >
- <div
- class="row js-empty-state"
- >
- <div
- class="col-12"
- >
- <div
- class="svg-content svg-250"
- >
- <img
- src="/test/empty_state.svg"
- />
- </div>
- </div>
- <div
- class="col-12"
- >
- <div
- class="text-content text-center"
- >
- <h4>
- Make and review changes in the browser with the Web IDE
- </h4>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </article>
-</div>
-`;
diff --git a/spec/frontend_integration/ide/ide_helper.js b/spec/frontend_integration/ide/helpers/ide_helper.js
index fea8bc24031..7ace586fe08 100644
--- a/spec/frontend_integration/ide/ide_helper.js
+++ b/spec/frontend_integration/ide/helpers/ide_helper.js
@@ -1,4 +1,8 @@
+import { TEST_HOST } from 'helpers/test_constants';
import { findAllByText, fireEvent, getByLabelText, screen } from '@testing-library/dom';
+import { initIde } from '~/ide';
+import extendStore from '~/ide/stores/extend';
+import { IDE_DATASET } from './mock_data';
const isFolderRowOpen = row => row.matches('.folder.is-open');
@@ -12,16 +16,23 @@ const clickOnLeftSidebarTab = name => {
button.click();
};
-const findMonacoEditor = () =>
+export const findMonacoEditor = () =>
screen.findByLabelText(/Editor content;/).then(x => x.closest('.monaco-editor'));
-const findAndSetEditorValue = async value => {
+export const findAndSetEditorValue = async value => {
const editor = await findMonacoEditor();
const uri = editor.getAttribute('data-uri');
window.monaco.editor.getModel(uri).setValue(value);
};
+export const getEditorValue = async () => {
+ const editor = await findMonacoEditor();
+ const uri = editor.getAttribute('data-uri');
+
+ return window.monaco.editor.getModel(uri).getValue();
+};
+
const findTreeBody = () => screen.findByTestId('ide-tree-body', {}, { timeout: 5000 });
const findRootActions = () => screen.findByTestId('ide-root-actions', {}, { timeout: 7000 });
@@ -107,6 +118,10 @@ export const createFile = async (path, content) => {
await findAndSetEditorValue(content);
};
+export const getFilesList = () => {
+ return screen.getAllByTestId('file-row-name-container').map(e => e.textContent.trim());
+};
+
export const deleteFile = async path => {
const row = await findAndTraverseToPath(path);
clickFileRowAction(row, 'Delete');
@@ -120,3 +135,16 @@ export const commit = async () => {
screen.getByText('Commit').click();
};
+
+export const createIdeComponent = (container, { isRepoEmpty = false, path = '' } = {}) => {
+ global.jsdom.reconfigure({
+ url: `${TEST_HOST}/-/ide/project/gitlab-test/lorem-ipsum${
+ isRepoEmpty ? '-empty' : ''
+ }/tree/master/-/${path}`,
+ });
+
+ const el = document.createElement('div');
+ Object.assign(el.dataset, IDE_DATASET);
+ container.appendChild(el);
+ return initIde(el, { extendStore });
+};
diff --git a/spec/frontend_integration/ide/helpers/mock_data.js b/spec/frontend_integration/ide/helpers/mock_data.js
new file mode 100644
index 00000000000..f70739e5ac0
--- /dev/null
+++ b/spec/frontend_integration/ide/helpers/mock_data.js
@@ -0,0 +1,12 @@
+export const IDE_DATASET = {
+ emptyStateSvgPath: '/test/empty_state.svg',
+ noChangesStateSvgPath: '/test/no_changes_state.svg',
+ committedStateSvgPath: '/test/committed_state.svg',
+ pipelinesEmptyStateSvgPath: '/test/pipelines_empty_state.svg',
+ promotionSvgPath: '/test/promotion.svg',
+ ciHelpPagePath: '/test/ci_help_page',
+ webIDEHelpPagePath: '/test/web_ide_help_page',
+ clientsidePreviewEnabled: 'true',
+ renderWhitespaceInCode: 'false',
+ codesandboxBundlerUrl: 'test/codesandbox_bundler',
+};
diff --git a/spec/frontend_integration/ide/ide_integration_spec.js b/spec/frontend_integration/ide/ide_integration_spec.js
index 1f5c1d38450..9d515d20749 100644
--- a/spec/frontend_integration/ide/ide_integration_spec.js
+++ b/spec/frontend_integration/ide/ide_integration_spec.js
@@ -1,61 +1,27 @@
-import { TEST_HOST } from 'helpers/test_constants';
import { waitForText } from 'helpers/wait_for_text';
import waitForPromises from 'helpers/wait_for_promises';
import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
import { createCommitId } from 'test_helpers/factories/commit_id';
-import { initIde } from '~/ide';
-import extendStore from '~/ide/stores/extend';
-import * as ideHelper from './ide_helper';
-
-const TEST_DATASET = {
- emptyStateSvgPath: '/test/empty_state.svg',
- noChangesStateSvgPath: '/test/no_changes_state.svg',
- committedStateSvgPath: '/test/committed_state.svg',
- pipelinesEmptyStateSvgPath: '/test/pipelines_empty_state.svg',
- promotionSvgPath: '/test/promotion.svg',
- ciHelpPagePath: '/test/ci_help_page',
- webIDEHelpPagePath: '/test/web_ide_help_page',
- clientsidePreviewEnabled: 'true',
- renderWhitespaceInCode: 'false',
- codesandboxBundlerUrl: 'test/codesandbox_bundler',
-};
+import * as ideHelper from './helpers/ide_helper';
describe('WebIDE', () => {
useOverclockTimers();
let vm;
- let root;
+ let container;
beforeEach(() => {
- root = document.createElement('div');
- document.body.appendChild(root);
-
- global.jsdom.reconfigure({
- url: `${TEST_HOST}/-/ide/project/gitlab-test/lorem-ipsum`,
- });
+ setFixtures('<div class="webide-container"></div>');
+ container = document.querySelector('.webide-container');
});
afterEach(() => {
vm.$destroy();
vm = null;
- root.remove();
- });
-
- const createComponent = () => {
- const el = document.createElement('div');
- Object.assign(el.dataset, TEST_DATASET);
- root.appendChild(el);
- vm = initIde(el, { extendStore });
- };
-
- it('runs', () => {
- createComponent();
-
- expect(root).toMatchSnapshot();
});
it('user commits changes', async () => {
- createComponent();
+ vm = ideHelper.createIdeComponent(container);
await ideHelper.createFile('foo/bar/test.txt', 'Lorem ipsum dolar sit');
await ideHelper.deleteFile('foo/bar/.gitkeep');
@@ -89,7 +55,7 @@ describe('WebIDE', () => {
});
it('user adds file that starts with +', async () => {
- createComponent();
+ vm = ideHelper.createIdeComponent(container);
await ideHelper.createFile('+test', 'Hello world!');
await ideHelper.openFile('+test');
diff --git a/spec/frontend_integration/ide/user_opens_ide_spec.js b/spec/frontend_integration/ide/user_opens_ide_spec.js
new file mode 100644
index 00000000000..958cab483eb
--- /dev/null
+++ b/spec/frontend_integration/ide/user_opens_ide_spec.js
@@ -0,0 +1,163 @@
+import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
+import { findByText, screen } from '@testing-library/dom';
+import * as ideHelper from './helpers/ide_helper';
+
+describe('IDE: User opens IDE', () => {
+ useOverclockTimers();
+
+ let vm;
+ let container;
+
+ beforeEach(() => {
+ setFixtures('<div class="webide-container"></div>');
+ container = document.querySelector('.webide-container');
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ vm = null;
+ });
+
+ it('shows loading indicator while the IDE is loading', async () => {
+ vm = ideHelper.createIdeComponent(container);
+
+ expect(container.querySelectorAll('.multi-file-loading-container')).toHaveLength(3);
+ });
+
+ describe('when the project is empty', () => {
+ beforeEach(() => {
+ vm = ideHelper.createIdeComponent(container, { isRepoEmpty: true });
+ });
+
+ it('shows "No files" in the left sidebar', async () => {
+ expect(await screen.findByText('No files')).toBeDefined();
+ });
+
+ it('shows a "New file" button', async () => {
+ const button = await screen.findByTitle('New file');
+
+ expect(button.tagName).toEqual('BUTTON');
+ });
+ });
+
+ describe('when the file tree is loaded', () => {
+ beforeEach(async () => {
+ vm = ideHelper.createIdeComponent(container);
+
+ await screen.findByText('README'); // wait for file tree to load
+ });
+
+ it('shows a list of files in the left sidebar', async () => {
+ expect(ideHelper.getFilesList()).toEqual(
+ expect.arrayContaining(['README', 'LICENSE', 'CONTRIBUTING.md']),
+ );
+ });
+
+ it('shows empty state in the main editor window', async () => {
+ expect(
+ await screen.findByText(
+ "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes.",
+ ),
+ ).toBeDefined();
+ });
+
+ it('shows commit button in disabled state', async () => {
+ const button = await screen.findByTestId('begin-commit-button');
+
+ expect(button.getAttribute('disabled')).toBeDefined();
+ });
+
+ it('shows branch/MR dropdown with master selected', async () => {
+ const dropdown = await screen.findByTestId('ide-nav-dropdown');
+
+ expect(dropdown.textContent).toContain('master');
+ });
+ });
+
+ describe('a path to a text file is present in the URL', () => {
+ beforeEach(async () => {
+ vm = ideHelper.createIdeComponent(container, { path: 'README.md' });
+
+ // a new tab is open for README.md
+ await findByText(document.querySelector('.multi-file-edit-pane'), 'README.md');
+ });
+
+ it('opens the file and its contents are shown in Monaco', async () => {
+ expect(await ideHelper.getEditorValue()).toContain('Sample repo for testing gitlab features');
+ });
+ });
+
+ describe('a path to a binary file is present in the URL', () => {
+ beforeEach(async () => {
+ vm = ideHelper.createIdeComponent(container, { path: 'Gemfile.zip' });
+
+ // a new tab is open for Gemfile.zip
+ await findByText(document.querySelector('.multi-file-edit-pane'), 'Gemfile.zip');
+ });
+
+ it('shows download viewer', async () => {
+ const downloadButton = await screen.findByText('Download');
+
+ expect(downloadButton.getAttribute('download')).toEqual('Gemfile.zip');
+ expect(downloadButton.getAttribute('href')).toContain('/raw/');
+ });
+ });
+
+ describe('a path to an image is present in the URL', () => {
+ beforeEach(async () => {
+ vm = ideHelper.createIdeComponent(container, { path: 'files/images/logo-white.png' });
+
+ // a new tab is open for logo-white.png
+ await findByText(document.querySelector('.multi-file-edit-pane'), 'logo-white.png');
+ });
+
+ it('shows image viewer', async () => {
+ const viewer = await screen.findByTestId('image-viewer');
+ const img = viewer.querySelector('img');
+
+ expect(img.src).toContain('logo-white.png');
+ });
+ });
+
+ describe('path in URL is a directory', () => {
+ beforeEach(async () => {
+ vm = ideHelper.createIdeComponent(container, { path: 'files/images' });
+
+ // wait for folders in left sidebar to be expanded
+ await screen.findByText('images');
+ });
+
+ it('expands folders in the left sidebar', () => {
+ expect(ideHelper.getFilesList()).toEqual(
+ expect.arrayContaining(['files', 'images', 'logo-white.png', 'logo-black.png']),
+ );
+ });
+
+ it('shows empty state in the main editor window', async () => {
+ expect(
+ await screen.findByText(
+ "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes.",
+ ),
+ ).toBeDefined();
+ });
+ });
+
+ describe("a file for path in url doesn't exist in the repo", () => {
+ beforeEach(async () => {
+ vm = ideHelper.createIdeComponent(container, { path: 'abracadabra/hocus-focus.txt' });
+
+ // a new tab is open for hocus-focus.txt
+ await findByText(document.querySelector('.multi-file-edit-pane'), 'hocus-focus.txt');
+ });
+
+ it('create new folders and file in the left sidebar', () => {
+ expect(ideHelper.getFilesList()).toEqual(
+ expect.arrayContaining(['abracadabra', 'hocus-focus.txt']),
+ );
+ });
+
+ it('creates a blank new file', async () => {
+ expect(await ideHelper.getEditorValue()).toEqual('\n');
+ });
+ });
+});