summaryrefslogtreecommitdiff
path: root/spec/javascripts/feature_highlight
diff options
context:
space:
mode:
authorClement Ho <clemmakesapps@gmail.com>2017-09-04 12:13:58 +0000
committerPhil Hughes <me@iamphill.com>2017-09-04 12:13:58 +0000
commite7bc0d7c2064ec53805c17cbd150b1e348a865be (patch)
tree605f952d87202af8be70dcb0bc88d2eb477aab56 /spec/javascripts/feature_highlight
parent970af9964ea9404942818d8c3394d2903955ed69 (diff)
downloadgitlab-ce-e7bc0d7c2064ec53805c17cbd150b1e348a865be.tar.gz
Add feature highlight to Issue Boards in new navigation sidebar
Diffstat (limited to 'spec/javascripts/feature_highlight')
-rw-r--r--spec/javascripts/feature_highlight/feature_highlight_helper_spec.js219
-rw-r--r--spec/javascripts/feature_highlight/feature_highlight_options_spec.js45
-rw-r--r--spec/javascripts/feature_highlight/feature_highlight_spec.js122
3 files changed, 386 insertions, 0 deletions
diff --git a/spec/javascripts/feature_highlight/feature_highlight_helper_spec.js b/spec/javascripts/feature_highlight/feature_highlight_helper_spec.js
new file mode 100644
index 00000000000..114d282e48a
--- /dev/null
+++ b/spec/javascripts/feature_highlight/feature_highlight_helper_spec.js
@@ -0,0 +1,219 @@
+import Cookies from 'js-cookie';
+import {
+ getCookieName,
+ getSelector,
+ showPopover,
+ hidePopover,
+ dismiss,
+ mouseleave,
+ mouseenter,
+ setupDismissButton,
+} from '~/feature_highlight/feature_highlight_helper';
+
+describe('feature highlight helper', () => {
+ describe('getCookieName', () => {
+ it('returns `feature-highlighted-` prefix', () => {
+ const cookieId = 'cookieId';
+ expect(getCookieName(cookieId)).toEqual(`feature-highlighted-${cookieId}`);
+ });
+ });
+
+ describe('getSelector', () => {
+ it('returns js-feature-highlight selector', () => {
+ const highlightId = 'highlightId';
+ expect(getSelector(highlightId)).toEqual(`.js-feature-highlight[data-highlight=${highlightId}]`);
+ });
+ });
+
+ describe('showPopover', () => {
+ it('returns true when popover is shown', () => {
+ const context = {
+ hasClass: () => false,
+ popover: () => {},
+ addClass: () => {},
+ };
+
+ expect(showPopover.call(context)).toEqual(true);
+ });
+
+ it('returns false when popover is already shown', () => {
+ const context = {
+ hasClass: () => true,
+ };
+
+ expect(showPopover.call(context)).toEqual(false);
+ });
+
+ it('shows popover', (done) => {
+ const context = {
+ hasClass: () => false,
+ popover: () => {},
+ addClass: () => {},
+ };
+
+ spyOn(context, 'popover').and.callFake((method) => {
+ expect(method).toEqual('show');
+ done();
+ });
+
+ showPopover.call(context);
+ });
+
+ it('adds disable-animation and js-popover-show class', (done) => {
+ const context = {
+ hasClass: () => false,
+ popover: () => {},
+ addClass: () => {},
+ };
+
+ spyOn(context, 'addClass').and.callFake((classNames) => {
+ expect(classNames).toEqual('disable-animation js-popover-show');
+ done();
+ });
+
+ showPopover.call(context);
+ });
+ });
+
+ describe('hidePopover', () => {
+ it('returns true when popover is hidden', () => {
+ const context = {
+ hasClass: () => true,
+ popover: () => {},
+ removeClass: () => {},
+ };
+
+ expect(hidePopover.call(context)).toEqual(true);
+ });
+
+ it('returns false when popover is already hidden', () => {
+ const context = {
+ hasClass: () => false,
+ };
+
+ expect(hidePopover.call(context)).toEqual(false);
+ });
+
+ it('hides popover', (done) => {
+ const context = {
+ hasClass: () => true,
+ popover: () => {},
+ removeClass: () => {},
+ };
+
+ spyOn(context, 'popover').and.callFake((method) => {
+ expect(method).toEqual('hide');
+ done();
+ });
+
+ hidePopover.call(context);
+ });
+
+ it('removes disable-animation and js-popover-show class', (done) => {
+ const context = {
+ hasClass: () => true,
+ popover: () => {},
+ removeClass: () => {},
+ };
+
+ spyOn(context, 'removeClass').and.callFake((classNames) => {
+ expect(classNames).toEqual('disable-animation js-popover-show');
+ done();
+ });
+
+ hidePopover.call(context);
+ });
+ });
+
+ describe('dismiss', () => {
+ const context = {
+ hide: () => {},
+ };
+
+ beforeEach(() => {
+ spyOn(Cookies, 'set').and.callFake(() => {});
+ spyOn(hidePopover, 'call').and.callFake(() => {});
+ spyOn(context, 'hide').and.callFake(() => {});
+ dismiss.call(context);
+ });
+
+ it('sets cookie to true', () => {
+ expect(Cookies.set).toHaveBeenCalled();
+ });
+
+ it('calls hide popover', () => {
+ expect(hidePopover.call).toHaveBeenCalled();
+ });
+
+ it('calls hide', () => {
+ expect(context.hide).toHaveBeenCalled();
+ });
+ });
+
+ describe('mouseleave', () => {
+ it('calls hide popover if .popover:hover is false', () => {
+ const fakeJquery = {
+ length: 0,
+ };
+
+ spyOn($.fn, 'init').and.callFake(selector => (selector === '.popover:hover' ? fakeJquery : $.fn));
+ spyOn(hidePopover, 'call');
+ mouseleave();
+ expect(hidePopover.call).toHaveBeenCalled();
+ });
+
+ it('does not call hide popover if .popover:hover is true', () => {
+ const fakeJquery = {
+ length: 1,
+ };
+
+ spyOn($.fn, 'init').and.callFake(selector => (selector === '.popover:hover' ? fakeJquery : $.fn));
+ spyOn(hidePopover, 'call');
+ mouseleave();
+ expect(hidePopover.call).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('mouseenter', () => {
+ const context = {};
+
+ it('shows popover', () => {
+ spyOn(showPopover, 'call').and.returnValue(false);
+ mouseenter.call(context);
+ expect(showPopover.call).toHaveBeenCalled();
+ });
+
+ it('registers mouseleave event if popover is showed', (done) => {
+ spyOn(showPopover, 'call').and.returnValue(true);
+ spyOn($.fn, 'on').and.callFake((eventName) => {
+ expect(eventName).toEqual('mouseleave');
+ done();
+ });
+ mouseenter.call(context);
+ });
+
+ it('does not register mouseleave event if popover is not showed', () => {
+ spyOn(showPopover, 'call').and.returnValue(false);
+ const spy = spyOn($.fn, 'on').and.callFake(() => {});
+ mouseenter.call(context);
+ expect(spy).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('setupDismissButton', () => {
+ it('registers click event callback', (done) => {
+ const context = {
+ getAttribute: () => 'popoverId',
+ dataset: {
+ highlight: 'cookieId',
+ },
+ };
+
+ spyOn($.fn, 'on').and.callFake((event) => {
+ expect(event).toEqual('click');
+ done();
+ });
+ setupDismissButton.call(context);
+ });
+ });
+});
diff --git a/spec/javascripts/feature_highlight/feature_highlight_options_spec.js b/spec/javascripts/feature_highlight/feature_highlight_options_spec.js
new file mode 100644
index 00000000000..7feb361edec
--- /dev/null
+++ b/spec/javascripts/feature_highlight/feature_highlight_options_spec.js
@@ -0,0 +1,45 @@
+import domContentLoaded from '~/feature_highlight/feature_highlight_options';
+import bp from '~/breakpoints';
+
+describe('feature highlight options', () => {
+ describe('domContentLoaded', () => {
+ const highlightOrder = [];
+
+ beforeEach(() => {
+ // Check for when highlightFeatures is called
+ spyOn(highlightOrder, 'find').and.callFake(() => {});
+ });
+
+ it('should not call highlightFeatures when breakpoint is xs', () => {
+ spyOn(bp, 'getBreakpointSize').and.returnValue('xs');
+
+ domContentLoaded(highlightOrder);
+ expect(bp.getBreakpointSize).toHaveBeenCalled();
+ expect(highlightOrder.find).not.toHaveBeenCalled();
+ });
+
+ it('should not call highlightFeatures when breakpoint is sm', () => {
+ spyOn(bp, 'getBreakpointSize').and.returnValue('sm');
+
+ domContentLoaded(highlightOrder);
+ expect(bp.getBreakpointSize).toHaveBeenCalled();
+ expect(highlightOrder.find).not.toHaveBeenCalled();
+ });
+
+ it('should not call highlightFeatures when breakpoint is md', () => {
+ spyOn(bp, 'getBreakpointSize').and.returnValue('md');
+
+ domContentLoaded(highlightOrder);
+ expect(bp.getBreakpointSize).toHaveBeenCalled();
+ expect(highlightOrder.find).not.toHaveBeenCalled();
+ });
+
+ it('should call highlightFeatures when breakpoint is lg', () => {
+ spyOn(bp, 'getBreakpointSize').and.returnValue('lg');
+
+ domContentLoaded(highlightOrder);
+ expect(bp.getBreakpointSize).toHaveBeenCalled();
+ expect(highlightOrder.find).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/javascripts/feature_highlight/feature_highlight_spec.js b/spec/javascripts/feature_highlight/feature_highlight_spec.js
new file mode 100644
index 00000000000..6abe8425ee7
--- /dev/null
+++ b/spec/javascripts/feature_highlight/feature_highlight_spec.js
@@ -0,0 +1,122 @@
+import Cookies from 'js-cookie';
+import * as featureHighlightHelper from '~/feature_highlight/feature_highlight_helper';
+import * as featureHighlight from '~/feature_highlight/feature_highlight';
+
+describe('feature highlight', () => {
+ describe('setupFeatureHighlightPopover', () => {
+ const selector = '.js-feature-highlight[data-highlight=test]';
+ beforeEach(() => {
+ setFixtures(`
+ <div>
+ <div class="js-feature-highlight" data-highlight="test" disabled>
+ Trigger
+ </div>
+ </div>
+ <div class="feature-highlight-popover-content">
+ Content
+ <div class="dismiss-feature-highlight">
+ Dismiss
+ </div>
+ </div>
+ `);
+ spyOn(window, 'addEventListener');
+ spyOn(window, 'removeEventListener');
+ featureHighlight.setupFeatureHighlightPopover('test', 0);
+ });
+
+ it('setups popover content', () => {
+ const $popoverContent = $('.feature-highlight-popover-content');
+ const outerHTML = $popoverContent.prop('outerHTML');
+
+ expect($(selector).data('content')).toEqual(outerHTML);
+ });
+
+ it('setups mouseenter', () => {
+ const showSpy = spyOn(featureHighlightHelper.showPopover, 'call');
+ $(selector).trigger('mouseenter');
+
+ expect(showSpy).toHaveBeenCalled();
+ });
+
+ it('setups debounced mouseleave', (done) => {
+ const hideSpy = spyOn(featureHighlightHelper.hidePopover, 'call');
+ $(selector).trigger('mouseleave');
+
+ // Even though we've set the debounce to 0ms, setTimeout is needed for the debounce
+ setTimeout(() => {
+ expect(hideSpy).toHaveBeenCalled();
+ done();
+ }, 0);
+ });
+
+ it('setups inserted.bs.popover', () => {
+ $(selector).trigger('mouseenter');
+ const popoverId = $(selector).attr('aria-describedby');
+ const spyEvent = spyOnEvent(`#${popoverId} .dismiss-feature-highlight`, 'click');
+
+ $(`#${popoverId} .dismiss-feature-highlight`).click();
+ expect(spyEvent).toHaveBeenTriggered();
+ });
+
+ it('setups show.bs.popover', () => {
+ $(selector).trigger('show.bs.popover');
+ expect(window.addEventListener).toHaveBeenCalledWith('scroll', jasmine.any(Function));
+ });
+
+ it('setups hide.bs.popover', () => {
+ $(selector).trigger('hide.bs.popover');
+ expect(window.removeEventListener).toHaveBeenCalledWith('scroll', jasmine.any(Function));
+ });
+
+ it('removes disabled attribute', () => {
+ expect($('.js-feature-highlight').is(':disabled')).toEqual(false);
+ });
+
+ it('displays popover', () => {
+ expect($(selector).attr('aria-describedby')).toBeFalsy();
+ $(selector).trigger('mouseenter');
+ expect($(selector).attr('aria-describedby')).toBeTruthy();
+ });
+ });
+
+ describe('shouldHighlightFeature', () => {
+ it('should return false if element is not found', () => {
+ spyOn(document, 'querySelector').and.returnValue(null);
+ spyOn(Cookies, 'get').and.returnValue(null);
+
+ expect(featureHighlight.shouldHighlightFeature()).toBeFalsy();
+ });
+
+ it('should return false if previouslyDismissed', () => {
+ spyOn(document, 'querySelector').and.returnValue(document.createElement('div'));
+ spyOn(Cookies, 'get').and.returnValue('true');
+
+ expect(featureHighlight.shouldHighlightFeature()).toBeFalsy();
+ });
+
+ it('should return true if element is found and not previouslyDismissed', () => {
+ spyOn(document, 'querySelector').and.returnValue(document.createElement('div'));
+ spyOn(Cookies, 'get').and.returnValue(null);
+
+ expect(featureHighlight.shouldHighlightFeature()).toBeTruthy();
+ });
+ });
+
+ describe('highlightFeatures', () => {
+ it('calls setupFeatureHighlightPopover if shouldHighlightFeature returns true', () => {
+ // Mimic shouldHighlightFeature set to true
+ const highlightOrder = ['issue-boards'];
+ spyOn(highlightOrder, 'find').and.returnValue(highlightOrder[0]);
+
+ expect(featureHighlight.highlightFeatures(highlightOrder)).toEqual(true);
+ });
+
+ it('does not call setupFeatureHighlightPopover if shouldHighlightFeature returns false', () => {
+ // Mimic shouldHighlightFeature set to false
+ const highlightOrder = ['issue-boards'];
+ spyOn(highlightOrder, 'find').and.returnValue(null);
+
+ expect(featureHighlight.highlightFeatures(highlightOrder)).toEqual(false);
+ });
+ });
+});