diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js index 4f01345ee3b..622764107ad 100644 --- a/app/assets/javascripts/awards_handler.js +++ b/app/assets/javascripts/awards_handler.js @@ -1,8 +1,8 @@ /* eslint-disable class-methods-use-this */ -/* global Flash */ import _ from 'underscore'; import Cookies from 'js-cookie'; import { isInIssuePage, updateTooltipTitle } from './lib/utils/common_utils'; +import Flash from './flash'; const animationEndEventString = 'animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd'; const transitionEndEventString = 'transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd'; diff --git a/app/assets/javascripts/blob/balsamiq_viewer.js b/app/assets/javascripts/blob/balsamiq_viewer.js index 8641a6fdae6..062577af385 100644 --- a/app/assets/javascripts/blob/balsamiq_viewer.js +++ b/app/assets/javascripts/blob/balsamiq_viewer.js @@ -1,9 +1,8 @@ -/* global Flash */ - +import Flash from '../flash'; import BalsamiqViewer from './balsamiq/balsamiq_viewer'; function onError() { - const flash = new window.Flash('Balsamiq file could not be loaded.'); + const flash = new Flash('Balsamiq file could not be loaded.'); return flash; } diff --git a/app/assets/javascripts/blob/file_template_mediator.js b/app/assets/javascripts/blob/file_template_mediator.js index a20c6ca7a21..583e5faa506 100644 --- a/app/assets/javascripts/blob/file_template_mediator.js +++ b/app/assets/javascripts/blob/file_template_mediator.js @@ -1,6 +1,5 @@ /* eslint-disable class-methods-use-this */ -/* global Flash */ - +import Flash from '../flash'; import FileTemplateTypeSelector from './template_selectors/type_selector'; import BlobCiYamlSelector from './template_selectors/ci_yaml_selector'; import DockerfileSelector from './template_selectors/dockerfile_selector'; diff --git a/app/assets/javascripts/blob/viewer/index.js b/app/assets/javascripts/blob/viewer/index.js index e0b73f13d36..54132e8537b 100644 --- a/app/assets/javascripts/blob/viewer/index.js +++ b/app/assets/javascripts/blob/viewer/index.js @@ -1,4 +1,4 @@ -/* global Flash */ +import Flash from '../../flash'; import { handleLocationHash } from '../../lib/utils/common_utils'; export default class BlobViewer { diff --git a/app/assets/javascripts/boards/boards_bundle.js b/app/assets/javascripts/boards/boards_bundle.js index 815248f38ee..ef4093b59e3 100644 --- a/app/assets/javascripts/boards/boards_bundle.js +++ b/app/assets/javascripts/boards/boards_bundle.js @@ -1,10 +1,10 @@ /* eslint-disable one-var, quote-props, comma-dangle, space-before-function-paren */ /* global BoardService */ -/* global Flash */ import _ from 'underscore'; import Vue from 'vue'; import VueResource from 'vue-resource'; +import Flash from '../flash'; import FilteredSearchBoards from './filtered_search_boards'; import eventHub from './eventhub'; import './models/issue'; diff --git a/app/assets/javascripts/boards/components/board_sidebar.js b/app/assets/javascripts/boards/components/board_sidebar.js index 590b7be36e3..7f3afefc9cc 100644 --- a/app/assets/javascripts/boards/components/board_sidebar.js +++ b/app/assets/javascripts/boards/components/board_sidebar.js @@ -3,9 +3,9 @@ /* global MilestoneSelect */ /* global LabelsSelect */ /* global Sidebar */ -/* global Flash */ import Vue from 'vue'; +import Flash from '../../flash'; import eventHub from '../../sidebar/event_hub'; import AssigneeTitle from '../../sidebar/components/assignees/assignee_title'; import Assignees from '../../sidebar/components/assignees/assignees'; diff --git a/app/assets/javascripts/boards/components/modal/footer.js b/app/assets/javascripts/boards/components/modal/footer.js index a656f0546c0..de9e44cef35 100644 --- a/app/assets/javascripts/boards/components/modal/footer.js +++ b/app/assets/javascripts/boards/components/modal/footer.js @@ -1,7 +1,7 @@ /* eslint-disable no-new */ -/* global Flash */ import Vue from 'vue'; +import Flash from '../../../flash'; import './lists_dropdown'; const ModalStore = gl.issueBoards.ModalStore; diff --git a/app/assets/javascripts/boards/components/sidebar/remove_issue.js b/app/assets/javascripts/boards/components/sidebar/remove_issue.js index 1e623cf58b7..1ad97211934 100644 --- a/app/assets/javascripts/boards/components/sidebar/remove_issue.js +++ b/app/assets/javascripts/boards/components/sidebar/remove_issue.js @@ -1,7 +1,7 @@ /* eslint-disable no-new */ -/* global Flash */ import Vue from 'vue'; +import Flash from '../../../flash'; const Store = gl.issueBoards.BoardsStore; diff --git a/app/assets/javascripts/create_merge_request_dropdown.js b/app/assets/javascripts/create_merge_request_dropdown.js index ff2f2c81971..bf40eb3ee11 100644 --- a/app/assets/javascripts/create_merge_request_dropdown.js +++ b/app/assets/javascripts/create_merge_request_dropdown.js @@ -1,5 +1,5 @@ /* eslint-disable no-new */ -/* global Flash */ +import Flash from './flash'; import DropLab from './droplab/drop_lab'; import ISetter from './droplab/plugins/input_setter'; diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js index cdf5e3c0290..49bb6c52180 100644 --- a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js +++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js @@ -1,7 +1,6 @@ -/* global Flash */ - import Vue from 'vue'; import Cookies from 'js-cookie'; +import Flash from '../flash'; import Translate from '../vue_shared/translate'; import banner from './components/banner.vue'; import stageCodeComponent from './components/stage_code_component.vue'; diff --git a/app/assets/javascripts/deploy_keys/components/app.vue b/app/assets/javascripts/deploy_keys/components/app.vue index a663e30dfd0..54e13b79a4f 100644 --- a/app/assets/javascripts/deploy_keys/components/app.vue +++ b/app/assets/javascripts/deploy_keys/components/app.vue @@ -1,5 +1,5 @@ ', 'alert'); + + expect( + el.querySelector('.flash-text').textContent.trim(), + ).toBe(''); + }); + + it('adds container classes when inside content wrapper', () => { + el.innerHTML = createFlashEl('testing', 'alert', true); + + expect( + el.querySelector('.flash-text').classList.contains('container-fluid'), + ).toBeTruthy(); + expect( + el.querySelector('.flash-text').classList.contains('container-limited'), + ).toBeTruthy(); + }); + }); + + describe('hideFlash', () => { + let el; + + beforeEach(() => { + el = document.createElement('div'); + el.className = 'js-testing'; + }); + + it('sets transition style', () => { + hideFlash(el); + + expect( + el.style.transition, + ).toBe('opacity 0.3s'); + }); + + 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: '', + }); + + expect( + el.querySelector('.flash-action').textContent.trim(), + ).toBe(''); + }); + }); + + 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 += ` +