From 859a6fb938bb9ee2a317c46dfa4fcc1af49608f0 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 18 Feb 2021 10:34:06 +0000 Subject: Add latest changes from gitlab-org/gitlab@13-9-stable-ee --- .../frontend_integration/ide/helpers/ide_helper.js | 8 ++- spec/frontend_integration/ide/helpers/start.js | 13 ++--- .../ide/ide_integration_spec.js | 6 +-- .../ide/user_opens_file_spec.js | 2 +- .../ide/user_opens_ide_spec.js | 2 +- .../frontend_integration/ide/user_opens_mr_spec.js | 60 ++++++++++++++++++++++ .../test_helpers/factories/commit.js | 2 +- spec/frontend_integration/test_helpers/fixtures.js | 14 ++++- .../test_helpers/mock_server/index.js | 6 +++ .../test_helpers/mock_server/routes/404.js | 2 + .../test_helpers/mock_server/routes/projects.js | 18 +++++++ 11 files changed, 119 insertions(+), 14 deletions(-) create mode 100644 spec/frontend_integration/ide/user_opens_mr_spec.js (limited to 'spec/frontend_integration') diff --git a/spec/frontend_integration/ide/helpers/ide_helper.js b/spec/frontend_integration/ide/helpers/ide_helper.js index 8d5d047b146..9e6bafc1297 100644 --- a/spec/frontend_integration/ide/helpers/ide_helper.js +++ b/spec/frontend_integration/ide/helpers/ide_helper.js @@ -69,7 +69,7 @@ const openFileRow = (row) => { row.click(); }; -const findAndTraverseToPath = async (path, index = 0, row = null) => { +export const findAndTraverseToPath = async (path, index = 0, row = null) => { if (!path) { return row; } @@ -110,6 +110,12 @@ const findAndClickRootAction = async (name) => { button.click(); }; +/** + * Drop leading "/-/ide" and file path from the current URL + */ +export const getBaseRoute = (url = window.location.pathname) => + url.replace(/^\/-\/ide/, '').replace(/\/-\/.*$/, ''); + export const clickPreviewMarkdown = () => { screen.getByText('Preview Markdown').click(); }; diff --git a/spec/frontend_integration/ide/helpers/start.js b/spec/frontend_integration/ide/helpers/start.js index 43a996286e7..173a9610c84 100644 --- a/spec/frontend_integration/ide/helpers/start.js +++ b/spec/frontend_integration/ide/helpers/start.js @@ -1,14 +1,15 @@ import { TEST_HOST } from 'helpers/test_constants'; -import extendStore from '~/ide/stores/extend'; -import { IDE_DATASET } from './mock_data'; import { initIde } from '~/ide'; import Editor from '~/ide/lib/editor'; +import extendStore from '~/ide/stores/extend'; +import { IDE_DATASET } from './mock_data'; + +export default (container, { isRepoEmpty = false, path = '', mrId = '' } = {}) => { + const projectName = isRepoEmpty ? 'lorem-ipsum-empty' : 'lorem-ipsum'; + const pathSuffix = mrId ? `merge_requests/${mrId}` : `tree/master/-/${path}`; -export default (container, { isRepoEmpty = false, path = '' } = {}) => { global.jsdom.reconfigure({ - url: `${TEST_HOST}/-/ide/project/gitlab-test/lorem-ipsum${ - isRepoEmpty ? '-empty' : '' - }/tree/master/-/${path}`, + url: `${TEST_HOST}/-/ide/project/gitlab-test/${projectName}/${pathSuffix}`, }); const el = document.createElement('div'); diff --git a/spec/frontend_integration/ide/ide_integration_spec.js b/spec/frontend_integration/ide/ide_integration_spec.js index 00a73661d14..3ce88de11fe 100644 --- a/spec/frontend_integration/ide/ide_integration_spec.js +++ b/spec/frontend_integration/ide/ide_integration_spec.js @@ -1,8 +1,8 @@ -import { waitForText } from 'helpers/wait_for_text'; -import waitForPromises from 'helpers/wait_for_promises'; import { setTestTimeout } from 'helpers/timeout'; -import { useOverclockTimers } from 'test_helpers/utils/overclock_timers'; +import waitForPromises from 'helpers/wait_for_promises'; +import { waitForText } from 'helpers/wait_for_text'; import { createCommitId } from 'test_helpers/factories/commit_id'; +import { useOverclockTimers } from 'test_helpers/utils/overclock_timers'; import * as ideHelper from './helpers/ide_helper'; import startWebIDE from './helpers/start'; diff --git a/spec/frontend_integration/ide/user_opens_file_spec.js b/spec/frontend_integration/ide/user_opens_file_spec.js index 7fa6dcecc9e..2cb3363ef85 100644 --- a/spec/frontend_integration/ide/user_opens_file_spec.js +++ b/spec/frontend_integration/ide/user_opens_file_spec.js @@ -1,5 +1,5 @@ -import { useOverclockTimers } from 'test_helpers/utils/overclock_timers'; import { screen } from '@testing-library/dom'; +import { useOverclockTimers } from 'test_helpers/utils/overclock_timers'; import * as ideHelper from './helpers/ide_helper'; import startWebIDE from './helpers/start'; diff --git a/spec/frontend_integration/ide/user_opens_ide_spec.js b/spec/frontend_integration/ide/user_opens_ide_spec.js index 502cb2e2c7d..f56cd008d1c 100644 --- a/spec/frontend_integration/ide/user_opens_ide_spec.js +++ b/spec/frontend_integration/ide/user_opens_ide_spec.js @@ -1,5 +1,5 @@ -import { useOverclockTimers } from 'test_helpers/utils/overclock_timers'; import { screen } from '@testing-library/dom'; +import { useOverclockTimers } from 'test_helpers/utils/overclock_timers'; import * as ideHelper from './helpers/ide_helper'; import startWebIDE from './helpers/start'; diff --git a/spec/frontend_integration/ide/user_opens_mr_spec.js b/spec/frontend_integration/ide/user_opens_mr_spec.js new file mode 100644 index 00000000000..9cf0ff5da56 --- /dev/null +++ b/spec/frontend_integration/ide/user_opens_mr_spec.js @@ -0,0 +1,60 @@ +import { basename } from 'path'; +import { getMergeRequests, getMergeRequestWithChanges } from 'test_helpers/fixtures'; +import { useOverclockTimers } from 'test_helpers/utils/overclock_timers'; +import * as ideHelper from './helpers/ide_helper'; +import startWebIDE from './helpers/start'; + +const getRelevantChanges = () => + getMergeRequestWithChanges().changes.filter((x) => !x.deleted_file); + +describe('IDE: User opens Merge Request', () => { + useOverclockTimers(); + + let vm; + let container; + let changes; + + beforeEach(async () => { + const [{ iid: mrId }] = getMergeRequests(); + + changes = getRelevantChanges(); + + setFixtures('
'); + container = document.querySelector('.webide-container'); + + vm = startWebIDE(container, { mrId }); + + await ideHelper.waitForTabToOpen(basename(changes[0].new_path)); + await ideHelper.waitForMonacoEditor(); + }); + + afterEach(async () => { + vm.$destroy(); + vm = null; + }); + + const findAllTabs = () => Array.from(document.querySelectorAll('.multi-file-tab')); + const findAllTabsData = () => + findAllTabs().map((el) => ({ + title: el.getAttribute('title'), + text: el.textContent.trim(), + })); + + it('shows first change as active in file tree', async () => { + const firstPath = changes[0].new_path; + const row = await ideHelper.findAndTraverseToPath(firstPath); + + expect(row).toHaveClass('is-open'); + expect(row).toHaveClass('is-active'); + }); + + it('opens other changes', () => { + // We only show first 10 changes + const expectedTabs = changes.slice(0, 10).map((x) => ({ + title: `${ideHelper.getBaseRoute()}/-/${x.new_path}/`, + text: basename(x.new_path), + })); + + expect(findAllTabsData()).toEqual(expectedTabs); + }); +}); diff --git a/spec/frontend_integration/test_helpers/factories/commit.js b/spec/frontend_integration/test_helpers/factories/commit.js index 09bb5fd589b..196295addbe 100644 --- a/spec/frontend_integration/test_helpers/factories/commit.js +++ b/spec/frontend_integration/test_helpers/factories/commit.js @@ -1,5 +1,5 @@ -import { withValues } from '../utils/obj'; import { getCommit } from '../fixtures'; +import { withValues } from '../utils/obj'; import { createCommitId } from './commit_id'; export const createNewCommit = ({ id = createCommitId(), message }, orig = getCommit()) => { diff --git a/spec/frontend_integration/test_helpers/fixtures.js b/spec/frontend_integration/test_helpers/fixtures.js index fde3fd8cb63..b2768440607 100644 --- a/spec/frontend_integration/test_helpers/fixtures.js +++ b/spec/frontend_integration/test_helpers/fixtures.js @@ -1,4 +1,10 @@ -/* eslint-disable global-require, import/no-unresolved */ +/* eslint-disable global-require */ +// We use "require" rather than `fs` so that this works in a browser environment. + +/* eslint "import/no-unresolved": 0 */ +// We don't want to require *all* fixtures to be generated (especailly in a local environment). +// We use `eslint` instead of `eslint-disable`, so that we also don't trigger an `Unused eslint-disable directive` when all fixtures are present. + import { memoize } from 'lodash'; const createFactoryWithDefault = (fn, defaultValue) => () => { @@ -25,6 +31,12 @@ export const getBranch = factory.json(() => export const getMergeRequests = factory.json(() => require('test_fixtures/api/merge_requests/get.json'), ); +export const getMergeRequestWithChanges = factory.json(() => + require('test_fixtures/api/merge_requests/changes.json'), +); +export const getMergeRequestVersions = factory.json(() => + require('test_fixtures/api/merge_requests/versions.json'), +); export const getRepositoryFiles = factory.json(() => require('test_fixtures/projects_json/files.json'), ); diff --git a/spec/frontend_integration/test_helpers/mock_server/index.js b/spec/frontend_integration/test_helpers/mock_server/index.js index 2aebdefaafb..20cb441daa7 100644 --- a/spec/frontend_integration/test_helpers/mock_server/index.js +++ b/spec/frontend_integration/test_helpers/mock_server/index.js @@ -4,6 +4,8 @@ import { getEmptyProject, getBranch, getMergeRequests, + getMergeRequestWithChanges, + getMergeRequestVersions, getRepositoryFiles, getBlobReadme, getBlobImage, @@ -16,6 +18,8 @@ export const createMockServerOptions = () => ({ project: Model, branch: Model, mergeRequest: Model, + mergeRequestChange: Model, + mergeRequestVersion: Model, file: Model, userPermission: Model, }, @@ -30,6 +34,8 @@ export const createMockServerOptions = () => ({ projects: [getProject(), getEmptyProject()], branches: [getBranch()], mergeRequests: getMergeRequests(), + mergeRequestChanges: [getMergeRequestWithChanges()], + mergeRequestVersions: getMergeRequestVersions(), filesRaw: [ { raw: getBlobReadme(), diff --git a/spec/frontend_integration/test_helpers/mock_server/routes/404.js b/spec/frontend_integration/test_helpers/mock_server/routes/404.js index bc8edba927e..54183f1189c 100644 --- a/spec/frontend_integration/test_helpers/mock_server/routes/404.js +++ b/spec/frontend_integration/test_helpers/mock_server/routes/404.js @@ -1,3 +1,5 @@ +import { Response } from 'miragejs'; + export default (server) => { ['get', 'post', 'put', 'delete', 'patch'].forEach((method) => { server[method]('*', () => { diff --git a/spec/frontend_integration/test_helpers/mock_server/routes/projects.js b/spec/frontend_integration/test_helpers/mock_server/routes/projects.js index de37aa98eee..e6e09121fd4 100644 --- a/spec/frontend_integration/test_helpers/mock_server/routes/projects.js +++ b/spec/frontend_integration/test_helpers/mock_server/routes/projects.js @@ -20,4 +20,22 @@ export default (server) => { return result.models; }); + + server.get('/api/v4/projects/:id/merge_requests/:mid', (schema, request) => { + const mr = schema.mergeRequests.findBy({ iid: request.params.mid }); + + return mr.attrs; + }); + + server.get('/api/v4/projects/:id/merge_requests/:mid/versions', (schema, request) => { + const versions = schema.mergeRequestVersions.where({ merge_request_id: request.params.mid }); + + return versions.models; + }); + + server.get('/api/v4/projects/:id/merge_requests/:mid/changes', (schema, request) => { + const mrWithChanges = schema.mergeRequestChanges.findBy({ iid: request.params.mid }); + + return mrWithChanges.attrs; + }); }; -- cgit v1.2.3