Commit b63cce88 authored by Paul Slaughter's avatar Paul Slaughter

Disallow fs in FE integration specs

- This is because we'd like to run these in the browser
- Also removes a potential circular dependency
when loading specs in the browser
parent f1eaac5c
...@@ -30,6 +30,8 @@ module.exports = path => { ...@@ -30,6 +30,8 @@ module.exports = path => {
testMatch = testMatch.map(path => path.replace('_spec.js', '')); testMatch = testMatch.map(path => path.replace('_spec.js', ''));
} }
const TEST_FIXTURES_PATTERN = 'test_fixtures(/.*)$';
const moduleNameMapper = { const moduleNameMapper = {
'^~(/.*)$': '<rootDir>/app/assets/javascripts$1', '^~(/.*)$': '<rootDir>/app/assets/javascripts$1',
'^ee_component(/.*)$': '^ee_component(/.*)$':
...@@ -38,12 +40,12 @@ module.exports = path => { ...@@ -38,12 +40,12 @@ module.exports = path => {
'^ee_else_ce(/.*)$': '<rootDir>/app/assets/javascripts$1', '^ee_else_ce(/.*)$': '<rootDir>/app/assets/javascripts$1',
'^helpers(/.*)$': '<rootDir>/spec/frontend/helpers$1', '^helpers(/.*)$': '<rootDir>/spec/frontend/helpers$1',
'^vendor(/.*)$': '<rootDir>/vendor/assets/javascripts$1', '^vendor(/.*)$': '<rootDir>/vendor/assets/javascripts$1',
[TEST_FIXTURES_PATTERN]: '<rootDir>/tmp/tests/frontend/fixtures$1',
'\\.(jpg|jpeg|png|svg|css)$': '<rootDir>/spec/frontend/__mocks__/file_mock.js', '\\.(jpg|jpeg|png|svg|css)$': '<rootDir>/spec/frontend/__mocks__/file_mock.js',
'emojis(/.*).json': '<rootDir>/fixtures/emojis$1.json', 'emojis(/.*).json': '<rootDir>/fixtures/emojis$1.json',
'^spec/test_constants$': '<rootDir>/spec/frontend/helpers/test_constants', '^spec/test_constants$': '<rootDir>/spec/frontend/helpers/test_constants',
'^jest/(.*)$': '<rootDir>/spec/frontend/$1', '^jest/(.*)$': '<rootDir>/spec/frontend/$1',
'test_helpers(/.*)$': '<rootDir>/spec/frontend_integration/test_helpers$1', 'test_helpers(/.*)$': '<rootDir>/spec/frontend_integration/test_helpers$1',
'test_fixtures(/.*)$': '<rootDir>/tmp/tests/frontend/fixtures$1',
}; };
const collectCoverageFrom = ['<rootDir>/app/assets/javascripts/**/*.{js,vue}']; const collectCoverageFrom = ['<rootDir>/app/assets/javascripts/**/*.{js,vue}'];
...@@ -55,7 +57,7 @@ module.exports = path => { ...@@ -55,7 +57,7 @@ module.exports = path => {
'^ee_component(/.*)$': rootDirEE, '^ee_component(/.*)$': rootDirEE,
'^ee_else_ce(/.*)$': rootDirEE, '^ee_else_ce(/.*)$': rootDirEE,
'^ee_jest/(.*)$': '<rootDir>/ee/spec/frontend/$1', '^ee_jest/(.*)$': '<rootDir>/ee/spec/frontend/$1',
'test_fixtures(/.*)$': '<rootDir>/tmp/tests/frontend/fixtures-ee$1', [TEST_FIXTURES_PATTERN]: '<rootDir>/tmp/tests/frontend/fixtures-ee$1',
}); });
collectCoverageFrom.push(rootDirEE.replace('$1', '/**/*.{js,vue}')); collectCoverageFrom.push(rootDirEE.replace('$1', '/**/*.{js,vue}'));
......
...@@ -4,5 +4,9 @@ settings: ...@@ -4,5 +4,9 @@ settings:
import/resolver: import/resolver:
jest: jest:
jestConfigFile: 'jest.config.integration.js' jestConfigFile: 'jest.config.integration.js'
rules:
no-restricted-imports:
- error
- fs
globals: globals:
mockServer: false mockServer: false
import { TEST_HOST } from 'helpers/test_constants';
import { findAllByText, fireEvent, getByLabelText, screen } from '@testing-library/dom'; 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'); const isFolderRowOpen = row => row.matches('.folder.is-open');
...@@ -135,16 +131,3 @@ export const commit = async () => { ...@@ -135,16 +131,3 @@ export const commit = async () => {
screen.getByText('Commit').click(); 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 });
};
import { TEST_HOST } from 'helpers/test_constants';
import extendStore from '~/ide/stores/extend';
import { IDE_DATASET } from './mock_data';
import { initIde } from '~/ide';
export default (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 });
};
...@@ -3,6 +3,7 @@ import waitForPromises from 'helpers/wait_for_promises'; ...@@ -3,6 +3,7 @@ import waitForPromises from 'helpers/wait_for_promises';
import { useOverclockTimers } from 'test_helpers/utils/overclock_timers'; import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
import { createCommitId } from 'test_helpers/factories/commit_id'; import { createCommitId } from 'test_helpers/factories/commit_id';
import * as ideHelper from './helpers/ide_helper'; import * as ideHelper from './helpers/ide_helper';
import startWebIDE from './helpers/start';
describe('WebIDE', () => { describe('WebIDE', () => {
useOverclockTimers(); useOverclockTimers();
...@@ -21,7 +22,7 @@ describe('WebIDE', () => { ...@@ -21,7 +22,7 @@ describe('WebIDE', () => {
}); });
it('user commits changes', async () => { it('user commits changes', async () => {
vm = ideHelper.createIdeComponent(container); vm = startWebIDE(container);
await ideHelper.createFile('foo/bar/test.txt', 'Lorem ipsum dolar sit'); await ideHelper.createFile('foo/bar/test.txt', 'Lorem ipsum dolar sit');
await ideHelper.deleteFile('foo/bar/.gitkeep'); await ideHelper.deleteFile('foo/bar/.gitkeep');
...@@ -55,7 +56,7 @@ describe('WebIDE', () => { ...@@ -55,7 +56,7 @@ describe('WebIDE', () => {
}); });
it('user adds file that starts with +', async () => { it('user adds file that starts with +', async () => {
vm = ideHelper.createIdeComponent(container); vm = startWebIDE(container);
await ideHelper.createFile('+test', 'Hello world!'); await ideHelper.createFile('+test', 'Hello world!');
await ideHelper.openFile('+test'); await ideHelper.openFile('+test');
......
import { useOverclockTimers } from 'test_helpers/utils/overclock_timers'; import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
import { findByText, screen } from '@testing-library/dom'; import { findByText, screen } from '@testing-library/dom';
import * as ideHelper from './helpers/ide_helper'; import * as ideHelper from './helpers/ide_helper';
import startWebIDE from './helpers/start';
describe('IDE: User opens IDE', () => { describe('IDE: User opens IDE', () => {
useOverclockTimers(); useOverclockTimers();
...@@ -19,14 +20,14 @@ describe('IDE: User opens IDE', () => { ...@@ -19,14 +20,14 @@ describe('IDE: User opens IDE', () => {
}); });
it('shows loading indicator while the IDE is loading', async () => { it('shows loading indicator while the IDE is loading', async () => {
vm = ideHelper.createIdeComponent(container); vm = startWebIDE(container);
expect(container.querySelectorAll('.multi-file-loading-container')).toHaveLength(3); expect(container.querySelectorAll('.multi-file-loading-container')).toHaveLength(3);
}); });
describe('when the project is empty', () => { describe('when the project is empty', () => {
beforeEach(() => { beforeEach(() => {
vm = ideHelper.createIdeComponent(container, { isRepoEmpty: true }); vm = startWebIDE(container, { isRepoEmpty: true });
}); });
it('shows "No files" in the left sidebar', async () => { it('shows "No files" in the left sidebar', async () => {
...@@ -42,7 +43,7 @@ describe('IDE: User opens IDE', () => { ...@@ -42,7 +43,7 @@ describe('IDE: User opens IDE', () => {
describe('when the file tree is loaded', () => { describe('when the file tree is loaded', () => {
beforeEach(async () => { beforeEach(async () => {
vm = ideHelper.createIdeComponent(container); vm = startWebIDE(container);
await screen.findByText('README'); // wait for file tree to load await screen.findByText('README'); // wait for file tree to load
}); });
...@@ -76,7 +77,7 @@ describe('IDE: User opens IDE', () => { ...@@ -76,7 +77,7 @@ describe('IDE: User opens IDE', () => {
describe('a path to a text file is present in the URL', () => { describe('a path to a text file is present in the URL', () => {
beforeEach(async () => { beforeEach(async () => {
vm = ideHelper.createIdeComponent(container, { path: 'README.md' }); vm = startWebIDE(container, { path: 'README.md' });
// a new tab is open for README.md // a new tab is open for README.md
await findByText(document.querySelector('.multi-file-edit-pane'), 'README.md'); await findByText(document.querySelector('.multi-file-edit-pane'), 'README.md');
...@@ -89,7 +90,7 @@ describe('IDE: User opens IDE', () => { ...@@ -89,7 +90,7 @@ describe('IDE: User opens IDE', () => {
describe('a path to a binary file is present in the URL', () => { describe('a path to a binary file is present in the URL', () => {
beforeEach(async () => { beforeEach(async () => {
vm = ideHelper.createIdeComponent(container, { path: 'Gemfile.zip' }); vm = startWebIDE(container, { path: 'Gemfile.zip' });
// a new tab is open for Gemfile.zip // a new tab is open for Gemfile.zip
await findByText(document.querySelector('.multi-file-edit-pane'), 'Gemfile.zip'); await findByText(document.querySelector('.multi-file-edit-pane'), 'Gemfile.zip');
...@@ -105,7 +106,7 @@ describe('IDE: User opens IDE', () => { ...@@ -105,7 +106,7 @@ describe('IDE: User opens IDE', () => {
describe('a path to an image is present in the URL', () => { describe('a path to an image is present in the URL', () => {
beforeEach(async () => { beforeEach(async () => {
vm = ideHelper.createIdeComponent(container, { path: 'files/images/logo-white.png' }); vm = startWebIDE(container, { path: 'files/images/logo-white.png' });
// a new tab is open for logo-white.png // a new tab is open for logo-white.png
await findByText(document.querySelector('.multi-file-edit-pane'), 'logo-white.png'); await findByText(document.querySelector('.multi-file-edit-pane'), 'logo-white.png');
...@@ -121,7 +122,7 @@ describe('IDE: User opens IDE', () => { ...@@ -121,7 +122,7 @@ describe('IDE: User opens IDE', () => {
describe('path in URL is a directory', () => { describe('path in URL is a directory', () => {
beforeEach(async () => { beforeEach(async () => {
vm = ideHelper.createIdeComponent(container, { path: 'files/images' }); vm = startWebIDE(container, { path: 'files/images' });
// wait for folders in left sidebar to be expanded // wait for folders in left sidebar to be expanded
await screen.findByText('images'); await screen.findByText('images');
...@@ -144,7 +145,7 @@ describe('IDE: User opens IDE', () => { ...@@ -144,7 +145,7 @@ describe('IDE: User opens IDE', () => {
describe("a file for path in url doesn't exist in the repo", () => { describe("a file for path in url doesn't exist in the repo", () => {
beforeEach(async () => { beforeEach(async () => {
vm = ideHelper.createIdeComponent(container, { path: 'abracadabra/hocus-focus.txt' }); vm = startWebIDE(container, { path: 'abracadabra/hocus-focus.txt' });
// a new tab is open for hocus-focus.txt // a new tab is open for hocus-focus.txt
await findByText(document.querySelector('.multi-file-edit-pane'), 'hocus-focus.txt'); await findByText(document.querySelector('.multi-file-edit-pane'), 'hocus-focus.txt');
......
/* eslint-disable global-require, import/no-unresolved */ /* eslint-disable global-require, import/no-unresolved */
import { memoize } from 'lodash'; import { memoize } from 'lodash';
import { readFileSync } from 'fs';
import { join } from 'path';
export const getProject = () => require('test_fixtures/api/projects/get.json'); const createFactoryWithDefault = (fn, defaultValue) => () => {
export const getEmptyProject = () => require('test_fixtures/api/projects/get_empty.json'); try {
export const getBranch = () => require('test_fixtures/api/projects/branches/get.json'); return fn();
export const getMergeRequests = () => require('test_fixtures/api/merge_requests/get.json'); } catch {
export const getRepositoryFiles = () => require('test_fixtures/projects_json/files.json'); return defaultValue;
}
};
export const getBlobReadme = () => const factory = {
readFileSync(require.resolve('test_fixtures/blob/text/README.md'), 'utf8'); json: fn => createFactoryWithDefault(fn, { error: 'fixture not found' }),
export const getBlobZip = () => text: fn => createFactoryWithDefault(fn, 'Hello world\nHow are you today?\n'),
readFileSync(require.resolve('test_fixtures/blob/binary/Gemfile.zip'), 'utf8'); binary: fn => createFactoryWithDefault(fn, ''),
export const getBlobImage = () => };
readFileSync(
join(require.resolve('test_fixtures/blob/text/README.md'), '../..', 'images/logo-white.png'),
'utf8',
);
export const getPipelinesEmptyResponse = () => export const getProject = factory.json(() => require('test_fixtures/api/projects/get.json'));
require('test_fixtures/projects_json/pipelines_empty.json'); export const getEmptyProject = factory.json(() =>
require('test_fixtures/api/projects/get_empty.json'),
);
export const getBranch = factory.json(() =>
require('test_fixtures/api/projects/branches/get.json'),
);
export const getMergeRequests = factory.json(() =>
require('test_fixtures/api/merge_requests/get.json'),
);
export const getRepositoryFiles = factory.json(() =>
require('test_fixtures/projects_json/files.json'),
);
export const getPipelinesEmptyResponse = factory.json(() =>
require('test_fixtures/projects_json/pipelines_empty.json'),
);
export const getCommit = memoize(() => getBranch().commit); export const getCommit = memoize(() => getBranch().commit);
export const getBlobReadme = factory.text(() => require('test_fixtures/blob/text/README.md'));
export const getBlobZip = factory.binary(() => require('test_fixtures/blob/binary/Gemfile.zip'));
export const getBlobImage = factory.binary(() =>
require('test_fixtures/blob/images/logo-white.png'),
);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment