diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-11-30 11:02:35 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-11-30 11:02:35 +0000 |
commit | 434a0ce52d75e13d48eac9ce83774954c7c5d48d (patch) | |
tree | de3b7a7cf1ce8b07555f28df592297c76894c90f /spec/frontend_integration/ide | |
parent | 0a0d9493ca481c56b739a3df27c31262283150fe (diff) | |
download | gitlab-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.snap | 114 | ||||
-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.js | 12 | ||||
-rw-r--r-- | spec/frontend_integration/ide/ide_integration_spec.js | 46 | ||||
-rw-r--r-- | spec/frontend_integration/ide/user_opens_ide_spec.js | 163 |
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'); + }); + }); +}); |