diff options
Diffstat (limited to 'spec')
16 files changed, 238 insertions, 13 deletions
diff --git a/spec/features/ide/user_commits_changes_spec.rb b/spec/features/ide/user_commits_changes_spec.rb index e1e586a4f18..04b215710b3 100644 --- a/spec/features/ide/user_commits_changes_spec.rb +++ b/spec/features/ide/user_commits_changes_spec.rb @@ -9,6 +9,8 @@ RSpec.describe 'IDE user commits changes', :js do let(:user) { project.first_owner } before do + stub_feature_flags(vscode_web_ide: false) + sign_in(user) ide_visit(project) diff --git a/spec/features/ide/user_opens_merge_request_spec.rb b/spec/features/ide/user_opens_merge_request_spec.rb index 8f4668d49ee..8a95d7c5544 100644 --- a/spec/features/ide/user_opens_merge_request_spec.rb +++ b/spec/features/ide/user_opens_merge_request_spec.rb @@ -8,6 +8,8 @@ RSpec.describe 'IDE merge request', :js do let(:user) { project.first_owner } before do + stub_feature_flags(vscode_web_ide: false) + sign_in(user) visit(merge_request_path(merge_request)) diff --git a/spec/features/ide_spec.rb b/spec/features/ide_spec.rb index 2505ab0afee..c7c740c2293 100644 --- a/spec/features/ide_spec.rb +++ b/spec/features/ide_spec.rb @@ -4,12 +4,14 @@ require 'spec_helper' RSpec.describe 'IDE', :js do describe 'sub-groups' do + let(:ide_iframe_selector) { '#ide iframe' } let(:user) { create(:user) } let(:group) { create(:group) } let(:subgroup) { create(:group, parent: group) } let(:subgroup_project) { create(:project, :repository, namespace: subgroup) } before do + stub_feature_flags(vscode_web_ide: vscode_ff) subgroup_project.add_maintainer(user) sign_in(user) @@ -20,8 +22,28 @@ RSpec.describe 'IDE', :js do wait_for_requests end - it 'loads project in web IDE' do - expect(page).to have_selector('.context-header', text: subgroup_project.name) + context 'with vscode feature flag on' do + let(:vscode_ff) { true } + + it 'loads project in Web IDE' do + iframe = find(ide_iframe_selector) + + page.within_frame(iframe) do + expect(page).to have_selector('.title', text: subgroup_project.name.upcase) + end + end + end + + context 'with vscode feature flag off' do + let(:vscode_ff) { false } + + it 'loads project in legacy Web IDE' do + expect(page).to have_selector('.context-header', text: subgroup_project.name) + end + + it 'does not load new Web IDE' do + expect(page).not_to have_selector(ide_iframe_selector) + end end end end diff --git a/spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb b/spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb index 484f740faee..d2774aa74c9 100644 --- a/spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb +++ b/spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb @@ -8,6 +8,10 @@ RSpec.describe 'User creates new blob', :js do let(:user) { create(:user) } let(:project) { create(:project, :empty_repo) } + before do + stub_feature_flags(vscode_web_ide: false) + end + shared_examples 'creating a file' do it 'allows the user to add a new file in Web IDE' do visit project_path(project) diff --git a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb index 0ad44f31a52..52686469243 100644 --- a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb +++ b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb @@ -9,6 +9,8 @@ RSpec.describe 'Projects > Files > Project owner sees a link to create a license let(:project_maintainer) { project.first_owner } before do + stub_feature_flags(vscode_web_ide: false) + sign_in(project_maintainer) end diff --git a/spec/features/projects/files/user_edits_files_spec.rb b/spec/features/projects/files/user_edits_files_spec.rb index ad96f6b6239..1a9c5483218 100644 --- a/spec/features/projects/files/user_edits_files_spec.rb +++ b/spec/features/projects/files/user_edits_files_spec.rb @@ -14,6 +14,8 @@ RSpec.describe 'Projects > Files > User edits files', :js do let(:user) { create(:user) } before do + stub_feature_flags(vscode_web_ide: false) + sign_in(user) end diff --git a/spec/features/projects/tree/create_directory_spec.rb b/spec/features/projects/tree/create_directory_spec.rb index 074469a9b55..9c950cfee6e 100644 --- a/spec/features/projects/tree/create_directory_spec.rb +++ b/spec/features/projects/tree/create_directory_spec.rb @@ -7,6 +7,8 @@ RSpec.describe 'Multi-file editor new directory', :js do let(:project) { create(:project, :repository) } before do + stub_feature_flags(vscode_web_ide: false) + project.add_maintainer(user) sign_in(user) diff --git a/spec/features/projects/tree/create_file_spec.rb b/spec/features/projects/tree/create_file_spec.rb index 85c644fa528..c0567ed4580 100644 --- a/spec/features/projects/tree/create_file_spec.rb +++ b/spec/features/projects/tree/create_file_spec.rb @@ -7,6 +7,8 @@ RSpec.describe 'Multi-file editor new file', :js do let(:project) { create(:project, :repository) } before do + stub_feature_flags(vscode_web_ide: false) + project.add_maintainer(user) sign_in(user) diff --git a/spec/features/projects/tree/tree_show_spec.rb b/spec/features/projects/tree/tree_show_spec.rb index 163e347d03d..7e971e09455 100644 --- a/spec/features/projects/tree/tree_show_spec.rb +++ b/spec/features/projects/tree/tree_show_spec.rb @@ -117,6 +117,10 @@ RSpec.describe 'Projects tree', :js do end context 'web IDE' do + before do + stub_feature_flags(vscode_web_ide: false) + end + it 'opens folder in IDE' do visit project_tree_path(project, File.join('master', 'bar')) diff --git a/spec/features/projects/tree/upload_file_spec.rb b/spec/features/projects/tree/upload_file_spec.rb index ce00483bc91..f32141d6051 100644 --- a/spec/features/projects/tree/upload_file_spec.rb +++ b/spec/features/projects/tree/upload_file_spec.rb @@ -9,6 +9,8 @@ RSpec.describe 'Multi-file editor upload file', :js do let(:img_file) { File.join(Rails.root, 'spec', 'fixtures', 'dk.png') } before do + stub_feature_flags(vscode_web_ide: false) + project.add_maintainer(user) sign_in(user) diff --git a/spec/frontend/ide/init_gitlab_web_ide_spec.js b/spec/frontend/ide/init_gitlab_web_ide_spec.js new file mode 100644 index 00000000000..ec8559f1b56 --- /dev/null +++ b/spec/frontend/ide/init_gitlab_web_ide_spec.js @@ -0,0 +1,62 @@ +import { start } from '@gitlab/web-ide'; +import { initGitlabWebIDE } from '~/ide/init_gitlab_web_ide'; +import { TEST_HOST } from 'helpers/test_constants'; + +jest.mock('@gitlab/web-ide'); + +const ROOT_ELEMENT_ID = 'ide'; +const TEST_NONCE = 'test123nonce'; +const TEST_PROJECT = { path_with_namespace: 'group1/project1' }; +const TEST_BRANCH_NAME = '12345-foo-patch'; +const TEST_GITLAB_URL = 'https://test-gitlab/'; +const TEST_GITLAB_WEB_IDE_PUBLIC_PATH = 'test/webpack/assets/gitlab-web-ide/public/path'; + +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('ide-loading'); + el.dataset.project = JSON.stringify(TEST_PROJECT); + el.dataset.cspNonce = TEST_NONCE; + el.dataset.branchName = TEST_BRANCH_NAME; + + document.body.append(el); + }; + const findRootElement = () => document.getElementById(ROOT_ELEMENT_ID); + const act = () => initGitlabWebIDE(findRootElement()); + + beforeEach(() => { + process.env.GITLAB_WEB_IDE_PUBLIC_PATH = TEST_GITLAB_WEB_IDE_PUBLIC_PATH; + window.gon.gitlab_url = TEST_GITLAB_URL; + + createRootElement(); + + act(); + }); + + afterEach(() => { + document.body.innerHTML = ''; + }); + + it('calls start with element', () => { + expect(start).toHaveBeenCalledWith(findRootElement(), { + baseUrl: `${TEST_HOST}/${TEST_GITLAB_WEB_IDE_PUBLIC_PATH}`, + projectPath: TEST_PROJECT.path_with_namespace, + ref: TEST_BRANCH_NAME, + gitlabUrl: TEST_GITLAB_URL, + nonce: TEST_NONCE, + }); + }); + + it('clears classes and data from root element', () => { + const rootEl = findRootElement(); + + // why: Snapshot to test that `ide-loading` was removed and no other + // artifacts are remaining. + expect(rootEl.outerHTML).toBe( + '<div id="ide" class="gl--flex-center gl-relative gl-h-full"></div>', + ); + }); +}); diff --git a/spec/frontend/pipeline_wizard/components/editor_spec.js b/spec/frontend/pipeline_wizard/components/editor_spec.js index 540a08d2c7f..b4ddc6e7d42 100644 --- a/spec/frontend/pipeline_wizard/components/editor_spec.js +++ b/spec/frontend/pipeline_wizard/components/editor_spec.js @@ -57,13 +57,4 @@ describe('Pages Yaml Editor wrapper', () => { }); }); }); - - describe('events', () => { - const wrapper = mount(YamlEditor, defaultOptions); - - it('emits touch if content is changed in editor', async () => { - await wrapper.vm.editor.setValue('foo: boo'); - expect(wrapper.emitted('touch')).toEqual([expect.any(Array)]); - }); - }); }); diff --git a/spec/frontend/pipeline_wizard/components/wrapper_spec.js b/spec/frontend/pipeline_wizard/components/wrapper_spec.js index 357a9d21723..9e73ca6c9b7 100644 --- a/spec/frontend/pipeline_wizard/components/wrapper_spec.js +++ b/spec/frontend/pipeline_wizard/components/wrapper_spec.js @@ -2,6 +2,7 @@ import { Document, parseDocument } from 'yaml'; import { GlProgressBar } from '@gitlab/ui'; import { nextTick } from 'vue'; import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper'; +import { mockTracking } from 'helpers/tracking_helper'; import PipelineWizardWrapper, { i18n } from '~/pipeline_wizard/components/wrapper.vue'; import WizardStep from '~/pipeline_wizard/components/step.vue'; import CommitStep from '~/pipeline_wizard/components/commit.vue'; @@ -19,9 +20,11 @@ describe('Pipeline Wizard - wrapper.vue', () => { const steps = parseDocument(stepsYaml).toJS(); const getAsYamlNode = (value) => new Document(value).contents; + const templateId = 'my-namespace/my-template'; const createComponent = (props = {}, mountFn = shallowMountExtended) => { wrapper = mountFn(PipelineWizardWrapper, { propsData: { + templateId, projectPath: '/user/repo', defaultBranch: 'main', filename: '.gitlab-ci.yml', @@ -311,4 +314,126 @@ describe('Pipeline Wizard - wrapper.vue', () => { }); }); }); + + describe('when commit step done', () => { + beforeEach(() => { + createComponent(); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + it('emits done', () => { + expect(wrapper.emitted('done')).toBeUndefined(); + + wrapper.findComponent(CommitStep).vm.$emit('done'); + + expect(wrapper.emitted('done')).toHaveLength(1); + }); + }); + + describe('tracking', () => { + let trackingSpy; + const trackingCategory = `pipeline_wizard:${templateId}`; + + const setUpTrackingSpy = () => { + trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn); + }; + + it('tracks next button click event', () => { + createComponent(); + setUpTrackingSpy(); + findFirstVisibleStep().vm.$emit('next'); + + expect(trackingSpy).toHaveBeenCalledWith(trackingCategory, 'click_button', { + category: trackingCategory, + property: 'next', + label: 'pipeline_wizard_navigation', + extras: { + fromStep: 0, + toStep: 1, + }, + }); + }); + + it('tracks back button click event', () => { + createComponent(); + + // Navigate to step 1 without the spy set up + findFirstVisibleStep().vm.$emit('next'); + + // Now enable the tracking spy + setUpTrackingSpy(); + + findFirstVisibleStep().vm.$emit('back'); + + expect(trackingSpy).toHaveBeenCalledWith(trackingCategory, 'click_button', { + category: trackingCategory, + property: 'back', + label: 'pipeline_wizard_navigation', + extras: { + fromStep: 1, + toStep: 0, + }, + }); + }); + + it('tracks back button click event on the commit step', () => { + createComponent(); + + // Navigate to step 2 without the spy set up + findFirstVisibleStep().vm.$emit('next'); + findFirstVisibleStep().vm.$emit('next'); + + // Now enable the tracking spy + setUpTrackingSpy(); + + wrapper.findComponent(CommitStep).vm.$emit('back'); + + expect(trackingSpy).toHaveBeenCalledWith(trackingCategory, 'click_button', { + category: trackingCategory, + property: 'back', + label: 'pipeline_wizard_navigation', + extras: { + fromStep: 2, + toStep: 1, + }, + }); + }); + + it('tracks done event on the commit step', () => { + createComponent(); + + // Navigate to step 2 without the spy set up + findFirstVisibleStep().vm.$emit('next'); + findFirstVisibleStep().vm.$emit('next'); + + // Now enable the tracking spy + setUpTrackingSpy(); + + wrapper.findComponent(CommitStep).vm.$emit('done'); + + expect(trackingSpy).toHaveBeenCalledWith(trackingCategory, 'click_button', { + category: trackingCategory, + label: 'pipeline_wizard_commit', + property: 'commit', + }); + }); + + it('tracks when editor emits touch events', () => { + createComponent(); + setUpTrackingSpy(); + + wrapper.findComponent(YamlEditor).vm.$emit('touch'); + + expect(trackingSpy).toHaveBeenCalledWith(trackingCategory, 'edit', { + category: trackingCategory, + label: 'pipeline_wizard_editor_interaction', + extras: { + currentStep: 0, + }, + }); + }); + }); }); diff --git a/spec/frontend/pipeline_wizard/mock/yaml.js b/spec/frontend/pipeline_wizard/mock/yaml.js index e7087b59ce7..12b6f1052b2 100644 --- a/spec/frontend/pipeline_wizard/mock/yaml.js +++ b/spec/frontend/pipeline_wizard/mock/yaml.js @@ -71,6 +71,7 @@ bar: barVal `; export const fullTemplate = ` +id: test/full-template title: some title description: some description filename: foo.yml @@ -84,6 +85,7 @@ steps: `; export const fullTemplateWithoutFilename = ` +id: test/full-template-no-filename title: some title description: some description steps: diff --git a/spec/frontend/pipeline_wizard/pipeline_wizard_spec.js b/spec/frontend/pipeline_wizard/pipeline_wizard_spec.js index 3f689ffdbc8..13234525159 100644 --- a/spec/frontend/pipeline_wizard/pipeline_wizard_spec.js +++ b/spec/frontend/pipeline_wizard/pipeline_wizard_spec.js @@ -59,6 +59,7 @@ describe('PipelineWizard', () => { defaultBranch, projectPath, filename: parseDocument(template).get('filename'), + templateId: parseDocument(template).get('id'), }), ); }); diff --git a/spec/frontend_integration/ide/helpers/start.js b/spec/frontend_integration/ide/helpers/start.js index 925db12f36e..40e6a725358 100644 --- a/spec/frontend_integration/ide/helpers/start.js +++ b/spec/frontend_integration/ide/helpers/start.js @@ -1,7 +1,7 @@ import { editor as monacoEditor } from 'monaco-editor'; import setWindowLocation from 'helpers/set_window_location_helper'; import { TEST_HOST } from 'helpers/test_constants'; -import { initIde } from '~/ide'; +import { initLegacyWebIDE } from '~/ide'; import extendStore from '~/ide/stores/extend'; import { getProject, getEmptyProject } from 'jest/../frontend_integration/test_helpers/fixtures'; import { IDE_DATASET } from './mock_data'; @@ -16,7 +16,7 @@ export default (container, { isRepoEmpty = false, path = '', mrId = '' } = {}) = const el = document.createElement('div'); Object.assign(el.dataset, IDE_DATASET, { project: JSON.stringify(project) }); container.appendChild(el); - const vm = initIde(el, { extendStore }); + const vm = initLegacyWebIDE(el, { extendStore }); // We need to dispose of editor Singleton things or tests will bump into eachother vm.$on('destroy', () => monacoEditor.getModels().forEach((model) => model.dispose())); |