summaryrefslogtreecommitdiff
path: root/spec/javascripts
diff options
context:
space:
mode:
Diffstat (limited to 'spec/javascripts')
-rw-r--r--spec/javascripts/ajax_loading_spinner_spec.js57
-rw-r--r--spec/javascripts/avatar_helper_spec.js98
-rw-r--r--spec/javascripts/bootstrap_linked_tabs_spec.js67
-rw-r--r--spec/javascripts/ci_variable_list/ajax_variable_list_spec.js231
-rw-r--r--spec/javascripts/ci_variable_list/ci_variable_list_spec.js294
-rw-r--r--spec/javascripts/ci_variable_list/native_form_variable_list_spec.js37
-rw-r--r--spec/javascripts/close_reopen_report_toggle_spec.js272
-rw-r--r--spec/javascripts/commit_merge_requests_spec.js69
-rw-r--r--spec/javascripts/commits_spec.js98
-rw-r--r--spec/javascripts/create_item_dropdown_spec.js195
-rw-r--r--spec/javascripts/deploy_keys/components/action_btn_spec.js72
-rw-r--r--spec/javascripts/deploy_keys/components/app_spec.js155
-rw-r--r--spec/javascripts/deploy_keys/components/key_spec.js157
-rw-r--r--spec/javascripts/deploy_keys/components/keys_panel_spec.js63
-rw-r--r--spec/javascripts/diff_comments_store_spec.js141
-rw-r--r--spec/javascripts/diffs/create_diffs_store.js5
-rw-r--r--spec/javascripts/diffs/mock_data/diff_discussions.js5
-rw-r--r--spec/javascripts/diffs/mock_data/diff_file.js5
-rw-r--r--spec/javascripts/diffs/mock_data/diff_file_unreadable.js5
-rw-r--r--spec/javascripts/diffs/mock_data/diff_with_commit.js7
-rw-r--r--spec/javascripts/diffs/mock_data/merge_request_diffs.js7
-rw-r--r--spec/javascripts/dirty_submit/dirty_submit_collection_spec.js29
-rw-r--r--spec/javascripts/dirty_submit/dirty_submit_factory_spec.js18
-rw-r--r--spec/javascripts/dirty_submit/dirty_submit_form_spec.js114
-rw-r--r--spec/javascripts/dirty_submit/helper.js48
-rw-r--r--spec/javascripts/editor/editor_lite_spec.js160
-rw-r--r--spec/javascripts/emoji_spec.js486
-rw-r--r--spec/javascripts/feature_highlight/feature_highlight_helper_spec.js75
-rw-r--r--spec/javascripts/feature_highlight/feature_highlight_spec.js141
-rw-r--r--spec/javascripts/filtered_search/dropdown_utils_spec.js374
-rw-r--r--spec/javascripts/filtered_search/filtered_search_manager_spec.js580
-rw-r--r--spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js152
-rw-r--r--spec/javascripts/filtered_search/issues_filtered_search_token_keys_spec.js148
-rw-r--r--spec/javascripts/filtered_search/recent_searches_root_spec.js30
-rw-r--r--spec/javascripts/filtered_search/services/recent_searches_service_spec.js158
-rw-r--r--spec/javascripts/filtered_search/visual_token_value_spec.js389
-rw-r--r--spec/javascripts/flash_spec.js236
-rw-r--r--spec/javascripts/frequent_items/components/app_spec.js257
-rw-r--r--spec/javascripts/frequent_items/mock_data.js168
-rw-r--r--spec/javascripts/frequent_items/store/actions_spec.js228
-rw-r--r--spec/javascripts/frequent_items/store/mutations_spec.js117
-rw-r--r--spec/javascripts/frequent_items/utils_spec.js130
-rw-r--r--spec/javascripts/gl_dropdown_spec.js22
-rw-r--r--spec/javascripts/groups/components/app_spec.js533
-rw-r--r--spec/javascripts/groups/components/group_folder_spec.js67
-rw-r--r--spec/javascripts/groups/components/group_item_spec.js218
-rw-r--r--spec/javascripts/groups/components/groups_spec.js76
-rw-r--r--spec/javascripts/groups/components/item_actions_spec.js84
-rw-r--r--spec/javascripts/groups/components/item_caret_spec.js38
-rw-r--r--spec/javascripts/groups/components/item_stats_spec.js128
-rw-r--r--spec/javascripts/groups/components/item_stats_value_spec.js82
-rw-r--r--spec/javascripts/groups/components/item_type_icon_spec.js58
-rw-r--r--spec/javascripts/groups/mock_data.js398
-rw-r--r--spec/javascripts/groups/service/groups_service_spec.js42
-rw-r--r--spec/javascripts/groups/store/groups_store_spec.js123
-rw-r--r--spec/javascripts/helpers/filtered_search_spec_helper.js70
-rw-r--r--spec/javascripts/helpers/init_vue_mr_page_helper.js2
-rw-r--r--spec/javascripts/helpers/vue_mount_component_helper.js40
-rw-r--r--spec/javascripts/ide/components/activity_bar_spec.js72
-rw-r--r--spec/javascripts/ide/components/commit_sidebar/radio_group_spec.js139
-rw-r--r--spec/javascripts/ide/components/file_row_extra_spec.js170
-rw-r--r--spec/javascripts/ide/components/file_templates/bar_spec.js117
-rw-r--r--spec/javascripts/ide/components/ide_review_spec.js69
-rw-r--r--spec/javascripts/ide/components/ide_side_bar_spec.js57
-rw-r--r--spec/javascripts/ide/components/ide_spec.js125
-rw-r--r--spec/javascripts/ide/components/ide_status_bar_spec.js129
-rw-r--r--spec/javascripts/ide/components/ide_tree_list_spec.js77
-rw-r--r--spec/javascripts/ide/components/ide_tree_spec.js34
-rw-r--r--spec/javascripts/ide/components/jobs/detail/description_spec.js28
-rw-r--r--spec/javascripts/ide/components/jobs/item_spec.js39
-rw-r--r--spec/javascripts/ide/components/merge_requests/item_spec.js63
-rw-r--r--spec/javascripts/ide/components/nav_dropdown_button_spec.js93
-rw-r--r--spec/javascripts/ide/components/nav_dropdown_spec.js80
-rw-r--r--spec/javascripts/ide/components/new_dropdown/button_spec.js65
-rw-r--r--spec/javascripts/ide/components/new_dropdown/index_spec.js84
-rw-r--r--spec/javascripts/ide/components/new_dropdown/modal_spec.js150
-rw-r--r--spec/javascripts/ide/components/new_dropdown/upload_spec.js112
-rw-r--r--spec/javascripts/ide/components/repo_editor_spec.js43
-rw-r--r--spec/javascripts/ide/components/repo_tab_spec.js185
-rw-r--r--spec/javascripts/ide/components/repo_tabs_spec.js35
-rw-r--r--spec/javascripts/ide/components/shared/tokened_input_spec.js133
-rw-r--r--spec/javascripts/ide/lib/common/model_manager_spec.js126
-rw-r--r--spec/javascripts/ide/lib/common/model_spec.js137
-rw-r--r--spec/javascripts/ide/lib/decorations/controller_spec.js143
-rw-r--r--spec/javascripts/ide/lib/diff/controller_spec.js215
-rw-r--r--spec/javascripts/ide/lib/editor_spec.js287
-rw-r--r--spec/javascripts/ide/stores/actions/tree_spec.js3
-rw-r--r--spec/javascripts/image_diff/helpers/badge_helper_spec.js130
-rw-r--r--spec/javascripts/image_diff/helpers/comment_indicator_helper_spec.js144
-rw-r--r--spec/javascripts/image_diff/helpers/dom_helper_spec.js120
-rw-r--r--spec/javascripts/image_diff/helpers/utils_helper_spec.js152
-rw-r--r--spec/javascripts/image_diff/image_badge_spec.js96
-rw-r--r--spec/javascripts/image_diff/image_diff_spec.js361
-rw-r--r--spec/javascripts/image_diff/mock_data.js28
-rw-r--r--spec/javascripts/image_diff/replaced_image_diff_spec.js355
-rw-r--r--spec/javascripts/integrations/integration_settings_form_spec.js301
-rw-r--r--spec/javascripts/issuable_spec.js64
-rw-r--r--spec/javascripts/issue_show/components/app_spec.js568
-rw-r--r--spec/javascripts/issue_show/components/description_spec.js210
-rw-r--r--spec/javascripts/issue_show/components/edited_spec.js49
-rw-r--r--spec/javascripts/issue_show/components/fields/description_template_spec.js43
-rw-r--r--spec/javascripts/issue_show/components/form_spec.js98
-rw-r--r--spec/javascripts/issue_show/components/title_spec.js105
-rw-r--r--spec/javascripts/issue_show/helpers.js1
-rw-r--r--spec/javascripts/issue_show/mock_data.js1
-rw-r--r--spec/javascripts/jobs/components/artifacts_block_spec.js119
-rw-r--r--spec/javascripts/jobs/components/commit_block_spec.js89
-rw-r--r--spec/javascripts/jobs/components/empty_state_spec.js141
-rw-r--r--spec/javascripts/jobs/components/environments_block_spec.js261
-rw-r--r--spec/javascripts/jobs/components/job_container_item_spec.js99
-rw-r--r--spec/javascripts/jobs/components/job_log_spec.js65
-rw-r--r--spec/javascripts/jobs/components/jobs_container_spec.js131
-rw-r--r--spec/javascripts/jobs/components/manual_variables_form_spec.js103
-rw-r--r--spec/javascripts/jobs/components/sidebar_spec.js169
-rw-r--r--spec/javascripts/jobs/components/stages_dropdown_spec.js163
-rw-r--r--spec/javascripts/jobs/components/trigger_block_spec.js100
-rw-r--r--spec/javascripts/jobs/components/unmet_prerequisites_block_spec.js37
-rw-r--r--spec/javascripts/jobs/mixins/delayed_job_mixin_spec.js93
-rw-r--r--spec/javascripts/jobs/store/actions_spec.js512
-rw-r--r--spec/javascripts/jobs/store/helpers.js6
-rw-r--r--spec/javascripts/landing_spec.js166
-rw-r--r--spec/javascripts/lib/utils/csrf_token_spec.js50
-rw-r--r--spec/javascripts/lib/utils/navigation_utility_spec.js23
-rw-r--r--spec/javascripts/lib/utils/poll_spec.js222
-rw-r--r--spec/javascripts/lib/utils/sticky_spec.js66
-rw-r--r--spec/javascripts/line_highlighter_spec.js17
-rw-r--r--spec/javascripts/monitoring/components/dashboard_resize_browser_spec.js (renamed from spec/javascripts/monitoring/components/dashboard_resize_spec.js)7
-rw-r--r--spec/javascripts/notebook/cells/code_spec.js74
-rw-r--r--spec/javascripts/notebook/cells/markdown_spec.js105
-rw-r--r--spec/javascripts/notebook/cells/output/html_sanitize_tests.js68
-rw-r--r--spec/javascripts/notebook/cells/output/html_spec.js31
-rw-r--r--spec/javascripts/notebook/cells/output/index_spec.js115
-rw-r--r--spec/javascripts/notebook/cells/prompt_spec.js56
-rw-r--r--spec/javascripts/notebook/index_spec.js100
-rw-r--r--spec/javascripts/oauth_remember_me_spec.js39
-rw-r--r--spec/javascripts/pages/admin/application_settings/account_and_limits_spec.js36
-rw-r--r--spec/javascripts/pages/admin/jobs/index/components/stop_jobs_modal_spec.js61
-rw-r--r--spec/javascripts/pages/admin/users/new/index_spec.js43
-rw-r--r--spec/javascripts/pages/labels/components/promote_label_modal_spec.js103
-rw-r--r--spec/javascripts/pages/milestones/shared/components/delete_milestone_modal_spec.js106
-rw-r--r--spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js98
-rw-r--r--spec/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js192
-rw-r--r--spec/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js106
-rw-r--r--spec/javascripts/pages/sessions/new/preserve_url_fragment_spec.js61
-rw-r--r--spec/javascripts/pipelines/header_component_spec.js108
-rw-r--r--spec/javascripts/pipelines/linked_pipelines_mock.json3535
-rw-r--r--spec/javascripts/pipelines/mock_data.js423
-rw-r--r--spec/javascripts/pipelines/pipeline_details_mediator_spec.js36
-rw-r--r--spec/javascripts/pipelines/pipelines_actions_spec.js128
-rw-r--r--spec/javascripts/pipelines/pipelines_artifacts_spec.js38
-rw-r--r--spec/javascripts/pipelines/pipelines_spec.js783
-rw-r--r--spec/javascripts/pipelines/pipelines_table_spec.js86
-rw-r--r--spec/javascripts/pipelines/stage_spec.js136
-rw-r--r--spec/javascripts/pipelines/stores/pipeline.json167
-rw-r--r--spec/javascripts/pipelines/stores/pipeline_store.js165
-rw-r--r--spec/javascripts/pipelines/stores/pipeline_with_triggered.json381
-rw-r--r--spec/javascripts/pipelines/stores/pipeline_with_triggered_by.json379
-rw-r--r--spec/javascripts/pipelines/stores/pipeline_with_triggered_triggered_by.json452
-rw-r--r--spec/javascripts/pipelines/time_ago_spec.js64
-rw-r--r--spec/javascripts/pipelines_spec.js19
-rw-r--r--spec/javascripts/prometheus_metrics/mock_data.js41
-rw-r--r--spec/javascripts/prometheus_metrics/prometheus_metrics_spec.js178
-rw-r--r--spec/javascripts/related_merge_requests/components/related_merge_requests_spec.js88
-rw-r--r--spec/javascripts/related_merge_requests/store/actions_spec.js110
-rw-r--r--spec/javascripts/related_merge_requests/store/mutations_spec.js49
-rw-r--r--spec/javascripts/reports/components/grouped_test_reports_app_spec.js239
-rw-r--r--spec/javascripts/reports/components/modal_open_name_spec.js47
-rw-r--r--spec/javascripts/reports/components/modal_spec.js54
-rw-r--r--spec/javascripts/reports/components/summary_row_spec.js37
-rw-r--r--spec/javascripts/reports/components/test_issue_body_spec.js72
-rw-r--r--spec/javascripts/reports/mock_data/mock_data.js8
-rw-r--r--spec/javascripts/reports/mock_data/new_and_fixed_failures_report.json55
-rw-r--r--spec/javascripts/reports/mock_data/new_errors_report.json38
-rw-r--r--spec/javascripts/reports/mock_data/new_failures_report.json38
-rw-r--r--spec/javascripts/reports/mock_data/no_failures_report.json28
-rw-r--r--spec/javascripts/reports/mock_data/resolved_failures.json58
-rw-r--r--spec/javascripts/reports/store/actions_spec.js171
-rw-r--r--spec/javascripts/reports/store/mutations_spec.js126
-rw-r--r--spec/javascripts/search_autocomplete_spec.js24
-rw-r--r--spec/javascripts/settings_panels_spec.js45
-rw-r--r--spec/javascripts/sidebar/components/time_tracking/time_tracker_spec.js278
-rw-r--r--spec/javascripts/sidebar/lock/edit_form_buttons_spec.js32
-rw-r--r--spec/javascripts/sidebar/lock/lock_issue_sidebar_spec.js99
-rw-r--r--spec/javascripts/sidebar/mock_data.js7
-rw-r--r--spec/javascripts/sidebar/participants_spec.js202
-rw-r--r--spec/javascripts/sidebar/sidebar_mediator_spec.js134
-rw-r--r--spec/javascripts/sidebar/sidebar_move_issue_spec.js166
-rw-r--r--spec/javascripts/sidebar/sidebar_subscriptions_spec.js38
-rw-r--r--spec/javascripts/sidebar/subscriptions_spec.js100
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js4
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js99
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js13
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js7
-rw-r--r--spec/javascripts/vue_mr_widget/stores/artifacts_list/actions_spec.js165
-rw-r--r--spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js112
-rw-r--r--spec/javascripts/vue_shared/components/ci_badge_link_spec.js100
-rw-r--r--spec/javascripts/vue_shared/components/ci_icon_spec.js122
-rw-r--r--spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js123
-rw-r--r--spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js105
-rw-r--r--spec/javascripts/vue_shared/components/dropdown/dropdown_button_spec.js81
-rw-r--r--spec/javascripts/vue_shared/components/dropdown/dropdown_hidden_input_spec.js36
-rw-r--r--spec/javascripts/vue_shared/components/dropdown/mock_data.js11
-rw-r--r--spec/javascripts/vue_shared/components/file_finder/item_spec.js140
-rw-r--r--spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js190
-rw-r--r--spec/javascripts/vue_shared/components/gl_countdown_spec.js77
-rw-r--r--spec/javascripts/vue_shared/components/header_ci_component_spec.js93
-rw-r--r--spec/javascripts/vue_shared/components/markdown/suggestions_spec.js106
-rw-r--r--spec/javascripts/vue_shared/components/markdown/toolbar_spec.js40
-rw-r--r--spec/javascripts/vue_shared/components/navigation_tabs_spec.js64
-rw-r--r--spec/javascripts/vue_shared/components/pikaday_spec.js30
-rw-r--r--spec/javascripts/vue_shared/components/project_avatar/default_spec.js58
-rw-r--r--spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js109
-rw-r--r--spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js142
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/mock_data.js57
-rw-r--r--spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js107
-rw-r--r--spec/javascripts/vue_shared/components/tabs/tab_spec.js32
-rw-r--r--spec/javascripts/vue_shared/components/tabs/tabs_spec.js68
-rw-r--r--spec/javascripts/vue_shared/components/toggle_button_spec.js101
-rw-r--r--spec/javascripts/vue_shared/components/user_avatar/user_avatar_svg_spec.js29
219 files changed, 95 insertions, 29716 deletions
diff --git a/spec/javascripts/ajax_loading_spinner_spec.js b/spec/javascripts/ajax_loading_spinner_spec.js
deleted file mode 100644
index 89195a4397f..00000000000
--- a/spec/javascripts/ajax_loading_spinner_spec.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import $ from 'jquery';
-import AjaxLoadingSpinner from '~/ajax_loading_spinner';
-
-describe('Ajax Loading Spinner', () => {
- const fixtureTemplate = 'static/ajax_loading_spinner.html';
- preloadFixtures(fixtureTemplate);
-
- beforeEach(() => {
- loadFixtures(fixtureTemplate);
- AjaxLoadingSpinner.init();
- });
-
- it('change current icon with spinner icon and disable link while waiting ajax response', done => {
- spyOn($, 'ajax').and.callFake(req => {
- const xhr = new XMLHttpRequest();
- const ajaxLoadingSpinner = document.querySelector('.js-ajax-loading-spinner');
- const icon = ajaxLoadingSpinner.querySelector('i');
-
- req.beforeSend(xhr, { dataType: 'text/html' });
-
- expect(icon).not.toHaveClass('fa-trash-o');
- expect(icon).toHaveClass('fa-spinner');
- expect(icon).toHaveClass('fa-spin');
- expect(icon.dataset.icon).toEqual('fa-trash-o');
- expect(ajaxLoadingSpinner.getAttribute('disabled')).toEqual('');
-
- req.complete({});
-
- done();
- const deferred = $.Deferred();
- return deferred.promise();
- });
- document.querySelector('.js-ajax-loading-spinner').click();
- });
-
- it('use original icon again and enabled the link after complete the ajax request', done => {
- spyOn($, 'ajax').and.callFake(req => {
- const xhr = new XMLHttpRequest();
- const ajaxLoadingSpinner = document.querySelector('.js-ajax-loading-spinner');
-
- req.beforeSend(xhr, { dataType: 'text/html' });
- req.complete({});
-
- const icon = ajaxLoadingSpinner.querySelector('i');
-
- expect(icon).toHaveClass('fa-trash-o');
- expect(icon).not.toHaveClass('fa-spinner');
- expect(icon).not.toHaveClass('fa-spin');
- expect(ajaxLoadingSpinner.getAttribute('disabled')).toEqual(null);
-
- done();
- const deferred = $.Deferred();
- return deferred.promise();
- });
- document.querySelector('.js-ajax-loading-spinner').click();
- });
-});
diff --git a/spec/javascripts/avatar_helper_spec.js b/spec/javascripts/avatar_helper_spec.js
deleted file mode 100644
index c1ef08e0f1b..00000000000
--- a/spec/javascripts/avatar_helper_spec.js
+++ /dev/null
@@ -1,98 +0,0 @@
-import { TEST_HOST } from 'spec/test_constants';
-import { getFirstCharacterCapitalized } from '~/lib/utils/text_utility';
-import {
- DEFAULT_SIZE_CLASS,
- IDENTICON_BG_COUNT,
- renderAvatar,
- renderIdenticon,
- getIdenticonBackgroundClass,
- getIdenticonTitle,
-} from '~/helpers/avatar_helper';
-
-function matchAll(str) {
- return new RegExp(`^${str}$`);
-}
-
-describe('avatar_helper', () => {
- describe('getIdenticonBackgroundClass', () => {
- it('returns identicon bg class from id', () => {
- expect(getIdenticonBackgroundClass(1)).toEqual('bg2');
- });
-
- it(`wraps around if id is bigger than ${IDENTICON_BG_COUNT}`, () => {
- expect(getIdenticonBackgroundClass(IDENTICON_BG_COUNT + 4)).toEqual('bg5');
- expect(getIdenticonBackgroundClass(IDENTICON_BG_COUNT * 5 + 6)).toEqual('bg7');
- });
- });
-
- describe('getIdenticonTitle', () => {
- it('returns identicon title from name', () => {
- expect(getIdenticonTitle('Lorem')).toEqual('L');
- expect(getIdenticonTitle('dolar-sit-amit')).toEqual('D');
- expect(getIdenticonTitle('%-with-special-chars')).toEqual('%');
- });
-
- it('returns space if name is falsey', () => {
- expect(getIdenticonTitle('')).toEqual(' ');
- expect(getIdenticonTitle(null)).toEqual(' ');
- });
- });
-
- describe('renderIdenticon', () => {
- it('renders with the first letter as title and bg based on id', () => {
- const entity = {
- id: IDENTICON_BG_COUNT + 3,
- name: 'Xavior',
- };
- const options = {
- sizeClass: 's32',
- };
-
- const result = renderIdenticon(entity, options);
-
- expect(result).toHaveClass(`identicon ${options.sizeClass} bg4`);
- expect(result).toHaveText(matchAll(getFirstCharacterCapitalized(entity.name)));
- });
-
- it('renders with defaults, if no options are given', () => {
- const entity = {
- id: 1,
- name: 'tanuki',
- };
-
- const result = renderIdenticon(entity);
-
- expect(result).toHaveClass(`identicon ${DEFAULT_SIZE_CLASS} bg2`);
- expect(result).toHaveText(matchAll(getFirstCharacterCapitalized(entity.name)));
- });
- });
-
- describe('renderAvatar', () => {
- it('renders an image with the avatarUrl', () => {
- const avatarUrl = `${TEST_HOST}/not-real-assets/test.png`;
-
- const result = renderAvatar({
- avatar_url: avatarUrl,
- });
-
- expect(result).toBeMatchedBy('img');
- expect(result).toHaveAttr('src', avatarUrl);
- expect(result).toHaveClass(DEFAULT_SIZE_CLASS);
- });
-
- it('renders an identicon if no avatarUrl', () => {
- const entity = {
- id: 1,
- name: 'walrus',
- };
- const options = {
- sizeClass: 's16',
- };
-
- const result = renderAvatar(entity, options);
-
- expect(result).toHaveClass(`identicon ${options.sizeClass} bg2`);
- expect(result).toHaveText(matchAll(getFirstCharacterCapitalized(entity.name)));
- });
- });
-});
diff --git a/spec/javascripts/bootstrap_linked_tabs_spec.js b/spec/javascripts/bootstrap_linked_tabs_spec.js
deleted file mode 100644
index 1d21637ceae..00000000000
--- a/spec/javascripts/bootstrap_linked_tabs_spec.js
+++ /dev/null
@@ -1,67 +0,0 @@
-import LinkedTabs from '~/lib/utils/bootstrap_linked_tabs';
-
-describe('Linked Tabs', () => {
- preloadFixtures('static/linked_tabs.html');
-
- beforeEach(() => {
- loadFixtures('static/linked_tabs.html');
- });
-
- describe('when is initialized', () => {
- beforeEach(() => {
- spyOn(window.history, 'replaceState').and.callFake(function() {});
- });
-
- it('should activate the tab correspondent to the given action', () => {
- // eslint-disable-next-line no-new
- new LinkedTabs({
- action: 'tab1',
- defaultAction: 'tab1',
- parentEl: '.linked-tabs',
- });
-
- expect(document.querySelector('#tab1').classList).toContain('active');
- });
-
- it('should active the default tab action when the action is show', () => {
- // eslint-disable-next-line no-new
- new LinkedTabs({
- action: 'show',
- defaultAction: 'tab1',
- parentEl: '.linked-tabs',
- });
-
- expect(document.querySelector('#tab1').classList).toContain('active');
- });
- });
-
- describe('on click', () => {
- it('should change the url according to the clicked tab', () => {
- const historySpy = spyOn(window.history, 'replaceState').and.callFake(() => {});
-
- const linkedTabs = new LinkedTabs({
- action: 'show',
- defaultAction: 'tab1',
- parentEl: '.linked-tabs',
- });
-
- const secondTab = document.querySelector('.linked-tabs li:nth-child(2) a');
- const newState =
- secondTab.getAttribute('href') +
- linkedTabs.currentLocation.search +
- linkedTabs.currentLocation.hash;
-
- secondTab.click();
-
- if (historySpy) {
- expect(historySpy).toHaveBeenCalledWith(
- {
- url: newState,
- },
- document.title,
- newState,
- );
- }
- });
- });
-});
diff --git a/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js b/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js
deleted file mode 100644
index a1377564073..00000000000
--- a/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js
+++ /dev/null
@@ -1,231 +0,0 @@
-import $ from 'jquery';
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import AjaxFormVariableList from '~/ci_variable_list/ajax_variable_list';
-
-const VARIABLE_PATCH_ENDPOINT = 'http://test.host/frontend-fixtures/builds-project/-/variables';
-const HIDE_CLASS = 'hide';
-
-describe('AjaxFormVariableList', () => {
- preloadFixtures('projects/ci_cd_settings.html');
- preloadFixtures('projects/ci_cd_settings_with_variables.html');
-
- let container;
- let saveButton;
- let errorBox;
-
- let mock;
- let ajaxVariableList;
-
- beforeEach(() => {
- loadFixtures('projects/ci_cd_settings.html');
- container = document.querySelector('.js-ci-variable-list-section');
-
- mock = new MockAdapter(axios);
-
- const ajaxVariableListEl = document.querySelector('.js-ci-variable-list-section');
- saveButton = ajaxVariableListEl.querySelector('.js-ci-variables-save-button');
- errorBox = container.querySelector('.js-ci-variable-error-box');
- ajaxVariableList = new AjaxFormVariableList({
- container,
- formField: 'variables',
- saveButton,
- errorBox,
- saveEndpoint: container.dataset.saveEndpoint,
- maskableRegex: container.dataset.maskableRegex,
- });
-
- spyOn(ajaxVariableList, 'updateRowsWithPersistedVariables').and.callThrough();
- spyOn(ajaxVariableList.variableList, 'toggleEnableRow').and.callThrough();
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- describe('onSaveClicked', () => {
- it('shows loading spinner while waiting for the request', done => {
- const loadingIcon = saveButton.querySelector('.js-ci-variables-save-loading-icon');
-
- mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(() => {
- expect(loadingIcon.classList.contains(HIDE_CLASS)).toEqual(false);
-
- return [200, {}];
- });
-
- expect(loadingIcon.classList.contains(HIDE_CLASS)).toEqual(true);
-
- ajaxVariableList
- .onSaveClicked()
- .then(() => {
- expect(loadingIcon.classList.contains(HIDE_CLASS)).toEqual(true);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('calls `updateRowsWithPersistedVariables` with the persisted variables', done => {
- const variablesResponse = [{ id: 1, key: 'foo', value: 'bar' }];
- mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(200, {
- variables: variablesResponse,
- });
-
- ajaxVariableList
- .onSaveClicked()
- .then(() => {
- expect(ajaxVariableList.updateRowsWithPersistedVariables).toHaveBeenCalledWith(
- variablesResponse,
- );
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('hides any previous error box', done => {
- mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(200);
-
- expect(errorBox.classList.contains(HIDE_CLASS)).toEqual(true);
-
- ajaxVariableList
- .onSaveClicked()
- .then(() => {
- expect(errorBox.classList.contains(HIDE_CLASS)).toEqual(true);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('disables remove buttons while waiting for the request', done => {
- mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(() => {
- expect(ajaxVariableList.variableList.toggleEnableRow).toHaveBeenCalledWith(false);
-
- return [200, {}];
- });
-
- ajaxVariableList
- .onSaveClicked()
- .then(() => {
- expect(ajaxVariableList.variableList.toggleEnableRow).toHaveBeenCalledWith(true);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('hides secret values', done => {
- mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(200, {});
-
- const row = container.querySelector('.js-row');
- const valueInput = row.querySelector('.js-ci-variable-input-value');
- const valuePlaceholder = row.querySelector('.js-secret-value-placeholder');
-
- valueInput.value = 'bar';
- $(valueInput).trigger('input');
-
- expect(valuePlaceholder.classList.contains(HIDE_CLASS)).toBe(true);
- expect(valueInput.classList.contains(HIDE_CLASS)).toBe(false);
-
- ajaxVariableList
- .onSaveClicked()
- .then(() => {
- expect(valuePlaceholder.classList.contains(HIDE_CLASS)).toBe(false);
- expect(valueInput.classList.contains(HIDE_CLASS)).toBe(true);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('shows error box with validation errors', done => {
- const validationError = 'some validation error';
- mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(400, [validationError]);
-
- expect(errorBox.classList.contains(HIDE_CLASS)).toEqual(true);
-
- ajaxVariableList
- .onSaveClicked()
- .then(() => {
- expect(errorBox.classList.contains(HIDE_CLASS)).toEqual(false);
- expect(errorBox.textContent.trim().replace(/\n+\s+/m, ' ')).toEqual(
- `Validation failed ${validationError}`,
- );
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('shows flash message when request fails', done => {
- mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(500);
-
- expect(errorBox.classList.contains(HIDE_CLASS)).toEqual(true);
-
- ajaxVariableList
- .onSaveClicked()
- .then(() => {
- expect(errorBox.classList.contains(HIDE_CLASS)).toEqual(true);
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('updateRowsWithPersistedVariables', () => {
- beforeEach(() => {
- loadFixtures('projects/ci_cd_settings_with_variables.html');
- container = document.querySelector('.js-ci-variable-list-section');
-
- const ajaxVariableListEl = document.querySelector('.js-ci-variable-list-section');
- saveButton = ajaxVariableListEl.querySelector('.js-ci-variables-save-button');
- errorBox = container.querySelector('.js-ci-variable-error-box');
- ajaxVariableList = new AjaxFormVariableList({
- container,
- formField: 'variables',
- saveButton,
- errorBox,
- saveEndpoint: container.dataset.saveEndpoint,
- });
- });
-
- it('removes variable that was removed', () => {
- expect(container.querySelectorAll('.js-row').length).toBe(3);
-
- container.querySelector('.js-row-remove-button').click();
-
- expect(container.querySelectorAll('.js-row').length).toBe(3);
-
- ajaxVariableList.updateRowsWithPersistedVariables([]);
-
- expect(container.querySelectorAll('.js-row').length).toBe(2);
- });
-
- it('updates new variable row with persisted ID', () => {
- const row = container.querySelector('.js-row:last-child');
- const idInput = row.querySelector('.js-ci-variable-input-id');
- const keyInput = row.querySelector('.js-ci-variable-input-key');
- const valueInput = row.querySelector('.js-ci-variable-input-value');
-
- keyInput.value = 'foo';
- $(keyInput).trigger('input');
- valueInput.value = 'bar';
- $(valueInput).trigger('input');
-
- expect(idInput.value).toEqual('');
-
- ajaxVariableList.updateRowsWithPersistedVariables([
- {
- id: 3,
- key: 'foo',
- value: 'bar',
- },
- ]);
-
- expect(idInput.value).toEqual('3');
- expect(row.dataset.isPersisted).toEqual('true');
- });
- });
-
- describe('maskableRegex', () => {
- it('takes in the regex provided by the data attribute', () => {
- expect(container.dataset.maskableRegex).toBe('^[a-zA-Z0-9_+=/@:.-]{8,}$');
- expect(ajaxVariableList.maskableRegex).toBe(container.dataset.maskableRegex);
- });
- });
-});
diff --git a/spec/javascripts/ci_variable_list/ci_variable_list_spec.js b/spec/javascripts/ci_variable_list/ci_variable_list_spec.js
deleted file mode 100644
index c0c3a83a44b..00000000000
--- a/spec/javascripts/ci_variable_list/ci_variable_list_spec.js
+++ /dev/null
@@ -1,294 +0,0 @@
-import $ from 'jquery';
-import getSetTimeoutPromise from 'spec/helpers/set_timeout_promise_helper';
-import VariableList from '~/ci_variable_list/ci_variable_list';
-
-const HIDE_CLASS = 'hide';
-
-describe('VariableList', () => {
- preloadFixtures('pipeline_schedules/edit.html');
- preloadFixtures('pipeline_schedules/edit_with_variables.html');
- preloadFixtures('projects/ci_cd_settings.html');
-
- let $wrapper;
- let variableList;
-
- describe('with only key/value inputs', () => {
- describe('with no variables', () => {
- beforeEach(() => {
- loadFixtures('pipeline_schedules/edit.html');
- $wrapper = $('.js-ci-variable-list-section');
-
- variableList = new VariableList({
- container: $wrapper,
- formField: 'schedule',
- });
- variableList.init();
- });
-
- it('should remove the row when clicking the remove button', () => {
- $wrapper.find('.js-row-remove-button').trigger('click');
-
- expect($wrapper.find('.js-row').length).toBe(0);
- });
-
- it('should add another row when editing the last rows key input', () => {
- const $row = $wrapper.find('.js-row');
- $row
- .find('.js-ci-variable-input-key')
- .val('foo')
- .trigger('input');
-
- expect($wrapper.find('.js-row').length).toBe(2);
-
- // Check for the correct default in the new row
- const $keyInput = $wrapper.find('.js-row:last-child').find('.js-ci-variable-input-key');
-
- expect($keyInput.val()).toBe('');
- });
-
- it('should add another row when editing the last rows value textarea', () => {
- const $row = $wrapper.find('.js-row');
- $row
- .find('.js-ci-variable-input-value')
- .val('foo')
- .trigger('input');
-
- expect($wrapper.find('.js-row').length).toBe(2);
-
- // Check for the correct default in the new row
- const $valueInput = $wrapper.find('.js-row:last-child').find('.js-ci-variable-input-key');
-
- expect($valueInput.val()).toBe('');
- });
-
- it('should remove empty row after blurring', () => {
- const $row = $wrapper.find('.js-row');
- $row
- .find('.js-ci-variable-input-key')
- .val('foo')
- .trigger('input');
-
- expect($wrapper.find('.js-row').length).toBe(2);
-
- $row
- .find('.js-ci-variable-input-key')
- .val('')
- .trigger('input')
- .trigger('blur');
-
- expect($wrapper.find('.js-row').length).toBe(1);
- });
- });
-
- describe('with persisted variables', () => {
- beforeEach(() => {
- loadFixtures('pipeline_schedules/edit_with_variables.html');
- $wrapper = $('.js-ci-variable-list-section');
-
- variableList = new VariableList({
- container: $wrapper,
- formField: 'schedule',
- });
- variableList.init();
- });
-
- it('should have "Reveal values" button initially when there are already variables', () => {
- expect($wrapper.find('.js-secret-value-reveal-button').text()).toBe('Reveal values');
- });
-
- it('should reveal hidden values', () => {
- const $row = $wrapper.find('.js-row:first-child');
- const $inputValue = $row.find('.js-ci-variable-input-value');
- const $placeholder = $row.find('.js-secret-value-placeholder');
-
- expect($placeholder.hasClass(HIDE_CLASS)).toBe(false);
- expect($inputValue.hasClass(HIDE_CLASS)).toBe(true);
-
- // Reveal values
- $wrapper.find('.js-secret-value-reveal-button').click();
-
- expect($placeholder.hasClass(HIDE_CLASS)).toBe(true);
- expect($inputValue.hasClass(HIDE_CLASS)).toBe(false);
- });
- });
- });
-
- describe('with all inputs(key, value, protected)', () => {
- beforeEach(() => {
- loadFixtures('projects/ci_cd_settings.html');
- $wrapper = $('.js-ci-variable-list-section');
-
- $wrapper.find('.js-ci-variable-input-protected').attr('data-default', 'false');
-
- variableList = new VariableList({
- container: $wrapper,
- formField: 'variables',
- });
- variableList.init();
- });
-
- it('should not add another row when editing the last rows protected checkbox', done => {
- const $row = $wrapper.find('.js-row:last-child');
- $row.find('.ci-variable-protected-item .js-project-feature-toggle').click();
-
- getSetTimeoutPromise()
- .then(() => {
- expect($wrapper.find('.js-row').length).toBe(1);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('should not add another row when editing the last rows masked checkbox', done => {
- const $row = $wrapper.find('.js-row:last-child');
- $row.find('.ci-variable-masked-item .js-project-feature-toggle').click();
-
- getSetTimeoutPromise()
- .then(() => {
- expect($wrapper.find('.js-row').length).toBe(1);
- })
- .then(done)
- .catch(done.fail);
- });
-
- describe('validateMaskability', () => {
- let $row;
-
- const maskingErrorElement = '.js-row:last-child .masking-validation-error';
-
- beforeEach(() => {
- $row = $wrapper.find('.js-row:last-child');
- $row.find('.ci-variable-masked-item .js-project-feature-toggle').click();
- });
-
- it('has a regex provided via a data attribute', () => {
- expect($wrapper.attr('data-maskable-regex')).toBe('^[a-zA-Z0-9_+=/@:.-]{8,}$');
- });
-
- it('allows values that are 8 characters long', done => {
- $row.find('.js-ci-variable-input-value').val('looooong');
-
- getSetTimeoutPromise()
- .then(() => {
- expect($wrapper.find(maskingErrorElement)).toHaveClass('hide');
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('rejects values that are shorter than 8 characters', done => {
- $row.find('.js-ci-variable-input-value').val('short');
-
- getSetTimeoutPromise()
- .then(() => {
- expect($wrapper.find(maskingErrorElement)).toBeVisible();
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('allows values with base 64 characters', done => {
- $row.find('.js-ci-variable-input-value').val('abcABC123_+=/-');
-
- getSetTimeoutPromise()
- .then(() => {
- expect($wrapper.find(maskingErrorElement)).toHaveClass('hide');
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('rejects values with other special characters', done => {
- $row.find('.js-ci-variable-input-value').val('1234567$');
-
- getSetTimeoutPromise()
- .then(() => {
- expect($wrapper.find(maskingErrorElement)).toBeVisible();
- })
- .then(done)
- .catch(done.fail);
- });
- });
- });
-
- describe('toggleEnableRow method', () => {
- beforeEach(() => {
- loadFixtures('pipeline_schedules/edit_with_variables.html');
- $wrapper = $('.js-ci-variable-list-section');
-
- variableList = new VariableList({
- container: $wrapper,
- formField: 'variables',
- });
- variableList.init();
- });
-
- it('should disable all key inputs', () => {
- expect($wrapper.find('.js-ci-variable-input-key:not([disabled])').length).toBe(3);
-
- variableList.toggleEnableRow(false);
-
- expect($wrapper.find('.js-ci-variable-input-key[disabled]').length).toBe(3);
- });
-
- it('should disable all remove buttons', () => {
- expect($wrapper.find('.js-row-remove-button:not([disabled])').length).toBe(3);
-
- variableList.toggleEnableRow(false);
-
- expect($wrapper.find('.js-row-remove-button[disabled]').length).toBe(3);
- });
-
- it('should enable all remove buttons', () => {
- variableList.toggleEnableRow(false);
-
- expect($wrapper.find('.js-row-remove-button[disabled]').length).toBe(3);
-
- variableList.toggleEnableRow(true);
-
- expect($wrapper.find('.js-row-remove-button:not([disabled])').length).toBe(3);
- });
-
- it('should enable all key inputs', () => {
- variableList.toggleEnableRow(false);
-
- expect($wrapper.find('.js-ci-variable-input-key[disabled]').length).toBe(3);
-
- variableList.toggleEnableRow(true);
-
- expect($wrapper.find('.js-ci-variable-input-key:not([disabled])').length).toBe(3);
- });
- });
-
- describe('hideValues', () => {
- beforeEach(() => {
- loadFixtures('projects/ci_cd_settings.html');
- $wrapper = $('.js-ci-variable-list-section');
-
- variableList = new VariableList({
- container: $wrapper,
- formField: 'variables',
- });
- variableList.init();
- });
-
- it('should hide value input and show placeholder stars', () => {
- const $row = $wrapper.find('.js-row');
- const $inputValue = $row.find('.js-ci-variable-input-value');
- const $placeholder = $row.find('.js-secret-value-placeholder');
-
- $row
- .find('.js-ci-variable-input-value')
- .val('foo')
- .trigger('input');
-
- expect($placeholder.hasClass(HIDE_CLASS)).toBe(true);
- expect($inputValue.hasClass(HIDE_CLASS)).toBe(false);
-
- variableList.hideValues();
-
- expect($placeholder.hasClass(HIDE_CLASS)).toBe(false);
- expect($inputValue.hasClass(HIDE_CLASS)).toBe(true);
- });
- });
-});
diff --git a/spec/javascripts/ci_variable_list/native_form_variable_list_spec.js b/spec/javascripts/ci_variable_list/native_form_variable_list_spec.js
deleted file mode 100644
index 4982b68fa81..00000000000
--- a/spec/javascripts/ci_variable_list/native_form_variable_list_spec.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import $ from 'jquery';
-import setupNativeFormVariableList from '~/ci_variable_list/native_form_variable_list';
-
-describe('NativeFormVariableList', () => {
- preloadFixtures('pipeline_schedules/edit.html');
-
- let $wrapper;
-
- beforeEach(() => {
- loadFixtures('pipeline_schedules/edit.html');
- $wrapper = $('.js-ci-variable-list-section');
-
- setupNativeFormVariableList({
- container: $wrapper,
- formField: 'schedule',
- });
- });
-
- describe('onFormSubmit', () => {
- it('should clear out the `name` attribute on the inputs for the last empty row on form submission (avoid BE validation)', () => {
- const $row = $wrapper.find('.js-row');
-
- expect($row.find('.js-ci-variable-input-key').attr('name')).toBe(
- 'schedule[variables_attributes][][key]',
- );
-
- expect($row.find('.js-ci-variable-input-value').attr('name')).toBe(
- 'schedule[variables_attributes][][secret_value]',
- );
-
- $wrapper.closest('form').trigger('trigger-submit');
-
- expect($row.find('.js-ci-variable-input-key').attr('name')).toBe('');
- expect($row.find('.js-ci-variable-input-value').attr('name')).toBe('');
- });
- });
-});
diff --git a/spec/javascripts/close_reopen_report_toggle_spec.js b/spec/javascripts/close_reopen_report_toggle_spec.js
deleted file mode 100644
index 04a7ae7f429..00000000000
--- a/spec/javascripts/close_reopen_report_toggle_spec.js
+++ /dev/null
@@ -1,272 +0,0 @@
-/* eslint-disable jasmine/no-unsafe-spy */
-
-import CloseReopenReportToggle from '~/close_reopen_report_toggle';
-import DropLab from '~/droplab/drop_lab';
-
-describe('CloseReopenReportToggle', () => {
- describe('class constructor', () => {
- const dropdownTrigger = {};
- const dropdownList = {};
- const button = {};
- let commentTypeToggle;
-
- beforeEach(function() {
- commentTypeToggle = new CloseReopenReportToggle({
- dropdownTrigger,
- dropdownList,
- button,
- });
- });
-
- it('sets .dropdownTrigger', function() {
- expect(commentTypeToggle.dropdownTrigger).toBe(dropdownTrigger);
- });
-
- it('sets .dropdownList', function() {
- expect(commentTypeToggle.dropdownList).toBe(dropdownList);
- });
-
- it('sets .button', function() {
- expect(commentTypeToggle.button).toBe(button);
- });
- });
-
- describe('initDroplab', () => {
- let closeReopenReportToggle;
- const dropdownList = jasmine.createSpyObj('dropdownList', ['querySelector']);
- const dropdownTrigger = {};
- const button = {};
- const reopenItem = {};
- const closeItem = {};
- const config = {};
-
- beforeEach(() => {
- spyOn(DropLab.prototype, 'init');
- dropdownList.querySelector.and.returnValues(reopenItem, closeItem);
-
- closeReopenReportToggle = new CloseReopenReportToggle({
- dropdownTrigger,
- dropdownList,
- button,
- });
-
- spyOn(closeReopenReportToggle, 'setConfig').and.returnValue(config);
-
- closeReopenReportToggle.initDroplab();
- });
-
- it('sets .reopenItem and .closeItem', () => {
- expect(dropdownList.querySelector).toHaveBeenCalledWith('.reopen-item');
- expect(dropdownList.querySelector).toHaveBeenCalledWith('.close-item');
- expect(closeReopenReportToggle.reopenItem).toBe(reopenItem);
- expect(closeReopenReportToggle.closeItem).toBe(closeItem);
- });
-
- it('sets .droplab', () => {
- expect(closeReopenReportToggle.droplab).toEqual(jasmine.any(Object));
- });
-
- it('calls .setConfig', () => {
- expect(closeReopenReportToggle.setConfig).toHaveBeenCalled();
- });
-
- it('calls droplab.init', () => {
- expect(DropLab.prototype.init).toHaveBeenCalledWith(
- dropdownTrigger,
- dropdownList,
- jasmine.any(Array),
- config,
- );
- });
- });
-
- describe('updateButton', () => {
- let closeReopenReportToggle;
- const dropdownList = {};
- const dropdownTrigger = {};
- const button = jasmine.createSpyObj('button', ['blur']);
- const isClosed = true;
-
- beforeEach(() => {
- closeReopenReportToggle = new CloseReopenReportToggle({
- dropdownTrigger,
- dropdownList,
- button,
- });
-
- spyOn(closeReopenReportToggle, 'toggleButtonType');
-
- closeReopenReportToggle.updateButton(isClosed);
- });
-
- it('calls .toggleButtonType', () => {
- expect(closeReopenReportToggle.toggleButtonType).toHaveBeenCalledWith(isClosed);
- });
-
- it('calls .button.blur', () => {
- expect(closeReopenReportToggle.button.blur).toHaveBeenCalled();
- });
- });
-
- describe('toggleButtonType', () => {
- let closeReopenReportToggle;
- const dropdownList = {};
- const dropdownTrigger = {};
- const button = {};
- const isClosed = true;
- const showItem = jasmine.createSpyObj('showItem', ['click']);
- const hideItem = {};
- showItem.classList = jasmine.createSpyObj('classList', ['add', 'remove']);
- hideItem.classList = jasmine.createSpyObj('classList', ['add', 'remove']);
-
- beforeEach(() => {
- closeReopenReportToggle = new CloseReopenReportToggle({
- dropdownTrigger,
- dropdownList,
- button,
- });
-
- spyOn(closeReopenReportToggle, 'getButtonTypes').and.returnValue([showItem, hideItem]);
-
- closeReopenReportToggle.toggleButtonType(isClosed);
- });
-
- it('calls .getButtonTypes', () => {
- expect(closeReopenReportToggle.getButtonTypes).toHaveBeenCalledWith(isClosed);
- });
-
- it('removes hide class and add selected class to showItem, opposite for hideItem', () => {
- expect(showItem.classList.remove).toHaveBeenCalledWith('hidden');
- expect(showItem.classList.add).toHaveBeenCalledWith('droplab-item-selected');
- expect(hideItem.classList.add).toHaveBeenCalledWith('hidden');
- expect(hideItem.classList.remove).toHaveBeenCalledWith('droplab-item-selected');
- });
-
- it('clicks the showItem', () => {
- expect(showItem.click).toHaveBeenCalled();
- });
- });
-
- describe('getButtonTypes', () => {
- let closeReopenReportToggle;
- const dropdownList = {};
- const dropdownTrigger = {};
- const button = {};
- const reopenItem = {};
- const closeItem = {};
-
- beforeEach(() => {
- closeReopenReportToggle = new CloseReopenReportToggle({
- dropdownTrigger,
- dropdownList,
- button,
- });
-
- closeReopenReportToggle.reopenItem = reopenItem;
- closeReopenReportToggle.closeItem = closeItem;
- });
-
- it('returns reopenItem, closeItem if isClosed is true', () => {
- const buttonTypes = closeReopenReportToggle.getButtonTypes(true);
-
- expect(buttonTypes).toEqual([reopenItem, closeItem]);
- });
-
- it('returns closeItem, reopenItem if isClosed is false', () => {
- const buttonTypes = closeReopenReportToggle.getButtonTypes(false);
-
- expect(buttonTypes).toEqual([closeItem, reopenItem]);
- });
- });
-
- describe('setDisable', () => {
- let closeReopenReportToggle;
- const dropdownList = {};
- const dropdownTrigger = jasmine.createSpyObj('button', ['setAttribute', 'removeAttribute']);
- const button = jasmine.createSpyObj('button', ['setAttribute', 'removeAttribute']);
-
- beforeEach(() => {
- closeReopenReportToggle = new CloseReopenReportToggle({
- dropdownTrigger,
- dropdownList,
- button,
- });
- });
-
- it('disable .button and .dropdownTrigger if shouldDisable is true', () => {
- closeReopenReportToggle.setDisable(true);
-
- expect(button.setAttribute).toHaveBeenCalledWith('disabled', 'true');
- expect(dropdownTrigger.setAttribute).toHaveBeenCalledWith('disabled', 'true');
- });
-
- it('disable .button and .dropdownTrigger if shouldDisable is undefined', () => {
- closeReopenReportToggle.setDisable();
-
- expect(button.setAttribute).toHaveBeenCalledWith('disabled', 'true');
- expect(dropdownTrigger.setAttribute).toHaveBeenCalledWith('disabled', 'true');
- });
-
- it('enable .button and .dropdownTrigger if shouldDisable is false', () => {
- closeReopenReportToggle.setDisable(false);
-
- expect(button.removeAttribute).toHaveBeenCalledWith('disabled');
- expect(dropdownTrigger.removeAttribute).toHaveBeenCalledWith('disabled');
- });
- });
-
- describe('setConfig', () => {
- let closeReopenReportToggle;
- const dropdownList = {};
- const dropdownTrigger = {};
- const button = {};
- let config;
-
- beforeEach(() => {
- closeReopenReportToggle = new CloseReopenReportToggle({
- dropdownTrigger,
- dropdownList,
- button,
- });
-
- config = closeReopenReportToggle.setConfig();
- });
-
- it('returns a config object', () => {
- expect(config).toEqual({
- InputSetter: [
- {
- input: button,
- valueAttribute: 'data-text',
- inputAttribute: 'data-value',
- },
- {
- input: button,
- valueAttribute: 'data-text',
- inputAttribute: 'title',
- },
- {
- input: button,
- valueAttribute: 'data-button-class',
- inputAttribute: 'class',
- },
- {
- input: dropdownTrigger,
- valueAttribute: 'data-toggle-class',
- inputAttribute: 'class',
- },
- {
- input: button,
- valueAttribute: 'data-url',
- inputAttribute: 'href',
- },
- {
- input: button,
- valueAttribute: 'data-method',
- inputAttribute: 'data-method',
- },
- ],
- });
- });
- });
-});
diff --git a/spec/javascripts/commit_merge_requests_spec.js b/spec/javascripts/commit_merge_requests_spec.js
deleted file mode 100644
index 82968e028d1..00000000000
--- a/spec/javascripts/commit_merge_requests_spec.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import * as CommitMergeRequests from '~/commit_merge_requests';
-
-describe('CommitMergeRequests', () => {
- describe('createContent', () => {
- it('should return created content', () => {
- const content1 = CommitMergeRequests.createContent([
- { iid: 1, path: '/path1', title: 'foo' },
- { iid: 2, path: '/path2', title: 'baz' },
- ])[0];
-
- expect(content1.tagName).toEqual('SPAN');
- expect(content1.childElementCount).toEqual(4);
-
- const content2 = CommitMergeRequests.createContent([])[0];
-
- expect(content2.tagName).toEqual('SPAN');
- expect(content2.childElementCount).toEqual(0);
- expect(content2.innerText).toEqual('No related merge requests found');
- });
- });
-
- describe('getHeaderText', () => {
- it('should return header text', () => {
- expect(CommitMergeRequests.getHeaderText(0, 1)).toEqual('1 merge request');
- expect(CommitMergeRequests.getHeaderText(0, 2)).toEqual('2 merge requests');
- expect(CommitMergeRequests.getHeaderText(1, 1)).toEqual(',');
- expect(CommitMergeRequests.getHeaderText(1, 2)).toEqual(',');
- });
- });
-
- describe('createHeader', () => {
- it('should return created header', () => {
- const header = CommitMergeRequests.createHeader(0, 1)[0];
-
- expect(header.tagName).toEqual('SPAN');
- expect(header.innerText).toEqual('1 merge request');
- });
- });
-
- describe('createItem', () => {
- it('should return created item', () => {
- const item = CommitMergeRequests.createItem({ iid: 1, path: '/path', title: 'foo' })[0];
-
- expect(item.tagName).toEqual('SPAN');
- expect(item.childElementCount).toEqual(2);
- expect(item.children[0].tagName).toEqual('A');
- expect(item.children[1].tagName).toEqual('SPAN');
- });
- });
-
- describe('createLink', () => {
- it('should return created link', () => {
- const link = CommitMergeRequests.createLink({ iid: 1, path: '/path', title: 'foo' })[0];
-
- expect(link.tagName).toEqual('A');
- expect(link.href).toMatch(/\/path$/);
- expect(link.innerText).toEqual('!1');
- });
- });
-
- describe('createTitle', () => {
- it('should return created title', () => {
- const title = CommitMergeRequests.createTitle({ iid: 1, path: '/path', title: 'foo' })[0];
-
- expect(title.tagName).toEqual('SPAN');
- expect(title.innerText).toEqual('foo');
- });
- });
-});
diff --git a/spec/javascripts/commits_spec.js b/spec/javascripts/commits_spec.js
deleted file mode 100644
index 28b89157bd3..00000000000
--- a/spec/javascripts/commits_spec.js
+++ /dev/null
@@ -1,98 +0,0 @@
-import $ from 'jquery';
-import 'vendor/jquery.endless-scroll';
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import CommitsList from '~/commits';
-import Pager from '~/pager';
-
-describe('Commits List', () => {
- let commitsList;
-
- beforeEach(() => {
- setFixtures(`
- <form class="commits-search-form" action="/h5bp/html5-boilerplate/commits/master">
- <input id="commits-search">
- </form>
- <ol id="commits-list"></ol>
- `);
- spyOn(Pager, 'init').and.stub();
- commitsList = new CommitsList(25);
- });
-
- it('should be defined', () => {
- expect(CommitsList).toBeDefined();
- });
-
- describe('processCommits', () => {
- it('should join commit headers', () => {
- commitsList.$contentList = $(`
- <div>
- <li class="commit-header" data-day="2016-09-20">
- <span class="day">20 Sep, 2016</span>
- <span class="commits-count">1 commit</span>
- </li>
- <li class="commit"></li>
- </div>
- `);
-
- const data = `
- <li class="commit-header" data-day="2016-09-20">
- <span class="day">20 Sep, 2016</span>
- <span class="commits-count">1 commit</span>
- </li>
- <li class="commit"></li>
- `;
-
- // The last commit header should be removed
- // since the previous one has the same data-day value.
- expect(commitsList.processCommits(data).find('li.commit-header').length).toBe(0);
- });
- });
-
- describe('on entering input', () => {
- let ajaxSpy;
- let mock;
-
- beforeEach(() => {
- commitsList.searchField.val('');
-
- spyOn(window.history, 'replaceState').and.stub();
- mock = new MockAdapter(axios);
-
- mock.onGet('/h5bp/html5-boilerplate/commits/master').reply(200, {
- html: '<li>Result</li>',
- });
-
- ajaxSpy = spyOn(axios, 'get').and.callThrough();
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('should save the last search string', done => {
- commitsList.searchField.val('GitLab');
- commitsList
- .filterResults()
- .then(() => {
- expect(ajaxSpy).toHaveBeenCalled();
- expect(commitsList.lastSearch).toEqual('GitLab');
-
- done();
- })
- .catch(done.fail);
- });
-
- it('should not make ajax call if the input does not change', done => {
- commitsList
- .filterResults()
- .then(() => {
- expect(ajaxSpy).not.toHaveBeenCalled();
- expect(commitsList.lastSearch).toEqual('');
-
- done();
- })
- .catch(done.fail);
- });
- });
-});
diff --git a/spec/javascripts/create_item_dropdown_spec.js b/spec/javascripts/create_item_dropdown_spec.js
deleted file mode 100644
index a814952faab..00000000000
--- a/spec/javascripts/create_item_dropdown_spec.js
+++ /dev/null
@@ -1,195 +0,0 @@
-import $ from 'jquery';
-import CreateItemDropdown from '~/create_item_dropdown';
-
-const DROPDOWN_ITEM_DATA = [
- {
- title: 'one',
- id: 'one',
- text: 'one',
- },
- {
- title: 'two',
- id: 'two',
- text: 'two',
- },
- {
- title: 'three',
- id: 'three',
- text: 'three',
- },
-];
-
-describe('CreateItemDropdown', () => {
- preloadFixtures('static/create_item_dropdown.html');
-
- let $wrapperEl;
- let createItemDropdown;
-
- function createItemAndClearInput(text) {
- // Filter for the new item
- $wrapperEl
- .find('.dropdown-input-field')
- .val(text)
- .trigger('input');
-
- // Create the new item
- const $createButton = $wrapperEl.find('.js-dropdown-create-new-item');
- $createButton.click();
-
- // Clear out the filter
- $wrapperEl
- .find('.dropdown-input-field')
- .val('')
- .trigger('input');
- }
-
- beforeEach(() => {
- loadFixtures('static/create_item_dropdown.html');
- $wrapperEl = $('.js-create-item-dropdown-fixture-root');
- });
-
- afterEach(() => {
- $wrapperEl.remove();
- });
-
- describe('items', () => {
- beforeEach(() => {
- createItemDropdown = new CreateItemDropdown({
- $dropdown: $wrapperEl.find('.js-dropdown-menu-toggle'),
- defaultToggleLabel: 'All variables',
- fieldName: 'variable[environment]',
- getData: (term, callback) => {
- callback(DROPDOWN_ITEM_DATA);
- },
- });
- });
-
- it('should have a dropdown item for each piece of data', () => {
- // Get the data in the dropdown
- $('.js-dropdown-menu-toggle').click();
-
- const $itemEls = $wrapperEl.find('.js-dropdown-content a');
-
- expect($itemEls.length).toEqual(DROPDOWN_ITEM_DATA.length);
- });
- });
-
- describe('created items', () => {
- const NEW_ITEM_TEXT = 'foobarbaz';
-
- beforeEach(() => {
- createItemDropdown = new CreateItemDropdown({
- $dropdown: $wrapperEl.find('.js-dropdown-menu-toggle'),
- defaultToggleLabel: 'All variables',
- fieldName: 'variable[environment]',
- getData: (term, callback) => {
- callback(DROPDOWN_ITEM_DATA);
- },
- });
-
- // Open the dropdown
- $('.js-dropdown-menu-toggle').click();
-
- // Filter for the new item
- $wrapperEl
- .find('.dropdown-input-field')
- .val(NEW_ITEM_TEXT)
- .trigger('input');
- });
-
- it('create new item button should include the filter text', () => {
- expect($wrapperEl.find('.js-dropdown-create-new-item code').text()).toEqual(NEW_ITEM_TEXT);
- });
-
- it('should update the dropdown with the newly created item', () => {
- // Create the new item
- const $createButton = $wrapperEl.find('.js-dropdown-create-new-item');
- $createButton.click();
-
- expect($wrapperEl.find('.dropdown-toggle-text').text()).toEqual(NEW_ITEM_TEXT);
- expect($wrapperEl.find('input[name="variable[environment]"]').val()).toEqual(NEW_ITEM_TEXT);
- });
-
- it('should include newly created item in dropdown list', () => {
- createItemAndClearInput(NEW_ITEM_TEXT);
-
- const $itemEls = $wrapperEl.find('.js-dropdown-content a');
-
- expect($itemEls.length).toEqual(1 + DROPDOWN_ITEM_DATA.length);
- expect($($itemEls.get(DROPDOWN_ITEM_DATA.length)).text()).toEqual(NEW_ITEM_TEXT);
- });
-
- it('should not duplicate an item when trying to create an existing item', () => {
- createItemAndClearInput(DROPDOWN_ITEM_DATA[0].text);
-
- const $itemEls = $wrapperEl.find('.js-dropdown-content a');
-
- expect($itemEls.length).toEqual(DROPDOWN_ITEM_DATA.length);
- });
- });
-
- describe('clearDropdown()', () => {
- beforeEach(() => {
- createItemDropdown = new CreateItemDropdown({
- $dropdown: $wrapperEl.find('.js-dropdown-menu-toggle'),
- defaultToggleLabel: 'All variables',
- fieldName: 'variable[environment]',
- getData: (term, callback) => {
- callback(DROPDOWN_ITEM_DATA);
- },
- });
- });
-
- it('should clear all data and filter input', () => {
- const filterInput = $wrapperEl.find('.dropdown-input-field');
-
- // Get the data in the dropdown
- $('.js-dropdown-menu-toggle').click();
-
- // Filter for an item
- filterInput.val('one').trigger('input');
-
- const $itemElsAfterFilter = $wrapperEl.find('.js-dropdown-content a');
-
- expect($itemElsAfterFilter.length).toEqual(1);
-
- createItemDropdown.clearDropdown();
-
- const $itemElsAfterClear = $wrapperEl.find('.js-dropdown-content a');
-
- expect($itemElsAfterClear.length).toEqual(0);
- expect(filterInput.val()).toEqual('');
- });
- });
-
- describe('createNewItemFromValue option', () => {
- beforeEach(() => {
- createItemDropdown = new CreateItemDropdown({
- $dropdown: $wrapperEl.find('.js-dropdown-menu-toggle'),
- defaultToggleLabel: 'All variables',
- fieldName: 'variable[environment]',
- getData: (term, callback) => {
- callback(DROPDOWN_ITEM_DATA);
- },
- createNewItemFromValue: newValue => ({
- title: `${newValue}-title`,
- id: `${newValue}-id`,
- text: `${newValue}-text`,
- }),
- });
- });
-
- it('all items go through createNewItemFromValue', () => {
- // Get the data in the dropdown
- $('.js-dropdown-menu-toggle').click();
-
- createItemAndClearInput('new-item');
-
- const $itemEls = $wrapperEl.find('.js-dropdown-content a');
-
- expect($itemEls.length).toEqual(1 + DROPDOWN_ITEM_DATA.length);
- expect($($itemEls[3]).text()).toEqual('new-item-text');
- expect($wrapperEl.find('.dropdown-toggle-text').text()).toEqual('new-item-title');
- });
- });
-});
diff --git a/spec/javascripts/deploy_keys/components/action_btn_spec.js b/spec/javascripts/deploy_keys/components/action_btn_spec.js
deleted file mode 100644
index 5bf72cc0018..00000000000
--- a/spec/javascripts/deploy_keys/components/action_btn_spec.js
+++ /dev/null
@@ -1,72 +0,0 @@
-import Vue from 'vue';
-import eventHub from '~/deploy_keys/eventhub';
-import actionBtn from '~/deploy_keys/components/action_btn.vue';
-
-describe('Deploy keys action btn', () => {
- const data = getJSONFixture('deploy_keys/keys.json');
- const deployKey = data.enabled_keys[0];
- let vm;
-
- beforeEach(done => {
- const ActionBtnComponent = Vue.extend({
- components: {
- actionBtn,
- },
- data() {
- return {
- deployKey,
- };
- },
- template: `
- <action-btn
- :deploy-key="deployKey"
- type="enable">
- Enable
- </action-btn>`,
- });
-
- vm = new ActionBtnComponent().$mount();
-
- Vue.nextTick()
- .then(done)
- .catch(done.fail);
- });
-
- it('renders the default slot', () => {
- expect(vm.$el.textContent.trim()).toBe('Enable');
- });
-
- it('sends eventHub event with btn type', done => {
- spyOn(eventHub, '$emit');
-
- vm.$el.click();
-
- Vue.nextTick(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('enable.key', deployKey, jasmine.anything());
-
- done();
- });
- });
-
- it('shows loading spinner after click', done => {
- vm.$el.click();
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.fa')).toBeDefined();
-
- done();
- });
- });
-
- it('disables button after click', done => {
- vm.$el.click();
-
- Vue.nextTick(() => {
- expect(vm.$el.classList.contains('disabled')).toBeTruthy();
-
- expect(vm.$el.getAttribute('disabled')).toBe('disabled');
-
- done();
- });
- });
-});
diff --git a/spec/javascripts/deploy_keys/components/app_spec.js b/spec/javascripts/deploy_keys/components/app_spec.js
deleted file mode 100644
index c9a9814d122..00000000000
--- a/spec/javascripts/deploy_keys/components/app_spec.js
+++ /dev/null
@@ -1,155 +0,0 @@
-import Vue from 'vue';
-import MockAdapter from 'axios-mock-adapter';
-import { TEST_HOST } from 'spec/test_constants';
-import axios from '~/lib/utils/axios_utils';
-import eventHub from '~/deploy_keys/eventhub';
-import deployKeysApp from '~/deploy_keys/components/app.vue';
-
-describe('Deploy keys app component', () => {
- const data = getJSONFixture('deploy_keys/keys.json');
- let vm;
- let mock;
-
- beforeEach(done => {
- // set up axios mock before component
- mock = new MockAdapter(axios);
- mock.onGet(`${TEST_HOST}/dummy/`).replyOnce(200, data);
-
- const Component = Vue.extend(deployKeysApp);
-
- vm = new Component({
- propsData: {
- endpoint: `${TEST_HOST}/dummy`,
- projectId: '8',
- },
- }).$mount();
-
- setTimeout(done);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('renders loading icon', done => {
- vm.store.keys = {};
- vm.isLoading = false;
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelectorAll('.deploy-keys .nav-links li').length).toBe(0);
-
- expect(vm.$el.querySelector('.fa-spinner')).toBeDefined();
-
- done();
- });
- });
-
- it('renders keys panels', () => {
- expect(vm.$el.querySelectorAll('.deploy-keys .nav-links li').length).toBe(3);
- });
-
- it('renders the titles with keys count', () => {
- const textContent = selector => {
- const element = vm.$el.querySelector(`${selector}`);
-
- expect(element).not.toBeNull();
- return element.textContent.trim();
- };
-
- expect(textContent('.js-deployKeys-tab-enabled_keys')).toContain('Enabled deploy keys');
- expect(textContent('.js-deployKeys-tab-available_project_keys')).toContain(
- 'Privately accessible deploy keys',
- );
-
- expect(textContent('.js-deployKeys-tab-public_keys')).toContain(
- 'Publicly accessible deploy keys',
- );
-
- expect(textContent('.js-deployKeys-tab-enabled_keys .badge')).toBe(
- `${vm.store.keys.enabled_keys.length}`,
- );
-
- expect(textContent('.js-deployKeys-tab-available_project_keys .badge')).toBe(
- `${vm.store.keys.available_project_keys.length}`,
- );
-
- expect(textContent('.js-deployKeys-tab-public_keys .badge')).toBe(
- `${vm.store.keys.public_keys.length}`,
- );
- });
-
- it('does not render key panels when keys object is empty', done => {
- vm.store.keys = {};
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelectorAll('.deploy-keys .nav-links li').length).toBe(0);
-
- done();
- });
- });
-
- it('re-fetches deploy keys when enabling a key', done => {
- const key = data.public_keys[0];
-
- spyOn(vm.service, 'getKeys');
- spyOn(vm.service, 'enableKey').and.callFake(() => Promise.resolve());
-
- eventHub.$emit('enable.key', key);
-
- Vue.nextTick(() => {
- expect(vm.service.enableKey).toHaveBeenCalledWith(key.id);
- expect(vm.service.getKeys).toHaveBeenCalled();
- done();
- });
- });
-
- it('re-fetches deploy keys when disabling a key', done => {
- const key = data.public_keys[0];
-
- spyOn(window, 'confirm').and.returnValue(true);
- spyOn(vm.service, 'getKeys');
- spyOn(vm.service, 'disableKey').and.callFake(() => Promise.resolve());
-
- eventHub.$emit('disable.key', key);
-
- Vue.nextTick(() => {
- expect(vm.service.disableKey).toHaveBeenCalledWith(key.id);
- expect(vm.service.getKeys).toHaveBeenCalled();
- done();
- });
- });
-
- it('calls disableKey when removing a key', done => {
- const key = data.public_keys[0];
-
- spyOn(window, 'confirm').and.returnValue(true);
- spyOn(vm.service, 'getKeys');
- spyOn(vm.service, 'disableKey').and.callFake(() => Promise.resolve());
-
- eventHub.$emit('remove.key', key);
-
- Vue.nextTick(() => {
- expect(vm.service.disableKey).toHaveBeenCalledWith(key.id);
- expect(vm.service.getKeys).toHaveBeenCalled();
- done();
- });
- });
-
- it('hasKeys returns true when there are keys', () => {
- expect(vm.hasKeys).toEqual(3);
- });
-
- it('resets disable button loading state', done => {
- spyOn(window, 'confirm').and.returnValue(false);
-
- const btn = vm.$el.querySelector('.btn-warning');
-
- btn.click();
-
- Vue.nextTick(() => {
- expect(btn.querySelector('.btn-warning')).not.toExist();
-
- done();
- });
- });
-});
diff --git a/spec/javascripts/deploy_keys/components/key_spec.js b/spec/javascripts/deploy_keys/components/key_spec.js
deleted file mode 100644
index 7117dc4a9ee..00000000000
--- a/spec/javascripts/deploy_keys/components/key_spec.js
+++ /dev/null
@@ -1,157 +0,0 @@
-import Vue from 'vue';
-import DeployKeysStore from '~/deploy_keys/store';
-import key from '~/deploy_keys/components/key.vue';
-import { getTimeago } from '~/lib/utils/datetime_utility';
-
-describe('Deploy keys key', () => {
- let vm;
- const KeyComponent = Vue.extend(key);
- const data = getJSONFixture('deploy_keys/keys.json');
- const createComponent = deployKey => {
- const store = new DeployKeysStore();
- store.keys = data;
-
- vm = new KeyComponent({
- propsData: {
- deployKey,
- store,
- endpoint: 'https://test.host/dummy/endpoint',
- },
- }).$mount();
- };
-
- describe('enabled key', () => {
- const deployKey = data.enabled_keys[0];
-
- beforeEach(done => {
- createComponent(deployKey);
-
- setTimeout(done);
- });
-
- it('renders the keys title', () => {
- expect(vm.$el.querySelector('.title').textContent.trim()).toContain('My title');
- });
-
- it('renders human friendly formatted created date', () => {
- expect(vm.$el.querySelector('.key-created-at').textContent.trim()).toBe(
- `${getTimeago().format(deployKey.created_at)}`,
- );
- });
-
- it('shows pencil button for editing', () => {
- expect(vm.$el.querySelector('.btn .ic-pencil')).toExist();
- });
-
- it('shows disable button when the project is not deletable', () => {
- expect(vm.$el.querySelector('.btn .ic-cancel')).toExist();
- });
-
- it('shows remove button when the project is deletable', done => {
- vm.deployKey.destroyed_when_orphaned = true;
- vm.deployKey.almost_orphaned = true;
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.btn .ic-remove')).toExist();
- done();
- });
- });
- });
-
- describe('deploy key labels', () => {
- it('shows write access title when key has write access', done => {
- vm.deployKey.deploy_keys_projects[0].can_push = true;
-
- Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.deploy-project-label').getAttribute('data-original-title'),
- ).toBe('Write access allowed');
- done();
- });
- });
-
- it('does not show write access title when key has write access', done => {
- vm.deployKey.deploy_keys_projects[0].can_push = false;
-
- Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.deploy-project-label').getAttribute('data-original-title'),
- ).toBe('Read access only');
- done();
- });
- });
-
- it('shows expandable button if more than two projects', () => {
- const labels = vm.$el.querySelectorAll('.deploy-project-label');
-
- expect(labels.length).toBe(2);
- expect(labels[1].textContent).toContain('others');
- expect(labels[1].getAttribute('data-original-title')).toContain('Expand');
- });
-
- it('expands all project labels after click', done => {
- const { length } = vm.deployKey.deploy_keys_projects;
- vm.$el.querySelectorAll('.deploy-project-label')[1].click();
-
- Vue.nextTick(() => {
- const labels = vm.$el.querySelectorAll('.deploy-project-label');
-
- expect(labels.length).toBe(length);
- expect(labels[1].textContent).not.toContain(`+${length} others`);
- expect(labels[1].getAttribute('data-original-title')).not.toContain('Expand');
- done();
- });
- });
-
- it('shows two projects', done => {
- vm.deployKey.deploy_keys_projects = [...vm.deployKey.deploy_keys_projects].slice(0, 2);
-
- Vue.nextTick(() => {
- const labels = vm.$el.querySelectorAll('.deploy-project-label');
-
- expect(labels.length).toBe(2);
- expect(labels[1].textContent).toContain(
- vm.deployKey.deploy_keys_projects[1].project.full_name,
- );
- done();
- });
- });
- });
-
- describe('public keys', () => {
- const deployKey = data.public_keys[0];
-
- beforeEach(done => {
- createComponent(deployKey);
-
- setTimeout(done);
- });
-
- it('renders deploy keys without any enabled projects', done => {
- vm.deployKey.deploy_keys_projects = [];
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.deploy-project-list').textContent.trim()).toBe('None');
-
- done();
- });
- });
-
- it('shows enable button', () => {
- expect(vm.$el.querySelectorAll('.btn')[0].textContent.trim()).toBe('Enable');
- });
-
- it('shows pencil button for editing', () => {
- expect(vm.$el.querySelector('.btn .ic-pencil')).toExist();
- });
-
- it('shows disable button when key is enabled', done => {
- vm.store.keys.enabled_keys.push(deployKey);
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.btn .ic-cancel')).toExist();
-
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/deploy_keys/components/keys_panel_spec.js b/spec/javascripts/deploy_keys/components/keys_panel_spec.js
deleted file mode 100644
index f71f5ccf082..00000000000
--- a/spec/javascripts/deploy_keys/components/keys_panel_spec.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import Vue from 'vue';
-import DeployKeysStore from '~/deploy_keys/store';
-import deployKeysPanel from '~/deploy_keys/components/keys_panel.vue';
-
-describe('Deploy keys panel', () => {
- const data = getJSONFixture('deploy_keys/keys.json');
- let vm;
-
- beforeEach(done => {
- const DeployKeysPanelComponent = Vue.extend(deployKeysPanel);
- const store = new DeployKeysStore();
- store.keys = data;
-
- vm = new DeployKeysPanelComponent({
- propsData: {
- title: 'test',
- keys: data.enabled_keys,
- showHelpBox: true,
- store,
- endpoint: 'https://test.host/dummy/endpoint',
- },
- }).$mount();
-
- setTimeout(done);
- });
-
- it('renders list of keys', () => {
- expect(vm.$el.querySelectorAll('.deploy-key').length).toBe(vm.keys.length);
- });
-
- it('renders table header', () => {
- const tableHeader = vm.$el.querySelector('.table-row-header');
-
- expect(tableHeader).toExist();
- expect(tableHeader.textContent).toContain('Deploy key');
- expect(tableHeader.textContent).toContain('Project usage');
- expect(tableHeader.textContent).toContain('Created');
- });
-
- it('renders help box if keys are empty', done => {
- vm.keys = [];
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.settings-message')).toBeDefined();
-
- expect(vm.$el.querySelector('.settings-message').textContent.trim()).toBe(
- 'No deploy keys found. Create one with the form above.',
- );
-
- done();
- });
- });
-
- it('renders no table header if keys are empty', done => {
- vm.keys = [];
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.table-row-header')).not.toExist();
-
- done();
- });
- });
-});
diff --git a/spec/javascripts/diff_comments_store_spec.js b/spec/javascripts/diff_comments_store_spec.js
deleted file mode 100644
index a6d363ce88e..00000000000
--- a/spec/javascripts/diff_comments_store_spec.js
+++ /dev/null
@@ -1,141 +0,0 @@
-/* eslint-disable jasmine/no-global-setup, dot-notation, jasmine/no-expect-in-setup-teardown */
-/* global CommentsStore */
-
-import '~/diff_notes/models/discussion';
-import '~/diff_notes/models/note';
-import '~/diff_notes/stores/comments';
-
-function createDiscussion(noteId = 1, resolved = true) {
- CommentsStore.create({
- discussionId: 'a',
- noteId,
- canResolve: true,
- resolved,
- resolvedBy: 'test',
- authorName: 'test',
- authorAvatar: 'test',
- noteTruncated: 'test...',
- });
-}
-
-beforeEach(() => {
- CommentsStore.state = {};
-});
-
-describe('New discussion', () => {
- it('creates new discussion', () => {
- expect(Object.keys(CommentsStore.state).length).toBe(0);
- createDiscussion();
-
- expect(Object.keys(CommentsStore.state).length).toBe(1);
- });
-
- it('creates new note in discussion', () => {
- createDiscussion();
- createDiscussion(2);
-
- const discussion = CommentsStore.state['a'];
-
- expect(Object.keys(discussion.notes).length).toBe(2);
- });
-});
-
-describe('Get note', () => {
- beforeEach(() => {
- expect(Object.keys(CommentsStore.state).length).toBe(0);
- createDiscussion();
- });
-
- it('gets note by ID', () => {
- const note = CommentsStore.get('a', 1);
-
- expect(note).toBeDefined();
- expect(note.id).toBe(1);
- });
-});
-
-describe('Delete discussion', () => {
- beforeEach(() => {
- expect(Object.keys(CommentsStore.state).length).toBe(0);
- createDiscussion();
- });
-
- it('deletes discussion by ID', () => {
- CommentsStore.delete('a', 1);
-
- expect(Object.keys(CommentsStore.state).length).toBe(0);
- });
-
- it('deletes discussion when no more notes', () => {
- createDiscussion();
- createDiscussion(2);
-
- expect(Object.keys(CommentsStore.state).length).toBe(1);
- expect(Object.keys(CommentsStore.state['a'].notes).length).toBe(2);
-
- CommentsStore.delete('a', 1);
- CommentsStore.delete('a', 2);
-
- expect(Object.keys(CommentsStore.state).length).toBe(0);
- });
-});
-
-describe('Update note', () => {
- beforeEach(() => {
- expect(Object.keys(CommentsStore.state).length).toBe(0);
- createDiscussion();
- });
-
- it('updates note to be unresolved', () => {
- CommentsStore.update('a', 1, false, 'test');
-
- const note = CommentsStore.get('a', 1);
-
- expect(note.resolved).toBe(false);
- });
-});
-
-describe('Discussion resolved', () => {
- beforeEach(() => {
- expect(Object.keys(CommentsStore.state).length).toBe(0);
- createDiscussion();
- });
-
- it('is resolved with single note', () => {
- const discussion = CommentsStore.state['a'];
-
- expect(discussion.isResolved()).toBe(true);
- });
-
- it('is unresolved with 2 notes', () => {
- const discussion = CommentsStore.state['a'];
- createDiscussion(2, false);
-
- expect(discussion.isResolved()).toBe(false);
- });
-
- it('is resolved with 2 notes', () => {
- const discussion = CommentsStore.state['a'];
- createDiscussion(2);
-
- expect(discussion.isResolved()).toBe(true);
- });
-
- it('resolve all notes', () => {
- const discussion = CommentsStore.state['a'];
- createDiscussion(2, false);
-
- discussion.resolveAllNotes();
-
- expect(discussion.isResolved()).toBe(true);
- });
-
- it('unresolve all notes', () => {
- const discussion = CommentsStore.state['a'];
- createDiscussion(2);
-
- discussion.unResolveAllNotes();
-
- expect(discussion.isResolved()).toBe(false);
- });
-});
diff --git a/spec/javascripts/diffs/create_diffs_store.js b/spec/javascripts/diffs/create_diffs_store.js
deleted file mode 100644
index 9df057dd8b2..00000000000
--- a/spec/javascripts/diffs/create_diffs_store.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// No new code should be added to this file. Instead, modify the
-// file this one re-exports from. For more detail about why, see:
-// https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/31349
-
-export { default } from '../../frontend/diffs/create_diffs_store';
diff --git a/spec/javascripts/diffs/mock_data/diff_discussions.js b/spec/javascripts/diffs/mock_data/diff_discussions.js
deleted file mode 100644
index 17586fddd0f..00000000000
--- a/spec/javascripts/diffs/mock_data/diff_discussions.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// No new code should be added to this file. Instead, modify the
-// file this one re-exports from. For more detail about why, see:
-// https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/31349
-
-export { default } from '../../../frontend/diffs/mock_data/diff_discussions';
diff --git a/spec/javascripts/diffs/mock_data/diff_file.js b/spec/javascripts/diffs/mock_data/diff_file.js
deleted file mode 100644
index 9dc365b7403..00000000000
--- a/spec/javascripts/diffs/mock_data/diff_file.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// No new code should be added to this file. Instead, modify the
-// file this one re-exports from. For more detail about why, see:
-// https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/31349
-
-export { default } from '../../../frontend/diffs/mock_data/diff_file';
diff --git a/spec/javascripts/diffs/mock_data/diff_file_unreadable.js b/spec/javascripts/diffs/mock_data/diff_file_unreadable.js
deleted file mode 100644
index 09a0dc61847..00000000000
--- a/spec/javascripts/diffs/mock_data/diff_file_unreadable.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// No new code should be added to this file. Instead, modify the
-// file this one re-exports from. For more detail about why, see:
-// https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/31349
-
-export { default } from '../../../frontend/diffs/mock_data/diff_file_unreadable';
diff --git a/spec/javascripts/diffs/mock_data/diff_with_commit.js b/spec/javascripts/diffs/mock_data/diff_with_commit.js
deleted file mode 100644
index c36b0239060..00000000000
--- a/spec/javascripts/diffs/mock_data/diff_with_commit.js
+++ /dev/null
@@ -1,7 +0,0 @@
-// No new code should be added to this file. Instead, modify the
-// file this one re-exports from. For more detail about why, see:
-// https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/31349
-
-import getDiffWithCommit from '../../../frontend/diffs/mock_data/diff_with_commit';
-
-export default getDiffWithCommit;
diff --git a/spec/javascripts/diffs/mock_data/merge_request_diffs.js b/spec/javascripts/diffs/mock_data/merge_request_diffs.js
deleted file mode 100644
index de29eb7e560..00000000000
--- a/spec/javascripts/diffs/mock_data/merge_request_diffs.js
+++ /dev/null
@@ -1,7 +0,0 @@
-// No new code should be added to this file. Instead, modify the
-// file this one re-exports from. For more detail about why, see:
-// https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/31349
-
-import diffsMockData from '../../../frontend/diffs/mock_data/merge_request_diffs';
-
-export default diffsMockData;
diff --git a/spec/javascripts/dirty_submit/dirty_submit_collection_spec.js b/spec/javascripts/dirty_submit/dirty_submit_collection_spec.js
deleted file mode 100644
index 47be0b3ce9d..00000000000
--- a/spec/javascripts/dirty_submit/dirty_submit_collection_spec.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import DirtySubmitCollection from '~/dirty_submit/dirty_submit_collection';
-import { setInputValue, createForm } from './helper';
-
-describe('DirtySubmitCollection', () => {
- it('disables submits until there are changes', done => {
- const testElementsCollection = [createForm(), createForm()];
- const forms = testElementsCollection.map(testElements => testElements.form);
-
- new DirtySubmitCollection(forms); // eslint-disable-line no-new
-
- testElementsCollection.forEach(testElements => {
- const { input, submit } = testElements;
- const originalValue = input.value;
-
- expect(submit.disabled).toBe(true);
-
- return setInputValue(input, `${originalValue} changes`)
- .then(() => {
- expect(submit.disabled).toBe(false);
- })
- .then(() => setInputValue(input, originalValue))
- .then(() => {
- expect(submit.disabled).toBe(true);
- })
- .then(done)
- .catch(done.fail);
- });
- });
-});
diff --git a/spec/javascripts/dirty_submit/dirty_submit_factory_spec.js b/spec/javascripts/dirty_submit/dirty_submit_factory_spec.js
deleted file mode 100644
index 40843a68582..00000000000
--- a/spec/javascripts/dirty_submit/dirty_submit_factory_spec.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import dirtySubmitFactory from '~/dirty_submit/dirty_submit_factory';
-import DirtySubmitForm from '~/dirty_submit/dirty_submit_form';
-import DirtySubmitCollection from '~/dirty_submit/dirty_submit_collection';
-import { createForm } from './helper';
-
-describe('DirtySubmitCollection', () => {
- it('returns a DirtySubmitForm instance for single form elements', () => {
- const { form } = createForm();
-
- expect(dirtySubmitFactory(form) instanceof DirtySubmitForm).toBe(true);
- });
-
- it('returns a DirtySubmitCollection instance for a collection of form elements', () => {
- const forms = [createForm().form, createForm().form];
-
- expect(dirtySubmitFactory(forms) instanceof DirtySubmitCollection).toBe(true);
- });
-});
diff --git a/spec/javascripts/dirty_submit/dirty_submit_form_spec.js b/spec/javascripts/dirty_submit/dirty_submit_form_spec.js
deleted file mode 100644
index 42f806fa1bf..00000000000
--- a/spec/javascripts/dirty_submit/dirty_submit_form_spec.js
+++ /dev/null
@@ -1,114 +0,0 @@
-import { range as rge } from 'lodash';
-import DirtySubmitForm from '~/dirty_submit/dirty_submit_form';
-import { getInputValue, setInputValue, createForm } from './helper';
-
-function expectToToggleDisableOnDirtyUpdate(submit, input) {
- const originalValue = getInputValue(input);
-
- expect(submit.disabled).toBe(true);
-
- return setInputValue(input, `${originalValue} changes`)
- .then(() => expect(submit.disabled).toBe(false))
- .then(() => setInputValue(input, originalValue))
- .then(() => expect(submit.disabled).toBe(true));
-}
-
-describe('DirtySubmitForm', () => {
- const originalThrottleDuration = DirtySubmitForm.THROTTLE_DURATION;
-
- describe('submit button tests', () => {
- beforeEach(() => {
- DirtySubmitForm.THROTTLE_DURATION = 0;
- });
-
- afterEach(() => {
- DirtySubmitForm.THROTTLE_DURATION = originalThrottleDuration;
- });
-
- it('disables submit until there are changes', done => {
- const { form, input, submit } = createForm();
-
- new DirtySubmitForm(form); // eslint-disable-line no-new
-
- return expectToToggleDisableOnDirtyUpdate(submit, input)
- .then(done)
- .catch(done.fail);
- });
-
- it('disables submit until there are changes when initializing with a falsy value', done => {
- const { form, input, submit } = createForm();
- input.value = '';
-
- new DirtySubmitForm(form); // eslint-disable-line no-new
-
- return expectToToggleDisableOnDirtyUpdate(submit, input)
- .then(done)
- .catch(done.fail);
- });
-
- it('disables submit until there are changes for radio inputs', done => {
- const { form, input, submit } = createForm('radio');
-
- new DirtySubmitForm(form); // eslint-disable-line no-new
-
- return expectToToggleDisableOnDirtyUpdate(submit, input)
- .then(done)
- .catch(done.fail);
- });
-
- it('disables submit until there are changes for checkbox inputs', done => {
- const { form, input, submit } = createForm('checkbox');
-
- new DirtySubmitForm(form); // eslint-disable-line no-new
-
- return expectToToggleDisableOnDirtyUpdate(submit, input)
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('throttling tests', () => {
- beforeEach(() => {
- jasmine.clock().install();
- jasmine.clock().mockDate();
- DirtySubmitForm.THROTTLE_DURATION = 100;
- });
-
- afterEach(() => {
- jasmine.clock().uninstall();
- DirtySubmitForm.THROTTLE_DURATION = originalThrottleDuration;
- });
-
- it('throttles updates when rapid changes are made to a single form element', () => {
- const { form, input } = createForm();
- const updateDirtyInputSpy = spyOn(new DirtySubmitForm(form), 'updateDirtyInput');
-
- rge(10).forEach(i => {
- setInputValue(input, `change ${i}`, false);
- });
-
- jasmine.clock().tick(101);
-
- expect(updateDirtyInputSpy).toHaveBeenCalledTimes(2);
- });
-
- it('does not throttle updates when rapid changes are made to different form elements', () => {
- const form = document.createElement('form');
- const range = rge(10);
- range.forEach(i => {
- form.innerHTML += `<input type="text" name="input-${i}" class="js-input-${i}"/>`;
- });
-
- const updateDirtyInputSpy = spyOn(new DirtySubmitForm(form), 'updateDirtyInput');
-
- range.forEach(i => {
- const input = form.querySelector(`.js-input-${i}`);
- setInputValue(input, `change`, false);
- });
-
- jasmine.clock().tick(101);
-
- expect(updateDirtyInputSpy).toHaveBeenCalledTimes(range.length);
- });
- });
-});
diff --git a/spec/javascripts/dirty_submit/helper.js b/spec/javascripts/dirty_submit/helper.js
deleted file mode 100644
index b51783cb915..00000000000
--- a/spec/javascripts/dirty_submit/helper.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import DirtySubmitForm from '~/dirty_submit/dirty_submit_form';
-import setTimeoutPromiseHelper from '../helpers/set_timeout_promise_helper';
-
-function isCheckableType(type) {
- return /^(radio|checkbox)$/.test(type);
-}
-
-export function setInputValue(element, value) {
- const { type } = element;
- let eventType;
-
- if (isCheckableType(type)) {
- element.checked = !element.checked;
- eventType = 'change';
- } else {
- element.value = value;
- eventType = 'input';
- }
-
- element.dispatchEvent(
- new Event(eventType, {
- bubbles: true,
- }),
- );
-
- return setTimeoutPromiseHelper(DirtySubmitForm.THROTTLE_DURATION);
-}
-
-export function getInputValue(input) {
- return isCheckableType(input.type) ? input.checked : input.value;
-}
-
-export function createForm(type = 'text') {
- const form = document.createElement('form');
- form.innerHTML = `
- <input type="${type}" name="${type}" class="js-input"/>
- <button type="submit" class="js-dirty-submit"></button>
- `;
-
- const input = form.querySelector('.js-input');
- const submit = form.querySelector('.js-dirty-submit');
-
- return {
- form,
- input,
- submit,
- };
-}
diff --git a/spec/javascripts/editor/editor_lite_spec.js b/spec/javascripts/editor/editor_lite_spec.js
deleted file mode 100644
index 106264aa13f..00000000000
--- a/spec/javascripts/editor/editor_lite_spec.js
+++ /dev/null
@@ -1,160 +0,0 @@
-import { editor as monacoEditor, Uri } from 'monaco-editor';
-import Editor from '~/editor/editor_lite';
-import { DEFAULT_THEME, themes } from '~/ide/lib/themes';
-
-describe('Base editor', () => {
- let editorEl;
- let editor;
- const blobContent = 'Foo Bar';
- const blobPath = 'test.md';
- const uri = new Uri('gitlab', false, blobPath);
- const fakeModel = { foo: 'bar' };
-
- beforeEach(() => {
- setFixtures('<div id="editor" data-editor-loading></div>');
- editorEl = document.getElementById('editor');
- editor = new Editor();
- });
-
- afterEach(() => {
- editor.dispose();
- editorEl.remove();
- });
-
- it('initializes Editor with basic properties', () => {
- expect(editor).toBeDefined();
- expect(editor.editorEl).toBe(null);
- expect(editor.blobContent).toEqual('');
- expect(editor.blobPath).toEqual('');
- });
-
- it('removes `editor-loading` data attribute from the target DOM element', () => {
- editor.createInstance({ el: editorEl });
-
- expect(editorEl.dataset.editorLoading).toBeUndefined();
- });
-
- describe('instance of the Editor', () => {
- let modelSpy;
- let instanceSpy;
- let setModel;
- let dispose;
-
- beforeEach(() => {
- setModel = jasmine.createSpy();
- dispose = jasmine.createSpy();
- modelSpy = spyOn(monacoEditor, 'createModel').and.returnValue(fakeModel);
- instanceSpy = spyOn(monacoEditor, 'create').and.returnValue({
- setModel,
- dispose,
- });
- });
-
- it('does nothing if no dom element is supplied', () => {
- editor.createInstance();
-
- expect(editor.editorEl).toBe(null);
- expect(editor.blobContent).toEqual('');
- expect(editor.blobPath).toEqual('');
-
- expect(modelSpy).not.toHaveBeenCalled();
- expect(instanceSpy).not.toHaveBeenCalled();
- expect(setModel).not.toHaveBeenCalled();
- });
-
- it('creates model to be supplied to Monaco editor', () => {
- editor.createInstance({ el: editorEl, blobPath, blobContent });
-
- expect(modelSpy).toHaveBeenCalledWith(blobContent, undefined, uri);
- expect(setModel).toHaveBeenCalledWith(fakeModel);
- });
-
- it('initializes the instance on a supplied DOM node', () => {
- editor.createInstance({ el: editorEl });
-
- expect(editor.editorEl).not.toBe(null);
- expect(instanceSpy).toHaveBeenCalledWith(editorEl, jasmine.anything());
- });
- });
-
- describe('implementation', () => {
- beforeEach(() => {
- editor.createInstance({ el: editorEl, blobPath, blobContent });
- });
-
- afterEach(() => {
- editor.model.dispose();
- });
-
- it('correctly proxies value from the model', () => {
- expect(editor.getValue()).toEqual(blobContent);
- });
-
- it('is capable of changing the language of the model', () => {
- const blobRenamedPath = 'test.js';
-
- expect(editor.model.getLanguageIdentifier().language).toEqual('markdown');
- editor.updateModelLanguage(blobRenamedPath);
-
- expect(editor.model.getLanguageIdentifier().language).toEqual('javascript');
- });
-
- it('falls back to plaintext if there is no language associated with an extension', () => {
- const blobRenamedPath = 'test.myext';
- const spy = spyOn(console, 'error');
-
- editor.updateModelLanguage(blobRenamedPath);
-
- expect(spy).not.toHaveBeenCalled();
- expect(editor.model.getLanguageIdentifier().language).toEqual('plaintext');
- });
- });
-
- describe('syntax highlighting theme', () => {
- let themeDefineSpy;
- let themeSetSpy;
- let defaultScheme;
-
- beforeEach(() => {
- themeDefineSpy = spyOn(monacoEditor, 'defineTheme');
- themeSetSpy = spyOn(monacoEditor, 'setTheme');
- defaultScheme = window.gon.user_color_scheme;
- });
-
- afterEach(() => {
- window.gon.user_color_scheme = defaultScheme;
- });
-
- it('sets default syntax highlighting theme', () => {
- const expectedTheme = themes.find(t => t.name === DEFAULT_THEME);
-
- editor = new Editor();
-
- expect(themeDefineSpy).toHaveBeenCalledWith(DEFAULT_THEME, expectedTheme.data);
- expect(themeSetSpy).toHaveBeenCalledWith(DEFAULT_THEME);
- });
-
- it('sets correct theme if it is set in users preferences', () => {
- const expectedTheme = themes.find(t => t.name !== DEFAULT_THEME);
-
- expect(expectedTheme.name).not.toBe(DEFAULT_THEME);
-
- window.gon.user_color_scheme = expectedTheme.name;
- editor = new Editor();
-
- expect(themeDefineSpy).toHaveBeenCalledWith(expectedTheme.name, expectedTheme.data);
- expect(themeSetSpy).toHaveBeenCalledWith(expectedTheme.name);
- });
-
- it('falls back to default theme if a selected one is not supported yet', () => {
- const name = 'non-existent-theme';
- const nonExistentTheme = { name };
-
- window.gon.user_color_scheme = nonExistentTheme.name;
- editor = new Editor();
-
- expect(themeDefineSpy).not.toHaveBeenCalled();
- expect(themeSetSpy).toHaveBeenCalledWith(DEFAULT_THEME);
- });
- });
-});
diff --git a/spec/javascripts/emoji_spec.js b/spec/javascripts/emoji_spec.js
deleted file mode 100644
index 3db4d9800f1..00000000000
--- a/spec/javascripts/emoji_spec.js
+++ /dev/null
@@ -1,486 +0,0 @@
-import { glEmojiTag } from '~/emoji';
-import isEmojiUnicodeSupported, {
- isFlagEmoji,
- isRainbowFlagEmoji,
- isKeycapEmoji,
- isSkinToneComboEmoji,
- isHorceRacingSkinToneComboEmoji,
- isPersonZwjEmoji,
-} from '~/emoji/support/is_emoji_unicode_supported';
-
-const emptySupportMap = {
- personZwj: false,
- horseRacing: false,
- flag: false,
- skinToneModifier: false,
- '9.0': false,
- '8.0': false,
- '7.0': false,
- 6.1: false,
- '6.0': false,
- 5.2: false,
- 5.1: false,
- 4.1: false,
- '4.0': false,
- 3.2: false,
- '3.0': false,
- 1.1: false,
-};
-
-const emojiFixtureMap = {
- bomb: {
- name: 'bomb',
- moji: '💣',
- unicodeVersion: '6.0',
- },
- construction_worker_tone5: {
- name: 'construction_worker_tone5',
- moji: '👷🏿',
- unicodeVersion: '8.0',
- },
- five: {
- name: 'five',
- moji: '5️⃣',
- unicodeVersion: '3.0',
- },
- grey_question: {
- name: 'grey_question',
- moji: '❔',
- unicodeVersion: '6.0',
- },
-};
-
-function markupToDomElement(markup) {
- const div = document.createElement('div');
- div.innerHTML = markup;
- return div.firstElementChild;
-}
-
-function testGlEmojiImageFallback(element, name, src) {
- expect(element.tagName.toLowerCase()).toBe('img');
- expect(element.getAttribute('src')).toBe(src);
- expect(element.getAttribute('title')).toBe(`:${name}:`);
- expect(element.getAttribute('alt')).toBe(`:${name}:`);
-}
-
-const defaults = {
- forceFallback: false,
- sprite: false,
-};
-
-function testGlEmojiElement(element, name, unicodeVersion, unicodeMoji, options = {}) {
- const opts = Object.assign({}, defaults, options);
- expect(element.tagName.toLowerCase()).toBe('gl-emoji');
- expect(element.dataset.name).toBe(name);
- expect(element.dataset.fallbackSrc.length).toBeGreaterThan(0);
- expect(element.dataset.unicodeVersion).toBe(unicodeVersion);
-
- const fallbackSpriteClass = `emoji-${name}`;
- if (opts.sprite) {
- expect(element.dataset.fallbackSpriteClass).toBe(fallbackSpriteClass);
- }
-
- if (opts.forceFallback && opts.sprite) {
- expect(element.getAttribute('class')).toBe(`emoji-icon ${fallbackSpriteClass}`);
- }
-
- if (opts.forceFallback && !opts.sprite) {
- // Check for image fallback
- testGlEmojiImageFallback(element.firstElementChild, name, element.dataset.fallbackSrc);
- } else {
- // Otherwise make sure things are still unicode text
- expect(element.textContent.trim()).toBe(unicodeMoji);
- }
-}
-
-describe('gl_emoji', () => {
- describe('glEmojiTag', () => {
- it('bomb emoji', () => {
- const emojiKey = 'bomb';
- const markup = glEmojiTag(emojiFixtureMap[emojiKey].name);
- const glEmojiElement = markupToDomElement(markup);
- testGlEmojiElement(
- glEmojiElement,
- emojiFixtureMap[emojiKey].name,
- emojiFixtureMap[emojiKey].unicodeVersion,
- emojiFixtureMap[emojiKey].moji,
- );
- });
-
- it('bomb emoji with image fallback', () => {
- const emojiKey = 'bomb';
- const markup = glEmojiTag(emojiFixtureMap[emojiKey].name, {
- forceFallback: true,
- });
- const glEmojiElement = markupToDomElement(markup);
- testGlEmojiElement(
- glEmojiElement,
- emojiFixtureMap[emojiKey].name,
- emojiFixtureMap[emojiKey].unicodeVersion,
- emojiFixtureMap[emojiKey].moji,
- {
- forceFallback: true,
- },
- );
- });
-
- it('bomb emoji with sprite fallback readiness', () => {
- const emojiKey = 'bomb';
- const markup = glEmojiTag(emojiFixtureMap[emojiKey].name, {
- sprite: true,
- });
- const glEmojiElement = markupToDomElement(markup);
- testGlEmojiElement(
- glEmojiElement,
- emojiFixtureMap[emojiKey].name,
- emojiFixtureMap[emojiKey].unicodeVersion,
- emojiFixtureMap[emojiKey].moji,
- {
- sprite: true,
- },
- );
- });
-
- it('bomb emoji with sprite fallback', () => {
- const emojiKey = 'bomb';
- const markup = glEmojiTag(emojiFixtureMap[emojiKey].name, {
- forceFallback: true,
- sprite: true,
- });
- const glEmojiElement = markupToDomElement(markup);
- testGlEmojiElement(
- glEmojiElement,
- emojiFixtureMap[emojiKey].name,
- emojiFixtureMap[emojiKey].unicodeVersion,
- emojiFixtureMap[emojiKey].moji,
- {
- forceFallback: true,
- sprite: true,
- },
- );
- });
-
- it('question mark when invalid emoji name given', () => {
- const name = 'invalid_emoji';
- const emojiKey = 'grey_question';
- const markup = glEmojiTag(name);
- const glEmojiElement = markupToDomElement(markup);
- testGlEmojiElement(
- glEmojiElement,
- emojiFixtureMap[emojiKey].name,
- emojiFixtureMap[emojiKey].unicodeVersion,
- emojiFixtureMap[emojiKey].moji,
- );
- });
-
- it('question mark with image fallback when invalid emoji name given', () => {
- const name = 'invalid_emoji';
- const emojiKey = 'grey_question';
- const markup = glEmojiTag(name, {
- forceFallback: true,
- });
- const glEmojiElement = markupToDomElement(markup);
- testGlEmojiElement(
- glEmojiElement,
- emojiFixtureMap[emojiKey].name,
- emojiFixtureMap[emojiKey].unicodeVersion,
- emojiFixtureMap[emojiKey].moji,
- {
- forceFallback: true,
- },
- );
- });
- });
-
- describe('isFlagEmoji', () => {
- it('should gracefully handle empty string', () => {
- expect(isFlagEmoji('')).toBeFalsy();
- });
-
- it('should detect flag_ac', () => {
- expect(isFlagEmoji('🇦🇨')).toBeTruthy();
- });
-
- it('should detect flag_us', () => {
- expect(isFlagEmoji('🇺🇸')).toBeTruthy();
- });
-
- it('should detect flag_zw', () => {
- expect(isFlagEmoji('🇿🇼')).toBeTruthy();
- });
-
- it('should not detect flags', () => {
- expect(isFlagEmoji('🎏')).toBeFalsy();
- });
-
- it('should not detect triangular_flag_on_post', () => {
- expect(isFlagEmoji('🚩')).toBeFalsy();
- });
-
- it('should not detect single letter', () => {
- expect(isFlagEmoji('🇦')).toBeFalsy();
- });
-
- it('should not detect >2 letters', () => {
- expect(isFlagEmoji('🇦🇧🇨')).toBeFalsy();
- });
- });
-
- describe('isRainbowFlagEmoji', () => {
- it('should gracefully handle empty string', () => {
- expect(isRainbowFlagEmoji('')).toBeFalsy();
- });
-
- it('should detect rainbow_flag', () => {
- expect(isRainbowFlagEmoji('🏳🌈')).toBeTruthy();
- });
-
- it("should not detect flag_white on its' own", () => {
- expect(isRainbowFlagEmoji('🏳')).toBeFalsy();
- });
-
- it("should not detect rainbow on its' own", () => {
- expect(isRainbowFlagEmoji('🌈')).toBeFalsy();
- });
-
- it('should not detect flag_white with something else', () => {
- expect(isRainbowFlagEmoji('🏳🔵')).toBeFalsy();
- });
- });
-
- describe('isKeycapEmoji', () => {
- it('should gracefully handle empty string', () => {
- expect(isKeycapEmoji('')).toBeFalsy();
- });
-
- it('should detect one(keycap)', () => {
- expect(isKeycapEmoji('1️⃣')).toBeTruthy();
- });
-
- it('should detect nine(keycap)', () => {
- expect(isKeycapEmoji('9️⃣')).toBeTruthy();
- });
-
- it('should not detect ten(keycap)', () => {
- expect(isKeycapEmoji('🔟')).toBeFalsy();
- });
-
- it('should not detect hash(keycap)', () => {
- expect(isKeycapEmoji('#⃣')).toBeFalsy();
- });
- });
-
- describe('isSkinToneComboEmoji', () => {
- it('should gracefully handle empty string', () => {
- expect(isSkinToneComboEmoji('')).toBeFalsy();
- });
-
- it('should detect hand_splayed_tone5', () => {
- expect(isSkinToneComboEmoji('🖐🏿')).toBeTruthy();
- });
-
- it('should not detect hand_splayed', () => {
- expect(isSkinToneComboEmoji('🖐')).toBeFalsy();
- });
-
- it('should detect lifter_tone1', () => {
- expect(isSkinToneComboEmoji('🏋🏻')).toBeTruthy();
- });
-
- it('should not detect lifter', () => {
- expect(isSkinToneComboEmoji('🏋')).toBeFalsy();
- });
-
- it('should detect rowboat_tone4', () => {
- expect(isSkinToneComboEmoji('🚣🏾')).toBeTruthy();
- });
-
- it('should not detect rowboat', () => {
- expect(isSkinToneComboEmoji('🚣')).toBeFalsy();
- });
-
- it('should not detect individual tone emoji', () => {
- expect(isSkinToneComboEmoji('🏻')).toBeFalsy();
- });
- });
-
- describe('isHorceRacingSkinToneComboEmoji', () => {
- it('should gracefully handle empty string', () => {
- expect(isHorceRacingSkinToneComboEmoji('')).toBeFalsy();
- });
-
- it('should detect horse_racing_tone2', () => {
- expect(isHorceRacingSkinToneComboEmoji('🏇🏼')).toBeTruthy();
- });
-
- it('should not detect horse_racing', () => {
- expect(isHorceRacingSkinToneComboEmoji('🏇')).toBeFalsy();
- });
- });
-
- describe('isPersonZwjEmoji', () => {
- it('should gracefully handle empty string', () => {
- expect(isPersonZwjEmoji('')).toBeFalsy();
- });
-
- it('should detect couple_mm', () => {
- expect(isPersonZwjEmoji('👨‍❤️‍👨')).toBeTruthy();
- });
-
- it('should not detect couple_with_heart', () => {
- expect(isPersonZwjEmoji('💑')).toBeFalsy();
- });
-
- it('should not detect couplekiss', () => {
- expect(isPersonZwjEmoji('💏')).toBeFalsy();
- });
-
- it('should detect family_mmb', () => {
- expect(isPersonZwjEmoji('👨‍👨‍👦')).toBeTruthy();
- });
-
- it('should detect family_mwgb', () => {
- expect(isPersonZwjEmoji('👨‍👩‍👧‍👦')).toBeTruthy();
- });
-
- it('should not detect family', () => {
- expect(isPersonZwjEmoji('👪')).toBeFalsy();
- });
-
- it('should detect kiss_ww', () => {
- expect(isPersonZwjEmoji('👩‍❤️‍💋‍👩')).toBeTruthy();
- });
-
- it('should not detect girl', () => {
- expect(isPersonZwjEmoji('👧')).toBeFalsy();
- });
-
- it('should not detect girl_tone5', () => {
- expect(isPersonZwjEmoji('👧🏿')).toBeFalsy();
- });
-
- it('should not detect man', () => {
- expect(isPersonZwjEmoji('👨')).toBeFalsy();
- });
-
- it('should not detect woman', () => {
- expect(isPersonZwjEmoji('👩')).toBeFalsy();
- });
- });
-
- describe('isEmojiUnicodeSupported', () => {
- it('should gracefully handle empty string with unicode support', () => {
- const isSupported = isEmojiUnicodeSupported({ '1.0': true }, '', '1.0');
-
- expect(isSupported).toBeTruthy();
- });
-
- it('should gracefully handle empty string without unicode support', () => {
- const isSupported = isEmojiUnicodeSupported({}, '', '1.0');
-
- expect(isSupported).toBeFalsy();
- });
-
- it('bomb(6.0) with 6.0 support', () => {
- const emojiKey = 'bomb';
- const unicodeSupportMap = Object.assign({}, emptySupportMap, {
- '6.0': true,
- });
- const isSupported = isEmojiUnicodeSupported(
- unicodeSupportMap,
- emojiFixtureMap[emojiKey].moji,
- emojiFixtureMap[emojiKey].unicodeVersion,
- );
-
- expect(isSupported).toBeTruthy();
- });
-
- it('bomb(6.0) without 6.0 support', () => {
- const emojiKey = 'bomb';
- const unicodeSupportMap = emptySupportMap;
- const isSupported = isEmojiUnicodeSupported(
- unicodeSupportMap,
- emojiFixtureMap[emojiKey].moji,
- emojiFixtureMap[emojiKey].unicodeVersion,
- );
-
- expect(isSupported).toBeFalsy();
- });
-
- it('bomb(6.0) without 6.0 but with 9.0 support', () => {
- const emojiKey = 'bomb';
- const unicodeSupportMap = Object.assign({}, emptySupportMap, {
- '9.0': true,
- });
- const isSupported = isEmojiUnicodeSupported(
- unicodeSupportMap,
- emojiFixtureMap[emojiKey].moji,
- emojiFixtureMap[emojiKey].unicodeVersion,
- );
-
- expect(isSupported).toBeFalsy();
- });
-
- it('construction_worker_tone5(8.0) without skin tone modifier support', () => {
- const emojiKey = 'construction_worker_tone5';
- const unicodeSupportMap = Object.assign({}, emptySupportMap, {
- skinToneModifier: false,
- '9.0': true,
- '8.0': true,
- '7.0': true,
- 6.1: true,
- '6.0': true,
- 5.2: true,
- 5.1: true,
- 4.1: true,
- '4.0': true,
- 3.2: true,
- '3.0': true,
- 1.1: true,
- });
- const isSupported = isEmojiUnicodeSupported(
- unicodeSupportMap,
- emojiFixtureMap[emojiKey].moji,
- emojiFixtureMap[emojiKey].unicodeVersion,
- );
-
- expect(isSupported).toBeFalsy();
- });
-
- it('use native keycap on >=57 chrome', () => {
- const emojiKey = 'five';
- const unicodeSupportMap = Object.assign({}, emptySupportMap, {
- '3.0': true,
- meta: {
- isChrome: true,
- chromeVersion: 57,
- },
- });
- const isSupported = isEmojiUnicodeSupported(
- unicodeSupportMap,
- emojiFixtureMap[emojiKey].moji,
- emojiFixtureMap[emojiKey].unicodeVersion,
- );
-
- expect(isSupported).toBeTruthy();
- });
-
- it('fallback keycap on <57 chrome', () => {
- const emojiKey = 'five';
- const unicodeSupportMap = Object.assign({}, emptySupportMap, {
- '3.0': true,
- meta: {
- isChrome: true,
- chromeVersion: 50,
- },
- });
- const isSupported = isEmojiUnicodeSupported(
- unicodeSupportMap,
- emojiFixtureMap[emojiKey].moji,
- emojiFixtureMap[emojiKey].unicodeVersion,
- );
-
- expect(isSupported).toBeFalsy();
- });
- });
-});
diff --git a/spec/javascripts/feature_highlight/feature_highlight_helper_spec.js b/spec/javascripts/feature_highlight/feature_highlight_helper_spec.js
deleted file mode 100644
index ba35f7bf7c6..00000000000
--- a/spec/javascripts/feature_highlight/feature_highlight_helper_spec.js
+++ /dev/null
@@ -1,75 +0,0 @@
-import $ from 'jquery';
-import MockAdapter from 'axios-mock-adapter';
-import getSetTimeoutPromise from 'spec/helpers/set_timeout_promise_helper';
-import axios from '~/lib/utils/axios_utils';
-import { getSelector, dismiss, inserted } from '~/feature_highlight/feature_highlight_helper';
-import { togglePopover } from '~/shared/popover';
-
-describe('feature highlight helper', () => {
- describe('getSelector', () => {
- it('returns js-feature-highlight selector', () => {
- const highlightId = 'highlightId';
-
- expect(getSelector(highlightId)).toEqual(
- `.js-feature-highlight[data-highlight=${highlightId}]`,
- );
- });
- });
-
- describe('dismiss', () => {
- let mock;
- const context = {
- hide: () => {},
- attr: () => '/-/callouts/dismiss',
- };
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
-
- spyOn(togglePopover, 'call').and.callFake(() => {});
- spyOn(context, 'hide').and.callFake(() => {});
- dismiss.call(context);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('calls persistent dismissal endpoint', done => {
- const spy = jasmine.createSpy('dismiss-endpoint-hit');
- mock.onPost('/-/callouts/dismiss').reply(spy);
-
- getSetTimeoutPromise()
- .then(() => {
- expect(spy).toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('calls hide popover', () => {
- expect(togglePopover.call).toHaveBeenCalledWith(context, false);
- });
-
- it('calls hide', () => {
- expect(context.hide).toHaveBeenCalled();
- });
- });
-
- describe('inserted', () => {
- it('registers click event callback', done => {
- const context = {
- getAttribute: () => 'popoverId',
- dataset: {
- highlight: 'some-feature',
- },
- };
-
- spyOn($.fn, 'on').and.callFake(event => {
- expect(event).toEqual('click');
- done();
- });
- inserted.call(context);
- });
- });
-});
diff --git a/spec/javascripts/feature_highlight/feature_highlight_spec.js b/spec/javascripts/feature_highlight/feature_highlight_spec.js
deleted file mode 100644
index 40ac4bbb6a0..00000000000
--- a/spec/javascripts/feature_highlight/feature_highlight_spec.js
+++ /dev/null
@@ -1,141 +0,0 @@
-import $ from 'jquery';
-import MockAdapter from 'axios-mock-adapter';
-import * as featureHighlight from '~/feature_highlight/feature_highlight';
-import * as popover from '~/shared/popover';
-import axios from '~/lib/utils/axios_utils';
-
-describe('feature highlight', () => {
- beforeEach(() => {
- setFixtures(`
- <div>
- <div class="js-feature-highlight" data-highlight="test" data-highlight-priority="10" data-dismiss-endpoint="/test" disabled>
- Trigger
- </div>
- </div>
- <div class="feature-highlight-popover-content">
- Content
- <div class="dismiss-feature-highlight">
- Dismiss
- </div>
- </div>
- `);
- });
-
- describe('setupFeatureHighlightPopover', () => {
- let mock;
- const selector = '.js-feature-highlight[data-highlight=test]';
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- mock.onGet('/test').reply(200);
- spyOn(window, 'addEventListener');
- featureHighlight.setupFeatureHighlightPopover('test', 0);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('setup popover content', () => {
- const $popoverContent = $('.feature-highlight-popover-content');
- const outerHTML = $popoverContent.prop('outerHTML');
-
- expect($(selector).data('content')).toEqual(outerHTML);
- });
-
- it('setup mouseenter', () => {
- const toggleSpy = spyOn(popover.togglePopover, 'call');
- $(selector).trigger('mouseenter');
-
- expect(toggleSpy).toHaveBeenCalledWith(jasmine.any(Object), true);
- });
-
- it('setup debounced mouseleave', done => {
- const toggleSpy = spyOn(popover.togglePopover, 'call');
- $(selector).trigger('mouseleave');
-
- // Even though we've set the debounce to 0ms, setTimeout is needed for the debounce
- setTimeout(() => {
- expect(toggleSpy).toHaveBeenCalledWith(jasmine.any(Object), false);
- done();
- }, 0);
- });
-
- it('setup show.bs.popover', () => {
- $(selector).trigger('show.bs.popover');
-
- expect(window.addEventListener).toHaveBeenCalledWith('scroll', jasmine.any(Function), {
- once: true,
- });
- });
-
- it('removes disabled attribute', () => {
- expect($('.js-feature-highlight').is(':disabled')).toEqual(false);
- });
-
- it('displays popover', () => {
- expect(document.querySelector(selector).getAttribute('aria-describedby')).toBeFalsy();
- $(selector).trigger('mouseenter');
-
- expect(document.querySelector(selector).getAttribute('aria-describedby')).toBeTruthy();
- });
-
- it('toggles when clicked', () => {
- $(selector).trigger('mouseenter');
- const popoverId = $(selector).attr('aria-describedby');
- const toggleSpy = spyOn(popover.togglePopover, 'call');
-
- $(`#${popoverId} .dismiss-feature-highlight`).click();
-
- expect(toggleSpy).toHaveBeenCalled();
- });
- });
-
- describe('findHighestPriorityFeature', () => {
- beforeEach(() => {
- setFixtures(`
- <div class="js-feature-highlight" data-highlight="test" data-highlight-priority="10" disabled></div>
- <div class="js-feature-highlight" data-highlight="test-high-priority" data-highlight-priority="20" disabled></div>
- <div class="js-feature-highlight" data-highlight="test-low-priority" data-highlight-priority="0" disabled></div>
- `);
- });
-
- it('should pick the highest priority feature highlight', () => {
- setFixtures(`
- <div class="js-feature-highlight" data-highlight="test" data-highlight-priority="10" disabled></div>
- <div class="js-feature-highlight" data-highlight="test-high-priority" data-highlight-priority="20" disabled></div>
- <div class="js-feature-highlight" data-highlight="test-low-priority" data-highlight-priority="0" disabled></div>
- `);
-
- expect($('.js-feature-highlight').length).toBeGreaterThan(1);
- expect(featureHighlight.findHighestPriorityFeature()).toEqual('test-high-priority');
- });
-
- it('should work when no priority is set', () => {
- setFixtures(`
- <div class="js-feature-highlight" data-highlight="test" disabled></div>
- `);
-
- expect(featureHighlight.findHighestPriorityFeature()).toEqual('test');
- });
-
- it('should pick the highest priority feature highlight when some have no priority set', () => {
- setFixtures(`
- <div class="js-feature-highlight" data-highlight="test-no-priority1" disabled></div>
- <div class="js-feature-highlight" data-highlight="test" data-highlight-priority="10" disabled></div>
- <div class="js-feature-highlight" data-highlight="test-no-priority2" disabled></div>
- <div class="js-feature-highlight" data-highlight="test-high-priority" data-highlight-priority="20" disabled></div>
- <div class="js-feature-highlight" data-highlight="test-low-priority" data-highlight-priority="0" disabled></div>
- `);
-
- expect($('.js-feature-highlight').length).toBeGreaterThan(1);
- expect(featureHighlight.findHighestPriorityFeature()).toEqual('test-high-priority');
- });
- });
-
- describe('highlightFeatures', () => {
- it('calls setupFeatureHighlightPopover', () => {
- expect(featureHighlight.highlightFeatures()).toEqual('test');
- });
- });
-});
diff --git a/spec/javascripts/filtered_search/dropdown_utils_spec.js b/spec/javascripts/filtered_search/dropdown_utils_spec.js
deleted file mode 100644
index 6eda4f391a4..00000000000
--- a/spec/javascripts/filtered_search/dropdown_utils_spec.js
+++ /dev/null
@@ -1,374 +0,0 @@
-import DropdownUtils from '~/filtered_search/dropdown_utils';
-import FilteredSearchDropdownManager from '~/filtered_search/filtered_search_dropdown_manager';
-import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
-import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
-
-describe('Dropdown Utils', () => {
- const issueListFixture = 'issues/issue_list.html';
- preloadFixtures(issueListFixture);
-
- describe('getEscapedText', () => {
- it('should return same word when it has no space', () => {
- const escaped = DropdownUtils.getEscapedText('textWithoutSpace');
-
- expect(escaped).toBe('textWithoutSpace');
- });
-
- it('should escape with double quotes', () => {
- let escaped = DropdownUtils.getEscapedText('text with space');
-
- expect(escaped).toBe('"text with space"');
-
- escaped = DropdownUtils.getEscapedText("won't fix");
-
- expect(escaped).toBe('"won\'t fix"');
- });
-
- it('should escape with single quotes', () => {
- const escaped = DropdownUtils.getEscapedText('won"t fix');
-
- expect(escaped).toBe("'won\"t fix'");
- });
-
- it('should escape with single quotes by default', () => {
- const escaped = DropdownUtils.getEscapedText('won"t\' fix');
-
- expect(escaped).toBe("'won\"t' fix'");
- });
- });
-
- describe('filterWithSymbol', () => {
- let input;
- const item = {
- title: '@root',
- };
-
- beforeEach(() => {
- setFixtures(`
- <input type="text" id="test" />
- `);
-
- input = document.getElementById('test');
- });
-
- it('should filter without symbol', () => {
- input.value = 'roo';
-
- const updatedItem = DropdownUtils.filterWithSymbol('@', input, item);
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- it('should filter with symbol', () => {
- input.value = '@roo';
-
- const updatedItem = DropdownUtils.filterWithSymbol('@', input, item);
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- describe('filters multiple word title', () => {
- const multipleWordItem = {
- title: 'Community Contributions',
- };
-
- it('should filter with double quote', () => {
- input.value = '"';
-
- const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- it('should filter with double quote and symbol', () => {
- input.value = '~"';
-
- const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- it('should filter with double quote and multiple words', () => {
- input.value = '"community con';
-
- const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- it('should filter with double quote, symbol and multiple words', () => {
- input.value = '~"community con';
-
- const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- it('should filter with single quote', () => {
- input.value = "'";
-
- const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- it('should filter with single quote and symbol', () => {
- input.value = "~'";
-
- const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- it('should filter with single quote and multiple words', () => {
- input.value = "'community con";
-
- const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- it('should filter with single quote, symbol and multiple words', () => {
- input.value = "~'community con";
-
- const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
- });
- });
-
- describe('filterHint', () => {
- let input;
- let allowedKeys;
-
- beforeEach(() => {
- setFixtures(`
- <ul class="tokens-container">
- <li class="input-token">
- <input class="filtered-search" type="text" id="test" />
- </li>
- </ul>
- `);
-
- input = document.getElementById('test');
- allowedKeys = IssuableFilteredSearchTokenKeys.getKeys();
- });
-
- function config() {
- return {
- input,
- allowedKeys,
- };
- }
-
- it('should filter', () => {
- input.value = 'l';
- let updatedItem = DropdownUtils.filterHint(config(), {
- hint: 'label',
- });
-
- expect(updatedItem.droplab_hidden).toBe(false);
-
- input.value = 'o';
- updatedItem = DropdownUtils.filterHint(config(), {
- hint: 'label',
- });
-
- expect(updatedItem.droplab_hidden).toBe(true);
- });
-
- it('should return droplab_hidden false when item has no hint', () => {
- const updatedItem = DropdownUtils.filterHint(config(), {}, '');
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- it('should allow multiple if item.type is array', () => {
- input.value = 'label:~first la';
- const updatedItem = DropdownUtils.filterHint(config(), {
- hint: 'label',
- type: 'array',
- });
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- it('should prevent multiple if item.type is not array', () => {
- input.value = 'milestone:~first mile';
- let updatedItem = DropdownUtils.filterHint(config(), {
- hint: 'milestone',
- });
-
- expect(updatedItem.droplab_hidden).toBe(true);
-
- updatedItem = DropdownUtils.filterHint(config(), {
- hint: 'milestone',
- type: 'string',
- });
-
- expect(updatedItem.droplab_hidden).toBe(true);
- });
- });
-
- describe('setDataValueIfSelected', () => {
- beforeEach(() => {
- spyOn(FilteredSearchDropdownManager, 'addWordToInput').and.callFake(() => {});
- });
-
- it('calls addWordToInput when dataValue exists', () => {
- const selected = {
- getAttribute: () => 'value',
- hasAttribute: () => false,
- };
-
- DropdownUtils.setDataValueIfSelected(null, '=', selected);
-
- expect(FilteredSearchDropdownManager.addWordToInput.calls.count()).toEqual(1);
- });
-
- it('returns true when dataValue exists', () => {
- const selected = {
- getAttribute: () => 'value',
- hasAttribute: () => false,
- };
-
- const result = DropdownUtils.setDataValueIfSelected(null, '=', selected);
- const result2 = DropdownUtils.setDataValueIfSelected(null, '!=', selected);
-
- expect(result).toBe(true);
- expect(result2).toBe(true);
- });
-
- it('returns false when dataValue does not exist', () => {
- const selected = {
- getAttribute: () => null,
- };
-
- const result = DropdownUtils.setDataValueIfSelected(null, '=', selected);
- const result2 = DropdownUtils.setDataValueIfSelected(null, '!=', selected);
-
- expect(result).toBe(false);
- expect(result2).toBe(false);
- });
- });
-
- describe('getInputSelectionPosition', () => {
- describe('word with trailing spaces', () => {
- const value = 'label:none ';
-
- it('should return selectionStart when cursor is at the trailing space', () => {
- const { left, right } = DropdownUtils.getInputSelectionPosition({
- selectionStart: 11,
- value,
- });
-
- expect(left).toBe(11);
- expect(right).toBe(11);
- });
-
- it('should return input when cursor is at the start of input', () => {
- const { left, right } = DropdownUtils.getInputSelectionPosition({
- selectionStart: 0,
- value,
- });
-
- expect(left).toBe(0);
- expect(right).toBe(10);
- });
-
- it('should return input when cursor is at the middle of input', () => {
- const { left, right } = DropdownUtils.getInputSelectionPosition({
- selectionStart: 7,
- value,
- });
-
- expect(left).toBe(0);
- expect(right).toBe(10);
- });
-
- it('should return input when cursor is at the end of input', () => {
- const { left, right } = DropdownUtils.getInputSelectionPosition({
- selectionStart: 10,
- value,
- });
-
- expect(left).toBe(0);
- expect(right).toBe(10);
- });
- });
-
- describe('multiple words', () => {
- const value = 'label:~"Community Contribution"';
-
- it('should return input when cursor is after the first word', () => {
- const { left, right } = DropdownUtils.getInputSelectionPosition({
- selectionStart: 17,
- value,
- });
-
- expect(left).toBe(0);
- expect(right).toBe(31);
- });
-
- it('should return input when cursor is before the second word', () => {
- const { left, right } = DropdownUtils.getInputSelectionPosition({
- selectionStart: 18,
- value,
- });
-
- expect(left).toBe(0);
- expect(right).toBe(31);
- });
- });
-
- describe('incomplete multiple words', () => {
- const value = 'label:~"Community Contribution';
-
- it('should return entire input when cursor is at the start of input', () => {
- const { left, right } = DropdownUtils.getInputSelectionPosition({
- selectionStart: 0,
- value,
- });
-
- expect(left).toBe(0);
- expect(right).toBe(30);
- });
-
- it('should return entire input when cursor is at the end of input', () => {
- const { left, right } = DropdownUtils.getInputSelectionPosition({
- selectionStart: 30,
- value,
- });
-
- expect(left).toBe(0);
- expect(right).toBe(30);
- });
- });
- });
-
- describe('getSearchQuery', () => {
- let authorToken;
-
- beforeEach(() => {
- loadFixtures(issueListFixture);
-
- authorToken = FilteredSearchSpecHelper.createFilterVisualToken('author', '=', '@user');
- const searchTermToken = FilteredSearchSpecHelper.createSearchVisualToken('search term');
-
- const tokensContainer = document.querySelector('.tokens-container');
- tokensContainer.appendChild(searchTermToken);
- tokensContainer.appendChild(authorToken);
- });
-
- it('uses original value if present', () => {
- const originalValue = 'original dance';
- const valueContainer = authorToken.querySelector('.value-container');
- valueContainer.dataset.originalValue = originalValue;
-
- const searchQuery = DropdownUtils.getSearchQuery();
-
- expect(searchQuery).toBe(' search term author:=original dance');
- });
- });
-});
diff --git a/spec/javascripts/filtered_search/filtered_search_manager_spec.js b/spec/javascripts/filtered_search/filtered_search_manager_spec.js
deleted file mode 100644
index d0b54a16747..00000000000
--- a/spec/javascripts/filtered_search/filtered_search_manager_spec.js
+++ /dev/null
@@ -1,580 +0,0 @@
-import RecentSearchesService from '~/filtered_search/services/recent_searches_service';
-import RecentSearchesServiceError from '~/filtered_search/services/recent_searches_service_error';
-import RecentSearchesRoot from '~/filtered_search/recent_searches_root';
-import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
-import '~/lib/utils/common_utils';
-import DropdownUtils from '~/filtered_search/dropdown_utils';
-import FilteredSearchVisualTokens from '~/filtered_search/filtered_search_visual_tokens';
-import FilteredSearchDropdownManager from '~/filtered_search/filtered_search_dropdown_manager';
-import FilteredSearchManager from '~/filtered_search/filtered_search_manager';
-import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
-import { BACKSPACE_KEY_CODE, DELETE_KEY_CODE } from '~/lib/utils/keycodes';
-
-describe('Filtered Search Manager', function() {
- let input;
- let manager;
- let tokensContainer;
- const page = 'issues';
- const placeholder = 'Search or filter results...';
-
- function dispatchBackspaceEvent(element, eventType) {
- const event = new Event(eventType);
- event.keyCode = BACKSPACE_KEY_CODE;
- element.dispatchEvent(event);
- }
-
- function dispatchDeleteEvent(element, eventType) {
- const event = new Event(eventType);
- event.keyCode = DELETE_KEY_CODE;
- element.dispatchEvent(event);
- }
-
- function dispatchAltBackspaceEvent(element, eventType) {
- const event = new Event(eventType);
- event.altKey = true;
- event.keyCode = BACKSPACE_KEY_CODE;
- element.dispatchEvent(event);
- }
-
- function dispatchCtrlBackspaceEvent(element, eventType) {
- const event = new Event(eventType);
- event.ctrlKey = true;
- event.keyCode = BACKSPACE_KEY_CODE;
- element.dispatchEvent(event);
- }
-
- function dispatchMetaBackspaceEvent(element, eventType) {
- const event = new Event(eventType);
- event.metaKey = true;
- event.keyCode = BACKSPACE_KEY_CODE;
- element.dispatchEvent(event);
- }
-
- function getVisualTokens() {
- return tokensContainer.querySelectorAll('.js-visual-token');
- }
-
- beforeEach(() => {
- setFixtures(`
- <div class="filtered-search-box">
- <form>
- <ul class="tokens-container list-unstyled">
- ${FilteredSearchSpecHelper.createInputHTML(placeholder)}
- </ul>
- <button class="clear-search" type="button">
- <i class="fa fa-times"></i>
- </button>
- </form>
- </div>
- `);
-
- spyOn(FilteredSearchDropdownManager.prototype, 'setDropdown').and.callFake(() => {});
- });
-
- const initializeManager = () => {
- /* eslint-disable jasmine/no-unsafe-spy */
- spyOn(FilteredSearchManager.prototype, 'loadSearchParamsFromURL').and.callFake(() => {});
- spyOn(FilteredSearchManager.prototype, 'tokenChange').and.callFake(() => {});
- spyOn(FilteredSearchDropdownManager.prototype, 'updateDropdownOffset').and.callFake(() => {});
- spyOn(gl.utils, 'getParameterByName').and.returnValue(null);
- spyOn(FilteredSearchVisualTokens, 'unselectTokens').and.callThrough();
- /* eslint-enable jasmine/no-unsafe-spy */
-
- input = document.querySelector('.filtered-search');
- tokensContainer = document.querySelector('.tokens-container');
- manager = new FilteredSearchManager({ page });
- manager.setup();
- };
-
- afterEach(() => {
- manager.cleanup();
- });
-
- describe('class constructor', () => {
- const isLocalStorageAvailable = 'isLocalStorageAvailable';
- let RecentSearchesStoreSpy;
-
- beforeEach(() => {
- spyOn(RecentSearchesService, 'isAvailable').and.returnValue(isLocalStorageAvailable);
- spyOn(RecentSearchesRoot.prototype, 'render');
- RecentSearchesStoreSpy = spyOnDependency(FilteredSearchManager, 'RecentSearchesStore');
- });
-
- it('should instantiate RecentSearchesStore with isLocalStorageAvailable', () => {
- manager = new FilteredSearchManager({ page });
-
- expect(RecentSearchesService.isAvailable).toHaveBeenCalled();
- expect(RecentSearchesStoreSpy).toHaveBeenCalledWith({
- isLocalStorageAvailable,
- allowedKeys: IssuableFilteredSearchTokenKeys.getKeys(),
- });
- });
- });
-
- describe('setup', () => {
- beforeEach(() => {
- manager = new FilteredSearchManager({ page });
- });
-
- it('should not instantiate Flash if an RecentSearchesServiceError is caught', () => {
- spyOn(RecentSearchesService.prototype, 'fetch').and.callFake(() =>
- Promise.reject(new RecentSearchesServiceError()),
- );
- spyOn(window, 'Flash');
-
- manager.setup();
-
- expect(window.Flash).not.toHaveBeenCalled();
- });
- });
-
- describe('searchState', () => {
- beforeEach(() => {
- spyOn(FilteredSearchManager.prototype, 'search').and.callFake(() => {});
- initializeManager();
- });
-
- it('should blur button', () => {
- const e = {
- preventDefault: () => {},
- currentTarget: {
- blur: () => {},
- },
- };
- spyOn(e.currentTarget, 'blur').and.callThrough();
- manager.searchState(e);
-
- expect(e.currentTarget.blur).toHaveBeenCalled();
- });
-
- it('should not call search if there is no state', () => {
- const e = {
- preventDefault: () => {},
- currentTarget: {
- blur: () => {},
- },
- };
-
- manager.searchState(e);
-
- expect(FilteredSearchManager.prototype.search).not.toHaveBeenCalled();
- });
-
- it('should call search when there is state', () => {
- const e = {
- preventDefault: () => {},
- currentTarget: {
- blur: () => {},
- dataset: {
- state: 'opened',
- },
- },
- };
-
- manager.searchState(e);
-
- expect(FilteredSearchManager.prototype.search).toHaveBeenCalledWith('opened');
- });
- });
-
- describe('search', () => {
- const defaultParams = '?scope=all&utf8=%E2%9C%93&state=opened';
-
- beforeEach(() => {
- initializeManager();
- });
-
- it('should search with a single word', done => {
- input.value = 'searchTerm';
-
- spyOnDependency(FilteredSearchManager, 'visitUrl').and.callFake(url => {
- expect(url).toEqual(`${defaultParams}&search=searchTerm`);
- done();
- });
-
- manager.search();
- });
-
- it('should search with multiple words', done => {
- input.value = 'awesome search terms';
-
- spyOnDependency(FilteredSearchManager, 'visitUrl').and.callFake(url => {
- expect(url).toEqual(`${defaultParams}&search=awesome+search+terms`);
- done();
- });
-
- manager.search();
- });
-
- it('should search with special characters', done => {
- input.value = '~!@#$%^&*()_+{}:<>,.?/';
-
- spyOnDependency(FilteredSearchManager, 'visitUrl').and.callFake(url => {
- expect(url).toEqual(
- `${defaultParams}&search=~!%40%23%24%25%5E%26*()_%2B%7B%7D%3A%3C%3E%2C.%3F%2F`,
- );
- done();
- });
-
- manager.search();
- });
-
- it('removes duplicated tokens', done => {
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
- ${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug')}
- ${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug')}
- `);
-
- spyOnDependency(FilteredSearchManager, 'visitUrl').and.callFake(url => {
- expect(url).toEqual(`${defaultParams}&label_name[]=bug`);
- done();
- });
-
- manager.search();
- });
- });
-
- describe('handleInputPlaceholder', () => {
- beforeEach(() => {
- initializeManager();
- });
-
- it('should render placeholder when there is no input', () => {
- expect(input.placeholder).toEqual(placeholder);
- });
-
- it('should not render placeholder when there is input', () => {
- input.value = 'test words';
-
- const event = new Event('input');
- input.dispatchEvent(event);
-
- expect(input.placeholder).toEqual('');
- });
-
- it('should not render placeholder when there are tokens and no input', () => {
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
- FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug'),
- );
-
- const event = new Event('input');
- input.dispatchEvent(event);
-
- expect(input.placeholder).toEqual('');
- });
- });
-
- describe('checkForBackspace', () => {
- beforeEach(() => {
- initializeManager();
- });
-
- describe('tokens and no input', () => {
- beforeEach(() => {
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
- FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug'),
- );
- });
-
- it('removes last token', () => {
- spyOn(FilteredSearchVisualTokens, 'removeLastTokenPartial').and.callThrough();
- dispatchBackspaceEvent(input, 'keyup');
- dispatchBackspaceEvent(input, 'keyup');
-
- expect(FilteredSearchVisualTokens.removeLastTokenPartial).toHaveBeenCalled();
- });
-
- it('sets the input', () => {
- spyOn(FilteredSearchVisualTokens, 'getLastTokenPartial').and.callThrough();
- dispatchDeleteEvent(input, 'keyup');
- dispatchDeleteEvent(input, 'keyup');
-
- expect(FilteredSearchVisualTokens.getLastTokenPartial).toHaveBeenCalled();
- expect(input.value).toEqual('~bug');
- });
- });
-
- it('does not remove token or change input when there is existing input', () => {
- spyOn(FilteredSearchVisualTokens, 'removeLastTokenPartial').and.callThrough();
- spyOn(FilteredSearchVisualTokens, 'getLastTokenPartial').and.callThrough();
-
- input.value = 'text';
- dispatchDeleteEvent(input, 'keyup');
-
- expect(FilteredSearchVisualTokens.removeLastTokenPartial).not.toHaveBeenCalled();
- expect(FilteredSearchVisualTokens.getLastTokenPartial).not.toHaveBeenCalled();
- expect(input.value).toEqual('text');
- });
-
- it('does not remove previous token on single backspace press', () => {
- spyOn(FilteredSearchVisualTokens, 'removeLastTokenPartial').and.callThrough();
- spyOn(FilteredSearchVisualTokens, 'getLastTokenPartial').and.callThrough();
-
- input.value = 't';
- dispatchDeleteEvent(input, 'keyup');
-
- expect(FilteredSearchVisualTokens.removeLastTokenPartial).not.toHaveBeenCalled();
- expect(FilteredSearchVisualTokens.getLastTokenPartial).not.toHaveBeenCalled();
- expect(input.value).toEqual('t');
- });
- });
-
- describe('checkForAltOrCtrlBackspace', () => {
- beforeEach(() => {
- initializeManager();
- spyOn(FilteredSearchVisualTokens, 'removeLastTokenPartial').and.callThrough();
- });
-
- describe('tokens and no input', () => {
- beforeEach(() => {
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
- FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug'),
- );
- });
-
- it('removes last token via alt-backspace', () => {
- dispatchAltBackspaceEvent(input, 'keydown');
-
- expect(FilteredSearchVisualTokens.removeLastTokenPartial).toHaveBeenCalled();
- });
-
- it('removes last token via ctrl-backspace', () => {
- dispatchCtrlBackspaceEvent(input, 'keydown');
-
- expect(FilteredSearchVisualTokens.removeLastTokenPartial).toHaveBeenCalled();
- });
- });
-
- describe('tokens and input', () => {
- beforeEach(() => {
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
- FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug'),
- );
- });
-
- it('does not remove token or change input via alt-backspace when there is existing input', () => {
- input = manager.filteredSearchInput;
- input.value = 'text';
- dispatchAltBackspaceEvent(input, 'keydown');
-
- expect(FilteredSearchVisualTokens.removeLastTokenPartial).not.toHaveBeenCalled();
- expect(input.value).toEqual('text');
- });
-
- it('does not remove token or change input via ctrl-backspace when there is existing input', () => {
- input = manager.filteredSearchInput;
- input.value = 'text';
- dispatchCtrlBackspaceEvent(input, 'keydown');
-
- expect(FilteredSearchVisualTokens.removeLastTokenPartial).not.toHaveBeenCalled();
- expect(input.value).toEqual('text');
- });
- });
- });
-
- describe('checkForMetaBackspace', () => {
- beforeEach(() => {
- initializeManager();
- });
-
- beforeEach(() => {
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
- FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug'),
- );
- });
-
- it('removes all tokens and input', () => {
- spyOn(FilteredSearchManager.prototype, 'clearSearch').and.callThrough();
- dispatchMetaBackspaceEvent(input, 'keydown');
-
- expect(manager.clearSearch).toHaveBeenCalled();
- expect(manager.filteredSearchInput.value).toEqual('');
- expect(DropdownUtils.getSearchQuery()).toEqual('');
- });
- });
-
- describe('removeToken', () => {
- beforeEach(() => {
- initializeManager();
- });
-
- it('removes token even when it is already selected', () => {
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
- FilteredSearchSpecHelper.createFilterVisualTokenHTML('milestone', '=', 'none', true),
- );
-
- tokensContainer.querySelector('.js-visual-token .remove-token').click();
-
- expect(tokensContainer.querySelector('.js-visual-token')).toEqual(null);
- });
-
- describe('unselected token', () => {
- beforeEach(() => {
- spyOn(FilteredSearchManager.prototype, 'removeSelectedToken').and.callThrough();
-
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
- FilteredSearchSpecHelper.createFilterVisualTokenHTML('milestone', '=', 'none'),
- );
- tokensContainer.querySelector('.js-visual-token .remove-token').click();
- });
-
- it('removes token when remove button is selected', () => {
- expect(tokensContainer.querySelector('.js-visual-token')).toEqual(null);
- });
-
- it('calls removeSelectedToken', () => {
- expect(manager.removeSelectedToken).toHaveBeenCalled();
- });
- });
- });
-
- describe('removeSelectedTokenKeydown', () => {
- beforeEach(() => {
- initializeManager();
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
- FilteredSearchSpecHelper.createFilterVisualTokenHTML('milestone', '=', 'none', true),
- );
- });
-
- it('removes selected token when the backspace key is pressed', () => {
- expect(getVisualTokens().length).toEqual(1);
-
- dispatchBackspaceEvent(document, 'keydown');
-
- expect(getVisualTokens().length).toEqual(0);
- });
-
- it('removes selected token when the delete key is pressed', () => {
- expect(getVisualTokens().length).toEqual(1);
-
- dispatchDeleteEvent(document, 'keydown');
-
- expect(getVisualTokens().length).toEqual(0);
- });
-
- it('updates the input placeholder after removal', () => {
- manager.handleInputPlaceholder();
-
- expect(input.placeholder).toEqual('');
- expect(getVisualTokens().length).toEqual(1);
-
- dispatchBackspaceEvent(document, 'keydown');
-
- expect(input.placeholder).not.toEqual('');
- expect(getVisualTokens().length).toEqual(0);
- });
-
- it('updates the clear button after removal', () => {
- manager.toggleClearSearchButton();
-
- const clearButton = document.querySelector('.clear-search');
-
- expect(clearButton.classList.contains('hidden')).toEqual(false);
- expect(getVisualTokens().length).toEqual(1);
-
- dispatchBackspaceEvent(document, 'keydown');
-
- expect(clearButton.classList.contains('hidden')).toEqual(true);
- expect(getVisualTokens().length).toEqual(0);
- });
- });
-
- describe('removeSelectedToken', () => {
- beforeEach(() => {
- spyOn(FilteredSearchVisualTokens, 'removeSelectedToken').and.callThrough();
- spyOn(FilteredSearchManager.prototype, 'handleInputPlaceholder').and.callThrough();
- spyOn(FilteredSearchManager.prototype, 'toggleClearSearchButton').and.callThrough();
- initializeManager();
- });
-
- it('calls FilteredSearchVisualTokens.removeSelectedToken', () => {
- manager.removeSelectedToken();
-
- expect(FilteredSearchVisualTokens.removeSelectedToken).toHaveBeenCalled();
- });
-
- it('calls handleInputPlaceholder', () => {
- manager.removeSelectedToken();
-
- expect(manager.handleInputPlaceholder).toHaveBeenCalled();
- });
-
- it('calls toggleClearSearchButton', () => {
- manager.removeSelectedToken();
-
- expect(manager.toggleClearSearchButton).toHaveBeenCalled();
- });
-
- it('calls update dropdown offset', () => {
- manager.removeSelectedToken();
-
- expect(manager.dropdownManager.updateDropdownOffset).toHaveBeenCalled();
- });
- });
-
- describe('Clearing search', () => {
- beforeEach(() => {
- initializeManager();
- });
-
- it('Clicking the "x" clear button, clears the input', () => {
- const inputValue = 'label:=~bug';
- manager.filteredSearchInput.value = inputValue;
- manager.filteredSearchInput.dispatchEvent(new Event('input'));
-
- expect(DropdownUtils.getSearchQuery()).toEqual(inputValue);
-
- manager.clearSearchButton.click();
-
- expect(manager.filteredSearchInput.value).toEqual('');
- expect(DropdownUtils.getSearchQuery()).toEqual('');
- });
- });
-
- describe('toggleInputContainerFocus', () => {
- beforeEach(() => {
- initializeManager();
- });
-
- it('toggles on focus', () => {
- input.focus();
-
- expect(document.querySelector('.filtered-search-box').classList.contains('focus')).toEqual(
- true,
- );
- });
-
- it('toggles on blur', () => {
- input.blur();
-
- expect(document.querySelector('.filtered-search-box').classList.contains('focus')).toEqual(
- false,
- );
- });
- });
-
- describe('getAllParams', () => {
- beforeEach(() => {
- this.paramsArr = ['key=value', 'otherkey=othervalue'];
-
- initializeManager();
- });
-
- it('correctly modifies params when custom modifier is passed', () => {
- const modifedParams = manager.getAllParams.call(
- {
- modifyUrlParams: paramsArr => paramsArr.reverse(),
- },
- [].concat(this.paramsArr),
- );
-
- expect(modifedParams[0]).toBe(this.paramsArr[1]);
- });
-
- it('does not modify params when no custom modifier is passed', () => {
- const modifedParams = manager.getAllParams.call({}, this.paramsArr);
-
- expect(modifedParams[1]).toBe(this.paramsArr[1]);
- });
- });
-});
diff --git a/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js b/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js
deleted file mode 100644
index dec03e5ab93..00000000000
--- a/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js
+++ /dev/null
@@ -1,152 +0,0 @@
-import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
-import FilteredSearchTokenizer from '~/filtered_search/filtered_search_tokenizer';
-
-describe('Filtered Search Tokenizer', () => {
- const allowedKeys = IssuableFilteredSearchTokenKeys.getKeys();
-
- describe('processTokens', () => {
- it('returns for input containing only search value', () => {
- const results = FilteredSearchTokenizer.processTokens('searchTerm', allowedKeys);
-
- expect(results.searchToken).toBe('searchTerm');
- expect(results.tokens.length).toBe(0);
- expect(results.lastToken).toBe(results.searchToken);
- });
-
- it('returns for input containing only tokens', () => {
- const results = FilteredSearchTokenizer.processTokens(
- 'author:@root label:~"Very Important" milestone:%v1.0 assignee:none',
- allowedKeys,
- );
-
- expect(results.searchToken).toBe('');
- expect(results.tokens.length).toBe(4);
- expect(results.tokens[3]).toBe(results.lastToken);
-
- expect(results.tokens[0].key).toBe('author');
- expect(results.tokens[0].value).toBe('root');
- expect(results.tokens[0].symbol).toBe('@');
-
- expect(results.tokens[1].key).toBe('label');
- expect(results.tokens[1].value).toBe('"Very Important"');
- expect(results.tokens[1].symbol).toBe('~');
-
- expect(results.tokens[2].key).toBe('milestone');
- expect(results.tokens[2].value).toBe('v1.0');
- expect(results.tokens[2].symbol).toBe('%');
-
- expect(results.tokens[3].key).toBe('assignee');
- expect(results.tokens[3].value).toBe('none');
- expect(results.tokens[3].symbol).toBe('');
- });
-
- it('returns for input starting with search value and ending with tokens', () => {
- const results = FilteredSearchTokenizer.processTokens(
- 'searchTerm anotherSearchTerm milestone:none',
- allowedKeys,
- );
-
- expect(results.searchToken).toBe('searchTerm anotherSearchTerm');
- expect(results.tokens.length).toBe(1);
- expect(results.tokens[0]).toBe(results.lastToken);
- expect(results.tokens[0].key).toBe('milestone');
- expect(results.tokens[0].value).toBe('none');
- expect(results.tokens[0].symbol).toBe('');
- });
-
- it('returns for input starting with tokens and ending with search value', () => {
- const results = FilteredSearchTokenizer.processTokens(
- 'assignee:@user searchTerm',
- allowedKeys,
- );
-
- expect(results.searchToken).toBe('searchTerm');
- expect(results.tokens.length).toBe(1);
- expect(results.tokens[0].key).toBe('assignee');
- expect(results.tokens[0].value).toBe('user');
- expect(results.tokens[0].symbol).toBe('@');
- expect(results.lastToken).toBe(results.searchToken);
- });
-
- it('returns for input containing search value wrapped between tokens', () => {
- const results = FilteredSearchTokenizer.processTokens(
- 'author:@root label:~"Won\'t fix" searchTerm anotherSearchTerm milestone:none',
- allowedKeys,
- );
-
- expect(results.searchToken).toBe('searchTerm anotherSearchTerm');
- expect(results.tokens.length).toBe(3);
- expect(results.tokens[2]).toBe(results.lastToken);
-
- expect(results.tokens[0].key).toBe('author');
- expect(results.tokens[0].value).toBe('root');
- expect(results.tokens[0].symbol).toBe('@');
-
- expect(results.tokens[1].key).toBe('label');
- expect(results.tokens[1].value).toBe('"Won\'t fix"');
- expect(results.tokens[1].symbol).toBe('~');
-
- expect(results.tokens[2].key).toBe('milestone');
- expect(results.tokens[2].value).toBe('none');
- expect(results.tokens[2].symbol).toBe('');
- });
-
- it('returns for input containing search value in between tokens', () => {
- const results = FilteredSearchTokenizer.processTokens(
- 'author:@root searchTerm assignee:none anotherSearchTerm label:~Doing',
- allowedKeys,
- );
-
- expect(results.searchToken).toBe('searchTerm anotherSearchTerm');
- expect(results.tokens.length).toBe(3);
- expect(results.tokens[2]).toBe(results.lastToken);
-
- expect(results.tokens[0].key).toBe('author');
- expect(results.tokens[0].value).toBe('root');
- expect(results.tokens[0].symbol).toBe('@');
-
- expect(results.tokens[1].key).toBe('assignee');
- expect(results.tokens[1].value).toBe('none');
- expect(results.tokens[1].symbol).toBe('');
-
- expect(results.tokens[2].key).toBe('label');
- expect(results.tokens[2].value).toBe('Doing');
- expect(results.tokens[2].symbol).toBe('~');
- });
-
- it('returns search value for invalid tokens', () => {
- const results = FilteredSearchTokenizer.processTokens('fake:token', allowedKeys);
-
- expect(results.lastToken).toBe('fake:token');
- expect(results.searchToken).toBe('fake:token');
- expect(results.tokens.length).toEqual(0);
- });
-
- it('returns search value and token for mix of valid and invalid tokens', () => {
- const results = FilteredSearchTokenizer.processTokens('label:real fake:token', allowedKeys);
-
- expect(results.tokens.length).toEqual(1);
- expect(results.tokens[0].key).toBe('label');
- expect(results.tokens[0].value).toBe('real');
- expect(results.tokens[0].symbol).toBe('');
- expect(results.lastToken).toBe('fake:token');
- expect(results.searchToken).toBe('fake:token');
- });
-
- it('returns search value for invalid symbols', () => {
- const results = FilteredSearchTokenizer.processTokens('std::includes', allowedKeys);
-
- expect(results.lastToken).toBe('std::includes');
- expect(results.searchToken).toBe('std::includes');
- });
-
- it('removes duplicated values', () => {
- const results = FilteredSearchTokenizer.processTokens('label:~foo label:~foo', allowedKeys);
-
- expect(results.tokens.length).toBe(1);
- expect(results.tokens[0].key).toBe('label');
- expect(results.tokens[0].value).toBe('foo');
- expect(results.tokens[0].symbol).toBe('~');
- });
- });
-});
diff --git a/spec/javascripts/filtered_search/issues_filtered_search_token_keys_spec.js b/spec/javascripts/filtered_search/issues_filtered_search_token_keys_spec.js
deleted file mode 100644
index c7be900ba2c..00000000000
--- a/spec/javascripts/filtered_search/issues_filtered_search_token_keys_spec.js
+++ /dev/null
@@ -1,148 +0,0 @@
-import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
-
-describe('Issues Filtered Search Token Keys', () => {
- describe('get', () => {
- let tokenKeys;
-
- beforeEach(() => {
- tokenKeys = IssuableFilteredSearchTokenKeys.get();
- });
-
- it('should return tokenKeys', () => {
- expect(tokenKeys).not.toBeNull();
- });
-
- it('should return tokenKeys as an array', () => {
- expect(tokenKeys instanceof Array).toBe(true);
- });
-
- it('should always return the same array', () => {
- const tokenKeys2 = IssuableFilteredSearchTokenKeys.get();
-
- expect(tokenKeys).toEqual(tokenKeys2);
- });
-
- it('should return assignee as a string', () => {
- const assignee = tokenKeys.find(tokenKey => tokenKey.key === 'assignee');
-
- expect(assignee.type).toEqual('string');
- });
- });
-
- describe('getKeys', () => {
- it('should return keys', () => {
- const getKeys = IssuableFilteredSearchTokenKeys.getKeys();
- const keys = IssuableFilteredSearchTokenKeys.get().map(i => i.key);
-
- keys.forEach((key, i) => {
- expect(key).toEqual(getKeys[i]);
- });
- });
- });
-
- describe('getConditions', () => {
- let conditions;
-
- beforeEach(() => {
- conditions = IssuableFilteredSearchTokenKeys.getConditions();
- });
-
- it('should return conditions', () => {
- expect(conditions).not.toBeNull();
- });
-
- it('should return conditions as an array', () => {
- expect(conditions instanceof Array).toBe(true);
- });
- });
-
- describe('searchByKey', () => {
- it('should return null when key not found', () => {
- const tokenKey = IssuableFilteredSearchTokenKeys.searchByKey('notakey');
-
- expect(tokenKey).toBeNull();
- });
-
- it('should return tokenKey when found by key', () => {
- const tokenKeys = IssuableFilteredSearchTokenKeys.get();
- const result = IssuableFilteredSearchTokenKeys.searchByKey(tokenKeys[0].key);
-
- expect(result).toEqual(tokenKeys[0]);
- });
- });
-
- describe('searchBySymbol', () => {
- it('should return null when symbol not found', () => {
- const tokenKey = IssuableFilteredSearchTokenKeys.searchBySymbol('notasymbol');
-
- expect(tokenKey).toBeNull();
- });
-
- it('should return tokenKey when found by symbol', () => {
- const tokenKeys = IssuableFilteredSearchTokenKeys.get();
- const result = IssuableFilteredSearchTokenKeys.searchBySymbol(tokenKeys[0].symbol);
-
- expect(result).toEqual(tokenKeys[0]);
- });
- });
-
- describe('searchByKeyParam', () => {
- it('should return null when key param not found', () => {
- const tokenKey = IssuableFilteredSearchTokenKeys.searchByKeyParam('notakeyparam');
-
- expect(tokenKey).toBeNull();
- });
-
- it('should return tokenKey when found by key param', () => {
- const tokenKeys = IssuableFilteredSearchTokenKeys.get();
- const result = IssuableFilteredSearchTokenKeys.searchByKeyParam(
- `${tokenKeys[0].key}_${tokenKeys[0].param}`,
- );
-
- expect(result).toEqual(tokenKeys[0]);
- });
-
- it('should return alternative tokenKey when found by key param', () => {
- const tokenKeys = IssuableFilteredSearchTokenKeys.getAlternatives();
- const result = IssuableFilteredSearchTokenKeys.searchByKeyParam(
- `${tokenKeys[0].key}_${tokenKeys[0].param}`,
- );
-
- expect(result).toEqual(tokenKeys[0]);
- });
- });
-
- describe('searchByConditionUrl', () => {
- it('should return null when condition url not found', () => {
- const condition = IssuableFilteredSearchTokenKeys.searchByConditionUrl(null);
-
- expect(condition).toBeNull();
- });
-
- it('should return condition when found by url', () => {
- const conditions = IssuableFilteredSearchTokenKeys.getConditions();
- const result = IssuableFilteredSearchTokenKeys.searchByConditionUrl(conditions[0].url);
-
- expect(result).toBe(conditions[0]);
- });
- });
-
- describe('searchByConditionKeyValue', () => {
- it('should return null when condition tokenKey and value not found', () => {
- const condition = IssuableFilteredSearchTokenKeys.searchByConditionKeyValue(null, null);
-
- expect(condition).toBeNull();
- });
-
- it('should return condition when found by tokenKey and value', () => {
- const conditions = IssuableFilteredSearchTokenKeys.getConditions();
- const result = IssuableFilteredSearchTokenKeys.searchByConditionKeyValue(
- conditions[0].tokenKey,
- conditions[0].operator,
- conditions[0].value,
- );
-
- expect(result).toEqual(conditions[0]);
- });
- });
-});
diff --git a/spec/javascripts/filtered_search/recent_searches_root_spec.js b/spec/javascripts/filtered_search/recent_searches_root_spec.js
deleted file mode 100644
index 70dd4e9570d..00000000000
--- a/spec/javascripts/filtered_search/recent_searches_root_spec.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import RecentSearchesRoot from '~/filtered_search/recent_searches_root';
-
-describe('RecentSearchesRoot', () => {
- describe('render', () => {
- let recentSearchesRoot;
- let data;
- let template;
- let VueSpy;
-
- beforeEach(() => {
- recentSearchesRoot = {
- store: {
- state: 'state',
- },
- };
-
- VueSpy = spyOnDependency(RecentSearchesRoot, 'Vue').and.callFake(options => {
- ({ data, template } = options);
- });
-
- RecentSearchesRoot.prototype.render.call(recentSearchesRoot);
- });
-
- it('should instantiate Vue', () => {
- expect(VueSpy).toHaveBeenCalled();
- expect(data()).toBe(recentSearchesRoot.store.state);
- expect(template).toContain(':is-local-storage-available="isLocalStorageAvailable"');
- });
- });
-});
diff --git a/spec/javascripts/filtered_search/services/recent_searches_service_spec.js b/spec/javascripts/filtered_search/services/recent_searches_service_spec.js
deleted file mode 100644
index 188f83eca16..00000000000
--- a/spec/javascripts/filtered_search/services/recent_searches_service_spec.js
+++ /dev/null
@@ -1,158 +0,0 @@
-import RecentSearchesService from '~/filtered_search/services/recent_searches_service';
-import RecentSearchesServiceError from '~/filtered_search/services/recent_searches_service_error';
-import AccessorUtilities from '~/lib/utils/accessor';
-
-describe('RecentSearchesService', () => {
- let service;
-
- beforeEach(() => {
- service = new RecentSearchesService();
- window.localStorage.removeItem(service.localStorageKey);
- });
-
- describe('fetch', () => {
- beforeEach(() => {
- spyOn(RecentSearchesService, 'isAvailable').and.returnValue(true);
- });
-
- it('should default to empty array', done => {
- const fetchItemsPromise = service.fetch();
-
- fetchItemsPromise
- .then(items => {
- expect(items).toEqual([]);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('should reject when unable to parse', done => {
- window.localStorage.setItem(service.localStorageKey, 'fail');
- const fetchItemsPromise = service.fetch();
-
- fetchItemsPromise
- .then(done.fail)
- .catch(error => {
- expect(error).toEqual(jasmine.any(SyntaxError));
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('should reject when service is unavailable', done => {
- RecentSearchesService.isAvailable.and.returnValue(false);
-
- service
- .fetch()
- .then(done.fail)
- .catch(error => {
- expect(error).toEqual(jasmine.any(Error));
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('should return items from localStorage', done => {
- window.localStorage.setItem(service.localStorageKey, '["foo", "bar"]');
- const fetchItemsPromise = service.fetch();
-
- fetchItemsPromise
- .then(items => {
- expect(items).toEqual(['foo', 'bar']);
- })
- .then(done)
- .catch(done.fail);
- });
-
- describe('if .isAvailable returns `false`', () => {
- beforeEach(() => {
- RecentSearchesService.isAvailable.and.returnValue(false);
-
- spyOn(window.localStorage, 'getItem');
- });
-
- it('should not call .getItem', done => {
- RecentSearchesService.prototype
- .fetch()
- .then(done.fail)
- .catch(err => {
- expect(err).toEqual(new RecentSearchesServiceError());
- expect(window.localStorage.getItem).not.toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
- });
- });
- });
-
- describe('setRecentSearches', () => {
- beforeEach(() => {
- spyOn(RecentSearchesService, 'isAvailable').and.returnValue(true);
- });
-
- it('should save things in localStorage', () => {
- const items = ['foo', 'bar'];
- service.save(items);
- const newLocalStorageValue = window.localStorage.getItem(service.localStorageKey);
-
- expect(JSON.parse(newLocalStorageValue)).toEqual(items);
- });
- });
-
- describe('save', () => {
- beforeEach(() => {
- spyOn(window.localStorage, 'setItem');
- spyOn(RecentSearchesService, 'isAvailable');
- });
-
- describe('if .isAvailable returns `true`', () => {
- const searchesString = 'searchesString';
- const localStorageKey = 'localStorageKey';
- const recentSearchesService = {
- localStorageKey,
- };
-
- beforeEach(() => {
- RecentSearchesService.isAvailable.and.returnValue(true);
-
- spyOn(JSON, 'stringify').and.returnValue(searchesString);
- });
-
- it('should call .setItem', () => {
- RecentSearchesService.prototype.save.call(recentSearchesService);
-
- expect(window.localStorage.setItem).toHaveBeenCalledWith(localStorageKey, searchesString);
- });
- });
-
- describe('if .isAvailable returns `false`', () => {
- beforeEach(() => {
- RecentSearchesService.isAvailable.and.returnValue(false);
- });
-
- it('should not call .setItem', () => {
- RecentSearchesService.prototype.save();
-
- expect(window.localStorage.setItem).not.toHaveBeenCalled();
- });
- });
- });
-
- describe('isAvailable', () => {
- let isAvailable;
-
- beforeEach(() => {
- spyOn(AccessorUtilities, 'isLocalStorageAccessSafe').and.callThrough();
-
- isAvailable = RecentSearchesService.isAvailable();
- });
-
- it('should call .isLocalStorageAccessSafe', () => {
- expect(AccessorUtilities.isLocalStorageAccessSafe).toHaveBeenCalled();
- });
-
- it('should return a boolean', () => {
- expect(typeof isAvailable).toBe('boolean');
- });
- });
-});
diff --git a/spec/javascripts/filtered_search/visual_token_value_spec.js b/spec/javascripts/filtered_search/visual_token_value_spec.js
deleted file mode 100644
index 4469ade1874..00000000000
--- a/spec/javascripts/filtered_search/visual_token_value_spec.js
+++ /dev/null
@@ -1,389 +0,0 @@
-import { escape as esc } from 'lodash';
-import VisualTokenValue from '~/filtered_search/visual_token_value';
-import AjaxCache from '~/lib/utils/ajax_cache';
-import UsersCache from '~/lib/utils/users_cache';
-import DropdownUtils from '~/filtered_search//dropdown_utils';
-import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
-
-describe('Filtered Search Visual Tokens', () => {
- const findElements = tokenElement => {
- const tokenNameElement = tokenElement.querySelector('.name');
- const tokenValueContainer = tokenElement.querySelector('.value-container');
- const tokenValueElement = tokenValueContainer.querySelector('.value');
- const tokenOperatorElement = tokenElement.querySelector('.operator');
- const tokenType = tokenNameElement.innerText.toLowerCase();
- const tokenValue = tokenValueElement.innerText;
- const tokenOperator = tokenOperatorElement.innerText;
- const subject = new VisualTokenValue(tokenValue, tokenType, tokenOperator);
- return { subject, tokenValueContainer, tokenValueElement };
- };
-
- let tokensContainer;
- let authorToken;
- let bugLabelToken;
-
- beforeEach(() => {
- setFixtures(`
- <ul class="tokens-container">
- ${FilteredSearchSpecHelper.createInputHTML()}
- </ul>
- `);
- tokensContainer = document.querySelector('.tokens-container');
-
- authorToken = FilteredSearchSpecHelper.createFilterVisualToken('author', '=', '@user');
- bugLabelToken = FilteredSearchSpecHelper.createFilterVisualToken('label', '=', '~bug');
- });
-
- describe('updateUserTokenAppearance', () => {
- let usersCacheSpy;
-
- beforeEach(() => {
- spyOn(UsersCache, 'retrieve').and.callFake(username => usersCacheSpy(username));
- });
-
- it('ignores error if UsersCache throws', done => {
- spyOn(window, 'Flash');
- const dummyError = new Error('Earth rotated backwards');
- const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
- const tokenValue = tokenValueElement.innerText;
- usersCacheSpy = username => {
- expect(`@${username}`).toBe(tokenValue);
- return Promise.reject(dummyError);
- };
-
- subject
- .updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
- .then(() => {
- expect(window.Flash.calls.count()).toBe(0);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('does nothing if user cannot be found', done => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
- const tokenValue = tokenValueElement.innerText;
- usersCacheSpy = username => {
- expect(`@${username}`).toBe(tokenValue);
- return Promise.resolve(undefined);
- };
-
- subject
- .updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
- .then(() => {
- expect(tokenValueElement.innerText).toBe(tokenValue);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('replaces author token with avatar and display name', done => {
- const dummyUser = {
- name: 'Important Person',
- avatar_url: 'https://host.invalid/mypics/avatar.png',
- };
- const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
- const tokenValue = tokenValueElement.innerText;
- usersCacheSpy = username => {
- expect(`@${username}`).toBe(tokenValue);
- return Promise.resolve(dummyUser);
- };
-
- subject
- .updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
- .then(() => {
- expect(tokenValueContainer.dataset.originalValue).toBe(tokenValue);
- expect(tokenValueElement.innerText.trim()).toBe(dummyUser.name);
- const avatar = tokenValueElement.querySelector('img.avatar');
-
- expect(avatar.src).toBe(dummyUser.avatar_url);
- expect(avatar.alt).toBe('');
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('escapes user name when creating token', done => {
- const dummyUser = {
- name: '<script>',
- avatar_url: `${gl.TEST_HOST}/mypics/avatar.png`,
- };
- const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
- const tokenValue = tokenValueElement.innerText;
- usersCacheSpy = username => {
- expect(`@${username}`).toBe(tokenValue);
- return Promise.resolve(dummyUser);
- };
-
- subject
- .updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
- .then(() => {
- expect(tokenValueElement.innerText.trim()).toBe(dummyUser.name);
- tokenValueElement.querySelector('.avatar').remove();
-
- expect(tokenValueElement.innerHTML.trim()).toBe(esc(dummyUser.name));
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('updateLabelTokenColor', () => {
- const jsonFixtureName = 'labels/project_labels.json';
- const dummyEndpoint = '/dummy/endpoint';
-
- preloadFixtures(jsonFixtureName);
-
- let labelData;
-
- beforeAll(() => {
- labelData = getJSONFixture(jsonFixtureName);
- });
-
- const missingLabelToken = FilteredSearchSpecHelper.createFilterVisualToken(
- 'label',
- '=',
- '~doesnotexist',
- );
- const spaceLabelToken = FilteredSearchSpecHelper.createFilterVisualToken(
- 'label',
- '=',
- '~"some space"',
- );
-
- beforeEach(() => {
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
- ${bugLabelToken.outerHTML}
- ${missingLabelToken.outerHTML}
- ${spaceLabelToken.outerHTML}
- `);
-
- const filteredSearchInput = document.querySelector('.filtered-search');
- filteredSearchInput.dataset.runnerTagsEndpoint = `${dummyEndpoint}/admin/runners/tag_list`;
- filteredSearchInput.dataset.labelsEndpoint = `${dummyEndpoint}/-/labels`;
- filteredSearchInput.dataset.milestonesEndpoint = `${dummyEndpoint}/-/milestones`;
-
- AjaxCache.internalStorage = {};
- AjaxCache.internalStorage[`${filteredSearchInput.dataset.labelsEndpoint}.json`] = labelData;
- });
-
- const parseColor = color => {
- const dummyElement = document.createElement('div');
- dummyElement.style.color = color;
- return dummyElement.style.color;
- };
-
- const expectValueContainerStyle = (tokenValueContainer, label) => {
- expect(tokenValueContainer.getAttribute('style')).not.toBe(null);
- expect(tokenValueContainer.style.backgroundColor).toBe(parseColor(label.color));
- expect(tokenValueContainer.style.color).toBe(parseColor(label.text_color));
- };
-
- const findLabel = tokenValue =>
- labelData.find(label => tokenValue === `~${DropdownUtils.getEscapedText(label.title)}`);
-
- it('updates the color of a label token', done => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(bugLabelToken);
- const tokenValue = tokenValueElement.innerText;
- const matchingLabel = findLabel(tokenValue);
-
- subject
- .updateLabelTokenColor(tokenValueContainer, tokenValue)
- .then(() => {
- expectValueContainerStyle(tokenValueContainer, matchingLabel);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('updates the color of a label token with spaces', done => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(spaceLabelToken);
- const tokenValue = tokenValueElement.innerText;
- const matchingLabel = findLabel(tokenValue);
-
- subject
- .updateLabelTokenColor(tokenValueContainer, tokenValue)
- .then(() => {
- expectValueContainerStyle(tokenValueContainer, matchingLabel);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('does not change color of a missing label', done => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(missingLabelToken);
- const tokenValue = tokenValueElement.innerText;
- const matchingLabel = findLabel(tokenValue);
-
- expect(matchingLabel).toBe(undefined);
-
- subject
- .updateLabelTokenColor(tokenValueContainer, tokenValue)
- .then(() => {
- expect(tokenValueContainer.getAttribute('style')).toBe(null);
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('setTokenStyle', () => {
- let originalTextColor;
-
- beforeEach(() => {
- originalTextColor = bugLabelToken.style.color;
- });
-
- it('should set backgroundColor', () => {
- const originalBackgroundColor = bugLabelToken.style.backgroundColor;
- const token = VisualTokenValue.setTokenStyle(bugLabelToken, 'blue', 'white');
-
- expect(token.style.backgroundColor).toEqual('blue');
- expect(token.style.backgroundColor).not.toEqual(originalBackgroundColor);
- });
-
- it('should set textColor', () => {
- const token = VisualTokenValue.setTokenStyle(bugLabelToken, 'white', 'black');
-
- expect(token.style.color).toEqual('black');
- expect(token.style.color).not.toEqual(originalTextColor);
- });
-
- it('should add inverted class when textColor is #FFFFFF', () => {
- const token = VisualTokenValue.setTokenStyle(bugLabelToken, 'black', '#FFFFFF');
-
- expect(token.style.color).toEqual('rgb(255, 255, 255)');
- expect(token.style.color).not.toEqual(originalTextColor);
- expect(token.querySelector('.remove-token').classList.contains('inverted')).toEqual(true);
- });
- });
-
- describe('render', () => {
- const setupSpies = subject => {
- spyOn(subject, 'updateLabelTokenColor'); // eslint-disable-line jasmine/no-unsafe-spy
- const updateLabelTokenColorSpy = subject.updateLabelTokenColor;
-
- spyOn(subject, 'updateUserTokenAppearance'); // eslint-disable-line jasmine/no-unsafe-spy
- const updateUserTokenAppearanceSpy = subject.updateUserTokenAppearance;
-
- return { updateLabelTokenColorSpy, updateUserTokenAppearanceSpy };
- };
-
- const keywordToken = FilteredSearchSpecHelper.createFilterVisualToken('search');
- const milestoneToken = FilteredSearchSpecHelper.createFilterVisualToken(
- 'milestone',
- 'upcoming',
- );
-
- beforeEach(() => {
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
- ${authorToken.outerHTML}
- ${bugLabelToken.outerHTML}
- ${keywordToken.outerHTML}
- ${milestoneToken.outerHTML}
- `);
- });
-
- it('renders a author token value element', () => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
-
- const { updateLabelTokenColorSpy, updateUserTokenAppearanceSpy } = setupSpies(subject);
- subject.render(tokenValueContainer, tokenValueElement);
-
- expect(updateUserTokenAppearanceSpy.calls.count()).toBe(1);
- const expectedArgs = [tokenValueContainer, tokenValueElement];
-
- expect(updateUserTokenAppearanceSpy.calls.argsFor(0)).toEqual(expectedArgs);
- expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
- });
-
- it('renders a label token value element', () => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(bugLabelToken);
-
- const { updateLabelTokenColorSpy, updateUserTokenAppearanceSpy } = setupSpies(subject);
- subject.render(tokenValueContainer, tokenValueElement);
-
- expect(updateLabelTokenColorSpy.calls.count()).toBe(1);
- const expectedArgs = [tokenValueContainer];
-
- expect(updateLabelTokenColorSpy.calls.argsFor(0)).toEqual(expectedArgs);
- expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
- });
-
- it('renders a milestone token value element', () => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(milestoneToken);
-
- const { updateLabelTokenColorSpy, updateUserTokenAppearanceSpy } = setupSpies(subject);
- subject.render(tokenValueContainer, tokenValueElement);
-
- expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
- expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
- });
-
- it('does not update user token appearance for `none` filter', () => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
-
- subject.tokenValue = 'none';
-
- const { updateUserTokenAppearanceSpy } = setupSpies(subject);
- subject.render(tokenValueContainer, tokenValueElement);
-
- expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
- });
-
- it('does not update user token appearance for `None` filter', () => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
-
- subject.tokenValue = 'None';
-
- const { updateUserTokenAppearanceSpy } = setupSpies(subject);
- subject.render(tokenValueContainer, tokenValueElement);
-
- expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
- });
-
- it('does not update user token appearance for `any` filter', () => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
-
- subject.tokenValue = 'any';
-
- const { updateUserTokenAppearanceSpy } = setupSpies(subject);
- subject.render(tokenValueContainer, tokenValueElement);
-
- expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
- });
-
- it('does not update label token color for `None` filter', () => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(bugLabelToken);
-
- subject.tokenValue = 'None';
-
- const { updateLabelTokenColorSpy } = setupSpies(subject);
- subject.render(tokenValueContainer, tokenValueElement);
-
- expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
- });
-
- it('does not update label token color for `none` filter', () => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(bugLabelToken);
-
- subject.tokenValue = 'none';
-
- const { updateLabelTokenColorSpy } = setupSpies(subject);
- subject.render(tokenValueContainer, tokenValueElement);
-
- expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
- });
-
- it('does not update label token color for `any` filter', () => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(bugLabelToken);
-
- subject.tokenValue = 'any';
-
- const { updateLabelTokenColorSpy } = setupSpies(subject);
- subject.render(tokenValueContainer, tokenValueElement);
-
- expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
- });
- });
-});
diff --git a/spec/javascripts/flash_spec.js b/spec/javascripts/flash_spec.js
deleted file mode 100644
index 39ca4eedb69..00000000000
--- a/spec/javascripts/flash_spec.js
+++ /dev/null
@@ -1,236 +0,0 @@
-import flash, { createFlashEl, createAction, hideFlash, removeFlashClickListener } from '~/flash';
-
-describe('Flash', () => {
- describe('createFlashEl', () => {
- let el;
-
- beforeEach(() => {
- el = document.createElement('div');
- });
-
- afterEach(() => {
- el.innerHTML = '';
- });
-
- it('creates flash element with type', () => {
- el.innerHTML = createFlashEl('testing', 'alert');
-
- expect(el.querySelector('.flash-alert')).not.toBeNull();
- });
-
- it('escapes text', () => {
- el.innerHTML = createFlashEl('<script>alert("a");</script>', 'alert');
-
- expect(el.querySelector('.flash-text').textContent.trim()).toBe(
- '<script>alert("a");</script>',
- );
- });
- });
-
- describe('hideFlash', () => {
- let el;
-
- beforeEach(() => {
- el = document.createElement('div');
- el.className = 'js-testing';
- });
-
- it('sets transition style', () => {
- hideFlash(el);
-
- expect(el.style['transition-property']).toBe('opacity');
-
- expect(el.style['transition-duration']).toBe('0.15s');
- });
-
- it('sets opacity style', () => {
- hideFlash(el);
-
- expect(el.style.opacity).toBe('0');
- });
-
- it('does not set styles when fadeTransition is false', () => {
- hideFlash(el, false);
-
- expect(el.style.opacity).toBe('');
-
- expect(el.style.transition).toBe('');
- });
-
- it('removes element after transitionend', () => {
- document.body.appendChild(el);
-
- hideFlash(el);
- el.dispatchEvent(new Event('transitionend'));
-
- expect(document.querySelector('.js-testing')).toBeNull();
- });
-
- it('calls event listener callback once', () => {
- spyOn(el, 'remove').and.callThrough();
- document.body.appendChild(el);
-
- hideFlash(el);
-
- el.dispatchEvent(new Event('transitionend'));
- el.dispatchEvent(new Event('transitionend'));
-
- expect(el.remove.calls.count()).toBe(1);
- });
- });
-
- describe('createAction', () => {
- let el;
-
- beforeEach(() => {
- el = document.createElement('div');
- });
-
- it('creates link with href', () => {
- el.innerHTML = createAction({
- href: 'testing',
- title: 'test',
- });
-
- expect(el.querySelector('.flash-action').href).toContain('testing');
- });
-
- it('uses hash as href when no href is present', () => {
- el.innerHTML = createAction({
- title: 'test',
- });
-
- expect(el.querySelector('.flash-action').href).toContain('#');
- });
-
- it('adds role when no href is present', () => {
- el.innerHTML = createAction({
- title: 'test',
- });
-
- expect(el.querySelector('.flash-action').getAttribute('role')).toBe('button');
- });
-
- it('escapes the title text', () => {
- el.innerHTML = createAction({
- title: '<script>alert("a")</script>',
- });
-
- expect(el.querySelector('.flash-action').textContent.trim()).toBe(
- '<script>alert("a")</script>',
- );
- });
- });
-
- describe('createFlash', () => {
- describe('no flash-container', () => {
- it('does not add to the DOM', () => {
- const flashEl = flash('testing');
-
- expect(flashEl).toBeNull();
-
- expect(document.querySelector('.flash-alert')).toBeNull();
- });
- });
-
- describe('with flash-container', () => {
- beforeEach(() => {
- document.body.innerHTML += `
- <div class="content-wrapper js-content-wrapper">
- <div class="flash-container"></div>
- </div>
- `;
- });
-
- afterEach(() => {
- document.querySelector('.js-content-wrapper').remove();
- });
-
- it('adds flash element into container', () => {
- flash('test', 'alert', document, null, false, true);
-
- expect(document.querySelector('.flash-alert')).not.toBeNull();
-
- expect(document.body.className).toContain('flash-shown');
- });
-
- it('adds flash into specified parent', () => {
- flash('test', 'alert', document.querySelector('.content-wrapper'));
-
- expect(document.querySelector('.content-wrapper .flash-alert')).not.toBeNull();
- });
-
- it('adds container classes when inside content-wrapper', () => {
- flash('test');
-
- expect(document.querySelector('.flash-text').className).toBe('flash-text');
- });
-
- it('does not add container when outside of content-wrapper', () => {
- document.querySelector('.content-wrapper').className = 'js-content-wrapper';
- flash('test');
-
- expect(document.querySelector('.flash-text').className.trim()).toContain('flash-text');
- });
-
- it('removes element after clicking', () => {
- flash('test', 'alert', document, null, false, true);
-
- document.querySelector('.flash-alert .js-close-icon').click();
-
- expect(document.querySelector('.flash-alert')).toBeNull();
-
- expect(document.body.className).not.toContain('flash-shown');
- });
-
- describe('with actionConfig', () => {
- it('adds action link', () => {
- flash('test', 'alert', document, {
- title: 'test',
- });
-
- expect(document.querySelector('.flash-action')).not.toBeNull();
- });
-
- it('calls actionConfig clickHandler on click', () => {
- const actionConfig = {
- title: 'test',
- clickHandler: jasmine.createSpy('actionConfig'),
- };
-
- flash('test', 'alert', document, actionConfig);
-
- document.querySelector('.flash-action').click();
-
- expect(actionConfig.clickHandler).toHaveBeenCalled();
- });
- });
- });
- });
-
- describe('removeFlashClickListener', () => {
- beforeEach(() => {
- document.body.innerHTML += `
- <div class="flash-container">
- <div class="flash">
- <div class="close-icon js-close-icon"></div>
- </div>
- </div>
- `;
- });
-
- it('removes global flash on click', done => {
- const flashEl = document.querySelector('.flash');
-
- removeFlashClickListener(flashEl, false);
-
- flashEl.querySelector('.js-close-icon').click();
-
- setTimeout(() => {
- expect(document.querySelector('.flash')).toBeNull();
-
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/frequent_items/components/app_spec.js b/spec/javascripts/frequent_items/components/app_spec.js
deleted file mode 100644
index b293ed541fd..00000000000
--- a/spec/javascripts/frequent_items/components/app_spec.js
+++ /dev/null
@@ -1,257 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import Vue from 'vue';
-import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
-import axios from '~/lib/utils/axios_utils';
-import appComponent from '~/frequent_items/components/app.vue';
-import eventHub from '~/frequent_items/event_hub';
-import store from '~/frequent_items/store';
-import { FREQUENT_ITEMS, HOUR_IN_MS } from '~/frequent_items/constants';
-import { getTopFrequentItems } from '~/frequent_items/utils';
-import { currentSession, mockFrequentProjects, mockSearchedProjects } from '../mock_data';
-
-let session;
-const createComponentWithStore = (namespace = 'projects') => {
- session = currentSession[namespace];
- gon.api_version = session.apiVersion;
- const Component = Vue.extend(appComponent);
-
- return mountComponentWithStore(Component, {
- store,
- props: {
- namespace,
- currentUserName: session.username,
- currentItem: session.project || session.group,
- },
- });
-};
-
-describe('Frequent Items App Component', () => {
- let vm;
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- vm = createComponentWithStore();
- });
-
- afterEach(() => {
- mock.restore();
- vm.$destroy();
- });
-
- describe('methods', () => {
- describe('dropdownOpenHandler', () => {
- it('should fetch frequent items when no search has been previously made on desktop', () => {
- spyOn(vm, 'fetchFrequentItems');
-
- vm.dropdownOpenHandler();
-
- expect(vm.fetchFrequentItems).toHaveBeenCalledWith();
- });
- });
-
- describe('logItemAccess', () => {
- let storage;
-
- beforeEach(() => {
- storage = {};
-
- spyOn(window.localStorage, 'setItem').and.callFake((storageKey, value) => {
- storage[storageKey] = value;
- });
-
- spyOn(window.localStorage, 'getItem').and.callFake(storageKey => {
- if (storage[storageKey]) {
- return storage[storageKey];
- }
-
- return null;
- });
- });
-
- it('should create a project store if it does not exist and adds a project', () => {
- vm.logItemAccess(session.storageKey, session.project);
-
- const projects = JSON.parse(storage[session.storageKey]);
-
- expect(projects.length).toBe(1);
- expect(projects[0].frequency).toBe(1);
- expect(projects[0].lastAccessedOn).toBeDefined();
- });
-
- it('should prevent inserting same report multiple times into store', () => {
- vm.logItemAccess(session.storageKey, session.project);
- vm.logItemAccess(session.storageKey, session.project);
-
- const projects = JSON.parse(storage[session.storageKey]);
-
- expect(projects.length).toBe(1);
- });
-
- it('should increase frequency of report if it was logged multiple times over the course of an hour', () => {
- let projects;
- const newTimestamp = Date.now() + HOUR_IN_MS + 1;
-
- vm.logItemAccess(session.storageKey, session.project);
- projects = JSON.parse(storage[session.storageKey]);
-
- expect(projects[0].frequency).toBe(1);
-
- vm.logItemAccess(session.storageKey, {
- ...session.project,
- lastAccessedOn: newTimestamp,
- });
- projects = JSON.parse(storage[session.storageKey]);
-
- expect(projects[0].frequency).toBe(2);
- expect(projects[0].lastAccessedOn).not.toBe(session.project.lastAccessedOn);
- });
-
- it('should always update project metadata', () => {
- let projects;
- const oldProject = {
- ...session.project,
- };
-
- const newProject = {
- ...session.project,
- name: 'New Name',
- avatarUrl: 'new/avatar.png',
- namespace: 'New / Namespace',
- webUrl: 'http://localhost/new/web/url',
- };
-
- vm.logItemAccess(session.storageKey, oldProject);
- projects = JSON.parse(storage[session.storageKey]);
-
- expect(projects[0].name).toBe(oldProject.name);
- expect(projects[0].avatarUrl).toBe(oldProject.avatarUrl);
- expect(projects[0].namespace).toBe(oldProject.namespace);
- expect(projects[0].webUrl).toBe(oldProject.webUrl);
-
- vm.logItemAccess(session.storageKey, newProject);
- projects = JSON.parse(storage[session.storageKey]);
-
- expect(projects[0].name).toBe(newProject.name);
- expect(projects[0].avatarUrl).toBe(newProject.avatarUrl);
- expect(projects[0].namespace).toBe(newProject.namespace);
- expect(projects[0].webUrl).toBe(newProject.webUrl);
- });
-
- it('should not add more than 20 projects in store', () => {
- for (let id = 0; id < FREQUENT_ITEMS.MAX_COUNT; id += 1) {
- const project = {
- ...session.project,
- id,
- };
- vm.logItemAccess(session.storageKey, project);
- }
-
- const projects = JSON.parse(storage[session.storageKey]);
-
- expect(projects.length).toBe(FREQUENT_ITEMS.MAX_COUNT);
- });
- });
- });
-
- describe('created', () => {
- it('should bind event listeners on eventHub', done => {
- spyOn(eventHub, '$on');
-
- createComponentWithStore().$mount();
-
- Vue.nextTick(() => {
- expect(eventHub.$on).toHaveBeenCalledWith('projects-dropdownOpen', jasmine.any(Function));
- done();
- });
- });
- });
-
- describe('beforeDestroy', () => {
- it('should unbind event listeners on eventHub', done => {
- spyOn(eventHub, '$off');
-
- vm.$mount();
- vm.$destroy();
-
- Vue.nextTick(() => {
- expect(eventHub.$off).toHaveBeenCalledWith('projects-dropdownOpen', jasmine.any(Function));
- done();
- });
- });
- });
-
- describe('template', () => {
- it('should render search input', () => {
- expect(vm.$el.querySelector('.search-input-container')).toBeDefined();
- });
-
- it('should render loading animation', done => {
- vm.$store.dispatch('fetchSearchedItems');
-
- Vue.nextTick(() => {
- const loadingEl = vm.$el.querySelector('.loading-animation');
-
- expect(loadingEl).toBeDefined();
- expect(loadingEl.classList.contains('prepend-top-20')).toBe(true);
- expect(loadingEl.querySelector('span').getAttribute('aria-label')).toBe('Loading projects');
- done();
- });
- });
-
- it('should render frequent projects list header', done => {
- Vue.nextTick(() => {
- const sectionHeaderEl = vm.$el.querySelector('.section-header');
-
- expect(sectionHeaderEl).toBeDefined();
- expect(sectionHeaderEl.innerText.trim()).toBe('Frequently visited');
- done();
- });
- });
-
- it('should render frequent projects list', done => {
- const expectedResult = getTopFrequentItems(mockFrequentProjects);
- spyOn(window.localStorage, 'getItem').and.callFake(() =>
- JSON.stringify(mockFrequentProjects),
- );
-
- expect(vm.$el.querySelectorAll('.frequent-items-list-container li').length).toBe(1);
-
- vm.fetchFrequentItems();
- Vue.nextTick(() => {
- expect(vm.$el.querySelectorAll('.frequent-items-list-container li').length).toBe(
- expectedResult.length,
- );
- done();
- });
- });
-
- it('should render searched projects list', done => {
- mock.onGet(/\/api\/v4\/projects.json(.*)$/).replyOnce(200, mockSearchedProjects);
-
- expect(vm.$el.querySelectorAll('.frequent-items-list-container li').length).toBe(1);
-
- vm.$store.dispatch('setSearchQuery', 'gitlab');
- vm.$nextTick()
- .then(() => {
- expect(vm.$el.querySelector('.loading-animation')).toBeDefined();
- })
-
- // This test waits for multiple ticks in order to allow the responses to
- // propagate through each interceptor installed on the Axios instance.
- // This shouldn't be necessary; this test should be refactored to avoid this.
- // https://gitlab.com/gitlab-org/gitlab/issues/32479
- .then(vm.$nextTick)
- .then(vm.$nextTick)
- .then(vm.$nextTick)
-
- .then(() => {
- expect(vm.$el.querySelectorAll('.frequent-items-list-container li').length).toBe(
- mockSearchedProjects.data.length,
- );
- })
- .then(done)
- .catch(done.fail);
- });
- });
-});
diff --git a/spec/javascripts/frequent_items/mock_data.js b/spec/javascripts/frequent_items/mock_data.js
deleted file mode 100644
index 419f70e41af..00000000000
--- a/spec/javascripts/frequent_items/mock_data.js
+++ /dev/null
@@ -1,168 +0,0 @@
-export const currentSession = {
- groups: {
- username: 'root',
- storageKey: 'root/frequent-groups',
- apiVersion: 'v4',
- group: {
- id: 1,
- name: 'dummy-group',
- full_name: 'dummy-parent-group',
- webUrl: `${gl.TEST_HOST}/dummy-group`,
- avatarUrl: null,
- lastAccessedOn: Date.now(),
- },
- },
- projects: {
- username: 'root',
- storageKey: 'root/frequent-projects',
- apiVersion: 'v4',
- project: {
- id: 1,
- name: 'dummy-project',
- namespace: 'SampleGroup / Dummy-Project',
- webUrl: `${gl.TEST_HOST}/samplegroup/dummy-project`,
- avatarUrl: null,
- lastAccessedOn: Date.now(),
- },
- },
-};
-
-export const mockNamespace = 'projects';
-
-export const mockStorageKey = 'test-user/frequent-projects';
-
-export const mockGroup = {
- id: 1,
- name: 'Sub451',
- namespace: 'Commit451 / Sub451',
- webUrl: `${gl.TEST_HOST}/Commit451/Sub451`,
- avatarUrl: null,
-};
-
-export const mockRawGroup = {
- id: 1,
- name: 'Sub451',
- full_name: 'Commit451 / Sub451',
- web_url: `${gl.TEST_HOST}/Commit451/Sub451`,
- avatar_url: null,
-};
-
-export const mockFrequentGroups = [
- {
- id: 3,
- name: 'Subgroup451',
- full_name: 'Commit451 / Subgroup451',
- webUrl: '/Commit451/Subgroup451',
- avatarUrl: null,
- frequency: 7,
- lastAccessedOn: 1497979281815,
- },
- {
- id: 1,
- name: 'Commit451',
- full_name: 'Commit451',
- webUrl: '/Commit451',
- avatarUrl: null,
- frequency: 3,
- lastAccessedOn: 1497979281815,
- },
-];
-
-export const mockSearchedGroups = [mockRawGroup];
-export const mockProcessedSearchedGroups = [mockGroup];
-
-export const mockProject = {
- id: 1,
- name: 'GitLab Community Edition',
- namespace: 'gitlab-org / gitlab-ce',
- webUrl: `${gl.TEST_HOST}/gitlab-org/gitlab-foss`,
- avatarUrl: null,
-};
-
-export const mockRawProject = {
- id: 1,
- name: 'GitLab Community Edition',
- name_with_namespace: 'gitlab-org / gitlab-ce',
- web_url: `${gl.TEST_HOST}/gitlab-org/gitlab-foss`,
- avatar_url: null,
-};
-
-export const mockFrequentProjects = [
- {
- id: 1,
- name: 'GitLab Community Edition',
- namespace: 'gitlab-org / gitlab-ce',
- webUrl: `${gl.TEST_HOST}/gitlab-org/gitlab-foss`,
- avatarUrl: null,
- frequency: 1,
- lastAccessedOn: Date.now(),
- },
- {
- id: 2,
- name: 'GitLab CI',
- namespace: 'gitlab-org / gitlab-ci',
- webUrl: `${gl.TEST_HOST}/gitlab-org/gitlab-ci`,
- avatarUrl: null,
- frequency: 9,
- lastAccessedOn: Date.now(),
- },
- {
- id: 3,
- name: 'Typeahead.Js',
- namespace: 'twitter / typeahead-js',
- webUrl: `${gl.TEST_HOST}/twitter/typeahead-js`,
- avatarUrl: '/uploads/-/system/project/avatar/7/TWBS.png',
- frequency: 2,
- lastAccessedOn: Date.now(),
- },
- {
- id: 4,
- name: 'Intel',
- namespace: 'platform / hardware / bsp / intel',
- webUrl: `${gl.TEST_HOST}/platform/hardware/bsp/intel`,
- avatarUrl: null,
- frequency: 3,
- lastAccessedOn: Date.now(),
- },
- {
- id: 5,
- name: 'v4.4',
- namespace: 'platform / hardware / bsp / kernel / common / v4.4',
- webUrl: `${gl.TEST_HOST}/platform/hardware/bsp/kernel/common/v4.4`,
- avatarUrl: null,
- frequency: 8,
- lastAccessedOn: Date.now(),
- },
-];
-
-export const mockSearchedProjects = { data: [mockRawProject] };
-export const mockProcessedSearchedProjects = [mockProject];
-
-export const unsortedFrequentItems = [
- { id: 1, frequency: 12, lastAccessedOn: 1491400843391 },
- { id: 2, frequency: 14, lastAccessedOn: 1488240890738 },
- { id: 3, frequency: 44, lastAccessedOn: 1497675908472 },
- { id: 4, frequency: 8, lastAccessedOn: 1497979281815 },
- { id: 5, frequency: 34, lastAccessedOn: 1488089211943 },
- { id: 6, frequency: 14, lastAccessedOn: 1493517292488 },
- { id: 7, frequency: 42, lastAccessedOn: 1486815299875 },
- { id: 8, frequency: 33, lastAccessedOn: 1500762279114 },
- { id: 10, frequency: 46, lastAccessedOn: 1483251641543 },
-];
-
-/**
- * This const has a specific order which tests authenticity
- * of `getTopFrequentItems` method so
- * DO NOT change order of items in this const.
- */
-export const sortedFrequentItems = [
- { id: 10, frequency: 46, lastAccessedOn: 1483251641543 },
- { id: 3, frequency: 44, lastAccessedOn: 1497675908472 },
- { id: 7, frequency: 42, lastAccessedOn: 1486815299875 },
- { id: 5, frequency: 34, lastAccessedOn: 1488089211943 },
- { id: 8, frequency: 33, lastAccessedOn: 1500762279114 },
- { id: 6, frequency: 14, lastAccessedOn: 1493517292488 },
- { id: 2, frequency: 14, lastAccessedOn: 1488240890738 },
- { id: 1, frequency: 12, lastAccessedOn: 1491400843391 },
- { id: 4, frequency: 8, lastAccessedOn: 1497979281815 },
-];
diff --git a/spec/javascripts/frequent_items/store/actions_spec.js b/spec/javascripts/frequent_items/store/actions_spec.js
deleted file mode 100644
index 7b065b69cce..00000000000
--- a/spec/javascripts/frequent_items/store/actions_spec.js
+++ /dev/null
@@ -1,228 +0,0 @@
-import testAction from 'spec/helpers/vuex_action_helper';
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import AccessorUtilities from '~/lib/utils/accessor';
-import * as actions from '~/frequent_items/store/actions';
-import * as types from '~/frequent_items/store/mutation_types';
-import state from '~/frequent_items/store/state';
-import {
- mockNamespace,
- mockStorageKey,
- mockFrequentProjects,
- mockSearchedProjects,
-} from '../mock_data';
-
-describe('Frequent Items Dropdown Store Actions', () => {
- let mockedState;
- let mock;
-
- beforeEach(() => {
- mockedState = state();
- mock = new MockAdapter(axios);
-
- mockedState.namespace = mockNamespace;
- mockedState.storageKey = mockStorageKey;
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- describe('setNamespace', () => {
- it('should set namespace', done => {
- testAction(
- actions.setNamespace,
- mockNamespace,
- mockedState,
- [{ type: types.SET_NAMESPACE, payload: mockNamespace }],
- [],
- done,
- );
- });
- });
-
- describe('setStorageKey', () => {
- it('should set storage key', done => {
- testAction(
- actions.setStorageKey,
- mockStorageKey,
- mockedState,
- [{ type: types.SET_STORAGE_KEY, payload: mockStorageKey }],
- [],
- done,
- );
- });
- });
-
- describe('requestFrequentItems', () => {
- it('should request frequent items', done => {
- testAction(
- actions.requestFrequentItems,
- null,
- mockedState,
- [{ type: types.REQUEST_FREQUENT_ITEMS }],
- [],
- done,
- );
- });
- });
-
- describe('receiveFrequentItemsSuccess', () => {
- it('should set frequent items', done => {
- testAction(
- actions.receiveFrequentItemsSuccess,
- mockFrequentProjects,
- mockedState,
- [{ type: types.RECEIVE_FREQUENT_ITEMS_SUCCESS, payload: mockFrequentProjects }],
- [],
- done,
- );
- });
- });
-
- describe('receiveFrequentItemsError', () => {
- it('should set frequent items error state', done => {
- testAction(
- actions.receiveFrequentItemsError,
- null,
- mockedState,
- [{ type: types.RECEIVE_FREQUENT_ITEMS_ERROR }],
- [],
- done,
- );
- });
- });
-
- describe('fetchFrequentItems', () => {
- it('should dispatch `receiveFrequentItemsSuccess`', done => {
- mockedState.namespace = mockNamespace;
- mockedState.storageKey = mockStorageKey;
-
- testAction(
- actions.fetchFrequentItems,
- null,
- mockedState,
- [],
- [{ type: 'requestFrequentItems' }, { type: 'receiveFrequentItemsSuccess', payload: [] }],
- done,
- );
- });
-
- it('should dispatch `receiveFrequentItemsError`', done => {
- spyOn(AccessorUtilities, 'isLocalStorageAccessSafe').and.returnValue(false);
- mockedState.namespace = mockNamespace;
- mockedState.storageKey = mockStorageKey;
-
- testAction(
- actions.fetchFrequentItems,
- null,
- mockedState,
- [],
- [{ type: 'requestFrequentItems' }, { type: 'receiveFrequentItemsError' }],
- done,
- );
- });
- });
-
- describe('requestSearchedItems', () => {
- it('should request searched items', done => {
- testAction(
- actions.requestSearchedItems,
- null,
- mockedState,
- [{ type: types.REQUEST_SEARCHED_ITEMS }],
- [],
- done,
- );
- });
- });
-
- describe('receiveSearchedItemsSuccess', () => {
- it('should set searched items', done => {
- testAction(
- actions.receiveSearchedItemsSuccess,
- mockSearchedProjects,
- mockedState,
- [{ type: types.RECEIVE_SEARCHED_ITEMS_SUCCESS, payload: mockSearchedProjects }],
- [],
- done,
- );
- });
- });
-
- describe('receiveSearchedItemsError', () => {
- it('should set searched items error state', done => {
- testAction(
- actions.receiveSearchedItemsError,
- null,
- mockedState,
- [{ type: types.RECEIVE_SEARCHED_ITEMS_ERROR }],
- [],
- done,
- );
- });
- });
-
- describe('fetchSearchedItems', () => {
- beforeEach(() => {
- gon.api_version = 'v4';
- });
-
- it('should dispatch `receiveSearchedItemsSuccess`', done => {
- mock.onGet(/\/api\/v4\/projects.json(.*)$/).replyOnce(200, mockSearchedProjects, {});
-
- testAction(
- actions.fetchSearchedItems,
- null,
- mockedState,
- [],
- [
- { type: 'requestSearchedItems' },
- {
- type: 'receiveSearchedItemsSuccess',
- payload: { data: mockSearchedProjects, headers: {} },
- },
- ],
- done,
- );
- });
-
- it('should dispatch `receiveSearchedItemsError`', done => {
- gon.api_version = 'v4';
- mock.onGet(/\/api\/v4\/projects.json(.*)$/).replyOnce(500);
-
- testAction(
- actions.fetchSearchedItems,
- null,
- mockedState,
- [],
- [{ type: 'requestSearchedItems' }, { type: 'receiveSearchedItemsError' }],
- done,
- );
- });
- });
-
- describe('setSearchQuery', () => {
- it('should commit query and dispatch `fetchSearchedItems` when query is present', done => {
- testAction(
- actions.setSearchQuery,
- { query: 'test' },
- mockedState,
- [{ type: types.SET_SEARCH_QUERY, payload: { query: 'test' } }],
- [{ type: 'fetchSearchedItems', payload: { query: 'test' } }],
- done,
- );
- });
-
- it('should commit query and dispatch `fetchFrequentItems` when query is empty', done => {
- testAction(
- actions.setSearchQuery,
- null,
- mockedState,
- [{ type: types.SET_SEARCH_QUERY, payload: null }],
- [{ type: 'fetchFrequentItems' }],
- done,
- );
- });
- });
-});
diff --git a/spec/javascripts/frequent_items/store/mutations_spec.js b/spec/javascripts/frequent_items/store/mutations_spec.js
deleted file mode 100644
index d36964b2600..00000000000
--- a/spec/javascripts/frequent_items/store/mutations_spec.js
+++ /dev/null
@@ -1,117 +0,0 @@
-import state from '~/frequent_items/store/state';
-import mutations from '~/frequent_items/store/mutations';
-import * as types from '~/frequent_items/store/mutation_types';
-import {
- mockNamespace,
- mockStorageKey,
- mockFrequentProjects,
- mockSearchedProjects,
- mockProcessedSearchedProjects,
- mockSearchedGroups,
- mockProcessedSearchedGroups,
-} from '../mock_data';
-
-describe('Frequent Items dropdown mutations', () => {
- let stateCopy;
-
- beforeEach(() => {
- stateCopy = state();
- });
-
- describe('SET_NAMESPACE', () => {
- it('should set namespace', () => {
- mutations[types.SET_NAMESPACE](stateCopy, mockNamespace);
-
- expect(stateCopy.namespace).toEqual(mockNamespace);
- });
- });
-
- describe('SET_STORAGE_KEY', () => {
- it('should set storage key', () => {
- mutations[types.SET_STORAGE_KEY](stateCopy, mockStorageKey);
-
- expect(stateCopy.storageKey).toEqual(mockStorageKey);
- });
- });
-
- describe('SET_SEARCH_QUERY', () => {
- it('should set search query', () => {
- const searchQuery = 'gitlab-ce';
-
- mutations[types.SET_SEARCH_QUERY](stateCopy, searchQuery);
-
- expect(stateCopy.searchQuery).toEqual(searchQuery);
- });
- });
-
- describe('REQUEST_FREQUENT_ITEMS', () => {
- it('should set view states when requesting frequent items', () => {
- mutations[types.REQUEST_FREQUENT_ITEMS](stateCopy);
-
- expect(stateCopy.isLoadingItems).toEqual(true);
- expect(stateCopy.hasSearchQuery).toEqual(false);
- });
- });
-
- describe('RECEIVE_FREQUENT_ITEMS_SUCCESS', () => {
- it('should set view states when receiving frequent items', () => {
- mutations[types.RECEIVE_FREQUENT_ITEMS_SUCCESS](stateCopy, mockFrequentProjects);
-
- expect(stateCopy.items).toEqual(mockFrequentProjects);
- expect(stateCopy.isLoadingItems).toEqual(false);
- expect(stateCopy.hasSearchQuery).toEqual(false);
- expect(stateCopy.isFetchFailed).toEqual(false);
- });
- });
-
- describe('RECEIVE_FREQUENT_ITEMS_ERROR', () => {
- it('should set items and view states when error occurs retrieving frequent items', () => {
- mutations[types.RECEIVE_FREQUENT_ITEMS_ERROR](stateCopy);
-
- expect(stateCopy.items).toEqual([]);
- expect(stateCopy.isLoadingItems).toEqual(false);
- expect(stateCopy.hasSearchQuery).toEqual(false);
- expect(stateCopy.isFetchFailed).toEqual(true);
- });
- });
-
- describe('REQUEST_SEARCHED_ITEMS', () => {
- it('should set view states when requesting searched items', () => {
- mutations[types.REQUEST_SEARCHED_ITEMS](stateCopy);
-
- expect(stateCopy.isLoadingItems).toEqual(true);
- expect(stateCopy.hasSearchQuery).toEqual(true);
- });
- });
-
- describe('RECEIVE_SEARCHED_ITEMS_SUCCESS', () => {
- it('should set items and view states when receiving searched items', () => {
- mutations[types.RECEIVE_SEARCHED_ITEMS_SUCCESS](stateCopy, mockSearchedProjects);
-
- expect(stateCopy.items).toEqual(mockProcessedSearchedProjects);
- expect(stateCopy.isLoadingItems).toEqual(false);
- expect(stateCopy.hasSearchQuery).toEqual(true);
- expect(stateCopy.isFetchFailed).toEqual(false);
- });
-
- it('should also handle the different `full_name` key for namespace in groups payload', () => {
- mutations[types.RECEIVE_SEARCHED_ITEMS_SUCCESS](stateCopy, mockSearchedGroups);
-
- expect(stateCopy.items).toEqual(mockProcessedSearchedGroups);
- expect(stateCopy.isLoadingItems).toEqual(false);
- expect(stateCopy.hasSearchQuery).toEqual(true);
- expect(stateCopy.isFetchFailed).toEqual(false);
- });
- });
-
- describe('RECEIVE_SEARCHED_ITEMS_ERROR', () => {
- it('should set view states when error occurs retrieving searched items', () => {
- mutations[types.RECEIVE_SEARCHED_ITEMS_ERROR](stateCopy);
-
- expect(stateCopy.items).toEqual([]);
- expect(stateCopy.isLoadingItems).toEqual(false);
- expect(stateCopy.hasSearchQuery).toEqual(true);
- expect(stateCopy.isFetchFailed).toEqual(true);
- });
- });
-});
diff --git a/spec/javascripts/frequent_items/utils_spec.js b/spec/javascripts/frequent_items/utils_spec.js
deleted file mode 100644
index 2939b46bc31..00000000000
--- a/spec/javascripts/frequent_items/utils_spec.js
+++ /dev/null
@@ -1,130 +0,0 @@
-import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
-import {
- isMobile,
- getTopFrequentItems,
- updateExistingFrequentItem,
- sanitizeItem,
-} from '~/frequent_items/utils';
-import { HOUR_IN_MS, FREQUENT_ITEMS } from '~/frequent_items/constants';
-import { mockProject, unsortedFrequentItems, sortedFrequentItems } from './mock_data';
-
-describe('Frequent Items utils spec', () => {
- describe('isMobile', () => {
- it('returns true when the screen is medium ', () => {
- spyOn(bp, 'getBreakpointSize').and.returnValue('md');
-
- expect(isMobile()).toBe(true);
- });
-
- it('returns true when the screen is small ', () => {
- spyOn(bp, 'getBreakpointSize').and.returnValue('sm');
-
- expect(isMobile()).toBe(true);
- });
-
- it('returns true when the screen is extra-small ', () => {
- spyOn(bp, 'getBreakpointSize').and.returnValue('xs');
-
- expect(isMobile()).toBe(true);
- });
-
- it('returns false when the screen is larger than medium ', () => {
- spyOn(bp, 'getBreakpointSize').and.returnValue('lg');
-
- expect(isMobile()).toBe(false);
- });
- });
-
- describe('getTopFrequentItems', () => {
- it('returns empty array if no items provided', () => {
- const result = getTopFrequentItems();
-
- expect(result.length).toBe(0);
- });
-
- it('returns correct amount of items for mobile', () => {
- spyOn(bp, 'getBreakpointSize').and.returnValue('md');
- const result = getTopFrequentItems(unsortedFrequentItems);
-
- expect(result.length).toBe(FREQUENT_ITEMS.LIST_COUNT_MOBILE);
- });
-
- it('returns correct amount of items for desktop', () => {
- spyOn(bp, 'getBreakpointSize').and.returnValue('xl');
- const result = getTopFrequentItems(unsortedFrequentItems);
-
- expect(result.length).toBe(FREQUENT_ITEMS.LIST_COUNT_DESKTOP);
- });
-
- it('sorts frequent items in order of frequency and lastAccessedOn', () => {
- spyOn(bp, 'getBreakpointSize').and.returnValue('xl');
- const result = getTopFrequentItems(unsortedFrequentItems);
- const expectedResult = sortedFrequentItems.slice(0, FREQUENT_ITEMS.LIST_COUNT_DESKTOP);
-
- expect(result).toEqual(expectedResult);
- });
- });
-
- describe('updateExistingFrequentItem', () => {
- let mockedProject;
-
- beforeEach(() => {
- mockedProject = {
- ...mockProject,
- frequency: 1,
- lastAccessedOn: 1497979281815,
- };
- });
-
- it('updates item if accessed over an hour ago', () => {
- const newTimestamp = Date.now() + HOUR_IN_MS + 1;
- const newItem = {
- ...mockedProject,
- lastAccessedOn: newTimestamp,
- };
- const result = updateExistingFrequentItem(mockedProject, newItem);
-
- expect(result.frequency).toBe(mockedProject.frequency + 1);
- });
-
- it('does not update item if accessed within the hour', () => {
- const newItem = {
- ...mockedProject,
- lastAccessedOn: mockedProject.lastAccessedOn + HOUR_IN_MS,
- };
- const result = updateExistingFrequentItem(mockedProject, newItem);
-
- expect(result.frequency).toBe(mockedProject.frequency);
- });
- });
-
- describe('sanitizeItem', () => {
- it('strips HTML tags for name and namespace', () => {
- const input = {
- name: '<br><b>test</b>',
- namespace: '<br>test',
- id: 1,
- };
-
- expect(sanitizeItem(input)).toEqual({ name: 'test', namespace: 'test', id: 1 });
- });
-
- it("skips `name` key if it doesn't exist on the item", () => {
- const input = {
- namespace: '<br>test',
- id: 1,
- };
-
- expect(sanitizeItem(input)).toEqual({ namespace: 'test', id: 1 });
- });
-
- it("skips `namespace` key if it doesn't exist on the item", () => {
- const input = {
- name: '<br><b>test</b>',
- id: 1,
- };
-
- expect(sanitizeItem(input)).toEqual({ name: 'test', id: 1 });
- });
- });
-});
diff --git a/spec/javascripts/gl_dropdown_spec.js b/spec/javascripts/gl_dropdown_spec.js
index 00bc552bd7d..06f76c581f2 100644
--- a/spec/javascripts/gl_dropdown_spec.js
+++ b/spec/javascripts/gl_dropdown_spec.js
@@ -44,19 +44,17 @@ describe('glDropdown', function describeDropdown() {
};
function initDropDown(hasRemote, isFilterable, extraOpts = {}) {
- const options = Object.assign(
- {
- selectable: true,
- filterable: isFilterable,
- data: hasRemote ? remoteMock.bind({}, this.projectsData) : this.projectsData,
- search: {
- fields: ['name'],
- },
- text: project => project.name_with_namespace || project.name,
- id: project => project.id,
+ const options = {
+ selectable: true,
+ filterable: isFilterable,
+ data: hasRemote ? remoteMock.bind({}, this.projectsData) : this.projectsData,
+ search: {
+ fields: ['name'],
},
- extraOpts,
- );
+ text: project => project.name_with_namespace || project.name,
+ id: project => project.id,
+ ...extraOpts,
+ };
this.dropdownButtonElement = $(
'#js-project-dropdown',
this.dropdownContainerElement,
diff --git a/spec/javascripts/groups/components/app_spec.js b/spec/javascripts/groups/components/app_spec.js
deleted file mode 100644
index 23b2564d3f9..00000000000
--- a/spec/javascripts/groups/components/app_spec.js
+++ /dev/null
@@ -1,533 +0,0 @@
-import '~/flash';
-import $ from 'jquery';
-import Vue from 'vue';
-
-import appComponent from '~/groups/components/app.vue';
-import groupFolderComponent from '~/groups/components/group_folder.vue';
-import groupItemComponent from '~/groups/components/group_item.vue';
-import eventHub from '~/groups/event_hub';
-import GroupsStore from '~/groups/store/groups_store';
-import GroupsService from '~/groups/service/groups_service';
-
-import {
- mockEndpoint,
- mockGroups,
- mockSearchedGroups,
- mockRawPageInfo,
- mockParentGroupItem,
- mockRawChildren,
- mockChildren,
- mockPageInfo,
-} from '../mock_data';
-
-const createComponent = (hideProjects = false) => {
- const Component = Vue.extend(appComponent);
- const store = new GroupsStore(false);
- const service = new GroupsService(mockEndpoint);
-
- store.state.pageInfo = mockPageInfo;
-
- return new Component({
- propsData: {
- store,
- service,
- hideProjects,
- },
- });
-};
-
-const returnServicePromise = (data, failed) =>
- new Promise((resolve, reject) => {
- if (failed) {
- reject(data);
- } else {
- resolve({
- json() {
- return data;
- },
- });
- }
- });
-
-describe('AppComponent', () => {
- let vm;
-
- beforeEach(done => {
- Vue.component('group-folder', groupFolderComponent);
- Vue.component('group-item', groupItemComponent);
-
- vm = createComponent();
-
- Vue.nextTick(() => {
- done();
- });
- });
-
- describe('computed', () => {
- beforeEach(() => {
- vm.$mount();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('groups', () => {
- it('should return list of groups from store', () => {
- spyOn(vm.store, 'getGroups');
-
- const { groups } = vm;
-
- expect(vm.store.getGroups).toHaveBeenCalled();
- expect(groups).not.toBeDefined();
- });
- });
-
- describe('pageInfo', () => {
- it('should return pagination info from store', () => {
- spyOn(vm.store, 'getPaginationInfo');
-
- const { pageInfo } = vm;
-
- expect(vm.store.getPaginationInfo).toHaveBeenCalled();
- expect(pageInfo).not.toBeDefined();
- });
- });
- });
-
- describe('methods', () => {
- beforeEach(() => {
- vm.$mount();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('fetchGroups', () => {
- it('should call `getGroups` with all the params provided', done => {
- spyOn(vm.service, 'getGroups').and.returnValue(returnServicePromise(mockGroups));
-
- vm.fetchGroups({
- parentId: 1,
- page: 2,
- filterGroupsBy: 'git',
- sortBy: 'created_desc',
- archived: true,
- });
- setTimeout(() => {
- expect(vm.service.getGroups).toHaveBeenCalledWith(1, 2, 'git', 'created_desc', true);
- done();
- }, 0);
- });
-
- it('should set headers to store for building pagination info when called with `updatePagination`', done => {
- spyOn(vm.service, 'getGroups').and.returnValue(
- returnServicePromise({ headers: mockRawPageInfo }),
- );
- spyOn(vm, 'updatePagination');
-
- vm.fetchGroups({ updatePagination: true });
- setTimeout(() => {
- expect(vm.service.getGroups).toHaveBeenCalled();
- expect(vm.updatePagination).toHaveBeenCalled();
- done();
- }, 0);
- });
-
- it('should show flash error when request fails', done => {
- spyOn(vm.service, 'getGroups').and.returnValue(returnServicePromise(null, true));
- spyOn($, 'scrollTo');
- spyOn(window, 'Flash');
-
- vm.fetchGroups({});
- setTimeout(() => {
- expect(vm.isLoading).toBe(false);
- expect($.scrollTo).toHaveBeenCalledWith(0);
- expect(window.Flash).toHaveBeenCalledWith('An error occurred. Please try again.');
- done();
- }, 0);
- });
- });
-
- describe('fetchAllGroups', () => {
- it('should fetch default set of groups', done => {
- spyOn(vm, 'fetchGroups').and.returnValue(returnServicePromise(mockGroups));
- spyOn(vm, 'updatePagination').and.callThrough();
- spyOn(vm, 'updateGroups').and.callThrough();
-
- vm.fetchAllGroups();
-
- expect(vm.isLoading).toBe(true);
- expect(vm.fetchGroups).toHaveBeenCalled();
- setTimeout(() => {
- expect(vm.isLoading).toBe(false);
- expect(vm.updateGroups).toHaveBeenCalled();
- done();
- }, 0);
- });
-
- it('should fetch matching set of groups when app is loaded with search query', done => {
- spyOn(vm, 'fetchGroups').and.returnValue(returnServicePromise(mockSearchedGroups));
- spyOn(vm, 'updateGroups').and.callThrough();
-
- vm.fetchAllGroups();
-
- expect(vm.fetchGroups).toHaveBeenCalledWith({
- page: null,
- filterGroupsBy: null,
- sortBy: null,
- updatePagination: true,
- archived: null,
- });
- setTimeout(() => {
- expect(vm.updateGroups).toHaveBeenCalled();
- done();
- }, 0);
- });
- });
-
- describe('fetchPage', () => {
- it('should fetch groups for provided page details and update window state', done => {
- spyOn(vm, 'fetchGroups').and.returnValue(returnServicePromise(mockGroups));
- spyOn(vm, 'updateGroups').and.callThrough();
- const mergeUrlParams = spyOnDependency(appComponent, 'mergeUrlParams').and.callThrough();
- spyOn(window.history, 'replaceState');
- spyOn($, 'scrollTo');
-
- vm.fetchPage(2, null, null, true);
-
- expect(vm.isLoading).toBe(true);
- expect(vm.fetchGroups).toHaveBeenCalledWith({
- page: 2,
- filterGroupsBy: null,
- sortBy: null,
- updatePagination: true,
- archived: true,
- });
- setTimeout(() => {
- expect(vm.isLoading).toBe(false);
- expect($.scrollTo).toHaveBeenCalledWith(0);
- expect(mergeUrlParams).toHaveBeenCalledWith({ page: 2 }, jasmine.any(String));
- expect(window.history.replaceState).toHaveBeenCalledWith(
- {
- page: jasmine.any(String),
- },
- jasmine.any(String),
- jasmine.any(String),
- );
-
- expect(vm.updateGroups).toHaveBeenCalled();
- done();
- }, 0);
- });
- });
-
- describe('toggleChildren', () => {
- let groupItem;
-
- beforeEach(() => {
- groupItem = Object.assign({}, mockParentGroupItem);
- groupItem.isOpen = false;
- groupItem.isChildrenLoading = false;
- });
-
- it('should fetch children of given group and expand it if group is collapsed and children are not loaded', done => {
- spyOn(vm, 'fetchGroups').and.returnValue(returnServicePromise(mockRawChildren));
- spyOn(vm.store, 'setGroupChildren');
-
- vm.toggleChildren(groupItem);
-
- expect(groupItem.isChildrenLoading).toBe(true);
- expect(vm.fetchGroups).toHaveBeenCalledWith({
- parentId: groupItem.id,
- });
- setTimeout(() => {
- expect(vm.store.setGroupChildren).toHaveBeenCalled();
- done();
- }, 0);
- });
-
- it('should skip network request while expanding group if children are already loaded', () => {
- spyOn(vm, 'fetchGroups');
- groupItem.children = mockRawChildren;
-
- vm.toggleChildren(groupItem);
-
- expect(vm.fetchGroups).not.toHaveBeenCalled();
- expect(groupItem.isOpen).toBe(true);
- });
-
- it('should collapse group if it is already expanded', () => {
- spyOn(vm, 'fetchGroups');
- groupItem.isOpen = true;
-
- vm.toggleChildren(groupItem);
-
- expect(vm.fetchGroups).not.toHaveBeenCalled();
- expect(groupItem.isOpen).toBe(false);
- });
-
- it('should set `isChildrenLoading` back to `false` if load request fails', done => {
- spyOn(vm, 'fetchGroups').and.returnValue(returnServicePromise({}, true));
-
- vm.toggleChildren(groupItem);
-
- expect(groupItem.isChildrenLoading).toBe(true);
- setTimeout(() => {
- expect(groupItem.isChildrenLoading).toBe(false);
- done();
- }, 0);
- });
- });
-
- describe('showLeaveGroupModal', () => {
- it('caches candidate group (as props) which is to be left', () => {
- const group = Object.assign({}, mockParentGroupItem);
-
- expect(vm.targetGroup).toBe(null);
- expect(vm.targetParentGroup).toBe(null);
- vm.showLeaveGroupModal(group, mockParentGroupItem);
-
- expect(vm.targetGroup).not.toBe(null);
- expect(vm.targetParentGroup).not.toBe(null);
- });
-
- it('updates props which show modal confirmation dialog', () => {
- const group = Object.assign({}, mockParentGroupItem);
-
- expect(vm.showModal).toBe(false);
- expect(vm.groupLeaveConfirmationMessage).toBe('');
- vm.showLeaveGroupModal(group, mockParentGroupItem);
-
- expect(vm.showModal).toBe(true);
- expect(vm.groupLeaveConfirmationMessage).toBe(
- `Are you sure you want to leave the "${group.fullName}" group?`,
- );
- });
- });
-
- describe('hideLeaveGroupModal', () => {
- it('hides modal confirmation which is shown before leaving the group', () => {
- const group = Object.assign({}, mockParentGroupItem);
- vm.showLeaveGroupModal(group, mockParentGroupItem);
-
- expect(vm.showModal).toBe(true);
- vm.hideLeaveGroupModal();
-
- expect(vm.showModal).toBe(false);
- });
- });
-
- describe('leaveGroup', () => {
- let groupItem;
- let childGroupItem;
-
- beforeEach(() => {
- groupItem = Object.assign({}, mockParentGroupItem);
- groupItem.children = mockChildren;
- [childGroupItem] = groupItem.children;
- groupItem.isChildrenLoading = false;
- vm.targetGroup = childGroupItem;
- vm.targetParentGroup = groupItem;
- });
-
- it('hides modal confirmation leave group and remove group item from tree', done => {
- const notice = `You left the "${childGroupItem.fullName}" group.`;
- spyOn(vm.service, 'leaveGroup').and.returnValue(Promise.resolve({ data: { notice } }));
- spyOn(vm.store, 'removeGroup').and.callThrough();
- spyOn(window, 'Flash');
- spyOn($, 'scrollTo');
-
- vm.leaveGroup();
-
- expect(vm.showModal).toBe(false);
- expect(vm.targetGroup.isBeingRemoved).toBe(true);
- expect(vm.service.leaveGroup).toHaveBeenCalledWith(vm.targetGroup.leavePath);
- setTimeout(() => {
- expect($.scrollTo).toHaveBeenCalledWith(0);
- expect(vm.store.removeGroup).toHaveBeenCalledWith(vm.targetGroup, vm.targetParentGroup);
- expect(window.Flash).toHaveBeenCalledWith(notice, 'notice');
- done();
- }, 0);
- });
-
- it('should show error flash message if request failed to leave group', done => {
- const message = 'An error occurred. Please try again.';
- spyOn(vm.service, 'leaveGroup').and.returnValue(
- returnServicePromise({ status: 500 }, true),
- );
- spyOn(vm.store, 'removeGroup').and.callThrough();
- spyOn(window, 'Flash');
-
- vm.leaveGroup();
-
- expect(vm.targetGroup.isBeingRemoved).toBe(true);
- expect(vm.service.leaveGroup).toHaveBeenCalledWith(childGroupItem.leavePath);
- setTimeout(() => {
- expect(vm.store.removeGroup).not.toHaveBeenCalled();
- expect(window.Flash).toHaveBeenCalledWith(message);
- expect(vm.targetGroup.isBeingRemoved).toBe(false);
- done();
- }, 0);
- });
-
- it('should show appropriate error flash message if request forbids to leave group', done => {
- const message = 'Failed to leave the group. Please make sure you are not the only owner.';
- spyOn(vm.service, 'leaveGroup').and.returnValue(
- returnServicePromise({ status: 403 }, true),
- );
- spyOn(vm.store, 'removeGroup').and.callThrough();
- spyOn(window, 'Flash');
-
- vm.leaveGroup(childGroupItem, groupItem);
-
- expect(vm.targetGroup.isBeingRemoved).toBe(true);
- expect(vm.service.leaveGroup).toHaveBeenCalledWith(childGroupItem.leavePath);
- setTimeout(() => {
- expect(vm.store.removeGroup).not.toHaveBeenCalled();
- expect(window.Flash).toHaveBeenCalledWith(message);
- expect(vm.targetGroup.isBeingRemoved).toBe(false);
- done();
- }, 0);
- });
- });
-
- describe('updatePagination', () => {
- it('should set pagination info to store from provided headers', () => {
- spyOn(vm.store, 'setPaginationInfo');
-
- vm.updatePagination(mockRawPageInfo);
-
- expect(vm.store.setPaginationInfo).toHaveBeenCalledWith(mockRawPageInfo);
- });
- });
-
- describe('updateGroups', () => {
- it('should call setGroups on store if method was called directly', () => {
- spyOn(vm.store, 'setGroups');
-
- vm.updateGroups(mockGroups);
-
- expect(vm.store.setGroups).toHaveBeenCalledWith(mockGroups);
- });
-
- it('should call setSearchedGroups on store if method was called with fromSearch param', () => {
- spyOn(vm.store, 'setSearchedGroups');
-
- vm.updateGroups(mockGroups, true);
-
- expect(vm.store.setSearchedGroups).toHaveBeenCalledWith(mockGroups);
- });
-
- it('should set `isSearchEmpty` prop based on groups count', () => {
- vm.updateGroups(mockGroups);
-
- expect(vm.isSearchEmpty).toBe(false);
-
- vm.updateGroups([]);
-
- expect(vm.isSearchEmpty).toBe(true);
- });
- });
- });
-
- describe('created', () => {
- it('should bind event listeners on eventHub', done => {
- spyOn(eventHub, '$on');
-
- const newVm = createComponent();
- newVm.$mount();
-
- Vue.nextTick(() => {
- expect(eventHub.$on).toHaveBeenCalledWith('fetchPage', jasmine.any(Function));
- expect(eventHub.$on).toHaveBeenCalledWith('toggleChildren', jasmine.any(Function));
- expect(eventHub.$on).toHaveBeenCalledWith('showLeaveGroupModal', jasmine.any(Function));
- expect(eventHub.$on).toHaveBeenCalledWith('updatePagination', jasmine.any(Function));
- expect(eventHub.$on).toHaveBeenCalledWith('updateGroups', jasmine.any(Function));
- newVm.$destroy();
- done();
- });
- });
-
- it('should initialize `searchEmptyMessage` prop with correct string when `hideProjects` is `false`', done => {
- const newVm = createComponent();
- newVm.$mount();
- Vue.nextTick(() => {
- expect(newVm.searchEmptyMessage).toBe('No groups or projects matched your search');
- newVm.$destroy();
- done();
- });
- });
-
- it('should initialize `searchEmptyMessage` prop with correct string when `hideProjects` is `true`', done => {
- const newVm = createComponent(true);
- newVm.$mount();
- Vue.nextTick(() => {
- expect(newVm.searchEmptyMessage).toBe('No groups matched your search');
- newVm.$destroy();
- done();
- });
- });
- });
-
- describe('beforeDestroy', () => {
- it('should unbind event listeners on eventHub', done => {
- spyOn(eventHub, '$off');
-
- const newVm = createComponent();
- newVm.$mount();
- newVm.$destroy();
-
- Vue.nextTick(() => {
- expect(eventHub.$off).toHaveBeenCalledWith('fetchPage', jasmine.any(Function));
- expect(eventHub.$off).toHaveBeenCalledWith('toggleChildren', jasmine.any(Function));
- expect(eventHub.$off).toHaveBeenCalledWith('showLeaveGroupModal', jasmine.any(Function));
- expect(eventHub.$off).toHaveBeenCalledWith('updatePagination', jasmine.any(Function));
- expect(eventHub.$off).toHaveBeenCalledWith('updateGroups', jasmine.any(Function));
- done();
- });
- });
- });
-
- describe('template', () => {
- beforeEach(() => {
- vm.$mount();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('should render loading icon', done => {
- vm.isLoading = true;
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.loading-animation')).toBeDefined();
- expect(vm.$el.querySelector('span').getAttribute('aria-label')).toBe('Loading groups');
- done();
- });
- });
-
- it('should render groups tree', done => {
- vm.store.state.groups = [mockParentGroupItem];
- vm.isLoading = false;
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.groups-list-tree-container')).toBeDefined();
- done();
- });
- });
-
- it('renders modal confirmation dialog', done => {
- vm.groupLeaveConfirmationMessage = 'Are you sure you want to leave the "foo" group?';
- vm.showModal = true;
- Vue.nextTick(() => {
- const modalDialogEl = vm.$el.querySelector('.modal');
-
- expect(modalDialogEl).not.toBe(null);
- expect(modalDialogEl.querySelector('.modal-title').innerText.trim()).toBe('Are you sure?');
- expect(modalDialogEl.querySelector('.btn.btn-warning').innerText.trim()).toBe('Leave');
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/groups/components/group_folder_spec.js b/spec/javascripts/groups/components/group_folder_spec.js
deleted file mode 100644
index fdfd1b82bd8..00000000000
--- a/spec/javascripts/groups/components/group_folder_spec.js
+++ /dev/null
@@ -1,67 +0,0 @@
-import Vue from 'vue';
-
-import groupFolderComponent from '~/groups/components/group_folder.vue';
-import groupItemComponent from '~/groups/components/group_item.vue';
-import { mockGroups, mockParentGroupItem } from '../mock_data';
-
-const createComponent = (groups = mockGroups, parentGroup = mockParentGroupItem) => {
- const Component = Vue.extend(groupFolderComponent);
-
- return new Component({
- propsData: {
- groups,
- parentGroup,
- },
- });
-};
-
-describe('GroupFolderComponent', () => {
- let vm;
-
- beforeEach(done => {
- Vue.component('group-item', groupItemComponent);
-
- vm = createComponent();
- vm.$mount();
-
- Vue.nextTick(() => {
- done();
- });
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('computed', () => {
- describe('hasMoreChildren', () => {
- it('should return false when childrenCount of group is less than MAX_CHILDREN_COUNT', () => {
- expect(vm.hasMoreChildren).toBeFalsy();
- });
- });
-
- describe('moreChildrenStats', () => {
- it('should return message with count of excess children over MAX_CHILDREN_COUNT limit', () => {
- expect(vm.moreChildrenStats).toBe('3 more items');
- });
- });
- });
-
- describe('template', () => {
- it('should render component template correctly', () => {
- expect(vm.$el.classList.contains('group-list-tree')).toBeTruthy();
- expect(vm.$el.querySelectorAll('li.group-row').length).toBe(7);
- });
-
- it('should render more children link when groups list has children over MAX_CHILDREN_COUNT limit', () => {
- const parentGroup = Object.assign({}, mockParentGroupItem);
- parentGroup.childrenCount = 21;
-
- const newVm = createComponent(mockGroups, parentGroup);
- newVm.$mount();
-
- expect(newVm.$el.querySelector('li.group-row a.has-more-items')).toBeDefined();
- newVm.$destroy();
- });
- });
-});
diff --git a/spec/javascripts/groups/components/group_item_spec.js b/spec/javascripts/groups/components/group_item_spec.js
deleted file mode 100644
index 2889d7ae4ff..00000000000
--- a/spec/javascripts/groups/components/group_item_spec.js
+++ /dev/null
@@ -1,218 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import groupItemComponent from '~/groups/components/group_item.vue';
-import groupFolderComponent from '~/groups/components/group_folder.vue';
-import eventHub from '~/groups/event_hub';
-import { mockParentGroupItem, mockChildren } from '../mock_data';
-
-const createComponent = (group = mockParentGroupItem, parentGroup = mockChildren[0]) => {
- const Component = Vue.extend(groupItemComponent);
-
- return mountComponent(Component, {
- group,
- parentGroup,
- });
-};
-
-describe('GroupItemComponent', () => {
- let vm;
-
- beforeEach(done => {
- Vue.component('group-folder', groupFolderComponent);
-
- vm = createComponent();
-
- Vue.nextTick(() => {
- done();
- });
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('computed', () => {
- describe('groupDomId', () => {
- it('should return ID string suffixed with group ID', () => {
- expect(vm.groupDomId).toBe('group-55');
- });
- });
-
- describe('rowClass', () => {
- it('should return map of classes based on group details', () => {
- const classes = ['is-open', 'has-children', 'has-description', 'being-removed'];
- const { rowClass } = vm;
-
- expect(Object.keys(rowClass).length).toBe(classes.length);
- Object.keys(rowClass).forEach(className => {
- expect(classes.indexOf(className)).toBeGreaterThan(-1);
- });
- });
- });
-
- describe('hasChildren', () => {
- it('should return boolean value representing if group has any children present', () => {
- let newVm;
- const group = Object.assign({}, mockParentGroupItem);
-
- group.childrenCount = 5;
- newVm = createComponent(group);
-
- expect(newVm.hasChildren).toBeTruthy();
- newVm.$destroy();
-
- group.childrenCount = 0;
- newVm = createComponent(group);
-
- expect(newVm.hasChildren).toBeFalsy();
- newVm.$destroy();
- });
- });
-
- describe('hasAvatar', () => {
- it('should return boolean value representing if group has any avatar present', () => {
- let newVm;
- const group = Object.assign({}, mockParentGroupItem);
-
- group.avatarUrl = null;
- newVm = createComponent(group);
-
- expect(newVm.hasAvatar).toBeFalsy();
- newVm.$destroy();
-
- group.avatarUrl = '/uploads/group_avatar.png';
- newVm = createComponent(group);
-
- expect(newVm.hasAvatar).toBeTruthy();
- newVm.$destroy();
- });
- });
-
- describe('isGroup', () => {
- it('should return boolean value representing if group item is of type `group` or not', () => {
- let newVm;
- const group = Object.assign({}, mockParentGroupItem);
-
- group.type = 'group';
- newVm = createComponent(group);
-
- expect(newVm.isGroup).toBeTruthy();
- newVm.$destroy();
-
- group.type = 'project';
- newVm = createComponent(group);
-
- expect(newVm.isGroup).toBeFalsy();
- newVm.$destroy();
- });
- });
- });
-
- describe('methods', () => {
- describe('onClickRowGroup', () => {
- let event;
-
- beforeEach(() => {
- const classList = {
- contains() {
- return false;
- },
- };
-
- event = {
- target: {
- classList,
- parentElement: {
- classList,
- },
- },
- };
- });
-
- it('should emit `toggleChildren` event when expand is clicked on a group and it has children present', () => {
- spyOn(eventHub, '$emit');
-
- vm.onClickRowGroup(event);
-
- expect(eventHub.$emit).toHaveBeenCalledWith('toggleChildren', vm.group);
- });
-
- it('should navigate page to group homepage if group does not have any children present', done => {
- const group = Object.assign({}, mockParentGroupItem);
- group.childrenCount = 0;
- const newVm = createComponent(group);
- const visitUrl = spyOnDependency(groupItemComponent, 'visitUrl').and.stub();
- spyOn(eventHub, '$emit');
-
- newVm.onClickRowGroup(event);
- setTimeout(() => {
- expect(eventHub.$emit).not.toHaveBeenCalled();
- expect(visitUrl).toHaveBeenCalledWith(newVm.group.relativePath);
- done();
- }, 0);
- });
- });
- });
-
- describe('template', () => {
- let group = null;
-
- describe('for a group pending deletion', () => {
- beforeEach(() => {
- group = { ...mockParentGroupItem, pendingRemoval: true };
- vm = createComponent(group);
- });
-
- it('renders the group pending removal badge', () => {
- const badgeEl = vm.$el.querySelector('.badge-warning');
-
- expect(badgeEl).toBeDefined();
- expect(badgeEl).toContainText('pending removal');
- });
- });
-
- describe('for a group not scheduled for deletion', () => {
- beforeEach(() => {
- group = { ...mockParentGroupItem, pendingRemoval: false };
- vm = createComponent(group);
- });
-
- it('does not render the group pending removal badge', () => {
- const groupTextContainer = vm.$el.querySelector('.group-text-container');
-
- expect(groupTextContainer).not.toContainText('pending removal');
- });
- });
-
- it('should render component template correctly', () => {
- const visibilityIconEl = vm.$el.querySelector('.item-visibility');
-
- expect(vm.$el.getAttribute('id')).toBe('group-55');
- expect(vm.$el.classList.contains('group-row')).toBeTruthy();
-
- expect(vm.$el.querySelector('.group-row-contents')).toBeDefined();
- expect(vm.$el.querySelector('.group-row-contents .controls')).toBeDefined();
- expect(vm.$el.querySelector('.group-row-contents .stats')).toBeDefined();
-
- expect(vm.$el.querySelector('.folder-toggle-wrap')).toBeDefined();
- expect(vm.$el.querySelector('.folder-toggle-wrap .folder-caret')).toBeDefined();
- expect(vm.$el.querySelector('.folder-toggle-wrap .item-type-icon')).toBeDefined();
-
- expect(vm.$el.querySelector('.avatar-container')).toBeDefined();
- expect(vm.$el.querySelector('.avatar-container a.no-expand')).toBeDefined();
- expect(vm.$el.querySelector('.avatar-container .avatar')).toBeDefined();
-
- expect(vm.$el.querySelector('.title')).toBeDefined();
- expect(vm.$el.querySelector('.title a.no-expand')).toBeDefined();
-
- expect(visibilityIconEl).not.toBe(null);
- expect(visibilityIconEl.dataset.originalTitle).toBe(vm.visibilityTooltip);
- expect(visibilityIconEl.querySelectorAll('svg').length).toBeGreaterThan(0);
-
- expect(vm.$el.querySelector('.access-type')).toBeDefined();
- expect(vm.$el.querySelector('.description')).toBeDefined();
-
- expect(vm.$el.querySelector('.group-list-tree')).toBeDefined();
- });
- });
-});
diff --git a/spec/javascripts/groups/components/groups_spec.js b/spec/javascripts/groups/components/groups_spec.js
deleted file mode 100644
index 8423467742e..00000000000
--- a/spec/javascripts/groups/components/groups_spec.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import Vue from 'vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import groupsComponent from '~/groups/components/groups.vue';
-import groupFolderComponent from '~/groups/components/group_folder.vue';
-import groupItemComponent from '~/groups/components/group_item.vue';
-import eventHub from '~/groups/event_hub';
-import { mockGroups, mockPageInfo } from '../mock_data';
-
-const createComponent = (searchEmpty = false) => {
- const Component = Vue.extend(groupsComponent);
-
- return mountComponent(Component, {
- groups: mockGroups,
- pageInfo: mockPageInfo,
- searchEmptyMessage: 'No matching results',
- searchEmpty,
- });
-};
-
-describe('GroupsComponent', () => {
- let vm;
-
- beforeEach(done => {
- Vue.component('group-folder', groupFolderComponent);
- Vue.component('group-item', groupItemComponent);
-
- vm = createComponent();
-
- Vue.nextTick(() => {
- done();
- });
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('methods', () => {
- describe('change', () => {
- it('should emit `fetchPage` event when page is changed via pagination', () => {
- spyOn(eventHub, '$emit').and.stub();
-
- vm.change(2);
-
- expect(eventHub.$emit).toHaveBeenCalledWith(
- 'fetchPage',
- 2,
- jasmine.any(Object),
- jasmine.any(Object),
- jasmine.any(Object),
- );
- });
- });
- });
-
- describe('template', () => {
- it('should render component template correctly', done => {
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.groups-list-tree-container')).toBeDefined();
- expect(vm.$el.querySelector('.group-list-tree')).toBeDefined();
- expect(vm.$el.querySelector('.gl-pagination')).toBeDefined();
- expect(vm.$el.querySelectorAll('.has-no-search-results').length).toBe(0);
- done();
- });
- });
-
- it('should render empty search message when `searchEmpty` is `true`', done => {
- vm.searchEmpty = true;
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.has-no-search-results')).toBeDefined();
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/groups/components/item_actions_spec.js b/spec/javascripts/groups/components/item_actions_spec.js
deleted file mode 100644
index 9a9d6208eac..00000000000
--- a/spec/javascripts/groups/components/item_actions_spec.js
+++ /dev/null
@@ -1,84 +0,0 @@
-import Vue from 'vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import itemActionsComponent from '~/groups/components/item_actions.vue';
-import eventHub from '~/groups/event_hub';
-import { mockParentGroupItem, mockChildren } from '../mock_data';
-
-const createComponent = (group = mockParentGroupItem, parentGroup = mockChildren[0]) => {
- const Component = Vue.extend(itemActionsComponent);
-
- return mountComponent(Component, {
- group,
- parentGroup,
- });
-};
-
-describe('ItemActionsComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('methods', () => {
- describe('onLeaveGroup', () => {
- it('emits `showLeaveGroupModal` event with `group` and `parentGroup` props', () => {
- spyOn(eventHub, '$emit');
- vm.onLeaveGroup();
-
- expect(eventHub.$emit).toHaveBeenCalledWith(
- 'showLeaveGroupModal',
- vm.group,
- vm.parentGroup,
- );
- });
- });
- });
-
- describe('template', () => {
- it('should render component template correctly', () => {
- expect(vm.$el.classList.contains('controls')).toBeTruthy();
- });
-
- it('should render Edit Group button with correct attribute values', () => {
- const group = Object.assign({}, mockParentGroupItem);
- group.canEdit = true;
- const newVm = createComponent(group);
-
- const editBtn = newVm.$el.querySelector('a.edit-group');
-
- expect(editBtn).toBeDefined();
- expect(editBtn.classList.contains('no-expand')).toBeTruthy();
- expect(editBtn.getAttribute('href')).toBe(group.editPath);
- expect(editBtn.getAttribute('aria-label')).toBe('Edit group');
- expect(editBtn.dataset.originalTitle).toBe('Edit group');
- expect(editBtn.querySelectorAll('svg use').length).not.toBe(0);
- expect(editBtn.querySelector('svg use').getAttribute('xlink:href')).toContain('#settings');
-
- newVm.$destroy();
- });
-
- it('should render Leave Group button with correct attribute values', () => {
- const group = Object.assign({}, mockParentGroupItem);
- group.canLeave = true;
- const newVm = createComponent(group);
-
- const leaveBtn = newVm.$el.querySelector('a.leave-group');
-
- expect(leaveBtn).toBeDefined();
- expect(leaveBtn.classList.contains('no-expand')).toBeTruthy();
- expect(leaveBtn.getAttribute('href')).toBe(group.leavePath);
- expect(leaveBtn.getAttribute('aria-label')).toBe('Leave this group');
- expect(leaveBtn.dataset.originalTitle).toBe('Leave this group');
- expect(leaveBtn.querySelectorAll('svg use').length).not.toBe(0);
- expect(leaveBtn.querySelector('svg use').getAttribute('xlink:href')).toContain('#leave');
-
- newVm.$destroy();
- });
- });
-});
diff --git a/spec/javascripts/groups/components/item_caret_spec.js b/spec/javascripts/groups/components/item_caret_spec.js
deleted file mode 100644
index 0eb56abbd61..00000000000
--- a/spec/javascripts/groups/components/item_caret_spec.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import Vue from 'vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import itemCaretComponent from '~/groups/components/item_caret.vue';
-
-const createComponent = (isGroupOpen = false) => {
- const Component = Vue.extend(itemCaretComponent);
-
- return mountComponent(Component, {
- isGroupOpen,
- });
-};
-
-describe('ItemCaretComponent', () => {
- describe('template', () => {
- it('should render component template correctly', () => {
- const vm = createComponent();
-
- expect(vm.$el.classList.contains('folder-caret')).toBeTruthy();
- expect(vm.$el.querySelectorAll('svg').length).toBe(1);
- vm.$destroy();
- });
-
- it('should render caret down icon if `isGroupOpen` prop is `true`', () => {
- const vm = createComponent(true);
-
- expect(vm.$el.querySelector('svg use').getAttribute('xlink:href')).toContain('angle-down');
- vm.$destroy();
- });
-
- it('should render caret right icon if `isGroupOpen` prop is `false`', () => {
- const vm = createComponent();
-
- expect(vm.$el.querySelector('svg use').getAttribute('xlink:href')).toContain('angle-right');
- vm.$destroy();
- });
- });
-});
diff --git a/spec/javascripts/groups/components/item_stats_spec.js b/spec/javascripts/groups/components/item_stats_spec.js
deleted file mode 100644
index 13d17b87d76..00000000000
--- a/spec/javascripts/groups/components/item_stats_spec.js
+++ /dev/null
@@ -1,128 +0,0 @@
-import Vue from 'vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import itemStatsComponent from '~/groups/components/item_stats.vue';
-import {
- mockParentGroupItem,
- ITEM_TYPE,
- VISIBILITY_TYPE_ICON,
- GROUP_VISIBILITY_TYPE,
- PROJECT_VISIBILITY_TYPE,
-} from '../mock_data';
-
-const createComponent = (item = mockParentGroupItem) => {
- const Component = Vue.extend(itemStatsComponent);
-
- return mountComponent(Component, {
- item,
- });
-};
-
-describe('ItemStatsComponent', () => {
- describe('computed', () => {
- describe('visibilityIcon', () => {
- it('should return icon class based on `item.visibility` value', () => {
- Object.keys(VISIBILITY_TYPE_ICON).forEach(visibility => {
- const item = Object.assign({}, mockParentGroupItem, { visibility });
- const vm = createComponent(item);
-
- expect(vm.visibilityIcon).toBe(VISIBILITY_TYPE_ICON[visibility]);
- vm.$destroy();
- });
- });
- });
-
- describe('visibilityTooltip', () => {
- it('should return tooltip string for Group based on `item.visibility` value', () => {
- Object.keys(GROUP_VISIBILITY_TYPE).forEach(visibility => {
- const item = Object.assign({}, mockParentGroupItem, {
- visibility,
- type: ITEM_TYPE.GROUP,
- });
- const vm = createComponent(item);
-
- expect(vm.visibilityTooltip).toBe(GROUP_VISIBILITY_TYPE[visibility]);
- vm.$destroy();
- });
- });
-
- it('should return tooltip string for Project based on `item.visibility` value', () => {
- Object.keys(PROJECT_VISIBILITY_TYPE).forEach(visibility => {
- const item = Object.assign({}, mockParentGroupItem, {
- visibility,
- type: ITEM_TYPE.PROJECT,
- });
- const vm = createComponent(item);
-
- expect(vm.visibilityTooltip).toBe(PROJECT_VISIBILITY_TYPE[visibility]);
- vm.$destroy();
- });
- });
- });
-
- describe('isProject', () => {
- it('should return boolean value representing whether `item.type` is Project or not', () => {
- let item;
- let vm;
-
- item = Object.assign({}, mockParentGroupItem, { type: ITEM_TYPE.PROJECT });
- vm = createComponent(item);
-
- expect(vm.isProject).toBeTruthy();
- vm.$destroy();
-
- item = Object.assign({}, mockParentGroupItem, { type: ITEM_TYPE.GROUP });
- vm = createComponent(item);
-
- expect(vm.isProject).toBeFalsy();
- vm.$destroy();
- });
- });
-
- describe('isGroup', () => {
- it('should return boolean value representing whether `item.type` is Group or not', () => {
- let item;
- let vm;
-
- item = Object.assign({}, mockParentGroupItem, { type: ITEM_TYPE.GROUP });
- vm = createComponent(item);
-
- expect(vm.isGroup).toBeTruthy();
- vm.$destroy();
-
- item = Object.assign({}, mockParentGroupItem, { type: ITEM_TYPE.PROJECT });
- vm = createComponent(item);
-
- expect(vm.isGroup).toBeFalsy();
- vm.$destroy();
- });
- });
- });
-
- describe('template', () => {
- it('renders component container element correctly', () => {
- const vm = createComponent();
-
- expect(vm.$el.classList.contains('stats')).toBeTruthy();
-
- vm.$destroy();
- });
-
- it('renders start count and last updated information for project item correctly', () => {
- const item = Object.assign({}, mockParentGroupItem, {
- type: ITEM_TYPE.PROJECT,
- starCount: 4,
- });
- const vm = createComponent(item);
-
- const projectStarIconEl = vm.$el.querySelector('.project-stars');
-
- expect(projectStarIconEl).not.toBeNull();
- expect(projectStarIconEl.querySelectorAll('svg').length).toBeGreaterThan(0);
- expect(projectStarIconEl.querySelectorAll('.stat-value').length).toBeGreaterThan(0);
- expect(vm.$el.querySelectorAll('.last-updated').length).toBeGreaterThan(0);
-
- vm.$destroy();
- });
- });
-});
diff --git a/spec/javascripts/groups/components/item_stats_value_spec.js b/spec/javascripts/groups/components/item_stats_value_spec.js
deleted file mode 100644
index ff4e781ce1a..00000000000
--- a/spec/javascripts/groups/components/item_stats_value_spec.js
+++ /dev/null
@@ -1,82 +0,0 @@
-import Vue from 'vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import itemStatsValueComponent from '~/groups/components/item_stats_value.vue';
-
-const createComponent = ({ title, cssClass, iconName, tooltipPlacement, value }) => {
- const Component = Vue.extend(itemStatsValueComponent);
-
- return mountComponent(Component, {
- title,
- cssClass,
- iconName,
- tooltipPlacement,
- value,
- });
-};
-
-describe('ItemStatsValueComponent', () => {
- describe('computed', () => {
- let vm;
- const itemConfig = {
- title: 'Subgroups',
- cssClass: 'number-subgroups',
- iconName: 'folder',
- tooltipPlacement: 'left',
- };
-
- describe('isValuePresent', () => {
- it('returns true if non-empty `value` is present', () => {
- vm = createComponent(Object.assign({}, itemConfig, { value: 10 }));
-
- expect(vm.isValuePresent).toBeTruthy();
- });
-
- it('returns false if empty `value` is present', () => {
- vm = createComponent(itemConfig);
-
- expect(vm.isValuePresent).toBeFalsy();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
- });
- });
-
- describe('template', () => {
- let vm;
- beforeEach(() => {
- vm = createComponent({
- title: 'Subgroups',
- cssClass: 'number-subgroups',
- iconName: 'folder',
- tooltipPlacement: 'left',
- value: 10,
- });
- });
-
- it('renders component element correctly', () => {
- expect(vm.$el.classList.contains('number-subgroups')).toBeTruthy();
- expect(vm.$el.querySelectorAll('svg').length).toBeGreaterThan(0);
- expect(vm.$el.querySelectorAll('.stat-value').length).toBeGreaterThan(0);
- });
-
- it('renders element tooltip correctly', () => {
- expect(vm.$el.dataset.originalTitle).toBe('Subgroups');
- expect(vm.$el.dataset.placement).toBe('left');
- });
-
- it('renders element icon correctly', () => {
- expect(vm.$el.querySelector('svg use').getAttribute('xlink:href')).toContain('folder');
- });
-
- it('renders value count correctly', () => {
- expect(vm.$el.querySelector('.stat-value').innerText.trim()).toContain('10');
- });
-
- afterEach(() => {
- vm.$destroy();
- });
- });
-});
diff --git a/spec/javascripts/groups/components/item_type_icon_spec.js b/spec/javascripts/groups/components/item_type_icon_spec.js
deleted file mode 100644
index 321712e54a6..00000000000
--- a/spec/javascripts/groups/components/item_type_icon_spec.js
+++ /dev/null
@@ -1,58 +0,0 @@
-import Vue from 'vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import itemTypeIconComponent from '~/groups/components/item_type_icon.vue';
-import { ITEM_TYPE } from '../mock_data';
-
-const createComponent = (itemType = ITEM_TYPE.GROUP, isGroupOpen = false) => {
- const Component = Vue.extend(itemTypeIconComponent);
-
- return mountComponent(Component, {
- itemType,
- isGroupOpen,
- });
-};
-
-describe('ItemTypeIconComponent', () => {
- describe('template', () => {
- it('should render component template correctly', () => {
- const vm = createComponent();
- vm.$mount();
-
- expect(vm.$el.classList.contains('item-type-icon')).toBeTruthy();
- vm.$destroy();
- });
-
- it('should render folder open or close icon based `isGroupOpen` prop value', () => {
- let vm;
-
- vm = createComponent(ITEM_TYPE.GROUP, true);
- vm.$mount();
-
- expect(vm.$el.querySelector('use').getAttribute('xlink:href')).toContain('folder-open');
- vm.$destroy();
-
- vm = createComponent(ITEM_TYPE.GROUP);
- vm.$mount();
-
- expect(vm.$el.querySelector('use').getAttribute('xlink:href')).toContain('folder');
- vm.$destroy();
- });
-
- it('should render bookmark icon based on `isProject` prop value', () => {
- let vm;
-
- vm = createComponent(ITEM_TYPE.PROJECT);
- vm.$mount();
-
- expect(vm.$el.querySelector('use').getAttribute('xlink:href')).toContain('bookmark');
- vm.$destroy();
-
- vm = createComponent(ITEM_TYPE.GROUP);
- vm.$mount();
-
- expect(vm.$el.querySelector('use').getAttribute('xlink:href')).not.toContain('bookmark');
- vm.$destroy();
- });
- });
-});
diff --git a/spec/javascripts/groups/mock_data.js b/spec/javascripts/groups/mock_data.js
deleted file mode 100644
index 380dda9f7b1..00000000000
--- a/spec/javascripts/groups/mock_data.js
+++ /dev/null
@@ -1,398 +0,0 @@
-export const mockEndpoint = '/dashboard/groups.json';
-
-export const ITEM_TYPE = {
- PROJECT: 'project',
- GROUP: 'group',
-};
-
-export const GROUP_VISIBILITY_TYPE = {
- public: 'Public - The group and any public projects can be viewed without any authentication.',
- internal: 'Internal - The group and any internal projects can be viewed by any logged in user.',
- private: 'Private - The group and its projects can only be viewed by members.',
-};
-
-export const PROJECT_VISIBILITY_TYPE = {
- public: 'Public - The project can be accessed without any authentication.',
- internal: 'Internal - The project can be accessed by any logged in user.',
- private:
- 'Private - Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group.',
-};
-
-export const VISIBILITY_TYPE_ICON = {
- public: 'earth',
- internal: 'shield',
- private: 'lock',
-};
-
-export const mockParentGroupItem = {
- id: 55,
- name: 'hardware',
- description: '',
- visibility: 'public',
- fullName: 'platform / hardware',
- relativePath: '/platform/hardware',
- canEdit: true,
- type: 'group',
- avatarUrl: null,
- permission: 'Owner',
- editPath: '/groups/platform/hardware/edit',
- childrenCount: 3,
- leavePath: '/groups/platform/hardware/group_members/leave',
- parentId: 54,
- memberCount: '1',
- projectCount: 1,
- subgroupCount: 2,
- canLeave: false,
- children: [],
- isOpen: true,
- isChildrenLoading: false,
- isBeingRemoved: false,
- updatedAt: '2017-04-09T18:40:39.101Z',
-};
-
-export const mockRawChildren = [
- {
- id: 57,
- name: 'bsp',
- description: '',
- visibility: 'public',
- full_name: 'platform / hardware / bsp',
- relative_path: '/platform/hardware/bsp',
- can_edit: true,
- type: 'group',
- avatar_url: null,
- permission: 'Owner',
- edit_path: '/groups/platform/hardware/bsp/edit',
- children_count: 6,
- leave_path: '/groups/platform/hardware/bsp/group_members/leave',
- parent_id: 55,
- number_users_with_delimiter: '1',
- project_count: 4,
- subgroup_count: 2,
- can_leave: false,
- children: [],
- updated_at: '2017-04-09T18:40:39.101Z',
- },
-];
-
-export const mockChildren = [
- {
- id: 57,
- name: 'bsp',
- description: '',
- visibility: 'public',
- fullName: 'platform / hardware / bsp',
- relativePath: '/platform/hardware/bsp',
- canEdit: true,
- type: 'group',
- avatarUrl: null,
- permission: 'Owner',
- editPath: '/groups/platform/hardware/bsp/edit',
- childrenCount: 6,
- leavePath: '/groups/platform/hardware/bsp/group_members/leave',
- parentId: 55,
- memberCount: '1',
- projectCount: 4,
- subgroupCount: 2,
- canLeave: false,
- children: [],
- isOpen: true,
- isChildrenLoading: false,
- isBeingRemoved: false,
- updatedAt: '2017-04-09T18:40:39.101Z',
- },
-];
-
-export const mockGroups = [
- {
- id: 75,
- name: 'test-group',
- description: '',
- visibility: 'public',
- full_name: 'test-group',
- relative_path: '/test-group',
- can_edit: true,
- type: 'group',
- avatar_url: null,
- permission: 'Owner',
- edit_path: '/groups/test-group/edit',
- children_count: 2,
- leave_path: '/groups/test-group/group_members/leave',
- parent_id: null,
- number_users_with_delimiter: '1',
- project_count: 2,
- subgroup_count: 0,
- can_leave: false,
- updated_at: '2017-04-09T18:40:39.101Z',
- },
- {
- id: 67,
- name: 'open-source',
- description: '',
- visibility: 'private',
- full_name: 'open-source',
- relative_path: '/open-source',
- can_edit: true,
- type: 'group',
- avatar_url: null,
- permission: 'Owner',
- edit_path: '/groups/open-source/edit',
- children_count: 0,
- leave_path: '/groups/open-source/group_members/leave',
- parent_id: null,
- number_users_with_delimiter: '1',
- project_count: 0,
- subgroup_count: 0,
- can_leave: false,
- updated_at: '2017-04-09T18:40:39.101Z',
- },
- {
- id: 54,
- name: 'platform',
- description: '',
- visibility: 'public',
- full_name: 'platform',
- relative_path: '/platform',
- can_edit: true,
- type: 'group',
- avatar_url: null,
- permission: 'Owner',
- edit_path: '/groups/platform/edit',
- children_count: 1,
- leave_path: '/groups/platform/group_members/leave',
- parent_id: null,
- number_users_with_delimiter: '1',
- project_count: 0,
- subgroup_count: 1,
- can_leave: false,
- updated_at: '2017-04-09T18:40:39.101Z',
- },
- {
- id: 5,
- name: 'H5bp',
- description: 'Minus dolor consequuntur qui nam recusandae quam incidunt.',
- visibility: 'public',
- full_name: 'H5bp',
- relative_path: '/h5bp',
- can_edit: true,
- type: 'group',
- avatar_url: null,
- permission: 'Owner',
- edit_path: '/groups/h5bp/edit',
- children_count: 1,
- leave_path: '/groups/h5bp/group_members/leave',
- parent_id: null,
- number_users_with_delimiter: '5',
- project_count: 1,
- subgroup_count: 0,
- can_leave: false,
- updated_at: '2017-04-09T18:40:39.101Z',
- },
- {
- id: 4,
- name: 'Twitter',
- description: 'Deserunt hic nostrum placeat veniam.',
- visibility: 'public',
- full_name: 'Twitter',
- relative_path: '/twitter',
- can_edit: true,
- type: 'group',
- avatar_url: null,
- permission: 'Owner',
- edit_path: '/groups/twitter/edit',
- children_count: 2,
- leave_path: '/groups/twitter/group_members/leave',
- parent_id: null,
- number_users_with_delimiter: '5',
- project_count: 2,
- subgroup_count: 0,
- can_leave: false,
- updated_at: '2017-04-09T18:40:39.101Z',
- },
- {
- id: 3,
- name: 'Documentcloud',
- description: 'Consequatur saepe totam ea pariatur maxime.',
- visibility: 'public',
- full_name: 'Documentcloud',
- relative_path: '/documentcloud',
- can_edit: true,
- type: 'group',
- avatar_url: null,
- permission: 'Owner',
- edit_path: '/groups/documentcloud/edit',
- children_count: 1,
- leave_path: '/groups/documentcloud/group_members/leave',
- parent_id: null,
- number_users_with_delimiter: '5',
- project_count: 1,
- subgroup_count: 0,
- can_leave: false,
- updated_at: '2017-04-09T18:40:39.101Z',
- },
- {
- id: 2,
- name: 'Gitlab Org',
- description: 'Debitis ea quas aperiam velit doloremque ab.',
- visibility: 'public',
- full_name: 'Gitlab Org',
- relative_path: '/gitlab-org',
- can_edit: true,
- type: 'group',
- avatar_url: '/uploads/-/system/group/avatar/2/GitLab.png',
- permission: 'Owner',
- edit_path: '/groups/gitlab-org/edit',
- children_count: 4,
- leave_path: '/groups/gitlab-org/group_members/leave',
- parent_id: null,
- number_users_with_delimiter: '5',
- project_count: 4,
- subgroup_count: 0,
- can_leave: false,
- updated_at: '2017-04-09T18:40:39.101Z',
- },
-];
-
-export const mockSearchedGroups = [
- {
- id: 55,
- name: 'hardware',
- description: '',
- visibility: 'public',
- full_name: 'platform / hardware',
- relative_path: '/platform/hardware',
- can_edit: true,
- type: 'group',
- avatar_url: null,
- permission: 'Owner',
- edit_path: '/groups/platform/hardware/edit',
- children_count: 3,
- leave_path: '/groups/platform/hardware/group_members/leave',
- parent_id: 54,
- number_users_with_delimiter: '1',
- project_count: 1,
- subgroup_count: 2,
- can_leave: false,
- updated_at: '2017-04-09T18:40:39.101Z',
- children: [
- {
- id: 57,
- name: 'bsp',
- description: '',
- visibility: 'public',
- full_name: 'platform / hardware / bsp',
- relative_path: '/platform/hardware/bsp',
- can_edit: true,
- type: 'group',
- avatar_url: null,
- permission: 'Owner',
- edit_path: '/groups/platform/hardware/bsp/edit',
- children_count: 6,
- leave_path: '/groups/platform/hardware/bsp/group_members/leave',
- parent_id: 55,
- number_users_with_delimiter: '1',
- project_count: 4,
- subgroup_count: 2,
- can_leave: false,
- updated_at: '2017-04-09T18:40:39.101Z',
- children: [
- {
- id: 60,
- name: 'kernel',
- description: '',
- visibility: 'public',
- full_name: 'platform / hardware / bsp / kernel',
- relative_path: '/platform/hardware/bsp/kernel',
- can_edit: true,
- type: 'group',
- avatar_url: null,
- permission: 'Owner',
- edit_path: '/groups/platform/hardware/bsp/kernel/edit',
- children_count: 1,
- leave_path: '/groups/platform/hardware/bsp/kernel/group_members/leave',
- parent_id: 57,
- number_users_with_delimiter: '1',
- project_count: 0,
- subgroup_count: 1,
- can_leave: false,
- updated_at: '2017-04-09T18:40:39.101Z',
- children: [
- {
- id: 61,
- name: 'common',
- description: '',
- visibility: 'public',
- full_name: 'platform / hardware / bsp / kernel / common',
- relative_path: '/platform/hardware/bsp/kernel/common',
- can_edit: true,
- type: 'group',
- avatar_url: null,
- permission: 'Owner',
- edit_path: '/groups/platform/hardware/bsp/kernel/common/edit',
- children_count: 2,
- leave_path: '/groups/platform/hardware/bsp/kernel/common/group_members/leave',
- parent_id: 60,
- number_users_with_delimiter: '1',
- project_count: 2,
- subgroup_count: 0,
- can_leave: false,
- updated_at: '2017-04-09T18:40:39.101Z',
- children: [
- {
- id: 17,
- name: 'v4.4',
- description:
- 'Voluptatem qui ea error aperiam veritatis doloremque consequatur temporibus.',
- visibility: 'public',
- full_name: 'platform / hardware / bsp / kernel / common / v4.4',
- relative_path: '/platform/hardware/bsp/kernel/common/v4.4',
- can_edit: true,
- type: 'project',
- avatar_url: null,
- permission: null,
- edit_path: '/platform/hardware/bsp/kernel/common/v4.4/edit',
- star_count: 0,
- updated_at: '2017-09-12T06:37:04.925Z',
- },
- {
- id: 16,
- name: 'v4.1',
- description: 'Rerum expedita voluptatem doloribus neque ducimus ut hic.',
- visibility: 'public',
- full_name: 'platform / hardware / bsp / kernel / common / v4.1',
- relative_path: '/platform/hardware/bsp/kernel/common/v4.1',
- can_edit: true,
- type: 'project',
- avatar_url: null,
- permission: null,
- edit_path: '/platform/hardware/bsp/kernel/common/v4.1/edit',
- star_count: 0,
- updated_at: '2017-04-09T18:41:03.112Z',
- },
- ],
- },
- ],
- },
- ],
- },
- ],
- },
-];
-
-export const mockRawPageInfo = {
- 'x-per-page': 10,
- 'x-page': 10,
- 'x-total': 10,
- 'x-total-pages': 10,
- 'x-next-page': 10,
- 'x-prev-page': 10,
-};
-
-export const mockPageInfo = {
- perPage: 10,
- page: 10,
- total: 10,
- totalPages: 10,
- nextPage: 10,
- prevPage: 10,
-};
diff --git a/spec/javascripts/groups/service/groups_service_spec.js b/spec/javascripts/groups/service/groups_service_spec.js
deleted file mode 100644
index 45db962a1ef..00000000000
--- a/spec/javascripts/groups/service/groups_service_spec.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import axios from '~/lib/utils/axios_utils';
-
-import GroupsService from '~/groups/service/groups_service';
-import { mockEndpoint, mockParentGroupItem } from '../mock_data';
-
-describe('GroupsService', () => {
- let service;
-
- beforeEach(() => {
- service = new GroupsService(mockEndpoint);
- });
-
- describe('getGroups', () => {
- it('should return promise for `GET` request on provided endpoint', () => {
- spyOn(axios, 'get').and.stub();
- const params = {
- page: 2,
- filter: 'git',
- sort: 'created_asc',
- archived: true,
- };
-
- service.getGroups(55, 2, 'git', 'created_asc', true);
-
- expect(axios.get).toHaveBeenCalledWith(mockEndpoint, { params: { parent_id: 55 } });
-
- service.getGroups(null, 2, 'git', 'created_asc', true);
-
- expect(axios.get).toHaveBeenCalledWith(mockEndpoint, { params });
- });
- });
-
- describe('leaveGroup', () => {
- it('should return promise for `DELETE` request on provided endpoint', () => {
- spyOn(axios, 'delete').and.stub();
-
- service.leaveGroup(mockParentGroupItem.leavePath);
-
- expect(axios.delete).toHaveBeenCalledWith(mockParentGroupItem.leavePath);
- });
- });
-});
diff --git a/spec/javascripts/groups/store/groups_store_spec.js b/spec/javascripts/groups/store/groups_store_spec.js
deleted file mode 100644
index 38de4b89f31..00000000000
--- a/spec/javascripts/groups/store/groups_store_spec.js
+++ /dev/null
@@ -1,123 +0,0 @@
-import GroupsStore from '~/groups/store/groups_store';
-import {
- mockGroups,
- mockSearchedGroups,
- mockParentGroupItem,
- mockRawChildren,
- mockRawPageInfo,
-} from '../mock_data';
-
-describe('ProjectsStore', () => {
- describe('constructor', () => {
- it('should initialize default state', () => {
- let store;
-
- store = new GroupsStore();
-
- expect(Object.keys(store.state).length).toBe(2);
- expect(Array.isArray(store.state.groups)).toBeTruthy();
- expect(Object.keys(store.state.pageInfo).length).toBe(0);
- expect(store.hideProjects).not.toBeDefined();
-
- store = new GroupsStore(true);
-
- expect(store.hideProjects).toBeTruthy();
- });
- });
-
- describe('setGroups', () => {
- it('should set groups to state', () => {
- const store = new GroupsStore();
- spyOn(store, 'formatGroupItem').and.callThrough();
-
- store.setGroups(mockGroups);
-
- expect(store.state.groups.length).toBe(mockGroups.length);
- expect(store.formatGroupItem).toHaveBeenCalledWith(jasmine.any(Object));
- expect(Object.keys(store.state.groups[0]).indexOf('fullName')).toBeGreaterThan(-1);
- });
- });
-
- describe('setSearchedGroups', () => {
- it('should set searched groups to state', () => {
- const store = new GroupsStore();
- spyOn(store, 'formatGroupItem').and.callThrough();
-
- store.setSearchedGroups(mockSearchedGroups);
-
- expect(store.state.groups.length).toBe(mockSearchedGroups.length);
- expect(store.formatGroupItem).toHaveBeenCalledWith(jasmine.any(Object));
- expect(Object.keys(store.state.groups[0]).indexOf('fullName')).toBeGreaterThan(-1);
- expect(Object.keys(store.state.groups[0].children[0]).indexOf('fullName')).toBeGreaterThan(
- -1,
- );
- });
- });
-
- describe('setGroupChildren', () => {
- it('should set children to group item in state', () => {
- const store = new GroupsStore();
- spyOn(store, 'formatGroupItem').and.callThrough();
-
- store.setGroupChildren(mockParentGroupItem, mockRawChildren);
-
- expect(store.formatGroupItem).toHaveBeenCalledWith(jasmine.any(Object));
- expect(mockParentGroupItem.children.length).toBe(1);
- expect(Object.keys(mockParentGroupItem.children[0]).indexOf('fullName')).toBeGreaterThan(-1);
- expect(mockParentGroupItem.isOpen).toBeTruthy();
- expect(mockParentGroupItem.isChildrenLoading).toBeFalsy();
- });
- });
-
- describe('setPaginationInfo', () => {
- it('should parse and set pagination info in state', () => {
- const store = new GroupsStore();
-
- store.setPaginationInfo(mockRawPageInfo);
-
- expect(store.state.pageInfo.perPage).toBe(10);
- expect(store.state.pageInfo.page).toBe(10);
- expect(store.state.pageInfo.total).toBe(10);
- expect(store.state.pageInfo.totalPages).toBe(10);
- expect(store.state.pageInfo.nextPage).toBe(10);
- expect(store.state.pageInfo.previousPage).toBe(10);
- });
- });
-
- describe('formatGroupItem', () => {
- it('should parse group item object and return updated object', () => {
- let store;
- let updatedGroupItem;
-
- store = new GroupsStore();
- updatedGroupItem = store.formatGroupItem(mockRawChildren[0]);
-
- expect(Object.keys(updatedGroupItem).indexOf('fullName')).toBeGreaterThan(-1);
- expect(updatedGroupItem.childrenCount).toBe(mockRawChildren[0].children_count);
- expect(updatedGroupItem.isChildrenLoading).toBe(false);
- expect(updatedGroupItem.isBeingRemoved).toBe(false);
-
- store = new GroupsStore(true);
- updatedGroupItem = store.formatGroupItem(mockRawChildren[0]);
-
- expect(Object.keys(updatedGroupItem).indexOf('fullName')).toBeGreaterThan(-1);
- expect(updatedGroupItem.childrenCount).toBe(mockRawChildren[0].subgroup_count);
- });
- });
-
- describe('removeGroup', () => {
- it('should remove children from group item in state', () => {
- const store = new GroupsStore();
- const rawParentGroup = Object.assign({}, mockGroups[0]);
- const rawChildGroup = Object.assign({}, mockGroups[1]);
-
- store.setGroups([rawParentGroup]);
- store.setGroupChildren(store.state.groups[0], [rawChildGroup]);
- const childItem = store.state.groups[0].children[0];
-
- store.removeGroup(childItem, store.state.groups[0]);
-
- expect(store.state.groups[0].children.length).toBe(0);
- });
- });
-});
diff --git a/spec/javascripts/helpers/filtered_search_spec_helper.js b/spec/javascripts/helpers/filtered_search_spec_helper.js
index ceb7982bbc3..de17518ea51 100644
--- a/spec/javascripts/helpers/filtered_search_spec_helper.js
+++ b/spec/javascripts/helpers/filtered_search_spec_helper.js
@@ -1,69 +1 @@
-export default class FilteredSearchSpecHelper {
- static createFilterVisualTokenHTML(name, operator, value, isSelected) {
- return FilteredSearchSpecHelper.createFilterVisualToken(name, operator, value, isSelected)
- .outerHTML;
- }
-
- static createFilterVisualToken(name, operator, value, isSelected = false) {
- const li = document.createElement('li');
- li.classList.add('js-visual-token', 'filtered-search-token', `search-token-${name}`);
-
- li.innerHTML = `
- <div class="selectable ${isSelected ? 'selected' : ''}" role="button">
- <div class="name">${name}</div>
- <div class="operator">${operator}</div>
- <div class="value-container">
- <div class="value">${value}</div>
- <div class="remove-token" role="button">
- <i class="fa fa-close"></i>
- </div>
- </div>
- </div>
- `;
-
- return li;
- }
-
- static createNameFilterVisualTokenHTML(name) {
- return `
- <li class="js-visual-token filtered-search-token">
- <div class="name">${name}</div>
- </li>
- `;
- }
-
- static createNameOperatorFilterVisualTokenHTML(name, operator) {
- return `
- <li class="js-visual-token filtered-search-token">
- <div class="name">${name}</div>
- <div class="operator">${operator}</div>
- </li>
- `;
- }
-
- static createSearchVisualToken(name) {
- const li = document.createElement('li');
- li.classList.add('js-visual-token', 'filtered-search-term');
- li.innerHTML = `<div class="name">${name}</div>`;
- return li;
- }
-
- static createSearchVisualTokenHTML(name) {
- return FilteredSearchSpecHelper.createSearchVisualToken(name).outerHTML;
- }
-
- static createInputHTML(placeholder = '', value = '') {
- return `
- <li class="input-token">
- <input type='text' class='filtered-search' placeholder='${placeholder}' value='${value}'/>
- </li>
- `;
- }
-
- static createTokensContainerHTML(html, inputPlaceholder) {
- return `
- ${html}
- ${FilteredSearchSpecHelper.createInputHTML(inputPlaceholder)}
- `;
- }
-}
+export { default } from '../../frontend/helpers/filtered_search_spec_helper';
diff --git a/spec/javascripts/helpers/init_vue_mr_page_helper.js b/spec/javascripts/helpers/init_vue_mr_page_helper.js
index 04f969fcd2d..1ba08199764 100644
--- a/spec/javascripts/helpers/init_vue_mr_page_helper.js
+++ b/spec/javascripts/helpers/init_vue_mr_page_helper.js
@@ -2,7 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import initMRPage from '~/mr_notes/index';
import axios from '~/lib/utils/axios_utils';
import { userDataMock, notesDataMock, noteableDataMock } from '../../frontend/notes/mock_data';
-import diffFileMockData from '../diffs/mock_data/diff_file';
+import diffFileMockData from '../../frontend/diffs/mock_data/diff_file';
export default function initVueMRPage() {
const mrTestEl = document.createElement('div');
diff --git a/spec/javascripts/helpers/vue_mount_component_helper.js b/spec/javascripts/helpers/vue_mount_component_helper.js
index 6848c95d95d..c1857115b61 100644
--- a/spec/javascripts/helpers/vue_mount_component_helper.js
+++ b/spec/javascripts/helpers/vue_mount_component_helper.js
@@ -1,38 +1,2 @@
-import Vue from 'vue';
-
-const mountComponent = (Component, props = {}, el = null) =>
- new Component({
- propsData: props,
- }).$mount(el);
-
-export const createComponentWithStore = (Component, store, propsData = {}) =>
- new Component({
- store,
- propsData,
- });
-
-export const mountComponentWithStore = (Component, { el, props, store }) =>
- new Component({
- store,
- propsData: props || {},
- }).$mount(el);
-
-export const mountComponentWithSlots = (Component, { props, slots }) => {
- const component = new Component({
- propsData: props || {},
- });
-
- component.$slots = slots;
-
- return component.$mount();
-};
-
-/**
- * Mount a component with the given render method.
- *
- * This helps with inserting slots that need to be compiled.
- */
-export const mountComponentWithRender = (render, el = null) =>
- mountComponent(Vue.extend({ render }), {}, el);
-
-export default mountComponent;
+export { default } from '../../frontend/helpers/vue_mount_component_helper';
+export * from '../../frontend/helpers/vue_mount_component_helper';
diff --git a/spec/javascripts/ide/components/activity_bar_spec.js b/spec/javascripts/ide/components/activity_bar_spec.js
deleted file mode 100644
index 823ca29dab9..00000000000
--- a/spec/javascripts/ide/components/activity_bar_spec.js
+++ /dev/null
@@ -1,72 +0,0 @@
-import Vue from 'vue';
-import store from '~/ide/stores';
-import { leftSidebarViews } from '~/ide/constants';
-import ActivityBar from '~/ide/components/activity_bar.vue';
-import { createComponentWithStore } from '../../helpers/vue_mount_component_helper';
-import { resetStore } from '../helpers';
-
-describe('IDE activity bar', () => {
- const Component = Vue.extend(ActivityBar);
- let vm;
-
- beforeEach(() => {
- Vue.set(store.state.projects, 'abcproject', {
- web_url: 'testing',
- });
- Vue.set(store.state, 'currentProjectId', 'abcproject');
-
- vm = createComponentWithStore(Component, store);
- });
-
- afterEach(() => {
- vm.$destroy();
-
- resetStore(vm.$store);
- });
-
- describe('updateActivityBarView', () => {
- beforeEach(() => {
- spyOn(vm, 'updateActivityBarView');
-
- vm.$mount();
- });
-
- it('calls updateActivityBarView with edit value on click', () => {
- vm.$el.querySelector('.js-ide-edit-mode').click();
-
- expect(vm.updateActivityBarView).toHaveBeenCalledWith(leftSidebarViews.edit.name);
- });
-
- it('calls updateActivityBarView with commit value on click', () => {
- vm.$el.querySelector('.js-ide-commit-mode').click();
-
- expect(vm.updateActivityBarView).toHaveBeenCalledWith(leftSidebarViews.commit.name);
- });
-
- it('calls updateActivityBarView with review value on click', () => {
- vm.$el.querySelector('.js-ide-review-mode').click();
-
- expect(vm.updateActivityBarView).toHaveBeenCalledWith(leftSidebarViews.review.name);
- });
- });
-
- describe('active item', () => {
- beforeEach(() => {
- vm.$mount();
- });
-
- it('sets edit item active', () => {
- expect(vm.$el.querySelector('.js-ide-edit-mode').classList).toContain('active');
- });
-
- it('sets commit item active', done => {
- vm.$store.state.currentActivityView = leftSidebarViews.commit.name;
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.js-ide-commit-mode').classList).toContain('active');
-
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/ide/components/commit_sidebar/radio_group_spec.js b/spec/javascripts/ide/components/commit_sidebar/radio_group_spec.js
deleted file mode 100644
index b30f0e6822b..00000000000
--- a/spec/javascripts/ide/components/commit_sidebar/radio_group_spec.js
+++ /dev/null
@@ -1,139 +0,0 @@
-import Vue from 'vue';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
-import { resetStore } from 'spec/ide/helpers';
-import store from '~/ide/stores';
-import radioGroup from '~/ide/components/commit_sidebar/radio_group.vue';
-
-describe('IDE commit sidebar radio group', () => {
- let vm;
-
- beforeEach(done => {
- const Component = Vue.extend(radioGroup);
-
- store.state.commit.commitAction = '2';
-
- vm = createComponentWithStore(Component, store, {
- value: '1',
- label: 'test',
- checked: true,
- });
-
- vm.$mount();
-
- Vue.nextTick(done);
- });
-
- afterEach(() => {
- vm.$destroy();
-
- resetStore(vm.$store);
- });
-
- it('uses label if present', () => {
- expect(vm.$el.textContent).toContain('test');
- });
-
- it('uses slot if label is not present', done => {
- vm.$destroy();
-
- vm = new Vue({
- components: {
- radioGroup,
- },
- store,
- template: `
- <radio-group
- value="1"
- >
- Testing slot
- </radio-group>
- `,
- });
-
- vm.$mount();
-
- Vue.nextTick(() => {
- expect(vm.$el.textContent).toContain('Testing slot');
-
- done();
- });
- });
-
- it('updates store when changing radio button', done => {
- vm.$el.querySelector('input').dispatchEvent(new Event('change'));
-
- Vue.nextTick(() => {
- expect(store.state.commit.commitAction).toBe('1');
-
- done();
- });
- });
-
- describe('with input', () => {
- beforeEach(done => {
- vm.$destroy();
-
- const Component = Vue.extend(radioGroup);
-
- store.state.commit.commitAction = '1';
- store.state.commit.newBranchName = 'test-123';
-
- vm = createComponentWithStore(Component, store, {
- value: '1',
- label: 'test',
- checked: true,
- showInput: true,
- });
-
- vm.$mount();
-
- Vue.nextTick(done);
- });
-
- it('renders input box when commitAction matches value', () => {
- expect(vm.$el.querySelector('.form-control')).not.toBeNull();
- });
-
- it('hides input when commitAction doesnt match value', done => {
- store.state.commit.commitAction = '2';
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.form-control')).toBeNull();
- done();
- });
- });
-
- it('updates branch name in store on input', done => {
- const input = vm.$el.querySelector('.form-control');
- input.value = 'testing-123';
- input.dispatchEvent(new Event('input'));
-
- Vue.nextTick(() => {
- expect(store.state.commit.newBranchName).toBe('testing-123');
-
- done();
- });
- });
-
- it('renders newBranchName if present', () => {
- const input = vm.$el.querySelector('.form-control');
-
- expect(input.value).toBe('test-123');
- });
- });
-
- describe('tooltipTitle', () => {
- it('returns title when disabled', () => {
- vm.title = 'test title';
- vm.disabled = true;
-
- expect(vm.tooltipTitle).toBe('test title');
- });
-
- it('returns blank when not disabled', () => {
- vm.title = 'test title';
-
- expect(vm.tooltipTitle).not.toBe('test title');
- });
- });
-});
diff --git a/spec/javascripts/ide/components/file_row_extra_spec.js b/spec/javascripts/ide/components/file_row_extra_spec.js
deleted file mode 100644
index 9fd014b50ef..00000000000
--- a/spec/javascripts/ide/components/file_row_extra_spec.js
+++ /dev/null
@@ -1,170 +0,0 @@
-import Vue from 'vue';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
-import { createStore } from '~/ide/stores';
-import FileRowExtra from '~/ide/components/file_row_extra.vue';
-import { file, resetStore } from '../helpers';
-
-describe('IDE extra file row component', () => {
- let Component;
- let vm;
- let unstagedFilesCount = 0;
- let stagedFilesCount = 0;
- let changesCount = 0;
-
- beforeAll(() => {
- Component = Vue.extend(FileRowExtra);
- });
-
- beforeEach(() => {
- vm = createComponentWithStore(Component, createStore(), {
- file: {
- ...file('test'),
- },
- dropdownOpen: false,
- });
-
- spyOnProperty(vm, 'getUnstagedFilesCountForPath').and.returnValue(() => unstagedFilesCount);
- spyOnProperty(vm, 'getStagedFilesCountForPath').and.returnValue(() => stagedFilesCount);
- spyOnProperty(vm, 'getChangesInFolder').and.returnValue(() => changesCount);
-
- vm.$mount();
- });
-
- afterEach(() => {
- vm.$destroy();
- resetStore(vm.$store);
-
- stagedFilesCount = 0;
- unstagedFilesCount = 0;
- changesCount = 0;
- });
-
- describe('folderChangesTooltip', () => {
- it('returns undefined when changes count is 0', () => {
- changesCount = 0;
-
- expect(vm.folderChangesTooltip).toBe(undefined);
- });
-
- [{ input: 1, output: '1 changed file' }, { input: 2, output: '2 changed files' }].forEach(
- ({ input, output }) => {
- it('returns changed files count if changes count is not 0', () => {
- changesCount = input;
-
- expect(vm.folderChangesTooltip).toBe(output);
- });
- },
- );
- });
-
- describe('show tree changes count', () => {
- it('does not show for blobs', () => {
- vm.file.type = 'blob';
-
- expect(vm.$el.querySelector('.ide-tree-changes')).toBe(null);
- });
-
- it('does not show when changes count is 0', () => {
- vm.file.type = 'tree';
-
- expect(vm.$el.querySelector('.ide-tree-changes')).toBe(null);
- });
-
- it('does not show when tree is open', done => {
- vm.file.type = 'tree';
- vm.file.opened = true;
- changesCount = 1;
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.ide-tree-changes')).toBe(null);
-
- done();
- });
- });
-
- it('shows for trees with changes', done => {
- vm.file.type = 'tree';
- vm.file.opened = false;
- changesCount = 1;
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.ide-tree-changes')).not.toBe(null);
-
- done();
- });
- });
- });
-
- describe('changes file icon', () => {
- it('hides when file is not changed', () => {
- expect(vm.$el.querySelector('.file-changed-icon')).toBe(null);
- });
-
- it('shows when file is changed', done => {
- vm.file.changed = true;
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
-
- done();
- });
- });
-
- it('shows when file is staged', done => {
- vm.file.staged = true;
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
-
- done();
- });
- });
-
- it('shows when file is a tempFile', done => {
- vm.file.tempFile = true;
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
-
- done();
- });
- });
-
- it('shows when file is renamed', done => {
- vm.file.prevPath = 'original-file';
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
-
- done();
- });
- });
-
- it('hides when file is renamed', done => {
- vm.file.prevPath = 'original-file';
- vm.file.type = 'tree';
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.file-changed-icon')).toBe(null);
-
- done();
- });
- });
- });
-
- describe('merge request icon', () => {
- it('hides when not a merge request change', () => {
- expect(vm.$el.querySelector('.ic-git-merge')).toBe(null);
- });
-
- it('shows when a merge request change', done => {
- vm.file.mrChange = true;
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.ic-git-merge')).not.toBe(null);
-
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/ide/components/file_templates/bar_spec.js b/spec/javascripts/ide/components/file_templates/bar_spec.js
deleted file mode 100644
index 5399ada94ae..00000000000
--- a/spec/javascripts/ide/components/file_templates/bar_spec.js
+++ /dev/null
@@ -1,117 +0,0 @@
-import Vue from 'vue';
-import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
-import { createStore } from '~/ide/stores';
-import Bar from '~/ide/components/file_templates/bar.vue';
-import { resetStore, file } from '../../helpers';
-
-describe('IDE file templates bar component', () => {
- let Component;
- let vm;
-
- beforeAll(() => {
- Component = Vue.extend(Bar);
- });
-
- beforeEach(() => {
- const store = createStore();
-
- store.state.openFiles.push({
- ...file('file'),
- opened: true,
- active: true,
- });
-
- vm = mountComponentWithStore(Component, { store });
- });
-
- afterEach(() => {
- vm.$destroy();
- resetStore(vm.$store);
- });
-
- describe('template type dropdown', () => {
- it('renders dropdown component', () => {
- expect(vm.$el.querySelector('.dropdown').textContent).toContain('Choose a type');
- });
-
- it('calls setSelectedTemplateType when clicking item', () => {
- spyOn(vm, 'setSelectedTemplateType').and.stub();
-
- vm.$el.querySelector('.dropdown-content button').click();
-
- expect(vm.setSelectedTemplateType).toHaveBeenCalledWith({
- name: '.gitlab-ci.yml',
- key: 'gitlab_ci_ymls',
- });
- });
- });
-
- describe('template dropdown', () => {
- beforeEach(done => {
- vm.$store.state.fileTemplates.templates = [
- {
- name: 'test',
- },
- ];
- vm.$store.state.fileTemplates.selectedTemplateType = {
- name: '.gitlab-ci.yml',
- key: 'gitlab_ci_ymls',
- };
-
- vm.$nextTick(done);
- });
-
- it('renders dropdown component', () => {
- expect(vm.$el.querySelectorAll('.dropdown')[1].textContent).toContain('Choose a template');
- });
-
- it('calls fetchTemplate on click', () => {
- spyOn(vm, 'fetchTemplate').and.stub();
-
- vm.$el
- .querySelectorAll('.dropdown-content')[1]
- .querySelector('button')
- .click();
-
- expect(vm.fetchTemplate).toHaveBeenCalledWith({
- name: 'test',
- });
- });
- });
-
- it('shows undo button if updateSuccess is true', done => {
- vm.$store.state.fileTemplates.updateSuccess = true;
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.btn-default').style.display).not.toBe('none');
-
- done();
- });
- });
-
- it('calls undoFileTemplate when clicking undo button', () => {
- spyOn(vm, 'undoFileTemplate').and.stub();
-
- vm.$el.querySelector('.btn-default').click();
-
- expect(vm.undoFileTemplate).toHaveBeenCalled();
- });
-
- it('calls setSelectedTemplateType if activeFile name matches a template', done => {
- const fileName = '.gitlab-ci.yml';
-
- spyOn(vm, 'setSelectedTemplateType');
- vm.$store.state.openFiles[0].name = fileName;
-
- vm.setInitialType();
-
- vm.$nextTick(() => {
- expect(vm.setSelectedTemplateType).toHaveBeenCalledWith({
- name: fileName,
- key: 'gitlab_ci_ymls',
- });
-
- done();
- });
- });
-});
diff --git a/spec/javascripts/ide/components/ide_review_spec.js b/spec/javascripts/ide/components/ide_review_spec.js
deleted file mode 100644
index 396c5d282d4..00000000000
--- a/spec/javascripts/ide/components/ide_review_spec.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import Vue from 'vue';
-import IdeReview from '~/ide/components/ide_review.vue';
-import store from '~/ide/stores';
-import { createComponentWithStore } from '../../helpers/vue_mount_component_helper';
-import { trimText } from '../../helpers/text_helper';
-import { resetStore, file } from '../helpers';
-import { projectData } from '../mock_data';
-
-describe('IDE review mode', () => {
- const Component = Vue.extend(IdeReview);
- let vm;
-
- beforeEach(() => {
- store.state.currentProjectId = 'abcproject';
- store.state.currentBranchId = 'master';
- store.state.projects.abcproject = Object.assign({}, projectData);
- Vue.set(store.state.trees, 'abcproject/master', {
- tree: [file('fileName')],
- loading: false,
- });
-
- vm = createComponentWithStore(Component, store).$mount();
- });
-
- afterEach(() => {
- vm.$destroy();
-
- resetStore(vm.$store);
- });
-
- it('renders list of files', () => {
- expect(vm.$el.textContent).toContain('fileName');
- });
-
- describe('merge request', () => {
- beforeEach(done => {
- store.state.currentMergeRequestId = '1';
- store.state.projects.abcproject.mergeRequests['1'] = {
- iid: 123,
- web_url: 'testing123',
- };
-
- vm.$nextTick(done);
- });
-
- it('renders edit dropdown', () => {
- expect(vm.$el.querySelector('.btn')).not.toBe(null);
- });
-
- it('renders merge request link & IID', () => {
- const link = vm.$el.querySelector('.ide-review-sub-header');
-
- expect(link.querySelector('a').getAttribute('href')).toBe('testing123');
- expect(trimText(link.textContent)).toBe('Merge request (!123)');
- });
-
- it('changes text to latest changes when viewer is not mrdiff', done => {
- store.state.viewer = 'diff';
-
- vm.$nextTick(() => {
- expect(trimText(vm.$el.querySelector('.ide-review-sub-header').textContent)).toBe(
- 'Latest changes',
- );
-
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/ide/components/ide_side_bar_spec.js b/spec/javascripts/ide/components/ide_side_bar_spec.js
deleted file mode 100644
index 28f127a61c0..00000000000
--- a/spec/javascripts/ide/components/ide_side_bar_spec.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import Vue from 'vue';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
-import store from '~/ide/stores';
-import ideSidebar from '~/ide/components/ide_side_bar.vue';
-import { leftSidebarViews } from '~/ide/constants';
-import { resetStore } from '../helpers';
-import { projectData } from '../mock_data';
-
-describe('IdeSidebar', () => {
- let vm;
-
- beforeEach(() => {
- const Component = Vue.extend(ideSidebar);
-
- store.state.currentProjectId = 'abcproject';
- store.state.projects.abcproject = projectData;
-
- vm = createComponentWithStore(Component, store).$mount();
- });
-
- afterEach(() => {
- vm.$destroy();
-
- resetStore(vm.$store);
- });
-
- it('renders a sidebar', () => {
- expect(vm.$el.querySelector('.multi-file-commit-panel-inner')).not.toBeNull();
- });
-
- it('renders loading icon component', done => {
- vm.$store.state.loading = true;
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.multi-file-loading-container')).not.toBeNull();
- expect(vm.$el.querySelectorAll('.multi-file-loading-container').length).toBe(3);
-
- done();
- });
- });
-
- describe('activityBarComponent', () => {
- it('renders tree component', () => {
- expect(vm.$el.querySelector('.ide-file-list')).not.toBeNull();
- });
-
- it('renders commit component', done => {
- vm.$store.state.currentActivityView = leftSidebarViews.commit.name;
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.multi-file-commit-panel-section')).not.toBeNull();
-
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/ide/components/ide_spec.js b/spec/javascripts/ide/components/ide_spec.js
deleted file mode 100644
index 4241b994cba..00000000000
--- a/spec/javascripts/ide/components/ide_spec.js
+++ /dev/null
@@ -1,125 +0,0 @@
-import Vue from 'vue';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
-import store from '~/ide/stores';
-import ide from '~/ide/components/ide.vue';
-import { file, resetStore } from '../helpers';
-import { projectData } from '../mock_data';
-
-function bootstrap(projData) {
- const Component = Vue.extend(ide);
-
- store.state.currentProjectId = 'abcproject';
- store.state.currentBranchId = 'master';
- store.state.projects.abcproject = Object.assign({}, projData);
- Vue.set(store.state.trees, 'abcproject/master', {
- tree: [],
- loading: false,
- });
-
- return createComponentWithStore(Component, store, {
- emptyStateSvgPath: 'svg',
- noChangesStateSvgPath: 'svg',
- committedStateSvgPath: 'svg',
- });
-}
-
-describe('ide component, empty repo', () => {
- let vm;
-
- beforeEach(() => {
- const emptyProjData = Object.assign({}, projectData, { empty_repo: true, branches: {} });
- vm = bootstrap(emptyProjData);
- vm.$mount();
- });
-
- afterEach(() => {
- vm.$destroy();
-
- resetStore(vm.$store);
- });
-
- it('renders "New file" button in empty repo', done => {
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.ide-empty-state button[title="New file"]')).not.toBeNull();
- done();
- });
- });
-});
-
-describe('ide component, non-empty repo', () => {
- let vm;
-
- beforeEach(() => {
- vm = bootstrap(projectData);
- vm.$mount();
- });
-
- afterEach(() => {
- vm.$destroy();
-
- resetStore(vm.$store);
- });
-
- it('shows error message when set', done => {
- expect(vm.$el.querySelector('.gl-alert')).toBe(null);
-
- vm.$store.state.errorMessage = {
- text: 'error',
- };
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.gl-alert')).not.toBe(null);
-
- done();
- });
- });
-
- describe('onBeforeUnload', () => {
- it('returns undefined when no staged files or changed files', () => {
- expect(vm.onBeforeUnload()).toBe(undefined);
- });
-
- it('returns warning text when their are changed files', () => {
- vm.$store.state.changedFiles.push(file());
-
- expect(vm.onBeforeUnload()).toBe('Are you sure you want to lose unsaved changes?');
- });
-
- it('returns warning text when their are staged files', () => {
- vm.$store.state.stagedFiles.push(file());
-
- expect(vm.onBeforeUnload()).toBe('Are you sure you want to lose unsaved changes?');
- });
-
- it('updates event object', () => {
- const event = {};
- vm.$store.state.stagedFiles.push(file());
-
- vm.onBeforeUnload(event);
-
- expect(event.returnValue).toBe('Are you sure you want to lose unsaved changes?');
- });
- });
-
- describe('non-existent branch', () => {
- it('does not render "New file" button for non-existent branch when repo is not empty', done => {
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.ide-empty-state button[title="New file"]')).toBeNull();
- done();
- });
- });
- });
-
- describe('branch with files', () => {
- beforeEach(() => {
- store.state.trees['abcproject/master'].tree = [file()];
- });
-
- it('does not render "New file" button', done => {
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.ide-empty-state button[title="New file"]')).toBeNull();
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/ide/components/ide_status_bar_spec.js b/spec/javascripts/ide/components/ide_status_bar_spec.js
deleted file mode 100644
index 3facf1c266a..00000000000
--- a/spec/javascripts/ide/components/ide_status_bar_spec.js
+++ /dev/null
@@ -1,129 +0,0 @@
-import Vue from 'vue';
-import _ from 'lodash';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
-import { TEST_HOST } from 'spec/test_constants';
-import { createStore } from '~/ide/stores';
-import IdeStatusBar from '~/ide/components/ide_status_bar.vue';
-import { rightSidebarViews } from '~/ide/constants';
-import { projectData } from '../mock_data';
-
-const TEST_PROJECT_ID = 'abcproject';
-const TEST_MERGE_REQUEST_ID = '9001';
-const TEST_MERGE_REQUEST_URL = `${TEST_HOST}merge-requests/${TEST_MERGE_REQUEST_ID}`;
-
-describe('ideStatusBar', () => {
- let store;
- let vm;
-
- const createComponent = () => {
- vm = createComponentWithStore(Vue.extend(IdeStatusBar), store).$mount();
- };
- const findMRStatus = () => vm.$el.querySelector('.js-ide-status-mr');
-
- beforeEach(() => {
- store = createStore();
- store.state.currentProjectId = TEST_PROJECT_ID;
- store.state.projects[TEST_PROJECT_ID] = _.clone(projectData);
- store.state.currentBranchId = 'master';
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('default', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('triggers a setInterval', () => {
- expect(vm.intervalId).not.toBe(null);
- });
-
- it('renders the statusbar', () => {
- expect(vm.$el.className).toBe('ide-status-bar');
- });
-
- describe('commitAgeUpdate', () => {
- beforeEach(function() {
- jasmine.clock().install();
- spyOn(vm, 'commitAgeUpdate').and.callFake(() => {});
- vm.startTimer();
- });
-
- afterEach(function() {
- jasmine.clock().uninstall();
- });
-
- it('gets called every second', () => {
- expect(vm.commitAgeUpdate).not.toHaveBeenCalled();
-
- jasmine.clock().tick(1100);
-
- expect(vm.commitAgeUpdate.calls.count()).toEqual(1);
-
- jasmine.clock().tick(1000);
-
- expect(vm.commitAgeUpdate.calls.count()).toEqual(2);
- });
- });
-
- describe('getCommitPath', () => {
- it('returns the path to the commit details', () => {
- expect(vm.getCommitPath('abc123de')).toBe('/commit/abc123de');
- });
- });
-
- describe('pipeline status', () => {
- it('opens right sidebar on clicking icon', done => {
- spyOn(vm, 'openRightPane');
- Vue.set(vm.$store.state.pipelines, 'latestPipeline', {
- details: {
- status: {
- text: 'success',
- details_path: 'test',
- icon: 'status_success',
- },
- },
- commit: {
- author_gravatar_url: 'www',
- },
- });
-
- vm.$nextTick()
- .then(() => {
- vm.$el.querySelector('.ide-status-pipeline button').click();
-
- expect(vm.openRightPane).toHaveBeenCalledWith(rightSidebarViews.pipelines);
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- it('does not show merge request status', () => {
- expect(findMRStatus()).toBe(null);
- });
- });
-
- describe('with merge request in store', () => {
- beforeEach(() => {
- store.state.projects[TEST_PROJECT_ID].mergeRequests = {
- [TEST_MERGE_REQUEST_ID]: {
- web_url: TEST_MERGE_REQUEST_URL,
- references: {
- short: `!${TEST_MERGE_REQUEST_ID}`,
- },
- },
- };
- store.state.currentMergeRequestId = TEST_MERGE_REQUEST_ID;
-
- createComponent();
- });
-
- it('shows merge request status', () => {
- expect(findMRStatus().textContent.trim()).toEqual(`Merge request !${TEST_MERGE_REQUEST_ID}`);
- expect(findMRStatus().querySelector('a').href).toEqual(TEST_MERGE_REQUEST_URL);
- });
- });
-});
diff --git a/spec/javascripts/ide/components/ide_tree_list_spec.js b/spec/javascripts/ide/components/ide_tree_list_spec.js
deleted file mode 100644
index f63007c7dd2..00000000000
--- a/spec/javascripts/ide/components/ide_tree_list_spec.js
+++ /dev/null
@@ -1,77 +0,0 @@
-import Vue from 'vue';
-import IdeTreeList from '~/ide/components/ide_tree_list.vue';
-import store from '~/ide/stores';
-import { createComponentWithStore } from '../../helpers/vue_mount_component_helper';
-import { resetStore, file } from '../helpers';
-import { projectData } from '../mock_data';
-
-describe('IDE tree list', () => {
- const Component = Vue.extend(IdeTreeList);
- const normalBranchTree = [file('fileName')];
- const emptyBranchTree = [];
- let vm;
-
- const bootstrapWithTree = (tree = normalBranchTree) => {
- store.state.currentProjectId = 'abcproject';
- store.state.currentBranchId = 'master';
- store.state.projects.abcproject = Object.assign({}, projectData);
- Vue.set(store.state.trees, 'abcproject/master', {
- tree,
- loading: false,
- });
-
- vm = createComponentWithStore(Component, store, {
- viewerType: 'edit',
- });
- };
-
- afterEach(() => {
- vm.$destroy();
-
- resetStore(vm.$store);
- });
-
- describe('normal branch', () => {
- beforeEach(() => {
- bootstrapWithTree();
-
- spyOn(vm, 'updateViewer').and.callThrough();
-
- vm.$mount();
- });
-
- it('updates viewer on mount', () => {
- expect(vm.updateViewer).toHaveBeenCalledWith('edit');
- });
-
- it('renders loading indicator', done => {
- store.state.trees['abcproject/master'].loading = true;
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.multi-file-loading-container')).not.toBeNull();
- expect(vm.$el.querySelectorAll('.multi-file-loading-container').length).toBe(3);
-
- done();
- });
- });
-
- it('renders list of files', () => {
- expect(vm.$el.textContent).toContain('fileName');
- });
- });
-
- describe('empty-branch state', () => {
- beforeEach(() => {
- bootstrapWithTree(emptyBranchTree);
-
- spyOn(vm, 'updateViewer').and.callThrough();
-
- vm.$mount();
- });
-
- it('does not load files if the branch is empty', () => {
- expect(vm.$el.textContent).not.toContain('fileName');
- expect(vm.$el.textContent).toContain('No files');
- });
- });
-});
diff --git a/spec/javascripts/ide/components/ide_tree_spec.js b/spec/javascripts/ide/components/ide_tree_spec.js
deleted file mode 100644
index 97a0a2432f1..00000000000
--- a/spec/javascripts/ide/components/ide_tree_spec.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import Vue from 'vue';
-import IdeTree from '~/ide/components/ide_tree.vue';
-import store from '~/ide/stores';
-import { createComponentWithStore } from '../../helpers/vue_mount_component_helper';
-import { resetStore, file } from '../helpers';
-import { projectData } from '../mock_data';
-
-describe('IdeRepoTree', () => {
- let vm;
-
- beforeEach(() => {
- const IdeRepoTree = Vue.extend(IdeTree);
-
- store.state.currentProjectId = 'abcproject';
- store.state.currentBranchId = 'master';
- store.state.projects.abcproject = Object.assign({}, projectData);
- Vue.set(store.state.trees, 'abcproject/master', {
- tree: [file('fileName')],
- loading: false,
- });
-
- vm = createComponentWithStore(IdeRepoTree, store).$mount();
- });
-
- afterEach(() => {
- vm.$destroy();
-
- resetStore(vm.$store);
- });
-
- it('renders list of files', () => {
- expect(vm.$el.textContent).toContain('fileName');
- });
-});
diff --git a/spec/javascripts/ide/components/jobs/detail/description_spec.js b/spec/javascripts/ide/components/jobs/detail/description_spec.js
deleted file mode 100644
index babae00d2f7..00000000000
--- a/spec/javascripts/ide/components/jobs/detail/description_spec.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import Vue from 'vue';
-import Description from '~/ide/components/jobs/detail/description.vue';
-import mountComponent from '../../../../helpers/vue_mount_component_helper';
-import { jobs } from '../../../mock_data';
-
-describe('IDE job description', () => {
- const Component = Vue.extend(Description);
- let vm;
-
- beforeEach(() => {
- vm = mountComponent(Component, {
- job: jobs[0],
- });
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders job details', () => {
- expect(vm.$el.textContent).toContain('#1');
- expect(vm.$el.textContent).toContain('test');
- });
-
- it('renders CI icon', () => {
- expect(vm.$el.querySelector('.ci-status-icon .ic-status_success_borderless')).not.toBe(null);
- });
-});
diff --git a/spec/javascripts/ide/components/jobs/item_spec.js b/spec/javascripts/ide/components/jobs/item_spec.js
deleted file mode 100644
index 2f97d39e98e..00000000000
--- a/spec/javascripts/ide/components/jobs/item_spec.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import Vue from 'vue';
-import JobItem from '~/ide/components/jobs/item.vue';
-import mountComponent from '../../../helpers/vue_mount_component_helper';
-import { jobs } from '../../mock_data';
-
-describe('IDE jobs item', () => {
- const Component = Vue.extend(JobItem);
- const job = jobs[0];
- let vm;
-
- beforeEach(() => {
- vm = mountComponent(Component, {
- job,
- });
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders job details', () => {
- expect(vm.$el.textContent).toContain(job.name);
- expect(vm.$el.textContent).toContain(`#${job.id}`);
- });
-
- it('renders CI icon', () => {
- expect(vm.$el.querySelector('.ic-status_success_borderless')).not.toBe(null);
- });
-
- it('does not render view logs button if not started', done => {
- vm.job.started = false;
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.btn')).toBe(null);
-
- done();
- });
- });
-});
diff --git a/spec/javascripts/ide/components/merge_requests/item_spec.js b/spec/javascripts/ide/components/merge_requests/item_spec.js
deleted file mode 100644
index 155a247defb..00000000000
--- a/spec/javascripts/ide/components/merge_requests/item_spec.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import Vue from 'vue';
-import router from '~/ide/ide_router';
-import Item from '~/ide/components/merge_requests/item.vue';
-import mountCompontent from '../../../helpers/vue_mount_component_helper';
-
-describe('IDE merge request item', () => {
- const Component = Vue.extend(Item);
- let vm;
-
- beforeEach(() => {
- vm = mountCompontent(Component, {
- item: {
- iid: 1,
- projectPathWithNamespace: 'gitlab-org/gitlab-ce',
- title: 'Merge request title',
- },
- currentId: '1',
- currentProjectId: 'gitlab-org/gitlab-ce',
- });
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders merge requests data', () => {
- expect(vm.$el.textContent).toContain('Merge request title');
- expect(vm.$el.textContent).toContain('gitlab-org/gitlab-ce!1');
- });
-
- it('renders link with href', () => {
- const expectedHref = router.resolve(
- `/project/${vm.item.projectPathWithNamespace}/merge_requests/${vm.item.iid}`,
- ).href;
-
- expect(vm.$el).toMatch('a');
- expect(vm.$el).toHaveAttr('href', expectedHref);
- });
-
- it('renders icon if ID matches currentId', () => {
- expect(vm.$el.querySelector('.ic-mobile-issue-close')).not.toBe(null);
- });
-
- it('does not render icon if ID does not match currentId', done => {
- vm.currentId = '2';
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.ic-mobile-issue-close')).toBe(null);
-
- done();
- });
- });
-
- it('does not render icon if project ID does not match', done => {
- vm.currentProjectId = 'test/test';
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.ic-mobile-issue-close')).toBe(null);
-
- done();
- });
- });
-});
diff --git a/spec/javascripts/ide/components/nav_dropdown_button_spec.js b/spec/javascripts/ide/components/nav_dropdown_button_spec.js
deleted file mode 100644
index bbaf97164ea..00000000000
--- a/spec/javascripts/ide/components/nav_dropdown_button_spec.js
+++ /dev/null
@@ -1,93 +0,0 @@
-import Vue from 'vue';
-import { trimText } from 'spec/helpers/text_helper';
-import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
-import NavDropdownButton from '~/ide/components/nav_dropdown_button.vue';
-import { createStore } from '~/ide/stores';
-
-describe('NavDropdown', () => {
- const TEST_BRANCH_ID = 'lorem-ipsum-dolar';
- const TEST_MR_ID = '12345';
- let store;
- let vm;
-
- beforeEach(() => {
- store = createStore();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- const createComponent = (props = {}) => {
- vm = mountComponentWithStore(Vue.extend(NavDropdownButton), { props, store });
- vm.$mount();
- };
-
- const findIcon = name => vm.$el.querySelector(`.ic-${name}`);
- const findMRIcon = () => findIcon('merge-request');
- const findBranchIcon = () => findIcon('branch');
-
- describe('normal', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('renders empty placeholders, if state is falsey', () => {
- expect(trimText(vm.$el.textContent)).toEqual('- -');
- });
-
- it('renders branch name, if state has currentBranchId', done => {
- vm.$store.state.currentBranchId = TEST_BRANCH_ID;
-
- vm.$nextTick()
- .then(() => {
- expect(trimText(vm.$el.textContent)).toEqual(`${TEST_BRANCH_ID} -`);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('renders mr id, if state has currentMergeRequestId', done => {
- vm.$store.state.currentMergeRequestId = TEST_MR_ID;
-
- vm.$nextTick()
- .then(() => {
- expect(trimText(vm.$el.textContent)).toEqual(`- !${TEST_MR_ID}`);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('renders branch and mr, if state has both', done => {
- vm.$store.state.currentBranchId = TEST_BRANCH_ID;
- vm.$store.state.currentMergeRequestId = TEST_MR_ID;
-
- vm.$nextTick()
- .then(() => {
- expect(trimText(vm.$el.textContent)).toEqual(`${TEST_BRANCH_ID} !${TEST_MR_ID}`);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('shows icons', () => {
- expect(findBranchIcon()).toBeTruthy();
- expect(findMRIcon()).toBeTruthy();
- });
- });
-
- describe('with showMergeRequests false', () => {
- beforeEach(() => {
- createComponent({ showMergeRequests: false });
- });
-
- it('shows single empty placeholder, if state is falsey', () => {
- expect(trimText(vm.$el.textContent)).toEqual('-');
- });
-
- it('shows only branch icon', () => {
- expect(findBranchIcon()).toBeTruthy();
- expect(findMRIcon()).toBe(null);
- });
- });
-});
diff --git a/spec/javascripts/ide/components/nav_dropdown_spec.js b/spec/javascripts/ide/components/nav_dropdown_spec.js
deleted file mode 100644
index dfb4d03540f..00000000000
--- a/spec/javascripts/ide/components/nav_dropdown_spec.js
+++ /dev/null
@@ -1,80 +0,0 @@
-import $ from 'jquery';
-import Vue from 'vue';
-import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
-import store from '~/ide/stores';
-import NavDropdown from '~/ide/components/nav_dropdown.vue';
-import { PERMISSION_READ_MR } from '~/ide/constants';
-
-const TEST_PROJECT_ID = 'lorem-ipsum';
-
-describe('IDE NavDropdown', () => {
- const Component = Vue.extend(NavDropdown);
- let vm;
- let $dropdown;
-
- beforeEach(() => {
- store.state.currentProjectId = TEST_PROJECT_ID;
- Vue.set(store.state.projects, TEST_PROJECT_ID, {
- userPermissions: {
- [PERMISSION_READ_MR]: true,
- },
- });
- vm = mountComponentWithStore(Component, { store });
- $dropdown = $(vm.$el);
-
- // block dispatch from doing anything
- spyOn(vm.$store, 'dispatch');
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- const findIcon = name => vm.$el.querySelector(`.ic-${name}`);
- const findMRIcon = () => findIcon('merge-request');
-
- it('renders nothing initially', () => {
- expect(vm.$el).not.toContainElement('.ide-nav-form');
- });
-
- it('renders nav form when show.bs.dropdown', done => {
- $dropdown.trigger('show.bs.dropdown');
-
- vm.$nextTick()
- .then(() => {
- expect(vm.$el).toContainElement('.ide-nav-form');
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('destroys nav form when closed', done => {
- $dropdown.trigger('show.bs.dropdown');
- $dropdown.trigger('hide.bs.dropdown');
-
- vm.$nextTick()
- .then(() => {
- expect(vm.$el).not.toContainElement('.ide-nav-form');
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('renders merge request icon', () => {
- expect(findMRIcon()).not.toBeNull();
- });
-
- describe('when user cannot read merge requests', () => {
- beforeEach(done => {
- store.state.projects[TEST_PROJECT_ID].userPermissions = {};
-
- vm.$nextTick()
- .then(done)
- .catch(done.fail);
- });
-
- it('does not render merge requests', () => {
- expect(findMRIcon()).toBeNull();
- });
- });
-});
diff --git a/spec/javascripts/ide/components/new_dropdown/button_spec.js b/spec/javascripts/ide/components/new_dropdown/button_spec.js
deleted file mode 100644
index 6a326b5bd92..00000000000
--- a/spec/javascripts/ide/components/new_dropdown/button_spec.js
+++ /dev/null
@@ -1,65 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import Button from '~/ide/components/new_dropdown/button.vue';
-
-describe('IDE new entry dropdown button component', () => {
- let Component;
- let vm;
-
- beforeAll(() => {
- Component = Vue.extend(Button);
- });
-
- beforeEach(() => {
- vm = mountComponent(Component, {
- label: 'Testing',
- icon: 'doc-new',
- });
-
- spyOn(vm, '$emit');
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders button with label', () => {
- expect(vm.$el.textContent).toContain('Testing');
- });
-
- it('renders icon', () => {
- expect(vm.$el.querySelector('.ic-doc-new')).not.toBe(null);
- });
-
- it('emits click event', () => {
- vm.$el.click();
-
- expect(vm.$emit).toHaveBeenCalledWith('click');
- });
-
- it('hides label if showLabel is false', done => {
- vm.showLabel = false;
-
- vm.$nextTick(() => {
- expect(vm.$el.textContent).not.toContain('Testing');
-
- done();
- });
- });
-
- describe('tooltipTitle', () => {
- it('returns empty string when showLabel is true', () => {
- expect(vm.tooltipTitle).toBe('');
- });
-
- it('returns label', done => {
- vm.showLabel = false;
-
- vm.$nextTick(() => {
- expect(vm.tooltipTitle).toBe('Testing');
-
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/ide/components/new_dropdown/index_spec.js b/spec/javascripts/ide/components/new_dropdown/index_spec.js
deleted file mode 100644
index 03afe997fed..00000000000
--- a/spec/javascripts/ide/components/new_dropdown/index_spec.js
+++ /dev/null
@@ -1,84 +0,0 @@
-import Vue from 'vue';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
-import store from '~/ide/stores';
-import newDropdown from '~/ide/components/new_dropdown/index.vue';
-import { resetStore } from '../../helpers';
-
-describe('new dropdown component', () => {
- let vm;
-
- beforeEach(() => {
- const component = Vue.extend(newDropdown);
-
- vm = createComponentWithStore(component, store, {
- branch: 'master',
- path: '',
- mouseOver: false,
- type: 'tree',
- });
-
- vm.$store.state.currentProjectId = 'abcproject';
- vm.$store.state.path = '';
- vm.$store.state.trees['abcproject/mybranch'] = {
- tree: [],
- };
-
- spyOn(vm, 'openNewEntryModal');
-
- vm.$mount();
- });
-
- afterEach(() => {
- vm.$destroy();
-
- resetStore(vm.$store);
- });
-
- it('renders new file, upload and new directory links', () => {
- const buttons = vm.$el.querySelectorAll('.dropdown-menu button');
-
- expect(buttons[0].textContent.trim()).toBe('New file');
- expect(buttons[1].textContent.trim()).toBe('Upload file');
- expect(buttons[2].textContent.trim()).toBe('New directory');
- });
-
- describe('createNewItem', () => {
- it('sets modalType to blob when new file is clicked', () => {
- vm.$el.querySelectorAll('.dropdown-menu button')[0].click();
-
- expect(vm.openNewEntryModal).toHaveBeenCalledWith({ type: 'blob', path: '' });
- });
-
- it('sets modalType to tree when new directory is clicked', () => {
- vm.$el.querySelectorAll('.dropdown-menu button')[2].click();
-
- expect(vm.openNewEntryModal).toHaveBeenCalledWith({ type: 'tree', path: '' });
- });
- });
-
- describe('isOpen', () => {
- it('scrolls dropdown into view', done => {
- spyOn(vm.$refs.dropdownMenu, 'scrollIntoView');
-
- vm.isOpen = true;
-
- setTimeout(() => {
- expect(vm.$refs.dropdownMenu.scrollIntoView).toHaveBeenCalledWith({
- block: 'nearest',
- });
-
- done();
- });
- });
- });
-
- describe('delete entry', () => {
- it('calls delete action', () => {
- spyOn(vm, 'deleteEntry');
-
- vm.$el.querySelectorAll('.dropdown-menu button')[4].click();
-
- expect(vm.deleteEntry).toHaveBeenCalledWith('');
- });
- });
-});
diff --git a/spec/javascripts/ide/components/new_dropdown/modal_spec.js b/spec/javascripts/ide/components/new_dropdown/modal_spec.js
deleted file mode 100644
index 0ea767e087d..00000000000
--- a/spec/javascripts/ide/components/new_dropdown/modal_spec.js
+++ /dev/null
@@ -1,150 +0,0 @@
-import Vue from 'vue';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
-import { createStore } from '~/ide/stores';
-import modal from '~/ide/components/new_dropdown/modal.vue';
-
-describe('new file modal component', () => {
- const Component = Vue.extend(modal);
- let vm;
-
- afterEach(() => {
- vm.$destroy();
- });
-
- ['tree', 'blob'].forEach(type => {
- describe(type, () => {
- beforeEach(() => {
- const store = createStore();
- store.state.entryModal = {
- type,
- path: '',
- entry: {
- path: '',
- },
- };
-
- vm = createComponentWithStore(Component, store).$mount();
-
- vm.name = 'testing';
- });
-
- it(`sets modal title as ${type}`, () => {
- const title = type === 'tree' ? 'directory' : 'file';
-
- expect(vm.$el.querySelector('.modal-title').textContent.trim()).toBe(`Create new ${title}`);
- });
-
- it(`sets button label as ${type}`, () => {
- const title = type === 'tree' ? 'directory' : 'file';
-
- expect(vm.$el.querySelector('.btn-success').textContent.trim()).toBe(`Create ${title}`);
- });
-
- it(`sets form label as ${type}`, () => {
- expect(vm.$el.querySelector('.label-bold').textContent.trim()).toBe('Name');
- });
-
- it(`${type === 'tree' ? 'does not show' : 'shows'} file templates`, () => {
- const templateFilesEl = vm.$el.querySelector('.file-templates');
- if (type === 'tree') {
- expect(templateFilesEl).toBeNull();
- } else {
- expect(templateFilesEl instanceof Element).toBeTruthy();
- }
- });
- });
- });
-
- describe('rename entry', () => {
- beforeEach(() => {
- const store = createStore();
- store.state.entryModal = {
- type: 'rename',
- path: '',
- entry: {
- name: 'test',
- type: 'blob',
- path: 'test-path',
- },
- };
-
- vm = createComponentWithStore(Component, store).$mount();
- });
-
- ['tree', 'blob'].forEach(type => {
- it(`renders title and button for renaming ${type}`, done => {
- const text = type === 'tree' ? 'folder' : 'file';
-
- vm.$store.state.entryModal.entry.type = type;
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.modal-title').textContent.trim()).toBe(`Rename ${text}`);
- expect(vm.$el.querySelector('.btn-success').textContent.trim()).toBe(`Rename ${text}`);
-
- done();
- });
- });
- });
-
- describe('entryName', () => {
- it('returns entries name', () => {
- expect(vm.entryName).toBe('test-path');
- });
-
- it('updated name', () => {
- vm.name = 'index.js';
-
- expect(vm.entryName).toBe('index.js');
- });
-
- it('removes leading/trailing spaces when found in the new name', () => {
- vm.entryName = ' index.js ';
-
- expect(vm.entryName).toBe('index.js');
- });
-
- it('does not remove internal spaces in the file name', () => {
- vm.entryName = ' In Praise of Idleness.txt ';
-
- expect(vm.entryName).toBe('In Praise of Idleness.txt');
- });
- });
- });
-
- describe('submitForm', () => {
- it('throws an error when target entry exists', () => {
- const store = createStore();
- store.state.entryModal = {
- type: 'rename',
- path: 'test-path/test',
- entry: {
- name: 'test',
- type: 'blob',
- path: 'test-path/test',
- },
- };
- store.state.entries = {
- 'test-path/test': {
- name: 'test',
- deleted: false,
- },
- };
-
- vm = createComponentWithStore(Component, store).$mount();
- const flashSpy = spyOnDependency(modal, 'flash');
-
- expect(flashSpy).not.toHaveBeenCalled();
-
- vm.submitForm();
-
- expect(flashSpy).toHaveBeenCalledWith(
- 'The name "test-path/test" is already taken in this directory.',
- 'alert',
- jasmine.anything(),
- null,
- false,
- true,
- );
- });
- });
-});
diff --git a/spec/javascripts/ide/components/new_dropdown/upload_spec.js b/spec/javascripts/ide/components/new_dropdown/upload_spec.js
deleted file mode 100644
index 66ddf6c0ee6..00000000000
--- a/spec/javascripts/ide/components/new_dropdown/upload_spec.js
+++ /dev/null
@@ -1,112 +0,0 @@
-import Vue from 'vue';
-import createComponent from 'spec/helpers/vue_mount_component_helper';
-import upload from '~/ide/components/new_dropdown/upload.vue';
-
-describe('new dropdown upload', () => {
- let vm;
-
- beforeEach(() => {
- const Component = Vue.extend(upload);
-
- vm = createComponent(Component, {
- path: '',
- });
-
- vm.entryName = 'testing';
-
- spyOn(vm, '$emit').and.callThrough();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('openFile', () => {
- it('calls for each file', () => {
- const files = ['test', 'test2', 'test3'];
-
- spyOn(vm, 'readFile');
- spyOnProperty(vm.$refs.fileUpload, 'files').and.returnValue(files);
-
- vm.openFile();
-
- expect(vm.readFile.calls.count()).toBe(3);
-
- files.forEach((file, i) => {
- expect(vm.readFile.calls.argsFor(i)).toEqual([file]);
- });
- });
- });
-
- describe('readFile', () => {
- beforeEach(() => {
- spyOn(FileReader.prototype, 'readAsDataURL');
- });
-
- it('calls readAsDataURL for all files', () => {
- const file = {
- type: 'images/png',
- };
-
- vm.readFile(file);
-
- expect(FileReader.prototype.readAsDataURL).toHaveBeenCalledWith(file);
- });
- });
-
- describe('createFile', () => {
- const textTarget = {
- result: 'base64,cGxhaW4gdGV4dA==',
- };
- const binaryTarget = {
- result: 'base64,w4I=',
- };
- const textFile = new File(['plain text'], 'textFile');
-
- const binaryFile = {
- name: 'binaryFile',
- type: 'image/png',
- };
-
- beforeEach(() => {
- spyOn(FileReader.prototype, 'readAsText').and.callThrough();
- });
-
- it('calls readAsText and creates file in plain text (without encoding) if the file content is plain text', done => {
- const waitForCreate = new Promise(resolve => vm.$on('create', resolve));
-
- vm.createFile(textTarget, textFile);
-
- expect(FileReader.prototype.readAsText).toHaveBeenCalledWith(textFile);
-
- waitForCreate
- .then(() => {
- expect(vm.$emit).toHaveBeenCalledWith('create', {
- name: textFile.name,
- type: 'blob',
- content: 'plain text',
- base64: false,
- binary: false,
- rawPath: '',
- });
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('splits content on base64 if binary', () => {
- vm.createFile(binaryTarget, binaryFile);
-
- expect(FileReader.prototype.readAsText).not.toHaveBeenCalledWith(textFile);
-
- expect(vm.$emit).toHaveBeenCalledWith('create', {
- name: binaryFile.name,
- type: 'blob',
- content: binaryTarget.result.split('base64,')[1],
- base64: true,
- binary: true,
- rawPath: binaryTarget.result,
- });
- });
- });
-});
diff --git a/spec/javascripts/ide/components/repo_editor_spec.js b/spec/javascripts/ide/components/repo_editor_spec.js
index ef0299f0d56..8db29011da7 100644
--- a/spec/javascripts/ide/components/repo_editor_spec.js
+++ b/spec/javascripts/ide/components/repo_editor_spec.js
@@ -26,7 +26,23 @@ describe('RepoEditor', () => {
f.active = true;
f.tempFile = true;
+
vm.$store.state.openFiles.push(f);
+ vm.$store.state.projects = {
+ 'gitlab-org/gitlab': {
+ branches: {
+ master: {
+ name: 'master',
+ commit: {
+ id: 'abcdefgh',
+ },
+ },
+ },
+ },
+ };
+ vm.$store.state.currentProjectId = 'gitlab-org/gitlab';
+ vm.$store.state.currentBranchId = 'master';
+
Vue.set(vm.$store.state.entries, f.path, f);
spyOn(vm, 'getFileData').and.returnValue(Promise.resolve());
@@ -46,11 +62,6 @@ describe('RepoEditor', () => {
});
const findEditor = () => vm.$el.querySelector('.multi-file-editor-holder');
- const changeRightPanelCollapsed = () => {
- const { state } = vm.$store;
-
- state.rightPanelCollapsed = !state.rightPanelCollapsed;
- };
it('sets renderWhitespace to `all`', () => {
vm.$store.state.renderWhitespaceInCode = true;
@@ -303,17 +314,6 @@ describe('RepoEditor', () => {
spyOn(vm.editor, 'updateDiffView');
});
- it('calls updateDimensions when rightPanelCollapsed is changed', done => {
- changeRightPanelCollapsed();
-
- vm.$nextTick(() => {
- expect(vm.editor.updateDimensions).toHaveBeenCalled();
- expect(vm.editor.updateDiffView).toHaveBeenCalled();
-
- done();
- });
- });
-
it('calls updateDimensions when panelResizing is false', done => {
vm.$store.state.panelResizing = true;
@@ -391,17 +391,6 @@ describe('RepoEditor', () => {
expect(findEditor()).toHaveCss({ display: 'none' });
});
- it('should not update dimensions', done => {
- changeRightPanelCollapsed();
-
- vm.$nextTick()
- .then(() => {
- expect(vm.editor.updateDimensions).not.toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
- });
-
describe('when file view mode changes to editor', () => {
beforeEach(done => {
vm.file.viewMode = FILE_VIEW_MODE_EDITOR;
diff --git a/spec/javascripts/ide/components/repo_tab_spec.js b/spec/javascripts/ide/components/repo_tab_spec.js
deleted file mode 100644
index 3b52f279bf2..00000000000
--- a/spec/javascripts/ide/components/repo_tab_spec.js
+++ /dev/null
@@ -1,185 +0,0 @@
-import Vue from 'vue';
-import store from '~/ide/stores';
-import repoTab from '~/ide/components/repo_tab.vue';
-import router from '~/ide/ide_router';
-import { file, resetStore } from '../helpers';
-
-describe('RepoTab', () => {
- let vm;
-
- function createComponent(propsData) {
- const RepoTab = Vue.extend(repoTab);
-
- return new RepoTab({
- store,
- propsData,
- }).$mount();
- }
-
- beforeEach(() => {
- spyOn(router, 'push');
- });
-
- afterEach(() => {
- vm.$destroy();
-
- resetStore(vm.$store);
- });
-
- it('renders a close link and a name link', () => {
- vm = createComponent({
- tab: file(),
- });
- vm.$store.state.openFiles.push(vm.tab);
- const close = vm.$el.querySelector('.multi-file-tab-close');
- const name = vm.$el.querySelector(`[title="${vm.tab.url}"]`);
-
- expect(close.innerHTML).toContain('#close');
- expect(name.textContent.trim()).toEqual(vm.tab.name);
- });
-
- it('does not call openPendingTab when tab is active', done => {
- vm = createComponent({
- tab: {
- ...file(),
- pending: true,
- active: true,
- },
- });
-
- spyOn(vm, 'openPendingTab');
-
- vm.$el.click();
-
- vm.$nextTick(() => {
- expect(vm.openPendingTab).not.toHaveBeenCalled();
-
- done();
- });
- });
-
- it('fires clickFile when the link is clicked', () => {
- vm = createComponent({
- tab: file(),
- });
-
- spyOn(vm, 'clickFile');
-
- vm.$el.click();
-
- expect(vm.clickFile).toHaveBeenCalledWith(vm.tab);
- });
-
- it('calls closeFile when clicking close button', () => {
- vm = createComponent({
- tab: file(),
- });
-
- spyOn(vm, 'closeFile');
-
- vm.$el.querySelector('.multi-file-tab-close').click();
-
- expect(vm.closeFile).toHaveBeenCalledWith(vm.tab);
- });
-
- it('changes icon on hover', done => {
- const tab = file();
- tab.changed = true;
- vm = createComponent({
- tab,
- });
-
- vm.$el.dispatchEvent(new Event('mouseover'));
-
- Vue.nextTick()
- .then(() => {
- expect(vm.$el.querySelector('.file-modified')).toBeNull();
-
- vm.$el.dispatchEvent(new Event('mouseout'));
- })
- .then(Vue.nextTick)
- .then(() => {
- expect(vm.$el.querySelector('.file-modified')).not.toBeNull();
-
- done();
- })
- .catch(done.fail);
- });
-
- describe('locked file', () => {
- let f;
-
- beforeEach(() => {
- f = file('locked file');
- f.file_lock = {
- user: {
- name: 'testuser',
- updated_at: new Date(),
- },
- };
-
- vm = createComponent({
- tab: f,
- });
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders lock icon', () => {
- expect(vm.$el.querySelector('.file-status-icon')).not.toBeNull();
- });
-
- it('renders a tooltip', () => {
- expect(vm.$el.querySelector('span:nth-child(2)').dataset.originalTitle).toContain(
- 'Locked by testuser',
- );
- });
- });
-
- describe('methods', () => {
- describe('closeTab', () => {
- it('closes tab if file has changed', done => {
- const tab = file();
- tab.changed = true;
- tab.opened = true;
- vm = createComponent({
- tab,
- });
- vm.$store.state.openFiles.push(tab);
- vm.$store.state.changedFiles.push(tab);
- vm.$store.state.entries[tab.path] = tab;
- vm.$store.dispatch('setFileActive', tab.path);
-
- vm.$el.querySelector('.multi-file-tab-close').click();
-
- vm.$nextTick(() => {
- expect(tab.opened).toBeFalsy();
- expect(vm.$store.state.changedFiles.length).toBe(1);
-
- done();
- });
- });
-
- it('closes tab when clicking close btn', done => {
- const tab = file('lose');
- tab.opened = true;
- vm = createComponent({
- tab,
- });
- vm.$store.state.openFiles.push(tab);
- vm.$store.state.entries[tab.path] = tab;
- vm.$store.dispatch('setFileActive', tab.path);
-
- vm.$el.querySelector('.multi-file-tab-close').click();
-
- vm.$nextTick(() => {
- expect(tab.opened).toBeFalsy();
-
- done();
- });
- });
- });
- });
-});
diff --git a/spec/javascripts/ide/components/repo_tabs_spec.js b/spec/javascripts/ide/components/repo_tabs_spec.js
deleted file mode 100644
index 583f71e6121..00000000000
--- a/spec/javascripts/ide/components/repo_tabs_spec.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import Vue from 'vue';
-import repoTabs from '~/ide/components/repo_tabs.vue';
-import createComponent from '../../helpers/vue_mount_component_helper';
-import { file } from '../helpers';
-
-describe('RepoTabs', () => {
- const openedFiles = [file('open1'), file('open2')];
- const RepoTabs = Vue.extend(repoTabs);
- let vm;
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders a list of tabs', done => {
- vm = createComponent(RepoTabs, {
- files: openedFiles,
- viewer: 'editor',
- hasChanges: false,
- activeFile: file('activeFile'),
- hasMergeRequest: false,
- });
- openedFiles[0].active = true;
-
- vm.$nextTick(() => {
- const tabs = [...vm.$el.querySelectorAll('.multi-file-tab')];
-
- expect(tabs.length).toEqual(2);
- expect(tabs[0].parentNode.classList.contains('active')).toEqual(true);
- expect(tabs[1].parentNode.classList.contains('active')).toEqual(false);
-
- done();
- });
- });
-});
diff --git a/spec/javascripts/ide/components/shared/tokened_input_spec.js b/spec/javascripts/ide/components/shared/tokened_input_spec.js
deleted file mode 100644
index 885fd976655..00000000000
--- a/spec/javascripts/ide/components/shared/tokened_input_spec.js
+++ /dev/null
@@ -1,133 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import TokenedInput from '~/ide/components/shared/tokened_input.vue';
-
-const TEST_PLACEHOLDER = 'Searching in test';
-const TEST_TOKENS = [
- { label: 'lorem', id: 1 },
- { label: 'ipsum', id: 2 },
- { label: 'dolar', id: 3 },
-];
-const TEST_VALUE = 'lorem';
-
-function getTokenElements(vm) {
- return Array.from(vm.$el.querySelectorAll('.filtered-search-token button'));
-}
-
-function createBackspaceEvent() {
- const e = new Event('keyup');
- e.keyCode = 8;
- e.which = e.keyCode;
- e.altKey = false;
- e.ctrlKey = true;
- e.shiftKey = false;
- e.metaKey = false;
- return e;
-}
-
-describe('IDE shared/TokenedInput', () => {
- const Component = Vue.extend(TokenedInput);
- let vm;
-
- beforeEach(() => {
- vm = mountComponent(Component, {
- tokens: TEST_TOKENS,
- placeholder: TEST_PLACEHOLDER,
- value: TEST_VALUE,
- });
-
- spyOn(vm, '$emit');
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders tokens', () => {
- const renderedTokens = getTokenElements(vm).map(x => x.textContent.trim());
-
- expect(renderedTokens).toEqual(TEST_TOKENS.map(x => x.label));
- });
-
- it('renders input', () => {
- expect(vm.$refs.input).toBeTruthy();
- expect(vm.$refs.input).toHaveValue(TEST_VALUE);
- });
-
- it('renders placeholder, when tokens are empty', done => {
- vm.tokens = [];
-
- vm.$nextTick()
- .then(() => {
- expect(vm.$refs.input).toHaveAttr('placeholder', TEST_PLACEHOLDER);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('triggers "removeToken" on token click', () => {
- getTokenElements(vm)[0].click();
-
- expect(vm.$emit).toHaveBeenCalledWith('removeToken', TEST_TOKENS[0]);
- });
-
- it('when input triggers backspace event, it calls "onBackspace"', () => {
- spyOn(vm, 'onBackspace');
-
- vm.$refs.input.dispatchEvent(createBackspaceEvent());
- vm.$refs.input.dispatchEvent(createBackspaceEvent());
-
- expect(vm.onBackspace).toHaveBeenCalledTimes(2);
- });
-
- it('triggers "removeToken" on backspaces when value is empty', () => {
- vm.value = '';
-
- vm.onBackspace();
-
- expect(vm.$emit).not.toHaveBeenCalled();
- expect(vm.backspaceCount).toEqual(1);
-
- vm.onBackspace();
-
- expect(vm.$emit).toHaveBeenCalledWith('removeToken', TEST_TOKENS[TEST_TOKENS.length - 1]);
- expect(vm.backspaceCount).toEqual(0);
- });
-
- it('does not trigger "removeToken" on backspaces when value is not empty', () => {
- vm.onBackspace();
- vm.onBackspace();
-
- expect(vm.backspaceCount).toEqual(0);
- expect(vm.$emit).not.toHaveBeenCalled();
- });
-
- it('does not trigger "removeToken" on backspaces when tokens are empty', () => {
- vm.tokens = [];
-
- vm.onBackspace();
- vm.onBackspace();
-
- expect(vm.backspaceCount).toEqual(0);
- expect(vm.$emit).not.toHaveBeenCalled();
- });
-
- it('triggers "focus" on input focus', () => {
- vm.$refs.input.dispatchEvent(new Event('focus'));
-
- expect(vm.$emit).toHaveBeenCalledWith('focus');
- });
-
- it('triggers "blur" on input blur', () => {
- vm.$refs.input.dispatchEvent(new Event('blur'));
-
- expect(vm.$emit).toHaveBeenCalledWith('blur');
- });
-
- it('triggers "input" with value on input change', () => {
- vm.$refs.input.value = 'something-else';
- vm.$refs.input.dispatchEvent(new Event('input'));
-
- expect(vm.$emit).toHaveBeenCalledWith('input', 'something-else');
- });
-});
diff --git a/spec/javascripts/ide/lib/common/model_manager_spec.js b/spec/javascripts/ide/lib/common/model_manager_spec.js
deleted file mode 100644
index 38ffa317e8e..00000000000
--- a/spec/javascripts/ide/lib/common/model_manager_spec.js
+++ /dev/null
@@ -1,126 +0,0 @@
-import eventHub from '~/ide/eventhub';
-import ModelManager from '~/ide/lib/common/model_manager';
-import { file } from '../../helpers';
-
-describe('Multi-file editor library model manager', () => {
- let instance;
-
- beforeEach(() => {
- instance = new ModelManager();
- });
-
- afterEach(() => {
- instance.dispose();
- });
-
- describe('addModel', () => {
- it('caches model', () => {
- instance.addModel(file());
-
- expect(instance.models.size).toBe(1);
- });
-
- it('caches model by file path', () => {
- const f = file('path-name');
- instance.addModel(f);
-
- expect(instance.models.keys().next().value).toBe(f.key);
- });
-
- it('adds model into disposable', () => {
- spyOn(instance.disposable, 'add').and.callThrough();
-
- instance.addModel(file());
-
- expect(instance.disposable.add).toHaveBeenCalled();
- });
-
- it('returns cached model', () => {
- spyOn(instance.models, 'get').and.callThrough();
-
- instance.addModel(file());
- instance.addModel(file());
-
- expect(instance.models.get).toHaveBeenCalled();
- });
-
- it('adds eventHub listener', () => {
- const f = file();
- spyOn(eventHub, '$on').and.callThrough();
-
- instance.addModel(f);
-
- expect(eventHub.$on).toHaveBeenCalledWith(
- `editor.update.model.dispose.${f.key}`,
- jasmine.anything(),
- );
- });
- });
-
- describe('hasCachedModel', () => {
- it('returns false when no models exist', () => {
- expect(instance.hasCachedModel('path')).toBeFalsy();
- });
-
- it('returns true when model exists', () => {
- const f = file('path-name');
-
- instance.addModel(f);
-
- expect(instance.hasCachedModel(f.key)).toBeTruthy();
- });
- });
-
- describe('getModel', () => {
- it('returns cached model', () => {
- instance.addModel(file('path-name'));
-
- expect(instance.getModel('path-name')).not.toBeNull();
- });
- });
-
- describe('removeCachedModel', () => {
- let f;
-
- beforeEach(() => {
- f = file();
-
- instance.addModel(f);
- });
-
- it('clears cached model', () => {
- instance.removeCachedModel(f);
-
- expect(instance.models.size).toBe(0);
- });
-
- it('removes eventHub listener', () => {
- spyOn(eventHub, '$off').and.callThrough();
-
- instance.removeCachedModel(f);
-
- expect(eventHub.$off).toHaveBeenCalledWith(
- `editor.update.model.dispose.${f.key}`,
- jasmine.anything(),
- );
- });
- });
-
- describe('dispose', () => {
- it('clears cached models', () => {
- instance.addModel(file());
-
- instance.dispose();
-
- expect(instance.models.size).toBe(0);
- });
-
- it('calls disposable dispose', () => {
- spyOn(instance.disposable, 'dispose').and.callThrough();
-
- instance.dispose();
-
- expect(instance.disposable.dispose).toHaveBeenCalled();
- });
- });
-});
diff --git a/spec/javascripts/ide/lib/common/model_spec.js b/spec/javascripts/ide/lib/common/model_spec.js
deleted file mode 100644
index f096e06f43c..00000000000
--- a/spec/javascripts/ide/lib/common/model_spec.js
+++ /dev/null
@@ -1,137 +0,0 @@
-import eventHub from '~/ide/eventhub';
-import Model from '~/ide/lib/common/model';
-import { file } from '../../helpers';
-
-describe('Multi-file editor library model', () => {
- let model;
-
- beforeEach(() => {
- spyOn(eventHub, '$on').and.callThrough();
-
- const f = file('path');
- f.mrChange = { diff: 'ABC' };
- f.baseRaw = 'test';
- model = new Model(f);
- });
-
- afterEach(() => {
- model.dispose();
- });
-
- it('creates original model & base model & new model', () => {
- expect(model.originalModel).not.toBeNull();
- expect(model.model).not.toBeNull();
- expect(model.baseModel).not.toBeNull();
-
- expect(model.originalModel.uri.path).toBe('original/path--path');
- expect(model.model.uri.path).toBe('path--path');
- expect(model.baseModel.uri.path).toBe('target/path--path');
- });
-
- it('creates model with head file to compare against', () => {
- const f = file('path');
- model.dispose();
-
- model = new Model(f, {
- ...f,
- content: '123 testing',
- });
-
- expect(model.head).not.toBeNull();
- expect(model.getOriginalModel().getValue()).toBe('123 testing');
- });
-
- it('adds eventHub listener', () => {
- expect(eventHub.$on).toHaveBeenCalledWith(
- `editor.update.model.dispose.${model.file.key}`,
- jasmine.anything(),
- );
- });
-
- describe('path', () => {
- it('returns file path', () => {
- expect(model.path).toBe(model.file.key);
- });
- });
-
- describe('getModel', () => {
- it('returns model', () => {
- expect(model.getModel()).toBe(model.model);
- });
- });
-
- describe('getOriginalModel', () => {
- it('returns original model', () => {
- expect(model.getOriginalModel()).toBe(model.originalModel);
- });
- });
-
- describe('getBaseModel', () => {
- it('returns base model', () => {
- expect(model.getBaseModel()).toBe(model.baseModel);
- });
- });
-
- describe('setValue', () => {
- it('updates models value', () => {
- model.setValue('testing 123');
-
- expect(model.getModel().getValue()).toBe('testing 123');
- });
- });
-
- describe('onChange', () => {
- it('calls callback on change', done => {
- const spy = jasmine.createSpy();
- model.onChange(spy);
-
- model.getModel().setValue('123');
-
- setTimeout(() => {
- expect(spy).toHaveBeenCalledWith(model, jasmine.anything());
- done();
- });
- });
- });
-
- describe('dispose', () => {
- it('calls disposable dispose', () => {
- spyOn(model.disposable, 'dispose').and.callThrough();
-
- model.dispose();
-
- expect(model.disposable.dispose).toHaveBeenCalled();
- });
-
- it('clears events', () => {
- model.onChange(() => {});
-
- expect(model.events.size).toBe(1);
-
- model.dispose();
-
- expect(model.events.size).toBe(0);
- });
-
- it('removes eventHub listener', () => {
- spyOn(eventHub, '$off').and.callThrough();
-
- model.dispose();
-
- expect(eventHub.$off).toHaveBeenCalledWith(
- `editor.update.model.dispose.${model.file.key}`,
- jasmine.anything(),
- );
- });
-
- it('calls onDispose callback', () => {
- const disposeSpy = jasmine.createSpy();
-
- model.onDispose(disposeSpy);
-
- model.dispose();
-
- expect(disposeSpy).toHaveBeenCalled();
- });
- });
-});
diff --git a/spec/javascripts/ide/lib/decorations/controller_spec.js b/spec/javascripts/ide/lib/decorations/controller_spec.js
deleted file mode 100644
index 4118774cca3..00000000000
--- a/spec/javascripts/ide/lib/decorations/controller_spec.js
+++ /dev/null
@@ -1,143 +0,0 @@
-import Editor from '~/ide/lib/editor';
-import DecorationsController from '~/ide/lib/decorations/controller';
-import Model from '~/ide/lib/common/model';
-import { file } from '../../helpers';
-
-describe('Multi-file editor library decorations controller', () => {
- let editorInstance;
- let controller;
- let model;
-
- beforeEach(() => {
- editorInstance = Editor.create();
- editorInstance.createInstance(document.createElement('div'));
-
- controller = new DecorationsController(editorInstance);
- model = new Model(file('path'));
- });
-
- afterEach(() => {
- model.dispose();
- editorInstance.dispose();
- controller.dispose();
- });
-
- describe('getAllDecorationsForModel', () => {
- it('returns empty array when no decorations exist for model', () => {
- const decorations = controller.getAllDecorationsForModel(model);
-
- expect(decorations).toEqual([]);
- });
-
- it('returns decorations by model URL', () => {
- controller.addDecorations(model, 'key', [{ decoration: 'decorationValue' }]);
-
- const decorations = controller.getAllDecorationsForModel(model);
-
- expect(decorations[0]).toEqual({ decoration: 'decorationValue' });
- });
- });
-
- describe('addDecorations', () => {
- it('caches decorations in a new map', () => {
- controller.addDecorations(model, 'key', [{ decoration: 'decorationValue' }]);
-
- expect(controller.decorations.size).toBe(1);
- });
-
- it('does not create new cache model', () => {
- controller.addDecorations(model, 'key', [{ decoration: 'decorationValue' }]);
- controller.addDecorations(model, 'key', [{ decoration: 'decorationValue2' }]);
-
- expect(controller.decorations.size).toBe(1);
- });
-
- it('caches decorations by model URL', () => {
- controller.addDecorations(model, 'key', [{ decoration: 'decorationValue' }]);
-
- expect(controller.decorations.size).toBe(1);
- expect(controller.decorations.keys().next().value).toBe('gitlab:path--path');
- });
-
- it('calls decorate method', () => {
- spyOn(controller, 'decorate');
-
- controller.addDecorations(model, 'key', [{ decoration: 'decorationValue' }]);
-
- expect(controller.decorate).toHaveBeenCalled();
- });
- });
-
- describe('decorate', () => {
- it('sets decorations on editor instance', () => {
- spyOn(controller.editor.instance, 'deltaDecorations');
-
- controller.decorate(model);
-
- expect(controller.editor.instance.deltaDecorations).toHaveBeenCalledWith([], []);
- });
-
- it('caches decorations', () => {
- spyOn(controller.editor.instance, 'deltaDecorations').and.returnValue([]);
-
- controller.decorate(model);
-
- expect(controller.editorDecorations.size).toBe(1);
- });
-
- it('caches decorations by model URL', () => {
- spyOn(controller.editor.instance, 'deltaDecorations').and.returnValue([]);
-
- controller.decorate(model);
-
- expect(controller.editorDecorations.keys().next().value).toBe('gitlab:path--path');
- });
- });
-
- describe('dispose', () => {
- it('clears cached decorations', () => {
- controller.addDecorations(model, 'key', [{ decoration: 'decorationValue' }]);
-
- controller.dispose();
-
- expect(controller.decorations.size).toBe(0);
- });
-
- it('clears cached editorDecorations', () => {
- controller.addDecorations(model, 'key', [{ decoration: 'decorationValue' }]);
-
- controller.dispose();
-
- expect(controller.editorDecorations.size).toBe(0);
- });
- });
-
- describe('hasDecorations', () => {
- it('returns true when decorations are cached', () => {
- controller.addDecorations(model, 'key', [{ decoration: 'decorationValue' }]);
-
- expect(controller.hasDecorations(model)).toBe(true);
- });
-
- it('returns false when no model decorations exist', () => {
- expect(controller.hasDecorations(model)).toBe(false);
- });
- });
-
- describe('removeDecorations', () => {
- beforeEach(() => {
- controller.addDecorations(model, 'key', [{ decoration: 'decorationValue' }]);
- controller.decorate(model);
- });
-
- it('removes cached decorations', () => {
- expect(controller.decorations.size).not.toBe(0);
- expect(controller.editorDecorations.size).not.toBe(0);
-
- controller.removeDecorations(model);
-
- expect(controller.decorations.size).toBe(0);
- expect(controller.editorDecorations.size).toBe(0);
- });
- });
-});
diff --git a/spec/javascripts/ide/lib/diff/controller_spec.js b/spec/javascripts/ide/lib/diff/controller_spec.js
deleted file mode 100644
index 90ebb95b687..00000000000
--- a/spec/javascripts/ide/lib/diff/controller_spec.js
+++ /dev/null
@@ -1,215 +0,0 @@
-import { Range } from 'monaco-editor';
-import Editor from '~/ide/lib/editor';
-import ModelManager from '~/ide/lib/common/model_manager';
-import DecorationsController from '~/ide/lib/decorations/controller';
-import DirtyDiffController, { getDiffChangeType, getDecorator } from '~/ide/lib/diff/controller';
-import { computeDiff } from '~/ide/lib/diff/diff';
-import { file } from '../../helpers';
-
-describe('Multi-file editor library dirty diff controller', () => {
- let editorInstance;
- let controller;
- let modelManager;
- let decorationsController;
- let model;
-
- beforeEach(() => {
- editorInstance = Editor.create();
- editorInstance.createInstance(document.createElement('div'));
-
- modelManager = new ModelManager();
- decorationsController = new DecorationsController(editorInstance);
-
- model = modelManager.addModel(file('path'));
-
- controller = new DirtyDiffController(modelManager, decorationsController);
- });
-
- afterEach(() => {
- controller.dispose();
- model.dispose();
- decorationsController.dispose();
- editorInstance.dispose();
- });
-
- describe('getDiffChangeType', () => {
- ['added', 'removed', 'modified'].forEach(type => {
- it(`returns ${type}`, () => {
- const change = {
- [type]: true,
- };
-
- expect(getDiffChangeType(change)).toBe(type);
- });
- });
- });
-
- describe('getDecorator', () => {
- ['added', 'removed', 'modified'].forEach(type => {
- it(`returns with linesDecorationsClassName for ${type}`, () => {
- const change = {
- [type]: true,
- };
-
- expect(getDecorator(change).options.linesDecorationsClassName).toBe(
- `dirty-diff dirty-diff-${type}`,
- );
- });
-
- it('returns with line numbers', () => {
- const change = {
- lineNumber: 1,
- endLineNumber: 2,
- [type]: true,
- };
-
- const { range } = getDecorator(change);
-
- expect(range.startLineNumber).toBe(1);
- expect(range.endLineNumber).toBe(2);
- expect(range.startColumn).toBe(1);
- expect(range.endColumn).toBe(1);
- });
- });
- });
-
- describe('attachModel', () => {
- it('adds change event callback', () => {
- spyOn(model, 'onChange');
-
- controller.attachModel(model);
-
- expect(model.onChange).toHaveBeenCalled();
- });
-
- it('adds dispose event callback', () => {
- spyOn(model, 'onDispose');
-
- controller.attachModel(model);
-
- expect(model.onDispose).toHaveBeenCalled();
- });
-
- it('calls throttledComputeDiff on change', () => {
- spyOn(controller, 'throttledComputeDiff');
-
- controller.attachModel(model);
-
- model.getModel().setValue('123');
-
- expect(controller.throttledComputeDiff).toHaveBeenCalled();
- });
-
- it('caches model', () => {
- controller.attachModel(model);
-
- expect(controller.models.has(model.url)).toBe(true);
- });
- });
-
- describe('computeDiff', () => {
- it('posts to worker', () => {
- spyOn(controller.dirtyDiffWorker, 'postMessage');
-
- controller.computeDiff(model);
-
- expect(controller.dirtyDiffWorker.postMessage).toHaveBeenCalledWith({
- path: model.path,
- originalContent: '',
- newContent: '',
- });
- });
- });
-
- describe('reDecorate', () => {
- it('calls computeDiff when no decorations are cached', () => {
- spyOn(controller, 'computeDiff');
-
- controller.reDecorate(model);
-
- expect(controller.computeDiff).toHaveBeenCalledWith(model);
- });
-
- it('calls decorate when decorations are cached', () => {
- spyOn(controller.decorationsController, 'decorate');
-
- controller.decorationsController.decorations.set(model.url, 'test');
-
- controller.reDecorate(model);
-
- expect(controller.decorationsController.decorate).toHaveBeenCalledWith(model);
- });
- });
-
- describe('decorate', () => {
- it('adds decorations into decorations controller', () => {
- spyOn(controller.decorationsController, 'addDecorations');
-
- controller.decorate({ data: { changes: [], path: model.path } });
-
- expect(controller.decorationsController.addDecorations).toHaveBeenCalledWith(
- model,
- 'dirtyDiff',
- jasmine.anything(),
- );
- });
-
- it('adds decorations into editor', () => {
- const spy = spyOn(controller.decorationsController.editor.instance, 'deltaDecorations');
-
- controller.decorate({
- data: { changes: computeDiff('123', '1234'), path: model.path },
- });
-
- expect(spy).toHaveBeenCalledWith(
- [],
- [
- {
- range: new Range(1, 1, 1, 1),
- options: {
- isWholeLine: true,
- linesDecorationsClassName: 'dirty-diff dirty-diff-modified',
- },
- },
- ],
- );
- });
- });
-
- describe('dispose', () => {
- it('calls disposable dispose', () => {
- spyOn(controller.disposable, 'dispose').and.callThrough();
-
- controller.dispose();
-
- expect(controller.disposable.dispose).toHaveBeenCalled();
- });
-
- it('terminates worker', () => {
- spyOn(controller.dirtyDiffWorker, 'terminate').and.callThrough();
-
- controller.dispose();
-
- expect(controller.dirtyDiffWorker.terminate).toHaveBeenCalled();
- });
-
- it('removes worker event listener', () => {
- spyOn(controller.dirtyDiffWorker, 'removeEventListener').and.callThrough();
-
- controller.dispose();
-
- expect(controller.dirtyDiffWorker.removeEventListener).toHaveBeenCalledWith(
- 'message',
- jasmine.anything(),
- );
- });
-
- it('clears cached models', () => {
- controller.attachModel(model);
-
- model.dispose();
-
- expect(controller.models.size).toBe(0);
- });
- });
-});
diff --git a/spec/javascripts/ide/lib/editor_spec.js b/spec/javascripts/ide/lib/editor_spec.js
deleted file mode 100644
index 556bd45d3a5..00000000000
--- a/spec/javascripts/ide/lib/editor_spec.js
+++ /dev/null
@@ -1,287 +0,0 @@
-import { editor as monacoEditor } from 'monaco-editor';
-import Editor from '~/ide/lib/editor';
-import { file } from '../helpers';
-
-describe('Multi-file editor library', () => {
- let instance;
- let el;
- let holder;
-
- beforeEach(() => {
- el = document.createElement('div');
- holder = document.createElement('div');
- el.appendChild(holder);
-
- document.body.appendChild(el);
-
- instance = Editor.create();
- });
-
- afterEach(() => {
- instance.dispose();
-
- el.remove();
- });
-
- it('creates instance of editor', () => {
- expect(Editor.editorInstance).not.toBeNull();
- });
-
- it('creates instance returns cached instance', () => {
- expect(Editor.create()).toEqual(instance);
- });
-
- describe('createInstance', () => {
- it('creates editor instance', () => {
- spyOn(monacoEditor, 'create').and.callThrough();
-
- instance.createInstance(holder);
-
- expect(monacoEditor.create).toHaveBeenCalled();
- });
-
- it('creates dirty diff controller', () => {
- instance.createInstance(holder);
-
- expect(instance.dirtyDiffController).not.toBeNull();
- });
-
- it('creates model manager', () => {
- instance.createInstance(holder);
-
- expect(instance.modelManager).not.toBeNull();
- });
- });
-
- describe('createDiffInstance', () => {
- it('creates editor instance', () => {
- spyOn(monacoEditor, 'createDiffEditor').and.callThrough();
-
- instance.createDiffInstance(holder);
-
- expect(monacoEditor.createDiffEditor).toHaveBeenCalledWith(holder, {
- model: null,
- contextmenu: true,
- minimap: {
- enabled: false,
- },
- readOnly: true,
- scrollBeyondLastLine: false,
- renderWhitespace: 'none',
- quickSuggestions: false,
- occurrencesHighlight: false,
- wordWrap: 'on',
- renderSideBySide: true,
- renderLineHighlight: 'all',
- hideCursorInOverviewRuler: false,
- theme: 'vs white',
- });
- });
- });
-
- describe('createModel', () => {
- it('calls model manager addModel', () => {
- spyOn(instance.modelManager, 'addModel');
-
- instance.createModel('FILE');
-
- expect(instance.modelManager.addModel).toHaveBeenCalledWith('FILE', null);
- });
- });
-
- describe('attachModel', () => {
- let model;
-
- beforeEach(() => {
- instance.createInstance(document.createElement('div'));
-
- model = instance.createModel(file());
- });
-
- it('sets the current model on the instance', () => {
- instance.attachModel(model);
-
- expect(instance.currentModel).toBe(model);
- });
-
- it('attaches the model to the current instance', () => {
- spyOn(instance.instance, 'setModel');
-
- instance.attachModel(model);
-
- expect(instance.instance.setModel).toHaveBeenCalledWith(model.getModel());
- });
-
- it('sets original & modified when diff editor', () => {
- spyOn(instance.instance, 'getEditorType').and.returnValue('vs.editor.IDiffEditor');
- spyOn(instance.instance, 'setModel');
-
- instance.attachModel(model);
-
- expect(instance.instance.setModel).toHaveBeenCalledWith({
- original: model.getOriginalModel(),
- modified: model.getModel(),
- });
- });
-
- it('attaches the model to the dirty diff controller', () => {
- spyOn(instance.dirtyDiffController, 'attachModel');
-
- instance.attachModel(model);
-
- expect(instance.dirtyDiffController.attachModel).toHaveBeenCalledWith(model);
- });
-
- it('re-decorates with the dirty diff controller', () => {
- spyOn(instance.dirtyDiffController, 'reDecorate');
-
- instance.attachModel(model);
-
- expect(instance.dirtyDiffController.reDecorate).toHaveBeenCalledWith(model);
- });
- });
-
- describe('attachMergeRequestModel', () => {
- let model;
-
- beforeEach(() => {
- instance.createDiffInstance(document.createElement('div'));
-
- const f = file();
- f.mrChanges = { diff: 'ABC' };
- f.baseRaw = 'testing';
-
- model = instance.createModel(f);
- });
-
- it('sets original & modified', () => {
- spyOn(instance.instance, 'setModel');
-
- instance.attachMergeRequestModel(model);
-
- expect(instance.instance.setModel).toHaveBeenCalledWith({
- original: model.getBaseModel(),
- modified: model.getModel(),
- });
- });
- });
-
- describe('clearEditor', () => {
- it('resets the editor model', () => {
- instance.createInstance(document.createElement('div'));
-
- spyOn(instance.instance, 'setModel');
-
- instance.clearEditor();
-
- expect(instance.instance.setModel).toHaveBeenCalledWith(null);
- });
- });
-
- describe('dispose', () => {
- it('calls disposble dispose method', () => {
- spyOn(instance.disposable, 'dispose').and.callThrough();
-
- instance.dispose();
-
- expect(instance.disposable.dispose).toHaveBeenCalled();
- });
-
- it('resets instance', () => {
- instance.createInstance(document.createElement('div'));
-
- expect(instance.instance).not.toBeNull();
-
- instance.dispose();
-
- expect(instance.instance).toBeNull();
- });
-
- it('does not dispose modelManager', () => {
- spyOn(instance.modelManager, 'dispose');
-
- instance.dispose();
-
- expect(instance.modelManager.dispose).not.toHaveBeenCalled();
- });
-
- it('does not dispose decorationsController', () => {
- spyOn(instance.decorationsController, 'dispose');
-
- instance.dispose();
-
- expect(instance.decorationsController.dispose).not.toHaveBeenCalled();
- });
- });
-
- describe('updateDiffView', () => {
- describe('edit mode', () => {
- it('does not update options', () => {
- instance.createInstance(holder);
-
- spyOn(instance.instance, 'updateOptions');
-
- instance.updateDiffView();
-
- expect(instance.instance.updateOptions).not.toHaveBeenCalled();
- });
- });
-
- describe('diff mode', () => {
- beforeEach(() => {
- instance.createDiffInstance(holder);
-
- spyOn(instance.instance, 'updateOptions').and.callThrough();
- });
-
- it('sets renderSideBySide to false if el is less than 700 pixels', () => {
- spyOnProperty(instance.instance.getDomNode(), 'offsetWidth').and.returnValue(600);
-
- expect(instance.instance.updateOptions).not.toHaveBeenCalledWith({
- renderSideBySide: false,
- });
- });
-
- it('sets renderSideBySide to false if el is more than 700 pixels', () => {
- spyOnProperty(instance.instance.getDomNode(), 'offsetWidth').and.returnValue(800);
-
- expect(instance.instance.updateOptions).not.toHaveBeenCalledWith({
- renderSideBySide: true,
- });
- });
- });
- });
-
- describe('isDiffEditorType', () => {
- it('returns true when diff editor', () => {
- instance.createDiffInstance(holder);
-
- expect(instance.isDiffEditorType).toBe(true);
- });
-
- it('returns false when not diff editor', () => {
- instance.createInstance(holder);
-
- expect(instance.isDiffEditorType).toBe(false);
- });
- });
-
- it('sets quickSuggestions to false when language is markdown', () => {
- instance.createInstance(holder);
-
- spyOn(instance.instance, 'updateOptions').and.callThrough();
-
- const model = instance.createModel({
- ...file(),
- key: 'index.md',
- path: 'index.md',
- });
-
- instance.attachModel(model);
-
- expect(instance.instance.updateOptions).toHaveBeenCalledWith({
- readOnly: false,
- quickSuggestions: false,
- });
- });
-});
diff --git a/spec/javascripts/ide/stores/actions/tree_spec.js b/spec/javascripts/ide/stores/actions/tree_spec.js
index fabe44ce333..2201a3b4b57 100644
--- a/spec/javascripts/ide/stores/actions/tree_spec.js
+++ b/spec/javascripts/ide/stores/actions/tree_spec.js
@@ -30,6 +30,7 @@ describe('Multi-file store tree actions', () => {
store.state.currentBranchId = 'master';
store.state.projects.abcproject = {
web_url: '',
+ path_with_namespace: 'foo/abcproject',
};
});
@@ -57,7 +58,7 @@ describe('Multi-file store tree actions', () => {
store
.dispatch('getFiles', basicCallParameters)
.then(() => {
- expect(service.getFiles).toHaveBeenCalledWith('', '12345678');
+ expect(service.getFiles).toHaveBeenCalledWith('foo/abcproject', '12345678');
done();
})
diff --git a/spec/javascripts/image_diff/helpers/badge_helper_spec.js b/spec/javascripts/image_diff/helpers/badge_helper_spec.js
deleted file mode 100644
index b3001d45e3c..00000000000
--- a/spec/javascripts/image_diff/helpers/badge_helper_spec.js
+++ /dev/null
@@ -1,130 +0,0 @@
-import * as badgeHelper from '~/image_diff/helpers/badge_helper';
-import * as mockData from '../mock_data';
-
-describe('badge helper', () => {
- const { coordinate, noteId, badgeText, badgeNumber } = mockData;
- let containerEl;
- let buttonEl;
-
- beforeEach(() => {
- containerEl = document.createElement('div');
- });
-
- describe('createImageBadge', () => {
- beforeEach(() => {
- buttonEl = badgeHelper.createImageBadge(noteId, coordinate);
- });
-
- it('should create button', () => {
- expect(buttonEl.tagName).toEqual('BUTTON');
- expect(buttonEl.getAttribute('type')).toEqual('button');
- });
-
- it('should set disabled attribute', () => {
- expect(buttonEl.hasAttribute('disabled')).toEqual(true);
- });
-
- it('should set noteId', () => {
- expect(buttonEl.dataset.noteId).toEqual(noteId);
- });
-
- it('should set coordinate', () => {
- expect(buttonEl.style.left).toEqual(`${coordinate.x}px`);
- expect(buttonEl.style.top).toEqual(`${coordinate.y}px`);
- });
-
- describe('classNames', () => {
- it('should set .js-image-badge by default', () => {
- expect(buttonEl.className).toEqual('js-image-badge');
- });
-
- it('should add additional class names if parameter is passed', () => {
- const classNames = ['first-class', 'second-class'];
- buttonEl = badgeHelper.createImageBadge(noteId, coordinate, classNames);
-
- expect(buttonEl.className).toEqual(classNames.concat('js-image-badge').join(' '));
- });
- });
- });
-
- describe('addImageBadge', () => {
- beforeEach(() => {
- badgeHelper.addImageBadge(containerEl, {
- coordinate,
- badgeText,
- noteId,
- });
- buttonEl = containerEl.querySelector('button');
- });
-
- it('should appends button to container', () => {
- expect(buttonEl).toBeDefined();
- });
-
- it('should add badge classes', () => {
- expect(buttonEl.className).toContain('badge badge-pill');
- });
-
- it('should set the badge text', () => {
- expect(buttonEl.innerText).toEqual(badgeText);
- });
-
- it('should set the button coordinates', () => {
- expect(buttonEl.style.left).toEqual(`${coordinate.x}px`);
- expect(buttonEl.style.top).toEqual(`${coordinate.y}px`);
- });
-
- it('should set the button noteId', () => {
- expect(buttonEl.dataset.noteId).toEqual(noteId);
- });
- });
-
- describe('addImageCommentBadge', () => {
- beforeEach(() => {
- badgeHelper.addImageCommentBadge(containerEl, {
- coordinate,
- noteId,
- });
- buttonEl = containerEl.querySelector('button');
- });
-
- it('should append icon button to container', () => {
- expect(buttonEl).toBeDefined();
- });
-
- it('should create icon comment button', () => {
- const iconEl = buttonEl.querySelector('svg');
-
- expect(iconEl).toBeDefined();
- });
- });
-
- describe('addAvatarBadge', () => {
- let avatarBadgeEl;
-
- beforeEach(() => {
- containerEl.innerHTML = `
- <div id="${noteId}">
- <div class="badge hidden">
- </div>
- </div>
- `;
-
- badgeHelper.addAvatarBadge(containerEl, {
- detail: {
- noteId,
- badgeNumber,
- },
- });
- avatarBadgeEl = containerEl.querySelector(`#${noteId} .badge`);
- });
-
- it('should update badge number', () => {
- expect(avatarBadgeEl.innerText).toEqual(badgeNumber.toString());
- });
-
- it('should remove hidden class', () => {
- expect(avatarBadgeEl.classList.contains('hidden')).toEqual(false);
- });
- });
-});
diff --git a/spec/javascripts/image_diff/helpers/comment_indicator_helper_spec.js b/spec/javascripts/image_diff/helpers/comment_indicator_helper_spec.js
deleted file mode 100644
index 8e3e7f1222e..00000000000
--- a/spec/javascripts/image_diff/helpers/comment_indicator_helper_spec.js
+++ /dev/null
@@ -1,144 +0,0 @@
-import * as commentIndicatorHelper from '~/image_diff/helpers/comment_indicator_helper';
-import * as mockData from '../mock_data';
-
-describe('commentIndicatorHelper', () => {
- const { coordinate } = mockData;
- let containerEl;
-
- beforeEach(() => {
- containerEl = document.createElement('div');
- });
-
- describe('addCommentIndicator', () => {
- let buttonEl;
-
- beforeEach(() => {
- commentIndicatorHelper.addCommentIndicator(containerEl, coordinate);
- buttonEl = containerEl.querySelector('button');
- });
-
- it('should append button to container', () => {
- expect(buttonEl).toBeDefined();
- });
-
- describe('button', () => {
- it('should set coordinate', () => {
- expect(buttonEl.style.left).toEqual(`${coordinate.x}px`);
- expect(buttonEl.style.top).toEqual(`${coordinate.y}px`);
- });
-
- it('should contain image-comment-dark svg', () => {
- const svgEl = buttonEl.querySelector('svg');
-
- expect(svgEl).toBeDefined();
-
- const svgLink = svgEl.querySelector('use').getAttribute('xlink:href');
-
- expect(svgLink.indexOf('image-comment-dark')).not.toBe(-1);
- });
- });
- });
-
- describe('removeCommentIndicator', () => {
- it('should return removed false if there is no comment-indicator', () => {
- const result = commentIndicatorHelper.removeCommentIndicator(containerEl);
-
- expect(result.removed).toEqual(false);
- });
-
- describe('has comment indicator', () => {
- let result;
-
- beforeEach(() => {
- containerEl.innerHTML = `
- <div class="comment-indicator" style="left:${coordinate.x}px; top: ${coordinate.y}px;">
- <img src="${gl.TEST_HOST}/image.png">
- </div>
- `;
- result = commentIndicatorHelper.removeCommentIndicator(containerEl);
- });
-
- it('should remove comment indicator', () => {
- expect(containerEl.querySelector('.comment-indicator')).toBeNull();
- });
-
- it('should return removed true', () => {
- expect(result.removed).toEqual(true);
- });
-
- it('should return indicator meta', () => {
- expect(result.x).toEqual(coordinate.x);
- expect(result.y).toEqual(coordinate.y);
- expect(result.image).toBeDefined();
- expect(result.image.width).toBeDefined();
- expect(result.image.height).toBeDefined();
- });
- });
- });
-
- describe('showCommentIndicator', () => {
- describe('commentIndicator exists', () => {
- beforeEach(() => {
- containerEl.innerHTML = `
- <button class="comment-indicator"></button>
- `;
- commentIndicatorHelper.showCommentIndicator(containerEl, coordinate);
- });
-
- it('should set commentIndicator coordinates', () => {
- const commentIndicatorEl = containerEl.querySelector('.comment-indicator');
-
- expect(commentIndicatorEl.style.left).toEqual(`${coordinate.x}px`);
- expect(commentIndicatorEl.style.top).toEqual(`${coordinate.y}px`);
- });
- });
-
- describe('commentIndicator does not exist', () => {
- beforeEach(() => {
- commentIndicatorHelper.showCommentIndicator(containerEl, coordinate);
- });
-
- it('should addCommentIndicator', () => {
- const buttonEl = containerEl.querySelector('.comment-indicator');
-
- expect(buttonEl).toBeDefined();
- expect(buttonEl.style.left).toEqual(`${coordinate.x}px`);
- expect(buttonEl.style.top).toEqual(`${coordinate.y}px`);
- });
- });
- });
-
- describe('commentIndicatorOnClick', () => {
- let event;
- let textAreaEl;
-
- beforeEach(() => {
- containerEl.innerHTML = `
- <div class="diff-viewer">
- <button></button>
- <div class="note-container">
- <textarea class="note-textarea"></textarea>
- </div>
- </div>
- `;
- textAreaEl = containerEl.querySelector('textarea');
-
- event = {
- stopPropagation: () => {},
- currentTarget: containerEl.querySelector('button'),
- };
-
- spyOn(event, 'stopPropagation');
- spyOn(textAreaEl, 'focus');
- commentIndicatorHelper.commentIndicatorOnClick(event);
- });
-
- it('should stopPropagation', () => {
- expect(event.stopPropagation).toHaveBeenCalled();
- });
-
- it('should focus textAreaEl', () => {
- expect(textAreaEl.focus).toHaveBeenCalled();
- });
- });
-});
diff --git a/spec/javascripts/image_diff/helpers/dom_helper_spec.js b/spec/javascripts/image_diff/helpers/dom_helper_spec.js
deleted file mode 100644
index ffe712af2dd..00000000000
--- a/spec/javascripts/image_diff/helpers/dom_helper_spec.js
+++ /dev/null
@@ -1,120 +0,0 @@
-import * as domHelper from '~/image_diff/helpers/dom_helper';
-import * as mockData from '../mock_data';
-
-describe('domHelper', () => {
- const { imageMeta, badgeNumber } = mockData;
-
- describe('setPositionDataAttribute', () => {
- let containerEl;
- let attributeAfterCall;
- const position = {
- myProperty: 'myProperty',
- };
-
- beforeEach(() => {
- containerEl = document.createElement('div');
- containerEl.dataset.position = JSON.stringify(position);
- domHelper.setPositionDataAttribute(containerEl, imageMeta);
- attributeAfterCall = JSON.parse(containerEl.dataset.position);
- });
-
- it('should set x, y, width, height', () => {
- expect(attributeAfterCall.x).toEqual(imageMeta.x);
- expect(attributeAfterCall.y).toEqual(imageMeta.y);
- expect(attributeAfterCall.width).toEqual(imageMeta.width);
- expect(attributeAfterCall.height).toEqual(imageMeta.height);
- });
-
- it('should not override other properties', () => {
- expect(attributeAfterCall.myProperty).toEqual('myProperty');
- });
- });
-
- describe('updateDiscussionAvatarBadgeNumber', () => {
- let discussionEl;
-
- beforeEach(() => {
- discussionEl = document.createElement('div');
- discussionEl.innerHTML = `
- <a href="#" class="image-diff-avatar-link">
- <div class="badge"></div>
- </a>
- `;
- domHelper.updateDiscussionAvatarBadgeNumber(discussionEl, badgeNumber);
- });
-
- it('should update avatar badge number', () => {
- expect(discussionEl.querySelector('.badge').innerText).toEqual(badgeNumber.toString());
- });
- });
-
- describe('updateDiscussionBadgeNumber', () => {
- let discussionEl;
-
- beforeEach(() => {
- discussionEl = document.createElement('div');
- discussionEl.innerHTML = `
- <div class="badge"></div>
- `;
- domHelper.updateDiscussionBadgeNumber(discussionEl, badgeNumber);
- });
-
- it('should update discussion badge number', () => {
- expect(discussionEl.querySelector('.badge').innerText).toEqual(badgeNumber.toString());
- });
- });
-
- describe('toggleCollapsed', () => {
- let element;
- let discussionNotesEl;
-
- beforeEach(() => {
- element = document.createElement('div');
- element.innerHTML = `
- <div class="discussion-notes">
- <button></button>
- <form class="discussion-form"></form>
- </div>
- `;
- discussionNotesEl = element.querySelector('.discussion-notes');
- });
-
- describe('not collapsed', () => {
- beforeEach(() => {
- domHelper.toggleCollapsed({
- currentTarget: element.querySelector('button'),
- });
- });
-
- it('should add collapsed class', () => {
- expect(discussionNotesEl.classList.contains('collapsed')).toEqual(true);
- });
-
- it('should force formEl to display none', () => {
- const formEl = element.querySelector('.discussion-form');
-
- expect(formEl.style.display).toEqual('none');
- });
- });
-
- describe('collapsed', () => {
- beforeEach(() => {
- discussionNotesEl.classList.add('collapsed');
-
- domHelper.toggleCollapsed({
- currentTarget: element.querySelector('button'),
- });
- });
-
- it('should remove collapsed class', () => {
- expect(discussionNotesEl.classList.contains('collapsed')).toEqual(false);
- });
-
- it('should force formEl to display block', () => {
- const formEl = element.querySelector('.discussion-form');
-
- expect(formEl.style.display).toEqual('block');
- });
- });
- });
-});
diff --git a/spec/javascripts/image_diff/helpers/utils_helper_spec.js b/spec/javascripts/image_diff/helpers/utils_helper_spec.js
deleted file mode 100644
index 3b6378be883..00000000000
--- a/spec/javascripts/image_diff/helpers/utils_helper_spec.js
+++ /dev/null
@@ -1,152 +0,0 @@
-import * as utilsHelper from '~/image_diff/helpers/utils_helper';
-import ImageBadge from '~/image_diff/image_badge';
-import * as mockData from '../mock_data';
-
-describe('utilsHelper', () => {
- const { noteId, discussionId, image, imageProperties, imageMeta } = mockData;
-
- describe('resizeCoordinatesToImageElement', () => {
- let result;
-
- beforeEach(() => {
- result = utilsHelper.resizeCoordinatesToImageElement(image, imageMeta);
- });
-
- it('should return x based on widthRatio', () => {
- expect(result.x).toEqual(imageMeta.x * 0.5);
- });
-
- it('should return y based on heightRatio', () => {
- expect(result.y).toEqual(imageMeta.y * 0.5);
- });
-
- it('should return image width', () => {
- expect(result.width).toEqual(image.width);
- });
-
- it('should return image height', () => {
- expect(result.height).toEqual(image.height);
- });
- });
-
- describe('generateBadgeFromDiscussionDOM', () => {
- let discussionEl;
- let result;
-
- beforeEach(() => {
- const imageFrameEl = document.createElement('div');
- imageFrameEl.innerHTML = `
- <img src="${gl.TEST_HOST}/image.png">
- `;
- discussionEl = document.createElement('div');
- discussionEl.dataset.discussionId = discussionId;
- discussionEl.innerHTML = `
- <div class="note" id="${noteId}"></div>
- `;
- discussionEl.dataset.position = JSON.stringify(imageMeta);
- result = utilsHelper.generateBadgeFromDiscussionDOM(imageFrameEl, discussionEl);
- });
-
- it('should return actual image properties', () => {
- const { actual } = result;
-
- expect(actual.x).toEqual(imageMeta.x);
- expect(actual.y).toEqual(imageMeta.y);
- expect(actual.width).toEqual(imageMeta.width);
- expect(actual.height).toEqual(imageMeta.height);
- });
-
- it('should return browser image properties', () => {
- const { browser } = result;
-
- expect(browser.x).toBeDefined();
- expect(browser.y).toBeDefined();
- expect(browser.width).toBeDefined();
- expect(browser.height).toBeDefined();
- });
-
- it('should return instance of ImageBadge', () => {
- expect(result instanceof ImageBadge).toEqual(true);
- });
-
- it('should return noteId', () => {
- expect(result.noteId).toEqual(noteId);
- });
-
- it('should return discussionId', () => {
- expect(result.discussionId).toEqual(discussionId);
- });
- });
-
- describe('getTargetSelection', () => {
- let containerEl;
-
- beforeEach(() => {
- containerEl = {
- querySelector: () => imageProperties,
- };
- });
-
- function generateEvent(offsetX, offsetY) {
- return {
- currentTarget: containerEl,
- offsetX,
- offsetY,
- };
- }
-
- it('should return browser properties', () => {
- const event = generateEvent(25, 25);
- const result = utilsHelper.getTargetSelection(event);
-
- const { browser } = result;
-
- expect(browser.x).toEqual(event.offsetX);
- expect(browser.y).toEqual(event.offsetY);
- expect(browser.width).toEqual(imageProperties.width);
- expect(browser.height).toEqual(imageProperties.height);
- });
-
- it('should return resized actual image properties', () => {
- const event = generateEvent(50, 50);
- const result = utilsHelper.getTargetSelection(event);
-
- const { actual } = result;
-
- expect(actual.x).toEqual(100);
- expect(actual.y).toEqual(100);
- expect(actual.width).toEqual(imageProperties.naturalWidth);
- expect(actual.height).toEqual(imageProperties.naturalHeight);
- });
-
- describe('normalize coordinates', () => {
- it('should return x = 0 if x < 0', () => {
- const event = generateEvent(-5, 50);
- const result = utilsHelper.getTargetSelection(event);
-
- expect(result.browser.x).toEqual(0);
- });
-
- it('should return x = width if x > width', () => {
- const event = generateEvent(1000, 50);
- const result = utilsHelper.getTargetSelection(event);
-
- expect(result.browser.x).toEqual(imageProperties.width);
- });
-
- it('should return y = 0 if y < 0', () => {
- const event = generateEvent(50, -10);
- const result = utilsHelper.getTargetSelection(event);
-
- expect(result.browser.y).toEqual(0);
- });
-
- it('should return y = height if y > height', () => {
- const event = generateEvent(50, 1000);
- const result = utilsHelper.getTargetSelection(event);
-
- expect(result.browser.y).toEqual(imageProperties.height);
- });
- });
- });
-});
diff --git a/spec/javascripts/image_diff/image_badge_spec.js b/spec/javascripts/image_diff/image_badge_spec.js
deleted file mode 100644
index 2b23dce5d30..00000000000
--- a/spec/javascripts/image_diff/image_badge_spec.js
+++ /dev/null
@@ -1,96 +0,0 @@
-import ImageBadge from '~/image_diff/image_badge';
-import imageDiffHelper from '~/image_diff/helpers/index';
-import * as mockData from './mock_data';
-
-describe('ImageBadge', () => {
- const { noteId, discussionId, imageMeta } = mockData;
- const options = {
- noteId,
- discussionId,
- };
-
- it('should save actual property', () => {
- const imageBadge = new ImageBadge(
- Object.assign({}, options, {
- actual: imageMeta,
- }),
- );
-
- const { actual } = imageBadge;
-
- expect(actual.x).toEqual(imageMeta.x);
- expect(actual.y).toEqual(imageMeta.y);
- expect(actual.width).toEqual(imageMeta.width);
- expect(actual.height).toEqual(imageMeta.height);
- });
-
- it('should save browser property', () => {
- const imageBadge = new ImageBadge(
- Object.assign({}, options, {
- browser: imageMeta,
- }),
- );
-
- const { browser } = imageBadge;
-
- expect(browser.x).toEqual(imageMeta.x);
- expect(browser.y).toEqual(imageMeta.y);
- expect(browser.width).toEqual(imageMeta.width);
- expect(browser.height).toEqual(imageMeta.height);
- });
-
- it('should save noteId', () => {
- const imageBadge = new ImageBadge(options);
-
- expect(imageBadge.noteId).toEqual(noteId);
- });
-
- it('should save discussionId', () => {
- const imageBadge = new ImageBadge(options);
-
- expect(imageBadge.discussionId).toEqual(discussionId);
- });
-
- describe('default values', () => {
- let imageBadge;
-
- beforeEach(() => {
- imageBadge = new ImageBadge(options);
- });
-
- it('should return defaultimageMeta if actual property is not provided', () => {
- const { actual } = imageBadge;
-
- expect(actual.x).toEqual(0);
- expect(actual.y).toEqual(0);
- expect(actual.width).toEqual(0);
- expect(actual.height).toEqual(0);
- });
-
- it('should return defaultimageMeta if browser property is not provided', () => {
- const { browser } = imageBadge;
-
- expect(browser.x).toEqual(0);
- expect(browser.y).toEqual(0);
- expect(browser.width).toEqual(0);
- expect(browser.height).toEqual(0);
- });
- });
-
- describe('imageEl property is provided and not browser property', () => {
- beforeEach(() => {
- spyOn(imageDiffHelper, 'resizeCoordinatesToImageElement').and.returnValue(true);
- });
-
- it('should generate browser property', () => {
- const imageBadge = new ImageBadge(
- Object.assign({}, options, {
- imageEl: document.createElement('img'),
- }),
- );
-
- expect(imageDiffHelper.resizeCoordinatesToImageElement).toHaveBeenCalled();
- expect(imageBadge.browser).toEqual(true);
- });
- });
-});
diff --git a/spec/javascripts/image_diff/image_diff_spec.js b/spec/javascripts/image_diff/image_diff_spec.js
deleted file mode 100644
index 21e7b8e2e9b..00000000000
--- a/spec/javascripts/image_diff/image_diff_spec.js
+++ /dev/null
@@ -1,361 +0,0 @@
-import ImageDiff from '~/image_diff/image_diff';
-import * as imageUtility from '~/lib/utils/image_utility';
-import imageDiffHelper from '~/image_diff/helpers/index';
-import * as mockData from './mock_data';
-
-describe('ImageDiff', () => {
- let element;
- let imageDiff;
-
- beforeEach(() => {
- setFixtures(`
- <div id="element">
- <div class="diff-file">
- <div class="js-image-frame">
- <img src="${gl.TEST_HOST}/image.png">
- <div class="comment-indicator"></div>
- <div id="badge-1" class="badge">1</div>
- <div id="badge-2" class="badge">2</div>
- <div id="badge-3" class="badge">3</div>
- </div>
- <div class="note-container">
- <div class="discussion-notes">
- <div class="js-diff-notes-toggle"></div>
- <div class="notes"></div>
- </div>
- <div class="discussion-notes">
- <div class="js-diff-notes-toggle"></div>
- <div class="notes"></div>
- </div>
- </div>
- </div>
- </div>
- `);
- element = document.getElementById('element');
- });
-
- describe('constructor', () => {
- beforeEach(() => {
- imageDiff = new ImageDiff(element, {
- canCreateNote: true,
- renderCommentBadge: true,
- });
- });
-
- it('should set el', () => {
- expect(imageDiff.el).toEqual(element);
- });
-
- it('should set canCreateNote', () => {
- expect(imageDiff.canCreateNote).toEqual(true);
- });
-
- it('should set renderCommentBadge', () => {
- expect(imageDiff.renderCommentBadge).toEqual(true);
- });
-
- it('should set $noteContainer', () => {
- expect(imageDiff.$noteContainer[0]).toEqual(element.querySelector('.note-container'));
- });
-
- describe('default', () => {
- beforeEach(() => {
- imageDiff = new ImageDiff(element);
- });
-
- it('should set canCreateNote as false', () => {
- expect(imageDiff.canCreateNote).toEqual(false);
- });
-
- it('should set renderCommentBadge as false', () => {
- expect(imageDiff.renderCommentBadge).toEqual(false);
- });
- });
- });
-
- describe('init', () => {
- beforeEach(() => {
- spyOn(ImageDiff.prototype, 'bindEvents').and.callFake(() => {});
- imageDiff = new ImageDiff(element);
- imageDiff.init();
- });
-
- it('should set imageFrameEl', () => {
- expect(imageDiff.imageFrameEl).toEqual(element.querySelector('.diff-file .js-image-frame'));
- });
-
- it('should set imageEl', () => {
- expect(imageDiff.imageEl).toEqual(element.querySelector('.diff-file .js-image-frame img'));
- });
-
- it('should call bindEvents', () => {
- expect(imageDiff.bindEvents).toHaveBeenCalled();
- });
- });
-
- describe('bindEvents', () => {
- let imageEl;
-
- beforeEach(() => {
- spyOn(imageDiffHelper, 'toggleCollapsed').and.callFake(() => {});
- spyOn(imageDiffHelper, 'commentIndicatorOnClick').and.callFake(() => {});
- spyOn(imageDiffHelper, 'removeCommentIndicator').and.callFake(() => {});
- spyOn(ImageDiff.prototype, 'imageClicked').and.callFake(() => {});
- spyOn(ImageDiff.prototype, 'addBadge').and.callFake(() => {});
- spyOn(ImageDiff.prototype, 'removeBadge').and.callFake(() => {});
- spyOn(ImageDiff.prototype, 'renderBadges').and.callFake(() => {});
- imageEl = element.querySelector('.diff-file .js-image-frame img');
- });
-
- describe('default', () => {
- beforeEach(() => {
- spyOn(imageUtility, 'isImageLoaded').and.returnValue(false);
- imageDiff = new ImageDiff(element);
- imageDiff.imageEl = imageEl;
- imageDiff.bindEvents();
- });
-
- it('should register click event delegation to js-diff-notes-toggle', () => {
- element.querySelector('.js-diff-notes-toggle').click();
-
- expect(imageDiffHelper.toggleCollapsed).toHaveBeenCalled();
- });
-
- it('should register click event delegation to comment-indicator', () => {
- element.querySelector('.comment-indicator').click();
-
- expect(imageDiffHelper.commentIndicatorOnClick).toHaveBeenCalled();
- });
- });
-
- describe('image not loaded', () => {
- beforeEach(() => {
- spyOn(imageUtility, 'isImageLoaded').and.returnValue(false);
- imageDiff = new ImageDiff(element);
- imageDiff.imageEl = imageEl;
- imageDiff.bindEvents();
- });
-
- it('should registers load eventListener', () => {
- const loadEvent = new Event('load');
- imageEl.dispatchEvent(loadEvent);
-
- expect(imageDiff.renderBadges).toHaveBeenCalled();
- });
- });
-
- describe('canCreateNote', () => {
- beforeEach(() => {
- spyOn(imageUtility, 'isImageLoaded').and.returnValue(false);
- imageDiff = new ImageDiff(element, {
- canCreateNote: true,
- });
- imageDiff.imageEl = imageEl;
- imageDiff.bindEvents();
- });
-
- it('should register click.imageDiff event', () => {
- const event = new CustomEvent('click.imageDiff');
- element.dispatchEvent(event);
-
- expect(imageDiff.imageClicked).toHaveBeenCalled();
- });
-
- it('should register blur.imageDiff event', () => {
- const event = new CustomEvent('blur.imageDiff');
- element.dispatchEvent(event);
-
- expect(imageDiffHelper.removeCommentIndicator).toHaveBeenCalled();
- });
-
- it('should register addBadge.imageDiff event', () => {
- const event = new CustomEvent('addBadge.imageDiff');
- element.dispatchEvent(event);
-
- expect(imageDiff.addBadge).toHaveBeenCalled();
- });
-
- it('should register removeBadge.imageDiff event', () => {
- const event = new CustomEvent('removeBadge.imageDiff');
- element.dispatchEvent(event);
-
- expect(imageDiff.removeBadge).toHaveBeenCalled();
- });
- });
-
- describe('canCreateNote is false', () => {
- beforeEach(() => {
- spyOn(imageUtility, 'isImageLoaded').and.returnValue(false);
- imageDiff = new ImageDiff(element);
- imageDiff.imageEl = imageEl;
- imageDiff.bindEvents();
- });
-
- it('should not register click.imageDiff event', () => {
- const event = new CustomEvent('click.imageDiff');
- element.dispatchEvent(event);
-
- expect(imageDiff.imageClicked).not.toHaveBeenCalled();
- });
- });
- });
-
- describe('imageClicked', () => {
- beforeEach(() => {
- spyOn(imageDiffHelper, 'getTargetSelection').and.returnValue({
- actual: {},
- browser: {},
- });
- spyOn(imageDiffHelper, 'setPositionDataAttribute').and.callFake(() => {});
- spyOn(imageDiffHelper, 'showCommentIndicator').and.callFake(() => {});
- imageDiff = new ImageDiff(element);
- imageDiff.imageClicked({
- detail: {
- currentTarget: {},
- },
- });
- });
-
- it('should call getTargetSelection', () => {
- expect(imageDiffHelper.getTargetSelection).toHaveBeenCalled();
- });
-
- it('should call setPositionDataAttribute', () => {
- expect(imageDiffHelper.setPositionDataAttribute).toHaveBeenCalled();
- });
-
- it('should call showCommentIndicator', () => {
- expect(imageDiffHelper.showCommentIndicator).toHaveBeenCalled();
- });
- });
-
- describe('renderBadges', () => {
- beforeEach(() => {
- spyOn(ImageDiff.prototype, 'renderBadge').and.callFake(() => {});
- imageDiff = new ImageDiff(element);
- imageDiff.renderBadges();
- });
-
- it('should call renderBadge for each discussionEl', () => {
- const discussionEls = element.querySelectorAll('.note-container .discussion-notes .notes');
-
- expect(imageDiff.renderBadge.calls.count()).toEqual(discussionEls.length);
- });
- });
-
- describe('renderBadge', () => {
- let discussionEls;
-
- beforeEach(() => {
- spyOn(imageDiffHelper, 'addImageBadge').and.callFake(() => {});
- spyOn(imageDiffHelper, 'addImageCommentBadge').and.callFake(() => {});
- spyOn(imageDiffHelper, 'generateBadgeFromDiscussionDOM').and.returnValue({
- browser: {},
- noteId: 'noteId',
- });
- discussionEls = element.querySelectorAll('.note-container .discussion-notes .notes');
- imageDiff = new ImageDiff(element);
- imageDiff.renderBadge(discussionEls[0], 0);
- });
-
- it('should populate imageBadges', () => {
- expect(imageDiff.imageBadges.length).toEqual(1);
- });
-
- describe('renderCommentBadge', () => {
- beforeEach(() => {
- imageDiff.renderCommentBadge = true;
- imageDiff.renderBadge(discussionEls[0], 0);
- });
-
- it('should call addImageCommentBadge', () => {
- expect(imageDiffHelper.addImageCommentBadge).toHaveBeenCalled();
- });
- });
-
- describe('renderCommentBadge is false', () => {
- it('should call addImageBadge', () => {
- expect(imageDiffHelper.addImageBadge).toHaveBeenCalled();
- });
- });
- });
-
- describe('addBadge', () => {
- beforeEach(() => {
- spyOn(imageDiffHelper, 'addImageBadge').and.callFake(() => {});
- spyOn(imageDiffHelper, 'addAvatarBadge').and.callFake(() => {});
- spyOn(imageDiffHelper, 'updateDiscussionBadgeNumber').and.callFake(() => {});
- imageDiff = new ImageDiff(element);
- imageDiff.imageFrameEl = element.querySelector('.diff-file .js-image-frame');
- imageDiff.addBadge({
- detail: {
- x: 0,
- y: 1,
- width: 25,
- height: 50,
- noteId: 'noteId',
- discussionId: 'discussionId',
- },
- });
- });
-
- it('should add imageBadge to imageBadges', () => {
- expect(imageDiff.imageBadges.length).toEqual(1);
- });
-
- it('should call addImageBadge', () => {
- expect(imageDiffHelper.addImageBadge).toHaveBeenCalled();
- });
-
- it('should call addAvatarBadge', () => {
- expect(imageDiffHelper.addAvatarBadge).toHaveBeenCalled();
- });
-
- it('should call updateDiscussionBadgeNumber', () => {
- expect(imageDiffHelper.updateDiscussionBadgeNumber).toHaveBeenCalled();
- });
- });
-
- describe('removeBadge', () => {
- beforeEach(() => {
- const { imageMeta } = mockData;
-
- spyOn(imageDiffHelper, 'updateDiscussionBadgeNumber').and.callFake(() => {});
- spyOn(imageDiffHelper, 'updateDiscussionAvatarBadgeNumber').and.callFake(() => {});
- imageDiff = new ImageDiff(element);
- imageDiff.imageBadges = [imageMeta, imageMeta, imageMeta];
- imageDiff.imageFrameEl = element.querySelector('.diff-file .js-image-frame');
- imageDiff.removeBadge({
- detail: {
- badgeNumber: 2,
- },
- });
- });
-
- describe('cascade badge count', () => {
- it('should update next imageBadgeEl value', () => {
- const imageBadgeEls = imageDiff.imageFrameEl.querySelectorAll('.badge');
-
- expect(imageBadgeEls[0].innerText).toEqual('1');
- expect(imageBadgeEls[1].innerText).toEqual('2');
- expect(imageBadgeEls.length).toEqual(2);
- });
-
- it('should call updateDiscussionBadgeNumber', () => {
- expect(imageDiffHelper.updateDiscussionBadgeNumber).toHaveBeenCalled();
- });
-
- it('should call updateDiscussionAvatarBadgeNumber', () => {
- expect(imageDiffHelper.updateDiscussionAvatarBadgeNumber).toHaveBeenCalled();
- });
- });
-
- it('should remove badge from imageBadges', () => {
- expect(imageDiff.imageBadges.length).toEqual(2);
- });
-
- it('should remove imageBadgeEl', () => {
- expect(imageDiff.imageFrameEl.querySelector('#badge-2')).toBeNull();
- });
- });
-});
diff --git a/spec/javascripts/image_diff/mock_data.js b/spec/javascripts/image_diff/mock_data.js
deleted file mode 100644
index a0d1732dd0a..00000000000
--- a/spec/javascripts/image_diff/mock_data.js
+++ /dev/null
@@ -1,28 +0,0 @@
-export const noteId = 'noteId';
-export const discussionId = 'discussionId';
-export const badgeText = 'badgeText';
-export const badgeNumber = 5;
-
-export const coordinate = {
- x: 100,
- y: 100,
-};
-
-export const image = {
- width: 100,
- height: 100,
-};
-
-export const imageProperties = {
- width: image.width,
- height: image.height,
- naturalWidth: image.width * 2,
- naturalHeight: image.height * 2,
-};
-
-export const imageMeta = {
- x: coordinate.x,
- y: coordinate.y,
- width: imageProperties.naturalWidth,
- height: imageProperties.naturalHeight,
-};
diff --git a/spec/javascripts/image_diff/replaced_image_diff_spec.js b/spec/javascripts/image_diff/replaced_image_diff_spec.js
deleted file mode 100644
index 62e7c8b6c6a..00000000000
--- a/spec/javascripts/image_diff/replaced_image_diff_spec.js
+++ /dev/null
@@ -1,355 +0,0 @@
-import ReplacedImageDiff from '~/image_diff/replaced_image_diff';
-import ImageDiff from '~/image_diff/image_diff';
-import { viewTypes } from '~/image_diff/view_types';
-import imageDiffHelper from '~/image_diff/helpers/index';
-
-describe('ReplacedImageDiff', () => {
- let element;
- let replacedImageDiff;
-
- beforeEach(() => {
- setFixtures(`
- <div id="element">
- <div class="two-up">
- <div class="js-image-frame">
- <img src="${gl.TEST_HOST}/image.png">
- </div>
- </div>
- <div class="swipe">
- <div class="js-image-frame">
- <img src="${gl.TEST_HOST}/image.png">
- </div>
- </div>
- <div class="onion-skin">
- <div class="js-image-frame">
- <img src="${gl.TEST_HOST}/image.png">
- </div>
- </div>
- <div class="view-modes-menu">
- <div class="two-up">2-up</div>
- <div class="swipe">Swipe</div>
- <div class="onion-skin">Onion skin</div>
- </div>
- </div>
- `);
- element = document.getElementById('element');
- });
-
- function setupImageFrameEls() {
- replacedImageDiff.imageFrameEls = [];
- replacedImageDiff.imageFrameEls[viewTypes.TWO_UP] = element.querySelector(
- '.two-up .js-image-frame',
- );
- replacedImageDiff.imageFrameEls[viewTypes.SWIPE] = element.querySelector(
- '.swipe .js-image-frame',
- );
- replacedImageDiff.imageFrameEls[viewTypes.ONION_SKIN] = element.querySelector(
- '.onion-skin .js-image-frame',
- );
- }
-
- function setupViewModesEls() {
- replacedImageDiff.viewModesEls = [];
- replacedImageDiff.viewModesEls[viewTypes.TWO_UP] = element.querySelector(
- '.view-modes-menu .two-up',
- );
- replacedImageDiff.viewModesEls[viewTypes.SWIPE] = element.querySelector(
- '.view-modes-menu .swipe',
- );
- replacedImageDiff.viewModesEls[viewTypes.ONION_SKIN] = element.querySelector(
- '.view-modes-menu .onion-skin',
- );
- }
-
- function setupImageEls() {
- replacedImageDiff.imageEls = [];
- replacedImageDiff.imageEls[viewTypes.TWO_UP] = element.querySelector('.two-up img');
- replacedImageDiff.imageEls[viewTypes.SWIPE] = element.querySelector('.swipe img');
- replacedImageDiff.imageEls[viewTypes.ONION_SKIN] = element.querySelector('.onion-skin img');
- }
-
- it('should extend ImageDiff', () => {
- replacedImageDiff = new ReplacedImageDiff(element);
-
- expect(replacedImageDiff instanceof ImageDiff).toEqual(true);
- });
-
- describe('init', () => {
- beforeEach(() => {
- spyOn(ReplacedImageDiff.prototype, 'bindEvents').and.callFake(() => {});
- spyOn(ReplacedImageDiff.prototype, 'generateImageEls').and.callFake(() => {});
-
- replacedImageDiff = new ReplacedImageDiff(element);
- replacedImageDiff.init();
- });
-
- it('should set imageFrameEls', () => {
- const { imageFrameEls } = replacedImageDiff;
-
- expect(imageFrameEls).toBeDefined();
- expect(imageFrameEls[viewTypes.TWO_UP]).toEqual(
- element.querySelector('.two-up .js-image-frame'),
- );
-
- expect(imageFrameEls[viewTypes.SWIPE]).toEqual(
- element.querySelector('.swipe .js-image-frame'),
- );
-
- expect(imageFrameEls[viewTypes.ONION_SKIN]).toEqual(
- element.querySelector('.onion-skin .js-image-frame'),
- );
- });
-
- it('should set viewModesEls', () => {
- const { viewModesEls } = replacedImageDiff;
-
- expect(viewModesEls).toBeDefined();
- expect(viewModesEls[viewTypes.TWO_UP]).toEqual(
- element.querySelector('.view-modes-menu .two-up'),
- );
-
- expect(viewModesEls[viewTypes.SWIPE]).toEqual(
- element.querySelector('.view-modes-menu .swipe'),
- );
-
- expect(viewModesEls[viewTypes.ONION_SKIN]).toEqual(
- element.querySelector('.view-modes-menu .onion-skin'),
- );
- });
-
- it('should generateImageEls', () => {
- expect(ReplacedImageDiff.prototype.generateImageEls).toHaveBeenCalled();
- });
-
- it('should bindEvents', () => {
- expect(ReplacedImageDiff.prototype.bindEvents).toHaveBeenCalled();
- });
-
- describe('currentView', () => {
- it('should set currentView', () => {
- replacedImageDiff.init(viewTypes.ONION_SKIN);
-
- expect(replacedImageDiff.currentView).toEqual(viewTypes.ONION_SKIN);
- });
-
- it('should default to viewTypes.TWO_UP', () => {
- expect(replacedImageDiff.currentView).toEqual(viewTypes.TWO_UP);
- });
- });
- });
-
- describe('generateImageEls', () => {
- beforeEach(() => {
- spyOn(ReplacedImageDiff.prototype, 'bindEvents').and.callFake(() => {});
-
- replacedImageDiff = new ReplacedImageDiff(element, {
- canCreateNote: false,
- renderCommentBadge: false,
- });
-
- setupImageFrameEls();
- });
-
- it('should set imageEls', () => {
- replacedImageDiff.generateImageEls();
- const { imageEls } = replacedImageDiff;
-
- expect(imageEls).toBeDefined();
- expect(imageEls[viewTypes.TWO_UP]).toEqual(element.querySelector('.two-up img'));
- expect(imageEls[viewTypes.SWIPE]).toEqual(element.querySelector('.swipe img'));
- expect(imageEls[viewTypes.ONION_SKIN]).toEqual(element.querySelector('.onion-skin img'));
- });
- });
-
- describe('bindEvents', () => {
- beforeEach(() => {
- spyOn(ImageDiff.prototype, 'bindEvents').and.callFake(() => {});
- replacedImageDiff = new ReplacedImageDiff(element);
-
- setupViewModesEls();
- });
-
- it('should call super.bindEvents', () => {
- replacedImageDiff.bindEvents();
-
- expect(ImageDiff.prototype.bindEvents).toHaveBeenCalled();
- });
-
- it('should register click eventlistener to 2-up view mode', done => {
- spyOn(ReplacedImageDiff.prototype, 'changeView').and.callFake(viewMode => {
- expect(viewMode).toEqual(viewTypes.TWO_UP);
- done();
- });
-
- replacedImageDiff.bindEvents();
- replacedImageDiff.viewModesEls[viewTypes.TWO_UP].click();
- });
-
- it('should register click eventlistener to swipe view mode', done => {
- spyOn(ReplacedImageDiff.prototype, 'changeView').and.callFake(viewMode => {
- expect(viewMode).toEqual(viewTypes.SWIPE);
- done();
- });
-
- replacedImageDiff.bindEvents();
- replacedImageDiff.viewModesEls[viewTypes.SWIPE].click();
- });
-
- it('should register click eventlistener to onion skin view mode', done => {
- spyOn(ReplacedImageDiff.prototype, 'changeView').and.callFake(viewMode => {
- expect(viewMode).toEqual(viewTypes.SWIPE);
- done();
- });
-
- replacedImageDiff.bindEvents();
- replacedImageDiff.viewModesEls[viewTypes.SWIPE].click();
- });
- });
-
- describe('getters', () => {
- describe('imageEl', () => {
- beforeEach(() => {
- replacedImageDiff = new ReplacedImageDiff(element);
- replacedImageDiff.currentView = viewTypes.TWO_UP;
- setupImageEls();
- });
-
- it('should return imageEl based on currentView', () => {
- expect(replacedImageDiff.imageEl).toEqual(element.querySelector('.two-up img'));
-
- replacedImageDiff.currentView = viewTypes.SWIPE;
-
- expect(replacedImageDiff.imageEl).toEqual(element.querySelector('.swipe img'));
- });
- });
-
- describe('imageFrameEl', () => {
- beforeEach(() => {
- replacedImageDiff = new ReplacedImageDiff(element);
- replacedImageDiff.currentView = viewTypes.TWO_UP;
- setupImageFrameEls();
- });
-
- it('should return imageFrameEl based on currentView', () => {
- expect(replacedImageDiff.imageFrameEl).toEqual(
- element.querySelector('.two-up .js-image-frame'),
- );
-
- replacedImageDiff.currentView = viewTypes.ONION_SKIN;
-
- expect(replacedImageDiff.imageFrameEl).toEqual(
- element.querySelector('.onion-skin .js-image-frame'),
- );
- });
- });
- });
-
- describe('changeView', () => {
- beforeEach(() => {
- replacedImageDiff = new ReplacedImageDiff(element);
- spyOn(imageDiffHelper, 'removeCommentIndicator').and.returnValue({
- removed: false,
- });
- setupImageFrameEls();
- });
-
- describe('invalid viewType', () => {
- beforeEach(() => {
- replacedImageDiff.changeView('some-view-name');
- });
-
- it('should not call removeCommentIndicator', () => {
- expect(imageDiffHelper.removeCommentIndicator).not.toHaveBeenCalled();
- });
- });
-
- describe('valid viewType', () => {
- beforeEach(() => {
- jasmine.clock().install();
- spyOn(ReplacedImageDiff.prototype, 'renderNewView').and.callFake(() => {});
- replacedImageDiff.changeView(viewTypes.ONION_SKIN);
- });
-
- afterEach(() => {
- jasmine.clock().uninstall();
- });
-
- it('should call removeCommentIndicator', () => {
- expect(imageDiffHelper.removeCommentIndicator).toHaveBeenCalled();
- });
-
- it('should update currentView to newView', () => {
- expect(replacedImageDiff.currentView).toEqual(viewTypes.ONION_SKIN);
- });
-
- it('should clear imageBadges', () => {
- expect(replacedImageDiff.imageBadges.length).toEqual(0);
- });
-
- it('should call renderNewView', () => {
- jasmine.clock().tick(251);
-
- expect(replacedImageDiff.renderNewView).toHaveBeenCalled();
- });
- });
- });
-
- describe('renderNewView', () => {
- beforeEach(() => {
- replacedImageDiff = new ReplacedImageDiff(element);
- });
-
- it('should call renderBadges', () => {
- spyOn(ReplacedImageDiff.prototype, 'renderBadges').and.callFake(() => {});
-
- replacedImageDiff.renderNewView({
- removed: false,
- });
-
- expect(replacedImageDiff.renderBadges).toHaveBeenCalled();
- });
-
- describe('removeIndicator', () => {
- const indicator = {
- removed: true,
- x: 0,
- y: 1,
- image: {
- width: 50,
- height: 100,
- },
- };
-
- beforeEach(() => {
- setupImageEls();
- setupImageFrameEls();
- });
-
- it('should pass showCommentIndicator normalized indicator values', done => {
- spyOn(imageDiffHelper, 'showCommentIndicator').and.callFake(() => {});
- spyOn(imageDiffHelper, 'resizeCoordinatesToImageElement').and.callFake((imageEl, meta) => {
- expect(meta.x).toEqual(indicator.x);
- expect(meta.y).toEqual(indicator.y);
- expect(meta.width).toEqual(indicator.image.width);
- expect(meta.height).toEqual(indicator.image.height);
- done();
- });
- replacedImageDiff.renderNewView(indicator);
- });
-
- it('should call showCommentIndicator', done => {
- const normalized = {
- normalized: true,
- };
- spyOn(imageDiffHelper, 'resizeCoordinatesToImageElement').and.returnValue(normalized);
- spyOn(imageDiffHelper, 'showCommentIndicator').and.callFake(
- (imageFrameEl, normalizedIndicator) => {
- expect(normalizedIndicator).toEqual(normalized);
- done();
- },
- );
- replacedImageDiff.renderNewView(indicator);
- });
- });
- });
-});
diff --git a/spec/javascripts/integrations/integration_settings_form_spec.js b/spec/javascripts/integrations/integration_settings_form_spec.js
deleted file mode 100644
index 72d04be822f..00000000000
--- a/spec/javascripts/integrations/integration_settings_form_spec.js
+++ /dev/null
@@ -1,301 +0,0 @@
-import $ from 'jquery';
-import MockAdaptor from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import IntegrationSettingsForm from '~/integrations/integration_settings_form';
-
-describe('IntegrationSettingsForm', () => {
- const FIXTURE = 'services/edit_service.html';
- preloadFixtures(FIXTURE);
-
- beforeEach(() => {
- loadFixtures(FIXTURE);
- });
-
- describe('contructor', () => {
- let integrationSettingsForm;
-
- beforeEach(() => {
- integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
- spyOn(integrationSettingsForm, 'init');
- });
-
- it('should initialize form element refs on class object', () => {
- // Form Reference
- expect(integrationSettingsForm.$form).toBeDefined();
- expect(integrationSettingsForm.$form.prop('nodeName')).toEqual('FORM');
- expect(integrationSettingsForm.formActive).toBeDefined();
-
- // Form Child Elements
- expect(integrationSettingsForm.$submitBtn).toBeDefined();
- expect(integrationSettingsForm.$submitBtnLoader).toBeDefined();
- expect(integrationSettingsForm.$submitBtnLabel).toBeDefined();
- });
-
- it('should initialize form metadata on class object', () => {
- expect(integrationSettingsForm.testEndPoint).toBeDefined();
- expect(integrationSettingsForm.canTestService).toBeDefined();
- });
- });
-
- describe('toggleServiceState', () => {
- let integrationSettingsForm;
-
- beforeEach(() => {
- integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
- });
-
- it('should remove `novalidate` attribute to form when called with `true`', () => {
- integrationSettingsForm.formActive = true;
- integrationSettingsForm.toggleServiceState();
-
- expect(integrationSettingsForm.$form.attr('novalidate')).not.toBeDefined();
- });
-
- it('should set `novalidate` attribute to form when called with `false`', () => {
- integrationSettingsForm.formActive = false;
- integrationSettingsForm.toggleServiceState();
-
- expect(integrationSettingsForm.$form.attr('novalidate')).toBeDefined();
- });
- });
-
- describe('toggleSubmitBtnLabel', () => {
- let integrationSettingsForm;
-
- beforeEach(() => {
- integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
- });
-
- it('should set Save button label to "Test settings and save changes" when serviceActive & canTestService are `true`', () => {
- integrationSettingsForm.canTestService = true;
- integrationSettingsForm.formActive = true;
-
- integrationSettingsForm.toggleSubmitBtnLabel();
-
- expect(integrationSettingsForm.$submitBtnLabel.text()).toEqual(
- 'Test settings and save changes',
- );
- });
-
- it('should set Save button label to "Save changes" when either serviceActive or canTestService (or both) is `false`', () => {
- integrationSettingsForm.canTestService = false;
- integrationSettingsForm.formActive = false;
-
- integrationSettingsForm.toggleSubmitBtnLabel();
-
- expect(integrationSettingsForm.$submitBtnLabel.text()).toEqual('Save changes');
-
- integrationSettingsForm.formActive = true;
-
- integrationSettingsForm.toggleSubmitBtnLabel();
-
- expect(integrationSettingsForm.$submitBtnLabel.text()).toEqual('Save changes');
-
- integrationSettingsForm.canTestService = true;
- integrationSettingsForm.formActive = false;
-
- integrationSettingsForm.toggleSubmitBtnLabel();
-
- expect(integrationSettingsForm.$submitBtnLabel.text()).toEqual('Save changes');
- });
- });
-
- describe('toggleSubmitBtnState', () => {
- let integrationSettingsForm;
-
- beforeEach(() => {
- integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
- });
-
- it('should disable Save button and show loader animation when called with `true`', () => {
- integrationSettingsForm.toggleSubmitBtnState(true);
-
- expect(integrationSettingsForm.$submitBtn.is(':disabled')).toBeTruthy();
- expect(integrationSettingsForm.$submitBtnLoader.hasClass('hidden')).toBeFalsy();
- });
-
- it('should enable Save button and hide loader animation when called with `false`', () => {
- integrationSettingsForm.toggleSubmitBtnState(false);
-
- expect(integrationSettingsForm.$submitBtn.is(':disabled')).toBeFalsy();
- expect(integrationSettingsForm.$submitBtnLoader.hasClass('hidden')).toBeTruthy();
- });
- });
-
- describe('testSettings', () => {
- let integrationSettingsForm;
- let formData;
- let mock;
-
- beforeEach(() => {
- mock = new MockAdaptor(axios);
-
- spyOn(axios, 'put').and.callThrough();
-
- integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
- // eslint-disable-next-line no-jquery/no-serialize
- formData = integrationSettingsForm.$form.serialize();
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('should make an ajax request with provided `formData`', done => {
- integrationSettingsForm
- .testSettings(formData)
- .then(() => {
- expect(axios.put).toHaveBeenCalledWith(integrationSettingsForm.testEndPoint, formData);
-
- done();
- })
- .catch(done.fail);
- });
-
- it('should show error Flash with `Save anyway` action if ajax request responds with error in test', done => {
- const errorMessage = 'Test failed.';
- mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
- error: true,
- message: errorMessage,
- service_response: 'some error',
- test_failed: true,
- });
-
- integrationSettingsForm
- .testSettings(formData)
- .then(() => {
- const $flashContainer = $('.flash-container');
-
- expect(
- $flashContainer
- .find('.flash-text')
- .text()
- .trim(),
- ).toEqual('Test failed. some error');
-
- expect($flashContainer.find('.flash-action')).toBeDefined();
- expect(
- $flashContainer
- .find('.flash-action')
- .text()
- .trim(),
- ).toEqual('Save anyway');
-
- done();
- })
- .catch(done.fail);
- });
-
- it('should not show error Flash with `Save anyway` action if ajax request responds with error in validation', done => {
- const errorMessage = 'Validations failed.';
- mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
- error: true,
- message: errorMessage,
- service_response: 'some error',
- test_failed: false,
- });
-
- integrationSettingsForm
- .testSettings(formData)
- .then(() => {
- const $flashContainer = $('.flash-container');
-
- expect(
- $flashContainer
- .find('.flash-text')
- .text()
- .trim(),
- ).toEqual('Validations failed. some error');
-
- expect($flashContainer.find('.flash-action')).toBeDefined();
- expect(
- $flashContainer
- .find('.flash-action')
- .text()
- .trim(),
- ).toEqual('');
-
- done();
- })
- .catch(done.fail);
- });
-
- it('should submit form if ajax request responds without any error in test', done => {
- spyOn(integrationSettingsForm.$form, 'submit');
-
- mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
- error: false,
- });
-
- integrationSettingsForm
- .testSettings(formData)
- .then(() => {
- expect(integrationSettingsForm.$form.submit).toHaveBeenCalled();
-
- done();
- })
- .catch(done.fail);
- });
-
- it('should submit form when clicked on `Save anyway` action of error Flash', done => {
- spyOn(integrationSettingsForm.$form, 'submit');
-
- const errorMessage = 'Test failed.';
- mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
- error: true,
- message: errorMessage,
- test_failed: true,
- });
-
- integrationSettingsForm
- .testSettings(formData)
- .then(() => {
- const $flashAction = $('.flash-container .flash-action');
-
- expect($flashAction).toBeDefined();
-
- $flashAction.get(0).click();
- })
- .then(() => {
- expect(integrationSettingsForm.$form.submit).toHaveBeenCalled();
-
- done();
- })
- .catch(done.fail);
- });
-
- it('should show error Flash if ajax request failed', done => {
- const errorMessage = 'Something went wrong on our end.';
-
- mock.onPut(integrationSettingsForm.testEndPoint).networkError();
-
- integrationSettingsForm
- .testSettings(formData)
- .then(() => {
- expect(
- $('.flash-container .flash-text')
- .text()
- .trim(),
- ).toEqual(errorMessage);
-
- done();
- })
- .catch(done.fail);
- });
-
- it('should always call `toggleSubmitBtnState` with `false` once request is completed', done => {
- mock.onPut(integrationSettingsForm.testEndPoint).networkError();
-
- spyOn(integrationSettingsForm, 'toggleSubmitBtnState');
-
- integrationSettingsForm
- .testSettings(formData)
- .then(() => {
- expect(integrationSettingsForm.toggleSubmitBtnState).toHaveBeenCalledWith(false);
-
- done();
- })
- .catch(done.fail);
- });
- });
-});
diff --git a/spec/javascripts/issuable_spec.js b/spec/javascripts/issuable_spec.js
deleted file mode 100644
index 4d57bfb1b33..00000000000
--- a/spec/javascripts/issuable_spec.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import $ from 'jquery';
-import MockAdaptor from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import IssuableIndex from '~/issuable_index';
-import issuableInitBulkUpdateSidebar from '~/issuable_init_bulk_update_sidebar';
-
-describe('Issuable', () => {
- describe('initBulkUpdate', () => {
- it('should not set bulkUpdateSidebar', () => {
- new IssuableIndex('issue_'); // eslint-disable-line no-new
-
- expect(issuableInitBulkUpdateSidebar.bulkUpdateSidebar).toBeNull();
- });
-
- it('should set bulkUpdateSidebar', () => {
- const element = document.createElement('div');
- element.classList.add('issues-bulk-update');
- document.body.appendChild(element);
-
- new IssuableIndex('issue_'); // eslint-disable-line no-new
-
- expect(issuableInitBulkUpdateSidebar.bulkUpdateSidebar).toBeDefined();
- });
- });
-
- describe('resetIncomingEmailToken', () => {
- let mock;
-
- beforeEach(() => {
- const element = document.createElement('a');
- element.classList.add('incoming-email-token-reset');
- element.setAttribute('href', 'foo');
- document.body.appendChild(element);
-
- const input = document.createElement('input');
- input.setAttribute('id', 'issuable_email');
- document.body.appendChild(input);
-
- new IssuableIndex('issue_'); // eslint-disable-line no-new
-
- mock = new MockAdaptor(axios);
-
- mock.onPut('foo').reply(200, {
- new_address: 'testing123',
- });
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('should send request to reset email token', done => {
- spyOn(axios, 'put').and.callThrough();
- document.querySelector('.incoming-email-token-reset').click();
-
- setTimeout(() => {
- expect(axios.put).toHaveBeenCalledWith('foo');
- expect($('#issuable_email').val()).toBe('testing123');
-
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/issue_show/components/app_spec.js b/spec/javascripts/issue_show/components/app_spec.js
deleted file mode 100644
index f11d4f5ac33..00000000000
--- a/spec/javascripts/issue_show/components/app_spec.js
+++ /dev/null
@@ -1,568 +0,0 @@
-/* eslint-disable no-unused-vars */
-import Vue from 'vue';
-import MockAdapter from 'axios-mock-adapter';
-import setTimeoutPromise from 'spec/helpers/set_timeout_promise_helper';
-import GLDropdown from '~/gl_dropdown';
-import axios from '~/lib/utils/axios_utils';
-import '~/behaviors/markdown/render_gfm';
-import issuableApp from '~/issue_show/components/app.vue';
-import eventHub from '~/issue_show/event_hub';
-import { initialRequest, secondRequest } from '../mock_data';
-
-function formatText(text) {
- return text.trim().replace(/\s\s+/g, ' ');
-}
-
-const REALTIME_REQUEST_STACK = [initialRequest, secondRequest];
-
-describe('Issuable output', () => {
- let mock;
- let realtimeRequestCount = 0;
- let vm;
-
- beforeEach(done => {
- setFixtures(`
- <div>
- <div class="detail-page-description content-block">
- <details open>
- <summary>One</summary>
- </details>
- <details>
- <summary>Two</summary>
- </details>
- </div>
- <div class="flash-container"></div>
- <span id="task_status"></span>
- </div>
- `);
- spyOn(eventHub, '$emit');
-
- const IssuableDescriptionComponent = Vue.extend(issuableApp);
-
- mock = new MockAdapter(axios);
- mock
- .onGet('/gitlab-org/gitlab-shell/-/issues/9/realtime_changes/realtime_changes')
- .reply(() => {
- const res = Promise.resolve([200, REALTIME_REQUEST_STACK[realtimeRequestCount]]);
- realtimeRequestCount += 1;
- return res;
- });
-
- vm = new IssuableDescriptionComponent({
- propsData: {
- canUpdate: true,
- canDestroy: true,
- endpoint: '/gitlab-org/gitlab-shell/-/issues/9/realtime_changes',
- updateEndpoint: gl.TEST_HOST,
- issuableRef: '#1',
- initialTitleHtml: '',
- initialTitleText: '',
- initialDescriptionHtml: 'test',
- initialDescriptionText: 'test',
- lockVersion: 1,
- markdownPreviewPath: '/',
- markdownDocsPath: '/',
- projectNamespace: '/',
- projectPath: '/',
- issuableTemplateNamesPath: '/issuable-templates-path',
- },
- }).$mount();
-
- setTimeout(done);
- });
-
- afterEach(() => {
- mock.restore();
- realtimeRequestCount = 0;
-
- vm.poll.stop();
- vm.$destroy();
- });
-
- it('should render a title/description/edited and update title/description/edited on update', done => {
- let editedText;
- Vue.nextTick()
- .then(() => {
- editedText = vm.$el.querySelector('.edited-text');
- })
- .then(() => {
- expect(document.querySelector('title').innerText).toContain('this is a title (#1)');
- expect(vm.$el.querySelector('.title').innerHTML).toContain('<p>this is a title</p>');
- expect(vm.$el.querySelector('.md').innerHTML).toContain('<p>this is a description!</p>');
- expect(vm.$el.querySelector('.js-task-list-field').value).toContain(
- 'this is a description',
- );
-
- expect(formatText(editedText.innerText)).toMatch(/Edited[\s\S]+?by Some User/);
- expect(editedText.querySelector('.author-link').href).toMatch(/\/some_user$/);
- expect(editedText.querySelector('time')).toBeTruthy();
- expect(vm.state.lock_version).toEqual(1);
- })
- .then(() => {
- vm.poll.makeRequest();
- })
- .then(() => new Promise(resolve => setTimeout(resolve)))
- .then(() => {
- expect(document.querySelector('title').innerText).toContain('2 (#1)');
- expect(vm.$el.querySelector('.title').innerHTML).toContain('<p>2</p>');
- expect(vm.$el.querySelector('.md').innerHTML).toContain('<p>42</p>');
- expect(vm.$el.querySelector('.js-task-list-field').value).toContain('42');
- expect(vm.$el.querySelector('.edited-text')).toBeTruthy();
- expect(formatText(vm.$el.querySelector('.edited-text').innerText)).toMatch(
- /Edited[\s\S]+?by Other User/,
- );
-
- expect(editedText.querySelector('.author-link').href).toMatch(/\/other_user$/);
- expect(editedText.querySelector('time')).toBeTruthy();
- expect(vm.state.lock_version).toEqual(2);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('shows actions if permissions are correct', done => {
- vm.showForm = true;
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.btn')).not.toBeNull();
-
- done();
- });
- });
-
- it('does not show actions if permissions are incorrect', done => {
- vm.showForm = true;
- vm.canUpdate = false;
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.btn')).toBeNull();
-
- done();
- });
- });
-
- it('does not update formState if form is already open', done => {
- vm.updateAndShowForm();
-
- vm.state.titleText = 'testing 123';
-
- vm.updateAndShowForm();
-
- Vue.nextTick(() => {
- expect(vm.store.formState.title).not.toBe('testing 123');
-
- done();
- });
- });
-
- describe('updateIssuable', () => {
- it('fetches new data after update', done => {
- spyOn(vm, 'updateStoreState').and.callThrough();
- spyOn(vm.service, 'getData').and.callThrough();
- spyOn(vm.service, 'updateIssuable').and.returnValue(
- Promise.resolve({
- data: { web_url: window.location.pathname },
- }),
- );
-
- vm.updateIssuable()
- .then(() => {
- expect(vm.updateStoreState).toHaveBeenCalled();
- expect(vm.service.getData).toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('correctly updates issuable data', done => {
- spyOn(vm.service, 'updateIssuable').and.returnValue(
- Promise.resolve({
- data: { web_url: window.location.pathname },
- }),
- );
-
- vm.updateIssuable()
- .then(() => {
- expect(vm.service.updateIssuable).toHaveBeenCalledWith(vm.formState);
- expect(eventHub.$emit).toHaveBeenCalledWith('close.form');
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('does not redirect if issue has not moved', done => {
- const visitUrl = spyOnDependency(issuableApp, 'visitUrl');
- spyOn(vm.service, 'updateIssuable').and.returnValue(
- Promise.resolve({
- data: {
- web_url: window.location.pathname,
- confidential: vm.isConfidential,
- },
- }),
- );
-
- vm.updateIssuable();
-
- setTimeout(() => {
- expect(visitUrl).not.toHaveBeenCalled();
- done();
- });
- });
-
- it('redirects if returned web_url has changed', done => {
- const visitUrl = spyOnDependency(issuableApp, 'visitUrl');
- spyOn(vm.service, 'updateIssuable').and.returnValue(
- Promise.resolve({
- data: {
- web_url: '/testing-issue-move',
- confidential: vm.isConfidential,
- },
- }),
- );
-
- vm.updateIssuable();
-
- setTimeout(() => {
- expect(visitUrl).toHaveBeenCalledWith('/testing-issue-move');
- done();
- });
- });
-
- describe('shows dialog when issue has unsaved changed', () => {
- it('confirms on title change', done => {
- vm.showForm = true;
- vm.state.titleText = 'title has changed';
- const e = { returnValue: null };
- vm.handleBeforeUnloadEvent(e);
- Vue.nextTick(() => {
- expect(e.returnValue).not.toBeNull();
-
- done();
- });
- });
-
- it('confirms on description change', done => {
- vm.showForm = true;
- vm.state.descriptionText = 'description has changed';
- const e = { returnValue: null };
- vm.handleBeforeUnloadEvent(e);
- Vue.nextTick(() => {
- expect(e.returnValue).not.toBeNull();
-
- done();
- });
- });
-
- it('does nothing when nothing has changed', done => {
- const e = { returnValue: null };
- vm.handleBeforeUnloadEvent(e);
- Vue.nextTick(() => {
- expect(e.returnValue).toBeNull();
-
- done();
- });
- });
- });
-
- describe('error when updating', () => {
- it('closes form on error', done => {
- spyOn(vm.service, 'updateIssuable').and.callFake(() => Promise.reject());
- vm.updateIssuable();
-
- setTimeout(() => {
- expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form');
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
- `Error updating issue`,
- );
-
- done();
- });
- });
-
- it('returns the correct error message for issuableType', done => {
- spyOn(vm.service, 'updateIssuable').and.callFake(() => Promise.reject());
- vm.issuableType = 'merge request';
-
- Vue.nextTick(() => {
- vm.updateIssuable();
-
- setTimeout(() => {
- expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form');
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
- `Error updating merge request`,
- );
-
- done();
- });
- });
- });
-
- it('shows error message from backend if exists', done => {
- const msg = 'Custom error message from backend';
- spyOn(vm.service, 'updateIssuable').and.callFake(
- // eslint-disable-next-line prefer-promise-reject-errors
- () => Promise.reject({ response: { data: { errors: [msg] } } }),
- );
-
- vm.updateIssuable();
- setTimeout(() => {
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
- `${vm.defaultErrorMessage}. ${msg}`,
- );
-
- done();
- });
- });
- });
- });
-
- it('opens recaptcha modal if update rejected as spam', done => {
- function mockScriptSrc() {
- const recaptchaChild = vm.$children.find(
- // eslint-disable-next-line no-underscore-dangle
- child => child.$options._componentTag === 'recaptcha-modal',
- );
-
- recaptchaChild.scriptSrc = '//scriptsrc';
- }
-
- let modal;
- const promise = new Promise(resolve => {
- resolve({
- data: {
- recaptcha_html: '<div class="g-recaptcha">recaptcha_html</div>',
- },
- });
- });
-
- spyOn(vm.service, 'updateIssuable').and.returnValue(promise);
-
- vm.canUpdate = true;
- vm.showForm = true;
-
- vm.$nextTick()
- .then(() => mockScriptSrc())
- .then(() => vm.updateIssuable())
- .then(promise)
- .then(() => setTimeoutPromise())
- .then(() => {
- modal = vm.$el.querySelector('.js-recaptcha-modal');
-
- expect(modal.style.display).not.toEqual('none');
- expect(modal.querySelector('.g-recaptcha').textContent).toEqual('recaptcha_html');
- expect(document.body.querySelector('.js-recaptcha-script').src).toMatch('//scriptsrc');
- })
- .then(() => modal.querySelector('.close').click())
- .then(() => vm.$nextTick())
- .then(() => {
- expect(modal.style.display).toEqual('none');
- expect(document.body.querySelector('.js-recaptcha-script')).toBeNull();
- })
- .then(done)
- .catch(done.fail);
- });
-
- describe('deleteIssuable', () => {
- it('changes URL when deleted', done => {
- const visitUrl = spyOnDependency(issuableApp, 'visitUrl');
- spyOn(vm.service, 'deleteIssuable').and.returnValue(
- Promise.resolve({
- data: {
- web_url: '/test',
- },
- }),
- );
-
- vm.deleteIssuable();
-
- setTimeout(() => {
- expect(visitUrl).toHaveBeenCalledWith('/test');
-
- done();
- });
- });
-
- it('stops polling when deleting', done => {
- spyOnDependency(issuableApp, 'visitUrl');
- spyOn(vm.poll, 'stop').and.callThrough();
- spyOn(vm.service, 'deleteIssuable').and.returnValue(
- Promise.resolve({
- data: {
- web_url: '/test',
- },
- }),
- );
-
- vm.deleteIssuable();
-
- setTimeout(() => {
- expect(vm.poll.stop).toHaveBeenCalledWith();
-
- done();
- });
- });
-
- it('closes form on error', done => {
- spyOn(vm.service, 'deleteIssuable').and.returnValue(Promise.reject());
-
- vm.deleteIssuable();
-
- setTimeout(() => {
- expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form');
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
- 'Error deleting issue',
- );
-
- done();
- });
- });
- });
-
- describe('updateAndShowForm', () => {
- it('shows locked warning if form is open & data is different', done => {
- vm.$nextTick()
- .then(() => {
- vm.updateAndShowForm();
-
- vm.poll.makeRequest();
-
- return new Promise(resolve => {
- vm.$watch('formState.lockedWarningVisible', value => {
- if (value) resolve();
- });
- });
- })
- .then(() => {
- expect(vm.formState.lockedWarningVisible).toEqual(true);
- expect(vm.formState.lock_version).toEqual(1);
- expect(vm.$el.querySelector('.alert')).not.toBeNull();
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('requestTemplatesAndShowForm', () => {
- beforeEach(() => {
- spyOn(vm, 'updateAndShowForm');
- });
-
- it('shows the form if template names request is successful', done => {
- const mockData = [{ name: 'Bug' }];
- mock.onGet('/issuable-templates-path').reply(() => Promise.resolve([200, mockData]));
-
- vm.requestTemplatesAndShowForm()
- .then(() => {
- expect(vm.updateAndShowForm).toHaveBeenCalledWith(mockData);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('shows the form if template names request failed', done => {
- mock
- .onGet('/issuable-templates-path')
- .reply(() => Promise.reject(new Error('something went wrong')));
-
- vm.requestTemplatesAndShowForm()
- .then(() => {
- expect(document.querySelector('.flash-container .flash-text').textContent).toContain(
- 'Error updating issue',
- );
-
- expect(vm.updateAndShowForm).toHaveBeenCalledWith();
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('show inline edit button', () => {
- it('should not render by default', () => {
- expect(vm.$el.querySelector('.title-container .note-action-button')).toBeDefined();
- });
-
- it('should render if showInlineEditButton', () => {
- vm.showInlineEditButton = true;
-
- expect(vm.$el.querySelector('.title-container .note-action-button')).toBeDefined();
- });
- });
-
- describe('updateStoreState', () => {
- it('should make a request and update the state of the store', done => {
- const data = { foo: 1 };
- spyOn(vm.store, 'updateState');
- spyOn(vm.service, 'getData').and.returnValue(Promise.resolve({ data }));
-
- vm.updateStoreState()
- .then(() => {
- expect(vm.service.getData).toHaveBeenCalled();
- expect(vm.store.updateState).toHaveBeenCalledWith(data);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('should show error message if store update fails', done => {
- spyOn(vm.service, 'getData').and.returnValue(Promise.reject());
- vm.issuableType = 'merge request';
-
- vm.updateStoreState()
- .then(() => {
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
- `Error updating ${vm.issuableType}`,
- );
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('issueChanged', () => {
- beforeEach(() => {
- vm.store.formState.title = '';
- vm.store.formState.description = '';
- vm.initialDescriptionText = '';
- vm.initialTitleText = '';
- });
-
- it('returns true when title is changed', () => {
- vm.store.formState.title = 'RandomText';
-
- expect(vm.issueChanged).toBe(true);
- });
-
- it('returns false when title is empty null', () => {
- vm.store.formState.title = null;
-
- expect(vm.issueChanged).toBe(false);
- });
-
- it('returns false when `initialTitleText` is null and `formState.title` is empty string', () => {
- vm.store.formState.title = '';
- vm.initialTitleText = null;
-
- expect(vm.issueChanged).toBe(false);
- });
-
- it('returns true when description is changed', () => {
- vm.store.formState.description = 'RandomText';
-
- expect(vm.issueChanged).toBe(true);
- });
-
- it('returns false when description is empty null', () => {
- vm.store.formState.title = null;
-
- expect(vm.issueChanged).toBe(false);
- });
-
- it('returns false when `initialDescriptionText` is null and `formState.description` is empty string', () => {
- vm.store.formState.description = '';
- vm.initialDescriptionText = null;
-
- expect(vm.issueChanged).toBe(false);
- });
- });
-});
diff --git a/spec/javascripts/issue_show/components/description_spec.js b/spec/javascripts/issue_show/components/description_spec.js
deleted file mode 100644
index 83e498347f7..00000000000
--- a/spec/javascripts/issue_show/components/description_spec.js
+++ /dev/null
@@ -1,210 +0,0 @@
-import $ from 'jquery';
-import Vue from 'vue';
-import '~/behaviors/markdown/render_gfm';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import Description from '~/issue_show/components/description.vue';
-
-describe('Description component', () => {
- let vm;
- let DescriptionComponent;
- const props = {
- canUpdate: true,
- descriptionHtml: 'test',
- descriptionText: 'test',
- updatedAt: new Date().toString(),
- taskStatus: '',
- updateUrl: gl.TEST_HOST,
- };
-
- beforeEach(() => {
- DescriptionComponent = Vue.extend(Description);
-
- if (!document.querySelector('.issuable-meta')) {
- const metaData = document.createElement('div');
- metaData.classList.add('issuable-meta');
- metaData.innerHTML =
- '<div class="flash-container"></div><span id="task_status"></span><span id="task_status_short"></span>';
-
- document.body.appendChild(metaData);
- }
-
- vm = mountComponent(DescriptionComponent, props);
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- afterAll(() => {
- $('.issuable-meta .flash-container').remove();
- });
-
- it('animates description changes', done => {
- vm.descriptionHtml = 'changed';
-
- Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.md').classList.contains('issue-realtime-pre-pulse'),
- ).toBeTruthy();
-
- setTimeout(() => {
- expect(
- vm.$el.querySelector('.md').classList.contains('issue-realtime-trigger-pulse'),
- ).toBeTruthy();
-
- done();
- });
- });
- });
-
- it('opens recaptcha dialog if update rejected as spam', done => {
- let modal;
- const recaptchaChild = vm.$children.find(
- // eslint-disable-next-line no-underscore-dangle
- child => child.$options._componentTag === 'recaptcha-modal',
- );
-
- recaptchaChild.scriptSrc = '//scriptsrc';
-
- vm.taskListUpdateSuccess({
- recaptcha_html: '<div class="g-recaptcha">recaptcha_html</div>',
- });
-
- vm.$nextTick()
- .then(() => {
- modal = vm.$el.querySelector('.js-recaptcha-modal');
-
- expect(modal.style.display).not.toEqual('none');
- expect(modal.querySelector('.g-recaptcha').textContent).toEqual('recaptcha_html');
- expect(document.body.querySelector('.js-recaptcha-script').src).toMatch('//scriptsrc');
- })
- .then(() => modal.querySelector('.close').click())
- .then(() => vm.$nextTick())
- .then(() => {
- expect(modal.style.display).toEqual('none');
- expect(document.body.querySelector('.js-recaptcha-script')).toBeNull();
- })
- .then(done)
- .catch(done.fail);
- });
-
- describe('TaskList', () => {
- let TaskList;
-
- beforeEach(() => {
- vm.$destroy();
- vm = mountComponent(
- DescriptionComponent,
- Object.assign({}, props, {
- issuableType: 'issuableType',
- }),
- );
- TaskList = spyOnDependency(Description, 'TaskList');
- });
-
- it('re-inits the TaskList when description changed', done => {
- vm.descriptionHtml = 'changed';
-
- setTimeout(() => {
- expect(TaskList).toHaveBeenCalled();
- done();
- });
- });
-
- it('does not re-init the TaskList when canUpdate is false', done => {
- vm.canUpdate = false;
- vm.descriptionHtml = 'changed';
-
- setTimeout(() => {
- expect(TaskList).not.toHaveBeenCalled();
- done();
- });
- });
-
- it('calls with issuableType dataType', done => {
- vm.descriptionHtml = 'changed';
-
- setTimeout(() => {
- expect(TaskList).toHaveBeenCalledWith({
- dataType: 'issuableType',
- fieldName: 'description',
- selector: '.detail-page-description',
- onSuccess: jasmine.any(Function),
- onError: jasmine.any(Function),
- lockVersion: 0,
- });
-
- done();
- });
- });
- });
-
- describe('taskStatus', () => {
- it('adds full taskStatus', done => {
- vm.taskStatus = '1 of 1';
-
- setTimeout(() => {
- expect(document.querySelector('.issuable-meta #task_status').textContent.trim()).toBe(
- '1 of 1',
- );
-
- done();
- });
- });
-
- it('adds short taskStatus', done => {
- vm.taskStatus = '1 of 1';
-
- setTimeout(() => {
- expect(document.querySelector('.issuable-meta #task_status_short').textContent.trim()).toBe(
- '1/1 task',
- );
-
- done();
- });
- });
-
- it('clears task status text when no tasks are present', done => {
- vm.taskStatus = '0 of 0';
-
- setTimeout(() => {
- expect(document.querySelector('.issuable-meta #task_status').textContent.trim()).toBe('');
-
- done();
- });
- });
- });
-
- it('applies syntax highlighting and math when description changed', done => {
- spyOn(vm, 'renderGFM').and.callThrough();
- spyOn($.prototype, 'renderGFM').and.callThrough();
- vm.descriptionHtml = 'changed';
-
- Vue.nextTick(() => {
- setTimeout(() => {
- expect(vm.$refs['gfm-content']).toBeDefined();
- expect(vm.renderGFM).toHaveBeenCalled();
- expect($.prototype.renderGFM).toHaveBeenCalled();
-
- done();
- });
- });
- });
-
- it('sets data-update-url', () => {
- expect(vm.$el.querySelector('textarea').dataset.updateUrl).toEqual(gl.TEST_HOST);
- });
-
- describe('taskListUpdateError', () => {
- it('should create flash notification and emit an event to parent', () => {
- const msg =
- 'Someone edited this issue at the same time you did. The description has been updated and you will need to make your changes again.';
- spyOn(vm, '$emit');
-
- vm.taskListUpdateError();
-
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(msg);
- expect(vm.$emit).toHaveBeenCalledWith('taskListUpdateFailed');
- });
- });
-});
diff --git a/spec/javascripts/issue_show/components/edited_spec.js b/spec/javascripts/issue_show/components/edited_spec.js
deleted file mode 100644
index a1683f060c0..00000000000
--- a/spec/javascripts/issue_show/components/edited_spec.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import Vue from 'vue';
-import edited from '~/issue_show/components/edited.vue';
-
-function formatText(text) {
- return text.trim().replace(/\s\s+/g, ' ');
-}
-
-describe('edited', () => {
- const EditedComponent = Vue.extend(edited);
-
- it('should render an edited at+by string', () => {
- const editedComponent = new EditedComponent({
- propsData: {
- updatedAt: '2017-05-15T12:31:04.428Z',
- updatedByName: 'Some User',
- updatedByPath: '/some_user',
- },
- }).$mount();
-
- expect(formatText(editedComponent.$el.innerText)).toMatch(/Edited[\s\S]+?by Some User/);
- expect(editedComponent.$el.querySelector('.author-link').href).toMatch(/\/some_user$/);
- expect(editedComponent.$el.querySelector('time')).toBeTruthy();
- });
-
- it('if no updatedAt is provided, no time element will be rendered', () => {
- const editedComponent = new EditedComponent({
- propsData: {
- updatedByName: 'Some User',
- updatedByPath: '/some_user',
- },
- }).$mount();
-
- expect(formatText(editedComponent.$el.innerText)).toMatch(/Edited by Some User/);
- expect(editedComponent.$el.querySelector('.author-link').href).toMatch(/\/some_user$/);
- expect(editedComponent.$el.querySelector('time')).toBeFalsy();
- });
-
- it('if no updatedByName and updatedByPath is provided, no user element will be rendered', () => {
- const editedComponent = new EditedComponent({
- propsData: {
- updatedAt: '2017-05-15T12:31:04.428Z',
- },
- }).$mount();
-
- expect(formatText(editedComponent.$el.innerText)).not.toMatch(/by Some User/);
- expect(editedComponent.$el.querySelector('.author-link')).toBeFalsy();
- expect(editedComponent.$el.querySelector('time')).toBeTruthy();
- });
-});
diff --git a/spec/javascripts/issue_show/components/fields/description_template_spec.js b/spec/javascripts/issue_show/components/fields/description_template_spec.js
deleted file mode 100644
index 8d77a620d76..00000000000
--- a/spec/javascripts/issue_show/components/fields/description_template_spec.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import Vue from 'vue';
-import descriptionTemplate from '~/issue_show/components/fields/description_template.vue';
-
-describe('Issue description template component', () => {
- let vm;
- let formState;
-
- beforeEach(done => {
- const Component = Vue.extend(descriptionTemplate);
- formState = {
- description: 'test',
- };
-
- vm = new Component({
- propsData: {
- formState,
- issuableTemplates: [{ name: 'test' }],
- projectPath: '/',
- projectNamespace: '/',
- },
- }).$mount();
-
- Vue.nextTick(done);
- });
-
- it('renders templates as JSON array in data attribute', () => {
- expect(vm.$el.querySelector('.js-issuable-selector').getAttribute('data-data')).toBe(
- '[{"name":"test"}]',
- );
- });
-
- it('updates formState when changing template', () => {
- vm.issuableTemplate.editor.setValue('test new template');
-
- expect(formState.description).toBe('test new template');
- });
-
- it('returns formState description with editor getValue', () => {
- formState.description = 'testing new template';
-
- expect(vm.issuableTemplate.editor.getValue()).toBe('testing new template');
- });
-});
diff --git a/spec/javascripts/issue_show/components/form_spec.js b/spec/javascripts/issue_show/components/form_spec.js
deleted file mode 100644
index a111333ac80..00000000000
--- a/spec/javascripts/issue_show/components/form_spec.js
+++ /dev/null
@@ -1,98 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import formComponent from '~/issue_show/components/form.vue';
-import eventHub from '~/issue_show/event_hub';
-
-describe('Inline edit form component', () => {
- let vm;
- const defaultProps = {
- canDestroy: true,
- formState: {
- title: 'b',
- description: 'a',
- lockedWarningVisible: false,
- },
- issuableType: 'issue',
- markdownPreviewPath: '/',
- markdownDocsPath: '/',
- projectPath: '/',
- projectNamespace: '/',
- };
-
- afterEach(() => {
- vm.$destroy();
- });
-
- const createComponent = props => {
- const Component = Vue.extend(formComponent);
-
- vm = mountComponent(Component, {
- ...defaultProps,
- ...props,
- });
- };
-
- it('does not render template selector if no templates exist', () => {
- createComponent();
-
- expect(vm.$el.querySelector('.js-issuable-selector-wrap')).toBeNull();
- });
-
- it('renders template selector when templates exists', () => {
- createComponent({ issuableTemplates: ['test'] });
-
- expect(vm.$el.querySelector('.js-issuable-selector-wrap')).not.toBeNull();
- });
-
- it('hides locked warning by default', () => {
- createComponent();
-
- expect(vm.$el.querySelector('.alert')).toBeNull();
- });
-
- it('shows locked warning if formState is different', () => {
- createComponent({ formState: { ...defaultProps.formState, lockedWarningVisible: true } });
-
- expect(vm.$el.querySelector('.alert')).not.toBeNull();
- });
-
- it('hides locked warning when currently saving', () => {
- createComponent({
- formState: { ...defaultProps.formState, updateLoading: true, lockedWarningVisible: true },
- });
-
- expect(vm.$el.querySelector('.alert')).toBeNull();
- });
-
- describe('autosave', () => {
- let autosaveObj;
- let autosave;
-
- beforeEach(() => {
- autosaveObj = { reset: jasmine.createSpy() };
- autosave = spyOnDependency(formComponent, 'Autosave').and.returnValue(autosaveObj);
- });
-
- it('initialized Autosave on mount', () => {
- createComponent();
-
- expect(autosave).toHaveBeenCalledTimes(2);
- });
-
- it('calls reset on autosave when eventHub emits appropriate events', () => {
- createComponent();
-
- eventHub.$emit('close.form');
-
- expect(autosaveObj.reset).toHaveBeenCalledTimes(2);
-
- eventHub.$emit('delete.issuable');
-
- expect(autosaveObj.reset).toHaveBeenCalledTimes(4);
-
- eventHub.$emit('update.issuable');
-
- expect(autosaveObj.reset).toHaveBeenCalledTimes(6);
- });
- });
-});
diff --git a/spec/javascripts/issue_show/components/title_spec.js b/spec/javascripts/issue_show/components/title_spec.js
deleted file mode 100644
index 9754c8a6755..00000000000
--- a/spec/javascripts/issue_show/components/title_spec.js
+++ /dev/null
@@ -1,105 +0,0 @@
-import Vue from 'vue';
-import Store from '~/issue_show/stores';
-import titleComponent from '~/issue_show/components/title.vue';
-import eventHub from '~/issue_show/event_hub';
-
-describe('Title component', () => {
- let vm;
-
- beforeEach(() => {
- const Component = Vue.extend(titleComponent);
- const store = new Store({
- titleHtml: '',
- descriptionHtml: '',
- issuableRef: '',
- });
- vm = new Component({
- propsData: {
- issuableRef: '#1',
- titleHtml: 'Testing <img />',
- titleText: 'Testing',
- showForm: false,
- formState: store.formState,
- },
- }).$mount();
- });
-
- it('renders title HTML', () => {
- expect(vm.$el.querySelector('.title').innerHTML.trim()).toBe('Testing <img>');
- });
-
- it('updates page title when changing titleHtml', done => {
- spyOn(vm, 'setPageTitle');
- vm.titleHtml = 'test';
-
- Vue.nextTick(() => {
- expect(vm.setPageTitle).toHaveBeenCalled();
-
- done();
- });
- });
-
- it('animates title changes', done => {
- vm.titleHtml = 'test';
-
- Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.title').classList.contains('issue-realtime-pre-pulse'),
- ).toBeTruthy();
-
- setTimeout(() => {
- expect(
- vm.$el.querySelector('.title').classList.contains('issue-realtime-trigger-pulse'),
- ).toBeTruthy();
-
- done();
- });
- });
- });
-
- it('updates page title after changing title', done => {
- vm.titleHtml = 'changed';
- vm.titleText = 'changed';
-
- Vue.nextTick(() => {
- expect(document.querySelector('title').textContent.trim()).toContain('changed');
-
- done();
- });
- });
-
- describe('inline edit button', () => {
- beforeEach(() => {
- spyOn(eventHub, '$emit');
- });
-
- it('should not show by default', () => {
- expect(vm.$el.querySelector('.btn-edit')).toBeNull();
- });
-
- it('should not show if canUpdate is false', () => {
- vm.showInlineEditButton = true;
- vm.canUpdate = false;
-
- expect(vm.$el.querySelector('.btn-edit')).toBeNull();
- });
-
- it('should show if showInlineEditButton and canUpdate', () => {
- vm.showInlineEditButton = true;
- vm.canUpdate = true;
-
- expect(vm.$el.querySelector('.btn-edit')).toBeDefined();
- });
-
- it('should trigger open.form event when clicked', () => {
- vm.showInlineEditButton = true;
- vm.canUpdate = true;
-
- Vue.nextTick(() => {
- vm.$el.querySelector('.btn-edit').click();
-
- expect(eventHub.$emit).toHaveBeenCalledWith('open.form');
- });
- });
- });
-});
diff --git a/spec/javascripts/issue_show/helpers.js b/spec/javascripts/issue_show/helpers.js
deleted file mode 100644
index 951acfd4e10..00000000000
--- a/spec/javascripts/issue_show/helpers.js
+++ /dev/null
@@ -1 +0,0 @@
-export * from '../../frontend/issue_show/helpers.js';
diff --git a/spec/javascripts/issue_show/mock_data.js b/spec/javascripts/issue_show/mock_data.js
deleted file mode 100644
index 1b391bd1588..00000000000
--- a/spec/javascripts/issue_show/mock_data.js
+++ /dev/null
@@ -1 +0,0 @@
-export * from '../../frontend/issue_show/mock_data';
diff --git a/spec/javascripts/jobs/components/artifacts_block_spec.js b/spec/javascripts/jobs/components/artifacts_block_spec.js
deleted file mode 100644
index 9cb56737f3e..00000000000
--- a/spec/javascripts/jobs/components/artifacts_block_spec.js
+++ /dev/null
@@ -1,119 +0,0 @@
-import Vue from 'vue';
-import { getTimeago } from '~/lib/utils/datetime_utility';
-import component from '~/jobs/components/artifacts_block.vue';
-import mountComponent from '../../helpers/vue_mount_component_helper';
-import { trimText } from '../../helpers/text_helper';
-
-describe('Artifacts block', () => {
- const Component = Vue.extend(component);
- let vm;
-
- const expireAt = '2018-08-14T09:38:49.157Z';
- const timeago = getTimeago();
- const formattedDate = timeago.format(expireAt);
-
- const expiredArtifact = {
- expire_at: expireAt,
- expired: true,
- };
-
- const nonExpiredArtifact = {
- download_path: '/gitlab-org/gitlab-foss/-/jobs/98314558/artifacts/download',
- browse_path: '/gitlab-org/gitlab-foss/-/jobs/98314558/artifacts/browse',
- keep_path: '/gitlab-org/gitlab-foss/-/jobs/98314558/artifacts/keep',
- expire_at: expireAt,
- expired: false,
- };
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('with expired artifacts', () => {
- it('renders expired artifact date and info', () => {
- vm = mountComponent(Component, {
- artifact: expiredArtifact,
- });
-
- expect(vm.$el.querySelector('.js-artifacts-removed')).not.toBeNull();
- expect(vm.$el.querySelector('.js-artifacts-will-be-removed')).toBeNull();
- expect(trimText(vm.$el.querySelector('.js-artifacts-removed').textContent)).toEqual(
- `The artifacts were removed ${formattedDate}`,
- );
- });
- });
-
- describe('with artifacts that will expire', () => {
- it('renders will expire artifact date and info', () => {
- vm = mountComponent(Component, {
- artifact: nonExpiredArtifact,
- });
-
- expect(vm.$el.querySelector('.js-artifacts-removed')).toBeNull();
- expect(vm.$el.querySelector('.js-artifacts-will-be-removed')).not.toBeNull();
- expect(trimText(vm.$el.querySelector('.js-artifacts-will-be-removed').textContent)).toEqual(
- `The artifacts will be removed ${formattedDate}`,
- );
- });
- });
-
- describe('with keep path', () => {
- it('renders the keep button', () => {
- vm = mountComponent(Component, {
- artifact: nonExpiredArtifact,
- });
-
- expect(vm.$el.querySelector('.js-keep-artifacts')).not.toBeNull();
- });
- });
-
- describe('without keep path', () => {
- it('does not render the keep button', () => {
- vm = mountComponent(Component, {
- artifact: expiredArtifact,
- });
-
- expect(vm.$el.querySelector('.js-keep-artifacts')).toBeNull();
- });
- });
-
- describe('with download path', () => {
- it('renders the download button', () => {
- vm = mountComponent(Component, {
- artifact: nonExpiredArtifact,
- });
-
- expect(vm.$el.querySelector('.js-download-artifacts')).not.toBeNull();
- });
- });
-
- describe('without download path', () => {
- it('does not render the keep button', () => {
- vm = mountComponent(Component, {
- artifact: expiredArtifact,
- });
-
- expect(vm.$el.querySelector('.js-download-artifacts')).toBeNull();
- });
- });
-
- describe('with browse path', () => {
- it('does not render the browse button', () => {
- vm = mountComponent(Component, {
- artifact: nonExpiredArtifact,
- });
-
- expect(vm.$el.querySelector('.js-browse-artifacts')).not.toBeNull();
- });
- });
-
- describe('without browse path', () => {
- it('does not render the browse button', () => {
- vm = mountComponent(Component, {
- artifact: expiredArtifact,
- });
-
- expect(vm.$el.querySelector('.js-browse-artifacts')).toBeNull();
- });
- });
-});
diff --git a/spec/javascripts/jobs/components/commit_block_spec.js b/spec/javascripts/jobs/components/commit_block_spec.js
deleted file mode 100644
index c02f564d01a..00000000000
--- a/spec/javascripts/jobs/components/commit_block_spec.js
+++ /dev/null
@@ -1,89 +0,0 @@
-import Vue from 'vue';
-import component from '~/jobs/components/commit_block.vue';
-import mountComponent from '../../helpers/vue_mount_component_helper';
-
-describe('Commit block', () => {
- const Component = Vue.extend(component);
- let vm;
-
- const props = {
- commit: {
- short_id: '1f0fb84f',
- id: '1f0fb84fb6770d74d97eee58118fd3909cd4f48c',
- commit_path: 'commit/1f0fb84fb6770d74d97eee58118fd3909cd4f48c',
- title: 'Update README.md',
- },
- mergeRequest: {
- iid: '!21244',
- path: 'merge_requests/21244',
- },
- isLastBlock: true,
- };
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('pipeline short sha', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- ...props,
- });
- });
-
- it('renders pipeline short sha link', () => {
- expect(vm.$el.querySelector('.js-commit-sha').getAttribute('href')).toEqual(
- props.commit.commit_path,
- );
-
- expect(vm.$el.querySelector('.js-commit-sha').textContent.trim()).toEqual(
- props.commit.short_id,
- );
- });
-
- it('renders clipboard button', () => {
- expect(vm.$el.querySelector('button').getAttribute('data-clipboard-text')).toEqual(
- props.commit.id,
- );
- });
- });
-
- describe('with merge request', () => {
- it('renders merge request link and reference', () => {
- vm = mountComponent(Component, {
- ...props,
- });
-
- expect(vm.$el.querySelector('.js-link-commit').getAttribute('href')).toEqual(
- props.mergeRequest.path,
- );
-
- expect(vm.$el.querySelector('.js-link-commit').textContent.trim()).toEqual(
- `!${props.mergeRequest.iid}`,
- );
- });
- });
-
- describe('without merge request', () => {
- it('does not render merge request', () => {
- const copyProps = Object.assign({}, props);
- delete copyProps.mergeRequest;
-
- vm = mountComponent(Component, {
- ...copyProps,
- });
-
- expect(vm.$el.querySelector('.js-link-commit')).toBeNull();
- });
- });
-
- describe('git commit title', () => {
- it('renders git commit title', () => {
- vm = mountComponent(Component, {
- ...props,
- });
-
- expect(vm.$el.textContent).toContain(props.commit.title);
- });
- });
-});
diff --git a/spec/javascripts/jobs/components/empty_state_spec.js b/spec/javascripts/jobs/components/empty_state_spec.js
deleted file mode 100644
index c6eac4e27b3..00000000000
--- a/spec/javascripts/jobs/components/empty_state_spec.js
+++ /dev/null
@@ -1,141 +0,0 @@
-import Vue from 'vue';
-import component from '~/jobs/components/empty_state.vue';
-import mountComponent from '../../helpers/vue_mount_component_helper';
-
-describe('Empty State', () => {
- const Component = Vue.extend(component);
- let vm;
-
- const props = {
- illustrationPath: 'illustrations/pending_job_empty.svg',
- illustrationSizeClass: 'svg-430',
- title: 'This job has not started yet',
- playable: false,
- variablesSettingsUrl: '',
- };
-
- const content = 'This job is in pending state and is waiting to be picked by a runner';
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('renders image and title', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- ...props,
- content,
- });
- });
-
- it('renders img with provided path and size', () => {
- expect(vm.$el.querySelector('img').getAttribute('src')).toEqual(props.illustrationPath);
- expect(vm.$el.querySelector('.svg-content').classList).toContain(props.illustrationSizeClass);
- });
-
- it('renders provided title', () => {
- expect(vm.$el.querySelector('.js-job-empty-state-title').textContent.trim()).toEqual(
- props.title,
- );
- });
- });
-
- describe('with content', () => {
- it('renders content', () => {
- vm = mountComponent(Component, {
- ...props,
- content,
- });
-
- expect(vm.$el.querySelector('.js-job-empty-state-content').textContent.trim()).toEqual(
- content,
- );
- });
- });
-
- describe('without content', () => {
- it('does not render content', () => {
- vm = mountComponent(Component, {
- ...props,
- });
-
- expect(vm.$el.querySelector('.js-job-empty-state-content')).toBeNull();
- });
- });
-
- describe('with action', () => {
- it('renders action', () => {
- vm = mountComponent(Component, {
- ...props,
- content,
- action: {
- path: 'runner',
- button_title: 'Check runner',
- method: 'post',
- },
- });
-
- expect(vm.$el.querySelector('.js-job-empty-state-action').getAttribute('href')).toEqual(
- 'runner',
- );
- });
- });
-
- describe('without action', () => {
- it('does not render action', () => {
- vm = mountComponent(Component, {
- ...props,
- content,
- action: null,
- });
-
- expect(vm.$el.querySelector('.js-job-empty-state-action')).toBeNull();
- });
- });
-
- describe('without playbale action', () => {
- it('does not render manual variables form', () => {
- vm = mountComponent(Component, {
- ...props,
- content,
- });
-
- expect(vm.$el.querySelector('.js-manual-vars-form')).toBeNull();
- });
- });
-
- describe('with playbale action and not scheduled job', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- ...props,
- content,
- playable: true,
- scheduled: false,
- action: {
- path: 'runner',
- button_title: 'Check runner',
- method: 'post',
- },
- });
- });
-
- it('renders manual variables form', () => {
- expect(vm.$el.querySelector('.js-manual-vars-form')).not.toBeNull();
- });
-
- it('does not render the empty state action', () => {
- expect(vm.$el.querySelector('.js-job-empty-state-action')).toBeNull();
- });
- });
-
- describe('with playbale action and scheduled job', () => {
- it('does not render manual variables form', () => {
- vm = mountComponent(Component, {
- ...props,
- content,
- });
-
- expect(vm.$el.querySelector('.js-manual-vars-form')).toBeNull();
- });
- });
-});
diff --git a/spec/javascripts/jobs/components/environments_block_spec.js b/spec/javascripts/jobs/components/environments_block_spec.js
deleted file mode 100644
index 4f2359e83b6..00000000000
--- a/spec/javascripts/jobs/components/environments_block_spec.js
+++ /dev/null
@@ -1,261 +0,0 @@
-import Vue from 'vue';
-import component from '~/jobs/components/environments_block.vue';
-import mountComponent from '../../helpers/vue_mount_component_helper';
-
-const TEST_CLUSTER_NAME = 'test_cluster';
-const TEST_CLUSTER_PATH = 'path/to/test_cluster';
-const TEST_KUBERNETES_NAMESPACE = 'this-is-a-kubernetes-namespace';
-
-describe('Environments block', () => {
- const Component = Vue.extend(component);
- let vm;
- const status = {
- group: 'success',
- icon: 'status_success',
- label: 'passed',
- text: 'passed',
- tooltip: 'passed',
- };
-
- const environment = {
- environment_path: '/environment',
- name: 'environment',
- };
-
- const lastDeployment = { iid: 'deployment', deployable: { build_path: 'bar' } };
-
- const createEnvironmentWithLastDeployment = () => ({
- ...environment,
- last_deployment: { ...lastDeployment },
- });
-
- const createDeploymentWithCluster = () => ({ name: TEST_CLUSTER_NAME, path: TEST_CLUSTER_PATH });
-
- const createDeploymentWithClusterAndKubernetesNamespace = () => ({
- name: TEST_CLUSTER_NAME,
- path: TEST_CLUSTER_PATH,
- kubernetes_namespace: TEST_KUBERNETES_NAMESPACE,
- });
-
- const createComponent = (deploymentStatus = {}, deploymentCluster = {}) => {
- vm = mountComponent(Component, {
- deploymentStatus,
- deploymentCluster,
- iconStatus: status,
- });
- };
-
- const findText = () => vm.$el.textContent.trim();
- const findJobDeploymentLink = () => vm.$el.querySelector('.js-job-deployment-link');
- const findEnvironmentLink = () => vm.$el.querySelector('.js-environment-link');
- const findClusterLink = () => vm.$el.querySelector('.js-job-cluster-link');
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('with last deployment', () => {
- it('renders info for most recent deployment', () => {
- createComponent({
- status: 'last',
- environment,
- });
-
- expect(findText()).toEqual('This job is deployed to environment.');
- });
-
- describe('when there is a cluster', () => {
- it('renders info with cluster', () => {
- createComponent(
- {
- status: 'last',
- environment: createEnvironmentWithLastDeployment(),
- },
- createDeploymentWithCluster(),
- );
-
- expect(findText()).toEqual(
- `This job is deployed to environment using cluster ${TEST_CLUSTER_NAME}.`,
- );
- });
-
- describe('when there is a kubernetes namespace', () => {
- it('renders info with cluster', () => {
- createComponent(
- {
- status: 'last',
- environment: createEnvironmentWithLastDeployment(),
- },
- createDeploymentWithClusterAndKubernetesNamespace(),
- );
-
- expect(findText()).toEqual(
- `This job is deployed to environment using cluster ${TEST_CLUSTER_NAME} and namespace ${TEST_KUBERNETES_NAMESPACE}.`,
- );
- });
- });
- });
- });
-
- describe('with out of date deployment', () => {
- describe('with last deployment', () => {
- it('renders info for out date and most recent', () => {
- createComponent({
- status: 'out_of_date',
- environment: createEnvironmentWithLastDeployment(),
- });
-
- expect(findText()).toEqual(
- 'This job is an out-of-date deployment to environment. View the most recent deployment.',
- );
-
- expect(findJobDeploymentLink().getAttribute('href')).toEqual('bar');
- });
-
- describe('when there is a cluster', () => {
- it('renders info with cluster', () => {
- createComponent(
- {
- status: 'out_of_date',
- environment: createEnvironmentWithLastDeployment(),
- },
- createDeploymentWithCluster(),
- );
-
- expect(findText()).toEqual(
- `This job is an out-of-date deployment to environment using cluster ${TEST_CLUSTER_NAME}. View the most recent deployment.`,
- );
- });
-
- describe('when there is a kubernetes namespace', () => {
- it('renders info with cluster', () => {
- createComponent(
- {
- status: 'out_of_date',
- environment: createEnvironmentWithLastDeployment(),
- },
- createDeploymentWithClusterAndKubernetesNamespace(),
- );
-
- expect(findText()).toEqual(
- `This job is an out-of-date deployment to environment using cluster ${TEST_CLUSTER_NAME} and namespace ${TEST_KUBERNETES_NAMESPACE}. View the most recent deployment.`,
- );
- });
- });
- });
- });
-
- describe('without last deployment', () => {
- it('renders info about out of date deployment', () => {
- createComponent({
- status: 'out_of_date',
- environment,
- });
-
- expect(findText()).toEqual('This job is an out-of-date deployment to environment.');
- });
- });
- });
-
- describe('with failed deployment', () => {
- it('renders info about failed deployment', () => {
- createComponent({
- status: 'failed',
- environment,
- });
-
- expect(findText()).toEqual('The deployment of this job to environment did not succeed.');
- });
- });
-
- describe('creating deployment', () => {
- describe('with last deployment', () => {
- it('renders info about creating deployment and overriding latest deployment', () => {
- createComponent({
- status: 'creating',
- environment: createEnvironmentWithLastDeployment(),
- });
-
- expect(findText()).toEqual(
- 'This job is creating a deployment to environment. This will overwrite the latest deployment.',
- );
-
- expect(findJobDeploymentLink().getAttribute('href')).toEqual('bar');
- expect(findEnvironmentLink().getAttribute('href')).toEqual(environment.environment_path);
- expect(findClusterLink()).toBeNull();
- });
- });
-
- describe('without last deployment', () => {
- it('renders info about deployment being created', () => {
- createComponent({
- status: 'creating',
- environment,
- });
-
- expect(findText()).toEqual('This job is creating a deployment to environment.');
- });
-
- describe('when there is a cluster', () => {
- it('inclues information about the cluster', () => {
- createComponent(
- {
- status: 'creating',
- environment,
- },
- createDeploymentWithCluster(),
- );
-
- expect(findText()).toEqual(
- `This job is creating a deployment to environment using cluster ${TEST_CLUSTER_NAME}.`,
- );
- });
- });
- });
-
- describe('without environment', () => {
- it('does not render environment link', () => {
- createComponent({
- status: 'creating',
- environment: null,
- });
-
- expect(findEnvironmentLink()).toBeNull();
- });
- });
- });
-
- describe('with a cluster', () => {
- it('renders the cluster link', () => {
- createComponent(
- {
- status: 'last',
- environment: createEnvironmentWithLastDeployment(),
- },
- createDeploymentWithCluster(),
- );
-
- expect(findText()).toEqual(
- `This job is deployed to environment using cluster ${TEST_CLUSTER_NAME}.`,
- );
-
- expect(findClusterLink().getAttribute('href')).toEqual(TEST_CLUSTER_PATH);
- });
-
- describe('when the cluster is missing the path', () => {
- it('renders the name without a link', () => {
- createComponent(
- {
- status: 'last',
- environment: createEnvironmentWithLastDeployment(),
- },
- { name: 'the-cluster' },
- );
-
- expect(findText()).toContain('using cluster the-cluster.');
-
- expect(findClusterLink()).toBeNull();
- });
- });
- });
-});
diff --git a/spec/javascripts/jobs/components/job_container_item_spec.js b/spec/javascripts/jobs/components/job_container_item_spec.js
deleted file mode 100644
index 99f6d9a14d9..00000000000
--- a/spec/javascripts/jobs/components/job_container_item_spec.js
+++ /dev/null
@@ -1,99 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import JobContainerItem from '~/jobs/components/job_container_item.vue';
-import job from '../mock_data';
-
-describe('JobContainerItem', () => {
- const delayedJobFixture = getJSONFixture('jobs/delayed.json');
- const Component = Vue.extend(JobContainerItem);
- let vm;
-
- afterEach(() => {
- vm.$destroy();
- });
-
- const sharedTests = () => {
- it('displays a status icon', () => {
- expect(vm.$el).toHaveSpriteIcon(job.status.icon);
- });
-
- it('displays the job name', () => {
- expect(vm.$el).toContainText(job.name);
- });
-
- it('displays a link to the job', () => {
- const link = vm.$el.querySelector('.js-job-link');
-
- expect(link.href).toBe(job.status.details_path);
- });
- };
-
- describe('when a job is not active and not retied', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- job,
- isActive: false,
- });
- });
-
- sharedTests();
- });
-
- describe('when a job is active', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- job,
- isActive: true,
- });
- });
-
- sharedTests();
-
- it('displays an arrow', () => {
- expect(vm.$el).toHaveSpriteIcon('arrow-right');
- });
- });
-
- describe('when a job is retried', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- job: {
- ...job,
- retried: true,
- },
- isActive: false,
- });
- });
-
- sharedTests();
-
- it('displays an icon', () => {
- expect(vm.$el).toHaveSpriteIcon('retry');
- });
- });
-
- describe('for delayed job', () => {
- beforeEach(() => {
- const remainingMilliseconds = 1337000;
- spyOn(Date, 'now').and.callFake(
- () => new Date(delayedJobFixture.scheduled_at).getTime() - remainingMilliseconds,
- );
- });
-
- it('displays remaining time in tooltip', done => {
- vm = mountComponent(Component, {
- job: delayedJobFixture,
- isActive: false,
- });
-
- Vue.nextTick()
- .then(() => {
- expect(vm.$el.querySelector('.js-job-link').getAttribute('data-original-title')).toEqual(
- 'delayed job - delayed manual action (00:22:17)',
- );
- })
- .then(done)
- .catch(done.fail);
- });
- });
-});
diff --git a/spec/javascripts/jobs/components/job_log_spec.js b/spec/javascripts/jobs/components/job_log_spec.js
deleted file mode 100644
index fcaf2b3bb64..00000000000
--- a/spec/javascripts/jobs/components/job_log_spec.js
+++ /dev/null
@@ -1,65 +0,0 @@
-import Vue from 'vue';
-import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
-import component from '~/jobs/components/job_log.vue';
-import createStore from '~/jobs/store';
-import { resetStore } from '../store/helpers';
-
-describe('Job Log', () => {
- const Component = Vue.extend(component);
- let store;
- let vm;
-
- const trace =
- '<span>Running with gitlab-runner 12.1.0 (de7731dd)<br/></span><span> on docker-auto-scale-com d5ae8d25<br/></span><div class="append-right-8" data-timestamp="1565502765" data-section="prepare-executor" role="button"></div><span class="section section-header js-s-prepare-executor">Using Docker executor with image ruby:2.6 ...<br/></span>';
-
- beforeEach(() => {
- store = createStore();
- });
-
- afterEach(() => {
- resetStore(store);
- vm.$destroy();
- });
-
- it('renders provided trace', () => {
- vm = mountComponentWithStore(Component, {
- props: {
- trace,
- isComplete: true,
- },
- store,
- });
-
- expect(vm.$el.querySelector('code').textContent).toContain(
- 'Running with gitlab-runner 12.1.0 (de7731dd)',
- );
- });
-
- describe('while receiving trace', () => {
- it('renders animation', () => {
- vm = mountComponentWithStore(Component, {
- props: {
- trace,
- isComplete: false,
- },
- store,
- });
-
- expect(vm.$el.querySelector('.js-log-animation')).not.toBeNull();
- });
- });
-
- describe('when build trace has finishes', () => {
- it('does not render animation', () => {
- vm = mountComponentWithStore(Component, {
- props: {
- trace,
- isComplete: true,
- },
- store,
- });
-
- expect(vm.$el.querySelector('.js-log-animation')).toBeNull();
- });
- });
-});
diff --git a/spec/javascripts/jobs/components/jobs_container_spec.js b/spec/javascripts/jobs/components/jobs_container_spec.js
deleted file mode 100644
index 119b18b7557..00000000000
--- a/spec/javascripts/jobs/components/jobs_container_spec.js
+++ /dev/null
@@ -1,131 +0,0 @@
-import Vue from 'vue';
-import component from '~/jobs/components/jobs_container.vue';
-import mountComponent from '../../helpers/vue_mount_component_helper';
-
-describe('Jobs List block', () => {
- const Component = Vue.extend(component);
- let vm;
-
- const retried = {
- status: {
- details_path: '/gitlab-org/gitlab-foss/pipelines/28029444',
- group: 'success',
- has_details: true,
- icon: 'status_success',
- label: 'passed',
- text: 'passed',
- tooltip: 'passed',
- },
- id: 233432756,
- tooltip: 'build - passed',
- retried: true,
- };
-
- const active = {
- name: 'test',
- status: {
- details_path: '/gitlab-org/gitlab-foss/pipelines/28029444',
- group: 'success',
- has_details: true,
- icon: 'status_success',
- label: 'passed',
- text: 'passed',
- tooltip: 'passed',
- },
- id: 2322756,
- tooltip: 'build - passed',
- active: true,
- };
-
- const job = {
- name: 'build',
- status: {
- details_path: '/gitlab-org/gitlab-foss/pipelines/28029444',
- group: 'success',
- has_details: true,
- icon: 'status_success',
- label: 'passed',
- text: 'passed',
- tooltip: 'passed',
- },
- id: 232153,
- tooltip: 'build - passed',
- };
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders list of jobs', () => {
- vm = mountComponent(Component, {
- jobs: [job, retried, active],
- jobId: 12313,
- });
-
- expect(vm.$el.querySelectorAll('a').length).toEqual(3);
- });
-
- it('renders arrow right when job id matches `jobId`', () => {
- vm = mountComponent(Component, {
- jobs: [active],
- jobId: active.id,
- });
-
- expect(vm.$el.querySelector('a .js-arrow-right')).not.toBeNull();
- });
-
- it('does not render arrow right when job is not active', () => {
- vm = mountComponent(Component, {
- jobs: [job],
- jobId: active.id,
- });
-
- expect(vm.$el.querySelector('a .js-arrow-right')).toBeNull();
- });
-
- it('renders job name when present', () => {
- vm = mountComponent(Component, {
- jobs: [job],
- jobId: active.id,
- });
-
- expect(vm.$el.querySelector('a').textContent.trim()).toContain(job.name);
- expect(vm.$el.querySelector('a').textContent.trim()).not.toContain(job.id);
- });
-
- it('renders job id when job name is not available', () => {
- vm = mountComponent(Component, {
- jobs: [retried],
- jobId: active.id,
- });
-
- expect(vm.$el.querySelector('a').textContent.trim()).toContain(retried.id);
- });
-
- it('links to the job page', () => {
- vm = mountComponent(Component, {
- jobs: [job],
- jobId: active.id,
- });
-
- expect(vm.$el.querySelector('a').getAttribute('href')).toEqual(job.status.details_path);
- });
-
- it('renders retry icon when job was retried', () => {
- vm = mountComponent(Component, {
- jobs: [retried],
- jobId: active.id,
- });
-
- expect(vm.$el.querySelector('.js-retry-icon')).not.toBeNull();
- });
-
- it('does not render retry icon when job was not retried', () => {
- vm = mountComponent(Component, {
- jobs: [job],
- jobId: active.id,
- });
-
- expect(vm.$el.querySelector('.js-retry-icon')).toBeNull();
- });
-});
diff --git a/spec/javascripts/jobs/components/manual_variables_form_spec.js b/spec/javascripts/jobs/components/manual_variables_form_spec.js
deleted file mode 100644
index 82fd73ef033..00000000000
--- a/spec/javascripts/jobs/components/manual_variables_form_spec.js
+++ /dev/null
@@ -1,103 +0,0 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { GlDeprecatedButton } from '@gitlab/ui';
-import Form from '~/jobs/components/manual_variables_form.vue';
-
-const localVue = createLocalVue();
-
-describe('Manual Variables Form', () => {
- let wrapper;
-
- const requiredProps = {
- action: {
- path: '/play',
- method: 'post',
- button_title: 'Trigger this manual action',
- },
- variablesSettingsUrl: '/settings',
- };
-
- const factory = (props = {}) => {
- wrapper = shallowMount(localVue.extend(Form), {
- propsData: props,
- localVue,
- });
- };
-
- beforeEach(() => {
- factory(requiredProps);
- });
-
- afterEach(done => {
- // The component has a `nextTick` callback after some events so we need
- // to wait for those to finish before destroying.
- setImmediate(() => {
- wrapper.destroy();
- wrapper = null;
-
- done();
- });
- });
-
- it('renders empty form with correct placeholders', () => {
- expect(wrapper.find({ ref: 'inputKey' }).attributes('placeholder')).toBe('Input variable key');
- expect(wrapper.find({ ref: 'inputSecretValue' }).attributes('placeholder')).toBe(
- 'Input variable value',
- );
- });
-
- it('renders help text with provided link', () => {
- expect(wrapper.find('p').text()).toBe(
- 'Specify variable values to be used in this run. The values specified in CI/CD settings will be used as default',
- );
-
- expect(wrapper.find('a').attributes('href')).toBe(requiredProps.variablesSettingsUrl);
- });
-
- describe('when adding a new variable', () => {
- it('creates a new variable when user types a new key and resets the form', done => {
- wrapper.vm
- .$nextTick()
- .then(() => wrapper.find({ ref: 'inputKey' }).setValue('new key'))
- .then(() => {
- expect(wrapper.vm.variables.length).toBe(1);
- expect(wrapper.vm.variables[0].key).toBe('new key');
- expect(wrapper.find({ ref: 'inputKey' }).attributes('value')).toBe(undefined);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('creates a new variable when user types a new value and resets the form', done => {
- wrapper.vm
- .$nextTick()
- .then(() => wrapper.find({ ref: 'inputSecretValue' }).setValue('new value'))
- .then(() => {
- expect(wrapper.vm.variables.length).toBe(1);
- expect(wrapper.vm.variables[0].secret_value).toBe('new value');
- expect(wrapper.find({ ref: 'inputSecretValue' }).attributes('value')).toBe(undefined);
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('when deleting a variable', () => {
- beforeEach(done => {
- wrapper.vm.variables = [
- {
- key: 'new key',
- secret_value: 'value',
- id: '1',
- },
- ];
-
- wrapper.vm.$nextTick(done);
- });
-
- it('removes the variable row', () => {
- wrapper.find(GlDeprecatedButton).vm.$emit('click');
-
- expect(wrapper.vm.variables.length).toBe(0);
- });
- });
-});
diff --git a/spec/javascripts/jobs/components/sidebar_spec.js b/spec/javascripts/jobs/components/sidebar_spec.js
deleted file mode 100644
index 740bc3d0491..00000000000
--- a/spec/javascripts/jobs/components/sidebar_spec.js
+++ /dev/null
@@ -1,169 +0,0 @@
-import Vue from 'vue';
-import sidebarDetailsBlock from '~/jobs/components/sidebar.vue';
-import createStore from '~/jobs/store';
-import job, { jobsInStage } from '../mock_data';
-import { mountComponentWithStore } from '../../helpers/vue_mount_component_helper';
-import { trimText } from '../../helpers/text_helper';
-
-describe('Sidebar details block', () => {
- const SidebarComponent = Vue.extend(sidebarDetailsBlock);
- let vm;
- let store;
-
- beforeEach(() => {
- store = createStore();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('when there is no retry path retry', () => {
- it('should not render a retry button', () => {
- const copy = Object.assign({}, job);
- delete copy.retry_path;
-
- store.dispatch('receiveJobSuccess', copy);
- vm = mountComponentWithStore(SidebarComponent, {
- store,
- });
-
- expect(vm.$el.querySelector('.js-retry-button')).toBeNull();
- });
- });
-
- describe('without terminal path', () => {
- it('does not render terminal link', () => {
- store.dispatch('receiveJobSuccess', job);
- vm = mountComponentWithStore(SidebarComponent, { store });
-
- expect(vm.$el.querySelector('.js-terminal-link')).toBeNull();
- });
- });
-
- describe('with terminal path', () => {
- it('renders terminal link', () => {
- store.dispatch(
- 'receiveJobSuccess',
- Object.assign({}, job, { terminal_path: 'job/43123/terminal' }),
- );
- vm = mountComponentWithStore(SidebarComponent, {
- store,
- });
-
- expect(vm.$el.querySelector('.js-terminal-link')).not.toBeNull();
- });
- });
-
- beforeEach(() => {
- store.dispatch('receiveJobSuccess', job);
- vm = mountComponentWithStore(SidebarComponent, { store });
- });
-
- describe('actions', () => {
- it('should render link to new issue', () => {
- expect(vm.$el.querySelector('.js-new-issue').getAttribute('href')).toEqual(
- job.new_issue_path,
- );
-
- expect(vm.$el.querySelector('.js-new-issue').textContent.trim()).toEqual('New issue');
- });
-
- it('should render link to retry job', () => {
- expect(vm.$el.querySelector('.js-retry-button').getAttribute('href')).toEqual(job.retry_path);
- });
-
- it('should render link to cancel job', () => {
- expect(vm.$el.querySelector('.js-cancel-job').getAttribute('href')).toEqual(job.cancel_path);
- });
- });
-
- describe('information', () => {
- it('should render job duration', () => {
- expect(trimText(vm.$el.querySelector('.js-job-duration').textContent)).toEqual(
- 'Duration: 6 seconds',
- );
- });
-
- it('should render erased date', () => {
- expect(trimText(vm.$el.querySelector('.js-job-erased').textContent)).toEqual(
- 'Erased: 3 weeks ago',
- );
- });
-
- it('should render finished date', () => {
- expect(trimText(vm.$el.querySelector('.js-job-finished').textContent)).toEqual(
- 'Finished: 3 weeks ago',
- );
- });
-
- it('should render queued date', () => {
- expect(trimText(vm.$el.querySelector('.js-job-queued').textContent)).toEqual(
- 'Queued: 9 seconds',
- );
- });
-
- it('should render runner ID', () => {
- expect(trimText(vm.$el.querySelector('.js-job-runner').textContent)).toEqual(
- 'Runner: local ci runner (#1)',
- );
- });
-
- it('should render timeout information', () => {
- expect(trimText(vm.$el.querySelector('.js-job-timeout').textContent)).toEqual(
- 'Timeout: 1m 40s (from runner)',
- );
- });
-
- it('should render coverage', () => {
- expect(trimText(vm.$el.querySelector('.js-job-coverage').textContent)).toEqual(
- 'Coverage: 20%',
- );
- });
-
- it('should render tags', () => {
- expect(trimText(vm.$el.querySelector('.js-job-tags').textContent)).toEqual('Tags: tag');
- });
- });
-
- describe('stages dropdown', () => {
- beforeEach(() => {
- store.dispatch('receiveJobSuccess', job);
- });
-
- describe('with stages', () => {
- beforeEach(() => {
- vm = mountComponentWithStore(SidebarComponent, { store });
- });
-
- it('renders value provided as selectedStage as selected', () => {
- expect(vm.$el.querySelector('.js-selected-stage').textContent.trim()).toEqual(
- vm.selectedStage,
- );
- });
- });
-
- describe('without jobs for stages', () => {
- beforeEach(() => {
- store.dispatch('receiveJobSuccess', job);
- vm = mountComponentWithStore(SidebarComponent, { store });
- });
-
- it('does not render job container', () => {
- expect(vm.$el.querySelector('.js-jobs-container')).toBeNull();
- });
- });
-
- describe('with jobs for stages', () => {
- beforeEach(() => {
- store.dispatch('receiveJobSuccess', job);
- store.dispatch('receiveJobsForStageSuccess', jobsInStage.latest_statuses);
- vm = mountComponentWithStore(SidebarComponent, { store });
- });
-
- it('renders list of jobs', () => {
- expect(vm.$el.querySelector('.js-jobs-container')).not.toBeNull();
- });
- });
- });
-});
diff --git a/spec/javascripts/jobs/components/stages_dropdown_spec.js b/spec/javascripts/jobs/components/stages_dropdown_spec.js
deleted file mode 100644
index f1a01530104..00000000000
--- a/spec/javascripts/jobs/components/stages_dropdown_spec.js
+++ /dev/null
@@ -1,163 +0,0 @@
-import Vue from 'vue';
-import { trimText } from 'spec/helpers/text_helper';
-import component from '~/jobs/components/stages_dropdown.vue';
-import mountComponent from '../../helpers/vue_mount_component_helper';
-
-describe('Stages Dropdown', () => {
- const Component = Vue.extend(component);
- let vm;
-
- const mockPipelineData = {
- id: 28029444,
- details: {
- status: {
- details_path: '/gitlab-org/gitlab-foss/pipelines/28029444',
- group: 'success',
- has_details: true,
- icon: 'status_success',
- label: 'passed',
- text: 'passed',
- tooltip: 'passed',
- },
- },
- path: 'pipeline/28029444',
- flags: {
- merge_request_pipeline: true,
- detached_merge_request_pipeline: false,
- },
- merge_request: {
- iid: 1234,
- path: '/root/detached-merge-request-pipelines/-/merge_requests/1',
- title: 'Update README.md',
- source_branch: 'feature-1234',
- source_branch_path: '/root/detached-merge-request-pipelines/branches/feature-1234',
- target_branch: 'master',
- target_branch_path: '/root/detached-merge-request-pipelines/branches/master',
- },
- ref: {
- name: 'test-branch',
- },
- };
-
- describe('without a merge request pipeline', () => {
- let pipeline;
-
- beforeEach(() => {
- pipeline = JSON.parse(JSON.stringify(mockPipelineData));
- delete pipeline.merge_request;
- delete pipeline.flags.merge_request_pipeline;
- delete pipeline.flags.detached_merge_request_pipeline;
-
- vm = mountComponent(Component, {
- pipeline,
- stages: [{ name: 'build' }, { name: 'test' }],
- selectedStage: 'deploy',
- });
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders pipeline status', () => {
- expect(vm.$el.querySelector('.js-ci-status-icon-success')).not.toBeNull();
- });
-
- it('renders pipeline link', () => {
- expect(vm.$el.querySelector('.js-pipeline-path').getAttribute('href')).toEqual(
- 'pipeline/28029444',
- );
- });
-
- it('renders dropdown with stages', () => {
- expect(vm.$el.querySelector('.dropdown .js-stage-item').textContent).toContain('build');
- });
-
- it('rendes selected stage', () => {
- expect(vm.$el.querySelector('.dropdown .js-selected-stage').textContent).toContain('deploy');
- });
-
- it(`renders the pipeline info text like "Pipeline #123 for source_branch"`, () => {
- const expected = `Pipeline #${pipeline.id} for ${pipeline.ref.name}`;
- const actual = trimText(vm.$el.querySelector('.js-pipeline-info').innerText);
-
- expect(actual).toBe(expected);
- });
- });
-
- describe('with an "attached" merge request pipeline', () => {
- let pipeline;
-
- beforeEach(() => {
- pipeline = JSON.parse(JSON.stringify(mockPipelineData));
- pipeline.flags.merge_request_pipeline = true;
- pipeline.flags.detached_merge_request_pipeline = false;
-
- vm = mountComponent(Component, {
- pipeline,
- stages: [],
- selectedStage: 'deploy',
- });
- });
-
- it(`renders the pipeline info text like "Pipeline #123 for !456 with source_branch into target_branch"`, () => {
- const expected = `Pipeline #${pipeline.id} for !${pipeline.merge_request.iid} with ${pipeline.merge_request.source_branch} into ${pipeline.merge_request.target_branch}`;
- const actual = trimText(vm.$el.querySelector('.js-pipeline-info').innerText);
-
- expect(actual).toBe(expected);
- });
-
- it(`renders the correct merge request link`, () => {
- const actual = vm.$el.querySelector('.js-mr-link').href;
-
- expect(actual).toContain(pipeline.merge_request.path);
- });
-
- it(`renders the correct source branch link`, () => {
- const actual = vm.$el.querySelector('.js-source-branch-link').href;
-
- expect(actual).toContain(pipeline.merge_request.source_branch_path);
- });
-
- it(`renders the correct target branch link`, () => {
- const actual = vm.$el.querySelector('.js-target-branch-link').href;
-
- expect(actual).toContain(pipeline.merge_request.target_branch_path);
- });
- });
-
- describe('with a detached merge request pipeline', () => {
- let pipeline;
-
- beforeEach(() => {
- pipeline = JSON.parse(JSON.stringify(mockPipelineData));
- pipeline.flags.merge_request_pipeline = false;
- pipeline.flags.detached_merge_request_pipeline = true;
-
- vm = mountComponent(Component, {
- pipeline,
- stages: [],
- selectedStage: 'deploy',
- });
- });
-
- it(`renders the pipeline info like "Pipeline #123 for !456 with source_branch"`, () => {
- const expected = `Pipeline #${pipeline.id} for !${pipeline.merge_request.iid} with ${pipeline.merge_request.source_branch}`;
- const actual = trimText(vm.$el.querySelector('.js-pipeline-info').innerText);
-
- expect(actual).toBe(expected);
- });
-
- it(`renders the correct merge request link`, () => {
- const actual = vm.$el.querySelector('.js-mr-link').href;
-
- expect(actual).toContain(pipeline.merge_request.path);
- });
-
- it(`renders the correct source branch link`, () => {
- const actual = vm.$el.querySelector('.js-source-branch-link').href;
-
- expect(actual).toContain(pipeline.merge_request.source_branch_path);
- });
- });
-});
diff --git a/spec/javascripts/jobs/components/trigger_block_spec.js b/spec/javascripts/jobs/components/trigger_block_spec.js
deleted file mode 100644
index 448197b82c0..00000000000
--- a/spec/javascripts/jobs/components/trigger_block_spec.js
+++ /dev/null
@@ -1,100 +0,0 @@
-import Vue from 'vue';
-import component from '~/jobs/components/trigger_block.vue';
-import mountComponent from '../../helpers/vue_mount_component_helper';
-
-describe('Trigger block', () => {
- const Component = Vue.extend(component);
- let vm;
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('with short token', () => {
- it('renders short token', () => {
- vm = mountComponent(Component, {
- trigger: {
- short_token: '0a666b2',
- },
- });
-
- expect(vm.$el.querySelector('.js-short-token').textContent).toContain('0a666b2');
- });
- });
-
- describe('without short token', () => {
- it('does not render short token', () => {
- vm = mountComponent(Component, { trigger: {} });
-
- expect(vm.$el.querySelector('.js-short-token')).toBeNull();
- });
- });
-
- describe('with variables', () => {
- describe('hide/reveal variables', () => {
- it('should toggle variables on click', done => {
- vm = mountComponent(Component, {
- trigger: {
- short_token: 'bd7e',
- variables: [
- { key: 'UPLOAD_TO_GCS', value: 'false', public: false },
- { key: 'UPLOAD_TO_S3', value: 'true', public: false },
- ],
- },
- });
-
- vm.$el.querySelector('.js-reveal-variables').click();
-
- vm.$nextTick()
- .then(() => {
- expect(vm.$el.querySelector('.js-build-variables')).not.toBeNull();
- expect(vm.$el.querySelector('.js-reveal-variables').textContent.trim()).toEqual(
- 'Hide values',
- );
-
- expect(vm.$el.querySelector('.js-build-variables').textContent).toContain(
- 'UPLOAD_TO_GCS',
- );
-
- expect(vm.$el.querySelector('.js-build-variables').textContent).toContain('false');
- expect(vm.$el.querySelector('.js-build-variables').textContent).toContain(
- 'UPLOAD_TO_S3',
- );
-
- expect(vm.$el.querySelector('.js-build-variables').textContent).toContain('true');
-
- vm.$el.querySelector('.js-reveal-variables').click();
- })
- .then(vm.$nextTick)
- .then(() => {
- expect(vm.$el.querySelector('.js-reveal-variables').textContent.trim()).toEqual(
- 'Reveal values',
- );
-
- expect(vm.$el.querySelector('.js-build-variables').textContent).toContain(
- 'UPLOAD_TO_GCS',
- );
-
- expect(vm.$el.querySelector('.js-build-value').textContent).toContain('••••••');
-
- expect(vm.$el.querySelector('.js-build-variables').textContent).toContain(
- 'UPLOAD_TO_S3',
- );
-
- expect(vm.$el.querySelector('.js-build-value').textContent).toContain('••••••');
- })
- .then(done)
- .catch(done.fail);
- });
- });
- });
-
- describe('without variables', () => {
- it('does not render variables', () => {
- vm = mountComponent(Component, { trigger: {} });
-
- expect(vm.$el.querySelector('.js-reveal-variables')).toBeNull();
- expect(vm.$el.querySelector('.js-build-variables')).toBeNull();
- });
- });
-});
diff --git a/spec/javascripts/jobs/components/unmet_prerequisites_block_spec.js b/spec/javascripts/jobs/components/unmet_prerequisites_block_spec.js
deleted file mode 100644
index 68fcb321214..00000000000
--- a/spec/javascripts/jobs/components/unmet_prerequisites_block_spec.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import Vue from 'vue';
-import component from '~/jobs/components/unmet_prerequisites_block.vue';
-import mountComponent from '../../helpers/vue_mount_component_helper';
-
-describe('Unmet Prerequisites Block Job component', () => {
- const Component = Vue.extend(component);
- let vm;
- const helpPath = '/user/project/clusters/index.html#troubleshooting-failed-deployment-jobs';
-
- beforeEach(() => {
- vm = mountComponent(Component, {
- hasNoRunnersForProject: true,
- helpPath,
- });
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders an alert with the correct message', () => {
- const container = vm.$el.querySelector('.js-failed-unmet-prerequisites');
- const alertMessage =
- 'This job failed because the necessary resources were not successfully created.';
-
- expect(container).not.toBeNull();
- expect(container.innerHTML).toContain(alertMessage);
- });
-
- it('renders link to help page', () => {
- const helpLink = vm.$el.querySelector('.js-help-path');
-
- expect(helpLink).not.toBeNull();
- expect(helpLink.innerHTML).toContain('More information');
- expect(helpLink.getAttribute('href')).toEqual(helpPath);
- });
-});
diff --git a/spec/javascripts/jobs/mixins/delayed_job_mixin_spec.js b/spec/javascripts/jobs/mixins/delayed_job_mixin_spec.js
deleted file mode 100644
index b67187f1d50..00000000000
--- a/spec/javascripts/jobs/mixins/delayed_job_mixin_spec.js
+++ /dev/null
@@ -1,93 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
-
-describe('DelayedJobMixin', () => {
- const delayedJobFixture = getJSONFixture('jobs/delayed.json');
- const dummyComponent = Vue.extend({
- mixins: [delayedJobMixin],
- props: {
- job: {
- type: Object,
- required: true,
- },
- },
- template: '<div>{{ remainingTime }}</div>',
- });
-
- let vm;
-
- beforeEach(() => {
- jasmine.clock().install();
- });
-
- afterEach(() => {
- vm.$destroy();
- jasmine.clock().uninstall();
- });
-
- describe('if job is empty object', () => {
- beforeEach(() => {
- vm = mountComponent(dummyComponent, {
- job: {},
- });
- });
-
- it('sets remaining time to 00:00:00', () => {
- expect(vm.$el.innerText).toBe('00:00:00');
- });
-
- describe('after mounting', () => {
- beforeEach(done => {
- Vue.nextTick()
- .then(done)
- .catch(done.fail);
- });
-
- it('doe not update remaining time', () => {
- expect(vm.$el.innerText).toBe('00:00:00');
- });
- });
- });
-
- describe('if job is delayed job', () => {
- let remainingTimeInMilliseconds = 42000;
-
- beforeEach(() => {
- spyOn(Date, 'now').and.callFake(
- () => new Date(delayedJobFixture.scheduled_at).getTime() - remainingTimeInMilliseconds,
- );
- vm = mountComponent(dummyComponent, {
- job: delayedJobFixture,
- });
- });
-
- it('sets remaining time to 00:00:00', () => {
- expect(vm.$el.innerText).toBe('00:00:00');
- });
-
- describe('after mounting', () => {
- beforeEach(done => {
- Vue.nextTick()
- .then(done)
- .catch(done.fail);
- });
-
- it('sets remaining time', () => {
- expect(vm.$el.innerText).toBe('00:00:42');
- });
-
- it('updates remaining time', done => {
- remainingTimeInMilliseconds = 41000;
- jasmine.clock().tick(1000);
-
- Vue.nextTick()
- .then(() => {
- expect(vm.$el.innerText).toBe('00:00:41');
- })
- .then(done)
- .catch(done.fail);
- });
- });
- });
-});
diff --git a/spec/javascripts/jobs/store/actions_spec.js b/spec/javascripts/jobs/store/actions_spec.js
deleted file mode 100644
index 47257688bd5..00000000000
--- a/spec/javascripts/jobs/store/actions_spec.js
+++ /dev/null
@@ -1,512 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import testAction from 'spec/helpers/vuex_action_helper';
-import { TEST_HOST } from 'spec/test_constants';
-import axios from '~/lib/utils/axios_utils';
-import {
- setJobEndpoint,
- setTraceOptions,
- clearEtagPoll,
- stopPolling,
- requestJob,
- fetchJob,
- receiveJobSuccess,
- receiveJobError,
- scrollTop,
- scrollBottom,
- requestTrace,
- fetchTrace,
- startPollingTrace,
- stopPollingTrace,
- receiveTraceSuccess,
- receiveTraceError,
- toggleCollapsibleLine,
- requestJobsForStage,
- fetchJobsForStage,
- receiveJobsForStageSuccess,
- receiveJobsForStageError,
- hideSidebar,
- showSidebar,
- toggleSidebar,
-} from '~/jobs/store/actions';
-import state from '~/jobs/store/state';
-import * as types from '~/jobs/store/mutation_types';
-
-describe('Job State actions', () => {
- let mockedState;
-
- beforeEach(() => {
- mockedState = state();
- });
-
- describe('setJobEndpoint', () => {
- it('should commit SET_JOB_ENDPOINT mutation', done => {
- testAction(
- setJobEndpoint,
- 'job/872324.json',
- mockedState,
- [{ type: types.SET_JOB_ENDPOINT, payload: 'job/872324.json' }],
- [],
- done,
- );
- });
- });
-
- describe('setTraceOptions', () => {
- it('should commit SET_TRACE_OPTIONS mutation', done => {
- testAction(
- setTraceOptions,
- { pagePath: 'job/872324/trace.json' },
- mockedState,
- [{ type: types.SET_TRACE_OPTIONS, payload: { pagePath: 'job/872324/trace.json' } }],
- [],
- done,
- );
- });
- });
-
- describe('hideSidebar', () => {
- it('should commit HIDE_SIDEBAR mutation', done => {
- testAction(hideSidebar, null, mockedState, [{ type: types.HIDE_SIDEBAR }], [], done);
- });
- });
-
- describe('showSidebar', () => {
- it('should commit HIDE_SIDEBAR mutation', done => {
- testAction(showSidebar, null, mockedState, [{ type: types.SHOW_SIDEBAR }], [], done);
- });
- });
-
- describe('toggleSidebar', () => {
- describe('when isSidebarOpen is true', () => {
- it('should dispatch hideSidebar', done => {
- testAction(toggleSidebar, null, mockedState, [], [{ type: 'hideSidebar' }], done);
- });
- });
-
- describe('when isSidebarOpen is false', () => {
- it('should dispatch showSidebar', done => {
- mockedState.isSidebarOpen = false;
-
- testAction(toggleSidebar, null, mockedState, [], [{ type: 'showSidebar' }], done);
- });
- });
- });
-
- describe('requestJob', () => {
- it('should commit REQUEST_JOB mutation', done => {
- testAction(requestJob, null, mockedState, [{ type: types.REQUEST_JOB }], [], done);
- });
- });
-
- describe('fetchJob', () => {
- let mock;
-
- beforeEach(() => {
- mockedState.jobEndpoint = `${TEST_HOST}/endpoint.json`;
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- stopPolling();
- clearEtagPoll();
- });
-
- describe('success', () => {
- it('dispatches requestJob and receiveJobSuccess ', done => {
- mock.onGet(`${TEST_HOST}/endpoint.json`).replyOnce(200, { id: 121212, name: 'karma' });
-
- testAction(
- fetchJob,
- null,
- mockedState,
- [],
- [
- {
- type: 'requestJob',
- },
- {
- payload: { id: 121212, name: 'karma' },
- type: 'receiveJobSuccess',
- },
- ],
- done,
- );
- });
- });
-
- describe('error', () => {
- beforeEach(() => {
- mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500);
- });
-
- it('dispatches requestJob and receiveJobError ', done => {
- testAction(
- fetchJob,
- null,
- mockedState,
- [],
- [
- {
- type: 'requestJob',
- },
- {
- type: 'receiveJobError',
- },
- ],
- done,
- );
- });
- });
- });
-
- describe('receiveJobSuccess', () => {
- it('should commit RECEIVE_JOB_SUCCESS mutation', done => {
- testAction(
- receiveJobSuccess,
- { id: 121232132 },
- mockedState,
- [{ type: types.RECEIVE_JOB_SUCCESS, payload: { id: 121232132 } }],
- [],
- done,
- );
- });
- });
-
- describe('receiveJobError', () => {
- it('should commit RECEIVE_JOB_ERROR mutation', done => {
- testAction(receiveJobError, null, mockedState, [{ type: types.RECEIVE_JOB_ERROR }], [], done);
- });
- });
-
- describe('scrollTop', () => {
- it('should dispatch toggleScrollButtons action', done => {
- testAction(scrollTop, null, mockedState, [], [{ type: 'toggleScrollButtons' }], done);
- });
- });
-
- describe('scrollBottom', () => {
- it('should dispatch toggleScrollButtons action', done => {
- testAction(scrollBottom, null, mockedState, [], [{ type: 'toggleScrollButtons' }], done);
- });
- });
-
- describe('requestTrace', () => {
- it('should commit REQUEST_TRACE mutation', done => {
- testAction(requestTrace, null, mockedState, [{ type: types.REQUEST_TRACE }], [], done);
- });
- });
-
- describe('fetchTrace', () => {
- let mock;
-
- beforeEach(() => {
- mockedState.traceEndpoint = `${TEST_HOST}/endpoint`;
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- stopPolling();
- clearEtagPoll();
- });
-
- describe('success', () => {
- it('dispatches requestTrace, receiveTraceSuccess and stopPollingTrace when job is complete', done => {
- mock.onGet(`${TEST_HOST}/endpoint/trace.json`).replyOnce(200, {
- html: 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- :',
- complete: true,
- });
-
- testAction(
- fetchTrace,
- null,
- mockedState,
- [],
- [
- {
- type: 'toggleScrollisInBottom',
- payload: true,
- },
- {
- payload: {
- html: 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- :',
- complete: true,
- },
- type: 'receiveTraceSuccess',
- },
- {
- type: 'stopPollingTrace',
- },
- ],
- done,
- );
- });
-
- describe('when job is incomplete', () => {
- let tracePayload;
-
- beforeEach(() => {
- tracePayload = {
- html: 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- :',
- complete: false,
- };
-
- mock.onGet(`${TEST_HOST}/endpoint/trace.json`).replyOnce(200, tracePayload);
- });
-
- it('dispatches startPollingTrace', done => {
- testAction(
- fetchTrace,
- null,
- mockedState,
- [],
- [
- { type: 'toggleScrollisInBottom', payload: true },
- { type: 'receiveTraceSuccess', payload: tracePayload },
- { type: 'startPollingTrace' },
- ],
- done,
- );
- });
-
- it('does not dispatch startPollingTrace when timeout is non-empty', done => {
- mockedState.traceTimeout = 1;
-
- testAction(
- fetchTrace,
- null,
- mockedState,
- [],
- [
- { type: 'toggleScrollisInBottom', payload: true },
- { type: 'receiveTraceSuccess', payload: tracePayload },
- ],
- done,
- );
- });
- });
- });
-
- describe('error', () => {
- beforeEach(() => {
- mock.onGet(`${TEST_HOST}/endpoint/trace.json`).reply(500);
- });
-
- it('dispatches requestTrace and receiveTraceError ', done => {
- testAction(
- fetchTrace,
- null,
- mockedState,
- [],
- [
- {
- type: 'receiveTraceError',
- },
- ],
- done,
- );
- });
- });
- });
-
- describe('startPollingTrace', () => {
- let dispatch;
- let commit;
-
- beforeEach(() => {
- jasmine.clock().install();
-
- dispatch = jasmine.createSpy();
- commit = jasmine.createSpy();
-
- startPollingTrace({ dispatch, commit });
- });
-
- afterEach(() => {
- jasmine.clock().uninstall();
- });
-
- it('should save the timeout id but not call fetchTrace', () => {
- expect(commit).toHaveBeenCalledWith(types.SET_TRACE_TIMEOUT, 1);
- expect(dispatch).not.toHaveBeenCalledWith('fetchTrace');
- });
-
- describe('after timeout has passed', () => {
- beforeEach(() => {
- jasmine.clock().tick(4000);
- });
-
- it('should clear the timeout id and fetchTrace', () => {
- expect(commit).toHaveBeenCalledWith(types.SET_TRACE_TIMEOUT, 0);
- expect(dispatch).toHaveBeenCalledWith('fetchTrace');
- });
- });
- });
-
- describe('stopPollingTrace', () => {
- let origTimeout;
-
- beforeEach(() => {
- // Can't use spyOn(window, 'clearTimeout') because this caused unrelated specs to timeout
- // https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23838#note_280277727
- origTimeout = window.clearTimeout;
- window.clearTimeout = jasmine.createSpy();
- });
-
- afterEach(() => {
- window.clearTimeout = origTimeout;
- });
-
- it('should commit STOP_POLLING_TRACE mutation ', done => {
- const traceTimeout = 7;
-
- testAction(
- stopPollingTrace,
- null,
- { ...mockedState, traceTimeout },
- [{ type: types.SET_TRACE_TIMEOUT, payload: 0 }, { type: types.STOP_POLLING_TRACE }],
- [],
- )
- .then(() => {
- expect(window.clearTimeout).toHaveBeenCalledWith(traceTimeout);
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('receiveTraceSuccess', () => {
- it('should commit RECEIVE_TRACE_SUCCESS mutation ', done => {
- testAction(
- receiveTraceSuccess,
- 'hello world',
- mockedState,
- [{ type: types.RECEIVE_TRACE_SUCCESS, payload: 'hello world' }],
- [],
- done,
- );
- });
- });
-
- describe('receiveTraceError', () => {
- it('should commit stop polling trace', done => {
- testAction(receiveTraceError, null, mockedState, [], [{ type: 'stopPollingTrace' }], done);
- });
- });
-
- describe('toggleCollapsibleLine', () => {
- it('should commit TOGGLE_COLLAPSIBLE_LINE mutation ', done => {
- testAction(
- toggleCollapsibleLine,
- { isClosed: true },
- mockedState,
- [{ type: types.TOGGLE_COLLAPSIBLE_LINE, payload: { isClosed: true } }],
- [],
- done,
- );
- });
- });
-
- describe('requestJobsForStage', () => {
- it('should commit REQUEST_JOBS_FOR_STAGE mutation ', done => {
- testAction(
- requestJobsForStage,
- { name: 'deploy' },
- mockedState,
- [{ type: types.REQUEST_JOBS_FOR_STAGE, payload: { name: 'deploy' } }],
- [],
- done,
- );
- });
- });
-
- describe('fetchJobsForStage', () => {
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- describe('success', () => {
- it('dispatches requestJobsForStage and receiveJobsForStageSuccess ', done => {
- mock
- .onGet(`${TEST_HOST}/jobs.json`)
- .replyOnce(200, { latest_statuses: [{ id: 121212, name: 'build' }], retried: [] });
-
- testAction(
- fetchJobsForStage,
- { dropdown_path: `${TEST_HOST}/jobs.json` },
- mockedState,
- [],
- [
- {
- type: 'requestJobsForStage',
- payload: { dropdown_path: `${TEST_HOST}/jobs.json` },
- },
- {
- payload: [{ id: 121212, name: 'build' }],
- type: 'receiveJobsForStageSuccess',
- },
- ],
- done,
- );
- });
- });
-
- describe('error', () => {
- beforeEach(() => {
- mock.onGet(`${TEST_HOST}/jobs.json`).reply(500);
- });
-
- it('dispatches requestJobsForStage and receiveJobsForStageError', done => {
- testAction(
- fetchJobsForStage,
- { dropdown_path: `${TEST_HOST}/jobs.json` },
- mockedState,
- [],
- [
- {
- type: 'requestJobsForStage',
- payload: { dropdown_path: `${TEST_HOST}/jobs.json` },
- },
- {
- type: 'receiveJobsForStageError',
- },
- ],
- done,
- );
- });
- });
- });
-
- describe('receiveJobsForStageSuccess', () => {
- it('should commit RECEIVE_JOBS_FOR_STAGE_SUCCESS mutation ', done => {
- testAction(
- receiveJobsForStageSuccess,
- [{ id: 121212, name: 'karma' }],
- mockedState,
- [{ type: types.RECEIVE_JOBS_FOR_STAGE_SUCCESS, payload: [{ id: 121212, name: 'karma' }] }],
- [],
- done,
- );
- });
- });
-
- describe('receiveJobsForStageError', () => {
- it('should commit RECEIVE_JOBS_FOR_STAGE_ERROR mutation ', done => {
- testAction(
- receiveJobsForStageError,
- null,
- mockedState,
- [{ type: types.RECEIVE_JOBS_FOR_STAGE_ERROR }],
- [],
- done,
- );
- });
- });
-});
diff --git a/spec/javascripts/jobs/store/helpers.js b/spec/javascripts/jobs/store/helpers.js
deleted file mode 100644
index 81a769b4a6e..00000000000
--- a/spec/javascripts/jobs/store/helpers.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import state from '~/jobs/store/state';
-
-// eslint-disable-next-line import/prefer-default-export
-export const resetStore = store => {
- store.replaceState(state());
-};
diff --git a/spec/javascripts/landing_spec.js b/spec/javascripts/landing_spec.js
deleted file mode 100644
index bffef8fc64f..00000000000
--- a/spec/javascripts/landing_spec.js
+++ /dev/null
@@ -1,166 +0,0 @@
-import Cookies from 'js-cookie';
-import Landing from '~/landing';
-
-describe('Landing', function() {
- describe('class constructor', function() {
- beforeEach(function() {
- this.landingElement = {};
- this.dismissButton = {};
- this.cookieName = 'cookie_name';
-
- this.landing = new Landing(this.landingElement, this.dismissButton, this.cookieName);
- });
-
- it('should set .landing', function() {
- expect(this.landing.landingElement).toBe(this.landingElement);
- });
-
- it('should set .cookieName', function() {
- expect(this.landing.cookieName).toBe(this.cookieName);
- });
-
- it('should set .dismissButton', function() {
- expect(this.landing.dismissButton).toBe(this.dismissButton);
- });
-
- it('should set .eventWrapper', function() {
- expect(this.landing.eventWrapper).toEqual({});
- });
- });
-
- describe('toggle', function() {
- beforeEach(function() {
- this.isDismissed = false;
- this.landingElement = { classList: jasmine.createSpyObj('classList', ['toggle']) };
- this.landing = {
- isDismissed: () => {},
- addEvents: () => {},
- landingElement: this.landingElement,
- };
-
- spyOn(this.landing, 'isDismissed').and.returnValue(this.isDismissed);
- spyOn(this.landing, 'addEvents');
-
- Landing.prototype.toggle.call(this.landing);
- });
-
- it('should call .isDismissed', function() {
- expect(this.landing.isDismissed).toHaveBeenCalled();
- });
-
- it('should call .classList.toggle', function() {
- expect(this.landingElement.classList.toggle).toHaveBeenCalledWith('hidden', this.isDismissed);
- });
-
- it('should call .addEvents', function() {
- expect(this.landing.addEvents).toHaveBeenCalled();
- });
-
- describe('if isDismissed is true', function() {
- beforeEach(function() {
- this.isDismissed = true;
- this.landingElement = { classList: jasmine.createSpyObj('classList', ['toggle']) };
- this.landing = {
- isDismissed: () => {},
- addEvents: () => {},
- landingElement: this.landingElement,
- };
-
- spyOn(this.landing, 'isDismissed').and.returnValue(this.isDismissed);
- spyOn(this.landing, 'addEvents');
-
- this.landing.isDismissed.calls.reset();
-
- Landing.prototype.toggle.call(this.landing);
- });
-
- it('should not call .addEvents', function() {
- expect(this.landing.addEvents).not.toHaveBeenCalled();
- });
- });
- });
-
- describe('addEvents', function() {
- beforeEach(function() {
- this.dismissButton = jasmine.createSpyObj('dismissButton', ['addEventListener']);
- this.eventWrapper = {};
- this.landing = {
- eventWrapper: this.eventWrapper,
- dismissButton: this.dismissButton,
- dismissLanding: () => {},
- };
-
- Landing.prototype.addEvents.call(this.landing);
- });
-
- it('should set .eventWrapper.dismissLanding', function() {
- expect(this.eventWrapper.dismissLanding).toEqual(jasmine.any(Function));
- });
-
- it('should call .addEventListener', function() {
- expect(this.dismissButton.addEventListener).toHaveBeenCalledWith(
- 'click',
- this.eventWrapper.dismissLanding,
- );
- });
- });
-
- describe('removeEvents', function() {
- beforeEach(function() {
- this.dismissButton = jasmine.createSpyObj('dismissButton', ['removeEventListener']);
- this.eventWrapper = { dismissLanding: () => {} };
- this.landing = {
- eventWrapper: this.eventWrapper,
- dismissButton: this.dismissButton,
- };
-
- Landing.prototype.removeEvents.call(this.landing);
- });
-
- it('should call .removeEventListener', function() {
- expect(this.dismissButton.removeEventListener).toHaveBeenCalledWith(
- 'click',
- this.eventWrapper.dismissLanding,
- );
- });
- });
-
- describe('dismissLanding', function() {
- beforeEach(function() {
- this.landingElement = { classList: jasmine.createSpyObj('classList', ['add']) };
- this.cookieName = 'cookie_name';
- this.landing = { landingElement: this.landingElement, cookieName: this.cookieName };
-
- spyOn(Cookies, 'set');
-
- Landing.prototype.dismissLanding.call(this.landing);
- });
-
- it('should call .classList.add', function() {
- expect(this.landingElement.classList.add).toHaveBeenCalledWith('hidden');
- });
-
- it('should call Cookies.set', function() {
- expect(Cookies.set).toHaveBeenCalledWith(this.cookieName, 'true', { expires: 365 });
- });
- });
-
- describe('isDismissed', function() {
- beforeEach(function() {
- this.cookieName = 'cookie_name';
- this.landing = { cookieName: this.cookieName };
-
- spyOn(Cookies, 'get').and.returnValue('true');
-
- this.isDismissed = Landing.prototype.isDismissed.call(this.landing);
- });
-
- it('should call Cookies.get', function() {
- expect(Cookies.get).toHaveBeenCalledWith(this.cookieName);
- });
-
- it('should return a boolean', function() {
- expect(typeof this.isDismissed).toEqual('boolean');
- });
- });
-});
diff --git a/spec/javascripts/lib/utils/csrf_token_spec.js b/spec/javascripts/lib/utils/csrf_token_spec.js
deleted file mode 100644
index 867bee34ee5..00000000000
--- a/spec/javascripts/lib/utils/csrf_token_spec.js
+++ /dev/null
@@ -1,50 +0,0 @@
-import csrf from '~/lib/utils/csrf';
-
-describe('csrf', function() {
- beforeEach(() => {
- this.tokenKey = 'X-CSRF-Token';
- this.token =
- 'pH1cvjnP9grx2oKlhWEDvUZnJ8x2eXsIs1qzyHkF3DugSG5yTxR76CWeEZRhML2D1IeVB7NEW0t5l/axE4iJpQ==';
- });
-
- it('returns the correct headerKey', () => {
- expect(csrf.headerKey).toBe(this.tokenKey);
- });
-
- describe('when csrf token is in the DOM', () => {
- beforeEach(() => {
- setFixtures(`
- <meta name="csrf-token" content="${this.token}">
- `);
-
- csrf.init();
- });
-
- it('returns the csrf token', () => {
- expect(csrf.token).toBe(this.token);
- });
-
- it('returns the csrf headers object', () => {
- expect(csrf.headers[this.tokenKey]).toBe(this.token);
- });
- });
-
- describe('when csrf token is not in the DOM', () => {
- beforeEach(() => {
- setFixtures(`
- <meta name="some-other-token">
- `);
-
- csrf.init();
- });
-
- it('returns null for token', () => {
- expect(csrf.token).toBeNull();
- });
-
- it('returns empty object for headers', () => {
- expect(typeof csrf.headers).toBe('object');
- expect(Object.keys(csrf.headers).length).toBe(0);
- });
- });
-});
diff --git a/spec/javascripts/lib/utils/navigation_utility_spec.js b/spec/javascripts/lib/utils/navigation_utility_spec.js
deleted file mode 100644
index be620e4a27c..00000000000
--- a/spec/javascripts/lib/utils/navigation_utility_spec.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import findAndFollowLink from '~/lib/utils/navigation_utility';
-
-describe('findAndFollowLink', () => {
- it('visits a link when the selector exists', () => {
- const href = '/some/path';
- const visitUrl = spyOnDependency(findAndFollowLink, 'visitUrl');
-
- setFixtures(`<a class="my-shortcut" href="${href}">link</a>`);
-
- findAndFollowLink('.my-shortcut');
-
- expect(visitUrl).toHaveBeenCalledWith(href);
- });
-
- it('does not throw an exception when the selector does not exist', () => {
- const visitUrl = spyOnDependency(findAndFollowLink, 'visitUrl');
-
- // this should not throw an exception
- findAndFollowLink('.this-selector-does-not-exist');
-
- expect(visitUrl).not.toHaveBeenCalled();
- });
-});
diff --git a/spec/javascripts/lib/utils/poll_spec.js b/spec/javascripts/lib/utils/poll_spec.js
deleted file mode 100644
index 138041a349f..00000000000
--- a/spec/javascripts/lib/utils/poll_spec.js
+++ /dev/null
@@ -1,222 +0,0 @@
-/* eslint-disable jasmine/no-unsafe-spy */
-
-import Poll from '~/lib/utils/poll';
-import { successCodes } from '~/lib/utils/http_status';
-
-const waitForAllCallsToFinish = (service, waitForCount, successCallback) => {
- const timer = () => {
- setTimeout(() => {
- if (service.fetch.calls.count() === waitForCount) {
- successCallback();
- } else {
- timer();
- }
- }, 0);
- };
-
- timer();
-};
-
-function mockServiceCall(service, response, shouldFail = false) {
- const action = shouldFail ? Promise.reject : Promise.resolve;
- const responseObject = response;
-
- if (!responseObject.headers) responseObject.headers = {};
-
- service.fetch.and.callFake(action.bind(Promise, responseObject));
-}
-
-describe('Poll', () => {
- const service = jasmine.createSpyObj('service', ['fetch']);
- const callbacks = jasmine.createSpyObj('callbacks', ['success', 'error', 'notification']);
-
- function setup() {
- return new Poll({
- resource: service,
- method: 'fetch',
- successCallback: callbacks.success,
- errorCallback: callbacks.error,
- notificationCallback: callbacks.notification,
- }).makeRequest();
- }
-
- afterEach(() => {
- callbacks.success.calls.reset();
- callbacks.error.calls.reset();
- callbacks.notification.calls.reset();
- service.fetch.calls.reset();
- });
-
- it('calls the success callback when no header for interval is provided', done => {
- mockServiceCall(service, { status: 200 });
- setup();
-
- waitForAllCallsToFinish(service, 1, () => {
- expect(callbacks.success).toHaveBeenCalled();
- expect(callbacks.error).not.toHaveBeenCalled();
-
- done();
- });
- });
-
- it('calls the error callback when the http request returns an error', done => {
- mockServiceCall(service, { status: 500 }, true);
- setup();
-
- waitForAllCallsToFinish(service, 1, () => {
- expect(callbacks.success).not.toHaveBeenCalled();
- expect(callbacks.error).toHaveBeenCalled();
-
- done();
- });
- });
-
- it('skips the error callback when request is aborted', done => {
- mockServiceCall(service, { status: 0 }, true);
- setup();
-
- waitForAllCallsToFinish(service, 1, () => {
- expect(callbacks.success).not.toHaveBeenCalled();
- expect(callbacks.error).not.toHaveBeenCalled();
- expect(callbacks.notification).toHaveBeenCalled();
-
- done();
- });
- });
-
- it('should call the success callback when the interval header is -1', done => {
- mockServiceCall(service, { status: 200, headers: { 'poll-interval': -1 } });
- setup()
- .then(() => {
- expect(callbacks.success).toHaveBeenCalled();
- expect(callbacks.error).not.toHaveBeenCalled();
-
- done();
- })
- .catch(done.fail);
- });
-
- describe('for 2xx status code', () => {
- successCodes.forEach(httpCode => {
- it(`starts polling when http status is ${httpCode} and interval header is provided`, done => {
- mockServiceCall(service, { status: httpCode, headers: { 'poll-interval': 1 } });
-
- const Polling = new Poll({
- resource: service,
- method: 'fetch',
- data: { page: 1 },
- successCallback: callbacks.success,
- errorCallback: callbacks.error,
- });
-
- Polling.makeRequest();
-
- waitForAllCallsToFinish(service, 2, () => {
- Polling.stop();
-
- expect(service.fetch.calls.count()).toEqual(2);
- expect(service.fetch).toHaveBeenCalledWith({ page: 1 });
- expect(callbacks.success).toHaveBeenCalled();
- expect(callbacks.error).not.toHaveBeenCalled();
-
- done();
- });
- });
- });
- });
-
- describe('stop', () => {
- it('stops polling when method is called', done => {
- mockServiceCall(service, { status: 200, headers: { 'poll-interval': 1 } });
-
- const Polling = new Poll({
- resource: service,
- method: 'fetch',
- data: { page: 1 },
- successCallback: () => {
- Polling.stop();
- },
- errorCallback: callbacks.error,
- });
-
- spyOn(Polling, 'stop').and.callThrough();
-
- Polling.makeRequest();
-
- waitForAllCallsToFinish(service, 1, () => {
- expect(service.fetch.calls.count()).toEqual(1);
- expect(service.fetch).toHaveBeenCalledWith({ page: 1 });
- expect(Polling.stop).toHaveBeenCalled();
-
- done();
- });
- });
- });
-
- describe('enable', () => {
- it('should enable polling upon a response', done => {
- jasmine.clock().install();
-
- const Polling = new Poll({
- resource: service,
- method: 'fetch',
- data: { page: 1 },
- successCallback: () => {},
- });
-
- Polling.enable({
- data: { page: 4 },
- response: { status: 200, headers: { 'poll-interval': 1 } },
- });
-
- jasmine.clock().tick(1);
- jasmine.clock().uninstall();
-
- waitForAllCallsToFinish(service, 1, () => {
- Polling.stop();
-
- expect(service.fetch.calls.count()).toEqual(1);
- expect(service.fetch).toHaveBeenCalledWith({ page: 4 });
- expect(Polling.options.data).toEqual({ page: 4 });
- done();
- });
- });
- });
-
- describe('restart', () => {
- it('should restart polling when its called', done => {
- mockServiceCall(service, { status: 200, headers: { 'poll-interval': 1 } });
-
- const Polling = new Poll({
- resource: service,
- method: 'fetch',
- data: { page: 1 },
- successCallback: () => {
- Polling.stop();
- setTimeout(() => {
- Polling.restart({ data: { page: 4 } });
- }, 0);
- },
- errorCallback: callbacks.error,
- });
-
- spyOn(Polling, 'stop').and.callThrough();
- spyOn(Polling, 'enable').and.callThrough();
- spyOn(Polling, 'restart').and.callThrough();
-
- Polling.makeRequest();
-
- waitForAllCallsToFinish(service, 2, () => {
- Polling.stop();
-
- expect(service.fetch.calls.count()).toEqual(2);
- expect(service.fetch).toHaveBeenCalledWith({ page: 4 });
- expect(Polling.stop).toHaveBeenCalled();
- expect(Polling.enable).toHaveBeenCalled();
- expect(Polling.restart).toHaveBeenCalled();
- expect(Polling.options.data).toEqual({ page: 4 });
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/lib/utils/sticky_spec.js b/spec/javascripts/lib/utils/sticky_spec.js
deleted file mode 100644
index 1b1e7da1ed3..00000000000
--- a/spec/javascripts/lib/utils/sticky_spec.js
+++ /dev/null
@@ -1,66 +0,0 @@
-import { isSticky } from '~/lib/utils/sticky';
-
-describe('sticky', () => {
- let el;
-
- beforeEach(() => {
- document.body.innerHTML += `
- <div class="parent">
- <div id="js-sticky"></div>
- </div>
- `;
-
- el = document.getElementById('js-sticky');
- });
-
- afterEach(() => {
- el.parentNode.remove();
- });
-
- describe('when stuck', () => {
- it('does not remove is-stuck class', () => {
- isSticky(el, 0, el.offsetTop);
- isSticky(el, 0, el.offsetTop);
-
- expect(el.classList.contains('is-stuck')).toBeTruthy();
- });
-
- it('adds is-stuck class', () => {
- isSticky(el, 0, el.offsetTop);
-
- expect(el.classList.contains('is-stuck')).toBeTruthy();
- });
-
- it('inserts placeholder element', () => {
- isSticky(el, 0, el.offsetTop, true);
-
- expect(document.querySelector('.sticky-placeholder')).not.toBeNull();
- });
- });
-
- describe('when not stuck', () => {
- it('removes is-stuck class', () => {
- spyOn(el.classList, 'remove').and.callThrough();
-
- isSticky(el, 0, el.offsetTop);
- isSticky(el, 0, 0);
-
- expect(el.classList.remove).toHaveBeenCalledWith('is-stuck');
-
- expect(el.classList.contains('is-stuck')).toBeFalsy();
- });
-
- it('does not add is-stuck class', () => {
- isSticky(el, 0, 0);
-
- expect(el.classList.contains('is-stuck')).toBeFalsy();
- });
-
- it('removes placeholder', () => {
- isSticky(el, 0, el.offsetTop, true);
- isSticky(el, 0, 0, true);
-
- expect(document.querySelector('.sticky-placeholder')).toBeNull();
- });
- });
-});
diff --git a/spec/javascripts/line_highlighter_spec.js b/spec/javascripts/line_highlighter_spec.js
index 45b10fc3bd8..bedab0fd003 100644
--- a/spec/javascripts/line_highlighter_spec.js
+++ b/spec/javascripts/line_highlighter_spec.js
@@ -1,4 +1,4 @@
-/* eslint-disable no-else-return, dot-notation, no-return-assign, no-new, no-underscore-dangle */
+/* eslint-disable dot-notation, no-return-assign, no-new, no-underscore-dangle */
import $ from 'jquery';
import LineHighlighter from '~/line_highlighter';
@@ -8,10 +8,9 @@ describe('LineHighlighter', function() {
const clickLine = function(number, eventData = {}) {
if ($.isEmptyObject(eventData)) {
return $(`#L${number}`).click();
- } else {
- const e = $.Event('click', eventData);
- return $(`#L${number}`).trigger(e);
}
+ const e = $.Event('click', eventData);
+ return $(`#L${number}`).trigger(e);
};
beforeEach(function() {
loadFixtures('static/line_highlighter.html');
@@ -67,6 +66,16 @@ describe('LineHighlighter', function() {
expect(func).not.toThrow();
});
+
+ it('handles hashchange event', () => {
+ const highlighter = new LineHighlighter();
+
+ spyOn(highlighter, 'highlightHash');
+
+ window.dispatchEvent(new Event('hashchange'), 'L15');
+
+ expect(highlighter.highlightHash).toHaveBeenCalled();
+ });
});
describe('clickHandler', function() {
diff --git a/spec/javascripts/monitoring/components/dashboard_resize_spec.js b/spec/javascripts/monitoring/components/dashboard_resize_browser_spec.js
index 0c3193940e6..4416dbd014a 100644
--- a/spec/javascripts/monitoring/components/dashboard_resize_spec.js
+++ b/spec/javascripts/monitoring/components/dashboard_resize_browser_spec.js
@@ -1,3 +1,10 @@
+/**
+ * This file should only contain browser specific specs.
+ * If you need to add or update a spec, please see spec/frontend/monitoring/components/*.js
+ * https://gitlab.com/gitlab-org/gitlab/-/issues/194244#note_343427737
+ * https://gitlab.com/groups/gitlab-org/-/epics/895#what-if-theres-a-karma-spec-which-is-simply-unmovable-to-jest-ie-it-is-dependent-on-a-running-browser-environment
+ */
+
import Vue from 'vue';
import { createLocalVue } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
diff --git a/spec/javascripts/notebook/cells/code_spec.js b/spec/javascripts/notebook/cells/code_spec.js
deleted file mode 100644
index f3f97145ad3..00000000000
--- a/spec/javascripts/notebook/cells/code_spec.js
+++ /dev/null
@@ -1,74 +0,0 @@
-import Vue from 'vue';
-import CodeComponent from '~/notebook/cells/code.vue';
-
-const Component = Vue.extend(CodeComponent);
-
-describe('Code component', () => {
- let vm;
- let json;
-
- beforeEach(() => {
- json = getJSONFixture('blob/notebook/basic.json');
- });
-
- const setupComponent = cell => {
- const comp = new Component({
- propsData: {
- cell,
- },
- });
- comp.$mount();
- return comp;
- };
-
- describe('without output', () => {
- beforeEach(done => {
- vm = setupComponent(json.cells[0]);
-
- setTimeout(() => {
- done();
- });
- });
-
- it('does not render output prompt', () => {
- expect(vm.$el.querySelectorAll('.prompt').length).toBe(1);
- });
- });
-
- describe('with output', () => {
- beforeEach(done => {
- vm = setupComponent(json.cells[2]);
-
- setTimeout(() => {
- done();
- });
- });
-
- it('does not render output prompt', () => {
- expect(vm.$el.querySelectorAll('.prompt').length).toBe(2);
- });
-
- it('renders output cell', () => {
- expect(vm.$el.querySelector('.output')).toBeDefined();
- });
- });
-
- describe('with string for cell.source', () => {
- beforeEach(done => {
- const cell = json.cells[0];
- cell.source = cell.source.join('');
-
- vm = setupComponent(cell);
-
- setTimeout(() => {
- done();
- });
- });
-
- it('renders the same input as when cell.source is an array', () => {
- const expected = "console.log('test')";
-
- expect(vm.$el.querySelector('.input').innerText).toContain(expected);
- });
- });
-});
diff --git a/spec/javascripts/notebook/cells/markdown_spec.js b/spec/javascripts/notebook/cells/markdown_spec.js
deleted file mode 100644
index 07b18d97cd9..00000000000
--- a/spec/javascripts/notebook/cells/markdown_spec.js
+++ /dev/null
@@ -1,105 +0,0 @@
-import Vue from 'vue';
-import katex from 'katex';
-import MarkdownComponent from '~/notebook/cells/markdown.vue';
-
-const Component = Vue.extend(MarkdownComponent);
-
-window.katex = katex;
-
-describe('Markdown component', () => {
- let vm;
- let cell;
- let json;
-
- beforeEach(done => {
- json = getJSONFixture('blob/notebook/basic.json');
-
- // eslint-disable-next-line prefer-destructuring
- cell = json.cells[1];
-
- vm = new Component({
- propsData: {
- cell,
- },
- });
- vm.$mount();
-
- setTimeout(() => {
- done();
- });
- });
-
- it('does not render promot', () => {
- expect(vm.$el.querySelector('.prompt span')).toBeNull();
- });
-
- it('does not render the markdown text', () => {
- expect(vm.$el.querySelector('.markdown').innerHTML.trim()).not.toEqual(cell.source.join(''));
- });
-
- it('renders the markdown HTML', () => {
- expect(vm.$el.querySelector('.markdown h1')).not.toBeNull();
- });
-
- it('sanitizes output', done => {
- Object.assign(cell, {
- source: [
- '[XSS](data:text/html;base64,PHNjcmlwdD5hbGVydChkb2N1bWVudC5kb21haW4pPC9zY3JpcHQ+Cg==)\n',
- ],
- });
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('a').getAttribute('href')).toBeNull();
-
- done();
- });
- });
-
- describe('katex', () => {
- beforeEach(() => {
- json = getJSONFixture('blob/notebook/math.json');
- });
-
- it('renders multi-line katex', done => {
- vm = new Component({
- propsData: {
- cell: json.cells[0],
- },
- }).$mount();
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.katex')).not.toBeNull();
-
- done();
- });
- });
-
- it('renders inline katex', done => {
- vm = new Component({
- propsData: {
- cell: json.cells[1],
- },
- }).$mount();
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('p:first-child .katex')).not.toBeNull();
-
- done();
- });
- });
-
- it('renders multiple inline katex', done => {
- vm = new Component({
- propsData: {
- cell: json.cells[1],
- },
- }).$mount();
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelectorAll('p:nth-child(2) .katex').length).toBe(4);
-
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/notebook/cells/output/html_sanitize_tests.js b/spec/javascripts/notebook/cells/output/html_sanitize_tests.js
deleted file mode 100644
index 74c48f04367..00000000000
--- a/spec/javascripts/notebook/cells/output/html_sanitize_tests.js
+++ /dev/null
@@ -1,68 +0,0 @@
-export default {
- 'protocol-based JS injection: simple, no spaces': {
- input: '<a href="javascript:alert(\'XSS\');">foo</a>',
- output: '<a>foo</a>',
- },
- 'protocol-based JS injection: simple, spaces before': {
- input: '<a href="javascript :alert(\'XSS\');">foo</a>',
- output: '<a>foo</a>',
- },
- 'protocol-based JS injection: simple, spaces after': {
- input: '<a href="javascript: alert(\'XSS\');">foo</a>',
- output: '<a>foo</a>',
- },
- 'protocol-based JS injection: simple, spaces before and after': {
- input: '<a href="javascript : alert(\'XSS\');">foo</a>',
- output: '<a>foo</a>',
- },
- 'protocol-based JS injection: preceding colon': {
- input: '<a href=":javascript:alert(\'XSS\');">foo</a>',
- output: '<a>foo</a>',
- },
- 'protocol-based JS injection: UTF-8 encoding': {
- input: '<a href="javascript&#58;">foo</a>',
- output: '<a>foo</a>',
- },
- 'protocol-based JS injection: long UTF-8 encoding': {
- input: '<a href="javascript&#0058;">foo</a>',
- output: '<a>foo</a>',
- },
- 'protocol-based JS injection: long UTF-8 encoding without semicolons': {
- input:
- '<a href=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>foo</a>',
- output: '<a>foo</a>',
- },
- 'protocol-based JS injection: hex encoding': {
- input: '<a href="javascript&#x3A;">foo</a>',
- output: '<a>foo</a>',
- },
- 'protocol-based JS injection: long hex encoding': {
- input: '<a href="javascript&#x003A;">foo</a>',
- output: '<a>foo</a>',
- },
- 'protocol-based JS injection: hex encoding without semicolons': {
- input:
- '<a href=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>foo</a>',
- output: '<a>foo</a>',
- },
- 'protocol-based JS injection: null char': {
- input: '<a href=java\0script:alert("XSS")>foo</a>',
- output: '<a>foo</a>',
- },
- 'protocol-based JS injection: invalid URL char': {
- input: '<img src=javascript:alert("XSS")>',
- output: '<img>',
- },
- 'protocol-based JS injection: Unicode': {
- input: '<a href="\u0001java\u0003script:alert(\'XSS\')">foo</a>',
- output: '<a>foo</a>',
- },
- 'protocol-based JS injection: spaces and entities': {
- input: '<a href=" &#14; javascript:alert(\'XSS\');">foo</a>',
- output: '<a>foo</a>',
- },
- 'img on error': {
- input: '<img src="x" onerror="alert(document.domain)" />',
- output: '<img src="x">',
- },
-};
diff --git a/spec/javascripts/notebook/cells/output/html_spec.js b/spec/javascripts/notebook/cells/output/html_spec.js
deleted file mode 100644
index 3ee404fb187..00000000000
--- a/spec/javascripts/notebook/cells/output/html_spec.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import Vue from 'vue';
-import htmlOutput from '~/notebook/cells/output/html.vue';
-import sanitizeTests from './html_sanitize_tests';
-
-describe('html output cell', () => {
- function createComponent(rawCode) {
- const Component = Vue.extend(htmlOutput);
-
- return new Component({
- propsData: {
- rawCode,
- count: 0,
- index: 0,
- },
- }).$mount();
- }
-
- describe('sanitizes output', () => {
- Object.keys(sanitizeTests).forEach(key => {
- it(key, () => {
- const test = sanitizeTests[key];
- const vm = createComponent(test.input);
- const outputEl = [...vm.$el.querySelectorAll('div')].pop();
-
- expect(outputEl.innerHTML).toEqual(test.output);
-
- vm.$destroy();
- });
- });
- });
-});
diff --git a/spec/javascripts/notebook/cells/output/index_spec.js b/spec/javascripts/notebook/cells/output/index_spec.js
deleted file mode 100644
index 005569f1c2d..00000000000
--- a/spec/javascripts/notebook/cells/output/index_spec.js
+++ /dev/null
@@ -1,115 +0,0 @@
-import Vue from 'vue';
-import CodeComponent from '~/notebook/cells/output/index.vue';
-
-const Component = Vue.extend(CodeComponent);
-
-describe('Output component', () => {
- let vm;
- let json;
-
- const createComponent = output => {
- vm = new Component({
- propsData: {
- outputs: [].concat(output),
- count: 1,
- },
- });
- vm.$mount();
- };
-
- beforeEach(() => {
- json = getJSONFixture('blob/notebook/basic.json');
- });
-
- describe('text output', () => {
- beforeEach(done => {
- createComponent(json.cells[2].outputs[0]);
-
- setTimeout(() => {
- done();
- });
- });
-
- it('renders as plain text', () => {
- expect(vm.$el.querySelector('pre')).not.toBeNull();
- });
-
- it('renders promot', () => {
- expect(vm.$el.querySelector('.prompt span')).not.toBeNull();
- });
- });
-
- describe('image output', () => {
- beforeEach(done => {
- createComponent(json.cells[3].outputs[0]);
-
- setTimeout(() => {
- done();
- });
- });
-
- it('renders as an image', () => {
- expect(vm.$el.querySelector('img')).not.toBeNull();
- });
- });
-
- describe('html output', () => {
- it('renders raw HTML', () => {
- createComponent(json.cells[4].outputs[0]);
-
- expect(vm.$el.querySelector('p')).not.toBeNull();
- expect(vm.$el.querySelectorAll('p').length).toBe(1);
- expect(vm.$el.textContent.trim()).toContain('test');
- });
-
- it('renders multiple raw HTML outputs', () => {
- createComponent([json.cells[4].outputs[0], json.cells[4].outputs[0]]);
-
- expect(vm.$el.querySelectorAll('p').length).toBe(2);
- });
- });
-
- describe('svg output', () => {
- beforeEach(done => {
- createComponent(json.cells[5].outputs[0]);
-
- setTimeout(() => {
- done();
- });
- });
-
- it('renders as an svg', () => {
- expect(vm.$el.querySelector('svg')).not.toBeNull();
- });
- });
-
- describe('default to plain text', () => {
- beforeEach(done => {
- createComponent(json.cells[6].outputs[0]);
-
- setTimeout(() => {
- done();
- });
- });
-
- it('renders as plain text', () => {
- expect(vm.$el.querySelector('pre')).not.toBeNull();
- expect(vm.$el.textContent.trim()).toContain('testing');
- });
-
- it('renders promot', () => {
- expect(vm.$el.querySelector('.prompt span')).not.toBeNull();
- });
-
- it("renders as plain text when doesn't recognise other types", done => {
- createComponent(json.cells[7].outputs[0]);
-
- setTimeout(() => {
- expect(vm.$el.querySelector('pre')).not.toBeNull();
- expect(vm.$el.textContent.trim()).toContain('testing');
-
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/notebook/cells/prompt_spec.js b/spec/javascripts/notebook/cells/prompt_spec.js
deleted file mode 100644
index cbbcb1e68e3..00000000000
--- a/spec/javascripts/notebook/cells/prompt_spec.js
+++ /dev/null
@@ -1,56 +0,0 @@
-import Vue from 'vue';
-import PromptComponent from '~/notebook/cells/prompt.vue';
-
-const Component = Vue.extend(PromptComponent);
-
-describe('Prompt component', () => {
- let vm;
-
- describe('input', () => {
- beforeEach(done => {
- vm = new Component({
- propsData: {
- type: 'In',
- count: 1,
- },
- });
- vm.$mount();
-
- setTimeout(() => {
- done();
- });
- });
-
- it('renders in label', () => {
- expect(vm.$el.textContent.trim()).toContain('In');
- });
-
- it('renders count', () => {
- expect(vm.$el.textContent.trim()).toContain('1');
- });
- });
-
- describe('output', () => {
- beforeEach(done => {
- vm = new Component({
- propsData: {
- type: 'Out',
- count: 1,
- },
- });
- vm.$mount();
-
- setTimeout(() => {
- done();
- });
- });
-
- it('renders in label', () => {
- expect(vm.$el.textContent.trim()).toContain('Out');
- });
-
- it('renders count', () => {
- expect(vm.$el.textContent.trim()).toContain('1');
- });
- });
-});
diff --git a/spec/javascripts/notebook/index_spec.js b/spec/javascripts/notebook/index_spec.js
deleted file mode 100644
index 2e2ea5ad8af..00000000000
--- a/spec/javascripts/notebook/index_spec.js
+++ /dev/null
@@ -1,100 +0,0 @@
-import Vue from 'vue';
-import Notebook from '~/notebook/index.vue';
-
-const Component = Vue.extend(Notebook);
-
-describe('Notebook component', () => {
- let vm;
- let json;
- let jsonWithWorksheet;
-
- beforeEach(() => {
- json = getJSONFixture('blob/notebook/basic.json');
- jsonWithWorksheet = getJSONFixture('blob/notebook/worksheets.json');
- });
-
- describe('without JSON', () => {
- beforeEach(done => {
- vm = new Component({
- propsData: {
- notebook: {},
- },
- });
- vm.$mount();
-
- setTimeout(() => {
- done();
- });
- });
-
- it('does not render', () => {
- expect(vm.$el.tagName).toBeUndefined();
- });
- });
-
- describe('with JSON', () => {
- beforeEach(done => {
- vm = new Component({
- propsData: {
- notebook: json,
- codeCssClass: 'js-code-class',
- },
- });
- vm.$mount();
-
- setTimeout(() => {
- done();
- });
- });
-
- it('renders cells', () => {
- expect(vm.$el.querySelectorAll('.cell').length).toBe(json.cells.length);
- });
-
- it('renders markdown cell', () => {
- expect(vm.$el.querySelector('.markdown')).not.toBeNull();
- });
-
- it('renders code cell', () => {
- expect(vm.$el.querySelector('pre')).not.toBeNull();
- });
-
- it('add code class to code blocks', () => {
- expect(vm.$el.querySelector('.js-code-class')).not.toBeNull();
- });
- });
-
- describe('with worksheets', () => {
- beforeEach(done => {
- vm = new Component({
- propsData: {
- notebook: jsonWithWorksheet,
- codeCssClass: 'js-code-class',
- },
- });
- vm.$mount();
-
- setTimeout(() => {
- done();
- });
- });
-
- it('renders cells', () => {
- expect(vm.$el.querySelectorAll('.cell').length).toBe(
- jsonWithWorksheet.worksheets[0].cells.length,
- );
- });
-
- it('renders markdown cell', () => {
- expect(vm.$el.querySelector('.markdown')).not.toBeNull();
- });
-
- it('renders code cell', () => {
- expect(vm.$el.querySelector('pre')).not.toBeNull();
- });
-
- it('add code class to code blocks', () => {
- expect(vm.$el.querySelector('.js-code-class')).not.toBeNull();
- });
- });
-});
diff --git a/spec/javascripts/oauth_remember_me_spec.js b/spec/javascripts/oauth_remember_me_spec.js
deleted file mode 100644
index 381be82697e..00000000000
--- a/spec/javascripts/oauth_remember_me_spec.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import $ from 'jquery';
-import OAuthRememberMe from '~/pages/sessions/new/oauth_remember_me';
-
-describe('OAuthRememberMe', () => {
- preloadFixtures('static/oauth_remember_me.html');
-
- beforeEach(() => {
- loadFixtures('static/oauth_remember_me.html');
-
- new OAuthRememberMe({ container: $('#oauth-container') }).bindEvents();
- });
-
- it('adds the "remember_me" query parameter to all OAuth login buttons', () => {
- $('#oauth-container #remember_me').click();
-
- expect($('#oauth-container .oauth-login.twitter').attr('href')).toBe(
- 'http://example.com/?remember_me=1',
- );
-
- expect($('#oauth-container .oauth-login.github').attr('href')).toBe(
- 'http://example.com/?remember_me=1',
- );
-
- expect($('#oauth-container .oauth-login.facebook').attr('href')).toBe(
- 'http://example.com/?redirect_fragment=L1&remember_me=1',
- );
- });
-
- it('removes the "remember_me" query parameter from all OAuth login buttons', () => {
- $('#oauth-container #remember_me').click();
- $('#oauth-container #remember_me').click();
-
- expect($('#oauth-container .oauth-login.twitter').attr('href')).toBe('http://example.com/');
- expect($('#oauth-container .oauth-login.github').attr('href')).toBe('http://example.com/');
- expect($('#oauth-container .oauth-login.facebook').attr('href')).toBe(
- 'http://example.com/?redirect_fragment=L1',
- );
- });
-});
diff --git a/spec/javascripts/pages/admin/application_settings/account_and_limits_spec.js b/spec/javascripts/pages/admin/application_settings/account_and_limits_spec.js
deleted file mode 100644
index 6a239e307e9..00000000000
--- a/spec/javascripts/pages/admin/application_settings/account_and_limits_spec.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import $ from 'jquery';
-import initUserInternalRegexPlaceholder, {
- PLACEHOLDER_USER_EXTERNAL_DEFAULT_FALSE,
- PLACEHOLDER_USER_EXTERNAL_DEFAULT_TRUE,
-} from '~/pages/admin/application_settings/account_and_limits';
-
-describe('AccountAndLimits', () => {
- const FIXTURE = 'application_settings/accounts_and_limit.html';
- let $userDefaultExternal;
- let $userInternalRegex;
- preloadFixtures(FIXTURE);
-
- beforeEach(() => {
- loadFixtures(FIXTURE);
- initUserInternalRegexPlaceholder();
- $userDefaultExternal = $('#application_setting_user_default_external');
- $userInternalRegex = document.querySelector('#application_setting_user_default_internal_regex');
- });
-
- describe('Changing of userInternalRegex when userDefaultExternal', () => {
- it('is unchecked', () => {
- expect($userDefaultExternal.prop('checked')).toBeFalsy();
- expect($userInternalRegex.placeholder).toEqual(PLACEHOLDER_USER_EXTERNAL_DEFAULT_FALSE);
- expect($userInternalRegex.readOnly).toBeTruthy();
- });
-
- it('is checked', done => {
- if (!$userDefaultExternal.prop('checked')) $userDefaultExternal.click();
-
- expect($userDefaultExternal.prop('checked')).toBeTruthy();
- expect($userInternalRegex.placeholder).toEqual(PLACEHOLDER_USER_EXTERNAL_DEFAULT_TRUE);
- expect($userInternalRegex.readOnly).toBeFalsy();
- done();
- });
- });
-});
diff --git a/spec/javascripts/pages/admin/jobs/index/components/stop_jobs_modal_spec.js b/spec/javascripts/pages/admin/jobs/index/components/stop_jobs_modal_spec.js
deleted file mode 100644
index 9ad72e0b043..00000000000
--- a/spec/javascripts/pages/admin/jobs/index/components/stop_jobs_modal_spec.js
+++ /dev/null
@@ -1,61 +0,0 @@
-import Vue from 'vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import axios from '~/lib/utils/axios_utils';
-import stopJobsModal from '~/pages/admin/jobs/index/components/stop_jobs_modal.vue';
-
-describe('stop_jobs_modal.vue', () => {
- const props = {
- url: `${gl.TEST_HOST}/stop_jobs_modal.vue/stopAll`,
- };
- let vm;
-
- afterEach(() => {
- vm.$destroy();
- });
-
- beforeEach(() => {
- const Component = Vue.extend(stopJobsModal);
- vm = mountComponent(Component, props);
- });
-
- describe('onSubmit', () => {
- it('stops jobs and redirects to overview page', done => {
- const responseURL = `${gl.TEST_HOST}/stop_jobs_modal.vue/jobs`;
- const redirectSpy = spyOnDependency(stopJobsModal, 'redirectTo');
- spyOn(axios, 'post').and.callFake(url => {
- expect(url).toBe(props.url);
- return Promise.resolve({
- request: {
- responseURL,
- },
- });
- });
-
- vm.onSubmit()
- .then(() => {
- expect(redirectSpy).toHaveBeenCalledWith(responseURL);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('displays error if stopping jobs failed', done => {
- const dummyError = new Error('stopping jobs failed');
- const redirectSpy = spyOnDependency(stopJobsModal, 'redirectTo');
- spyOn(axios, 'post').and.callFake(url => {
- expect(url).toBe(props.url);
- return Promise.reject(dummyError);
- });
-
- vm.onSubmit()
- .then(done.fail)
- .catch(error => {
- expect(error).toBe(dummyError);
- expect(redirectSpy).not.toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
- });
- });
-});
diff --git a/spec/javascripts/pages/admin/users/new/index_spec.js b/spec/javascripts/pages/admin/users/new/index_spec.js
deleted file mode 100644
index 3896323eef7..00000000000
--- a/spec/javascripts/pages/admin/users/new/index_spec.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import $ from 'jquery';
-import UserInternalRegexHandler from '~/pages/admin/users/new/index';
-
-describe('UserInternalRegexHandler', () => {
- const FIXTURE = 'admin/users/new_with_internal_user_regex.html';
- let $userExternal;
- let $userEmail;
- let $warningMessage;
-
- preloadFixtures(FIXTURE);
-
- beforeEach(() => {
- loadFixtures(FIXTURE);
- // eslint-disable-next-line no-new
- new UserInternalRegexHandler();
- $userExternal = $('#user_external');
- $userEmail = $('#user_email');
- $warningMessage = $('#warning_external_automatically_set');
- if (!$userExternal.prop('checked')) $userExternal.prop('checked', 'checked');
- });
-
- describe('Behaviour of userExternal checkbox when', () => {
- it('matches email as internal', done => {
- expect($warningMessage.hasClass('hidden')).toBeTruthy();
-
- $userEmail.val('test@').trigger('input');
-
- expect($userExternal.prop('checked')).toBeFalsy();
- expect($warningMessage.hasClass('hidden')).toBeFalsy();
- done();
- });
-
- it('matches email as external', done => {
- expect($warningMessage.hasClass('hidden')).toBeTruthy();
-
- $userEmail.val('test.ext@').trigger('input');
-
- expect($userExternal.prop('checked')).toBeTruthy();
- expect($warningMessage.hasClass('hidden')).toBeTruthy();
- done();
- });
- });
-});
diff --git a/spec/javascripts/pages/labels/components/promote_label_modal_spec.js b/spec/javascripts/pages/labels/components/promote_label_modal_spec.js
deleted file mode 100644
index 5bad13c1ef2..00000000000
--- a/spec/javascripts/pages/labels/components/promote_label_modal_spec.js
+++ /dev/null
@@ -1,103 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import promoteLabelModal from '~/pages/projects/labels/components/promote_label_modal.vue';
-import eventHub from '~/pages/projects/labels/event_hub';
-import axios from '~/lib/utils/axios_utils';
-
-describe('Promote label modal', () => {
- let vm;
- const Component = Vue.extend(promoteLabelModal);
- const labelMockData = {
- labelTitle: 'Documentation',
- labelColor: '#5cb85c',
- labelTextColor: '#ffffff',
- url: `${gl.TEST_HOST}/dummy/promote/labels`,
- groupName: 'group',
- };
-
- describe('Modal title and description', () => {
- beforeEach(() => {
- vm = mountComponent(Component, labelMockData);
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('contains the proper description', () => {
- expect(vm.text).toContain(
- `Promoting ${labelMockData.labelTitle} will make it available for all projects inside ${labelMockData.groupName}`,
- );
- });
-
- it('contains a label span with the color', () => {
- const labelFromTitle = vm.$el.querySelector('.modal-header .label.color-label');
-
- expect(labelFromTitle.style.backgroundColor).not.toBe(null);
- expect(labelFromTitle.textContent).toContain(vm.labelTitle);
- });
- });
-
- describe('When requesting a label promotion', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- ...labelMockData,
- });
- spyOn(eventHub, '$emit');
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('redirects when a label is promoted', done => {
- const responseURL = `${gl.TEST_HOST}/dummy/endpoint`;
- spyOn(axios, 'post').and.callFake(url => {
- expect(url).toBe(labelMockData.url);
- expect(eventHub.$emit).toHaveBeenCalledWith(
- 'promoteLabelModal.requestStarted',
- labelMockData.url,
- );
- return Promise.resolve({
- request: {
- responseURL,
- },
- });
- });
-
- vm.onSubmit()
- .then(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestFinished', {
- labelUrl: labelMockData.url,
- successful: true,
- });
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('displays an error if promoting a label failed', done => {
- const dummyError = new Error('promoting label failed');
- dummyError.response = { status: 500 };
- spyOn(axios, 'post').and.callFake(url => {
- expect(url).toBe(labelMockData.url);
- expect(eventHub.$emit).toHaveBeenCalledWith(
- 'promoteLabelModal.requestStarted',
- labelMockData.url,
- );
- return Promise.reject(dummyError);
- });
-
- vm.onSubmit()
- .catch(error => {
- expect(error).toBe(dummyError);
- expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestFinished', {
- labelUrl: labelMockData.url,
- successful: false,
- });
- })
- .then(done)
- .catch(done.fail);
- });
- });
-});
diff --git a/spec/javascripts/pages/milestones/shared/components/delete_milestone_modal_spec.js b/spec/javascripts/pages/milestones/shared/components/delete_milestone_modal_spec.js
deleted file mode 100644
index 9075c8aa97a..00000000000
--- a/spec/javascripts/pages/milestones/shared/components/delete_milestone_modal_spec.js
+++ /dev/null
@@ -1,106 +0,0 @@
-import Vue from 'vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import axios from '~/lib/utils/axios_utils';
-import deleteMilestoneModal from '~/pages/milestones/shared/components/delete_milestone_modal.vue';
-import eventHub from '~/pages/milestones/shared/event_hub';
-
-describe('delete_milestone_modal.vue', () => {
- const Component = Vue.extend(deleteMilestoneModal);
- const props = {
- issueCount: 1,
- mergeRequestCount: 2,
- milestoneId: 3,
- milestoneTitle: 'my milestone title',
- milestoneUrl: `${gl.TEST_HOST}/delete_milestone_modal.vue/milestone`,
- };
- let vm;
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('onSubmit', () => {
- beforeEach(() => {
- vm = mountComponent(Component, props);
- spyOn(eventHub, '$emit');
- });
-
- it('deletes milestone and redirects to overview page', done => {
- const responseURL = `${gl.TEST_HOST}/delete_milestone_modal.vue/milestoneOverview`;
- spyOn(axios, 'delete').and.callFake(url => {
- expect(url).toBe(props.milestoneUrl);
- expect(eventHub.$emit).toHaveBeenCalledWith(
- 'deleteMilestoneModal.requestStarted',
- props.milestoneUrl,
- );
- eventHub.$emit.calls.reset();
- return Promise.resolve({
- request: {
- responseURL,
- },
- });
- });
- const redirectSpy = spyOnDependency(deleteMilestoneModal, 'redirectTo');
-
- vm.onSubmit()
- .then(() => {
- expect(redirectSpy).toHaveBeenCalledWith(responseURL);
- expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', {
- milestoneUrl: props.milestoneUrl,
- successful: true,
- });
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('displays error if deleting milestone failed', done => {
- const dummyError = new Error('deleting milestone failed');
- dummyError.response = { status: 418 };
- spyOn(axios, 'delete').and.callFake(url => {
- expect(url).toBe(props.milestoneUrl);
- expect(eventHub.$emit).toHaveBeenCalledWith(
- 'deleteMilestoneModal.requestStarted',
- props.milestoneUrl,
- );
- eventHub.$emit.calls.reset();
- return Promise.reject(dummyError);
- });
- const redirectSpy = spyOnDependency(deleteMilestoneModal, 'redirectTo');
-
- vm.onSubmit()
- .catch(error => {
- expect(error).toBe(dummyError);
- expect(redirectSpy).not.toHaveBeenCalled();
- expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', {
- milestoneUrl: props.milestoneUrl,
- successful: false,
- });
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('text', () => {
- it('contains the issue and milestone count', () => {
- vm = mountComponent(Component, props);
- const value = vm.text;
-
- expect(value).toContain('remove it from 1 issue and 2 merge requests');
- });
-
- it('contains neither issue nor milestone count', () => {
- vm = mountComponent(Component, {
- ...props,
- issueCount: 0,
- mergeRequestCount: 0,
- });
-
- const value = vm.text;
-
- expect(value).toContain('is not currently used');
- });
- });
-});
diff --git a/spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js b/spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js
deleted file mode 100644
index 78c0070187c..00000000000
--- a/spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js
+++ /dev/null
@@ -1,98 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import promoteMilestoneModal from '~/pages/milestones/shared/components/promote_milestone_modal.vue';
-import eventHub from '~/pages/milestones/shared/event_hub';
-import axios from '~/lib/utils/axios_utils';
-
-describe('Promote milestone modal', () => {
- let vm;
- const Component = Vue.extend(promoteMilestoneModal);
- const milestoneMockData = {
- milestoneTitle: 'v1.0',
- url: `${gl.TEST_HOST}/dummy/promote/milestones`,
- groupName: 'group',
- };
-
- describe('Modal title and description', () => {
- beforeEach(() => {
- vm = mountComponent(Component, milestoneMockData);
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('contains the proper description', () => {
- expect(vm.text).toContain(
- `Promoting ${milestoneMockData.milestoneTitle} will make it available for all projects inside ${milestoneMockData.groupName}.`,
- );
- });
-
- it('contains the correct title', () => {
- expect(vm.title).toEqual('Promote v1.0 to group milestone?');
- });
- });
-
- describe('When requesting a milestone promotion', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- ...milestoneMockData,
- });
- spyOn(eventHub, '$emit');
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('redirects when a milestone is promoted', done => {
- const responseURL = `${gl.TEST_HOST}/dummy/endpoint`;
- spyOn(axios, 'post').and.callFake(url => {
- expect(url).toBe(milestoneMockData.url);
- expect(eventHub.$emit).toHaveBeenCalledWith(
- 'promoteMilestoneModal.requestStarted',
- milestoneMockData.url,
- );
- return Promise.resolve({
- request: {
- responseURL,
- },
- });
- });
-
- vm.onSubmit()
- .then(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('promoteMilestoneModal.requestFinished', {
- milestoneUrl: milestoneMockData.url,
- successful: true,
- });
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('displays an error if promoting a milestone failed', done => {
- const dummyError = new Error('promoting milestone failed');
- dummyError.response = { status: 500 };
- spyOn(axios, 'post').and.callFake(url => {
- expect(url).toBe(milestoneMockData.url);
- expect(eventHub.$emit).toHaveBeenCalledWith(
- 'promoteMilestoneModal.requestStarted',
- milestoneMockData.url,
- );
- return Promise.reject(dummyError);
- });
-
- vm.onSubmit()
- .catch(error => {
- expect(error).toBe(dummyError);
- expect(eventHub.$emit).toHaveBeenCalledWith('promoteMilestoneModal.requestFinished', {
- milestoneUrl: milestoneMockData.url,
- successful: false,
- });
- })
- .then(done)
- .catch(done.fail);
- });
- });
-});
diff --git a/spec/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js b/spec/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js
deleted file mode 100644
index b20bc96f9be..00000000000
--- a/spec/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js
+++ /dev/null
@@ -1,192 +0,0 @@
-import Vue from 'vue';
-import Translate from '~/vue_shared/translate';
-import IntervalPatternInput from '~/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue';
-
-Vue.use(Translate);
-
-const IntervalPatternInputComponent = Vue.extend(IntervalPatternInput);
-const inputNameAttribute = 'schedule[cron]';
-
-const cronIntervalPresets = {
- everyDay: '0 4 * * *',
- everyWeek: '0 4 * * 0',
- everyMonth: '0 4 1 * *',
-};
-
-window.gl = window.gl || {};
-
-window.gl.pipelineScheduleFieldErrors = {
- updateFormValidityState: () => {},
-};
-
-describe('Interval Pattern Input Component', function() {
- describe('when prop initialCronInterval is passed (edit)', function() {
- describe('when prop initialCronInterval is custom', function() {
- beforeEach(function() {
- this.initialCronInterval = '1 2 3 4 5';
- this.intervalPatternComponent = new IntervalPatternInputComponent({
- propsData: {
- initialCronInterval: this.initialCronInterval,
- },
- }).$mount();
- });
-
- it('is initialized as a Vue component', function() {
- expect(this.intervalPatternComponent).toBeDefined();
- });
-
- it('prop initialCronInterval is set', function() {
- expect(this.intervalPatternComponent.initialCronInterval).toBe(this.initialCronInterval);
- });
-
- it('sets isEditable to true', function(done) {
- Vue.nextTick(() => {
- expect(this.intervalPatternComponent.isEditable).toBe(true);
- done();
- });
- });
- });
-
- describe('when prop initialCronInterval is preset', function() {
- beforeEach(function() {
- this.intervalPatternComponent = new IntervalPatternInputComponent({
- propsData: {
- inputNameAttribute,
- initialCronInterval: '0 4 * * *',
- },
- }).$mount();
- });
-
- it('is initialized as a Vue component', function() {
- expect(this.intervalPatternComponent).toBeDefined();
- });
-
- it('sets isEditable to false', function(done) {
- Vue.nextTick(() => {
- expect(this.intervalPatternComponent.isEditable).toBe(false);
- done();
- });
- });
- });
- });
-
- describe('when prop initialCronInterval is not passed (new)', function() {
- beforeEach(function() {
- this.intervalPatternComponent = new IntervalPatternInputComponent({
- propsData: {
- inputNameAttribute,
- },
- }).$mount();
- });
-
- it('is initialized as a Vue component', function() {
- expect(this.intervalPatternComponent).toBeDefined();
- });
-
- it('prop initialCronInterval is set', function() {
- const defaultInitialCronInterval = '';
-
- expect(this.intervalPatternComponent.initialCronInterval).toBe(defaultInitialCronInterval);
- });
-
- it('sets isEditable to true', function(done) {
- Vue.nextTick(() => {
- expect(this.intervalPatternComponent.isEditable).toBe(true);
- done();
- });
- });
- });
-
- describe('User Actions', function() {
- beforeEach(function() {
- // For an unknown reason, some browsers do not propagate click events
- // on radio buttons in a way Vue can register. So, we have to mount
- // to a fixture.
- setFixtures('<div id="my-mount"></div>');
-
- this.initialCronInterval = '1 2 3 4 5';
- this.intervalPatternComponent = new IntervalPatternInputComponent({
- propsData: {
- initialCronInterval: this.initialCronInterval,
- },
- }).$mount('#my-mount');
- });
-
- it('cronInterval is updated when everyday preset interval is selected', function(done) {
- this.intervalPatternComponent.$el.querySelector('#every-day').click();
-
- Vue.nextTick(() => {
- expect(this.intervalPatternComponent.cronInterval).toBe(cronIntervalPresets.everyDay);
- expect(this.intervalPatternComponent.$el.querySelector('.cron-interval-input').value).toBe(
- cronIntervalPresets.everyDay,
- );
- done();
- });
- });
-
- it('cronInterval is updated when everyweek preset interval is selected', function(done) {
- this.intervalPatternComponent.$el.querySelector('#every-week').click();
-
- Vue.nextTick(() => {
- expect(this.intervalPatternComponent.cronInterval).toBe(cronIntervalPresets.everyWeek);
- expect(this.intervalPatternComponent.$el.querySelector('.cron-interval-input').value).toBe(
- cronIntervalPresets.everyWeek,
- );
-
- done();
- });
- });
-
- it('cronInterval is updated when everymonth preset interval is selected', function(done) {
- this.intervalPatternComponent.$el.querySelector('#every-month').click();
-
- Vue.nextTick(() => {
- expect(this.intervalPatternComponent.cronInterval).toBe(cronIntervalPresets.everyMonth);
- expect(this.intervalPatternComponent.$el.querySelector('.cron-interval-input').value).toBe(
- cronIntervalPresets.everyMonth,
- );
- done();
- });
- });
-
- it('only a space is added to cronInterval (trimmed later) when custom radio is selected', function(done) {
- this.intervalPatternComponent.$el.querySelector('#every-month').click();
- this.intervalPatternComponent.$el.querySelector('#custom').click();
-
- Vue.nextTick(() => {
- const intervalWithSpaceAppended = `${cronIntervalPresets.everyMonth} `;
-
- expect(this.intervalPatternComponent.cronInterval).toBe(intervalWithSpaceAppended);
- expect(this.intervalPatternComponent.$el.querySelector('.cron-interval-input').value).toBe(
- intervalWithSpaceAppended,
- );
- done();
- });
- });
-
- it('text input is disabled when preset interval is selected', function(done) {
- this.intervalPatternComponent.$el.querySelector('#every-month').click();
-
- Vue.nextTick(() => {
- expect(this.intervalPatternComponent.isEditable).toBe(false);
- expect(
- this.intervalPatternComponent.$el.querySelector('.cron-interval-input').disabled,
- ).toBe(true);
- done();
- });
- });
-
- it('text input is enabled when custom is selected', function(done) {
- this.intervalPatternComponent.$el.querySelector('#every-month').click();
- this.intervalPatternComponent.$el.querySelector('#custom').click();
-
- Vue.nextTick(() => {
- expect(this.intervalPatternComponent.isEditable).toBe(true);
- expect(
- this.intervalPatternComponent.$el.querySelector('.cron-interval-input').disabled,
- ).toBe(false);
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js b/spec/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js
deleted file mode 100644
index ea809e1f170..00000000000
--- a/spec/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js
+++ /dev/null
@@ -1,106 +0,0 @@
-import Vue from 'vue';
-import Cookies from 'js-cookie';
-import PipelineSchedulesCallout from '~/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue';
-
-const PipelineSchedulesCalloutComponent = Vue.extend(PipelineSchedulesCallout);
-const cookieKey = 'pipeline_schedules_callout_dismissed';
-const docsUrl = 'help/ci/scheduled_pipelines';
-
-describe('Pipeline Schedule Callout', function() {
- beforeEach(() => {
- setFixtures(`
- <div id='pipeline-schedules-callout' data-docs-url=${docsUrl}></div>
- `);
- });
-
- describe('independent of cookies', () => {
- beforeEach(() => {
- this.calloutComponent = new PipelineSchedulesCalloutComponent().$mount();
- });
-
- it('the component can be initialized', () => {
- expect(this.calloutComponent).toBeDefined();
- });
-
- it('correctly sets illustrationSvg', () => {
- expect(this.calloutComponent.illustrationSvg).toContain('<svg');
- });
-
- it('correctly sets docsUrl', () => {
- expect(this.calloutComponent.docsUrl).toContain(docsUrl);
- });
- });
-
- describe(`when ${cookieKey} cookie is set`, () => {
- beforeEach(() => {
- Cookies.set(cookieKey, true);
- this.calloutComponent = new PipelineSchedulesCalloutComponent().$mount();
- });
-
- it('correctly sets calloutDismissed to true', () => {
- expect(this.calloutComponent.calloutDismissed).toBe(true);
- });
-
- it('does not render the callout', () => {
- expect(this.calloutComponent.$el.childNodes.length).toBe(0);
- });
- });
-
- describe('when cookie is not set', () => {
- beforeEach(() => {
- Cookies.remove(cookieKey);
- this.calloutComponent = new PipelineSchedulesCalloutComponent().$mount();
- });
-
- it('correctly sets calloutDismissed to false', () => {
- expect(this.calloutComponent.calloutDismissed).toBe(false);
- });
-
- it('renders the callout container', () => {
- expect(this.calloutComponent.$el.querySelector('.bordered-box')).not.toBeNull();
- });
-
- it('renders the callout svg', () => {
- expect(this.calloutComponent.$el.outerHTML).toContain('<svg');
- });
-
- it('renders the callout title', () => {
- expect(this.calloutComponent.$el.outerHTML).toContain('Scheduling Pipelines');
- });
-
- it('renders the callout text', () => {
- expect(this.calloutComponent.$el.outerHTML).toContain('runs pipelines in the future');
- });
-
- it('renders the documentation url', () => {
- expect(this.calloutComponent.$el.outerHTML).toContain(docsUrl);
- });
-
- it('updates calloutDismissed when close button is clicked', done => {
- this.calloutComponent.$el.querySelector('#dismiss-callout-btn').click();
-
- Vue.nextTick(() => {
- expect(this.calloutComponent.calloutDismissed).toBe(true);
- done();
- });
- });
-
- it('#dismissCallout updates calloutDismissed', done => {
- this.calloutComponent.dismissCallout();
-
- Vue.nextTick(() => {
- expect(this.calloutComponent.calloutDismissed).toBe(true);
- done();
- });
- });
-
- it('is hidden when close button is clicked', done => {
- this.calloutComponent.$el.querySelector('#dismiss-callout-btn').click();
-
- Vue.nextTick(() => {
- expect(this.calloutComponent.$el.childNodes.length).toBe(0);
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/pages/sessions/new/preserve_url_fragment_spec.js b/spec/javascripts/pages/sessions/new/preserve_url_fragment_spec.js
deleted file mode 100644
index 1809e92e1d9..00000000000
--- a/spec/javascripts/pages/sessions/new/preserve_url_fragment_spec.js
+++ /dev/null
@@ -1,61 +0,0 @@
-import $ from 'jquery';
-import preserveUrlFragment from '~/pages/sessions/new/preserve_url_fragment';
-
-describe('preserve_url_fragment', () => {
- preloadFixtures('sessions/new.html');
-
- beforeEach(() => {
- loadFixtures('sessions/new.html');
- });
-
- it('adds the url fragment to all login and sign up form actions', () => {
- preserveUrlFragment('#L65');
-
- expect($('#new_user').attr('action')).toBe('http://test.host/users/sign_in#L65');
- expect($('#new_new_user').attr('action')).toBe('http://test.host/users#L65');
- });
-
- it('does not add an empty url fragment to login and sign up form actions', () => {
- preserveUrlFragment();
-
- expect($('#new_user').attr('action')).toBe('http://test.host/users/sign_in');
- expect($('#new_new_user').attr('action')).toBe('http://test.host/users');
- });
-
- it('does not add an empty query parameter to OmniAuth login buttons', () => {
- preserveUrlFragment();
-
- expect($('#oauth-login-cas3').attr('href')).toBe('http://test.host/users/auth/cas3');
-
- expect($('.omniauth-container #oauth-login-auth0').attr('href')).toBe(
- 'http://test.host/users/auth/auth0',
- );
- });
-
- describe('adds "redirect_fragment" query parameter to OmniAuth login buttons', () => {
- it('when "remember_me" is not present', () => {
- preserveUrlFragment('#L65');
-
- expect($('#oauth-login-cas3').attr('href')).toBe(
- 'http://test.host/users/auth/cas3?redirect_fragment=L65',
- );
-
- expect($('.omniauth-container #oauth-login-auth0').attr('href')).toBe(
- 'http://test.host/users/auth/auth0?redirect_fragment=L65',
- );
- });
-
- it('when "remember-me" is present', () => {
- $('a.omniauth-btn').attr('href', (i, href) => `${href}?remember_me=1`);
- preserveUrlFragment('#L65');
-
- expect($('#oauth-login-cas3').attr('href')).toBe(
- 'http://test.host/users/auth/cas3?remember_me=1&redirect_fragment=L65',
- );
-
- expect($('#oauth-login-auth0').attr('href')).toBe(
- 'http://test.host/users/auth/auth0?remember_me=1&redirect_fragment=L65',
- );
- });
- });
-});
diff --git a/spec/javascripts/pipelines/header_component_spec.js b/spec/javascripts/pipelines/header_component_spec.js
deleted file mode 100644
index 9043f30397d..00000000000
--- a/spec/javascripts/pipelines/header_component_spec.js
+++ /dev/null
@@ -1,108 +0,0 @@
-import Vue from 'vue';
-import headerComponent from '~/pipelines/components/header_component.vue';
-import eventHub from '~/pipelines/event_hub';
-
-describe('Pipeline details header', () => {
- let HeaderComponent;
- let vm;
- let props;
-
- beforeEach(() => {
- spyOn(eventHub, '$emit');
- HeaderComponent = Vue.extend(headerComponent);
-
- const threeWeeksAgo = new Date();
- threeWeeksAgo.setDate(threeWeeksAgo.getDate() - 21);
-
- props = {
- pipeline: {
- details: {
- status: {
- group: 'failed',
- icon: 'status_failed',
- label: 'failed',
- text: 'failed',
- details_path: 'path',
- },
- },
- id: 123,
- created_at: threeWeeksAgo.toISOString(),
- user: {
- web_url: 'path',
- name: 'Foo',
- username: 'foobar',
- email: 'foo@bar.com',
- avatar_url: 'link',
- },
- retry_path: 'retry',
- cancel_path: 'cancel',
- delete_path: 'delete',
- },
- isLoading: false,
- };
-
- vm = new HeaderComponent({ propsData: props }).$mount();
- });
-
- afterEach(() => {
- eventHub.$off();
- vm.$destroy();
- });
-
- const findDeleteModal = () => document.getElementById(headerComponent.DELETE_MODAL_ID);
- const findDeleteModalSubmit = () =>
- [...findDeleteModal().querySelectorAll('.btn')].find(x => x.textContent === 'Delete pipeline');
-
- it('should render provided pipeline info', () => {
- expect(
- vm.$el
- .querySelector('.header-main-content')
- .textContent.replace(/\s+/g, ' ')
- .trim(),
- ).toContain('failed Pipeline #123 triggered 3 weeks ago by Foo');
- });
-
- describe('action buttons', () => {
- it('should not trigger eventHub when nothing happens', () => {
- expect(eventHub.$emit).not.toHaveBeenCalled();
- });
-
- it('should call postAction when retry button action is clicked', () => {
- vm.$el.querySelector('.js-retry-button').click();
-
- expect(eventHub.$emit).toHaveBeenCalledWith('headerPostAction', 'retry');
- });
-
- it('should call postAction when cancel button action is clicked', () => {
- vm.$el.querySelector('.js-btn-cancel-pipeline').click();
-
- expect(eventHub.$emit).toHaveBeenCalledWith('headerPostAction', 'cancel');
- });
-
- it('does not show delete modal', () => {
- expect(findDeleteModal()).not.toBeVisible();
- });
-
- describe('when delete button action is clicked', () => {
- beforeEach(done => {
- vm.$el.querySelector('.js-btn-delete-pipeline').click();
-
- // Modal needs two ticks to show
- vm.$nextTick()
- .then(() => vm.$nextTick())
- .then(done)
- .catch(done.fail);
- });
-
- it('should show delete modal', () => {
- expect(findDeleteModal()).toBeVisible();
- });
-
- it('should call delete when modal is submitted', () => {
- findDeleteModalSubmit().click();
-
- expect(eventHub.$emit).toHaveBeenCalledWith('headerDeleteAction', 'delete');
- });
- });
- });
-});
diff --git a/spec/javascripts/pipelines/linked_pipelines_mock.json b/spec/javascripts/pipelines/linked_pipelines_mock.json
deleted file mode 100644
index 60e214ddc32..00000000000
--- a/spec/javascripts/pipelines/linked_pipelines_mock.json
+++ /dev/null
@@ -1,3535 +0,0 @@
-{
- "id": 23211253,
- "user": {
- "id": 3585,
- "name": "Achilleas Pipinellis",
- "username": "axil",
- "state": "active",
- "avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/3585/avatar.png",
- "web_url": "https://gitlab.com/axil",
- "status_tooltip_html": "\u003cspan class=\"user-status-emoji has-tooltip\" title=\"I like pizza\" data-html=\"true\" data-placement=\"top\"\u003e\u003cgl-emoji title=\"slice of pizza\" data-name=\"pizza\" data-unicode-version=\"6.0\"\u003e🍕\u003c/gl-emoji\u003e\u003c/span\u003e",
- "path": "/axil"
- },
- "active": false,
- "coverage": null,
- "source": "push",
- "created_at": "2018-06-05T11:31:30.452Z",
- "updated_at": "2018-10-31T16:35:31.305Z",
- "path": "/gitlab-org/gitlab-runner/pipelines/23211253",
- "flags": {
- "latest": false,
- "stuck": false,
- "auto_devops": false,
- "merge_request": false,
- "yaml_errors": false,
- "retryable": false,
- "cancelable": false,
- "failure_reason": false
- },
- "details": {
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/pipelines/23211253",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "duration": 53,
- "finished_at": "2018-10-31T16:35:31.299Z",
- "stages": [
- {
- "name": "prebuild",
- "title": "prebuild: passed",
- "groups": [
- {
- "name": "review-docs-deploy",
- "size": 1,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "manual play action",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469032",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469032/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- },
- "jobs": [
- {
- "id": 72469032,
- "name": "review-docs-deploy",
- "started": "2018-10-31T16:34:58.778Z",
- "archived": false,
- "build_path": "/gitlab-org/gitlab-runner/-/jobs/72469032",
- "retry_path": "/gitlab-org/gitlab-runner/-/jobs/72469032/retry",
- "play_path": "/gitlab-org/gitlab-runner/-/jobs/72469032/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2018-06-05T11:31:30.495Z",
- "updated_at": "2018-10-31T16:35:31.251Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "manual play action",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469032",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469032/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/pipelines/23211253#prebuild",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "path": "/gitlab-org/gitlab-runner/pipelines/23211253#prebuild",
- "dropdown_path": "/gitlab-org/gitlab-runner/pipelines/23211253/stage.json?stage=prebuild"
- },
- {
- "name": "test",
- "title": "test: passed",
- "groups": [
- {
- "name": "docs check links",
- "size": 1,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469033",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469033/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "jobs": [
- {
- "id": 72469033,
- "name": "docs check links",
- "started": "2018-06-05T11:31:33.240Z",
- "archived": false,
- "build_path": "/gitlab-org/gitlab-runner/-/jobs/72469033",
- "retry_path": "/gitlab-org/gitlab-runner/-/jobs/72469033/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2018-06-05T11:31:30.627Z",
- "updated_at": "2018-06-05T11:31:54.363Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469033",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469033/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/pipelines/23211253#test",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "path": "/gitlab-org/gitlab-runner/pipelines/23211253#test",
- "dropdown_path": "/gitlab-org/gitlab-runner/pipelines/23211253/stage.json?stage=test"
- },
- {
- "name": "cleanup",
- "title": "cleanup: skipped",
- "groups": [
- {
- "name": "review-docs-cleanup",
- "size": 1,
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual stop action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469034",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "stop",
- "title": "Stop",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469034/play",
- "method": "post",
- "button_title": "Stop this environment"
- }
- },
- "jobs": [
- {
- "id": 72469034,
- "name": "review-docs-cleanup",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-org/gitlab-runner/-/jobs/72469034",
- "play_path": "/gitlab-org/gitlab-runner/-/jobs/72469034/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2018-06-05T11:31:30.760Z",
- "updated_at": "2018-06-05T11:31:56.037Z",
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual stop action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469034",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "stop",
- "title": "Stop",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469034/play",
- "method": "post",
- "button_title": "Stop this environment"
- }
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/pipelines/23211253#cleanup",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "path": "/gitlab-org/gitlab-runner/pipelines/23211253#cleanup",
- "dropdown_path": "/gitlab-org/gitlab-runner/pipelines/23211253/stage.json?stage=cleanup"
- }
- ],
- "artifacts": [],
- "manual_actions": [
- {
- "name": "review-docs-cleanup",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469034/play",
- "playable": true,
- "scheduled": false
- },
- {
- "name": "review-docs-deploy",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469032/play",
- "playable": true,
- "scheduled": false
- }
- ],
- "scheduled_actions": []
- },
- "ref": {
- "name": "docs/add-development-guide-to-readme",
- "path": "/gitlab-org/gitlab-runner/commits/docs/add-development-guide-to-readme",
- "tag": false,
- "branch": true,
- "merge_request": false
- },
- "commit": {
- "id": "8083eb0a920572214d0dccedd7981f05d535ad46",
- "short_id": "8083eb0a",
- "title": "Add link to development guide in readme",
- "created_at": "2018-06-05T11:30:48.000Z",
- "parent_ids": ["1d7cf79b5a1a2121b9474ac20d61c1b8f621289d"],
- "message": "Add link to development guide in readme\n\nCloses https://gitlab.com/gitlab-org/gitlab-runner/issues/3122\n",
- "author_name": "Achilleas Pipinellis",
- "author_email": "axil@gitlab.com",
- "authored_date": "2018-06-05T11:30:48.000Z",
- "committer_name": "Achilleas Pipinellis",
- "committer_email": "axil@gitlab.com",
- "committed_date": "2018-06-05T11:30:48.000Z",
- "author": {
- "id": 3585,
- "name": "Achilleas Pipinellis",
- "username": "axil",
- "state": "active",
- "avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/3585/avatar.png",
- "web_url": "https://gitlab.com/axil",
- "status_tooltip_html": null,
- "path": "/axil"
- },
- "author_gravatar_url": "https://secure.gravatar.com/avatar/1d37af00eec153a8333a4ce18e9aea41?s=80\u0026d=identicon",
- "commit_url": "https://gitlab.com/gitlab-org/gitlab-runner/commit/8083eb0a920572214d0dccedd7981f05d535ad46",
- "commit_path": "/gitlab-org/gitlab-runner/commit/8083eb0a920572214d0dccedd7981f05d535ad46"
- },
- "project": {
- "id": 1794617
- },
- "triggered_by": {
- "id": 12,
- "user": {
- "id": 376774,
- "name": "Alessio Caiazza",
- "username": "nolith",
- "state": "active",
- "avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/376774/avatar.png",
- "web_url": "https://gitlab.com/nolith",
- "status_tooltip_html": null,
- "path": "/nolith"
- },
- "active": false,
- "coverage": null,
- "source": "pipeline",
- "path": "/gitlab-com/gitlab-docs/pipelines/34993051",
- "details": {
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/34993051",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png"
- },
- "duration": 118,
- "finished_at": "2018-10-31T16:41:40.615Z",
- "stages": [
- {
- "name": "build-images",
- "title": "build-images: skipped",
- "groups": [
- {
- "name": "image:bootstrap",
- "size": 1,
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982853",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982853/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- },
- "jobs": [
- {
- "id": 11421321982853,
- "name": "image:bootstrap",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114982853",
- "play_path": "/gitlab-com/gitlab-docs/-/jobs/114982853/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2018-10-31T16:35:23.704Z",
- "updated_at": "2018-10-31T16:35:24.118Z",
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982853",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982853/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- }
- }
- ]
- },
- {
- "name": "image:builder-onbuild",
- "size": 1,
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982854",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982854/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- },
- "jobs": [
- {
- "id": 1149822131854,
- "name": "image:builder-onbuild",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114982854",
- "play_path": "/gitlab-com/gitlab-docs/-/jobs/114982854/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2018-10-31T16:35:23.728Z",
- "updated_at": "2018-10-31T16:35:24.070Z",
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982854",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982854/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- }
- }
- ]
- },
- {
- "name": "image:nginx-onbuild",
- "size": 1,
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982855",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982855/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- },
- "jobs": [
- {
- "id": 11498285523424,
- "name": "image:nginx-onbuild",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114982855",
- "play_path": "/gitlab-com/gitlab-docs/-/jobs/114982855/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2018-10-31T16:35:23.753Z",
- "updated_at": "2018-10-31T16:35:24.033Z",
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982855",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982855/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/34993051#build-images",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "path": "/gitlab-com/gitlab-docs/pipelines/34993051#build-images",
- "dropdown_path": "/gitlab-com/gitlab-docs/pipelines/34993051/stage.json?stage=build-images"
- },
- {
- "name": "build",
- "title": "build: failed",
- "groups": [
- {
- "name": "compile_dev",
- "size": 1,
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed - (script failure)",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114984694",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/528/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "jobs": [
- {
- "id": 1149846949786,
- "name": "compile_dev",
- "started": "2018-10-31T16:39:41.598Z",
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114984694",
- "retry_path": "/gitlab-com/gitlab-docs/-/jobs/114984694/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2018-10-31T16:39:41.138Z",
- "updated_at": "2018-10-31T16:41:40.072Z",
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed - (script failure)",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114984694",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/528/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "recoverable": false
- }
- ]
- }
- ],
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/34993051#build",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png"
- },
- "path": "/gitlab-com/gitlab-docs/pipelines/34993051#build",
- "dropdown_path": "/gitlab-com/gitlab-docs/pipelines/34993051/stage.json?stage=build"
- },
- {
- "name": "deploy",
- "title": "deploy: skipped",
- "groups": [
- {
- "name": "review",
- "size": 1,
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982857",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job has been skipped"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "jobs": [
- {
- "id": 11498282342357,
- "name": "review",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114982857",
- "playable": false,
- "scheduled": false,
- "created_at": "2018-10-31T16:35:23.805Z",
- "updated_at": "2018-10-31T16:41:40.569Z",
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982857",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job has been skipped"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- }
- }
- ]
- },
- {
- "name": "review_stop",
- "size": 1,
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982858",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job has been skipped"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "jobs": [
- {
- "id": 114982858,
- "name": "review_stop",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114982858",
- "playable": false,
- "scheduled": false,
- "created_at": "2018-10-31T16:35:23.840Z",
- "updated_at": "2018-10-31T16:41:40.480Z",
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982858",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job has been skipped"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/34993051#deploy",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "path": "/gitlab-com/gitlab-docs/pipelines/34993051#deploy",
- "dropdown_path": "/gitlab-com/gitlab-docs/pipelines/34993051/stage.json?stage=deploy"
- }
- ],
- "artifacts": [],
- "manual_actions": [
- {
- "name": "image:bootstrap",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982853/play",
- "playable": true,
- "scheduled": false
- },
- {
- "name": "image:builder-onbuild",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982854/play",
- "playable": true,
- "scheduled": false
- },
- {
- "name": "image:nginx-onbuild",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982855/play",
- "playable": true,
- "scheduled": false
- },
- {
- "name": "review_stop",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982858/play",
- "playable": false,
- "scheduled": false
- }
- ],
- "scheduled_actions": []
- },
- "project": {
- "id": 1794617,
- "name": "Test",
- "full_path": "/gitlab-com/gitlab-docs",
- "full_name": "GitLab.com / GitLab Docs"
- },
- "triggered_by": {
- "id": 349932310342451,
- "user": {
- "id": 376774,
- "name": "Alessio Caiazza",
- "username": "nolith",
- "state": "active",
- "avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/376774/avatar.png",
- "web_url": "https://gitlab.com/nolith",
- "status_tooltip_html": null,
- "path": "/nolith"
- },
- "active": false,
- "coverage": null,
- "source": "pipeline",
- "path": "/gitlab-com/gitlab-docs/pipelines/34993051",
- "details": {
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/34993051",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png"
- },
- "duration": 118,
- "finished_at": "2018-10-31T16:41:40.615Z",
- "stages": [
- {
- "name": "build-images",
- "title": "build-images: skipped",
- "groups": [
- {
- "name": "image:bootstrap",
- "size": 1,
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982853",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982853/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- },
- "jobs": [
- {
- "id": 11421321982853,
- "name": "image:bootstrap",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114982853",
- "play_path": "/gitlab-com/gitlab-docs/-/jobs/114982853/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2018-10-31T16:35:23.704Z",
- "updated_at": "2018-10-31T16:35:24.118Z",
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982853",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982853/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- }
- }
- ]
- },
- {
- "name": "image:builder-onbuild",
- "size": 1,
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982854",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982854/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- },
- "jobs": [
- {
- "id": 1149822131854,
- "name": "image:builder-onbuild",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114982854",
- "play_path": "/gitlab-com/gitlab-docs/-/jobs/114982854/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2018-10-31T16:35:23.728Z",
- "updated_at": "2018-10-31T16:35:24.070Z",
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982854",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982854/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- }
- }
- ]
- },
- {
- "name": "image:nginx-onbuild",
- "size": 1,
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982855",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982855/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- },
- "jobs": [
- {
- "id": 11498285523424,
- "name": "image:nginx-onbuild",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114982855",
- "play_path": "/gitlab-com/gitlab-docs/-/jobs/114982855/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2018-10-31T16:35:23.753Z",
- "updated_at": "2018-10-31T16:35:24.033Z",
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982855",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982855/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/34993051#build-images",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "path": "/gitlab-com/gitlab-docs/pipelines/34993051#build-images",
- "dropdown_path": "/gitlab-com/gitlab-docs/pipelines/34993051/stage.json?stage=build-images"
- },
- {
- "name": "build",
- "title": "build: failed",
- "groups": [
- {
- "name": "compile_dev",
- "size": 1,
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed - (script failure)",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114984694",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114984694/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "jobs": [
- {
- "id": 1149846949786,
- "name": "compile_dev",
- "started": "2018-10-31T16:39:41.598Z",
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114984694",
- "retry_path": "/gitlab-com/gitlab-docs/-/jobs/114984694/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2018-10-31T16:39:41.138Z",
- "updated_at": "2018-10-31T16:41:40.072Z",
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed - (script failure)",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114984694",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114984694/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "recoverable": false
- }
- ]
- }
- ],
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/34993051#build",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png"
- },
- "path": "/gitlab-com/gitlab-docs/pipelines/34993051#build",
- "dropdown_path": "/gitlab-com/gitlab-docs/pipelines/34993051/stage.json?stage=build"
- },
- {
- "name": "deploy",
- "title": "deploy: skipped",
- "groups": [
- {
- "name": "review",
- "size": 1,
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982857",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job has been skipped"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "jobs": [
- {
- "id": 11498282342357,
- "name": "review",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114982857",
- "playable": false,
- "scheduled": false,
- "created_at": "2018-10-31T16:35:23.805Z",
- "updated_at": "2018-10-31T16:41:40.569Z",
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982857",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job has been skipped"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- }
- }
- ]
- },
- {
- "name": "review_stop",
- "size": 1,
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982858",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job has been skipped"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "jobs": [
- {
- "id": 114982858,
- "name": "review_stop",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114982858",
- "playable": false,
- "scheduled": false,
- "created_at": "2018-10-31T16:35:23.840Z",
- "updated_at": "2018-10-31T16:41:40.480Z",
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982858",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job has been skipped"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/34993051#deploy",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "path": "/gitlab-com/gitlab-docs/pipelines/34993051#deploy",
- "dropdown_path": "/gitlab-com/gitlab-docs/pipelines/34993051/stage.json?stage=deploy"
- }
- ],
- "artifacts": [],
- "manual_actions": [
- {
- "name": "image:bootstrap",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982853/play",
- "playable": true,
- "scheduled": false
- },
- {
- "name": "image:builder-onbuild",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982854/play",
- "playable": true,
- "scheduled": false
- },
- {
- "name": "image:nginx-onbuild",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982855/play",
- "playable": true,
- "scheduled": false
- },
- {
- "name": "review_stop",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982858/play",
- "playable": false,
- "scheduled": false
- }
- ],
- "scheduled_actions": []
- },
- "project": {
- "id": 1794617,
- "name": "GitLab Docs",
- "full_path": "/gitlab-com/gitlab-docs",
- "full_name": "GitLab.com / GitLab Docs"
- }
- },
- "triggered": []
- },
- "triggered": [
- {
- "id": 34993051,
- "user": {
- "id": 376774,
- "name": "Alessio Caiazza",
- "username": "nolith",
- "state": "active",
- "avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/376774/avatar.png",
- "web_url": "https://gitlab.com/nolith",
- "status_tooltip_html": null,
- "path": "/nolith"
- },
- "active": false,
- "coverage": null,
- "source": "pipeline",
- "path": "/gitlab-com/gitlab-docs/pipelines/34993051",
- "details": {
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/34993051",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png"
- },
- "duration": 118,
- "finished_at": "2018-10-31T16:41:40.615Z",
- "stages": [
- {
- "name": "build-images",
- "title": "build-images: skipped",
- "groups": [
- {
- "name": "image:bootstrap",
- "size": 1,
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982853",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982853/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- },
- "jobs": [
- {
- "id": 114982853,
- "name": "image:bootstrap",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114982853",
- "play_path": "/gitlab-com/gitlab-docs/-/jobs/114982853/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2018-10-31T16:35:23.704Z",
- "updated_at": "2018-10-31T16:35:24.118Z",
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982853",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982853/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- }
- }
- ]
- },
- {
- "name": "image:builder-onbuild",
- "size": 1,
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982854",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982854/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- },
- "jobs": [
- {
- "id": 114982854,
- "name": "image:builder-onbuild",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114982854",
- "play_path": "/gitlab-com/gitlab-docs/-/jobs/114982854/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2018-10-31T16:35:23.728Z",
- "updated_at": "2018-10-31T16:35:24.070Z",
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982854",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982854/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- }
- }
- ]
- },
- {
- "name": "image:nginx-onbuild",
- "size": 1,
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982855",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982855/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- },
- "jobs": [
- {
- "id": 114982855,
- "name": "image:nginx-onbuild",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114982855",
- "play_path": "/gitlab-com/gitlab-docs/-/jobs/114982855/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2018-10-31T16:35:23.753Z",
- "updated_at": "2018-10-31T16:35:24.033Z",
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982855",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982855/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/34993051#build-images",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "path": "/gitlab-com/gitlab-docs/pipelines/34993051#build-images",
- "dropdown_path": "/gitlab-com/gitlab-docs/pipelines/34993051/stage.json?stage=build-images"
- },
- {
- "name": "build",
- "title": "build: failed",
- "groups": [
- {
- "name": "compile_dev",
- "size": 1,
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed - (script failure)",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114984694",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/528/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "jobs": [
- {
- "id": 114984694,
- "name": "compile_dev",
- "started": "2018-10-31T16:39:41.598Z",
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114984694",
- "retry_path": "/gitlab-com/gitlab-docs/-/jobs/114984694/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2018-10-31T16:39:41.138Z",
- "updated_at": "2018-10-31T16:41:40.072Z",
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed - (script failure)",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114984694",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/528/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "recoverable": false
- }
- ]
- }
- ],
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/34993051#build",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png"
- },
- "path": "/gitlab-com/gitlab-docs/pipelines/34993051#build",
- "dropdown_path": "/gitlab-com/gitlab-docs/pipelines/34993051/stage.json?stage=build"
- },
- {
- "name": "deploy",
- "title": "deploy: skipped",
- "groups": [
- {
- "name": "review",
- "size": 1,
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982857",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job has been skipped"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "jobs": [
- {
- "id": 114982857,
- "name": "review",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114982857",
- "playable": false,
- "scheduled": false,
- "created_at": "2018-10-31T16:35:23.805Z",
- "updated_at": "2018-10-31T16:41:40.569Z",
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982857",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job has been skipped"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- }
- }
- ]
- },
- {
- "name": "review_stop",
- "size": 1,
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982858",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job has been skipped"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "jobs": [
- {
- "id": 114982858,
- "name": "review_stop",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114982858",
- "playable": false,
- "scheduled": false,
- "created_at": "2018-10-31T16:35:23.840Z",
- "updated_at": "2018-10-31T16:41:40.480Z",
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982858",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job has been skipped"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/34993051#deploy",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "path": "/gitlab-com/gitlab-docs/pipelines/34993051#deploy",
- "dropdown_path": "/gitlab-com/gitlab-docs/pipelines/34993051/stage.json?stage=deploy"
- }
- ],
- "artifacts": [],
- "manual_actions": [
- {
- "name": "image:bootstrap",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982853/play",
- "playable": true,
- "scheduled": false
- },
- {
- "name": "image:builder-onbuild",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982854/play",
- "playable": true,
- "scheduled": false
- },
- {
- "name": "image:nginx-onbuild",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982855/play",
- "playable": true,
- "scheduled": false
- },
- {
- "name": "review_stop",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982858/play",
- "playable": false,
- "scheduled": false
- }
- ],
- "scheduled_actions": []
- },
- "project": {
- "id": 1794617,
- "name": "GitLab Docs",
- "full_path": "/gitlab-com/gitlab-docs",
- "full_name": "GitLab.com / GitLab Docs"
- }
- },
- {
- "id": 34993052,
- "user": {
- "id": 376774,
- "name": "Alessio Caiazza",
- "username": "nolith",
- "state": "active",
- "avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/376774/avatar.png",
- "web_url": "https://gitlab.com/nolith",
- "status_tooltip_html": null,
- "path": "/nolith"
- },
- "active": false,
- "coverage": null,
- "source": "pipeline",
- "path": "/gitlab-com/gitlab-docs/pipelines/34993051",
- "details": {
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/34993051",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png"
- },
- "duration": 118,
- "finished_at": "2018-10-31T16:41:40.615Z",
- "stages": [
- {
- "name": "build-images",
- "title": "build-images: skipped",
- "groups": [
- {
- "name": "image:bootstrap",
- "size": 1,
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982853",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982853/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- },
- "jobs": [
- {
- "id": 114982853,
- "name": "image:bootstrap",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114982853",
- "play_path": "/gitlab-com/gitlab-docs/-/jobs/114982853/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2018-10-31T16:35:23.704Z",
- "updated_at": "2018-10-31T16:35:24.118Z",
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982853",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982853/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- }
- }
- ]
- },
- {
- "name": "image:builder-onbuild",
- "size": 1,
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982854",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982854/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- },
- "jobs": [
- {
- "id": 114982854,
- "name": "image:builder-onbuild",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114982854",
- "play_path": "/gitlab-com/gitlab-docs/-/jobs/114982854/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2018-10-31T16:35:23.728Z",
- "updated_at": "2018-10-31T16:35:24.070Z",
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982854",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982854/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- }
- }
- ]
- },
- {
- "name": "image:nginx-onbuild",
- "size": 1,
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982855",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982855/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- },
- "jobs": [
- {
- "id": 1224982855,
- "name": "image:nginx-onbuild",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114982855",
- "play_path": "/gitlab-com/gitlab-docs/-/jobs/114982855/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2018-10-31T16:35:23.753Z",
- "updated_at": "2018-10-31T16:35:24.033Z",
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual play action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982855",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982855/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/34993051#build-images",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "path": "/gitlab-com/gitlab-docs/pipelines/34993051#build-images",
- "dropdown_path": "/gitlab-com/gitlab-docs/pipelines/34993051/stage.json?stage=build-images"
- },
- {
- "name": "build",
- "title": "build: failed",
- "groups": [
- {
- "name": "compile_dev",
- "size": 1,
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed - (script failure)",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114984694",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114984694/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "jobs": [
- {
- "id": 1123984694,
- "name": "compile_dev",
- "started": "2018-10-31T16:39:41.598Z",
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114984694",
- "retry_path": "/gitlab-com/gitlab-docs/-/jobs/114984694/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2018-10-31T16:39:41.138Z",
- "updated_at": "2018-10-31T16:41:40.072Z",
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed - (script failure)",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114984694",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114984694/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "recoverable": false
- }
- ]
- }
- ],
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/34993051#build",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png"
- },
- "path": "/gitlab-com/gitlab-docs/pipelines/34993051#build",
- "dropdown_path": "/gitlab-com/gitlab-docs/pipelines/34993051/stage.json?stage=build"
- },
- {
- "name": "deploy",
- "title": "deploy: skipped",
- "groups": [
- {
- "name": "review",
- "size": 1,
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982857",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job has been skipped"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "jobs": [
- {
- "id": 1143232982857,
- "name": "review",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114982857",
- "playable": false,
- "scheduled": false,
- "created_at": "2018-10-31T16:35:23.805Z",
- "updated_at": "2018-10-31T16:41:40.569Z",
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982857",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job has been skipped"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- }
- }
- ]
- },
- {
- "name": "review_stop",
- "size": 1,
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982858",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job has been skipped"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "jobs": [
- {
- "id": 114921313182858,
- "name": "review_stop",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-com/gitlab-docs/-/jobs/114982858",
- "playable": false,
- "scheduled": false,
- "created_at": "2018-10-31T16:35:23.840Z",
- "updated_at": "2018-10-31T16:41:40.480Z",
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/-/jobs/114982858",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job has been skipped"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/34993051#deploy",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "path": "/gitlab-com/gitlab-docs/pipelines/34993051#deploy",
- "dropdown_path": "/gitlab-com/gitlab-docs/pipelines/34993051/stage.json?stage=deploy"
- }
- ],
- "artifacts": [],
- "manual_actions": [
- {
- "name": "image:bootstrap",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982853/play",
- "playable": true,
- "scheduled": false
- },
- {
- "name": "image:builder-onbuild",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982854/play",
- "playable": true,
- "scheduled": false
- },
- {
- "name": "image:nginx-onbuild",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982855/play",
- "playable": true,
- "scheduled": false
- },
- {
- "name": "review_stop",
- "path": "/gitlab-com/gitlab-docs/-/jobs/114982858/play",
- "playable": false,
- "scheduled": false
- }
- ],
- "scheduled_actions": []
- },
- "project": {
- "id": 1794617,
- "name": "GitLab Docs",
- "full_path": "/gitlab-com/gitlab-docs",
- "full_name": "GitLab.com / GitLab Docs"
- },
- "triggered": [
- {
- "id": 26,
- "user": null,
- "active": false,
- "coverage": null,
- "source": "push",
- "created_at": "2019-01-06T17:48:37.599Z",
- "updated_at": "2019-01-06T17:48:38.371Z",
- "path": "/h5bp/html5-boilerplate/pipelines/26",
- "flags": {
- "latest": true,
- "stuck": false,
- "auto_devops": false,
- "merge_request": false,
- "yaml_errors": false,
- "retryable": true,
- "cancelable": false,
- "failure_reason": false
- },
- "details": {
- "status": {
- "icon": "status_warning",
- "text": "passed",
- "label": "passed with warnings",
- "group": "success-with-warnings",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/pipelines/26",
- "illustration": null,
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "duration": null,
- "finished_at": "2019-01-06T17:48:38.370Z",
- "stages": [
- {
- "name": "build",
- "title": "build: passed",
- "groups": [
- {
- "name": "build:linux",
- "size": 1,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/526",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/526/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "jobs": [
- {
- "id": 526,
- "name": "build:linux",
- "started": "2019-01-06T08:48:20.236Z",
- "archived": false,
- "build_path": "/h5bp/html5-boilerplate/-/jobs/526",
- "retry_path": "/h5bp/html5-boilerplate/-/jobs/526/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2019-01-06T17:48:37.806Z",
- "updated_at": "2019-01-06T17:48:37.806Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/526",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/526/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- }
- }
- ]
- },
- {
- "name": "build:osx",
- "size": 1,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/527",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/527/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "jobs": [
- {
- "id": 527,
- "name": "build:osx",
- "started": "2019-01-06T07:48:20.237Z",
- "archived": false,
- "build_path": "/h5bp/html5-boilerplate/-/jobs/527",
- "retry_path": "/h5bp/html5-boilerplate/-/jobs/527/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2019-01-06T17:48:37.846Z",
- "updated_at": "2019-01-06T17:48:37.846Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/527",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/527/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/pipelines/26#build",
- "illustration": null,
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "path": "/h5bp/html5-boilerplate/pipelines/26#build",
- "dropdown_path": "/h5bp/html5-boilerplate/pipelines/26/stage.json?stage=build"
- },
- {
- "name": "test",
- "title": "test: passed with warnings",
- "groups": [
- {
- "name": "jenkins",
- "size": 1,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": null,
- "group": "success",
- "tooltip": null,
- "has_details": false,
- "details_path": null,
- "illustration": null,
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "jobs": [
- {
- "id": 546,
- "name": "jenkins",
- "started": "2019-01-06T11:48:20.237Z",
- "archived": false,
- "build_path": "/h5bp/html5-boilerplate/-/jobs/546",
- "playable": false,
- "scheduled": false,
- "created_at": "2019-01-06T17:48:38.359Z",
- "updated_at": "2019-01-06T17:48:38.359Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": null,
- "group": "success",
- "tooltip": null,
- "has_details": false,
- "details_path": null,
- "illustration": null,
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- }
- }
- ]
- },
- {
- "name": "rspec:linux",
- "size": 3,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": false,
- "details_path": null,
- "illustration": null,
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "jobs": [
- {
- "id": 528,
- "name": "rspec:linux 0 3",
- "started": "2019-01-06T09:48:20.237Z",
- "archived": false,
- "build_path": "/h5bp/html5-boilerplate/-/jobs/528",
- "retry_path": "/h5bp/html5-boilerplate/-/jobs/528/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2019-01-06T17:48:37.885Z",
- "updated_at": "2019-01-06T17:48:37.885Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/528",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/528/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- }
- },
- {
- "id": 529,
- "name": "rspec:linux 1 3",
- "started": "2019-01-06T09:48:20.237Z",
- "archived": false,
- "build_path": "/h5bp/html5-boilerplate/-/jobs/529",
- "retry_path": "/h5bp/html5-boilerplate/-/jobs/529/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2019-01-06T17:48:37.907Z",
- "updated_at": "2019-01-06T17:48:37.907Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/529",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/529/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- }
- },
- {
- "id": 530,
- "name": "rspec:linux 2 3",
- "started": "2019-01-06T09:48:20.237Z",
- "archived": false,
- "build_path": "/h5bp/html5-boilerplate/-/jobs/530",
- "retry_path": "/h5bp/html5-boilerplate/-/jobs/530/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2019-01-06T17:48:37.927Z",
- "updated_at": "2019-01-06T17:48:37.927Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/530",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/530/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- }
- }
- ]
- },
- {
- "name": "rspec:osx",
- "size": 1,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/535",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/535/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "jobs": [
- {
- "id": 535,
- "name": "rspec:osx",
- "started": "2019-01-06T09:48:20.237Z",
- "archived": false,
- "build_path": "/h5bp/html5-boilerplate/-/jobs/535",
- "retry_path": "/h5bp/html5-boilerplate/-/jobs/535/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2019-01-06T17:48:38.018Z",
- "updated_at": "2019-01-06T17:48:38.018Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/535",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/535/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- }
- }
- ]
- },
- {
- "name": "rspec:windows",
- "size": 3,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": false,
- "details_path": null,
- "illustration": null,
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "jobs": [
- {
- "id": 531,
- "name": "rspec:windows 0 3",
- "started": "2019-01-06T09:48:20.237Z",
- "archived": false,
- "build_path": "/h5bp/html5-boilerplate/-/jobs/531",
- "retry_path": "/h5bp/html5-boilerplate/-/jobs/531/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2019-01-06T17:48:37.944Z",
- "updated_at": "2019-01-06T17:48:37.944Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/531",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/531/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- }
- },
- {
- "id": 532,
- "name": "rspec:windows 1 3",
- "started": "2019-01-06T09:48:20.237Z",
- "archived": false,
- "build_path": "/h5bp/html5-boilerplate/-/jobs/532",
- "retry_path": "/h5bp/html5-boilerplate/-/jobs/532/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2019-01-06T17:48:37.962Z",
- "updated_at": "2019-01-06T17:48:37.962Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/532",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/532/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- }
- },
- {
- "id": 534,
- "name": "rspec:windows 2 3",
- "started": "2019-01-06T09:48:20.237Z",
- "archived": false,
- "build_path": "/h5bp/html5-boilerplate/-/jobs/534",
- "retry_path": "/h5bp/html5-boilerplate/-/jobs/534/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2019-01-06T17:48:37.999Z",
- "updated_at": "2019-01-06T17:48:37.999Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/534",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/534/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- }
- }
- ]
- },
- {
- "name": "spinach:linux",
- "size": 1,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/536",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/536/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "jobs": [
- {
- "id": 536,
- "name": "spinach:linux",
- "started": "2019-01-06T09:48:20.237Z",
- "archived": false,
- "build_path": "/h5bp/html5-boilerplate/-/jobs/536",
- "retry_path": "/h5bp/html5-boilerplate/-/jobs/536/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2019-01-06T17:48:38.050Z",
- "updated_at": "2019-01-06T17:48:38.050Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/536",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/536/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- }
- }
- ]
- },
- {
- "name": "spinach:osx",
- "size": 1,
- "status": {
- "icon": "status_warning",
- "text": "failed",
- "label": "failed (allowed to fail)",
- "group": "failed-with-warnings",
- "tooltip": "failed - (unknown failure) (allowed to fail)",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/537",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/537/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "jobs": [
- {
- "id": 537,
- "name": "spinach:osx",
- "started": "2019-01-06T09:48:20.237Z",
- "archived": false,
- "build_path": "/h5bp/html5-boilerplate/-/jobs/537",
- "retry_path": "/h5bp/html5-boilerplate/-/jobs/537/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2019-01-06T17:48:38.069Z",
- "updated_at": "2019-01-06T17:48:38.069Z",
- "status": {
- "icon": "status_warning",
- "text": "failed",
- "label": "failed (allowed to fail)",
- "group": "failed-with-warnings",
- "tooltip": "failed - (unknown failure) (allowed to fail)",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/537",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/537/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "callout_message": "There is an unknown failure, please try again",
- "recoverable": true
- }
- ]
- }
- ],
- "status": {
- "icon": "status_warning",
- "text": "passed",
- "label": "passed with warnings",
- "group": "success-with-warnings",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/pipelines/26#test",
- "illustration": null,
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "path": "/h5bp/html5-boilerplate/pipelines/26#test",
- "dropdown_path": "/h5bp/html5-boilerplate/pipelines/26/stage.json?stage=test"
- },
- {
- "name": "security",
- "title": "security: passed",
- "groups": [
- {
- "name": "container_scanning",
- "size": 1,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/541",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/541/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "jobs": [
- {
- "id": 541,
- "name": "container_scanning",
- "started": "2019-01-06T09:48:20.237Z",
- "archived": false,
- "build_path": "/h5bp/html5-boilerplate/-/jobs/541",
- "retry_path": "/h5bp/html5-boilerplate/-/jobs/541/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2019-01-06T17:48:38.186Z",
- "updated_at": "2019-01-06T17:48:38.186Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/541",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/541/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- }
- }
- ]
- },
- {
- "name": "dast",
- "size": 1,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/538",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/538/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "jobs": [
- {
- "id": 538,
- "name": "dast",
- "started": "2019-01-06T09:48:20.237Z",
- "archived": false,
- "build_path": "/h5bp/html5-boilerplate/-/jobs/538",
- "retry_path": "/h5bp/html5-boilerplate/-/jobs/538/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2019-01-06T17:48:38.087Z",
- "updated_at": "2019-01-06T17:48:38.087Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/538",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/538/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- }
- }
- ]
- },
- {
- "name": "dependency_scanning",
- "size": 1,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/540",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/540/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "jobs": [
- {
- "id": 540,
- "name": "dependency_scanning",
- "started": "2019-01-06T09:48:20.237Z",
- "archived": false,
- "build_path": "/h5bp/html5-boilerplate/-/jobs/540",
- "retry_path": "/h5bp/html5-boilerplate/-/jobs/540/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2019-01-06T17:48:38.153Z",
- "updated_at": "2019-01-06T17:48:38.153Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/540",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/540/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- }
- }
- ]
- },
- {
- "name": "sast",
- "size": 1,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/539",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/539/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "jobs": [
- {
- "id": 539,
- "name": "sast",
- "started": "2019-01-06T09:48:20.237Z",
- "archived": false,
- "build_path": "/h5bp/html5-boilerplate/-/jobs/539",
- "retry_path": "/h5bp/html5-boilerplate/-/jobs/539/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2019-01-06T17:48:38.121Z",
- "updated_at": "2019-01-06T17:48:38.121Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/539",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/539/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/pipelines/26#security",
- "illustration": null,
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "path": "/h5bp/html5-boilerplate/pipelines/26#security",
- "dropdown_path": "/h5bp/html5-boilerplate/pipelines/26/stage.json?stage=security"
- },
- {
- "name": "deploy",
- "title": "deploy: passed",
- "groups": [
- {
- "name": "production",
- "size": 1,
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/544",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job has been skipped"
- },
- "favicon": "/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "jobs": [
- {
- "id": 544,
- "name": "production",
- "started": null,
- "archived": false,
- "build_path": "/h5bp/html5-boilerplate/-/jobs/544",
- "playable": false,
- "scheduled": false,
- "created_at": "2019-01-06T17:48:38.313Z",
- "updated_at": "2019-01-06T17:48:38.313Z",
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/544",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job has been skipped"
- },
- "favicon": "/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- }
- }
- ]
- },
- {
- "name": "staging",
- "size": 1,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/542",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/542/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "jobs": [
- {
- "id": 542,
- "name": "staging",
- "started": "2019-01-06T11:48:20.237Z",
- "archived": false,
- "build_path": "/h5bp/html5-boilerplate/-/jobs/542",
- "retry_path": "/h5bp/html5-boilerplate/-/jobs/542/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2019-01-06T17:48:38.219Z",
- "updated_at": "2019-01-06T17:48:38.219Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/542",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/h5bp/html5-boilerplate/-/jobs/542/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- }
- }
- ]
- },
- {
- "name": "stop staging",
- "size": 1,
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/543",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job has been skipped"
- },
- "favicon": "/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "jobs": [
- {
- "id": 543,
- "name": "stop staging",
- "started": null,
- "archived": false,
- "build_path": "/h5bp/html5-boilerplate/-/jobs/543",
- "playable": false,
- "scheduled": false,
- "created_at": "2019-01-06T17:48:38.283Z",
- "updated_at": "2019-01-06T17:48:38.283Z",
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/543",
- "illustration": {
- "image": "/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job has been skipped"
- },
- "favicon": "/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/pipelines/26#deploy",
- "illustration": null,
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "path": "/h5bp/html5-boilerplate/pipelines/26#deploy",
- "dropdown_path": "/h5bp/html5-boilerplate/pipelines/26/stage.json?stage=deploy"
- },
- {
- "name": "notify",
- "title": "notify: passed",
- "groups": [
- {
- "name": "slack",
- "size": 1,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "manual play action",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/545",
- "illustration": {
- "image": "/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/h5bp/html5-boilerplate/-/jobs/545/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- },
- "jobs": [
- {
- "id": 545,
- "name": "slack",
- "started": null,
- "archived": false,
- "build_path": "/h5bp/html5-boilerplate/-/jobs/545",
- "retry_path": "/h5bp/html5-boilerplate/-/jobs/545/retry",
- "play_path": "/h5bp/html5-boilerplate/-/jobs/545/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2019-01-06T17:48:38.341Z",
- "updated_at": "2019-01-06T17:48:38.341Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "manual play action",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/-/jobs/545",
- "illustration": {
- "image": "/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/h5bp/html5-boilerplate/-/jobs/545/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/h5bp/html5-boilerplate/pipelines/26#notify",
- "illustration": null,
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "path": "/h5bp/html5-boilerplate/pipelines/26#notify",
- "dropdown_path": "/h5bp/html5-boilerplate/pipelines/26/stage.json?stage=notify"
- }
- ],
- "artifacts": [
- {
- "name": "build:linux",
- "expired": null,
- "expire_at": null,
- "path": "/h5bp/html5-boilerplate/-/jobs/526/artifacts/download",
- "browse_path": "/h5bp/html5-boilerplate/-/jobs/526/artifacts/browse"
- },
- {
- "name": "build:osx",
- "expired": null,
- "expire_at": null,
- "path": "/h5bp/html5-boilerplate/-/jobs/527/artifacts/download",
- "browse_path": "/h5bp/html5-boilerplate/-/jobs/527/artifacts/browse"
- }
- ],
- "manual_actions": [
- {
- "name": "stop staging",
- "path": "/h5bp/html5-boilerplate/-/jobs/543/play",
- "playable": false,
- "scheduled": false
- },
- {
- "name": "production",
- "path": "/h5bp/html5-boilerplate/-/jobs/544/play",
- "playable": false,
- "scheduled": false
- },
- {
- "name": "slack",
- "path": "/h5bp/html5-boilerplate/-/jobs/545/play",
- "playable": true,
- "scheduled": false
- }
- ],
- "scheduled_actions": []
- },
- "ref": {
- "name": "master",
- "path": "/h5bp/html5-boilerplate/commits/master",
- "tag": false,
- "branch": true,
- "merge_request": false
- },
- "commit": {
- "id": "bad98c453eab56d20057f3929989251d45cd1a8b",
- "short_id": "bad98c45",
- "title": "remove instances of shrink-to-fit=no (#2103)",
- "created_at": "2018-12-17T20:52:18.000Z",
- "parent_ids": ["49130f6cfe9ff1f749015d735649a2bc6f66cf3a"],
- "message": "remove instances of shrink-to-fit=no (#2103)\n\ncloses #2102\r\n\r\nPer my findings, the need for it as a default was rectified with the release of iOS 9.3, where the viewport no longer shrunk to accommodate overflow, as was introduced in iOS 9.",
- "author_name": "Scott O'Hara",
- "author_email": "scottaohara@users.noreply.github.com",
- "authored_date": "2018-12-17T20:52:18.000Z",
- "committer_name": "Rob Larsen",
- "committer_email": "rob@drunkenfist.com",
- "committed_date": "2018-12-17T20:52:18.000Z",
- "author": null,
- "author_gravatar_url": "https://www.gravatar.com/avatar/6d597df7cf998d16cbe00ccac063b31e?s=80\u0026d=identicon",
- "commit_url": "http://localhost:3001/h5bp/html5-boilerplate/commit/bad98c453eab56d20057f3929989251d45cd1a8b",
- "commit_path": "/h5bp/html5-boilerplate/commit/bad98c453eab56d20057f3929989251d45cd1a8b"
- },
- "retry_path": "/h5bp/html5-boilerplate/pipelines/26/retry",
- "triggered_by": {
- "id": 4,
- "user": null,
- "active": false,
- "coverage": null,
- "source": "push",
- "path": "/gitlab-org/gitlab-test/pipelines/4",
- "details": {
- "status": {
- "icon": "status_warning",
- "text": "passed",
- "label": "passed with warnings",
- "group": "success-with-warnings",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-test/pipelines/4",
- "illustration": null,
- "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- }
- },
- "project": {
- "id": 1,
- "name": "Gitlab Test",
- "full_path": "/gitlab-org/gitlab-test",
- "full_name": "Gitlab Org / Gitlab Test"
- }
- },
- "triggered": [],
- "project": {
- "id": 1794617,
- "name": "GitLab Docs",
- "full_path": "/gitlab-com/gitlab-docs",
- "full_name": "GitLab.com / GitLab Docs"
- }
- }
- ]
- }
- ]
-}
diff --git a/spec/javascripts/pipelines/mock_data.js b/spec/javascripts/pipelines/mock_data.js
deleted file mode 100644
index f876987cd88..00000000000
--- a/spec/javascripts/pipelines/mock_data.js
+++ /dev/null
@@ -1,423 +0,0 @@
-export const pipelineWithStages = {
- id: 20333396,
- user: {
- id: 128633,
- name: 'Rémy Coutable',
- username: 'rymai',
- state: 'active',
- avatar_url:
- 'https://secure.gravatar.com/avatar/263da227929cc0035cb0eba512bcf81a?s=80\u0026d=identicon',
- web_url: 'https://gitlab.com/rymai',
- path: '/rymai',
- },
- active: true,
- coverage: '58.24',
- source: 'push',
- created_at: '2018-04-11T14:04:53.881Z',
- updated_at: '2018-04-11T14:05:00.792Z',
- path: '/gitlab-org/gitlab/pipelines/20333396',
- flags: {
- latest: true,
- stuck: false,
- auto_devops: false,
- yaml_errors: false,
- retryable: false,
- cancelable: true,
- failure_reason: false,
- },
- details: {
- status: {
- icon: 'status_running',
- text: 'running',
- label: 'running',
- group: 'running',
- has_details: true,
- details_path: '/gitlab-org/gitlab/pipelines/20333396',
- favicon:
- 'https://assets.gitlab-static.net/assets/ci_favicons/favicon_status_running-2eb56be2871937954b2ba6d6f4ee9fdf7e5e1c146ac45f7be98119ccaca1aca9.ico',
- },
- duration: null,
- finished_at: null,
- stages: [
- {
- name: 'build',
- title: 'build: skipped',
- status: {
- icon: 'status_skipped',
- text: 'skipped',
- label: 'skipped',
- group: 'skipped',
- has_details: true,
- details_path: '/gitlab-org/gitlab/pipelines/20333396#build',
- favicon:
- 'https://assets.gitlab-static.net/assets/ci_favicons/favicon_status_skipped-a2eee568a5bffdb494050c7b62dde241de9189280836288ac8923d369f16222d.ico',
- },
- path: '/gitlab-org/gitlab/pipelines/20333396#build',
- dropdown_path: '/gitlab-org/gitlab/pipelines/20333396/stage.json?stage=build',
- },
- {
- name: 'prepare',
- title: 'prepare: passed',
- status: {
- icon: 'status_success',
- text: 'passed',
- label: 'passed',
- group: 'success',
- has_details: true,
- details_path: '/gitlab-org/gitlab/pipelines/20333396#prepare',
- favicon:
- 'https://assets.gitlab-static.net/assets/ci_favicons/favicon_status_success-26f59841becbef8c6fe414e9e74471d8bfd6a91b5855c19fe7f5923a40a7da47.ico',
- },
- path: '/gitlab-org/gitlab/pipelines/20333396#prepare',
- dropdown_path: '/gitlab-org/gitlab/pipelines/20333396/stage.json?stage=prepare',
- },
- {
- name: 'test',
- title: 'test: running',
- status: {
- icon: 'status_running',
- text: 'running',
- label: 'running',
- group: 'running',
- has_details: true,
- details_path: '/gitlab-org/gitlab/pipelines/20333396#test',
- favicon:
- 'https://assets.gitlab-static.net/assets/ci_favicons/favicon_status_running-2eb56be2871937954b2ba6d6f4ee9fdf7e5e1c146ac45f7be98119ccaca1aca9.ico',
- },
- path: '/gitlab-org/gitlab/pipelines/20333396#test',
- dropdown_path: '/gitlab-org/gitlab/pipelines/20333396/stage.json?stage=test',
- },
- {
- name: 'post-test',
- title: 'post-test: created',
- status: {
- icon: 'status_created',
- text: 'created',
- label: 'created',
- group: 'created',
- has_details: true,
- details_path: '/gitlab-org/gitlab/pipelines/20333396#post-test',
- favicon:
- 'https://assets.gitlab-static.net/assets/ci_favicons/favicon_status_created-e997aa0b7db73165df8a9d6803932b18d7b7cc37d604d2d96e378fea2dba9c5f.ico',
- },
- path: '/gitlab-org/gitlab/pipelines/20333396#post-test',
- dropdown_path: '/gitlab-org/gitlab/pipelines/20333396/stage.json?stage=post-test',
- },
- {
- name: 'pages',
- title: 'pages: created',
- status: {
- icon: 'status_created',
- text: 'created',
- label: 'created',
- group: 'created',
- has_details: true,
- details_path: '/gitlab-org/gitlab/pipelines/20333396#pages',
- favicon:
- 'https://assets.gitlab-static.net/assets/ci_favicons/favicon_status_created-e997aa0b7db73165df8a9d6803932b18d7b7cc37d604d2d96e378fea2dba9c5f.ico',
- },
- path: '/gitlab-org/gitlab/pipelines/20333396#pages',
- dropdown_path: '/gitlab-org/gitlab/pipelines/20333396/stage.json?stage=pages',
- },
- {
- name: 'post-cleanup',
- title: 'post-cleanup: created',
- status: {
- icon: 'status_created',
- text: 'created',
- label: 'created',
- group: 'created',
- has_details: true,
- details_path: '/gitlab-org/gitlab/pipelines/20333396#post-cleanup',
- favicon:
- 'https://assets.gitlab-static.net/assets/ci_favicons/favicon_status_created-e997aa0b7db73165df8a9d6803932b18d7b7cc37d604d2d96e378fea2dba9c5f.ico',
- },
- path: '/gitlab-org/gitlab/pipelines/20333396#post-cleanup',
- dropdown_path: '/gitlab-org/gitlab/pipelines/20333396/stage.json?stage=post-cleanup',
- },
- ],
- artifacts: [
- {
- name: 'gitlab:assets:compile',
- expired: false,
- expire_at: '2018-05-12T14:22:54.730Z',
- path: '/gitlab-org/gitlab/-/jobs/62411438/artifacts/download',
- keep_path: '/gitlab-org/gitlab/-/jobs/62411438/artifacts/keep',
- browse_path: '/gitlab-org/gitlab/-/jobs/62411438/artifacts/browse',
- },
- {
- name: 'rspec-mysql 12 28',
- expired: false,
- expire_at: '2018-05-12T14:22:45.136Z',
- path: '/gitlab-org/gitlab/-/jobs/62411397/artifacts/download',
- keep_path: '/gitlab-org/gitlab/-/jobs/62411397/artifacts/keep',
- browse_path: '/gitlab-org/gitlab/-/jobs/62411397/artifacts/browse',
- },
- {
- name: 'rspec-mysql 6 28',
- expired: false,
- expire_at: '2018-05-12T14:22:41.523Z',
- path: '/gitlab-org/gitlab/-/jobs/62411391/artifacts/download',
- keep_path: '/gitlab-org/gitlab/-/jobs/62411391/artifacts/keep',
- browse_path: '/gitlab-org/gitlab/-/jobs/62411391/artifacts/browse',
- },
- {
- name: 'rspec-pg geo 0 1',
- expired: false,
- expire_at: '2018-05-12T14:22:13.287Z',
- path: '/gitlab-org/gitlab/-/jobs/62411353/artifacts/download',
- keep_path: '/gitlab-org/gitlab/-/jobs/62411353/artifacts/keep',
- browse_path: '/gitlab-org/gitlab/-/jobs/62411353/artifacts/browse',
- },
- {
- name: 'rspec-mysql 0 28',
- expired: false,
- expire_at: '2018-05-12T14:22:06.834Z',
- path: '/gitlab-org/gitlab/-/jobs/62411385/artifacts/download',
- keep_path: '/gitlab-org/gitlab/-/jobs/62411385/artifacts/keep',
- browse_path: '/gitlab-org/gitlab/-/jobs/62411385/artifacts/browse',
- },
- {
- name: 'spinach-mysql 0 2',
- expired: false,
- expire_at: '2018-05-12T14:21:51.409Z',
- path: '/gitlab-org/gitlab/-/jobs/62411423/artifacts/download',
- keep_path: '/gitlab-org/gitlab/-/jobs/62411423/artifacts/keep',
- browse_path: '/gitlab-org/gitlab/-/jobs/62411423/artifacts/browse',
- },
- {
- name: 'karma',
- expired: false,
- expire_at: '2018-05-12T14:21:20.934Z',
- path: '/gitlab-org/gitlab/-/jobs/62411440/artifacts/download',
- keep_path: '/gitlab-org/gitlab/-/jobs/62411440/artifacts/keep',
- browse_path: '/gitlab-org/gitlab/-/jobs/62411440/artifacts/browse',
- },
- {
- name: 'spinach-pg 0 2',
- expired: false,
- expire_at: '2018-05-12T14:20:01.028Z',
- path: '/gitlab-org/gitlab/-/jobs/62411419/artifacts/download',
- keep_path: '/gitlab-org/gitlab/-/jobs/62411419/artifacts/keep',
- browse_path: '/gitlab-org/gitlab/-/jobs/62411419/artifacts/browse',
- },
- {
- name: 'spinach-pg 1 2',
- expired: false,
- expire_at: '2018-05-12T14:19:04.336Z',
- path: '/gitlab-org/gitlab/-/jobs/62411421/artifacts/download',
- keep_path: '/gitlab-org/gitlab/-/jobs/62411421/artifacts/keep',
- browse_path: '/gitlab-org/gitlab/-/jobs/62411421/artifacts/browse',
- },
- {
- name: 'sast',
- expired: null,
- expire_at: null,
- path: '/gitlab-org/gitlab/-/jobs/62411442/artifacts/download',
- browse_path: '/gitlab-org/gitlab/-/jobs/62411442/artifacts/browse',
- },
- {
- name: 'code_quality',
- expired: false,
- expire_at: '2018-04-18T14:16:24.484Z',
- path: '/gitlab-org/gitlab/-/jobs/62411441/artifacts/download',
- keep_path: '/gitlab-org/gitlab/-/jobs/62411441/artifacts/keep',
- browse_path: '/gitlab-org/gitlab/-/jobs/62411441/artifacts/browse',
- },
- {
- name: 'cache gems',
- expired: null,
- expire_at: null,
- path: '/gitlab-org/gitlab/-/jobs/62411447/artifacts/download',
- browse_path: '/gitlab-org/gitlab/-/jobs/62411447/artifacts/browse',
- },
- {
- name: 'dependency_scanning',
- expired: null,
- expire_at: null,
- path: '/gitlab-org/gitlab/-/jobs/62411443/artifacts/download',
- browse_path: '/gitlab-org/gitlab/-/jobs/62411443/artifacts/browse',
- },
- {
- name: 'compile-assets',
- expired: false,
- expire_at: '2018-04-18T14:12:07.638Z',
- path: '/gitlab-org/gitlab/-/jobs/62411334/artifacts/download',
- keep_path: '/gitlab-org/gitlab/-/jobs/62411334/artifacts/keep',
- browse_path: '/gitlab-org/gitlab/-/jobs/62411334/artifacts/browse',
- },
- {
- name: 'setup-test-env',
- expired: false,
- expire_at: '2018-04-18T14:10:27.024Z',
- path: '/gitlab-org/gitlab/-/jobs/62411336/artifacts/download',
- keep_path: '/gitlab-org/gitlab/-/jobs/62411336/artifacts/keep',
- browse_path: '/gitlab-org/gitlab/-/jobs/62411336/artifacts/browse',
- },
- {
- name: 'retrieve-tests-metadata',
- expired: false,
- expire_at: '2018-05-12T14:06:35.926Z',
- path: '/gitlab-org/gitlab/-/jobs/62411333/artifacts/download',
- keep_path: '/gitlab-org/gitlab/-/jobs/62411333/artifacts/keep',
- browse_path: '/gitlab-org/gitlab/-/jobs/62411333/artifacts/browse',
- },
- ],
- manual_actions: [
- {
- name: 'package-and-qa',
- path: '/gitlab-org/gitlab/-/jobs/62411330/play',
- playable: true,
- },
- {
- name: 'review-docs-deploy',
- path: '/gitlab-org/gitlab/-/jobs/62411332/play',
- playable: true,
- },
- ],
- },
- ref: {
- name: 'master',
- path: '/gitlab-org/gitlab/commits/master',
- tag: false,
- branch: true,
- },
- commit: {
- id: 'e6a2885c503825792cb8a84a8731295e361bd059',
- short_id: 'e6a2885c',
- title: "Merge branch 'ce-to-ee-2018-04-11' into 'master'",
- created_at: '2018-04-11T14:04:39.000Z',
- parent_ids: [
- '5d9b5118f6055f72cff1a82b88133609912f2c1d',
- '6fdc6ee76a8062fe41b1a33f7c503334a6ebdc02',
- ],
- message:
- "Merge branch 'ce-to-ee-2018-04-11' into 'master'\n\nCE upstream - 2018-04-11 12:26 UTC\n\nSee merge request gitlab-org/gitlab-ee!5326",
- author_name: 'Rémy Coutable',
- author_email: 'remy@rymai.me',
- authored_date: '2018-04-11T14:04:39.000Z',
- committer_name: 'Rémy Coutable',
- committer_email: 'remy@rymai.me',
- committed_date: '2018-04-11T14:04:39.000Z',
- author: {
- id: 128633,
- name: 'Rémy Coutable',
- username: 'rymai',
- state: 'active',
- avatar_url:
- 'https://secure.gravatar.com/avatar/263da227929cc0035cb0eba512bcf81a?s=80\u0026d=identicon',
- web_url: 'https://gitlab.com/rymai',
- path: '/rymai',
- },
- author_gravatar_url:
- 'https://secure.gravatar.com/avatar/263da227929cc0035cb0eba512bcf81a?s=80\u0026d=identicon',
- commit_url:
- 'https://gitlab.com/gitlab-org/gitlab/commit/e6a2885c503825792cb8a84a8731295e361bd059',
- commit_path: '/gitlab-org/gitlab/commit/e6a2885c503825792cb8a84a8731295e361bd059',
- },
- cancel_path: '/gitlab-org/gitlab/pipelines/20333396/cancel',
- triggered_by: null,
- triggered: [],
-};
-
-export const stageReply = {
- name: 'deploy',
- title: 'deploy: running',
- latest_statuses: [
- {
- id: 928,
- name: 'stop staging',
- started: false,
- build_path: '/twitter/flight/-/jobs/928',
- cancel_path: '/twitter/flight/-/jobs/928/cancel',
- playable: false,
- created_at: '2018-04-04T20:02:02.728Z',
- updated_at: '2018-04-04T20:02:02.766Z',
- status: {
- icon: 'status_pending',
- text: 'pending',
- label: 'pending',
- group: 'pending',
- tooltip: 'pending',
- has_details: true,
- details_path: '/twitter/flight/-/jobs/928',
- favicon:
- '/assets/ci_favicons/dev/favicon_status_pending-db32e1faf94b9f89530ac519790920d1f18ea8f6af6cd2e0a26cd6840cacf101.ico',
- action: {
- icon: 'cancel',
- title: 'Cancel',
- path: '/twitter/flight/-/jobs/928/cancel',
- method: 'post',
- },
- },
- },
- {
- id: 926,
- name: 'production',
- started: false,
- build_path: '/twitter/flight/-/jobs/926',
- retry_path: '/twitter/flight/-/jobs/926/retry',
- play_path: '/twitter/flight/-/jobs/926/play',
- playable: true,
- created_at: '2018-04-04T20:00:57.202Z',
- updated_at: '2018-04-04T20:11:13.110Z',
- status: {
- icon: 'status_canceled',
- text: 'canceled',
- label: 'manual play action',
- group: 'canceled',
- tooltip: 'canceled',
- has_details: true,
- details_path: '/twitter/flight/-/jobs/926',
- favicon:
- '/assets/ci_favicons/dev/favicon_status_canceled-5491840b9b6feafba0bc599cbd49ee9580321dc809683856cf1b0d51532b1af6.ico',
- action: {
- icon: 'play',
- title: 'Play',
- path: '/twitter/flight/-/jobs/926/play',
- method: 'post',
- },
- },
- },
- {
- id: 217,
- name: 'staging',
- started: '2018-03-07T08:41:46.234Z',
- build_path: '/twitter/flight/-/jobs/217',
- retry_path: '/twitter/flight/-/jobs/217/retry',
- playable: false,
- created_at: '2018-03-07T14:41:58.093Z',
- updated_at: '2018-03-07T14:41:58.093Z',
- status: {
- icon: 'status_success',
- text: 'passed',
- label: 'passed',
- group: 'success',
- tooltip: 'passed',
- has_details: true,
- details_path: '/twitter/flight/-/jobs/217',
- favicon:
- '/assets/ci_favicons/dev/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.ico',
- action: {
- icon: 'retry',
- title: 'Retry',
- path: '/twitter/flight/-/jobs/217/retry',
- method: 'post',
- },
- },
- },
- ],
- status: {
- icon: 'status_running',
- text: 'running',
- label: 'running',
- group: 'running',
- tooltip: 'running',
- has_details: true,
- details_path: '/twitter/flight/pipelines/13#deploy',
- favicon:
- '/assets/ci_favicons/dev/favicon_status_running-c3ad2fc53ea6079c174e5b6c1351ff349e99ec3af5a5622fb77b0fe53ea279c1.ico',
- },
- path: '/twitter/flight/pipelines/13#deploy',
- dropdown_path: '/twitter/flight/pipelines/13/stage.json?stage=deploy',
-};
diff --git a/spec/javascripts/pipelines/pipeline_details_mediator_spec.js b/spec/javascripts/pipelines/pipeline_details_mediator_spec.js
deleted file mode 100644
index 61ee2dc13ca..00000000000
--- a/spec/javascripts/pipelines/pipeline_details_mediator_spec.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import PipelineMediator from '~/pipelines/pipeline_details_mediator';
-
-describe('PipelineMdediator', () => {
- let mediator;
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- mediator = new PipelineMediator({ endpoint: 'foo.json' });
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('should set defaults', () => {
- expect(mediator.options).toEqual({ endpoint: 'foo.json' });
- expect(mediator.state.isLoading).toEqual(false);
- expect(mediator.store).toBeDefined();
- expect(mediator.service).toBeDefined();
- });
-
- describe('request and store data', () => {
- it('should store received data', done => {
- mock.onGet('foo.json').reply(200, { id: '121123' });
- mediator.fetchPipeline();
-
- setTimeout(() => {
- expect(mediator.store.state.pipeline).toEqual({ id: '121123' });
- done();
- }, 0);
- });
- });
-});
diff --git a/spec/javascripts/pipelines/pipelines_actions_spec.js b/spec/javascripts/pipelines/pipelines_actions_spec.js
deleted file mode 100644
index 91f7d2167cc..00000000000
--- a/spec/javascripts/pipelines/pipelines_actions_spec.js
+++ /dev/null
@@ -1,128 +0,0 @@
-import Vue from 'vue';
-import MockAdapter from 'axios-mock-adapter';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import { TEST_HOST } from 'spec/test_constants';
-import axios from '~/lib/utils/axios_utils';
-import PipelinesActions from '~/pipelines/components/pipelines_actions.vue';
-
-describe('Pipelines Actions dropdown', () => {
- const Component = Vue.extend(PipelinesActions);
- let vm;
- let mock;
-
- afterEach(() => {
- vm.$destroy();
- mock.restore();
- });
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- });
-
- describe('manual actions', () => {
- const actions = [
- {
- name: 'stop_review',
- path: `${TEST_HOST}/root/review-app/builds/1893/play`,
- },
- {
- name: 'foo',
- path: `${TEST_HOST}/disabled/pipeline/action`,
- playable: false,
- },
- ];
-
- beforeEach(() => {
- vm = mountComponent(Component, { actions });
- });
-
- it('renders a dropdown with the provided actions', () => {
- const dropdownItems = vm.$el.querySelectorAll('.dropdown-menu li');
-
- expect(dropdownItems.length).toEqual(actions.length);
- });
-
- it("renders a disabled action when it's not playable", () => {
- const dropdownItem = vm.$el.querySelector('.dropdown-menu li:last-child button');
-
- expect(dropdownItem).toBeDisabled();
- });
-
- describe('on click', () => {
- it('makes a request and toggles the loading state', done => {
- mock.onPost(actions.path).reply(200);
-
- vm.$el.querySelector('.dropdown-menu li button').click();
-
- expect(vm.isLoading).toEqual(true);
-
- setTimeout(() => {
- expect(vm.isLoading).toEqual(false);
-
- done();
- });
- });
- });
- });
-
- describe('scheduled jobs', () => {
- const scheduledJobAction = {
- name: 'scheduled action',
- path: `${TEST_HOST}/scheduled/job/action`,
- playable: true,
- scheduled_at: '2063-04-05T00:42:00Z',
- };
- const expiredJobAction = {
- name: 'expired action',
- path: `${TEST_HOST}/expired/job/action`,
- playable: true,
- scheduled_at: '2018-10-05T08:23:00Z',
- };
- const findDropdownItem = action => {
- const buttons = vm.$el.querySelectorAll('.dropdown-menu li button');
- return Array.prototype.find.call(buttons, element =>
- element.innerText.trim().startsWith(action.name),
- );
- };
-
- beforeEach(done => {
- spyOn(Date, 'now').and.callFake(() => new Date('2063-04-04T00:42:00Z').getTime());
- vm = mountComponent(Component, { actions: [scheduledJobAction, expiredJobAction] });
-
- Vue.nextTick()
- .then(done)
- .catch(done.fail);
- });
-
- it('makes post request after confirming', done => {
- mock.onPost(scheduledJobAction.path).reply(200);
- spyOn(window, 'confirm').and.callFake(() => true);
-
- findDropdownItem(scheduledJobAction).click();
-
- expect(window.confirm).toHaveBeenCalled();
- setTimeout(() => {
- expect(mock.history.post.length).toBe(1);
- done();
- });
- });
-
- it('does not make post request if confirmation is cancelled', () => {
- mock.onPost(scheduledJobAction.path).reply(200);
- spyOn(window, 'confirm').and.callFake(() => false);
-
- findDropdownItem(scheduledJobAction).click();
-
- expect(window.confirm).toHaveBeenCalled();
- expect(mock.history.post.length).toBe(0);
- });
-
- it('displays the remaining time in the dropdown', () => {
- expect(findDropdownItem(scheduledJobAction)).toContainText('24:00:00');
- });
-
- it('displays 00:00:00 for expired jobs in the dropdown', () => {
- expect(findDropdownItem(expiredJobAction)).toContainText('00:00:00');
- });
- });
-});
diff --git a/spec/javascripts/pipelines/pipelines_artifacts_spec.js b/spec/javascripts/pipelines/pipelines_artifacts_spec.js
deleted file mode 100644
index 7705d5a19bf..00000000000
--- a/spec/javascripts/pipelines/pipelines_artifacts_spec.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import Vue from 'vue';
-import artifactsComp from '~/pipelines/components/pipelines_artifacts.vue';
-
-describe('Pipelines Artifacts dropdown', () => {
- let component;
- let artifacts;
-
- beforeEach(() => {
- const ArtifactsComponent = Vue.extend(artifactsComp);
-
- artifacts = [
- {
- name: 'artifact',
- path: '/download/path',
- },
- ];
-
- component = new ArtifactsComponent({
- propsData: {
- artifacts,
- },
- }).$mount();
- });
-
- it('should render a dropdown with the provided artifacts', () => {
- expect(component.$el.querySelectorAll('.dropdown-menu li').length).toEqual(artifacts.length);
- });
-
- it('should render a link with the provided path', () => {
- expect(component.$el.querySelector('.dropdown-menu li a').getAttribute('href')).toEqual(
- artifacts[0].path,
- );
-
- expect(component.$el.querySelector('.dropdown-menu li a').textContent).toContain(
- artifacts[0].name,
- );
- });
-});
diff --git a/spec/javascripts/pipelines/pipelines_spec.js b/spec/javascripts/pipelines/pipelines_spec.js
deleted file mode 100644
index 5cd91413c5f..00000000000
--- a/spec/javascripts/pipelines/pipelines_spec.js
+++ /dev/null
@@ -1,783 +0,0 @@
-import Vue from 'vue';
-import MockAdapter from 'axios-mock-adapter';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import axios from '~/lib/utils/axios_utils';
-import pipelinesComp from '~/pipelines/components/pipelines.vue';
-import Store from '~/pipelines/stores/pipelines_store';
-import { pipelineWithStages, stageReply } from './mock_data';
-
-describe('Pipelines', () => {
- const jsonFixtureName = 'pipelines/pipelines.json';
-
- preloadFixtures(jsonFixtureName);
-
- let PipelinesComponent;
- let pipelines;
- let vm;
- let mock;
-
- const paths = {
- endpoint: 'twitter/flight/pipelines.json',
- autoDevopsPath: '/help/topics/autodevops/index.md',
- helpPagePath: '/help/ci/quick_start/README',
- emptyStateSvgPath: '/assets/illustrations/pipelines_empty.svg',
- errorStateSvgPath: '/assets/illustrations/pipelines_failed.svg',
- noPipelinesSvgPath: '/assets/illustrations/pipelines_pending.svg',
- ciLintPath: '/ci/lint',
- resetCachePath: '/twitter/flight/settings/ci_cd/reset_cache',
- newPipelinePath: '/twitter/flight/pipelines/new',
- };
-
- const noPermissions = {
- endpoint: 'twitter/flight/pipelines.json',
- autoDevopsPath: '/help/topics/autodevops/index.md',
- helpPagePath: '/help/ci/quick_start/README',
- emptyStateSvgPath: '/assets/illustrations/pipelines_empty.svg',
- errorStateSvgPath: '/assets/illustrations/pipelines_failed.svg',
- noPipelinesSvgPath: '/assets/illustrations/pipelines_pending.svg',
- };
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
-
- pipelines = getJSONFixture(jsonFixtureName);
-
- PipelinesComponent = Vue.extend(pipelinesComp);
- });
-
- afterEach(() => {
- vm.$destroy();
- mock.restore();
- });
-
- describe('With permission', () => {
- describe('With pipelines in main tab', () => {
- beforeEach(done => {
- mock.onGet('twitter/flight/pipelines.json').reply(200, pipelines);
-
- vm = mountComponent(PipelinesComponent, {
- store: new Store(),
- hasGitlabCi: true,
- canCreatePipeline: true,
- ...paths,
- });
-
- setTimeout(() => {
- done();
- });
- });
-
- it('renders tabs', () => {
- expect(vm.$el.querySelector('.js-pipelines-tab-all').textContent.trim()).toContain('All');
- });
-
- it('renders Run Pipeline link', () => {
- expect(vm.$el.querySelector('.js-run-pipeline').getAttribute('href')).toEqual(
- paths.newPipelinePath,
- );
- });
-
- it('renders CI Lint link', () => {
- expect(vm.$el.querySelector('.js-ci-lint').getAttribute('href')).toEqual(paths.ciLintPath);
- });
-
- it('renders Clear Runner Cache button', () => {
- expect(vm.$el.querySelector('.js-clear-cache').textContent.trim()).toEqual(
- 'Clear Runner Caches',
- );
- });
-
- it('renders pipelines table', () => {
- expect(vm.$el.querySelectorAll('.gl-responsive-table-row').length).toEqual(
- pipelines.pipelines.length + 1,
- );
- });
- });
-
- describe('Without pipelines on main tab with CI', () => {
- beforeEach(done => {
- mock.onGet('twitter/flight/pipelines.json').reply(200, {
- pipelines: [],
- count: {
- all: 0,
- pending: 0,
- running: 0,
- finished: 0,
- },
- });
- vm = mountComponent(PipelinesComponent, {
- store: new Store(),
- hasGitlabCi: true,
- canCreatePipeline: true,
- ...paths,
- });
-
- setTimeout(() => {
- done();
- });
- });
-
- it('renders tabs', () => {
- expect(vm.$el.querySelector('.js-pipelines-tab-all').textContent.trim()).toContain('All');
- });
-
- it('renders Run Pipeline link', () => {
- expect(vm.$el.querySelector('.js-run-pipeline').getAttribute('href')).toEqual(
- paths.newPipelinePath,
- );
- });
-
- it('renders CI Lint link', () => {
- expect(vm.$el.querySelector('.js-ci-lint').getAttribute('href')).toEqual(paths.ciLintPath);
- });
-
- it('renders Clear Runner Cache button', () => {
- expect(vm.$el.querySelector('.js-clear-cache').textContent.trim()).toEqual(
- 'Clear Runner Caches',
- );
- });
-
- it('renders tab empty state', () => {
- expect(vm.$el.querySelector('.empty-state h4').textContent.trim()).toEqual(
- 'There are currently no pipelines.',
- );
- });
- });
-
- describe('Without pipelines nor CI', () => {
- beforeEach(done => {
- mock.onGet('twitter/flight/pipelines.json').reply(200, {
- pipelines: [],
- count: {
- all: 0,
- pending: 0,
- running: 0,
- finished: 0,
- },
- });
- vm = mountComponent(PipelinesComponent, {
- store: new Store(),
- hasGitlabCi: false,
- canCreatePipeline: true,
- ...paths,
- });
-
- setTimeout(() => {
- done();
- });
- });
-
- it('renders empty state', () => {
- expect(vm.$el.querySelector('.js-empty-state h4').textContent.trim()).toEqual(
- 'Build with confidence',
- );
-
- expect(vm.$el.querySelector('.js-get-started-pipelines').getAttribute('href')).toEqual(
- paths.helpPagePath,
- );
- });
-
- it('does not render tabs nor buttons', () => {
- expect(vm.$el.querySelector('.js-pipelines-tab-all')).toBeNull();
- expect(vm.$el.querySelector('.js-run-pipeline')).toBeNull();
- expect(vm.$el.querySelector('.js-ci-lint')).toBeNull();
- expect(vm.$el.querySelector('.js-clear-cache')).toBeNull();
- });
- });
-
- describe('When API returns error', () => {
- beforeEach(done => {
- mock.onGet('twitter/flight/pipelines.json').reply(500, {});
- vm = mountComponent(PipelinesComponent, {
- store: new Store(),
- hasGitlabCi: false,
- canCreatePipeline: true,
- ...paths,
- });
-
- setTimeout(() => {
- done();
- });
- });
-
- it('renders tabs', () => {
- expect(vm.$el.querySelector('.js-pipelines-tab-all').textContent.trim()).toContain('All');
- });
-
- it('renders buttons', () => {
- expect(vm.$el.querySelector('.js-run-pipeline').getAttribute('href')).toEqual(
- paths.newPipelinePath,
- );
-
- expect(vm.$el.querySelector('.js-ci-lint').getAttribute('href')).toEqual(paths.ciLintPath);
- expect(vm.$el.querySelector('.js-clear-cache').textContent.trim()).toEqual(
- 'Clear Runner Caches',
- );
- });
-
- it('renders error state', () => {
- expect(vm.$el.querySelector('.empty-state').textContent.trim()).toContain(
- 'There was an error fetching the pipelines.',
- );
- });
- });
- });
-
- describe('Without permission', () => {
- describe('With pipelines in main tab', () => {
- beforeEach(done => {
- mock.onGet('twitter/flight/pipelines.json').reply(200, pipelines);
-
- vm = mountComponent(PipelinesComponent, {
- store: new Store(),
- hasGitlabCi: false,
- canCreatePipeline: false,
- ...noPermissions,
- });
-
- setTimeout(() => {
- done();
- });
- });
-
- it('renders tabs', () => {
- expect(vm.$el.querySelector('.js-pipelines-tab-all').textContent.trim()).toContain('All');
- });
-
- it('does not render buttons', () => {
- expect(vm.$el.querySelector('.js-run-pipeline')).toBeNull();
- expect(vm.$el.querySelector('.js-ci-lint')).toBeNull();
- expect(vm.$el.querySelector('.js-clear-cache')).toBeNull();
- });
-
- it('renders pipelines table', () => {
- expect(vm.$el.querySelectorAll('.gl-responsive-table-row').length).toEqual(
- pipelines.pipelines.length + 1,
- );
- });
- });
-
- describe('Without pipelines on main tab with CI', () => {
- beforeEach(done => {
- mock.onGet('twitter/flight/pipelines.json').reply(200, {
- pipelines: [],
- count: {
- all: 0,
- pending: 0,
- running: 0,
- finished: 0,
- },
- });
-
- vm = mountComponent(PipelinesComponent, {
- store: new Store(),
- hasGitlabCi: true,
- canCreatePipeline: false,
- ...noPermissions,
- });
-
- setTimeout(() => {
- done();
- });
- });
-
- it('renders tabs', () => {
- expect(vm.$el.querySelector('.js-pipelines-tab-all').textContent.trim()).toContain('All');
- });
-
- it('does not render buttons', () => {
- expect(vm.$el.querySelector('.js-run-pipeline')).toBeNull();
- expect(vm.$el.querySelector('.js-ci-lint')).toBeNull();
- expect(vm.$el.querySelector('.js-clear-cache')).toBeNull();
- });
-
- it('renders tab empty state', () => {
- expect(vm.$el.querySelector('.empty-state h4').textContent.trim()).toEqual(
- 'There are currently no pipelines.',
- );
- });
- });
-
- describe('Without pipelines nor CI', () => {
- beforeEach(done => {
- mock.onGet('twitter/flight/pipelines.json').reply(200, {
- pipelines: [],
- count: {
- all: 0,
- pending: 0,
- running: 0,
- finished: 0,
- },
- });
-
- vm = mountComponent(PipelinesComponent, {
- store: new Store(),
- hasGitlabCi: false,
- canCreatePipeline: false,
- ...noPermissions,
- });
-
- setTimeout(() => {
- done();
- });
- });
-
- it('renders empty state without button to set CI', () => {
- expect(vm.$el.querySelector('.js-empty-state').textContent.trim()).toEqual(
- 'This project is not currently set up to run pipelines.',
- );
-
- expect(vm.$el.querySelector('.js-get-started-pipelines')).toBeNull();
- });
-
- it('does not render tabs or buttons', () => {
- expect(vm.$el.querySelector('.js-pipelines-tab-all')).toBeNull();
- expect(vm.$el.querySelector('.js-run-pipeline')).toBeNull();
- expect(vm.$el.querySelector('.js-ci-lint')).toBeNull();
- expect(vm.$el.querySelector('.js-clear-cache')).toBeNull();
- });
- });
-
- describe('When API returns error', () => {
- beforeEach(done => {
- mock.onGet('twitter/flight/pipelines.json').reply(500, {});
-
- vm = mountComponent(PipelinesComponent, {
- store: new Store(),
- hasGitlabCi: false,
- canCreatePipeline: true,
- ...noPermissions,
- });
-
- setTimeout(() => {
- done();
- });
- });
-
- it('renders tabs', () => {
- expect(vm.$el.querySelector('.js-pipelines-tab-all').textContent.trim()).toContain('All');
- });
-
- it('does not renders buttons', () => {
- expect(vm.$el.querySelector('.js-run-pipeline')).toBeNull();
- expect(vm.$el.querySelector('.js-ci-lint')).toBeNull();
- expect(vm.$el.querySelector('.js-clear-cache')).toBeNull();
- });
-
- it('renders error state', () => {
- expect(vm.$el.querySelector('.empty-state').textContent.trim()).toContain(
- 'There was an error fetching the pipelines.',
- );
- });
- });
- });
-
- describe('successful request', () => {
- describe('with pipelines', () => {
- beforeEach(() => {
- mock.onGet('twitter/flight/pipelines.json').reply(200, pipelines);
-
- vm = mountComponent(PipelinesComponent, {
- store: new Store(),
- hasGitlabCi: true,
- canCreatePipeline: true,
- ...paths,
- });
- });
-
- it('should render table', done => {
- setTimeout(() => {
- expect(vm.$el.querySelector('.table-holder')).toBeDefined();
- expect(vm.$el.querySelectorAll('.gl-responsive-table-row').length).toEqual(
- pipelines.pipelines.length + 1,
- );
- done();
- });
- });
-
- it('should render navigation tabs', done => {
- setTimeout(() => {
- expect(vm.$el.querySelector('.js-pipelines-tab-pending').textContent.trim()).toContain(
- 'Pending',
- );
-
- expect(vm.$el.querySelector('.js-pipelines-tab-all').textContent.trim()).toContain('All');
-
- expect(vm.$el.querySelector('.js-pipelines-tab-running').textContent.trim()).toContain(
- 'Running',
- );
-
- expect(vm.$el.querySelector('.js-pipelines-tab-finished').textContent.trim()).toContain(
- 'Finished',
- );
-
- expect(vm.$el.querySelector('.js-pipelines-tab-branches').textContent.trim()).toContain(
- 'Branches',
- );
-
- expect(vm.$el.querySelector('.js-pipelines-tab-tags').textContent.trim()).toContain(
- 'Tags',
- );
- done();
- });
- });
-
- it('should make an API request when using tabs', done => {
- setTimeout(() => {
- spyOn(vm, 'updateContent');
- vm.$el.querySelector('.js-pipelines-tab-finished').click();
-
- expect(vm.updateContent).toHaveBeenCalledWith({ scope: 'finished', page: '1' });
- done();
- });
- });
-
- describe('with pagination', () => {
- it('should make an API request when using pagination', done => {
- setTimeout(() => {
- spyOn(vm, 'updateContent');
- // Mock pagination
- vm.store.state.pageInfo = {
- page: 1,
- total: 10,
- perPage: 2,
- nextPage: 2,
- totalPages: 5,
- };
-
- vm.$nextTick(() => {
- vm.$el.querySelector('.next-page-item').click();
-
- expect(vm.updateContent).toHaveBeenCalledWith({ scope: 'all', page: '2' });
-
- done();
- });
- });
- });
- });
- });
- });
-
- describe('methods', () => {
- beforeEach(() => {
- spyOn(window.history, 'pushState').and.stub();
- });
-
- describe('updateContent', () => {
- it('should set given parameters', () => {
- vm = mountComponent(PipelinesComponent, {
- store: new Store(),
- hasGitlabCi: true,
- canCreatePipeline: true,
- ...paths,
- });
- vm.updateContent({ scope: 'finished', page: '4' });
-
- expect(vm.page).toEqual('4');
- expect(vm.scope).toEqual('finished');
- expect(vm.requestData.scope).toEqual('finished');
- expect(vm.requestData.page).toEqual('4');
- });
- });
-
- describe('onChangeTab', () => {
- it('should set page to 1', () => {
- vm = mountComponent(PipelinesComponent, {
- store: new Store(),
- hasGitlabCi: true,
- canCreatePipeline: true,
- ...paths,
- });
- spyOn(vm, 'updateContent');
-
- vm.onChangeTab('running');
-
- expect(vm.updateContent).toHaveBeenCalledWith({ scope: 'running', page: '1' });
- });
- });
-
- describe('onChangePage', () => {
- it('should update page and keep scope', () => {
- vm = mountComponent(PipelinesComponent, {
- store: new Store(),
- hasGitlabCi: true,
- canCreatePipeline: true,
- ...paths,
- });
- spyOn(vm, 'updateContent');
-
- vm.onChangePage(4);
-
- expect(vm.updateContent).toHaveBeenCalledWith({ scope: vm.scope, page: '4' });
- });
- });
- });
-
- describe('computed properties', () => {
- beforeEach(() => {
- vm = mountComponent(PipelinesComponent, {
- store: new Store(),
- hasGitlabCi: true,
- canCreatePipeline: true,
- ...paths,
- });
- });
-
- describe('tabs', () => {
- it('returns default tabs', () => {
- expect(vm.tabs).toEqual([
- { name: 'All', scope: 'all', count: undefined, isActive: true },
- { name: 'Pending', scope: 'pending', count: undefined, isActive: false },
- { name: 'Running', scope: 'running', count: undefined, isActive: false },
- { name: 'Finished', scope: 'finished', count: undefined, isActive: false },
- { name: 'Branches', scope: 'branches', isActive: false },
- { name: 'Tags', scope: 'tags', isActive: false },
- ]);
- });
- });
-
- describe('emptyTabMessage', () => {
- it('returns message with scope', done => {
- vm.scope = 'pending';
-
- vm.$nextTick(() => {
- expect(vm.emptyTabMessage).toEqual('There are currently no pending pipelines.');
- done();
- });
- });
-
- it('returns message without scope when scope is `all`', () => {
- expect(vm.emptyTabMessage).toEqual('There are currently no pipelines.');
- });
- });
-
- describe('stateToRender', () => {
- it('returns loading state when the app is loading', () => {
- expect(vm.stateToRender).toEqual('loading');
- });
-
- it('returns error state when app has error', done => {
- vm.hasError = true;
- vm.isLoading = false;
-
- vm.$nextTick(() => {
- expect(vm.stateToRender).toEqual('error');
- done();
- });
- });
-
- it('returns table list when app has pipelines', done => {
- vm.isLoading = false;
- vm.hasError = false;
- vm.state.pipelines = pipelines.pipelines;
-
- vm.$nextTick(() => {
- expect(vm.stateToRender).toEqual('tableList');
-
- done();
- });
- });
-
- it('returns empty tab when app does not have pipelines but project has pipelines', done => {
- vm.state.count.all = 10;
- vm.isLoading = false;
-
- vm.$nextTick(() => {
- expect(vm.stateToRender).toEqual('emptyTab');
-
- done();
- });
- });
-
- it('returns empty tab when project has CI', done => {
- vm.isLoading = false;
- vm.$nextTick(() => {
- expect(vm.stateToRender).toEqual('emptyTab');
-
- done();
- });
- });
-
- it('returns empty state when project does not have pipelines nor CI', done => {
- vm.isLoading = false;
- vm.hasGitlabCi = false;
- vm.$nextTick(() => {
- expect(vm.stateToRender).toEqual('emptyState');
-
- done();
- });
- });
- });
-
- describe('shouldRenderTabs', () => {
- it('returns true when state is loading & has already made the first request', done => {
- vm.isLoading = true;
- vm.hasMadeRequest = true;
-
- vm.$nextTick(() => {
- expect(vm.shouldRenderTabs).toEqual(true);
-
- done();
- });
- });
-
- it('returns true when state is tableList & has already made the first request', done => {
- vm.isLoading = false;
- vm.state.pipelines = pipelines.pipelines;
- vm.hasMadeRequest = true;
-
- vm.$nextTick(() => {
- expect(vm.shouldRenderTabs).toEqual(true);
-
- done();
- });
- });
-
- it('returns true when state is error & has already made the first request', done => {
- vm.isLoading = false;
- vm.hasError = true;
- vm.hasMadeRequest = true;
-
- vm.$nextTick(() => {
- expect(vm.shouldRenderTabs).toEqual(true);
-
- done();
- });
- });
-
- it('returns true when state is empty tab & has already made the first request', done => {
- vm.isLoading = false;
- vm.state.count.all = 10;
- vm.hasMadeRequest = true;
-
- vm.$nextTick(() => {
- expect(vm.shouldRenderTabs).toEqual(true);
-
- done();
- });
- });
-
- it('returns false when has not made first request', done => {
- vm.hasMadeRequest = false;
-
- vm.$nextTick(() => {
- expect(vm.shouldRenderTabs).toEqual(false);
-
- done();
- });
- });
-
- it('returns false when state is empty state', done => {
- vm.isLoading = false;
- vm.hasMadeRequest = true;
- vm.hasGitlabCi = false;
-
- vm.$nextTick(() => {
- expect(vm.shouldRenderTabs).toEqual(false);
-
- done();
- });
- });
- });
-
- describe('shouldRenderButtons', () => {
- it('returns true when it has paths & has made the first request', done => {
- vm.hasMadeRequest = true;
-
- vm.$nextTick(() => {
- expect(vm.shouldRenderButtons).toEqual(true);
-
- done();
- });
- });
-
- it('returns false when it has not made the first request', done => {
- vm.hasMadeRequest = false;
-
- vm.$nextTick(() => {
- expect(vm.shouldRenderButtons).toEqual(false);
-
- done();
- });
- });
- });
- });
-
- describe('updates results when a staged is clicked', () => {
- beforeEach(() => {
- const copyPipeline = Object.assign({}, pipelineWithStages);
- copyPipeline.id += 1;
- mock
- .onGet('twitter/flight/pipelines.json')
- .reply(
- 200,
- {
- pipelines: [pipelineWithStages],
- count: {
- all: 1,
- finished: 1,
- pending: 0,
- running: 0,
- },
- },
- {
- 'POLL-INTERVAL': 100,
- },
- )
- .onGet(pipelineWithStages.details.stages[0].dropdown_path)
- .reply(200, stageReply);
-
- vm = mountComponent(PipelinesComponent, {
- store: new Store(),
- hasGitlabCi: true,
- canCreatePipeline: true,
- ...paths,
- });
- });
-
- describe('when a request is being made', () => {
- it('stops polling, cancels the request, & restarts polling', done => {
- spyOn(vm.poll, 'stop');
- spyOn(vm.poll, 'restart');
- spyOn(vm.service.cancelationSource, 'cancel').and.callThrough();
-
- setTimeout(() => {
- vm.isMakingRequest = true;
- return vm
- .$nextTick()
- .then(() => {
- vm.$el.querySelector('.js-builds-dropdown-button').click();
- })
- .then(() => {
- expect(vm.service.cancelationSource.cancel).toHaveBeenCalled();
- expect(vm.poll.stop).toHaveBeenCalled();
-
- setTimeout(() => {
- expect(vm.poll.restart).toHaveBeenCalled();
- done();
- }, 0);
- })
- .catch(done.fail);
- }, 0);
- });
- });
-
- describe('when no request is being made', () => {
- it('stops polling & restarts polling', done => {
- spyOn(vm.poll, 'stop');
- spyOn(vm.poll, 'restart');
-
- setTimeout(() => {
- vm.$el.querySelector('.js-builds-dropdown-button').click();
-
- expect(vm.poll.stop).toHaveBeenCalled();
-
- setTimeout(() => {
- expect(vm.poll.restart).toHaveBeenCalled();
- done();
- }, 0);
- }, 0);
- });
- });
- });
-});
diff --git a/spec/javascripts/pipelines/pipelines_table_spec.js b/spec/javascripts/pipelines/pipelines_table_spec.js
deleted file mode 100644
index 5c3387190ab..00000000000
--- a/spec/javascripts/pipelines/pipelines_table_spec.js
+++ /dev/null
@@ -1,86 +0,0 @@
-import Vue from 'vue';
-import pipelinesTableComp from '~/pipelines/components/pipelines_table.vue';
-import '~/lib/utils/datetime_utility';
-
-describe('Pipelines Table', () => {
- const jsonFixtureName = 'pipelines/pipelines.json';
-
- let pipeline;
- let PipelinesTableComponent;
-
- preloadFixtures(jsonFixtureName);
-
- beforeEach(() => {
- const { pipelines } = getJSONFixture(jsonFixtureName);
-
- PipelinesTableComponent = Vue.extend(pipelinesTableComp);
- pipeline = pipelines.find(p => p.user !== null && p.commit !== null);
- });
-
- describe('table', () => {
- let component;
- beforeEach(() => {
- component = new PipelinesTableComponent({
- propsData: {
- pipelines: [],
- autoDevopsHelpPath: 'foo',
- viewType: 'root',
- },
- }).$mount();
- });
-
- afterEach(() => {
- component.$destroy();
- });
-
- it('should render a table', () => {
- expect(component.$el.getAttribute('class')).toContain('ci-table');
- });
-
- it('should render table head with correct columns', () => {
- expect(
- component.$el.querySelector('.table-section.js-pipeline-status').textContent.trim(),
- ).toEqual('Status');
-
- expect(
- component.$el.querySelector('.table-section.js-pipeline-info').textContent.trim(),
- ).toEqual('Pipeline');
-
- expect(
- component.$el.querySelector('.table-section.js-pipeline-commit').textContent.trim(),
- ).toEqual('Commit');
-
- expect(
- component.$el.querySelector('.table-section.js-pipeline-stages').textContent.trim(),
- ).toEqual('Stages');
- });
- });
-
- describe('without data', () => {
- it('should render an empty table', () => {
- const component = new PipelinesTableComponent({
- propsData: {
- pipelines: [],
- autoDevopsHelpPath: 'foo',
- viewType: 'root',
- },
- }).$mount();
-
- expect(component.$el.querySelectorAll('.commit.gl-responsive-table-row').length).toEqual(0);
- });
- });
-
- describe('with data', () => {
- it('should render rows', () => {
- const component = new PipelinesTableComponent({
- propsData: {
- pipelines: [pipeline],
- autoDevopsHelpPath: 'foo',
- viewType: 'root',
- },
- }).$mount();
-
- expect(component.$el.querySelectorAll('.commit.gl-responsive-table-row').length).toEqual(1);
- });
- });
-});
diff --git a/spec/javascripts/pipelines/stage_spec.js b/spec/javascripts/pipelines/stage_spec.js
deleted file mode 100644
index b99688ec371..00000000000
--- a/spec/javascripts/pipelines/stage_spec.js
+++ /dev/null
@@ -1,136 +0,0 @@
-import Vue from 'vue';
-import MockAdapter from 'axios-mock-adapter';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import axios from '~/lib/utils/axios_utils';
-import stage from '~/pipelines/components/stage.vue';
-import eventHub from '~/pipelines/event_hub';
-import { stageReply } from './mock_data';
-
-describe('Pipelines stage component', () => {
- let StageComponent;
- let component;
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
-
- StageComponent = Vue.extend(stage);
-
- component = mountComponent(StageComponent, {
- stage: {
- status: {
- group: 'success',
- icon: 'status_success',
- title: 'success',
- },
- dropdown_path: 'path.json',
- },
- updateDropdown: false,
- });
- });
-
- afterEach(() => {
- component.$destroy();
- mock.restore();
- });
-
- it('should render a dropdown with the status icon', () => {
- expect(component.$el.getAttribute('class')).toEqual('dropdown');
- expect(component.$el.querySelector('svg')).toBeDefined();
- expect(component.$el.querySelector('button').getAttribute('data-toggle')).toEqual('dropdown');
- });
-
- describe('with successful request', () => {
- beforeEach(() => {
- mock.onGet('path.json').reply(200, stageReply);
- });
-
- it('should render the received data and emit `clickedDropdown` event', done => {
- spyOn(eventHub, '$emit');
- component.$el.querySelector('button').click();
-
- setTimeout(() => {
- expect(
- component.$el.querySelector('.js-builds-dropdown-container ul').textContent.trim(),
- ).toContain(stageReply.latest_statuses[0].name);
-
- expect(eventHub.$emit).toHaveBeenCalledWith('clickedDropdown');
- done();
- }, 0);
- });
- });
-
- describe('when request fails', () => {
- beforeEach(() => {
- mock.onGet('path.json').reply(500);
- });
-
- it('should close the dropdown', () => {
- component.$el.click();
-
- setTimeout(() => {
- expect(component.$el.classList.contains('open')).toEqual(false);
- }, 0);
- });
- });
-
- describe('update endpoint correctly', () => {
- beforeEach(() => {
- const copyStage = Object.assign({}, stageReply);
- copyStage.latest_statuses[0].name = 'this is the updated content';
- mock.onGet('bar.json').reply(200, copyStage);
- });
-
- it('should update the stage to request the new endpoint provided', done => {
- component.stage = {
- status: {
- group: 'running',
- icon: 'status_running',
- title: 'running',
- },
- dropdown_path: 'bar.json',
- };
-
- Vue.nextTick(() => {
- component.$el.querySelector('button').click();
-
- setTimeout(() => {
- expect(
- component.$el.querySelector('.js-builds-dropdown-container ul').textContent.trim(),
- ).toContain('this is the updated content');
- done();
- });
- });
- });
- });
-
- describe('pipelineActionRequestComplete', () => {
- beforeEach(() => {
- mock.onGet('path.json').reply(200, stageReply);
-
- mock.onPost(`${stageReply.latest_statuses[0].status.action.path}.json`).reply(200);
- });
-
- describe('within pipeline table', () => {
- it('emits `refreshPipelinesTable` event when `pipelineActionRequestComplete` is triggered', done => {
- spyOn(eventHub, '$emit');
-
- component.type = 'PIPELINES_TABLE';
- component.$el.querySelector('button').click();
-
- setTimeout(() => {
- component.$el.querySelector('.js-ci-action').click();
- setTimeout(() => {
- component
- .$nextTick()
- .then(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('refreshPipelinesTable');
- })
- .then(done)
- .catch(done.fail);
- }, 0);
- }, 0);
- });
- });
- });
-});
diff --git a/spec/javascripts/pipelines/stores/pipeline.json b/spec/javascripts/pipelines/stores/pipeline.json
deleted file mode 100644
index 7d5891d3d52..00000000000
--- a/spec/javascripts/pipelines/stores/pipeline.json
+++ /dev/null
@@ -1,167 +0,0 @@
-{
- "id": 37232567,
- "user": {
- "id": 113870,
- "name": "Phil Hughes",
- "username": "iamphill",
- "state": "active",
- "avatar_url": "https://secure.gravatar.com/avatar/533a51534470a11062df393543eab649?s=80\u0026d=identicon",
- "web_url": "https://gitlab.com/iamphill",
- "status_tooltip_html": null,
- "path": "/iamphill"
- },
- "active": false,
- "coverage": null,
- "source": "push",
- "created_at": "2018-11-20T10:22:52.617Z",
- "updated_at": "2018-11-20T10:24:09.511Z",
- "path": "/gitlab-org/gl-vue-cli/pipelines/37232567",
- "flags": {
- "latest": true,
- "stuck": false,
- "auto_devops": false,
- "yaml_errors": false,
- "retryable": false,
- "cancelable": false,
- "failure_reason": false
- },
- "details": {
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gl-vue-cli/pipelines/37232567",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "duration": 65,
- "finished_at": "2018-11-20T10:24:09.483Z",
- "stages": [
- {
- "name": "test",
- "title": "test: passed",
- "groups": [
- {
- "name": "eslint",
- "size": 1,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gl-vue-cli/-/jobs/122845352",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/gitlab-org/gl-vue-cli/-/jobs/122845352/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "jobs": [
- {
- "id": 122845352,
- "name": "eslint",
- "started": "2018-11-20T10:22:53.369Z",
- "archived": false,
- "build_path": "/gitlab-org/gl-vue-cli/-/jobs/122845352",
- "retry_path": "/gitlab-org/gl-vue-cli/-/jobs/122845352/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2018-11-20T10:22:52.630Z",
- "updated_at": "2018-11-20T10:23:58.948Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gl-vue-cli/-/jobs/122845352",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/gitlab-org/gl-vue-cli/-/jobs/122845352/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gl-vue-cli/pipelines/37232567#test",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "path": "/gitlab-org/gl-vue-cli/pipelines/37232567#test",
- "dropdown_path": "/gitlab-org/gl-vue-cli/pipelines/37232567/stage.json?stage=test"
- }
- ],
- "artifacts": [],
- "manual_actions": [],
- "scheduled_actions": []
- },
- "ref": {
- "name": "master",
- "path": "/gitlab-org/gl-vue-cli/commits/master",
- "tag": false,
- "branch": true
- },
- "commit": {
- "id": "8f179601d481950bcb67032caeb33d1c24dde6bd",
- "short_id": "8f179601",
- "title": "Merge branch 'gl-cli-startt' into 'master'",
- "created_at": "2018-11-20T10:22:51.000Z",
- "parent_ids": [
- "781d78fcd3d6c17ccf208f0cf0ab47c3e5397118",
- "d227a0bb858c48eeee7393fcade1a33748f35183"
- ],
- "message": "Merge branch 'gl-cli-startt' into 'master'\n\nFirst iteration of the CLI\n\nCloses gitlab-foss#53657\n\nSee merge request gitlab-org/gl-vue-cli!2",
- "author_name": "Phil Hughes",
- "author_email": "me@iamphill.com",
- "authored_date": "2018-11-20T10:22:51.000Z",
- "committer_name": "Phil Hughes",
- "committer_email": "me@iamphill.com",
- "committed_date": "2018-11-20T10:22:51.000Z",
- "author": {
- "id": 113870,
- "name": "Phil Hughes",
- "username": "iamphill",
- "state": "active",
- "avatar_url": "https://secure.gravatar.com/avatar/533a51534470a11062df393543eab649?s=80\u0026d=identicon",
- "web_url": "https://gitlab.com/iamphill",
- "status_tooltip_html": null,
- "path": "/iamphill"
- },
- "author_gravatar_url": "https://secure.gravatar.com/avatar/533a51534470a11062df393543eab649?s=80\u0026d=identicon",
- "commit_url": "https://gitlab.com/gitlab-org/gl-vue-cli/commit/8f179601d481950bcb67032caeb33d1c24dde6bd",
- "commit_path": "/gitlab-org/gl-vue-cli/commit/8f179601d481950bcb67032caeb33d1c24dde6bd"
- },
- "triggered_by": null,
- "triggered": []
-}
diff --git a/spec/javascripts/pipelines/stores/pipeline_store.js b/spec/javascripts/pipelines/stores/pipeline_store.js
deleted file mode 100644
index 4a0b3bf4c02..00000000000
--- a/spec/javascripts/pipelines/stores/pipeline_store.js
+++ /dev/null
@@ -1,165 +0,0 @@
-import PipelineStore from '~/pipelines/stores/pipeline_store';
-import LinkedPipelines from '../linked_pipelines_mock.json';
-
-describe('EE Pipeline store', () => {
- let store;
- let data;
-
- beforeEach(() => {
- store = new PipelineStore();
- data = Object.assign({}, LinkedPipelines);
- });
-
- describe('storePipeline', () => {
- beforeAll(() => {
- store.storePipeline(data);
- });
-
- describe('triggered_by', () => {
- it('sets triggered_by as an array', () => {
- expect(store.state.pipeline.triggered_by.length).toEqual(1);
- });
-
- it('adds isExpanding & isLoading keys set to false', () => {
- expect(store.state.pipeline.triggered_by[0].isExpanded).toEqual(false);
- expect(store.state.pipeline.triggered_by[0].isLoading).toEqual(false);
- });
-
- it('parses nested triggered_by', () => {
- expect(store.state.pipeline.triggered_by[0].triggered_by.length).toEqual(1);
- expect(store.state.pipeline.triggered_by[0].triggered_by[0].isExpanded).toEqual(false);
- expect(store.state.pipeline.triggered_by[0].triggered_by[0].isLoading).toEqual(false);
- });
- });
-
- describe('triggered', () => {
- it('adds isExpanding & isLoading keys set to false for each triggered pipeline', () => {
- store.state.pipeline.triggered.forEach(pipeline => {
- expect(pipeline.isExpanded).toEqual(false);
- expect(pipeline.isLoading).toEqual(false);
- });
- });
-
- it('parses nested triggered pipelines', () => {
- store.state.pipeline.triggered[1].triggered.forEach(pipeline => {
- expect(pipeline.isExpanded).toEqual(false);
- expect(pipeline.isLoading).toEqual(false);
- });
- });
- });
- });
-
- describe('resetTriggeredByPipeline', () => {
- beforeEach(() => {
- store.storePipeline(data);
- });
-
- it('closes the pipeline & nested ones', () => {
- store.state.pipeline.triggered_by[0].isExpanded = true;
- store.state.pipeline.triggered_by[0].triggered_by[0].isExpanded = true;
-
- store.resetTriggeredByPipeline(store.state.pipeline, store.state.pipeline.triggered_by[0]);
-
- expect(store.state.pipeline.triggered_by[0].isExpanded).toEqual(false);
- expect(store.state.pipeline.triggered_by[0].triggered_by[0].isExpanded).toEqual(false);
- });
- });
-
- describe('openTriggeredByPipeline', () => {
- beforeEach(() => {
- store.storePipeline(data);
- });
-
- it('opens the given pipeline', () => {
- store.openTriggeredByPipeline(store.state.pipeline, store.state.pipeline.triggered_by[0]);
-
- expect(store.state.pipeline.triggered_by[0].isExpanded).toEqual(true);
- });
- });
-
- describe('closeTriggeredByPipeline', () => {
- beforeEach(() => {
- store.storePipeline(data);
- });
-
- it('closes the given pipeline', () => {
- // open it first
- store.openTriggeredByPipeline(store.state.pipeline, store.state.pipeline.triggered_by[0]);
-
- store.closeTriggeredByPipeline(store.state.pipeline, store.state.pipeline.triggered_by[0]);
-
- expect(store.state.pipeline.triggered_by[0].isExpanded).toEqual(false);
- });
- });
-
- describe('resetTriggeredPipelines', () => {
- beforeEach(() => {
- store.storePipeline(data);
- });
-
- it('closes the pipeline & nested ones', () => {
- store.state.pipeline.triggered[0].isExpanded = true;
- store.state.pipeline.triggered[0].triggered[0].isExpanded = true;
-
- store.resetTriggeredPipeline(store.state.pipeline, store.state.pipeline.triggered[0]);
-
- expect(store.state.pipeline.triggered[0].isExpanded).toEqual(false);
- expect(store.state.pipeline.triggered[0].triggered[0].isExpanded).toEqual(false);
- });
- });
-
- describe('openTriggeredPipeline', () => {
- beforeEach(() => {
- store.storePipeline(data);
- });
-
- it('opens the given pipeline', () => {
- store.openTriggeredPipeline(store.state.pipeline, store.state.pipeline.triggered[0]);
-
- expect(store.state.pipeline.triggered[0].isExpanded).toEqual(true);
- });
- });
-
- describe('closeTriggeredPipeline', () => {
- beforeEach(() => {
- store.storePipeline(data);
- });
-
- it('closes the given pipeline', () => {
- // open it first
- store.openTriggeredPipeline(store.state.pipeline, store.state.pipeline.triggered[0]);
-
- store.closeTriggeredPipeline(store.state.pipeline, store.state.pipeline.triggered[0]);
-
- expect(store.state.pipeline.triggered[0].isExpanded).toEqual(false);
- });
- });
-
- describe('toggleLoading', () => {
- beforeEach(() => {
- store.storePipeline(data);
- });
-
- it('toggles the isLoading property for the given pipeline', () => {
- store.togglePipeline(store.state.pipeline.triggered[0]);
-
- expect(store.state.pipeline.triggered[0].isLoading).toEqual(true);
- });
- });
-
- describe('addExpandedPipelineToRequestData', () => {
- it('pushes the given id to expandedPipelines array', () => {
- store.addExpandedPipelineToRequestData('213231');
-
- expect(store.state.expandedPipelines).toEqual(['213231']);
- });
- });
-
- describe('removeExpandedPipelineToRequestData', () => {
- it('pushes the given id to expandedPipelines array', () => {
- store.removeExpandedPipelineToRequestData('213231');
-
- expect(store.state.expandedPipelines).toEqual([]);
- });
- });
-});
diff --git a/spec/javascripts/pipelines/stores/pipeline_with_triggered.json b/spec/javascripts/pipelines/stores/pipeline_with_triggered.json
deleted file mode 100644
index 1fa15e45792..00000000000
--- a/spec/javascripts/pipelines/stores/pipeline_with_triggered.json
+++ /dev/null
@@ -1,381 +0,0 @@
-{
- "id": 23211253,
- "user": {
- "id": 3585,
- "name": "Achilleas Pipinellis",
- "username": "axil",
- "state": "active",
- "avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/3585/avatar.png",
- "web_url": "https://gitlab.com/axil",
- "status_tooltip_html": "\u003cspan class=\"user-status-emoji has-tooltip\" title=\"\" data-html=\"true\" data-placement=\"top\"\u003e\u003cgl-emoji title=\"trumpet\" data-name=\"trumpet\" data-unicode-version=\"6.0\"\u003e🎺\u003c/gl-emoji\u003e\u003c/span\u003e",
- "path": "/axil"
- },
- "active": false,
- "coverage": null,
- "source": "push",
- "created_at": "2018-06-05T11:31:30.452Z",
- "updated_at": "2018-10-31T16:35:31.305Z",
- "path": "/gitlab-org/gitlab-runner/pipelines/23211253",
- "flags": {
- "latest": false,
- "stuck": false,
- "auto_devops": false,
- "yaml_errors": false,
- "retryable": false,
- "cancelable": false,
- "failure_reason": false
- },
- "details": {
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/pipelines/23211253",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "duration": 53,
- "finished_at": "2018-10-31T16:35:31.299Z",
- "stages": [
- {
- "name": "prebuild",
- "title": "prebuild: passed",
- "groups": [
- {
- "name": "review-docs-deploy",
- "size": 1,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "manual play action",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469032",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469032/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- },
- "jobs": [
- {
- "id": 72469032,
- "name": "review-docs-deploy",
- "started": "2018-10-31T16:34:58.778Z",
- "archived": false,
- "build_path": "/gitlab-org/gitlab-runner/-/jobs/72469032",
- "retry_path": "/gitlab-org/gitlab-runner/-/jobs/72469032/retry",
- "play_path": "/gitlab-org/gitlab-runner/-/jobs/72469032/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2018-06-05T11:31:30.495Z",
- "updated_at": "2018-10-31T16:35:31.251Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "manual play action",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469032",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469032/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/pipelines/23211253#prebuild",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "path": "/gitlab-org/gitlab-runner/pipelines/23211253#prebuild",
- "dropdown_path": "/gitlab-org/gitlab-runner/pipelines/23211253/stage.json?stage=prebuild"
- },
- {
- "name": "test",
- "title": "test: passed",
- "groups": [
- {
- "name": "docs check links",
- "size": 1,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469033",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469033/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "jobs": [
- {
- "id": 72469033,
- "name": "docs check links",
- "started": "2018-06-05T11:31:33.240Z",
- "archived": false,
- "build_path": "/gitlab-org/gitlab-runner/-/jobs/72469033",
- "retry_path": "/gitlab-org/gitlab-runner/-/jobs/72469033/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2018-06-05T11:31:30.627Z",
- "updated_at": "2018-06-05T11:31:54.363Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469033",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469033/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/pipelines/23211253#test",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "path": "/gitlab-org/gitlab-runner/pipelines/23211253#test",
- "dropdown_path": "/gitlab-org/gitlab-runner/pipelines/23211253/stage.json?stage=test"
- },
- {
- "name": "cleanup",
- "title": "cleanup: skipped",
- "groups": [
- {
- "name": "review-docs-cleanup",
- "size": 1,
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual stop action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469034",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "stop",
- "title": "Stop",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469034/play",
- "method": "post",
- "button_title": "Stop this environment"
- }
- },
- "jobs": [
- {
- "id": 72469034,
- "name": "review-docs-cleanup",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-org/gitlab-runner/-/jobs/72469034",
- "play_path": "/gitlab-org/gitlab-runner/-/jobs/72469034/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2018-06-05T11:31:30.760Z",
- "updated_at": "2018-06-05T11:31:56.037Z",
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual stop action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469034",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "stop",
- "title": "Stop",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469034/play",
- "method": "post",
- "button_title": "Stop this environment"
- }
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/pipelines/23211253#cleanup",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "path": "/gitlab-org/gitlab-runner/pipelines/23211253#cleanup",
- "dropdown_path": "/gitlab-org/gitlab-runner/pipelines/23211253/stage.json?stage=cleanup"
- }
- ],
- "artifacts": [],
- "manual_actions": [
- {
- "name": "review-docs-cleanup",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469034/play",
- "playable": true,
- "scheduled": false
- },
- {
- "name": "review-docs-deploy",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469032/play",
- "playable": true,
- "scheduled": false
- }
- ],
- "scheduled_actions": []
- },
- "ref": {
- "name": "docs/add-development-guide-to-readme",
- "path": "/gitlab-org/gitlab-runner/commits/docs/add-development-guide-to-readme",
- "tag": false,
- "branch": true
- },
- "commit": {
- "id": "8083eb0a920572214d0dccedd7981f05d535ad46",
- "short_id": "8083eb0a",
- "title": "Add link to development guide in readme",
- "created_at": "2018-06-05T11:30:48.000Z",
- "parent_ids": ["1d7cf79b5a1a2121b9474ac20d61c1b8f621289d"],
- "message": "Add link to development guide in readme\n\nCloses https://gitlab.com/gitlab-org/gitlab-runner/issues/3122\n",
- "author_name": "Achilleas Pipinellis",
- "author_email": "axil@gitlab.com",
- "authored_date": "2018-06-05T11:30:48.000Z",
- "committer_name": "Achilleas Pipinellis",
- "committer_email": "axil@gitlab.com",
- "committed_date": "2018-06-05T11:30:48.000Z",
- "author": {
- "id": 3585,
- "name": "Achilleas Pipinellis",
- "username": "axil",
- "state": "active",
- "avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/3585/avatar.png",
- "web_url": "https://gitlab.com/axil",
- "status_tooltip_html": null,
- "path": "/axil"
- },
- "author_gravatar_url": "https://secure.gravatar.com/avatar/1d37af00eec153a8333a4ce18e9aea41?s=80\u0026d=identicon",
- "commit_url": "https://gitlab.com/gitlab-org/gitlab-runner/commit/8083eb0a920572214d0dccedd7981f05d535ad46",
- "commit_path": "/gitlab-org/gitlab-runner/commit/8083eb0a920572214d0dccedd7981f05d535ad46"
- },
- "triggered_by": null,
- "triggered": [
- {
- "id": 34993051,
- "user": {
- "id": 376774,
- "name": "Alessio Caiazza",
- "username": "nolith",
- "state": "active",
- "avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/376774/avatar.png",
- "web_url": "https://gitlab.com/nolith",
- "status_tooltip_html": null,
- "path": "/nolith"
- },
- "active": false,
- "coverage": null,
- "source": "pipeline",
- "path": "/gitlab-com/gitlab-docs/pipelines/34993051",
- "details": {
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/34993051",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png"
- }
- },
- "project": {
- "id": 1794617,
- "name": "GitLab Docs",
- "full_path": "/gitlab-com/gitlab-docs",
- "full_name": "GitLab.com / GitLab Docs"
- }
- }
- ]
-}
diff --git a/spec/javascripts/pipelines/stores/pipeline_with_triggered_by.json b/spec/javascripts/pipelines/stores/pipeline_with_triggered_by.json
deleted file mode 100644
index 7aeea6f3ebb..00000000000
--- a/spec/javascripts/pipelines/stores/pipeline_with_triggered_by.json
+++ /dev/null
@@ -1,379 +0,0 @@
-{
- "id": 23211253,
- "user": {
- "id": 3585,
- "name": "Achilleas Pipinellis",
- "username": "axil",
- "state": "active",
- "avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/3585/avatar.png",
- "web_url": "https://gitlab.com/axil",
- "status_tooltip_html": "\u003cspan class=\"user-status-emoji has-tooltip\" title=\"\" data-html=\"true\" data-placement=\"top\"\u003e\u003cgl-emoji title=\"trumpet\" data-name=\"trumpet\" data-unicode-version=\"6.0\"\u003e🎺\u003c/gl-emoji\u003e\u003c/span\u003e",
- "path": "/axil"
- },
- "active": false,
- "coverage": null,
- "source": "push",
- "created_at": "2018-06-05T11:31:30.452Z",
- "updated_at": "2018-10-31T16:35:31.305Z",
- "path": "/gitlab-org/gitlab-runner/pipelines/23211253",
- "flags": {
- "latest": false,
- "stuck": false,
- "auto_devops": false,
- "yaml_errors": false,
- "retryable": false,
- "cancelable": false,
- "failure_reason": false
- },
- "details": {
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/pipelines/23211253",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "duration": 53,
- "finished_at": "2018-10-31T16:35:31.299Z",
- "stages": [
- {
- "name": "prebuild",
- "title": "prebuild: passed",
- "groups": [
- {
- "name": "review-docs-deploy",
- "size": 1,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "manual play action",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469032",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469032/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- },
- "jobs": [
- {
- "id": 72469032,
- "name": "review-docs-deploy",
- "started": "2018-10-31T16:34:58.778Z",
- "archived": false,
- "build_path": "/gitlab-org/gitlab-runner/-/jobs/72469032",
- "retry_path": "/gitlab-org/gitlab-runner/-/jobs/72469032/retry",
- "play_path": "/gitlab-org/gitlab-runner/-/jobs/72469032/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2018-06-05T11:31:30.495Z",
- "updated_at": "2018-10-31T16:35:31.251Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "manual play action",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469032",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469032/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/pipelines/23211253#prebuild",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "path": "/gitlab-org/gitlab-runner/pipelines/23211253#prebuild",
- "dropdown_path": "/gitlab-org/gitlab-runner/pipelines/23211253/stage.json?stage=prebuild"
- },
- {
- "name": "test",
- "title": "test: passed",
- "groups": [
- {
- "name": "docs check links",
- "size": 1,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469033",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469033/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "jobs": [
- {
- "id": 72469033,
- "name": "docs check links",
- "started": "2018-06-05T11:31:33.240Z",
- "archived": false,
- "build_path": "/gitlab-org/gitlab-runner/-/jobs/72469033",
- "retry_path": "/gitlab-org/gitlab-runner/-/jobs/72469033/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2018-06-05T11:31:30.627Z",
- "updated_at": "2018-06-05T11:31:54.363Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469033",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469033/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/pipelines/23211253#test",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "path": "/gitlab-org/gitlab-runner/pipelines/23211253#test",
- "dropdown_path": "/gitlab-org/gitlab-runner/pipelines/23211253/stage.json?stage=test"
- },
- {
- "name": "cleanup",
- "title": "cleanup: skipped",
- "groups": [
- {
- "name": "review-docs-cleanup",
- "size": 1,
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual stop action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469034",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "stop",
- "title": "Stop",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469034/play",
- "method": "post",
- "button_title": "Stop this environment"
- }
- },
- "jobs": [
- {
- "id": 72469034,
- "name": "review-docs-cleanup",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-org/gitlab-runner/-/jobs/72469034",
- "play_path": "/gitlab-org/gitlab-runner/-/jobs/72469034/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2018-06-05T11:31:30.760Z",
- "updated_at": "2018-06-05T11:31:56.037Z",
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual stop action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469034",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "stop",
- "title": "Stop",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469034/play",
- "method": "post",
- "button_title": "Stop this environment"
- }
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/pipelines/23211253#cleanup",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "path": "/gitlab-org/gitlab-runner/pipelines/23211253#cleanup",
- "dropdown_path": "/gitlab-org/gitlab-runner/pipelines/23211253/stage.json?stage=cleanup"
- }
- ],
- "artifacts": [],
- "manual_actions": [
- {
- "name": "review-docs-cleanup",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469034/play",
- "playable": true,
- "scheduled": false
- },
- {
- "name": "review-docs-deploy",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469032/play",
- "playable": true,
- "scheduled": false
- }
- ],
- "scheduled_actions": []
- },
- "ref": {
- "name": "docs/add-development-guide-to-readme",
- "path": "/gitlab-org/gitlab-runner/commits/docs/add-development-guide-to-readme",
- "tag": false,
- "branch": true
- },
- "commit": {
- "id": "8083eb0a920572214d0dccedd7981f05d535ad46",
- "short_id": "8083eb0a",
- "title": "Add link to development guide in readme",
- "created_at": "2018-06-05T11:30:48.000Z",
- "parent_ids": ["1d7cf79b5a1a2121b9474ac20d61c1b8f621289d"],
- "message": "Add link to development guide in readme\n\nCloses https://gitlab.com/gitlab-org/gitlab-runner/issues/3122\n",
- "author_name": "Achilleas Pipinellis",
- "author_email": "axil@gitlab.com",
- "authored_date": "2018-06-05T11:30:48.000Z",
- "committer_name": "Achilleas Pipinellis",
- "committer_email": "axil@gitlab.com",
- "committed_date": "2018-06-05T11:30:48.000Z",
- "author": {
- "id": 3585,
- "name": "Achilleas Pipinellis",
- "username": "axil",
- "state": "active",
- "avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/3585/avatar.png",
- "web_url": "https://gitlab.com/axil",
- "status_tooltip_html": null,
- "path": "/axil"
- },
- "author_gravatar_url": "https://secure.gravatar.com/avatar/1d37af00eec153a8333a4ce18e9aea41?s=80\u0026d=identicon",
- "commit_url": "https://gitlab.com/gitlab-org/gitlab-runner/commit/8083eb0a920572214d0dccedd7981f05d535ad46",
- "commit_path": "/gitlab-org/gitlab-runner/commit/8083eb0a920572214d0dccedd7981f05d535ad46"
- },
- "triggered_by": {
- "id": 34993051,
- "user": {
- "id": 376774,
- "name": "Alessio Caiazza",
- "username": "nolith",
- "state": "active",
- "avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/376774/avatar.png",
- "web_url": "https://gitlab.com/nolith",
- "status_tooltip_html": null,
- "path": "/nolith"
- },
- "active": false,
- "coverage": null,
- "source": "pipeline",
- "path": "/gitlab-com/gitlab-docs/pipelines/34993051",
- "details": {
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/34993051",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png"
- }
- },
- "project": {
- "id": 1794617,
- "name": "GitLab Docs",
- "full_path": "/gitlab-com/gitlab-docs",
- "full_name": "GitLab.com / GitLab Docs"
- }
- },
- "triggered": []
-}
diff --git a/spec/javascripts/pipelines/stores/pipeline_with_triggered_triggered_by.json b/spec/javascripts/pipelines/stores/pipeline_with_triggered_triggered_by.json
deleted file mode 100644
index 2402cbae6c8..00000000000
--- a/spec/javascripts/pipelines/stores/pipeline_with_triggered_triggered_by.json
+++ /dev/null
@@ -1,452 +0,0 @@
-{
- "id": 23211253,
- "user": {
- "id": 3585,
- "name": "Achilleas Pipinellis",
- "username": "axil",
- "state": "active",
- "avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/3585/avatar.png",
- "web_url": "https://gitlab.com/axil",
- "status_tooltip_html": "\u003cspan class=\"user-status-emoji has-tooltip\" title=\"\" data-html=\"true\" data-placement=\"top\"\u003e\u003cgl-emoji title=\"trumpet\" data-name=\"trumpet\" data-unicode-version=\"6.0\"\u003e🎺\u003c/gl-emoji\u003e\u003c/span\u003e",
- "path": "/axil"
- },
- "active": false,
- "coverage": null,
- "source": "push",
- "created_at": "2018-06-05T11:31:30.452Z",
- "updated_at": "2018-10-31T16:35:31.305Z",
- "path": "/gitlab-org/gitlab-runner/pipelines/23211253",
- "flags": {
- "latest": false,
- "stuck": false,
- "auto_devops": false,
- "yaml_errors": false,
- "retryable": false,
- "cancelable": false,
- "failure_reason": false
- },
- "details": {
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/pipelines/23211253",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "duration": 53,
- "finished_at": "2018-10-31T16:35:31.299Z",
- "stages": [
- {
- "name": "prebuild",
- "title": "prebuild: passed",
- "groups": [
- {
- "name": "review-docs-deploy",
- "size": 1,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "manual play action",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469032",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469032/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- },
- "jobs": [
- {
- "id": 72469032,
- "name": "review-docs-deploy",
- "started": "2018-10-31T16:34:58.778Z",
- "archived": false,
- "build_path": "/gitlab-org/gitlab-runner/-/jobs/72469032",
- "retry_path": "/gitlab-org/gitlab-runner/-/jobs/72469032/retry",
- "play_path": "/gitlab-org/gitlab-runner/-/jobs/72469032/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2018-06-05T11:31:30.495Z",
- "updated_at": "2018-10-31T16:35:31.251Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "manual play action",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469032",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "play",
- "title": "Play",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469032/play",
- "method": "post",
- "button_title": "Trigger this manual action"
- }
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/pipelines/23211253#prebuild",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "path": "/gitlab-org/gitlab-runner/pipelines/23211253#prebuild",
- "dropdown_path": "/gitlab-org/gitlab-runner/pipelines/23211253/stage.json?stage=prebuild"
- },
- {
- "name": "test",
- "title": "test: passed",
- "groups": [
- {
- "name": "docs check links",
- "size": 1,
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469033",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469033/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- },
- "jobs": [
- {
- "id": 72469033,
- "name": "docs check links",
- "started": "2018-06-05T11:31:33.240Z",
- "archived": false,
- "build_path": "/gitlab-org/gitlab-runner/-/jobs/72469033",
- "retry_path": "/gitlab-org/gitlab-runner/-/jobs/72469033/retry",
- "playable": false,
- "scheduled": false,
- "created_at": "2018-06-05T11:31:30.627Z",
- "updated_at": "2018-06-05T11:31:54.363Z",
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469033",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/skipped-job_empty-8b877955fbf175e42ae65b6cb95346e15282c6fc5b682756c329af3a0055225e.svg",
- "size": "svg-430",
- "title": "This job does not have a trace."
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png",
- "action": {
- "icon": "retry",
- "title": "Retry",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469033/retry",
- "method": "post",
- "button_title": "Retry this job"
- }
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_success",
- "text": "passed",
- "label": "passed",
- "group": "success",
- "tooltip": "passed",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/pipelines/23211253#test",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
- },
- "path": "/gitlab-org/gitlab-runner/pipelines/23211253#test",
- "dropdown_path": "/gitlab-org/gitlab-runner/pipelines/23211253/stage.json?stage=test"
- },
- {
- "name": "cleanup",
- "title": "cleanup: skipped",
- "groups": [
- {
- "name": "review-docs-cleanup",
- "size": 1,
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual stop action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469034",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "stop",
- "title": "Stop",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469034/play",
- "method": "post",
- "button_title": "Stop this environment"
- }
- },
- "jobs": [
- {
- "id": 72469034,
- "name": "review-docs-cleanup",
- "started": null,
- "archived": false,
- "build_path": "/gitlab-org/gitlab-runner/-/jobs/72469034",
- "play_path": "/gitlab-org/gitlab-runner/-/jobs/72469034/play",
- "playable": true,
- "scheduled": false,
- "created_at": "2018-06-05T11:31:30.760Z",
- "updated_at": "2018-06-05T11:31:56.037Z",
- "status": {
- "icon": "status_manual",
- "text": "manual",
- "label": "manual stop action",
- "group": "manual",
- "tooltip": "manual action",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/-/jobs/72469034",
- "illustration": {
- "image": "https://assets.gitlab-static.net/assets/illustrations/manual_action-2b4ca0d1bcfd92aebf33d484e36cbf7a102d007f76b5a0cfea636033a629d601.svg",
- "size": "svg-394",
- "title": "This job requires a manual action",
- "content": "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
- },
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png",
- "action": {
- "icon": "stop",
- "title": "Stop",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469034/play",
- "method": "post",
- "button_title": "Stop this environment"
- }
- }
- }
- ]
- }
- ],
- "status": {
- "icon": "status_skipped",
- "text": "skipped",
- "label": "skipped",
- "group": "skipped",
- "tooltip": "skipped",
- "has_details": true,
- "details_path": "/gitlab-org/gitlab-runner/pipelines/23211253#cleanup",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_skipped-0b9c5e543588945e8c4ca57786bbf2d0c56631959c9f853300392d0315be829b.png"
- },
- "path": "/gitlab-org/gitlab-runner/pipelines/23211253#cleanup",
- "dropdown_path": "/gitlab-org/gitlab-runner/pipelines/23211253/stage.json?stage=cleanup"
- }
- ],
- "artifacts": [],
- "manual_actions": [
- {
- "name": "review-docs-cleanup",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469034/play",
- "playable": true,
- "scheduled": false
- },
- {
- "name": "review-docs-deploy",
- "path": "/gitlab-org/gitlab-runner/-/jobs/72469032/play",
- "playable": true,
- "scheduled": false
- }
- ],
- "scheduled_actions": []
- },
- "ref": {
- "name": "docs/add-development-guide-to-readme",
- "path": "/gitlab-org/gitlab-runner/commits/docs/add-development-guide-to-readme",
- "tag": false,
- "branch": true
- },
- "commit": {
- "id": "8083eb0a920572214d0dccedd7981f05d535ad46",
- "short_id": "8083eb0a",
- "title": "Add link to development guide in readme",
- "created_at": "2018-06-05T11:30:48.000Z",
- "parent_ids": ["1d7cf79b5a1a2121b9474ac20d61c1b8f621289d"],
- "message": "Add link to development guide in readme\n\nCloses https://gitlab.com/gitlab-org/gitlab-runner/issues/3122\n",
- "author_name": "Achilleas Pipinellis",
- "author_email": "axil@gitlab.com",
- "authored_date": "2018-06-05T11:30:48.000Z",
- "committer_name": "Achilleas Pipinellis",
- "committer_email": "axil@gitlab.com",
- "committed_date": "2018-06-05T11:30:48.000Z",
- "author": {
- "id": 3585,
- "name": "Achilleas Pipinellis",
- "username": "axil",
- "state": "active",
- "avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/3585/avatar.png",
- "web_url": "https://gitlab.com/axil",
- "status_tooltip_html": null,
- "path": "/axil"
- },
- "author_gravatar_url": "https://secure.gravatar.com/avatar/1d37af00eec153a8333a4ce18e9aea41?s=80\u0026d=identicon",
- "commit_url": "https://gitlab.com/gitlab-org/gitlab-runner/commit/8083eb0a920572214d0dccedd7981f05d535ad46",
- "commit_path": "/gitlab-org/gitlab-runner/commit/8083eb0a920572214d0dccedd7981f05d535ad46"
- },
- "triggered_by": {
- "id": 34993051,
- "user": {
- "id": 376774,
- "name": "Alessio Caiazza",
- "username": "nolith",
- "state": "active",
- "avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/376774/avatar.png",
- "web_url": "https://gitlab.com/nolith",
- "status_tooltip_html": null,
- "path": "/nolith"
- },
- "active": false,
- "coverage": null,
- "source": "pipeline",
- "path": "/gitlab-com/gitlab-docs/pipelines/34993051",
- "details": {
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/34993051",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png"
- }
- },
- "project": {
- "id": 1794617,
- "name": "GitLab Docs",
- "full_path": "/gitlab-com/gitlab-docs",
- "full_name": "GitLab.com / GitLab Docs"
- }
- },
- "triggered": [
- {
- "id": 349233051,
- "user": {
- "id": 376774,
- "name": "Alessio Caiazza",
- "username": "nolith",
- "state": "active",
- "avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/376774/avatar.png",
- "web_url": "https://gitlab.com/nolith",
- "status_tooltip_html": null,
- "path": "/nolith"
- },
- "active": false,
- "coverage": null,
- "source": "pipeline",
- "path": "/gitlab-com/gitlab-docs/pipelines/34993051",
- "details": {
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/349233051",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png"
- }
- },
- "project": {
- "id": 1794617,
- "name": "GitLab Docs",
- "full_path": "/gitlab-com/gitlab-docs",
- "full_name": "GitLab.com / GitLab Docs"
- }
- },
- {
- "id": 34993023,
- "user": {
- "id": 376774,
- "name": "Alessio Caiazza",
- "username": "nolith",
- "state": "active",
- "avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/376774/avatar.png",
- "web_url": "https://gitlab.com/nolith",
- "status_tooltip_html": null,
- "path": "/nolith"
- },
- "active": false,
- "coverage": null,
- "source": "pipeline",
- "path": "/gitlab-com/gitlab-docs/pipelines/34993023",
- "details": {
- "status": {
- "icon": "status_failed",
- "text": "failed",
- "label": "failed",
- "group": "failed",
- "tooltip": "failed",
- "has_details": true,
- "details_path": "/gitlab-com/gitlab-docs/pipelines/34993051",
- "illustration": null,
- "favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png"
- }
- },
- "project": {
- "id": 1794617,
- "name": "GitLab Docs",
- "full_path": "/gitlab-com/gitlab-docs",
- "full_name": "GitLab.com / GitLab Docs"
- }
- }
- ]
-}
diff --git a/spec/javascripts/pipelines/time_ago_spec.js b/spec/javascripts/pipelines/time_ago_spec.js
deleted file mode 100644
index 42b34c82f89..00000000000
--- a/spec/javascripts/pipelines/time_ago_spec.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import Vue from 'vue';
-import timeAgo from '~/pipelines/components/time_ago.vue';
-
-describe('Timeago component', () => {
- let TimeAgo;
- beforeEach(() => {
- TimeAgo = Vue.extend(timeAgo);
- });
-
- describe('with duration', () => {
- it('should render duration and timer svg', () => {
- const component = new TimeAgo({
- propsData: {
- duration: 10,
- finishedTime: '',
- },
- }).$mount();
-
- expect(component.$el.querySelector('.duration')).toBeDefined();
- expect(component.$el.querySelector('.duration svg')).toBeDefined();
- });
- });
-
- describe('without duration', () => {
- it('should not render duration and timer svg', () => {
- const component = new TimeAgo({
- propsData: {
- duration: 0,
- finishedTime: '',
- },
- }).$mount();
-
- expect(component.$el.querySelector('.duration')).toBe(null);
- });
- });
-
- describe('with finishedTime', () => {
- it('should render time and calendar icon', () => {
- const component = new TimeAgo({
- propsData: {
- duration: 0,
- finishedTime: '2017-04-26T12:40:23.277Z',
- },
- }).$mount();
-
- expect(component.$el.querySelector('.finished-at')).toBeDefined();
- expect(component.$el.querySelector('.finished-at i.fa-calendar')).toBeDefined();
- expect(component.$el.querySelector('.finished-at time')).toBeDefined();
- });
- });
-
- describe('without finishedTime', () => {
- it('should not render time and calendar icon', () => {
- const component = new TimeAgo({
- propsData: {
- duration: 0,
- finishedTime: '',
- },
- }).$mount();
-
- expect(component.$el.querySelector('.finished-at')).toBe(null);
- });
- });
-});
diff --git a/spec/javascripts/pipelines_spec.js b/spec/javascripts/pipelines_spec.js
deleted file mode 100644
index 6d4d634c575..00000000000
--- a/spec/javascripts/pipelines_spec.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import Pipelines from '~/pipelines';
-
-describe('Pipelines', () => {
- preloadFixtures('static/pipeline_graph.html');
-
- beforeEach(() => {
- loadFixtures('static/pipeline_graph.html');
- });
-
- it('should be defined', () => {
- expect(Pipelines).toBeDefined();
- });
-
- it('should create a `Pipelines` instance without options', () => {
- expect(() => {
- new Pipelines(); // eslint-disable-line no-new
- }).not.toThrow();
- });
-});
diff --git a/spec/javascripts/prometheus_metrics/mock_data.js b/spec/javascripts/prometheus_metrics/mock_data.js
deleted file mode 100644
index 3af56df92e2..00000000000
--- a/spec/javascripts/prometheus_metrics/mock_data.js
+++ /dev/null
@@ -1,41 +0,0 @@
-export const metrics = [
- {
- group: 'Kubernetes',
- priority: 1,
- active_metrics: 4,
- metrics_missing_requirements: 0,
- },
- {
- group: 'HAProxy',
- priority: 2,
- active_metrics: 3,
- metrics_missing_requirements: 0,
- },
- {
- group: 'Apache',
- priority: 3,
- active_metrics: 5,
- metrics_missing_requirements: 0,
- },
-];
-
-export const missingVarMetrics = [
- {
- group: 'Kubernetes',
- priority: 1,
- active_metrics: 4,
- metrics_missing_requirements: 0,
- },
- {
- group: 'HAProxy',
- priority: 2,
- active_metrics: 3,
- metrics_missing_requirements: 1,
- },
- {
- group: 'Apache',
- priority: 3,
- active_metrics: 5,
- metrics_missing_requirements: 3,
- },
-];
diff --git a/spec/javascripts/prometheus_metrics/prometheus_metrics_spec.js b/spec/javascripts/prometheus_metrics/prometheus_metrics_spec.js
deleted file mode 100644
index dca3e1553b9..00000000000
--- a/spec/javascripts/prometheus_metrics/prometheus_metrics_spec.js
+++ /dev/null
@@ -1,178 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import PrometheusMetrics from '~/prometheus_metrics/prometheus_metrics';
-import PANEL_STATE from '~/prometheus_metrics/constants';
-import { metrics, missingVarMetrics } from './mock_data';
-
-describe('PrometheusMetrics', () => {
- const FIXTURE = 'services/prometheus/prometheus_service.html';
- preloadFixtures(FIXTURE);
-
- beforeEach(() => {
- loadFixtures(FIXTURE);
- });
-
- describe('constructor', () => {
- let prometheusMetrics;
-
- beforeEach(() => {
- prometheusMetrics = new PrometheusMetrics('.js-prometheus-metrics-monitoring');
- });
-
- it('should initialize wrapper element refs on class object', () => {
- expect(prometheusMetrics.$wrapper).toBeDefined();
- expect(prometheusMetrics.$monitoredMetricsPanel).toBeDefined();
- expect(prometheusMetrics.$monitoredMetricsCount).toBeDefined();
- expect(prometheusMetrics.$monitoredMetricsLoading).toBeDefined();
- expect(prometheusMetrics.$monitoredMetricsEmpty).toBeDefined();
- expect(prometheusMetrics.$monitoredMetricsList).toBeDefined();
- expect(prometheusMetrics.$missingEnvVarPanel).toBeDefined();
- expect(prometheusMetrics.$panelToggle).toBeDefined();
- expect(prometheusMetrics.$missingEnvVarMetricCount).toBeDefined();
- expect(prometheusMetrics.$missingEnvVarMetricsList).toBeDefined();
- });
-
- it('should initialize metadata on class object', () => {
- expect(prometheusMetrics.backOffRequestCounter).toEqual(0);
- expect(prometheusMetrics.activeMetricsEndpoint).toContain('/test');
- });
- });
-
- describe('showMonitoringMetricsPanelState', () => {
- let prometheusMetrics;
-
- beforeEach(() => {
- prometheusMetrics = new PrometheusMetrics('.js-prometheus-metrics-monitoring');
- });
-
- it('should show loading state when called with `loading`', () => {
- prometheusMetrics.showMonitoringMetricsPanelState(PANEL_STATE.LOADING);
-
- expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeFalsy();
- expect(prometheusMetrics.$monitoredMetricsEmpty.hasClass('hidden')).toBeTruthy();
- expect(prometheusMetrics.$monitoredMetricsList.hasClass('hidden')).toBeTruthy();
- });
-
- it('should show metrics list when called with `list`', () => {
- prometheusMetrics.showMonitoringMetricsPanelState(PANEL_STATE.LIST);
-
- expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeTruthy();
- expect(prometheusMetrics.$monitoredMetricsEmpty.hasClass('hidden')).toBeTruthy();
- expect(prometheusMetrics.$monitoredMetricsList.hasClass('hidden')).toBeFalsy();
- });
-
- it('should show empty state when called with `empty`', () => {
- prometheusMetrics.showMonitoringMetricsPanelState(PANEL_STATE.EMPTY);
-
- expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeTruthy();
- expect(prometheusMetrics.$monitoredMetricsEmpty.hasClass('hidden')).toBeFalsy();
- expect(prometheusMetrics.$monitoredMetricsList.hasClass('hidden')).toBeTruthy();
- });
- });
-
- describe('populateActiveMetrics', () => {
- let prometheusMetrics;
-
- beforeEach(() => {
- prometheusMetrics = new PrometheusMetrics('.js-prometheus-metrics-monitoring');
- });
-
- it('should show monitored metrics list', () => {
- prometheusMetrics.populateActiveMetrics(metrics);
-
- const $metricsListLi = prometheusMetrics.$monitoredMetricsList.find('li');
-
- expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeTruthy();
- expect(prometheusMetrics.$monitoredMetricsList.hasClass('hidden')).toBeFalsy();
-
- expect(prometheusMetrics.$monitoredMetricsCount.text()).toEqual(
- '3 exporters with 12 metrics were found',
- );
-
- expect($metricsListLi.length).toEqual(metrics.length);
- expect(
- $metricsListLi
- .first()
- .find('.badge')
- .text(),
- ).toEqual(`${metrics[0].active_metrics}`);
- });
-
- it('should show missing environment variables list', () => {
- prometheusMetrics.populateActiveMetrics(missingVarMetrics);
-
- expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeTruthy();
- expect(prometheusMetrics.$missingEnvVarPanel.hasClass('hidden')).toBeFalsy();
-
- expect(prometheusMetrics.$missingEnvVarMetricCount.text()).toEqual('2');
- expect(prometheusMetrics.$missingEnvVarPanel.find('li').length).toEqual(2);
- expect(prometheusMetrics.$missingEnvVarPanel.find('.flash-container')).toBeDefined();
- });
- });
-
- describe('loadActiveMetrics', () => {
- let prometheusMetrics;
- let mock;
-
- function mockSuccess() {
- mock.onGet(prometheusMetrics.activeMetricsEndpoint).reply(200, {
- data: metrics,
- success: true,
- });
- }
-
- function mockError() {
- mock.onGet(prometheusMetrics.activeMetricsEndpoint).networkError();
- }
-
- beforeEach(() => {
- spyOn(axios, 'get').and.callThrough();
-
- prometheusMetrics = new PrometheusMetrics('.js-prometheus-metrics-monitoring');
-
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('should show loader animation while response is being loaded and hide it when request is complete', done => {
- mockSuccess();
-
- prometheusMetrics.loadActiveMetrics();
-
- expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeFalsy();
- expect(axios.get).toHaveBeenCalledWith(prometheusMetrics.activeMetricsEndpoint);
-
- setTimeout(() => {
- expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeTruthy();
- done();
- });
- });
-
- it('should show empty state if response failed to load', done => {
- mockError();
-
- prometheusMetrics.loadActiveMetrics();
-
- setTimeout(() => {
- expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeTruthy();
- expect(prometheusMetrics.$monitoredMetricsEmpty.hasClass('hidden')).toBeFalsy();
- done();
- });
- });
-
- it('should populate metrics list once response is loaded', done => {
- spyOn(prometheusMetrics, 'populateActiveMetrics');
- mockSuccess();
-
- prometheusMetrics.loadActiveMetrics();
-
- setTimeout(() => {
- expect(prometheusMetrics.populateActiveMetrics).toHaveBeenCalledWith(metrics);
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/related_merge_requests/components/related_merge_requests_spec.js b/spec/javascripts/related_merge_requests/components/related_merge_requests_spec.js
deleted file mode 100644
index d8bdf69dfee..00000000000
--- a/spec/javascripts/related_merge_requests/components/related_merge_requests_spec.js
+++ /dev/null
@@ -1,88 +0,0 @@
-import { mount, createLocalVue } from '@vue/test-utils';
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue';
-import RelatedMergeRequests from '~/related_merge_requests/components/related_merge_requests.vue';
-import createStore from '~/related_merge_requests/store/index';
-
-const FIXTURE_PATH = 'issues/related_merge_requests.json';
-const API_ENDPOINT = '/api/v4/projects/2/issues/33/related_merge_requests';
-const localVue = createLocalVue();
-
-describe('RelatedMergeRequests', () => {
- let wrapper;
- let mock;
- let mockData;
-
- beforeEach(done => {
- loadFixtures(FIXTURE_PATH);
- mockData = getJSONFixture(FIXTURE_PATH);
- mock = new MockAdapter(axios);
- mock.onGet(`${API_ENDPOINT}?per_page=100`).reply(200, mockData, { 'x-total': 2 });
-
- wrapper = mount(localVue.extend(RelatedMergeRequests), {
- localVue,
- store: createStore(),
- propsData: {
- endpoint: API_ENDPOINT,
- projectNamespace: 'gitlab-org',
- projectPath: 'gitlab-ce',
- },
- });
-
- setTimeout(done);
- });
-
- afterEach(() => {
- wrapper.destroy();
- mock.restore();
- });
-
- describe('methods', () => {
- describe('getAssignees', () => {
- const assignees = [{ name: 'foo' }, { name: 'bar' }];
-
- describe('when there is assignees array', () => {
- it('should return assignees array', () => {
- const mr = { assignees };
-
- expect(wrapper.vm.getAssignees(mr)).toEqual(assignees);
- });
- });
-
- it('should return an array with single assingee', () => {
- const mr = { assignee: assignees[0] };
-
- expect(wrapper.vm.getAssignees(mr)).toEqual([assignees[0]]);
- });
-
- it('should return empty array when assignee is not set', () => {
- expect(wrapper.vm.getAssignees({})).toEqual([]);
- expect(wrapper.vm.getAssignees({ assignee: null })).toEqual([]);
- });
- });
- });
-
- describe('template', () => {
- it('should render related merge request items', () => {
- expect(wrapper.find('.js-items-count').text()).toEqual('2');
- expect(wrapper.findAll(RelatedIssuableItem).length).toEqual(2);
-
- const props = wrapper
- .findAll(RelatedIssuableItem)
- .at(1)
- .props();
- const data = mockData[1];
-
- expect(props.idKey).toEqual(data.id);
- expect(props.pathIdSeparator).toEqual('!');
- expect(props.pipelineStatus).toBe(data.head_pipeline.detailed_status);
- expect(props.assignees).toEqual([data.assignee]);
- expect(props.isMergeRequest).toBe(true);
- expect(props.confidential).toEqual(false);
- expect(props.title).toEqual(data.title);
- expect(props.state).toEqual(data.state);
- expect(props.createdAt).toEqual(data.created_at);
- });
- });
-});
diff --git a/spec/javascripts/related_merge_requests/store/actions_spec.js b/spec/javascripts/related_merge_requests/store/actions_spec.js
deleted file mode 100644
index c4cd9f5f803..00000000000
--- a/spec/javascripts/related_merge_requests/store/actions_spec.js
+++ /dev/null
@@ -1,110 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import testAction from 'spec/helpers/vuex_action_helper';
-import axios from '~/lib/utils/axios_utils';
-import * as types from '~/related_merge_requests/store/mutation_types';
-import actionsModule, * as actions from '~/related_merge_requests/store/actions';
-
-describe('RelatedMergeRequest store actions', () => {
- let state;
- let flashSpy;
- let mock;
-
- beforeEach(() => {
- state = {
- apiEndpoint: '/api/related_merge_requests',
- };
- flashSpy = spyOnDependency(actionsModule, 'createFlash');
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- describe('setInitialState', () => {
- it('commits types.SET_INITIAL_STATE with given props', done => {
- const props = { a: 1, b: 2 };
-
- testAction(
- actions.setInitialState,
- props,
- {},
- [{ type: types.SET_INITIAL_STATE, payload: props }],
- [],
- done,
- );
- });
- });
-
- describe('requestData', () => {
- it('commits types.REQUEST_DATA', done => {
- testAction(actions.requestData, null, {}, [{ type: types.REQUEST_DATA }], [], done);
- });
- });
-
- describe('receiveDataSuccess', () => {
- it('commits types.RECEIVE_DATA_SUCCESS with data', done => {
- const data = { a: 1, b: 2 };
-
- testAction(
- actions.receiveDataSuccess,
- data,
- {},
- [{ type: types.RECEIVE_DATA_SUCCESS, payload: data }],
- [],
- done,
- );
- });
- });
-
- describe('receiveDataError', () => {
- it('commits types.RECEIVE_DATA_ERROR', done => {
- testAction(
- actions.receiveDataError,
- null,
- {},
- [{ type: types.RECEIVE_DATA_ERROR }],
- [],
- done,
- );
- });
- });
-
- describe('fetchMergeRequests', () => {
- describe('for a successful request', () => {
- it('should dispatch success action', done => {
- const data = { a: 1 };
- mock.onGet(`${state.apiEndpoint}?per_page=100`).replyOnce(200, data, { 'x-total': 2 });
-
- testAction(
- actions.fetchMergeRequests,
- null,
- state,
- [],
- [{ type: 'requestData' }, { type: 'receiveDataSuccess', payload: { data, total: 2 } }],
- done,
- );
- });
- });
-
- describe('for a failing request', () => {
- it('should dispatch error action', done => {
- mock.onGet(`${state.apiEndpoint}?per_page=100`).replyOnce(400);
-
- testAction(
- actions.fetchMergeRequests,
- null,
- state,
- [],
- [{ type: 'requestData' }, { type: 'receiveDataError' }],
- () => {
- expect(flashSpy).toHaveBeenCalledTimes(1);
- expect(flashSpy).toHaveBeenCalledWith(jasmine.stringMatching('Something went wrong'));
-
- done();
- },
- );
- });
- });
- });
-});
diff --git a/spec/javascripts/related_merge_requests/store/mutations_spec.js b/spec/javascripts/related_merge_requests/store/mutations_spec.js
deleted file mode 100644
index 21b6e26376b..00000000000
--- a/spec/javascripts/related_merge_requests/store/mutations_spec.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import mutations from '~/related_merge_requests/store/mutations';
-import * as types from '~/related_merge_requests/store/mutation_types';
-
-describe('RelatedMergeRequests Store Mutations', () => {
- describe('SET_INITIAL_STATE', () => {
- it('should set initial state according to given data', () => {
- const apiEndpoint = '/api';
- const state = {};
-
- mutations[types.SET_INITIAL_STATE](state, { apiEndpoint });
-
- expect(state.apiEndpoint).toEqual(apiEndpoint);
- });
- });
-
- describe('REQUEST_DATA', () => {
- it('should set loading flag', () => {
- const state = {};
-
- mutations[types.REQUEST_DATA](state);
-
- expect(state.isFetchingMergeRequests).toEqual(true);
- });
- });
-
- describe('RECEIVE_DATA_SUCCESS', () => {
- it('should set loading flag and data', () => {
- const state = {};
- const mrs = [1, 2, 3];
-
- mutations[types.RECEIVE_DATA_SUCCESS](state, { data: mrs, total: mrs.length });
-
- expect(state.isFetchingMergeRequests).toEqual(false);
- expect(state.mergeRequests).toEqual(mrs);
- expect(state.totalCount).toEqual(mrs.length);
- });
- });
-
- describe('RECEIVE_DATA_ERROR', () => {
- it('should set loading and error flags', () => {
- const state = {};
-
- mutations[types.RECEIVE_DATA_ERROR](state);
-
- expect(state.isFetchingMergeRequests).toEqual(false);
- expect(state.hasErrorFetchingMergeRequests).toEqual(true);
- });
- });
-});
diff --git a/spec/javascripts/reports/components/grouped_test_reports_app_spec.js b/spec/javascripts/reports/components/grouped_test_reports_app_spec.js
deleted file mode 100644
index bafc47c952a..00000000000
--- a/spec/javascripts/reports/components/grouped_test_reports_app_spec.js
+++ /dev/null
@@ -1,239 +0,0 @@
-import Vue from 'vue';
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import state from '~/reports/store/state';
-import component from '~/reports/components/grouped_test_reports_app.vue';
-import mountComponent from '../../helpers/vue_mount_component_helper';
-import newFailedTestReports from '../mock_data/new_failures_report.json';
-import newErrorsTestReports from '../mock_data/new_errors_report.json';
-import successTestReports from '../mock_data/no_failures_report.json';
-import mixedResultsTestReports from '../mock_data/new_and_fixed_failures_report.json';
-import resolvedFailures from '../mock_data/resolved_failures.json';
-
-describe('Grouped Test Reports App', () => {
- let vm;
- let mock;
- const Component = Vue.extend(component);
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- vm.$store.replaceState(state());
- vm.$destroy();
- mock.restore();
- });
-
- describe('with success result', () => {
- beforeEach(() => {
- mock.onGet('test_results.json').reply(200, successTestReports, {});
- vm = mountComponent(Component, {
- endpoint: 'test_results.json',
- });
- });
-
- it('renders success summary text', done => {
- setTimeout(() => {
- expect(vm.$el.querySelector('.gl-spinner')).toBeNull();
- expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual(
- 'Test summary contained no changed test results out of 11 total tests',
- );
-
- expect(vm.$el.textContent).toContain(
- 'rspec:pg found no changed test results out of 8 total tests',
- );
-
- expect(vm.$el.textContent).toContain(
- 'java ant found no changed test results out of 3 total tests',
- );
- done();
- }, 0);
- });
- });
-
- describe('with 204 result', () => {
- beforeEach(() => {
- mock.onGet('test_results.json').reply(204, {}, {});
- vm = mountComponent(Component, {
- endpoint: 'test_results.json',
- });
- });
-
- it('renders success summary text', done => {
- setTimeout(() => {
- expect(vm.$el.querySelector('.gl-spinner')).not.toBeNull();
- expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual(
- 'Test summary results are being parsed',
- );
-
- done();
- }, 0);
- });
- });
-
- describe('with new failed result', () => {
- beforeEach(() => {
- mock.onGet('test_results.json').reply(200, newFailedTestReports, {});
- vm = mountComponent(Component, {
- endpoint: 'test_results.json',
- });
- });
-
- it('renders failed summary text + new badge', done => {
- setTimeout(() => {
- expect(vm.$el.querySelector('.gl-spinner')).toBeNull();
- expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual(
- 'Test summary contained 2 failed out of 11 total tests',
- );
-
- expect(vm.$el.textContent).toContain('rspec:pg found 2 failed out of 8 total tests');
-
- expect(vm.$el.textContent).toContain('New');
- expect(vm.$el.textContent).toContain(
- 'java ant found no changed test results out of 3 total tests',
- );
- done();
- }, 0);
- });
- });
-
- describe('with new error result', () => {
- beforeEach(() => {
- mock.onGet('test_results.json').reply(200, newErrorsTestReports, {});
- vm = mountComponent(Component, {
- endpoint: 'test_results.json',
- });
- });
-
- it('renders error summary text + new badge', done => {
- setTimeout(() => {
- expect(vm.$el.querySelector('.gl-spinner')).toBeNull();
- expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual(
- 'Test summary contained 2 errors out of 11 total tests',
- );
-
- expect(vm.$el.textContent).toContain('karma found 2 errors out of 3 total tests');
-
- expect(vm.$el.textContent).toContain('New');
- expect(vm.$el.textContent).toContain(
- 'rspec:pg found no changed test results out of 8 total tests',
- );
- done();
- }, 0);
- });
- });
-
- describe('with mixed results', () => {
- beforeEach(() => {
- mock.onGet('test_results.json').reply(200, mixedResultsTestReports, {});
- vm = mountComponent(Component, {
- endpoint: 'test_results.json',
- });
- });
-
- it('renders summary text', done => {
- setTimeout(() => {
- expect(vm.$el.querySelector('.gl-spinner')).toBeNull();
- expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual(
- 'Test summary contained 2 failed and 2 fixed test results out of 11 total tests',
- );
-
- expect(vm.$el.textContent).toContain(
- 'rspec:pg found 1 failed and 2 fixed test results out of 8 total tests',
- );
-
- expect(vm.$el.textContent).toContain('New');
- expect(vm.$el.textContent).toContain(' java ant found 1 failed out of 3 total tests');
- done();
- }, 0);
- });
- });
-
- describe('with resolved failures and resolved errors', () => {
- beforeEach(() => {
- mock.onGet('test_results.json').reply(200, resolvedFailures, {});
- vm = mountComponent(Component, {
- endpoint: 'test_results.json',
- });
- });
-
- it('renders summary text', done => {
- setTimeout(() => {
- expect(vm.$el.querySelector('.gl-spinner')).toBeNull();
- expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual(
- 'Test summary contained 4 fixed test results out of 11 total tests',
- );
-
- expect(vm.$el.textContent).toContain(
- 'rspec:pg found 4 fixed test results out of 8 total tests',
- );
- done();
- }, 0);
- });
-
- it('renders resolved failures', done => {
- setTimeout(() => {
- expect(vm.$el.querySelector('.report-block-container').textContent).toContain(
- resolvedFailures.suites[0].resolved_failures[0].name,
- );
-
- expect(vm.$el.querySelector('.report-block-container').textContent).toContain(
- resolvedFailures.suites[0].resolved_failures[1].name,
- );
- done();
- }, 0);
- });
-
- it('renders resolved errors', done => {
- setTimeout(() => {
- expect(vm.$el.querySelector('.report-block-container').textContent).toContain(
- resolvedFailures.suites[0].resolved_errors[0].name,
- );
-
- expect(vm.$el.querySelector('.report-block-container').textContent).toContain(
- resolvedFailures.suites[0].resolved_errors[1].name,
- );
- done();
- }, 0);
- });
- });
-
- describe('with error', () => {
- beforeEach(() => {
- mock.onGet('test_results.json').reply(500, {}, {});
- vm = mountComponent(Component, {
- endpoint: 'test_results.json',
- });
- });
-
- it('renders loading summary text with loading icon', done => {
- setTimeout(() => {
- expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual(
- 'Test summary failed loading results',
- );
- done();
- }, 0);
- });
- });
-
- describe('while loading', () => {
- beforeEach(() => {
- mock.onGet('test_results.json').reply(200, {}, {});
- vm = mountComponent(Component, {
- endpoint: 'test_results.json',
- });
- });
-
- it('renders loading summary text with loading icon', done => {
- expect(vm.$el.querySelector('.gl-spinner')).not.toBeNull();
- expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual(
- 'Test summary results are being parsed',
- );
-
- setTimeout(() => {
- done();
- }, 0);
- });
- });
-});
diff --git a/spec/javascripts/reports/components/modal_open_name_spec.js b/spec/javascripts/reports/components/modal_open_name_spec.js
deleted file mode 100644
index ae1fb2bf187..00000000000
--- a/spec/javascripts/reports/components/modal_open_name_spec.js
+++ /dev/null
@@ -1,47 +0,0 @@
-import Vue from 'vue';
-import Vuex from 'vuex';
-import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
-import component from '~/reports/components/modal_open_name.vue';
-
-Vue.use(Vuex);
-
-describe('Modal open name', () => {
- const Component = Vue.extend(component);
- let vm;
-
- const store = new Vuex.Store({
- actions: {
- openModal: () => {},
- },
- state: {},
- mutations: {},
- });
-
- beforeEach(() => {
- vm = mountComponentWithStore(Component, {
- store,
- props: {
- issue: {
- title: 'Issue',
- },
- status: 'failed',
- },
- });
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders the issue name', () => {
- expect(vm.$el.textContent.trim()).toEqual('Issue');
- });
-
- it('calls openModal actions when button is clicked', () => {
- spyOn(vm, 'openModal');
-
- vm.$el.click();
-
- expect(vm.openModal).toHaveBeenCalled();
- });
-});
diff --git a/spec/javascripts/reports/components/modal_spec.js b/spec/javascripts/reports/components/modal_spec.js
deleted file mode 100644
index ff046e64b6e..00000000000
--- a/spec/javascripts/reports/components/modal_spec.js
+++ /dev/null
@@ -1,54 +0,0 @@
-import Vue from 'vue';
-import component from '~/reports/components/modal.vue';
-import state from '~/reports/store/state';
-import mountComponent from '../../helpers/vue_mount_component_helper';
-import { trimText } from '../../helpers/text_helper';
-
-describe('Grouped Test Reports Modal', () => {
- const Component = Vue.extend(component);
- const modalDataStructure = state().modal.data;
-
- // populate data
- modalDataStructure.execution_time.value = 0.009411;
- modalDataStructure.system_output.value = 'Failure/Error: is_expected.to eq(3)\n\n';
- modalDataStructure.class.value = 'link';
-
- let vm;
-
- beforeEach(() => {
- vm = mountComponent(Component, {
- title: 'Test#sum when a is 1 and b is 2 returns summary',
- modalData: modalDataStructure,
- });
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders code block', () => {
- expect(vm.$el.querySelector('code').textContent).toEqual(
- modalDataStructure.system_output.value,
- );
- });
-
- it('renders link', () => {
- expect(vm.$el.querySelector('.js-modal-link').getAttribute('href')).toEqual(
- modalDataStructure.class.value,
- );
-
- expect(trimText(vm.$el.querySelector('.js-modal-link').textContent)).toEqual(
- modalDataStructure.class.value,
- );
- });
-
- it('renders seconds', () => {
- expect(vm.$el.textContent).toContain(`${modalDataStructure.execution_time.value} s`);
- });
-
- it('render title', () => {
- expect(trimText(vm.$el.querySelector('.modal-title').textContent)).toEqual(
- 'Test#sum when a is 1 and b is 2 returns summary',
- );
- });
-});
diff --git a/spec/javascripts/reports/components/summary_row_spec.js b/spec/javascripts/reports/components/summary_row_spec.js
deleted file mode 100644
index a19fbad403c..00000000000
--- a/spec/javascripts/reports/components/summary_row_spec.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import component from '~/reports/components/summary_row.vue';
-
-describe('Summary row', () => {
- const Component = Vue.extend(component);
- let vm;
-
- const props = {
- summary: 'SAST detected 1 new vulnerability and 1 fixed vulnerability',
- popoverOptions: {
- title: 'Static Application Security Testing (SAST)',
- content: '<a>Learn more about SAST</a>',
- },
- statusIcon: 'warning',
- };
-
- beforeEach(() => {
- vm = mountComponent(Component, props);
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders provided summary', () => {
- expect(
- vm.$el.querySelector('.report-block-list-issue-description-text').textContent.trim(),
- ).toEqual(props.summary);
- });
-
- it('renders provided icon', () => {
- expect(vm.$el.querySelector('.report-block-list-icon span').classList).toContain(
- 'js-ci-status-icon-warning',
- );
- });
-});
diff --git a/spec/javascripts/reports/components/test_issue_body_spec.js b/spec/javascripts/reports/components/test_issue_body_spec.js
deleted file mode 100644
index 9c1cec4c9bc..00000000000
--- a/spec/javascripts/reports/components/test_issue_body_spec.js
+++ /dev/null
@@ -1,72 +0,0 @@
-import Vue from 'vue';
-import component from '~/reports/components/test_issue_body.vue';
-import createStore from '~/reports/store';
-import { mountComponentWithStore } from '../../helpers/vue_mount_component_helper';
-import { trimText } from '../../helpers/text_helper';
-import { issue } from '../mock_data/mock_data';
-
-describe('Test Issue body', () => {
- let vm;
- const Component = Vue.extend(component);
- const store = createStore();
-
- const commonProps = {
- issue,
- status: 'failed',
- };
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('on click', () => {
- it('calls openModal action', () => {
- vm = mountComponentWithStore(Component, {
- store,
- props: commonProps,
- });
-
- spyOn(vm, 'openModal');
-
- vm.$el.querySelector('button').click();
-
- expect(vm.openModal).toHaveBeenCalledWith({
- issue: commonProps.issue,
- });
- });
- });
-
- describe('is new', () => {
- beforeEach(() => {
- vm = mountComponentWithStore(Component, {
- store,
- props: Object.assign({}, commonProps, { isNew: true }),
- });
- });
-
- it('renders issue name', () => {
- expect(vm.$el.textContent).toContain(commonProps.issue.name);
- });
-
- it('renders new badge', () => {
- expect(trimText(vm.$el.querySelector('.badge').textContent)).toEqual('New');
- });
- });
-
- describe('not new', () => {
- beforeEach(() => {
- vm = mountComponentWithStore(Component, {
- store,
- props: commonProps,
- });
- });
-
- it('renders issue name', () => {
- expect(vm.$el.textContent).toContain(commonProps.issue.name);
- });
-
- it('does not renders new badge', () => {
- expect(vm.$el.querySelector('.badge')).toEqual(null);
- });
- });
-});
diff --git a/spec/javascripts/reports/mock_data/mock_data.js b/spec/javascripts/reports/mock_data/mock_data.js
deleted file mode 100644
index 0d90253bad2..00000000000
--- a/spec/javascripts/reports/mock_data/mock_data.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// eslint-disable-next-line import/prefer-default-export
-export const issue = {
- result: 'failure',
- name: 'Test#sum when a is 1 and b is 2 returns summary',
- execution_time: 0.009411,
- system_output:
- "Failure/Error: is_expected.to eq(3)\n\n expected: 3\n got: -1\n\n (compared using ==)\n./spec/test_spec.rb:12:in `block (4 levels) in \u003ctop (required)\u003e'",
-};
diff --git a/spec/javascripts/reports/mock_data/new_and_fixed_failures_report.json b/spec/javascripts/reports/mock_data/new_and_fixed_failures_report.json
deleted file mode 100644
index 6141e5433a6..00000000000
--- a/spec/javascripts/reports/mock_data/new_and_fixed_failures_report.json
+++ /dev/null
@@ -1,55 +0,0 @@
-{
- "status": "failed",
- "summary": { "total": 11, "resolved": 2, "errored": 0, "failed": 2 },
- "suites": [
- {
- "name": "rspec:pg",
- "status": "failed",
- "summary": { "total": 8, "resolved": 2, "errored": 0, "failed": 1 },
- "new_failures": [
- {
- "status": "failed",
- "name": "Test#subtract when a is 2 and b is 1 returns correct result",
- "execution_time": 0.00908,
- "system_output": "Failure/Error: is_expected.to eq(1)\n\n expected: 1\n got: 3\n\n (compared using ==)\n./spec/test_spec.rb:43:in `block (4 levels) in <top (required)>'"
- }
- ],
- "resolved_failures": [
- {
- "status": "success",
- "name": "Test#sum when a is 1 and b is 2 returns summary",
- "execution_time": 0.000318,
- "system_output": null
- },
- {
- "status": "success",
- "name": "Test#sum when a is 100 and b is 200 returns summary",
- "execution_time": 0.000074,
- "system_output": null
- }
- ],
- "existing_failures": [],
- "new_errors": [],
- "resolved_errors": [],
- "existing_errors": []
- },
- {
- "name": "java ant",
- "status": "failed",
- "summary": { "total": 3, "resolved": 0, "errored": 0, "failed": 1 },
- "new_failures": [],
- "resolved_failures": [],
- "existing_failures": [
- {
- "status": "failed",
- "name": "sumTest",
- "execution_time": 0.004,
- "system_output": "junit.framework.AssertionFailedError: expected:<3> but was:<-1>\n\tat CalculatorTest.sumTest(Unknown Source)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n\tat java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n"
- }
- ],
- "new_errors": [],
- "resolved_errors": [],
- "existing_errors": []
- }
- ]
-}
diff --git a/spec/javascripts/reports/mock_data/new_errors_report.json b/spec/javascripts/reports/mock_data/new_errors_report.json
deleted file mode 100644
index cebf98fdb63..00000000000
--- a/spec/javascripts/reports/mock_data/new_errors_report.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "summary": { "total": 11, "resolved": 0, "errored": 2, "failed": 0 },
- "suites": [
- {
- "name": "rspec:pg",
- "summary": { "total": 8, "resolved": 0, "errored": 0, "failed": 0 },
- "new_failures": [],
- "resolved_failures": [],
- "existing_failures": [],
- "new_errors": [],
- "resolved_errors": [],
- "existing_errors": []
- },
- {
- "name": "karma",
- "summary": { "total": 3, "resolved": 0, "errored": 2, "failed": 0 },
- "new_failures": [],
- "resolved_failures": [],
- "existing_failures": [],
- "new_errors": [
- {
- "result": "error",
- "name": "Test#sum when a is 1 and b is 2 returns summary",
- "execution_time": 0.009411,
- "system_output": "Failed: Error in render: 'TypeError: Cannot read property 'status' of undefined'"
- },
- {
- "result": "error",
- "name": "Test#sum when a is 100 and b is 200 returns summary",
- "execution_time": 0.000162,
- "system_output": "Failed: Error in render: 'TypeError: Cannot read property 'length' of undefined'"
- }
- ],
- "resolved_errors": [],
- "existing_errors": []
- }
- ]
-}
diff --git a/spec/javascripts/reports/mock_data/new_failures_report.json b/spec/javascripts/reports/mock_data/new_failures_report.json
deleted file mode 100644
index 8b9c12c6271..00000000000
--- a/spec/javascripts/reports/mock_data/new_failures_report.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "summary": { "total": 11, "resolved": 0, "errored": 0, "failed": 2 },
- "suites": [
- {
- "name": "rspec:pg",
- "summary": { "total": 8, "resolved": 0, "errored": 0, "failed": 2 },
- "new_failures": [
- {
- "result": "failure",
- "name": "Test#sum when a is 1 and b is 2 returns summary",
- "execution_time": 0.009411,
- "system_output": "Failure/Error: is_expected.to eq(3)\n\n expected: 3\n got: -1\n\n (compared using ==)\n./spec/test_spec.rb:12:in `block (4 levels) in <top (required)>'"
- },
- {
- "result": "failure",
- "name": "Test#sum when a is 100 and b is 200 returns summary",
- "execution_time": 0.000162,
- "system_output": "Failure/Error: is_expected.to eq(300)\n\n expected: 300\n got: -100\n\n (compared using ==)\n./spec/test_spec.rb:21:in `block (4 levels) in <top (required)>'"
- }
- ],
- "resolved_failures": [],
- "existing_failures": [],
- "new_errors": [],
- "resolved_errors": [],
- "existing_errors": []
- },
- {
- "name": "java ant",
- "summary": { "total": 3, "resolved": 0, "errored": 0, "failed": 0 },
- "new_failures": [],
- "resolved_failures": [],
- "existing_failures": [],
- "new_errors": [],
- "resolved_errors": [],
- "existing_errors": []
- }
- ]
-}
diff --git a/spec/javascripts/reports/mock_data/no_failures_report.json b/spec/javascripts/reports/mock_data/no_failures_report.json
deleted file mode 100644
index 7da9e0c6211..00000000000
--- a/spec/javascripts/reports/mock_data/no_failures_report.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "status": "success",
- "summary": { "total": 11, "resolved": 0, "errored": 0, "failed": 0 },
- "suites": [
- {
- "name": "rspec:pg",
- "status": "success",
- "summary": { "total": 8, "resolved": 0, "errored": 0, "failed": 0 },
- "new_failures": [],
- "resolved_failures": [],
- "existing_failures": [],
- "new_errors": [],
- "resolved_errors": [],
- "existing_errors": []
- },
- {
- "name": "java ant",
- "status": "success",
- "summary": { "total": 3, "resolved": 0, "errored": 0, "failed": 0 },
- "new_failures": [],
- "resolved_failures": [],
- "existing_failures": [],
- "new_errors": [],
- "resolved_errors": [],
- "existing_errors": []
- }
- ]
-}
diff --git a/spec/javascripts/reports/mock_data/resolved_failures.json b/spec/javascripts/reports/mock_data/resolved_failures.json
deleted file mode 100644
index 49de6aa840b..00000000000
--- a/spec/javascripts/reports/mock_data/resolved_failures.json
+++ /dev/null
@@ -1,58 +0,0 @@
-{
- "status": "success",
- "summary": { "total": 11, "resolved": 4, "errored": 0, "failed": 0 },
- "suites": [
- {
- "name": "rspec:pg",
- "status": "success",
- "summary": { "total": 8, "resolved": 4, "errored": 0, "failed": 0 },
- "new_failures": [],
- "resolved_failures": [
- {
- "status": "success",
- "name": "Test#sum when a is 1 and b is 2 returns summary",
- "execution_time": 0.000411,
- "system_output": null,
- "stack_trace": null
- },
- {
- "status": "success",
- "name": "Test#sum when a is 100 and b is 200 returns summary",
- "execution_time": 7.6e-5,
- "system_output": null,
- "stack_trace": null
- }
- ],
- "existing_failures": [],
- "new_errors": [],
- "resolved_errors": [
- {
- "status": "success",
- "name": "Test#sum when a is 4 and b is 4 returns summary",
- "execution_time": 0.00342,
- "system_output": null,
- "stack_trace": null
- },
- {
- "status": "success",
- "name": "Test#sum when a is 40 and b is 400 returns summary",
- "execution_time": 0.0000231,
- "system_output": null,
- "stack_trace": null
- }
- ],
- "existing_errors": []
- },
- {
- "name": "java ant",
- "status": "success",
- "summary": { "total": 3, "resolved": 0, "errored": 0, "failed": 0 },
- "new_failures": [],
- "resolved_failures": [],
- "existing_failures": [],
- "new_errors": [],
- "resolved_errors": [],
- "existing_errors": []
- }
- ]
-}
diff --git a/spec/javascripts/reports/store/actions_spec.js b/spec/javascripts/reports/store/actions_spec.js
deleted file mode 100644
index 18fdb179597..00000000000
--- a/spec/javascripts/reports/store/actions_spec.js
+++ /dev/null
@@ -1,171 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import testAction from 'spec/helpers/vuex_action_helper';
-import { TEST_HOST } from 'spec/test_constants';
-import axios from '~/lib/utils/axios_utils';
-import {
- setEndpoint,
- requestReports,
- fetchReports,
- stopPolling,
- clearEtagPoll,
- receiveReportsSuccess,
- receiveReportsError,
- openModal,
- setModalData,
-} from '~/reports/store/actions';
-import state from '~/reports/store/state';
-import * as types from '~/reports/store/mutation_types';
-
-describe('Reports Store Actions', () => {
- let mockedState;
-
- beforeEach(() => {
- mockedState = state();
- });
-
- describe('setEndpoint', () => {
- it('should commit SET_ENDPOINT mutation', done => {
- testAction(
- setEndpoint,
- 'endpoint.json',
- mockedState,
- [{ type: types.SET_ENDPOINT, payload: 'endpoint.json' }],
- [],
- done,
- );
- });
- });
-
- describe('requestReports', () => {
- it('should commit REQUEST_REPORTS mutation', done => {
- testAction(requestReports, null, mockedState, [{ type: types.REQUEST_REPORTS }], [], done);
- });
- });
-
- describe('fetchReports', () => {
- let mock;
-
- beforeEach(() => {
- mockedState.endpoint = `${TEST_HOST}/endpoint.json`;
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- stopPolling();
- clearEtagPoll();
- });
-
- describe('success', () => {
- it('dispatches requestReports and receiveReportsSuccess ', done => {
- mock
- .onGet(`${TEST_HOST}/endpoint.json`)
- .replyOnce(200, { summary: {}, suites: [{ name: 'rspec' }] });
-
- testAction(
- fetchReports,
- null,
- mockedState,
- [],
- [
- {
- type: 'requestReports',
- },
- {
- payload: { data: { summary: {}, suites: [{ name: 'rspec' }] }, status: 200 },
- type: 'receiveReportsSuccess',
- },
- ],
- done,
- );
- });
- });
-
- describe('error', () => {
- beforeEach(() => {
- mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500);
- });
-
- it('dispatches requestReports and receiveReportsError ', done => {
- testAction(
- fetchReports,
- null,
- mockedState,
- [],
- [
- {
- type: 'requestReports',
- },
- {
- type: 'receiveReportsError',
- },
- ],
- done,
- );
- });
- });
- });
-
- describe('receiveReportsSuccess', () => {
- it('should commit RECEIVE_REPORTS_SUCCESS mutation with 200', done => {
- testAction(
- receiveReportsSuccess,
- { data: { summary: {} }, status: 200 },
- mockedState,
- [{ type: types.RECEIVE_REPORTS_SUCCESS, payload: { summary: {} } }],
- [],
- done,
- );
- });
-
- it('should not commit RECEIVE_REPORTS_SUCCESS mutation with 204', done => {
- testAction(
- receiveReportsSuccess,
- { data: { summary: {} }, status: 204 },
- mockedState,
- [],
- [],
- done,
- );
- });
- });
-
- describe('receiveReportsError', () => {
- it('should commit RECEIVE_REPORTS_ERROR mutation', done => {
- testAction(
- receiveReportsError,
- null,
- mockedState,
- [{ type: types.RECEIVE_REPORTS_ERROR }],
- [],
- done,
- );
- });
- });
-
- describe('openModal', () => {
- it('should dispatch setModalData', done => {
- testAction(
- openModal,
- { name: 'foo' },
- mockedState,
- [],
- [{ type: 'setModalData', payload: { name: 'foo' } }],
- done,
- );
- });
- });
-
- describe('setModalData', () => {
- it('should commit SET_ISSUE_MODAL_DATA', done => {
- testAction(
- setModalData,
- { name: 'foo' },
- mockedState,
- [{ type: types.SET_ISSUE_MODAL_DATA, payload: { name: 'foo' } }],
- [],
- done,
- );
- });
- });
-});
diff --git a/spec/javascripts/reports/store/mutations_spec.js b/spec/javascripts/reports/store/mutations_spec.js
deleted file mode 100644
index 9446cd454ab..00000000000
--- a/spec/javascripts/reports/store/mutations_spec.js
+++ /dev/null
@@ -1,126 +0,0 @@
-import state from '~/reports/store/state';
-import mutations from '~/reports/store/mutations';
-import * as types from '~/reports/store/mutation_types';
-import { issue } from '../mock_data/mock_data';
-
-describe('Reports Store Mutations', () => {
- let stateCopy;
-
- beforeEach(() => {
- stateCopy = state();
- });
-
- describe('SET_ENDPOINT', () => {
- it('should set endpoint', () => {
- mutations[types.SET_ENDPOINT](stateCopy, 'endpoint.json');
-
- expect(stateCopy.endpoint).toEqual('endpoint.json');
- });
- });
-
- describe('REQUEST_REPORTS', () => {
- it('should set isLoading to true', () => {
- mutations[types.REQUEST_REPORTS](stateCopy);
-
- expect(stateCopy.isLoading).toEqual(true);
- });
- });
-
- describe('RECEIVE_REPORTS_SUCCESS', () => {
- const mockedResponse = {
- summary: {
- total: 14,
- resolved: 0,
- failed: 7,
- },
- suites: [
- {
- name: 'build:linux',
- summary: {
- total: 2,
- resolved: 0,
- failed: 1,
- },
- new_failures: [
- {
- name: 'StringHelper#concatenate when a is git and b is lab returns summary',
- execution_time: 0.0092435,
- system_output: "Failure/Error: is_expected.to eq('gitlab')",
- },
- ],
- resolved_failures: [
- {
- name: 'StringHelper#concatenate when a is git and b is lab returns summary',
- execution_time: 0.009235,
- system_output: "Failure/Error: is_expected.to eq('gitlab')",
- },
- ],
- existing_failures: [
- {
- name: 'StringHelper#concatenate when a is git and b is lab returns summary',
- execution_time: 1232.08,
- system_output: "Failure/Error: is_expected.to eq('gitlab')",
- },
- ],
- },
- ],
- };
-
- beforeEach(() => {
- mutations[types.RECEIVE_REPORTS_SUCCESS](stateCopy, mockedResponse);
- });
-
- it('should reset isLoading', () => {
- expect(stateCopy.isLoading).toEqual(false);
- });
-
- it('should reset hasError', () => {
- expect(stateCopy.hasError).toEqual(false);
- });
-
- it('should set summary counts', () => {
- expect(stateCopy.summary.total).toEqual(mockedResponse.summary.total);
- expect(stateCopy.summary.resolved).toEqual(mockedResponse.summary.resolved);
- expect(stateCopy.summary.failed).toEqual(mockedResponse.summary.failed);
- });
-
- it('should set reports', () => {
- expect(stateCopy.reports).toEqual(mockedResponse.suites);
- });
- });
-
- describe('RECEIVE_REPORTS_ERROR', () => {
- beforeEach(() => {
- mutations[types.RECEIVE_REPORTS_ERROR](stateCopy);
- });
-
- it('should reset isLoading', () => {
- expect(stateCopy.isLoading).toEqual(false);
- });
-
- it('should set hasError to true', () => {
- expect(stateCopy.hasError).toEqual(true);
- });
-
- it('should reset reports', () => {
- expect(stateCopy.reports).toEqual([]);
- });
- });
-
- describe('SET_ISSUE_MODAL_DATA', () => {
- beforeEach(() => {
- mutations[types.SET_ISSUE_MODAL_DATA](stateCopy, {
- issue,
- });
- });
-
- it('should set modal title', () => {
- expect(stateCopy.modal.title).toEqual(issue.name);
- });
-
- it('should set modal data', () => {
- expect(stateCopy.modal.data.execution_time.value).toEqual(issue.execution_time);
- expect(stateCopy.modal.data.system_output.value).toEqual(issue.system_output);
- });
- });
-});
diff --git a/spec/javascripts/search_autocomplete_spec.js b/spec/javascripts/search_autocomplete_spec.js
index e9bc1fc51e8..4f42d4880e8 100644
--- a/spec/javascripts/search_autocomplete_spec.js
+++ b/spec/javascripts/search_autocomplete_spec.js
@@ -188,4 +188,28 @@ describe('Search autocomplete dropdown', () => {
// example) on JavaScript-created keypresses.
expect(submitSpy).not.toHaveBeenTriggered();
});
+
+ describe('disableAutocomplete', function() {
+ beforeEach(function() {
+ widget.enableAutocomplete();
+ });
+
+ it('should close the Dropdown', function() {
+ const toggleSpy = spyOn(widget.dropdownToggle, 'dropdown');
+
+ widget.dropdown.addClass('show');
+ widget.disableAutocomplete();
+
+ expect(toggleSpy).toHaveBeenCalledWith('toggle');
+ });
+ });
+
+ describe('enableAutocomplete', function() {
+ it('should open the Dropdown', function() {
+ const toggleSpy = spyOn(widget.dropdownToggle, 'dropdown');
+ widget.enableAutocomplete();
+
+ expect(toggleSpy).toHaveBeenCalledWith('toggle');
+ });
+ });
});
diff --git a/spec/javascripts/settings_panels_spec.js b/spec/javascripts/settings_panels_spec.js
deleted file mode 100644
index 2c5d91a45bc..00000000000
--- a/spec/javascripts/settings_panels_spec.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import $ from 'jquery';
-import initSettingsPanels from '~/settings_panels';
-
-describe('Settings Panels', () => {
- preloadFixtures('groups/edit.html');
-
- beforeEach(() => {
- loadFixtures('groups/edit.html');
- });
-
- describe('initSettingsPane', () => {
- afterEach(() => {
- window.location.hash = '';
- });
-
- it('should expand linked hash fragment panel', () => {
- window.location.hash = '#js-general-settings';
-
- const panel = document.querySelector('#js-general-settings');
- // Our test environment automatically expands everything so we need to clear that out first
- panel.classList.remove('expanded');
-
- expect(panel.classList.contains('expanded')).toBe(false);
-
- initSettingsPanels();
-
- expect(panel.classList.contains('expanded')).toBe(true);
- });
- });
-
- it('does not change the text content of triggers', () => {
- const panel = document.querySelector('#js-general-settings');
- const trigger = panel.querySelector('.js-settings-toggle-trigger-only');
- const originalText = trigger.textContent;
-
- initSettingsPanels();
-
- expect(panel.classList.contains('expanded')).toBe(true);
-
- $(trigger).click();
-
- expect(panel.classList.contains('expanded')).toBe(false);
- expect(trigger.textContent).toEqual(originalText);
- });
-});
diff --git a/spec/javascripts/sidebar/components/time_tracking/time_tracker_spec.js b/spec/javascripts/sidebar/components/time_tracking/time_tracker_spec.js
deleted file mode 100644
index 1580f32cfca..00000000000
--- a/spec/javascripts/sidebar/components/time_tracking/time_tracker_spec.js
+++ /dev/null
@@ -1,278 +0,0 @@
-import Vue from 'vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import TimeTracker from '~/sidebar/components/time_tracking/time_tracker.vue';
-
-describe('Issuable Time Tracker', () => {
- let initialData;
- let vm;
-
- const initTimeTrackingComponent = ({
- timeEstimate,
- timeSpent,
- timeEstimateHumanReadable,
- timeSpentHumanReadable,
- limitToHours,
- }) => {
- setFixtures(`
- <div>
- <div id="mock-container"></div>
- </div>
- `);
-
- initialData = {
- timeEstimate,
- timeSpent,
- humanTimeEstimate: timeEstimateHumanReadable,
- humanTimeSpent: timeSpentHumanReadable,
- limitToHours: Boolean(limitToHours),
- rootPath: '/',
- };
-
- const TimeTrackingComponent = Vue.extend({
- ...TimeTracker,
- components: {
- ...TimeTracker.components,
- transition: {
- // disable animations
- template: '<div><slot></slot></div>',
- },
- },
- });
- vm = mountComponent(TimeTrackingComponent, initialData, '#mock-container');
- };
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('Initialization', () => {
- beforeEach(() => {
- initTimeTrackingComponent({
- timeEstimate: 10000, // 2h 46m
- timeSpent: 5000, // 1h 23m
- timeEstimateHumanReadable: '2h 46m',
- timeSpentHumanReadable: '1h 23m',
- });
- });
-
- it('should return something defined', () => {
- expect(vm).toBeDefined();
- });
-
- it('should correctly set timeEstimate', done => {
- Vue.nextTick(() => {
- expect(vm.timeEstimate).toBe(initialData.timeEstimate);
- done();
- });
- });
-
- it('should correctly set time_spent', done => {
- Vue.nextTick(() => {
- expect(vm.timeSpent).toBe(initialData.timeSpent);
- done();
- });
- });
- });
-
- describe('Content Display', () => {
- describe('Panes', () => {
- describe('Comparison pane', () => {
- beforeEach(() => {
- initTimeTrackingComponent({
- timeEstimate: 100000, // 1d 3h
- timeSpent: 5000, // 1h 23m
- timeEstimateHumanReadable: '1d 3h',
- timeSpentHumanReadable: '1h 23m',
- });
- });
-
- it('should show the "Comparison" pane when timeEstimate and time_spent are truthy', done => {
- Vue.nextTick(() => {
- expect(vm.showComparisonState).toBe(true);
- const $comparisonPane = vm.$el.querySelector('.time-tracking-comparison-pane');
-
- expect($comparisonPane).toBeVisible();
- done();
- });
- });
-
- it('should show full times when the sidebar is collapsed', done => {
- Vue.nextTick(() => {
- const timeTrackingText = vm.$el.querySelector('.time-tracking-collapsed-summary span')
- .innerText;
-
- expect(timeTrackingText).toBe('1h 23m / 1d 3h');
- done();
- });
- });
-
- describe('Remaining meter', () => {
- it('should display the remaining meter with the correct width', done => {
- Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.time-tracking-comparison-pane .progress[value="5"]'),
- ).not.toBeNull();
- done();
- });
- });
-
- it('should display the remaining meter with the correct background color when within estimate', done => {
- Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.time-tracking-comparison-pane .progress[variant="primary"]'),
- ).not.toBeNull();
- done();
- });
- });
-
- it('should display the remaining meter with the correct background color when over estimate', done => {
- vm.timeEstimate = 10000; // 2h 46m
- vm.timeSpent = 20000000; // 231 days
- Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.time-tracking-comparison-pane .progress[variant="danger"]'),
- ).not.toBeNull();
- done();
- });
- });
- });
- });
-
- describe('Comparison pane when limitToHours is true', () => {
- beforeEach(() => {
- initTimeTrackingComponent({
- timeEstimate: 100000, // 1d 3h
- timeSpent: 5000, // 1h 23m
- timeEstimateHumanReadable: '',
- timeSpentHumanReadable: '',
- limitToHours: true,
- });
- });
-
- it('should show the correct tooltip text', done => {
- Vue.nextTick(() => {
- expect(vm.showComparisonState).toBe(true);
- const $title = vm.$el.querySelector('.time-tracking-content .compare-meter').dataset
- .originalTitle;
-
- expect($title).toBe('Time remaining: 26h 23m');
- done();
- });
- });
- });
-
- describe('Estimate only pane', () => {
- beforeEach(() => {
- initTimeTrackingComponent({
- timeEstimate: 10000, // 2h 46m
- timeSpent: 0,
- timeEstimateHumanReadable: '2h 46m',
- timeSpentHumanReadable: '',
- });
- });
-
- it('should display the human readable version of time estimated', done => {
- Vue.nextTick(() => {
- const estimateText = vm.$el.querySelector('.time-tracking-estimate-only-pane')
- .innerText;
- const correctText = 'Estimated: 2h 46m';
-
- expect(estimateText).toBe(correctText);
- done();
- });
- });
- });
-
- describe('Spent only pane', () => {
- beforeEach(() => {
- initTimeTrackingComponent({
- timeEstimate: 0,
- timeSpent: 5000, // 1h 23m
- timeEstimateHumanReadable: '2h 46m',
- timeSpentHumanReadable: '1h 23m',
- });
- });
-
- it('should display the human readable version of time spent', done => {
- Vue.nextTick(() => {
- const spentText = vm.$el.querySelector('.time-tracking-spend-only-pane').innerText;
- const correctText = 'Spent: 1h 23m';
-
- expect(spentText).toBe(correctText);
- done();
- });
- });
- });
-
- describe('No time tracking pane', () => {
- beforeEach(() => {
- initTimeTrackingComponent({
- timeEstimate: 0,
- timeSpent: 0,
- timeEstimateHumanReadable: '',
- timeSpentHumanReadable: '',
- });
- });
-
- it('should only show the "No time tracking" pane when both timeEstimate and time_spent are falsey', done => {
- Vue.nextTick(() => {
- const $noTrackingPane = vm.$el.querySelector('.time-tracking-no-tracking-pane');
- const noTrackingText = $noTrackingPane.innerText;
- const correctText = 'No estimate or time spent';
-
- expect(vm.showNoTimeTrackingState).toBe(true);
- expect($noTrackingPane).toBeVisible();
- expect(noTrackingText).toBe(correctText);
- done();
- });
- });
- });
-
- describe('Help pane', () => {
- const helpButton = () => vm.$el.querySelector('.help-button');
- const closeHelpButton = () => vm.$el.querySelector('.close-help-button');
- const helpPane = () => vm.$el.querySelector('.time-tracking-help-state');
-
- beforeEach(done => {
- initTimeTrackingComponent({ timeEstimate: 0, timeSpent: 0 });
-
- Vue.nextTick()
- .then(done)
- .catch(done.fail);
- });
-
- it('should not show the "Help" pane by default', () => {
- expect(vm.showHelpState).toBe(false);
- expect(helpPane()).toBeNull();
- });
-
- it('should show the "Help" pane when help button is clicked', done => {
- helpButton().click();
-
- Vue.nextTick()
- .then(() => {
- expect(vm.showHelpState).toBe(true);
- expect(helpPane()).toBeVisible();
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('should not show the "Help" pane when help button is clicked and then closed', done => {
- helpButton().click();
-
- Vue.nextTick()
- .then(() => closeHelpButton().click())
- .then(() => Vue.nextTick())
- .then(() => {
- expect(vm.showHelpState).toBe(false);
- expect(helpPane()).toBeNull();
- })
- .then(done)
- .catch(done.fail);
- });
- });
- });
- });
-});
diff --git a/spec/javascripts/sidebar/lock/edit_form_buttons_spec.js b/spec/javascripts/sidebar/lock/edit_form_buttons_spec.js
deleted file mode 100644
index c532554efb4..00000000000
--- a/spec/javascripts/sidebar/lock/edit_form_buttons_spec.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import editFormButtons from '~/sidebar/components/lock/edit_form_buttons.vue';
-
-describe('EditFormButtons', () => {
- let vm1;
- let vm2;
-
- beforeEach(() => {
- const Component = Vue.extend(editFormButtons);
- const toggleForm = () => {};
- const updateLockedAttribute = () => {};
-
- vm1 = mountComponent(Component, {
- isLocked: true,
- toggleForm,
- updateLockedAttribute,
- });
-
- vm2 = mountComponent(Component, {
- isLocked: false,
- toggleForm,
- updateLockedAttribute,
- });
- });
-
- it('renders unlock or lock text based on locked state', () => {
- expect(vm1.$el.innerHTML.includes('Unlock')).toBe(true);
-
- expect(vm2.$el.innerHTML.includes('Lock')).toBe(true);
- });
-});
diff --git a/spec/javascripts/sidebar/lock/lock_issue_sidebar_spec.js b/spec/javascripts/sidebar/lock/lock_issue_sidebar_spec.js
deleted file mode 100644
index 5296908afe2..00000000000
--- a/spec/javascripts/sidebar/lock/lock_issue_sidebar_spec.js
+++ /dev/null
@@ -1,99 +0,0 @@
-import Vue from 'vue';
-import { mockTracking, triggerEvent } from 'spec/helpers/tracking_helper';
-import lockIssueSidebar from '~/sidebar/components/lock/lock_issue_sidebar.vue';
-
-describe('LockIssueSidebar', () => {
- let vm1;
- let vm2;
-
- beforeEach(() => {
- const Component = Vue.extend(lockIssueSidebar);
-
- const mediator = {
- service: {
- update: Promise.resolve(true),
- },
-
- store: {
- isLockDialogOpen: false,
- },
- };
-
- vm1 = new Component({
- propsData: {
- isLocked: true,
- isEditable: true,
- mediator,
- issuableType: 'issue',
- },
- }).$mount();
-
- vm2 = new Component({
- propsData: {
- isLocked: false,
- isEditable: false,
- mediator,
- issuableType: 'merge_request',
- },
- }).$mount();
- });
-
- it('shows if locked and/or editable', () => {
- expect(vm1.$el.innerHTML.includes('Edit')).toBe(true);
-
- expect(vm1.$el.innerHTML.includes('Locked')).toBe(true);
-
- expect(vm2.$el.innerHTML.includes('Unlocked')).toBe(true);
- });
-
- it('displays the edit form when editable', done => {
- expect(vm1.isLockDialogOpen).toBe(false);
-
- vm1.$el.querySelector('.lock-edit').click();
-
- expect(vm1.isLockDialogOpen).toBe(true);
-
- vm1.$nextTick(() => {
- expect(vm1.$el.innerHTML.includes('Unlock this issue?')).toBe(true);
-
- done();
- });
- });
-
- it('tracks an event when "Edit" is clicked', () => {
- const spy = mockTracking('_category_', vm1.$el, spyOn);
- triggerEvent('.lock-edit');
-
- expect(spy).toHaveBeenCalledWith('_category_', 'click_edit_button', {
- label: 'right_sidebar',
- property: 'lock_issue',
- });
- });
-
- it('displays the edit form when opened from collapsed state', done => {
- expect(vm1.isLockDialogOpen).toBe(false);
-
- vm1.$el.querySelector('.sidebar-collapsed-icon').click();
-
- expect(vm1.isLockDialogOpen).toBe(true);
-
- setTimeout(() => {
- expect(vm1.$el.innerHTML.includes('Unlock this issue?')).toBe(true);
-
- done();
- });
- });
-
- it('does not display the edit form when opened from collapsed state if not editable', done => {
- expect(vm2.isLockDialogOpen).toBe(false);
-
- vm2.$el.querySelector('.sidebar-collapsed-icon').click();
-
- Vue.nextTick()
- .then(() => {
- expect(vm2.isLockDialogOpen).toBe(false);
- })
- .then(done)
- .catch(done.fail);
- });
-});
diff --git a/spec/javascripts/sidebar/mock_data.js b/spec/javascripts/sidebar/mock_data.js
deleted file mode 100644
index c869ff96933..00000000000
--- a/spec/javascripts/sidebar/mock_data.js
+++ /dev/null
@@ -1,7 +0,0 @@
-// No new code should be added to this file. Instead, modify the
-// file this one re-exports from. For more detail about why, see:
-// https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/31349
-
-import mockData from '../../../spec/frontend/sidebar/mock_data';
-
-export default mockData;
diff --git a/spec/javascripts/sidebar/participants_spec.js b/spec/javascripts/sidebar/participants_spec.js
deleted file mode 100644
index 7e80e86f8ca..00000000000
--- a/spec/javascripts/sidebar/participants_spec.js
+++ /dev/null
@@ -1,202 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import participants from '~/sidebar/components/participants/participants.vue';
-
-const PARTICIPANT = {
- id: 1,
- state: 'active',
- username: 'marcene',
- name: 'Allie Will',
- web_url: 'foo.com',
- avatar_url: 'gravatar.com/avatar/xxx',
-};
-
-const PARTICIPANT_LIST = [PARTICIPANT, { ...PARTICIPANT, id: 2 }, { ...PARTICIPANT, id: 3 }];
-
-describe('Participants', function() {
- let vm;
- let Participants;
-
- beforeEach(() => {
- Participants = Vue.extend(participants);
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('collapsed sidebar state', () => {
- it('shows loading spinner when loading', () => {
- vm = mountComponent(Participants, {
- loading: true,
- });
-
- expect(vm.$el.querySelector('.js-participants-collapsed-loading-icon')).toBeDefined();
- });
-
- it('shows participant count when given', () => {
- vm = mountComponent(Participants, {
- loading: false,
- participants: PARTICIPANT_LIST,
- });
- const countEl = vm.$el.querySelector('.js-participants-collapsed-count');
-
- expect(countEl.textContent.trim()).toBe(`${PARTICIPANT_LIST.length}`);
- });
-
- it('shows full participant count when there are hidden participants', () => {
- vm = mountComponent(Participants, {
- loading: false,
- participants: PARTICIPANT_LIST,
- numberOfLessParticipants: 1,
- });
- const countEl = vm.$el.querySelector('.js-participants-collapsed-count');
-
- expect(countEl.textContent.trim()).toBe(`${PARTICIPANT_LIST.length}`);
- });
- });
-
- describe('expanded sidebar state', () => {
- it('shows loading spinner when loading', () => {
- vm = mountComponent(Participants, {
- loading: true,
- });
-
- expect(vm.$el.querySelector('.js-participants-expanded-loading-icon')).toBeDefined();
- });
-
- it('when only showing visible participants, shows an avatar only for each participant under the limit', done => {
- const numberOfLessParticipants = 2;
- vm = mountComponent(Participants, {
- loading: false,
- participants: PARTICIPANT_LIST,
- numberOfLessParticipants,
- });
- vm.isShowingMoreParticipants = false;
-
- Vue.nextTick()
- .then(() => {
- const participantEls = vm.$el.querySelectorAll('.js-participants-author');
-
- expect(participantEls.length).toBe(numberOfLessParticipants);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('when only showing all participants, each has an avatar', done => {
- const numberOfLessParticipants = 2;
- vm = mountComponent(Participants, {
- loading: false,
- participants: PARTICIPANT_LIST,
- numberOfLessParticipants,
- });
- vm.isShowingMoreParticipants = true;
-
- Vue.nextTick()
- .then(() => {
- const participantEls = vm.$el.querySelectorAll('.js-participants-author');
-
- expect(participantEls.length).toBe(PARTICIPANT_LIST.length);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('does not have more participants link when they can all be shown', () => {
- const numberOfLessParticipants = 100;
- vm = mountComponent(Participants, {
- loading: false,
- participants: PARTICIPANT_LIST,
- numberOfLessParticipants,
- });
- const moreParticipantLink = vm.$el.querySelector('.js-toggle-participants-button');
-
- expect(PARTICIPANT_LIST.length).toBeLessThan(numberOfLessParticipants);
- expect(moreParticipantLink).toBeNull();
- });
-
- it('when too many participants, has more participants link to show more', done => {
- vm = mountComponent(Participants, {
- loading: false,
- participants: PARTICIPANT_LIST,
- numberOfLessParticipants: 2,
- });
- vm.isShowingMoreParticipants = false;
-
- Vue.nextTick()
- .then(() => {
- const moreParticipantLink = vm.$el.querySelector('.js-toggle-participants-button');
-
- expect(moreParticipantLink.textContent.trim()).toBe('+ 1 more');
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('when too many participants and already showing them, has more participants link to show less', done => {
- vm = mountComponent(Participants, {
- loading: false,
- participants: PARTICIPANT_LIST,
- numberOfLessParticipants: 2,
- });
- vm.isShowingMoreParticipants = true;
-
- Vue.nextTick()
- .then(() => {
- const moreParticipantLink = vm.$el.querySelector('.js-toggle-participants-button');
-
- expect(moreParticipantLink.textContent.trim()).toBe('- show less');
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('clicking more participants link emits event', () => {
- vm = mountComponent(Participants, {
- loading: false,
- participants: PARTICIPANT_LIST,
- numberOfLessParticipants: 2,
- });
- const moreParticipantLink = vm.$el.querySelector('.js-toggle-participants-button');
-
- expect(vm.isShowingMoreParticipants).toBe(false);
-
- moreParticipantLink.click();
-
- expect(vm.isShowingMoreParticipants).toBe(true);
- });
-
- it('clicking on participants icon emits `toggleSidebar` event', () => {
- vm = mountComponent(Participants, {
- loading: false,
- participants: PARTICIPANT_LIST,
- numberOfLessParticipants: 2,
- });
- spyOn(vm, '$emit');
-
- const participantsIconEl = vm.$el.querySelector('.sidebar-collapsed-icon');
-
- participantsIconEl.click();
-
- expect(vm.$emit).toHaveBeenCalledWith('toggleSidebar');
- });
- });
-
- describe('when not showing participants label', () => {
- beforeEach(() => {
- vm = mountComponent(Participants, {
- participants: PARTICIPANT_LIST,
- showParticipantLabel: false,
- });
- });
-
- it('does not show sidebar collapsed icon', () => {
- expect(vm.$el.querySelector('.sidebar-collapsed-icon')).not.toBeTruthy();
- });
-
- it('does not show participants label title', () => {
- expect(vm.$el.querySelector('.title')).not.toBeTruthy();
- });
- });
-});
diff --git a/spec/javascripts/sidebar/sidebar_mediator_spec.js b/spec/javascripts/sidebar/sidebar_mediator_spec.js
deleted file mode 100644
index 2aa30fd1cc6..00000000000
--- a/spec/javascripts/sidebar/sidebar_mediator_spec.js
+++ /dev/null
@@ -1,134 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import SidebarMediator from '~/sidebar/sidebar_mediator';
-import SidebarStore from '~/sidebar/stores/sidebar_store';
-import SidebarService, { gqClient } from '~/sidebar/services/sidebar_service';
-import Mock from './mock_data';
-
-const { mediator: mediatorMockData } = Mock;
-
-describe('Sidebar mediator', function() {
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
-
- this.mediator = new SidebarMediator(mediatorMockData);
- });
-
- afterEach(() => {
- SidebarService.singleton = null;
- SidebarStore.singleton = null;
- SidebarMediator.singleton = null;
- mock.restore();
- });
-
- it('assigns yourself ', () => {
- this.mediator.assignYourself();
-
- expect(this.mediator.store.currentUser).toEqual(mediatorMockData.currentUser);
- expect(this.mediator.store.assignees[0]).toEqual(mediatorMockData.currentUser);
- });
-
- it('saves assignees', done => {
- mock.onPut(mediatorMockData.endpoint).reply(200, {});
- this.mediator
- .saveAssignees('issue[assignee_ids]')
- .then(resp => {
- expect(resp.status).toEqual(200);
- done();
- })
- .catch(done.fail);
- });
-
- it('fetches the data', done => {
- const mockData = Mock.responseMap.GET[mediatorMockData.endpoint];
- mock.onGet(mediatorMockData.endpoint).reply(200, mockData);
-
- const mockGraphQlData = Mock.graphQlResponseData;
- spyOn(gqClient, 'query').and.returnValue({
- data: mockGraphQlData,
- });
-
- spyOn(this.mediator, 'processFetchedData').and.callThrough();
-
- this.mediator
- .fetch()
- .then(() => {
- expect(this.mediator.processFetchedData).toHaveBeenCalledWith(mockData, mockGraphQlData);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('processes fetched data', () => {
- const mockData = Mock.responseMap.GET[mediatorMockData.endpoint];
- this.mediator.processFetchedData(mockData);
-
- expect(this.mediator.store.assignees).toEqual(mockData.assignees);
- expect(this.mediator.store.humanTimeEstimate).toEqual(mockData.human_time_estimate);
- expect(this.mediator.store.humanTotalTimeSpent).toEqual(mockData.human_total_time_spent);
- expect(this.mediator.store.participants).toEqual(mockData.participants);
- expect(this.mediator.store.subscribed).toEqual(mockData.subscribed);
- expect(this.mediator.store.timeEstimate).toEqual(mockData.time_estimate);
- expect(this.mediator.store.totalTimeSpent).toEqual(mockData.total_time_spent);
- });
-
- it('sets moveToProjectId', () => {
- const projectId = 7;
- spyOn(this.mediator.store, 'setMoveToProjectId').and.callThrough();
-
- this.mediator.setMoveToProjectId(projectId);
-
- expect(this.mediator.store.setMoveToProjectId).toHaveBeenCalledWith(projectId);
- });
-
- it('fetches autocomplete projects', done => {
- const searchTerm = 'foo';
- mock.onGet(mediatorMockData.projectsAutocompleteEndpoint).reply(200, {});
- spyOn(this.mediator.service, 'getProjectsAutocomplete').and.callThrough();
- spyOn(this.mediator.store, 'setAutocompleteProjects').and.callThrough();
-
- this.mediator
- .fetchAutocompleteProjects(searchTerm)
- .then(() => {
- expect(this.mediator.service.getProjectsAutocomplete).toHaveBeenCalledWith(searchTerm);
- expect(this.mediator.store.setAutocompleteProjects).toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('moves issue', done => {
- const mockData = Mock.responseMap.POST[mediatorMockData.moveIssueEndpoint];
- const moveToProjectId = 7;
- mock.onPost(mediatorMockData.moveIssueEndpoint).reply(200, mockData);
- this.mediator.store.setMoveToProjectId(moveToProjectId);
- spyOn(this.mediator.service, 'moveIssue').and.callThrough();
- const visitUrl = spyOnDependency(SidebarMediator, 'visitUrl');
-
- this.mediator
- .moveIssue()
- .then(() => {
- expect(this.mediator.service.moveIssue).toHaveBeenCalledWith(moveToProjectId);
- expect(visitUrl).toHaveBeenCalledWith(mockData.web_url);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('toggle subscription', done => {
- this.mediator.store.setSubscribedState(false);
- mock.onPost(mediatorMockData.toggleSubscriptionEndpoint).reply(200, {});
- spyOn(this.mediator.service, 'toggleSubscription').and.callThrough();
-
- this.mediator
- .toggleSubscription()
- .then(() => {
- expect(this.mediator.service.toggleSubscription).toHaveBeenCalled();
- expect(this.mediator.store.subscribed).toEqual(true);
- })
- .then(done)
- .catch(done.fail);
- });
-});
diff --git a/spec/javascripts/sidebar/sidebar_move_issue_spec.js b/spec/javascripts/sidebar/sidebar_move_issue_spec.js
deleted file mode 100644
index ec712450f2e..00000000000
--- a/spec/javascripts/sidebar/sidebar_move_issue_spec.js
+++ /dev/null
@@ -1,166 +0,0 @@
-import $ from 'jquery';
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import SidebarMediator from '~/sidebar/sidebar_mediator';
-import SidebarStore from '~/sidebar/stores/sidebar_store';
-import SidebarService from '~/sidebar/services/sidebar_service';
-import SidebarMoveIssue from '~/sidebar/lib/sidebar_move_issue';
-import Mock from './mock_data';
-
-describe('SidebarMoveIssue', function() {
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- const mockData = Mock.responseMap.GET['/autocomplete/projects?project_id=15'];
- mock.onGet('/autocomplete/projects?project_id=15').reply(200, mockData);
- this.mediator = new SidebarMediator(Mock.mediator);
- this.$content = $(`
- <div class="dropdown">
- <div class="js-toggle"></div>
- <div class="dropdown-menu">
- <div class="dropdown-content"></div>
- </div>
- <div class="js-confirm-button"></div>
- </div>
- `);
- this.$toggleButton = this.$content.find('.js-toggle');
- this.$confirmButton = this.$content.find('.js-confirm-button');
-
- this.sidebarMoveIssue = new SidebarMoveIssue(
- this.mediator,
- this.$toggleButton,
- this.$confirmButton,
- );
- this.sidebarMoveIssue.init();
- });
-
- afterEach(() => {
- SidebarService.singleton = null;
- SidebarStore.singleton = null;
- SidebarMediator.singleton = null;
-
- this.sidebarMoveIssue.destroy();
- mock.restore();
- });
-
- describe('init', () => {
- it('should initialize the dropdown and listeners', () => {
- spyOn(this.sidebarMoveIssue, 'initDropdown');
- spyOn(this.sidebarMoveIssue, 'addEventListeners');
-
- this.sidebarMoveIssue.init();
-
- expect(this.sidebarMoveIssue.initDropdown).toHaveBeenCalled();
- expect(this.sidebarMoveIssue.addEventListeners).toHaveBeenCalled();
- });
- });
-
- describe('destroy', () => {
- it('should remove the listeners', () => {
- spyOn(this.sidebarMoveIssue, 'removeEventListeners');
-
- this.sidebarMoveIssue.destroy();
-
- expect(this.sidebarMoveIssue.removeEventListeners).toHaveBeenCalled();
- });
- });
-
- describe('initDropdown', () => {
- it('should initialize the gl_dropdown', () => {
- spyOn($.fn, 'glDropdown');
-
- this.sidebarMoveIssue.initDropdown();
-
- expect($.fn.glDropdown).toHaveBeenCalled();
- });
-
- it('escapes html from project name', done => {
- this.$toggleButton.dropdown('toggle');
-
- setTimeout(() => {
- expect(this.$content.find('.js-move-issue-dropdown-item')[1].innerHTML.trim()).toEqual(
- '&lt;img src=x onerror=alert(document.domain)&gt; foo / bar',
- );
- done();
- });
- });
- });
-
- describe('onConfirmClicked', () => {
- it('should move the issue with valid project ID', () => {
- spyOn(this.mediator, 'moveIssue').and.returnValue(Promise.resolve());
- this.mediator.setMoveToProjectId(7);
-
- this.sidebarMoveIssue.onConfirmClicked();
-
- expect(this.mediator.moveIssue).toHaveBeenCalled();
- expect(this.$confirmButton.prop('disabled')).toBeTruthy();
- expect(this.$confirmButton.hasClass('is-loading')).toBe(true);
- });
-
- it('should remove loading state from confirm button on failure', done => {
- spyOn(window, 'Flash');
- spyOn(this.mediator, 'moveIssue').and.returnValue(Promise.reject());
- this.mediator.setMoveToProjectId(7);
-
- this.sidebarMoveIssue.onConfirmClicked();
-
- expect(this.mediator.moveIssue).toHaveBeenCalled();
- // Wait for the move issue request to fail
- setTimeout(() => {
- expect(window.Flash).toHaveBeenCalled();
- expect(this.$confirmButton.prop('disabled')).toBeFalsy();
- expect(this.$confirmButton.hasClass('is-loading')).toBe(false);
- done();
- });
- });
-
- it('should not move the issue with id=0', () => {
- spyOn(this.mediator, 'moveIssue');
- this.mediator.setMoveToProjectId(0);
-
- this.sidebarMoveIssue.onConfirmClicked();
-
- expect(this.mediator.moveIssue).not.toHaveBeenCalled();
- });
- });
-
- it('should set moveToProjectId on dropdown item "No project" click', done => {
- spyOn(this.mediator, 'setMoveToProjectId');
-
- // Open the dropdown
- this.$toggleButton.dropdown('toggle');
-
- // Wait for the autocomplete request to finish
- setTimeout(() => {
- this.$content
- .find('.js-move-issue-dropdown-item')
- .eq(0)
- .trigger('click');
-
- expect(this.mediator.setMoveToProjectId).toHaveBeenCalledWith(0);
- expect(this.$confirmButton.prop('disabled')).toBeTruthy();
- done();
- }, 0);
- });
-
- it('should set moveToProjectId on dropdown item click', done => {
- spyOn(this.mediator, 'setMoveToProjectId');
-
- // Open the dropdown
- this.$toggleButton.dropdown('toggle');
-
- // Wait for the autocomplete request to finish
- setTimeout(() => {
- this.$content
- .find('.js-move-issue-dropdown-item')
- .eq(1)
- .trigger('click');
-
- expect(this.mediator.setMoveToProjectId).toHaveBeenCalledWith(20);
- expect(this.$confirmButton.attr('disabled')).toBe(undefined);
- done();
- }, 0);
- });
-});
diff --git a/spec/javascripts/sidebar/sidebar_subscriptions_spec.js b/spec/javascripts/sidebar/sidebar_subscriptions_spec.js
deleted file mode 100644
index ee4516f3bcd..00000000000
--- a/spec/javascripts/sidebar/sidebar_subscriptions_spec.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import sidebarSubscriptions from '~/sidebar/components/subscriptions/sidebar_subscriptions.vue';
-import SidebarMediator from '~/sidebar/sidebar_mediator';
-import SidebarService from '~/sidebar/services/sidebar_service';
-import SidebarStore from '~/sidebar/stores/sidebar_store';
-import Mock from './mock_data';
-
-describe('Sidebar Subscriptions', function() {
- let vm;
- let SidebarSubscriptions;
-
- beforeEach(() => {
- SidebarSubscriptions = Vue.extend(sidebarSubscriptions);
- // Set up the stores, services, etc
- // eslint-disable-next-line no-new
- new SidebarMediator(Mock.mediator);
- });
-
- afterEach(() => {
- vm.$destroy();
- SidebarService.singleton = null;
- SidebarStore.singleton = null;
- SidebarMediator.singleton = null;
- });
-
- it('calls the mediator toggleSubscription on event', () => {
- const mediator = new SidebarMediator();
- spyOn(mediator, 'toggleSubscription').and.returnValue(Promise.resolve());
- vm = mountComponent(SidebarSubscriptions, {
- mediator,
- });
-
- vm.onToggleSubscription();
-
- expect(mediator.toggleSubscription).toHaveBeenCalled();
- });
-});
diff --git a/spec/javascripts/sidebar/subscriptions_spec.js b/spec/javascripts/sidebar/subscriptions_spec.js
deleted file mode 100644
index cdb39efbef8..00000000000
--- a/spec/javascripts/sidebar/subscriptions_spec.js
+++ /dev/null
@@ -1,100 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import { mockTracking } from 'spec/helpers/tracking_helper';
-import subscriptions from '~/sidebar/components/subscriptions/subscriptions.vue';
-import eventHub from '~/sidebar/event_hub';
-
-describe('Subscriptions', function() {
- let vm;
- let Subscriptions;
-
- beforeEach(() => {
- Subscriptions = Vue.extend(subscriptions);
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('shows loading spinner when loading', () => {
- vm = mountComponent(Subscriptions, {
- loading: true,
- subscribed: undefined,
- });
-
- expect(vm.$refs.toggleButton.isLoading).toBe(true);
- expect(vm.$refs.toggleButton.$el.querySelector('.project-feature-toggle')).toHaveClass(
- 'is-loading',
- );
- });
-
- it('is toggled "off" when currently not subscribed', () => {
- vm = mountComponent(Subscriptions, {
- subscribed: false,
- });
-
- expect(vm.$refs.toggleButton.$el.querySelector('.project-feature-toggle')).not.toHaveClass(
- 'is-checked',
- );
- });
-
- it('is toggled "on" when currently subscribed', () => {
- vm = mountComponent(Subscriptions, {
- subscribed: true,
- });
-
- expect(vm.$refs.toggleButton.$el.querySelector('.project-feature-toggle')).toHaveClass(
- 'is-checked',
- );
- });
-
- it('toggleSubscription method emits `toggleSubscription` event on eventHub and Component', () => {
- vm = mountComponent(Subscriptions, { subscribed: true });
- spyOn(eventHub, '$emit');
- spyOn(vm, '$emit');
- spyOn(vm, 'track');
-
- vm.toggleSubscription();
-
- expect(eventHub.$emit).toHaveBeenCalledWith('toggleSubscription', jasmine.any(Object));
- expect(vm.$emit).toHaveBeenCalledWith('toggleSubscription', jasmine.any(Object));
- });
-
- it('tracks the event when toggled', () => {
- vm = mountComponent(Subscriptions, { subscribed: true });
- const spy = mockTracking('_category_', vm.$el, spyOn);
- vm.toggleSubscription();
-
- expect(spy).toHaveBeenCalled();
- });
-
- it('onClickCollapsedIcon method emits `toggleSidebar` event on component', () => {
- vm = mountComponent(Subscriptions, { subscribed: true });
- spyOn(vm, '$emit');
-
- vm.onClickCollapsedIcon();
-
- expect(vm.$emit).toHaveBeenCalledWith('toggleSidebar');
- });
-
- describe('given project emails are disabled', () => {
- const subscribeDisabledDescription = 'Notifications have been disabled';
-
- beforeEach(() => {
- vm = mountComponent(Subscriptions, {
- subscribed: false,
- projectEmailsDisabled: true,
- subscribeDisabledDescription,
- });
- });
-
- it('sets the correct display text', () => {
- expect(vm.$el.textContent).toContain(subscribeDisabledDescription);
- expect(vm.$refs.tooltip.dataset.originalTitle).toBe(subscribeDisabledDescription);
- });
-
- it('does not render the toggle button', () => {
- expect(vm.$refs.toggleButton).toBeUndefined();
- });
- });
-});
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js
index de1d351677c..3cbaa47c832 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js
@@ -153,7 +153,7 @@ describe('MRWidgetHeader', () => {
beforeEach(() => {
vm = mountComponent(Component, {
- mr: Object.assign({}, mrDefaultOptions),
+ mr: { ...mrDefaultOptions },
});
});
@@ -176,7 +176,7 @@ describe('MRWidgetHeader', () => {
});
it('renders web ide button in disabled state with no href', () => {
- const mr = Object.assign({}, mrDefaultOptions, { canPushToSourceBranch: false });
+ const mr = { ...mrDefaultOptions, canPushToSourceBranch: false };
vm = mountComponent(Component, { mr });
const link = vm.$el.querySelector('.js-web-ide');
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js
deleted file mode 100644
index 76827cde093..00000000000
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js
+++ /dev/null
@@ -1,99 +0,0 @@
-import { mount, createLocalVue } from '@vue/test-utils';
-import MrWidgetPipelineContainer from '~/vue_merge_request_widget/components/mr_widget_pipeline_container.vue';
-import MrWidgetPipeline from '~/vue_merge_request_widget/components/mr_widget_pipeline.vue';
-import ArtifactsApp from '~/vue_merge_request_widget/components/artifacts_list_app.vue';
-import { mockStore } from '../mock_data';
-
-const localVue = createLocalVue();
-
-describe('MrWidgetPipelineContainer', () => {
- let wrapper;
-
- const factory = (props = {}) => {
- wrapper = mount(localVue.extend(MrWidgetPipelineContainer), {
- propsData: {
- mr: Object.assign({}, mockStore),
- ...props,
- },
- localVue,
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('when pre merge', () => {
- beforeEach(() => {
- factory();
- });
-
- it('renders pipeline', () => {
- expect(wrapper.find(MrWidgetPipeline).exists()).toBe(true);
- expect(wrapper.find(MrWidgetPipeline).props()).toEqual(
- jasmine.objectContaining({
- pipeline: mockStore.pipeline,
- pipelineCoverageDelta: mockStore.pipelineCoverageDelta,
- ciStatus: mockStore.ciStatus,
- hasCi: mockStore.hasCI,
- sourceBranch: mockStore.sourceBranch,
- sourceBranchLink: mockStore.sourceBranchLink,
- }),
- );
- });
-
- it('renders deployments', () => {
- const expectedProps = mockStore.deployments.map(dep =>
- jasmine.objectContaining({
- deployment: dep,
- showMetrics: false,
- }),
- );
-
- const deployments = wrapper.findAll('.mr-widget-extension .js-pre-deployment');
-
- expect(deployments.wrappers.map(x => x.props())).toEqual(expectedProps);
- });
- });
-
- describe('when post merge', () => {
- beforeEach(() => {
- factory({
- isPostMerge: true,
- });
- });
-
- it('renders pipeline', () => {
- expect(wrapper.find(MrWidgetPipeline).exists()).toBe(true);
- expect(wrapper.find(MrWidgetPipeline).props()).toEqual(
- jasmine.objectContaining({
- pipeline: mockStore.mergePipeline,
- pipelineCoverageDelta: mockStore.pipelineCoverageDelta,
- ciStatus: mockStore.ciStatus,
- hasCi: mockStore.hasCI,
- sourceBranch: mockStore.targetBranch,
- sourceBranchLink: mockStore.targetBranch,
- }),
- );
- });
-
- it('renders deployments', () => {
- const expectedProps = mockStore.postMergeDeployments.map(dep =>
- jasmine.objectContaining({
- deployment: dep,
- showMetrics: true,
- }),
- );
-
- const deployments = wrapper.findAll('.mr-widget-extension .js-post-deployment');
-
- expect(deployments.wrappers.map(x => x.props())).toEqual(expectedProps);
- });
- });
-
- describe('with artifacts path', () => {
- it('renders the artifacts app', () => {
- expect(wrapper.find(ArtifactsApp).isVisible()).toBe(true);
- });
- });
-});
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
index 5997c93105e..883c41085fa 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
@@ -122,6 +122,19 @@ describe('MRWidgetPipeline', () => {
);
});
+ it('should render CI error when no CI is provided and pipeline must succeed is turned on', () => {
+ vm = mountComponent(Component, {
+ pipeline: {},
+ hasCi: false,
+ pipelineMustSucceed: true,
+ troubleshootingDocsPath: 'help',
+ });
+
+ expect(vm.$el.querySelector('.media-body').textContent.trim()).toContain(
+ 'No pipeline has been run for this commit.',
+ );
+ });
+
describe('with a pipeline', () => {
beforeEach(() => {
vm = mountComponent(Component, {
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
index d396f2d9271..9ba429c3d20 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
@@ -18,6 +18,7 @@ const createTestMr = customConfig => {
isPipelineFailed: false,
isPipelinePassing: false,
isMergeAllowed: true,
+ isApproved: true,
onlyAllowMergeIfPipelineSucceeds: false,
ffOnlyEnabled: false,
hasCI: false,
@@ -919,8 +920,8 @@ describe('ReadyToMerge', () => {
});
});
- describe('Commit message area', () => {
- describe('when using merge commits', () => {
+ describe('Merge request project settings', () => {
+ describe('when the merge commit merge method is enabled', () => {
beforeEach(() => {
vm = createComponent({
mr: { ffOnlyEnabled: false },
@@ -936,7 +937,7 @@ describe('ReadyToMerge', () => {
});
});
- describe('when fast-forward merge is enabled', () => {
+ describe('when the fast-forward merge method is enabled', () => {
beforeEach(() => {
vm = createComponent({
mr: { ffOnlyEnabled: true },
diff --git a/spec/javascripts/vue_mr_widget/stores/artifacts_list/actions_spec.js b/spec/javascripts/vue_mr_widget/stores/artifacts_list/actions_spec.js
deleted file mode 100644
index 5070e74b5d2..00000000000
--- a/spec/javascripts/vue_mr_widget/stores/artifacts_list/actions_spec.js
+++ /dev/null
@@ -1,165 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import testAction from 'spec/helpers/vuex_action_helper';
-import { TEST_HOST } from 'spec/test_constants';
-import axios from '~/lib/utils/axios_utils';
-import {
- setEndpoint,
- requestArtifacts,
- clearEtagPoll,
- stopPolling,
- fetchArtifacts,
- receiveArtifactsSuccess,
- receiveArtifactsError,
-} from '~/vue_merge_request_widget/stores/artifacts_list/actions';
-import state from '~/vue_merge_request_widget/stores/artifacts_list/state';
-import * as types from '~/vue_merge_request_widget/stores/artifacts_list/mutation_types';
-
-describe('Artifacts App Store Actions', () => {
- let mockedState;
-
- beforeEach(() => {
- mockedState = state();
- });
-
- describe('setEndpoint', () => {
- it('should commit SET_ENDPOINT mutation', done => {
- testAction(
- setEndpoint,
- 'endpoint.json',
- mockedState,
- [{ type: types.SET_ENDPOINT, payload: 'endpoint.json' }],
- [],
- done,
- );
- });
- });
-
- describe('requestArtifacts', () => {
- it('should commit REQUEST_ARTIFACTS mutation', done => {
- testAction(
- requestArtifacts,
- null,
- mockedState,
- [{ type: types.REQUEST_ARTIFACTS }],
- [],
- done,
- );
- });
- });
-
- describe('fetchArtifacts', () => {
- let mock;
-
- beforeEach(() => {
- mockedState.endpoint = `${TEST_HOST}/endpoint.json`;
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- stopPolling();
- clearEtagPoll();
- });
-
- describe('success', () => {
- it('dispatches requestArtifacts and receiveArtifactsSuccess ', done => {
- mock.onGet(`${TEST_HOST}/endpoint.json`).replyOnce(200, [
- {
- text: 'result.txt',
- url: 'asda',
- job_name: 'generate-artifact',
- job_path: 'asda',
- },
- ]);
-
- testAction(
- fetchArtifacts,
- null,
- mockedState,
- [],
- [
- {
- type: 'requestArtifacts',
- },
- {
- payload: {
- data: [
- {
- text: 'result.txt',
- url: 'asda',
- job_name: 'generate-artifact',
- job_path: 'asda',
- },
- ],
- status: 200,
- },
- type: 'receiveArtifactsSuccess',
- },
- ],
- done,
- );
- });
- });
-
- describe('error', () => {
- beforeEach(() => {
- mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500);
- });
-
- it('dispatches requestArtifacts and receiveArtifactsError ', done => {
- testAction(
- fetchArtifacts,
- null,
- mockedState,
- [],
- [
- {
- type: 'requestArtifacts',
- },
- {
- type: 'receiveArtifactsError',
- },
- ],
- done,
- );
- });
- });
- });
-
- describe('receiveArtifactsSuccess', () => {
- it('should commit RECEIVE_ARTIFACTS_SUCCESS mutation with 200', done => {
- testAction(
- receiveArtifactsSuccess,
- { data: { summary: {} }, status: 200 },
- mockedState,
- [{ type: types.RECEIVE_ARTIFACTS_SUCCESS, payload: { summary: {} } }],
- [],
- done,
- );
- });
-
- it('should not commit RECEIVE_ARTIFACTS_SUCCESS mutation with 204', done => {
- testAction(
- receiveArtifactsSuccess,
- { data: { summary: {} }, status: 204 },
- mockedState,
- [],
- [],
- done,
- );
- });
- });
-
- describe('receiveArtifactsError', () => {
- it('should commit RECEIVE_ARTIFACTS_ERROR mutation', done => {
- testAction(
- receiveArtifactsError,
- null,
- mockedState,
- [{ type: types.RECEIVE_ARTIFACTS_ERROR }],
- [],
- done,
- );
- });
- });
-});
diff --git a/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js b/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js
deleted file mode 100644
index 1906585af7b..00000000000
--- a/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js
+++ /dev/null
@@ -1,112 +0,0 @@
-import MergeRequestStore from '~/vue_merge_request_widget/stores/mr_widget_store';
-import { stateKey } from '~/vue_merge_request_widget/stores/state_maps';
-import mockData from '../mock_data';
-
-describe('MergeRequestStore', () => {
- let store;
-
- beforeEach(() => {
- store = new MergeRequestStore(mockData);
- });
-
- describe('setData', () => {
- it('should set isSHAMismatch when the diff SHA changes', () => {
- store.setData({ ...mockData, diff_head_sha: 'a-different-string' });
-
- expect(store.isSHAMismatch).toBe(true);
- });
-
- it('should not set isSHAMismatch when other data changes', () => {
- store.setData({ ...mockData, work_in_progress: !mockData.work_in_progress });
-
- expect(store.isSHAMismatch).toBe(false);
- });
-
- it('should update cached sha after rebasing', () => {
- store.setData({ ...mockData, diff_head_sha: 'abc123' }, true);
-
- expect(store.isSHAMismatch).toBe(false);
- expect(store.sha).toBe('abc123');
- });
-
- describe('isPipelinePassing', () => {
- it('is true when the CI status is `success`', () => {
- store.setData({ ...mockData, ci_status: 'success' });
-
- expect(store.isPipelinePassing).toBe(true);
- });
-
- it('is true when the CI status is `success-with-warnings`', () => {
- store.setData({ ...mockData, ci_status: 'success-with-warnings' });
-
- expect(store.isPipelinePassing).toBe(true);
- });
-
- it('is false when the CI status is `failed`', () => {
- store.setData({ ...mockData, ci_status: 'failed' });
-
- expect(store.isPipelinePassing).toBe(false);
- });
-
- it('is false when the CI status is anything except `success`', () => {
- store.setData({ ...mockData, ci_status: 'foobarbaz' });
-
- expect(store.isPipelinePassing).toBe(false);
- });
- });
-
- describe('isPipelineSkipped', () => {
- it('should set isPipelineSkipped=true when the CI status is `skipped`', () => {
- store.setData({ ...mockData, ci_status: 'skipped' });
-
- expect(store.isPipelineSkipped).toBe(true);
- });
-
- it('should set isPipelineSkipped=false when the CI status is anything except `skipped`', () => {
- store.setData({ ...mockData, ci_status: 'foobarbaz' });
-
- expect(store.isPipelineSkipped).toBe(false);
- });
- });
-
- describe('isNothingToMergeState', () => {
- it('returns true when nothingToMerge', () => {
- store.state = stateKey.nothingToMerge;
-
- expect(store.isNothingToMergeState).toEqual(true);
- });
-
- it('returns false when not nothingToMerge', () => {
- store.state = 'state';
-
- expect(store.isNothingToMergeState).toEqual(false);
- });
- });
- });
-
- describe('setPaths', () => {
- it('should set the add ci config path', () => {
- store.setData({ ...mockData });
-
- expect(store.mergeRequestAddCiConfigPath).toEqual('/group2/project2/new/pipeline');
- });
-
- it('should set humanAccess=Maintainer when user has that role', () => {
- store.setData({ ...mockData });
-
- expect(store.humanAccess).toEqual('Maintainer');
- });
-
- it('should set pipelinesEmptySvgPath', () => {
- store.setData({ ...mockData });
-
- expect(store.pipelinesEmptySvgPath).toBe('/path/to/svg');
- });
-
- it('should set newPipelinePath', () => {
- store.setData({ ...mockData });
-
- expect(store.newPipelinePath).toBe('/group2/project2/pipelines/new');
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/ci_badge_link_spec.js b/spec/javascripts/vue_shared/components/ci_badge_link_spec.js
deleted file mode 100644
index 367e07d3ad3..00000000000
--- a/spec/javascripts/vue_shared/components/ci_badge_link_spec.js
+++ /dev/null
@@ -1,100 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import ciBadge from '~/vue_shared/components/ci_badge_link.vue';
-
-describe('CI Badge Link Component', () => {
- let CIBadge;
- let vm;
-
- const statuses = {
- canceled: {
- text: 'canceled',
- label: 'canceled',
- group: 'canceled',
- icon: 'status_canceled',
- details_path: 'status/canceled',
- },
- created: {
- text: 'created',
- label: 'created',
- group: 'created',
- icon: 'status_created',
- details_path: 'status/created',
- },
- failed: {
- text: 'failed',
- label: 'failed',
- group: 'failed',
- icon: 'status_failed',
- details_path: 'status/failed',
- },
- manual: {
- text: 'manual',
- label: 'manual action',
- group: 'manual',
- icon: 'status_manual',
- details_path: 'status/manual',
- },
- pending: {
- text: 'pending',
- label: 'pending',
- group: 'pending',
- icon: 'status_pending',
- details_path: 'status/pending',
- },
- running: {
- text: 'running',
- label: 'running',
- group: 'running',
- icon: 'status_running',
- details_path: 'status/running',
- },
- skipped: {
- text: 'skipped',
- label: 'skipped',
- group: 'skipped',
- icon: 'status_skipped',
- details_path: 'status/skipped',
- },
- success_warining: {
- text: 'passed',
- label: 'passed',
- group: 'success-with-warnings',
- icon: 'status_warning',
- details_path: 'status/warning',
- },
- success: {
- text: 'passed',
- label: 'passed',
- group: 'passed',
- icon: 'status_success',
- details_path: 'status/passed',
- },
- };
-
- beforeEach(() => {
- CIBadge = Vue.extend(ciBadge);
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('should render each status badge', () => {
- Object.keys(statuses).map(status => {
- vm = mountComponent(CIBadge, { status: statuses[status] });
-
- expect(vm.$el.getAttribute('href')).toEqual(statuses[status].details_path);
- expect(vm.$el.textContent.trim()).toEqual(statuses[status].text);
- expect(vm.$el.getAttribute('class')).toContain(`ci-status ci-${statuses[status].group}`);
- expect(vm.$el.querySelector('svg')).toBeDefined();
- return vm;
- });
- });
-
- it('should not render label', () => {
- vm = mountComponent(CIBadge, { status: statuses.canceled, showText: false });
-
- expect(vm.$el.textContent.trim()).toEqual('');
- });
-});
diff --git a/spec/javascripts/vue_shared/components/ci_icon_spec.js b/spec/javascripts/vue_shared/components/ci_icon_spec.js
deleted file mode 100644
index 9486d7d4f23..00000000000
--- a/spec/javascripts/vue_shared/components/ci_icon_spec.js
+++ /dev/null
@@ -1,122 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import ciIcon from '~/vue_shared/components/ci_icon.vue';
-
-describe('CI Icon component', () => {
- const Component = Vue.extend(ciIcon);
- let vm;
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('should render a span element with an svg', () => {
- vm = mountComponent(Component, {
- status: {
- icon: 'status_success',
- },
- });
-
- expect(vm.$el.tagName).toEqual('SPAN');
- expect(vm.$el.querySelector('span > svg')).toBeDefined();
- });
-
- it('should render a success status', () => {
- vm = mountComponent(Component, {
- status: {
- icon: 'status_success',
- group: 'success',
- },
- });
-
- expect(vm.$el.classList.contains('ci-status-icon-success')).toEqual(true);
- });
-
- it('should render a failed status', () => {
- vm = mountComponent(Component, {
- status: {
- icon: 'status_failed',
- group: 'failed',
- },
- });
-
- expect(vm.$el.classList.contains('ci-status-icon-failed')).toEqual(true);
- });
-
- it('should render success with warnings status', () => {
- vm = mountComponent(Component, {
- status: {
- icon: 'status_warning',
- group: 'warning',
- },
- });
-
- expect(vm.$el.classList.contains('ci-status-icon-warning')).toEqual(true);
- });
-
- it('should render pending status', () => {
- vm = mountComponent(Component, {
- status: {
- icon: 'status_pending',
- group: 'pending',
- },
- });
-
- expect(vm.$el.classList.contains('ci-status-icon-pending')).toEqual(true);
- });
-
- it('should render running status', () => {
- vm = mountComponent(Component, {
- status: {
- icon: 'status_running',
- group: 'running',
- },
- });
-
- expect(vm.$el.classList.contains('ci-status-icon-running')).toEqual(true);
- });
-
- it('should render created status', () => {
- vm = mountComponent(Component, {
- status: {
- icon: 'status_created',
- group: 'created',
- },
- });
-
- expect(vm.$el.classList.contains('ci-status-icon-created')).toEqual(true);
- });
-
- it('should render skipped status', () => {
- vm = mountComponent(Component, {
- status: {
- icon: 'status_skipped',
- group: 'skipped',
- },
- });
-
- expect(vm.$el.classList.contains('ci-status-icon-skipped')).toEqual(true);
- });
-
- it('should render canceled status', () => {
- vm = mountComponent(Component, {
- status: {
- icon: 'status_canceled',
- group: 'canceled',
- },
- });
-
- expect(vm.$el.classList.contains('ci-status-icon-canceled')).toEqual(true);
- });
-
- it('should render status for manual action', () => {
- vm = mountComponent(Component, {
- status: {
- icon: 'status_manual',
- group: 'manual',
- },
- });
-
- expect(vm.$el.classList.contains('ci-status-icon-manual')).toEqual(true);
- });
-});
diff --git a/spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js b/spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js
deleted file mode 100644
index fbe9337ecf4..00000000000
--- a/spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js
+++ /dev/null
@@ -1,123 +0,0 @@
-import Vue from 'vue';
-import MockAdapter from 'axios-mock-adapter';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import waitForPromises from 'spec/helpers/wait_for_promises';
-import { GREEN_BOX_IMAGE_URL } from 'spec/test_constants';
-import axios from '~/lib/utils/axios_utils';
-import contentViewer from '~/vue_shared/components/content_viewer/content_viewer.vue';
-import '~/behaviors/markdown/render_gfm';
-
-describe('ContentViewer', () => {
- let vm;
- let mock;
-
- function createComponent(props) {
- const ContentViewer = Vue.extend(contentViewer);
- vm = mountComponent(ContentViewer, props);
- }
-
- afterEach(() => {
- vm.$destroy();
- if (mock) mock.restore();
- });
-
- it('markdown preview renders + loads rendered markdown from server', done => {
- mock = new MockAdapter(axios);
- mock.onPost(`${gon.relative_url_root}/testproject/preview_markdown`).replyOnce(200, {
- body: '<b>testing</b>',
- });
-
- createComponent({
- path: 'test.md',
- content: '* Test',
- projectPath: 'testproject',
- type: 'markdown',
- });
-
- waitForPromises()
- .then(() => {
- expect(vm.$el.querySelector('.md-previewer').textContent).toContain('testing');
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('renders image preview', done => {
- createComponent({
- path: GREEN_BOX_IMAGE_URL,
- fileSize: 1024,
- type: 'image',
- });
-
- vm.$nextTick()
- .then(() => {
- expect(vm.$el.querySelector('img').getAttribute('src')).toBe(GREEN_BOX_IMAGE_URL);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('renders fallback download control', done => {
- createComponent({
- path: 'somepath/test.abc',
- fileSize: 1024,
- });
-
- vm.$nextTick()
- .then(() => {
- expect(
- vm.$el
- .querySelector('.file-info')
- .textContent.trim()
- .replace(/\s+/, ' '),
- ).toEqual('test.abc (1.00 KiB)');
-
- expect(vm.$el.querySelector('.btn.btn-default').textContent.trim()).toEqual('Download');
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('renders fallback download control for file with a data URL path properly', done => {
- createComponent({
- path: 'data:application/octet-stream;base64,U0VMRUNUICfEhHNnc2cnIGZyb20gVGFibGVuYW1lOwoK',
- filePath: 'somepath/test.abc',
- });
-
- vm.$nextTick()
- .then(() => {
- expect(vm.$el.querySelector('.file-info').textContent.trim()).toEqual('test.abc');
- expect(vm.$el.querySelector('.btn.btn-default')).toHaveAttr('download', 'test.abc');
- expect(vm.$el.querySelector('.btn.btn-default').textContent.trim()).toEqual('Download');
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('markdown preview receives the file path as a parameter', done => {
- mock = new MockAdapter(axios);
- spyOn(axios, 'post').and.callThrough();
- mock.onPost(`${gon.relative_url_root}/testproject/preview_markdown`).reply(200, {
- body: '<b>testing</b>',
- });
-
- createComponent({
- path: 'test.md',
- content: '* Test',
- projectPath: 'testproject',
- type: 'markdown',
- filePath: 'foo/test.md',
- });
-
- vm.$nextTick()
- .then(() => {
- expect(axios.post).toHaveBeenCalledWith(
- `${gon.relative_url_root}/testproject/preview_markdown`,
- { path: 'foo/test.md', text: '* Test' },
- jasmine.any(Object),
- );
- })
- .then(done)
- .catch(done.fail);
- });
-});
diff --git a/spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js b/spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js
deleted file mode 100644
index 6a83790093a..00000000000
--- a/spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js
+++ /dev/null
@@ -1,105 +0,0 @@
-import Vue from 'vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import { GREEN_BOX_IMAGE_URL, RED_BOX_IMAGE_URL } from 'spec/test_constants';
-import diffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
-
-describe('DiffViewer', () => {
- const requiredProps = {
- diffMode: 'replaced',
- diffViewerMode: 'image',
- newPath: GREEN_BOX_IMAGE_URL,
- newSha: 'ABC',
- oldPath: RED_BOX_IMAGE_URL,
- oldSha: 'DEF',
- };
- let vm;
-
- function createComponent(props) {
- const DiffViewer = Vue.extend(diffViewer);
-
- vm = mountComponent(DiffViewer, props);
- }
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders image diff', done => {
- window.gon = {
- relative_url_root: '',
- };
-
- createComponent(
- Object.assign({}, requiredProps, {
- projectPath: '',
- }),
- );
-
- setTimeout(() => {
- expect(vm.$el.querySelector('.deleted img').getAttribute('src')).toBe(
- `//-/raw/DEF/${RED_BOX_IMAGE_URL}`,
- );
-
- expect(vm.$el.querySelector('.added img').getAttribute('src')).toBe(
- `//-/raw/ABC/${GREEN_BOX_IMAGE_URL}`,
- );
-
- done();
- });
- });
-
- it('renders fallback download diff display', done => {
- createComponent(
- Object.assign({}, requiredProps, {
- diffViewerMode: 'added',
- newPath: 'test.abc',
- oldPath: 'testold.abc',
- }),
- );
-
- setTimeout(() => {
- expect(vm.$el.querySelector('.deleted .file-info').textContent.trim()).toContain(
- 'testold.abc',
- );
-
- expect(vm.$el.querySelector('.deleted .btn.btn-default').textContent.trim()).toContain(
- 'Download',
- );
-
- expect(vm.$el.querySelector('.added .file-info').textContent.trim()).toContain('test.abc');
- expect(vm.$el.querySelector('.added .btn.btn-default').textContent.trim()).toContain(
- 'Download',
- );
-
- done();
- });
- });
-
- it('renders renamed component', () => {
- createComponent(
- Object.assign({}, requiredProps, {
- diffMode: 'renamed',
- diffViewerMode: 'renamed',
- newPath: 'test.abc',
- oldPath: 'testold.abc',
- }),
- );
-
- expect(vm.$el.textContent).toContain('File moved');
- });
-
- it('renders mode changed component', () => {
- createComponent(
- Object.assign({}, requiredProps, {
- diffMode: 'mode_changed',
- newPath: 'test.abc',
- oldPath: 'testold.abc',
- aMode: '123',
- bMode: '321',
- }),
- );
-
- expect(vm.$el.textContent).toContain('File mode changed from 123 to 321');
- });
-});
diff --git a/spec/javascripts/vue_shared/components/dropdown/dropdown_button_spec.js b/spec/javascripts/vue_shared/components/dropdown/dropdown_button_spec.js
deleted file mode 100644
index b00fa785a0e..00000000000
--- a/spec/javascripts/vue_shared/components/dropdown/dropdown_button_spec.js
+++ /dev/null
@@ -1,81 +0,0 @@
-import Vue from 'vue';
-
-import { mountComponentWithSlots } from 'spec/helpers/vue_mount_component_helper';
-import dropdownButtonComponent from '~/vue_shared/components/dropdown/dropdown_button.vue';
-
-const defaultLabel = 'Select';
-const customLabel = 'Select project';
-
-const createComponent = (props, slots = {}) => {
- const Component = Vue.extend(dropdownButtonComponent);
-
- return mountComponentWithSlots(Component, { props, slots });
-};
-
-describe('DropdownButtonComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('computed', () => {
- describe('dropdownToggleText', () => {
- it('returns default toggle text', () => {
- expect(vm.toggleText).toBe(defaultLabel);
- });
-
- it('returns custom toggle text when provided via props', () => {
- const vmEmptyLabels = createComponent({ toggleText: customLabel });
-
- expect(vmEmptyLabels.toggleText).toBe(customLabel);
- vmEmptyLabels.$destroy();
- });
- });
- });
-
- describe('template', () => {
- it('renders component container element of type `button`', () => {
- expect(vm.$el.nodeName).toBe('BUTTON');
- });
-
- it('renders component container element with required data attributes', () => {
- expect(vm.$el.dataset.abilityName).toBe(vm.abilityName);
- expect(vm.$el.dataset.fieldName).toBe(vm.fieldName);
- expect(vm.$el.dataset.issueUpdate).toBe(vm.updatePath);
- expect(vm.$el.dataset.labels).toBe(vm.labelsPath);
- expect(vm.$el.dataset.namespacePath).toBe(vm.namespace);
- expect(vm.$el.dataset.showAny).not.toBeDefined();
- });
-
- it('renders dropdown toggle text element', () => {
- const dropdownToggleTextEl = vm.$el.querySelector('.dropdown-toggle-text');
-
- expect(dropdownToggleTextEl).not.toBeNull();
- expect(dropdownToggleTextEl.innerText.trim()).toBe(defaultLabel);
- });
-
- it('renders dropdown button icon', () => {
- const dropdownIconEl = vm.$el.querySelector('.dropdown-toggle-icon i.fa');
-
- expect(dropdownIconEl).not.toBeNull();
- expect(dropdownIconEl.classList.contains('fa-chevron-down')).toBe(true);
- });
-
- it('renders slot, if default slot exists', () => {
- vm = createComponent(
- {},
- {
- default: ['Lorem Ipsum Dolar'],
- },
- );
-
- expect(vm.$el).not.toContainElement('.dropdown-toggle-text');
- expect(vm.$el).toHaveText('Lorem Ipsum Dolar');
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/dropdown/dropdown_hidden_input_spec.js b/spec/javascripts/vue_shared/components/dropdown/dropdown_hidden_input_spec.js
deleted file mode 100644
index 402de2a8788..00000000000
--- a/spec/javascripts/vue_shared/components/dropdown/dropdown_hidden_input_spec.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import Vue from 'vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import dropdownHiddenInputComponent from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
-
-import { mockLabels } from './mock_data';
-
-const createComponent = (name = 'label_id[]', value = mockLabels[0].id) => {
- const Component = Vue.extend(dropdownHiddenInputComponent);
-
- return mountComponent(Component, {
- name,
- value,
- });
-};
-
-describe('DropdownHiddenInputComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('template', () => {
- it('renders input element of type `hidden`', () => {
- expect(vm.$el.nodeName).toBe('INPUT');
- expect(vm.$el.getAttribute('type')).toBe('hidden');
- expect(vm.$el.getAttribute('name')).toBe(vm.name);
- expect(vm.$el.getAttribute('value')).toBe(`${vm.value}`);
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/dropdown/mock_data.js b/spec/javascripts/vue_shared/components/dropdown/mock_data.js
deleted file mode 100644
index b09d42da401..00000000000
--- a/spec/javascripts/vue_shared/components/dropdown/mock_data.js
+++ /dev/null
@@ -1,11 +0,0 @@
-export const mockLabels = [
- {
- id: 26,
- title: 'Foo Label',
- description: 'Foobar',
- color: '#BADA55',
- text_color: '#FFFFFF',
- },
-];
-
-export default mockLabels;
diff --git a/spec/javascripts/vue_shared/components/file_finder/item_spec.js b/spec/javascripts/vue_shared/components/file_finder/item_spec.js
deleted file mode 100644
index e18d0a46223..00000000000
--- a/spec/javascripts/vue_shared/components/file_finder/item_spec.js
+++ /dev/null
@@ -1,140 +0,0 @@
-import Vue from 'vue';
-import { file } from 'spec/ide/helpers';
-import ItemComponent from '~/vue_shared/components/file_finder/item.vue';
-import createComponent from '../../../helpers/vue_mount_component_helper';
-
-describe('File finder item spec', () => {
- const Component = Vue.extend(ItemComponent);
- let vm;
- let localFile;
-
- beforeEach(() => {
- localFile = {
- ...file(),
- name: 'test file',
- path: 'test/file',
- };
-
- vm = createComponent(Component, {
- file: localFile,
- focused: true,
- searchText: '',
- index: 0,
- });
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders file name & path', () => {
- expect(vm.$el.textContent).toContain('test file');
- expect(vm.$el.textContent).toContain('test/file');
- });
-
- describe('focused', () => {
- it('adds is-focused class', () => {
- expect(vm.$el.classList).toContain('is-focused');
- });
-
- it('does not have is-focused class when not focused', done => {
- vm.focused = false;
-
- vm.$nextTick(() => {
- expect(vm.$el.classList).not.toContain('is-focused');
-
- done();
- });
- });
- });
-
- describe('changed file icon', () => {
- it('does not render when not a changed or temp file', () => {
- expect(vm.$el.querySelector('.diff-changed-stats')).toBe(null);
- });
-
- it('renders when a changed file', done => {
- vm.file.changed = true;
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.diff-changed-stats')).not.toBe(null);
-
- done();
- });
- });
-
- it('renders when a temp file', done => {
- vm.file.tempFile = true;
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.diff-changed-stats')).not.toBe(null);
-
- done();
- });
- });
- });
-
- it('emits event when clicked', () => {
- spyOn(vm, '$emit');
-
- vm.$el.click();
-
- expect(vm.$emit).toHaveBeenCalledWith('click', vm.file);
- });
-
- describe('path', () => {
- let el;
-
- beforeEach(done => {
- vm.searchText = 'file';
-
- el = vm.$el.querySelector('.diff-changed-file-path');
-
- vm.$nextTick(done);
- });
-
- it('highlights text', () => {
- expect(el.querySelectorAll('.highlighted').length).toBe(4);
- });
-
- it('adds ellipsis to long text', done => {
- vm.file.path = new Array(70)
- .fill()
- .map((_, i) => `${i}-`)
- .join('');
-
- vm.$nextTick(() => {
- expect(el.textContent).toBe(`...${vm.file.path.substr(vm.file.path.length - 60)}`);
- done();
- });
- });
- });
-
- describe('name', () => {
- let el;
-
- beforeEach(done => {
- vm.searchText = 'file';
-
- el = vm.$el.querySelector('.diff-changed-file-name');
-
- vm.$nextTick(done);
- });
-
- it('highlights text', () => {
- expect(el.querySelectorAll('.highlighted').length).toBe(4);
- });
-
- it('does not add ellipsis to long text', done => {
- vm.file.name = new Array(70)
- .fill()
- .map((_, i) => `${i}-`)
- .join('');
-
- vm.$nextTick(() => {
- expect(el.textContent).not.toBe(`...${vm.file.name.substr(vm.file.name.length - 60)}`);
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js b/spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js
deleted file mode 100644
index 0bb4a04557b..00000000000
--- a/spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js
+++ /dev/null
@@ -1,190 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import component from '~/vue_shared/components/filtered_search_dropdown.vue';
-
-describe('Filtered search dropdown', () => {
- const Component = Vue.extend(component);
- let vm;
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('with an empty array of items', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- items: [],
- filterKey: '',
- });
- });
-
- it('renders empty list', () => {
- expect(vm.$el.querySelectorAll('.js-filtered-dropdown-result').length).toEqual(0);
- });
-
- it('renders filter input', () => {
- expect(vm.$el.querySelector('.js-filtered-dropdown-input')).not.toBeNull();
- });
- });
-
- describe('when visible numbers is less than the items length', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- items: [{ title: 'One' }, { title: 'Two' }, { title: 'Three' }],
- visibleItems: 2,
- filterKey: 'title',
- });
- });
-
- it('it renders only the maximum number provided', () => {
- expect(vm.$el.querySelectorAll('.js-filtered-dropdown-result').length).toEqual(2);
- });
- });
-
- describe('when visible number is bigger than the items length', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- items: [{ title: 'One' }, { title: 'Two' }, { title: 'Three' }],
- filterKey: 'title',
- });
- });
-
- it('it renders the full list of items the maximum number provided', () => {
- expect(vm.$el.querySelectorAll('.js-filtered-dropdown-result').length).toEqual(3);
- });
- });
-
- describe('while filtering', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- items: [
- { title: 'One' },
- { title: 'Two/three' },
- { title: 'Three four' },
- { title: 'Five' },
- ],
- filterKey: 'title',
- });
- });
-
- it('updates the results to match the typed value', done => {
- vm.$el.querySelector('.js-filtered-dropdown-input').value = 'three';
- vm.$el.querySelector('.js-filtered-dropdown-input').dispatchEvent(new Event('input'));
- vm.$nextTick(() => {
- expect(vm.$el.querySelectorAll('.js-filtered-dropdown-result').length).toEqual(2);
- done();
- });
- });
-
- describe('when no value matches the typed one', () => {
- it('does not render any result', done => {
- vm.$el.querySelector('.js-filtered-dropdown-input').value = 'six';
- vm.$el.querySelector('.js-filtered-dropdown-input').dispatchEvent(new Event('input'));
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelectorAll('.js-filtered-dropdown-result').length).toEqual(0);
- done();
- });
- });
- });
- });
-
- describe('with create mode enabled', () => {
- describe('when there are no matches', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- items: [
- { title: 'One' },
- { title: 'Two/three' },
- { title: 'Three four' },
- { title: 'Five' },
- ],
- filterKey: 'title',
- showCreateMode: true,
- });
-
- vm.$el.querySelector('.js-filtered-dropdown-input').value = 'eleven';
- vm.$el.querySelector('.js-filtered-dropdown-input').dispatchEvent(new Event('input'));
- });
-
- it('renders a create button', done => {
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.js-dropdown-create-button')).not.toBeNull();
- done();
- });
- });
-
- it('renders computed button text', done => {
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.js-dropdown-create-button').textContent.trim()).toEqual(
- 'Create eleven',
- );
- done();
- });
- });
-
- describe('on click create button', () => {
- it('emits createItem event with the filter', done => {
- spyOn(vm, '$emit');
- vm.$nextTick(() => {
- vm.$el.querySelector('.js-dropdown-create-button').click();
-
- expect(vm.$emit).toHaveBeenCalledWith('createItem', 'eleven');
- done();
- });
- });
- });
- });
-
- describe('when there are matches', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- items: [
- { title: 'One' },
- { title: 'Two/three' },
- { title: 'Three four' },
- { title: 'Five' },
- ],
- filterKey: 'title',
- showCreateMode: true,
- });
-
- vm.$el.querySelector('.js-filtered-dropdown-input').value = 'one';
- vm.$el.querySelector('.js-filtered-dropdown-input').dispatchEvent(new Event('input'));
- });
-
- it('does not render a create button', done => {
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.js-dropdown-create-button')).toBeNull();
- done();
- });
- });
- });
- });
-
- describe('with create mode disabled', () => {
- describe('when there are no matches', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- items: [
- { title: 'One' },
- { title: 'Two/three' },
- { title: 'Three four' },
- { title: 'Five' },
- ],
- filterKey: 'title',
- });
-
- vm.$el.querySelector('.js-filtered-dropdown-input').value = 'eleven';
- vm.$el.querySelector('.js-filtered-dropdown-input').dispatchEvent(new Event('input'));
- });
-
- it('does not render a create button', done => {
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.js-dropdown-create-button')).toBeNull();
- done();
- });
- });
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/gl_countdown_spec.js b/spec/javascripts/vue_shared/components/gl_countdown_spec.js
deleted file mode 100644
index 929ffe219f4..00000000000
--- a/spec/javascripts/vue_shared/components/gl_countdown_spec.js
+++ /dev/null
@@ -1,77 +0,0 @@
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import Vue from 'vue';
-import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
-
-describe('GlCountdown', () => {
- const Component = Vue.extend(GlCountdown);
- let vm;
- let now = '2000-01-01T00:00:00Z';
-
- beforeEach(() => {
- spyOn(Date, 'now').and.callFake(() => new Date(now).getTime());
- jasmine.clock().install();
- });
-
- afterEach(() => {
- vm.$destroy();
- jasmine.clock().uninstall();
- });
-
- describe('when there is time remaining', () => {
- beforeEach(done => {
- vm = mountComponent(Component, {
- endDateString: '2000-01-01T01:02:03Z',
- });
-
- Vue.nextTick()
- .then(done)
- .catch(done.fail);
- });
-
- it('displays remaining time', () => {
- expect(vm.$el).toContainText('01:02:03');
- });
-
- it('updates remaining time', done => {
- now = '2000-01-01T00:00:01Z';
- jasmine.clock().tick(1000);
-
- Vue.nextTick()
- .then(() => {
- expect(vm.$el).toContainText('01:02:02');
- done();
- })
- .catch(done.fail);
- });
- });
-
- describe('when there is no time remaining', () => {
- beforeEach(done => {
- vm = mountComponent(Component, {
- endDateString: '1900-01-01T00:00:00Z',
- });
-
- Vue.nextTick()
- .then(done)
- .catch(done.fail);
- });
-
- it('displays 00:00:00', () => {
- expect(vm.$el).toContainText('00:00:00');
- });
- });
-
- describe('when an invalid date is passed', () => {
- it('throws a validation error', () => {
- spyOn(Vue.config, 'warnHandler').and.stub();
- vm = mountComponent(Component, {
- endDateString: 'this is invalid',
- });
-
- expect(Vue.config.warnHandler).toHaveBeenCalledTimes(1);
- const [errorMessage] = Vue.config.warnHandler.calls.argsFor(0);
-
- expect(errorMessage).toMatch(/^Invalid prop: .* "endDateString"/);
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/header_ci_component_spec.js b/spec/javascripts/vue_shared/components/header_ci_component_spec.js
deleted file mode 100644
index b1abc972e1d..00000000000
--- a/spec/javascripts/vue_shared/components/header_ci_component_spec.js
+++ /dev/null
@@ -1,93 +0,0 @@
-import Vue from 'vue';
-import mountComponent, { mountComponentWithSlots } from 'spec/helpers/vue_mount_component_helper';
-import headerCi from '~/vue_shared/components/header_ci_component.vue';
-
-describe('Header CI Component', () => {
- let HeaderCi;
- let vm;
- let props;
-
- beforeEach(() => {
- HeaderCi = Vue.extend(headerCi);
- props = {
- status: {
- group: 'failed',
- icon: 'status_failed',
- label: 'failed',
- text: 'failed',
- details_path: 'path',
- },
- itemName: 'job',
- itemId: 123,
- time: '2017-05-08T14:57:39.781Z',
- user: {
- web_url: 'path',
- name: 'Foo',
- username: 'foobar',
- email: 'foo@bar.com',
- avatar_url: 'link',
- },
- hasSidebarButton: true,
- };
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- const findActionButtons = () => vm.$el.querySelector('.header-action-buttons');
-
- describe('render', () => {
- beforeEach(() => {
- vm = mountComponent(HeaderCi, props);
- });
-
- it('should render status badge', () => {
- expect(vm.$el.querySelector('.ci-failed')).toBeDefined();
- expect(vm.$el.querySelector('.ci-status-icon-failed svg')).toBeDefined();
- expect(vm.$el.querySelector('.ci-failed').getAttribute('href')).toEqual(
- props.status.details_path,
- );
- });
-
- it('should render item name and id', () => {
- expect(vm.$el.querySelector('strong').textContent.trim()).toEqual('job #123');
- });
-
- it('should render timeago date', () => {
- expect(vm.$el.querySelector('time')).toBeDefined();
- });
-
- it('should render user icon and name', () => {
- expect(vm.$el.querySelector('.js-user-link').innerText.trim()).toContain(props.user.name);
- });
-
- it('should render sidebar toggle button', () => {
- expect(vm.$el.querySelector('.js-sidebar-build-toggle')).not.toBeNull();
- });
-
- it('should not render header action buttons when empty', () => {
- expect(findActionButtons()).toBeNull();
- });
- });
-
- describe('slot', () => {
- it('should render header action buttons', () => {
- vm = mountComponentWithSlots(HeaderCi, { props, slots: { default: 'Test Actions' } });
-
- const buttons = findActionButtons();
-
- expect(buttons).not.toBeNull();
- expect(buttons.textContent).toEqual('Test Actions');
- });
- });
-
- describe('shouldRenderTriggeredLabel', () => {
- it('should rendered created keyword when the shouldRenderTriggeredLabel is false', () => {
- vm = mountComponent(HeaderCi, { ...props, shouldRenderTriggeredLabel: false });
-
- expect(vm.$el.textContent).toContain('created');
- expect(vm.$el.textContent).not.toContain('triggered');
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/markdown/suggestions_spec.js b/spec/javascripts/vue_shared/components/markdown/suggestions_spec.js
deleted file mode 100644
index b7de40b4831..00000000000
--- a/spec/javascripts/vue_shared/components/markdown/suggestions_spec.js
+++ /dev/null
@@ -1,106 +0,0 @@
-import Vue from 'vue';
-import SuggestionsComponent from '~/vue_shared/components/markdown/suggestions.vue';
-
-const MOCK_DATA = {
- suggestions: [
- {
- id: 1,
- appliable: true,
- applied: false,
- current_user: {
- can_apply: true,
- },
- diff_lines: [
- {
- can_receive_suggestion: false,
- line_code: null,
- meta_data: null,
- new_line: null,
- old_line: 5,
- rich_text: '-test',
- text: '-test',
- type: 'old',
- },
- {
- can_receive_suggestion: true,
- line_code: null,
- meta_data: null,
- new_line: 5,
- old_line: null,
- rich_text: '+new test',
- text: '+new test',
- type: 'new',
- },
- ],
- },
- ],
- noteHtml: `
- <div class="suggestion">
- <div class="line">-oldtest</div>
- </div>
- <div class="suggestion">
- <div class="line">+newtest</div>
- </div>
- `,
- isApplied: false,
- helpPagePath: 'path_to_docs',
-};
-
-describe('Suggestion component', () => {
- let vm;
- let diffTable;
-
- beforeEach(done => {
- const Component = Vue.extend(SuggestionsComponent);
-
- vm = new Component({
- propsData: MOCK_DATA,
- }).$mount();
-
- diffTable = vm.generateDiff(0).$mount().$el;
-
- spyOn(vm, 'renderSuggestions');
- vm.renderSuggestions();
- Vue.nextTick(done);
- });
-
- describe('mounted', () => {
- it('renders a flash container', () => {
- expect(vm.$el.querySelector('.js-suggestions-flash')).not.toBeNull();
- });
-
- it('renders a container for suggestions', () => {
- expect(vm.$refs.container).not.toBeNull();
- });
-
- it('renders suggestions', () => {
- expect(vm.renderSuggestions).toHaveBeenCalled();
- expect(vm.$el.innerHTML.includes('oldtest')).toBe(true);
- expect(vm.$el.innerHTML.includes('newtest')).toBe(true);
- });
- });
-
- describe('generateDiff', () => {
- it('generates a diff table', () => {
- expect(diffTable.querySelector('.md-suggestion-diff')).not.toBeNull();
- });
-
- it('generates a diff table that contains contents of `oldLineContent`', () => {
- expect(diffTable.innerHTML.includes(vm.fromContent)).toBe(true);
- });
-
- it('generates a diff table that contains contents the suggested lines', () => {
- MOCK_DATA.suggestions[0].diff_lines.forEach(line => {
- const text = line.text.substring(1);
-
- expect(diffTable.innerHTML.includes(text)).toBe(true);
- });
- });
-
- it('generates a diff table with the correct line number for each suggested line', () => {
- const lines = diffTable.querySelectorAll('.old_line');
-
- expect(parseInt([...lines][0].innerHTML, 10)).toBe(5);
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/markdown/toolbar_spec.js b/spec/javascripts/vue_shared/components/markdown/toolbar_spec.js
deleted file mode 100644
index 288eb40cc76..00000000000
--- a/spec/javascripts/vue_shared/components/markdown/toolbar_spec.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import toolbar from '~/vue_shared/components/markdown/toolbar.vue';
-
-describe('toolbar', () => {
- let vm;
- const Toolbar = Vue.extend(toolbar);
- const props = {
- markdownDocsPath: '',
- };
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('user can attach file', () => {
- beforeEach(() => {
- vm = mountComponent(Toolbar, props);
- });
-
- it('should render uploading-container', () => {
- expect(vm.$el.querySelector('.uploading-container')).not.toBeNull();
- });
- });
-
- describe('user cannot attach file', () => {
- beforeEach(() => {
- vm = mountComponent(
- Toolbar,
- Object.assign({}, props, {
- canAttachFile: false,
- }),
- );
- });
-
- it('should not render uploading-container', () => {
- expect(vm.$el.querySelector('.uploading-container')).toBeNull();
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/navigation_tabs_spec.js b/spec/javascripts/vue_shared/components/navigation_tabs_spec.js
deleted file mode 100644
index beb980a6556..00000000000
--- a/spec/javascripts/vue_shared/components/navigation_tabs_spec.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import navigationTabs from '~/vue_shared/components/navigation_tabs.vue';
-
-describe('navigation tabs component', () => {
- let vm;
- let Component;
- let data;
-
- beforeEach(() => {
- data = [
- {
- name: 'All',
- scope: 'all',
- count: 1,
- isActive: true,
- },
- {
- name: 'Pending',
- scope: 'pending',
- count: 0,
- isActive: false,
- },
- {
- name: 'Running',
- scope: 'running',
- isActive: false,
- },
- ];
-
- Component = Vue.extend(navigationTabs);
- vm = mountComponent(Component, { tabs: data, scope: 'pipelines' });
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('should render tabs', () => {
- expect(vm.$el.querySelectorAll('li').length).toEqual(data.length);
- });
-
- it('should render active tab', () => {
- expect(vm.$el.querySelector('.active .js-pipelines-tab-all')).toBeDefined();
- });
-
- it('should render badge', () => {
- expect(vm.$el.querySelector('.js-pipelines-tab-all .badge').textContent.trim()).toEqual('1');
- expect(vm.$el.querySelector('.js-pipelines-tab-pending .badge').textContent.trim()).toEqual(
- '0',
- );
- });
-
- it('should not render badge', () => {
- expect(vm.$el.querySelector('.js-pipelines-tab-running .badge')).toEqual(null);
- });
-
- it('should trigger onTabClick', () => {
- spyOn(vm, '$emit');
- vm.$el.querySelector('.js-pipelines-tab-pending').click();
-
- expect(vm.$emit).toHaveBeenCalledWith('onChangeTab', 'pending');
- });
-});
diff --git a/spec/javascripts/vue_shared/components/pikaday_spec.js b/spec/javascripts/vue_shared/components/pikaday_spec.js
deleted file mode 100644
index b787ba7596f..00000000000
--- a/spec/javascripts/vue_shared/components/pikaday_spec.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import datePicker from '~/vue_shared/components/pikaday.vue';
-
-describe('datePicker', () => {
- let vm;
- beforeEach(() => {
- const DatePicker = Vue.extend(datePicker);
- vm = mountComponent(DatePicker, {
- label: 'label',
- });
- });
-
- it('should render label text', () => {
- expect(vm.$el.querySelector('.dropdown-toggle-text').innerText.trim()).toEqual('label');
- });
-
- it('should show calendar', () => {
- expect(vm.$el.querySelector('.pika-single')).toBeDefined();
- });
-
- it('should toggle when dropdown is clicked', () => {
- const hidePicker = jasmine.createSpy();
- vm.$on('hidePicker', hidePicker);
-
- vm.$el.querySelector('.dropdown-menu-toggle').click();
-
- expect(hidePicker).toHaveBeenCalled();
- });
-});
diff --git a/spec/javascripts/vue_shared/components/project_avatar/default_spec.js b/spec/javascripts/vue_shared/components/project_avatar/default_spec.js
deleted file mode 100644
index 2ec19ebf80e..00000000000
--- a/spec/javascripts/vue_shared/components/project_avatar/default_spec.js
+++ /dev/null
@@ -1,58 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import { projectData } from 'spec/ide/mock_data';
-import { TEST_HOST } from 'spec/test_constants';
-import { getFirstCharacterCapitalized } from '~/lib/utils/text_utility';
-import ProjectAvatarDefault from '~/vue_shared/components/project_avatar/default.vue';
-
-describe('ProjectAvatarDefault component', () => {
- const Component = Vue.extend(ProjectAvatarDefault);
- let vm;
-
- beforeEach(() => {
- vm = mountComponent(Component, {
- project: projectData,
- });
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders identicon if project has no avatar_url', done => {
- const expectedText = getFirstCharacterCapitalized(projectData.name);
-
- vm.project = {
- ...vm.project,
- avatar_url: null,
- };
-
- vm.$nextTick()
- .then(() => {
- const identiconEl = vm.$el.querySelector('.identicon');
-
- expect(identiconEl).not.toBe(null);
- expect(identiconEl.textContent.trim()).toEqual(expectedText);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('renders avatar image if project has avatar_url', done => {
- const avatarUrl = `${TEST_HOST}/images/home/nasa.svg`;
-
- vm.project = {
- ...vm.project,
- avatar_url: avatarUrl,
- };
-
- vm.$nextTick()
- .then(() => {
- expect(vm.$el).toContainElement('.avatar');
- expect(vm.$el).not.toContainElement('.identicon');
- expect(vm.$el.querySelector('img')).toHaveAttr('src', avatarUrl);
- })
- .then(done)
- .catch(done.fail);
- });
-});
diff --git a/spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js b/spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js
deleted file mode 100644
index e73fb97b741..00000000000
--- a/spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js
+++ /dev/null
@@ -1,109 +0,0 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { trimText } from 'spec/helpers/text_helper';
-import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
-
-const localVue = createLocalVue();
-
-describe('ProjectListItem component', () => {
- const Component = localVue.extend(ProjectListItem);
- let wrapper;
- let vm;
- let options;
- loadJSONFixtures('static/projects.json');
- const project = getJSONFixture('static/projects.json')[0];
-
- beforeEach(() => {
- options = {
- propsData: {
- project,
- selected: false,
- },
- localVue,
- };
- });
-
- afterEach(() => {
- wrapper.vm.$destroy();
- });
-
- it('does not render a check mark icon if selected === false', () => {
- wrapper = shallowMount(Component, options);
-
- expect(wrapper.contains('.js-selected-icon.js-unselected')).toBe(true);
- });
-
- it('renders a check mark icon if selected === true', () => {
- options.propsData.selected = true;
-
- wrapper = shallowMount(Component, options);
-
- expect(wrapper.contains('.js-selected-icon.js-selected')).toBe(true);
- });
-
- it(`emits a "clicked" event when clicked`, () => {
- wrapper = shallowMount(Component, options);
- ({ vm } = wrapper);
-
- spyOn(vm, '$emit');
- wrapper.vm.onClick();
-
- expect(wrapper.vm.$emit).toHaveBeenCalledWith('click');
- });
-
- it(`renders the project avatar`, () => {
- wrapper = shallowMount(Component, options);
-
- expect(wrapper.contains('.js-project-avatar')).toBe(true);
- });
-
- it(`renders a simple namespace name with a trailing slash`, () => {
- options.propsData.project.name_with_namespace = 'a / b';
-
- wrapper = shallowMount(Component, options);
- const renderedNamespace = trimText(wrapper.find('.js-project-namespace').text());
-
- expect(renderedNamespace).toBe('a /');
- });
-
- it(`renders a properly truncated namespace with a trailing slash`, () => {
- options.propsData.project.name_with_namespace = 'a / b / c / d / e / f';
-
- wrapper = shallowMount(Component, options);
- const renderedNamespace = trimText(wrapper.find('.js-project-namespace').text());
-
- expect(renderedNamespace).toBe('a / ... / e /');
- });
-
- it(`renders the project name`, () => {
- options.propsData.project.name = 'my-test-project';
-
- wrapper = shallowMount(Component, options);
- const renderedName = trimText(wrapper.find('.js-project-name').text());
-
- expect(renderedName).toBe('my-test-project');
- });
-
- it(`renders the project name with highlighting in the case of a search query match`, () => {
- options.propsData.project.name = 'my-test-project';
- options.propsData.matcher = 'pro';
-
- wrapper = shallowMount(Component, options);
- const renderedName = trimText(wrapper.find('.js-project-name').html());
- const expected = 'my-test-<b>p</b><b>r</b><b>o</b>ject';
-
- expect(renderedName).toContain(expected);
- });
-
- it('prevents search query and project name XSS', () => {
- const alertSpy = spyOn(window, 'alert');
- options.propsData.project.name = "my-xss-pro<script>alert('XSS');</script>ject";
- options.propsData.matcher = "pro<script>alert('XSS');</script>";
-
- wrapper = shallowMount(Component, options);
- const renderedName = trimText(wrapper.find('.js-project-name').html());
- const expected = 'my-xss-project';
-
- expect(renderedName).toContain(expected);
- expect(alertSpy).not.toHaveBeenCalled();
- });
-});
diff --git a/spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js b/spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js
deleted file mode 100644
index 5d995f06abb..00000000000
--- a/spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js
+++ /dev/null
@@ -1,142 +0,0 @@
-import Vue from 'vue';
-import { head } from 'lodash';
-
-import { GlSearchBoxByType, GlInfiniteScroll } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
-import { trimText } from 'spec/helpers/text_helper';
-import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
-import ProjectSelector from '~/vue_shared/components/project_selector/project_selector.vue';
-
-const localVue = createLocalVue();
-
-describe('ProjectSelector component', () => {
- let wrapper;
- let vm;
- loadJSONFixtures('static/projects.json');
- const allProjects = getJSONFixture('static/projects.json');
- const searchResults = allProjects.slice(0, 5);
- let selected = [];
- selected = selected.concat(allProjects.slice(0, 3)).concat(allProjects.slice(5, 8));
-
- const findSearchInput = () => wrapper.find(GlSearchBoxByType).find('input');
-
- beforeEach(() => {
- jasmine.clock().install();
- jasmine.clock().mockDate();
-
- wrapper = mount(Vue.extend(ProjectSelector), {
- localVue,
- propsData: {
- projectSearchResults: searchResults,
- selectedProjects: selected,
- showNoResultsMessage: false,
- showMinimumSearchQueryMessage: false,
- showLoadingIndicator: false,
- showSearchErrorMessage: false,
- },
- attachToDocument: true,
- });
-
- ({ vm } = wrapper);
- });
-
- afterEach(() => {
- jasmine.clock().uninstall();
- vm.$destroy();
- });
-
- it('renders the search results', () => {
- expect(wrapper.findAll('.js-project-list-item').length).toBe(5);
- });
-
- it(`triggers a (debounced) search when the search input value changes`, () => {
- spyOn(vm, '$emit');
- const query = 'my test query!';
- const searchInput = findSearchInput();
-
- searchInput.setValue(query);
- searchInput.trigger('input');
-
- expect(vm.$emit).not.toHaveBeenCalledWith();
- jasmine.clock().tick(501);
-
- expect(vm.$emit).toHaveBeenCalledWith('searched', query);
- });
-
- it(`debounces the search input`, () => {
- spyOn(vm, '$emit');
- const searchInput = findSearchInput();
-
- const updateSearchQuery = (count = 0) => {
- if (count === 10) {
- jasmine.clock().tick(101);
-
- expect(vm.$emit).toHaveBeenCalledTimes(1);
- expect(vm.$emit).toHaveBeenCalledWith('searched', `search query #9`);
- } else {
- searchInput.setValue(`search query #${count}`);
- searchInput.trigger('input');
-
- jasmine.clock().tick(400);
- updateSearchQuery(count + 1);
- }
- };
-
- updateSearchQuery();
- });
-
- it(`includes a placeholder in the search box`, () => {
- const searchInput = findSearchInput();
-
- expect(searchInput.attributes('placeholder')).toBe('Search your projects');
- });
-
- it(`triggers a "bottomReached" event when user has scrolled to the bottom of the list`, () => {
- spyOn(vm, '$emit');
- wrapper.find(GlInfiniteScroll).vm.$emit('bottomReached');
-
- expect(vm.$emit).toHaveBeenCalledWith('bottomReached');
- });
-
- it(`triggers a "projectClicked" event when a project is clicked`, () => {
- spyOn(vm, '$emit');
- wrapper.find(ProjectListItem).vm.$emit('click', head(searchResults));
-
- expect(vm.$emit).toHaveBeenCalledWith('projectClicked', head(searchResults));
- });
-
- it(`shows a "no results" message if showNoResultsMessage === true`, () => {
- wrapper.setProps({ showNoResultsMessage: true });
-
- return vm.$nextTick().then(() => {
- const noResultsEl = wrapper.find('.js-no-results-message');
-
- expect(noResultsEl.exists()).toBe(true);
- expect(trimText(noResultsEl.text())).toEqual('Sorry, no projects matched your search');
- });
- });
-
- it(`shows a "minimum search query" message if showMinimumSearchQueryMessage === true`, () => {
- wrapper.setProps({ showMinimumSearchQueryMessage: true });
-
- return vm.$nextTick().then(() => {
- const minimumSearchEl = wrapper.find('.js-minimum-search-query-message');
-
- expect(minimumSearchEl.exists()).toBe(true);
- expect(trimText(minimumSearchEl.text())).toEqual('Enter at least three characters to search');
- });
- });
-
- it(`shows a error message if showSearchErrorMessage === true`, () => {
- wrapper.setProps({ showSearchErrorMessage: true });
-
- return vm.$nextTick().then(() => {
- const errorMessageEl = wrapper.find('.js-search-error-message');
-
- expect(errorMessageEl.exists()).toBe(true);
- expect(trimText(errorMessageEl.text())).toEqual(
- 'Something went wrong, unable to search projects',
- );
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/mock_data.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/mock_data.js
deleted file mode 100644
index 6564c012e67..00000000000
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/mock_data.js
+++ /dev/null
@@ -1,57 +0,0 @@
-export const mockLabels = [
- {
- id: 26,
- title: 'Foo Label',
- description: 'Foobar',
- color: '#BADA55',
- text_color: '#FFFFFF',
- },
- {
- id: 27,
- title: 'Foo::Bar',
- description: 'Foobar',
- color: '#0033CC',
- text_color: '#FFFFFF',
- },
-];
-
-export const mockSuggestedColors = [
- '#0033CC',
- '#428BCA',
- '#44AD8E',
- '#A8D695',
- '#5CB85C',
- '#69D100',
- '#004E00',
- '#34495E',
- '#7F8C8D',
- '#A295D6',
- '#5843AD',
- '#8E44AD',
- '#FFECDB',
- '#AD4363',
- '#D10069',
- '#CC0033',
- '#FF0000',
- '#D9534F',
- '#D1D100',
- '#F0AD4E',
- '#AD8D43',
-];
-
-export const mockConfig = {
- showCreate: true,
- isProject: true,
- abilityName: 'issue',
- context: {
- labels: mockLabels,
- },
- namespace: 'gitlab-org',
- updatePath: '/gitlab-org/my-project/issue/1',
- labelsPath: '/gitlab-org/my-project/-/labels.json',
- labelsWebUrl: '/gitlab-org/my-project/-/labels',
- labelFilterBasePath: '/gitlab-org/my-project/issues',
- canEdit: true,
- suggestedColors: mockSuggestedColors,
- emptyValueText: 'None',
-};
diff --git a/spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js b/spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js
deleted file mode 100644
index c062ee13231..00000000000
--- a/spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js
+++ /dev/null
@@ -1,107 +0,0 @@
-import Vue from 'vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import stackedProgressBarComponent from '~/vue_shared/components/stacked_progress_bar.vue';
-
-const createComponent = config => {
- const Component = Vue.extend(stackedProgressBarComponent);
- const defaultConfig = Object.assign(
- {},
- {
- successLabel: 'Synced',
- failureLabel: 'Failed',
- neutralLabel: 'Out of sync',
- successCount: 25,
- failureCount: 10,
- totalCount: 5000,
- },
- config,
- );
-
- return mountComponent(Component, defaultConfig);
-};
-
-describe('StackedProgressBarComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('computed', () => {
- describe('neutralCount', () => {
- it('returns neutralCount based on totalCount, successCount and failureCount', () => {
- expect(vm.neutralCount).toBe(4965); // 5000 - 25 - 10
- });
- });
- });
-
- describe('methods', () => {
- describe('getPercent', () => {
- it('returns percentage from provided count based on `totalCount`', () => {
- expect(vm.getPercent(500)).toBe(10);
- });
-
- it('returns percentage with decimal place from provided count based on `totalCount`', () => {
- expect(vm.getPercent(67)).toBe(1.3);
- });
-
- it('returns percentage as `< 1` from provided count based on `totalCount` when evaluated value is less than 1', () => {
- expect(vm.getPercent(10)).toBe('< 1');
- });
-
- it('returns 0 if totalCount is falsy', () => {
- vm = createComponent({ totalCount: 0 });
-
- expect(vm.getPercent(100)).toBe(0);
- });
- });
-
- describe('barStyle', () => {
- it('returns style string based on percentage provided', () => {
- expect(vm.barStyle(50)).toBe('width: 50%;');
- });
- });
-
- describe('getTooltip', () => {
- describe('when hideTooltips is false', () => {
- it('returns label string based on label and count provided', () => {
- expect(vm.getTooltip('Synced', 10)).toBe('Synced: 10');
- });
- });
-
- describe('when hideTooltips is true', () => {
- beforeEach(() => {
- vm = createComponent({ hideTooltips: true });
- });
-
- it('returns an empty string', () => {
- expect(vm.getTooltip('Synced', 10)).toBe('');
- });
- });
- });
- });
-
- describe('template', () => {
- it('renders container element', () => {
- expect(vm.$el.classList.contains('stacked-progress-bar')).toBeTruthy();
- });
-
- it('renders empty state when count is unavailable', () => {
- const vmX = createComponent({ totalCount: 0, successCount: 0, failureCount: 0 });
-
- expect(vmX.$el.querySelectorAll('.status-unavailable').length).not.toBe(0);
- vmX.$destroy();
- });
-
- it('renders bar elements when count is available', () => {
- expect(vm.$el.querySelectorAll('.status-green').length).not.toBe(0);
- expect(vm.$el.querySelectorAll('.status-neutral').length).not.toBe(0);
- expect(vm.$el.querySelectorAll('.status-red').length).not.toBe(0);
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/tabs/tab_spec.js b/spec/javascripts/vue_shared/components/tabs/tab_spec.js
deleted file mode 100644
index 8437fe37738..00000000000
--- a/spec/javascripts/vue_shared/components/tabs/tab_spec.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import Tab from '~/vue_shared/components/tabs/tab.vue';
-
-describe('Tab component', () => {
- const Component = Vue.extend(Tab);
- let vm;
-
- beforeEach(() => {
- vm = mountComponent(Component);
- });
-
- it('sets localActive to equal active', done => {
- vm.active = true;
-
- vm.$nextTick(() => {
- expect(vm.localActive).toBe(true);
-
- done();
- });
- });
-
- it('sets active class', done => {
- vm.active = true;
-
- vm.$nextTick(() => {
- expect(vm.$el.classList).toContain('active');
-
- done();
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/tabs/tabs_spec.js b/spec/javascripts/vue_shared/components/tabs/tabs_spec.js
deleted file mode 100644
index 50ba18cd338..00000000000
--- a/spec/javascripts/vue_shared/components/tabs/tabs_spec.js
+++ /dev/null
@@ -1,68 +0,0 @@
-import Vue from 'vue';
-import Tabs from '~/vue_shared/components/tabs/tabs';
-import Tab from '~/vue_shared/components/tabs/tab.vue';
-
-describe('Tabs component', () => {
- let vm;
-
- beforeEach(done => {
- vm = new Vue({
- components: {
- Tabs,
- Tab,
- },
- template: `
- <div>
- <tabs>
- <tab title="Testing" active>
- First tab
- </tab>
- <tab>
- <template slot="title">Test slot</template>
- Second tab
- </tab>
- </tabs>
- </div>
- `,
- }).$mount();
-
- setTimeout(done);
- });
-
- describe('tab links', () => {
- it('renders links for tabs', () => {
- expect(vm.$el.querySelectorAll('a').length).toBe(2);
- });
-
- it('renders link titles from props', () => {
- expect(vm.$el.querySelector('a').textContent).toContain('Testing');
- });
-
- it('renders link titles from slot', () => {
- expect(vm.$el.querySelectorAll('a')[1].textContent).toContain('Test slot');
- });
-
- it('renders active class', () => {
- expect(vm.$el.querySelector('a').classList).toContain('active');
- });
-
- it('updates active class on click', done => {
- vm.$el.querySelectorAll('a')[1].click();
-
- setTimeout(() => {
- expect(vm.$el.querySelector('a').classList).not.toContain('active');
- expect(vm.$el.querySelectorAll('a')[1].classList).toContain('active');
-
- done();
- });
- });
- });
-
- describe('content', () => {
- it('renders content panes', () => {
- expect(vm.$el.querySelectorAll('.tab-pane').length).toBe(2);
- expect(vm.$el.querySelectorAll('.tab-pane')[0].textContent).toContain('First tab');
- expect(vm.$el.querySelectorAll('.tab-pane')[1].textContent).toContain('Second tab');
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/toggle_button_spec.js b/spec/javascripts/vue_shared/components/toggle_button_spec.js
deleted file mode 100644
index ea0a89a3ab5..00000000000
--- a/spec/javascripts/vue_shared/components/toggle_button_spec.js
+++ /dev/null
@@ -1,101 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import toggleButton from '~/vue_shared/components/toggle_button.vue';
-
-describe('Toggle Button', () => {
- let vm;
- let Component;
-
- beforeEach(() => {
- Component = Vue.extend(toggleButton);
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('render output', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- value: true,
- name: 'foo',
- });
- });
-
- it('renders input with provided name', () => {
- expect(vm.$el.querySelector('input').getAttribute('name')).toEqual('foo');
- });
-
- it('renders input with provided value', () => {
- expect(vm.$el.querySelector('input').getAttribute('value')).toEqual('true');
- });
-
- it('renders input status icon', () => {
- expect(vm.$el.querySelectorAll('span.toggle-icon').length).toEqual(1);
- expect(vm.$el.querySelectorAll('svg.s16.toggle-icon-svg').length).toEqual(1);
- });
- });
-
- describe('is-checked', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- value: true,
- });
-
- spyOn(vm, '$emit');
- });
-
- it('renders is checked class', () => {
- expect(vm.$el.querySelector('button').classList.contains('is-checked')).toEqual(true);
- });
-
- it('sets aria-label representing toggle state', () => {
- vm.value = true;
-
- expect(vm.ariaLabel).toEqual('Toggle Status: ON');
-
- vm.value = false;
-
- expect(vm.ariaLabel).toEqual('Toggle Status: OFF');
- });
-
- it('emits change event when clicked', () => {
- vm.$el.querySelector('button').click();
-
- expect(vm.$emit).toHaveBeenCalledWith('change', false);
- });
- });
-
- describe('is-disabled', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- value: true,
- disabledInput: true,
- });
- spyOn(vm, '$emit');
- });
-
- it('renders disabled button', () => {
- expect(vm.$el.querySelector('button').classList.contains('is-disabled')).toEqual(true);
- });
-
- it('does not emit change event when clicked', () => {
- vm.$el.querySelector('button').click();
-
- expect(vm.$emit).not.toHaveBeenCalled();
- });
- });
-
- describe('is-loading', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- value: true,
- isLoading: true,
- });
- });
-
- it('renders loading class', () => {
- expect(vm.$el.querySelector('button').classList.contains('is-loading')).toEqual(true);
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/user_avatar/user_avatar_svg_spec.js b/spec/javascripts/vue_shared/components/user_avatar/user_avatar_svg_spec.js
deleted file mode 100644
index 31644416439..00000000000
--- a/spec/javascripts/vue_shared/components/user_avatar/user_avatar_svg_spec.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import Vue from 'vue';
-import avatarSvg from 'icons/_icon_random.svg';
-import UserAvatarSvg from '~/vue_shared/components/user_avatar/user_avatar_svg.vue';
-
-const UserAvatarSvgComponent = Vue.extend(UserAvatarSvg);
-
-describe('User Avatar Svg Component', function() {
- describe('Initialization', function() {
- beforeEach(function() {
- this.propsData = {
- size: 99,
- svg: avatarSvg,
- };
-
- this.userAvatarSvg = new UserAvatarSvgComponent({
- propsData: this.propsData,
- }).$mount();
- });
-
- it('should return a defined Vue component', function() {
- expect(this.userAvatarSvg).toBeDefined();
- });
-
- it('should have <svg> as a child element', function() {
- expect(this.userAvatarSvg.$el.tagName).toEqual('svg');
- expect(this.userAvatarSvg.$el.innerHTML).toContain('<path');
- });
- });
-});