summaryrefslogtreecommitdiff
path: root/spec/javascripts
diff options
context:
space:
mode:
authorkushalpandya <kushal@gitlab.com>2017-09-04 21:53:33 +0530
committerkushalpandya <kushal@gitlab.com>2017-09-05 13:11:21 +0530
commit399d8ffc34a63ae33b3205b45cce712878e3a92e (patch)
tree9a0559d358a3a5d8aa9d8389333eaa55c63a369a /spec/javascripts
parentf3fdab1e2cf573287b016c6f080280d72e94a531 (diff)
downloadgitlab-ce-399d8ffc34a63ae33b3205b45cce712878e3a92e.tar.gz
Projects Dropdown App Component Spec
Diffstat (limited to 'spec/javascripts')
-rw-r--r--spec/javascripts/projects_dropdown/components/app_spec.js348
1 files changed, 348 insertions, 0 deletions
diff --git a/spec/javascripts/projects_dropdown/components/app_spec.js b/spec/javascripts/projects_dropdown/components/app_spec.js
new file mode 100644
index 00000000000..42f0f6fc1af
--- /dev/null
+++ b/spec/javascripts/projects_dropdown/components/app_spec.js
@@ -0,0 +1,348 @@
+import Vue from 'vue';
+
+import bp from '~/breakpoints';
+import appComponent from '~/projects_dropdown/components/app.vue';
+import eventHub from '~/projects_dropdown/event_hub';
+import ProjectsStore from '~/projects_dropdown/store/projects_store';
+import ProjectsService from '~/projects_dropdown/service/projects_service';
+
+import mountComponent from '../../helpers/vue_mount_component_helper';
+import { currentSession, mockProject, mockRawProject } from '../mock_data';
+
+const createComponent = () => {
+ gon.api_version = currentSession.apiVersion;
+ const Component = Vue.extend(appComponent);
+ const store = new ProjectsStore();
+ const service = new ProjectsService(currentSession.username);
+
+ return mountComponent(Component, {
+ store,
+ service,
+ currentUserName: currentSession.username,
+ currentProject: currentSession.project,
+ });
+};
+
+const returnServicePromise = (data, failed) => new Promise((resolve, reject) => {
+ if (failed) {
+ reject(data);
+ } else {
+ resolve({
+ json() {
+ return data;
+ },
+ });
+ }
+});
+
+describe('AppComponent', () => {
+ describe('computed', () => {
+ let vm;
+
+ beforeEach(() => {
+ vm = createComponent();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('frequentProjects', () => {
+ it('should return list of frequently accessed projects from store', () => {
+ expect(vm.frequentProjects).toBeDefined();
+ expect(vm.frequentProjects.length).toBe(0);
+
+ vm.store.setFrequentProjects([mockProject]);
+ expect(vm.frequentProjects).toBeDefined();
+ expect(vm.frequentProjects.length).toBe(1);
+ });
+ });
+
+ describe('searchProjects', () => {
+ it('should return list of frequently accessed projects from store', () => {
+ expect(vm.searchProjects).toBeDefined();
+ expect(vm.searchProjects.length).toBe(0);
+
+ vm.store.setSearchedProjects([mockRawProject]);
+ expect(vm.searchProjects).toBeDefined();
+ expect(vm.searchProjects.length).toBe(1);
+ });
+ });
+ });
+
+ describe('methods', () => {
+ let vm;
+
+ beforeEach(() => {
+ vm = createComponent();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('toggleFrequentProjectsList', () => {
+ it('should toggle props which control visibility of Frequent Projects list from state passed', () => {
+ vm.toggleFrequentProjectsList(true);
+ expect(vm.isLoadingProjects).toBeFalsy();
+ expect(vm.isSearchListVisible).toBeFalsy();
+ expect(vm.isFrequentsListVisible).toBeTruthy();
+
+ vm.toggleFrequentProjectsList(false);
+ expect(vm.isLoadingProjects).toBeTruthy();
+ expect(vm.isSearchListVisible).toBeTruthy();
+ expect(vm.isFrequentsListVisible).toBeFalsy();
+ });
+ });
+
+ describe('toggleSearchProjectsList', () => {
+ it('should toggle props which control visibility of Searched Projects list from state passed', () => {
+ vm.toggleSearchProjectsList(true);
+ expect(vm.isLoadingProjects).toBeFalsy();
+ expect(vm.isFrequentsListVisible).toBeFalsy();
+ expect(vm.isSearchListVisible).toBeTruthy();
+
+ vm.toggleSearchProjectsList(false);
+ expect(vm.isLoadingProjects).toBeTruthy();
+ expect(vm.isFrequentsListVisible).toBeTruthy();
+ expect(vm.isSearchListVisible).toBeFalsy();
+ });
+ });
+
+ describe('toggleLoader', () => {
+ it('should toggle props which control visibility of list loading animation from state passed', () => {
+ vm.toggleLoader(true);
+ expect(vm.isFrequentsListVisible).toBeFalsy();
+ expect(vm.isSearchListVisible).toBeFalsy();
+ expect(vm.isLoadingProjects).toBeTruthy();
+
+ vm.toggleLoader(false);
+ expect(vm.isFrequentsListVisible).toBeTruthy();
+ expect(vm.isSearchListVisible).toBeTruthy();
+ expect(vm.isLoadingProjects).toBeFalsy();
+ });
+ });
+
+ describe('fetchFrequentProjects', () => {
+ it('should set props for loading animation to `true` while frequent projects list is being loaded', () => {
+ spyOn(vm, 'toggleLoader');
+
+ vm.fetchFrequentProjects();
+ expect(vm.isLocalStorageFailed).toBeFalsy();
+ expect(vm.toggleLoader).toHaveBeenCalledWith(true);
+ });
+
+ it('should set props for loading animation to `false` and props for frequent projects list to `true` once data is loaded', () => {
+ const mockData = [mockProject];
+
+ spyOn(vm.service, 'getFrequentProjects').and.returnValue(mockData);
+ spyOn(vm.store, 'setFrequentProjects');
+ spyOn(vm, 'toggleFrequentProjectsList');
+
+ vm.fetchFrequentProjects();
+ expect(vm.service.getFrequentProjects).toHaveBeenCalled();
+ expect(vm.store.setFrequentProjects).toHaveBeenCalledWith(mockData);
+ expect(vm.toggleFrequentProjectsList).toHaveBeenCalledWith(true);
+ });
+
+ it('should set props for failure message to `true` when method fails to fetch frequent projects list', () => {
+ spyOn(vm.service, 'getFrequentProjects').and.returnValue(null);
+ spyOn(vm.store, 'setFrequentProjects');
+ spyOn(vm, 'toggleFrequentProjectsList');
+
+ expect(vm.isLocalStorageFailed).toBeFalsy();
+
+ vm.fetchFrequentProjects();
+ expect(vm.service.getFrequentProjects).toHaveBeenCalled();
+ expect(vm.store.setFrequentProjects).toHaveBeenCalledWith([]);
+ expect(vm.toggleFrequentProjectsList).toHaveBeenCalledWith(true);
+ expect(vm.isLocalStorageFailed).toBeTruthy();
+ });
+
+ it('should set props for search results list to `true` if search query was already made previously', () => {
+ spyOn(bp, 'getBreakpointSize').and.returnValue('md');
+ spyOn(vm.service, 'getFrequentProjects');
+ spyOn(vm, 'toggleSearchProjectsList');
+
+ vm.searchQuery = 'test';
+ vm.fetchFrequentProjects();
+ expect(vm.service.getFrequentProjects).not.toHaveBeenCalled();
+ expect(vm.toggleSearchProjectsList).toHaveBeenCalledWith(true);
+ });
+
+ it('should set props for frequent projects list to `true` if search query was already made but screen size is less than 768px', () => {
+ spyOn(bp, 'getBreakpointSize').and.returnValue('sm');
+ spyOn(vm, 'toggleSearchProjectsList');
+ spyOn(vm.service, 'getFrequentProjects');
+
+ vm.searchQuery = 'test';
+ vm.fetchFrequentProjects();
+ expect(vm.service.getFrequentProjects).toHaveBeenCalled();
+ expect(vm.toggleSearchProjectsList).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('fetchSearchedProjects', () => {
+ const searchQuery = 'test';
+
+ it('should perform search with provided search query', (done) => {
+ const mockData = [mockRawProject];
+ spyOn(vm, 'toggleLoader');
+ spyOn(vm, 'toggleSearchProjectsList');
+ spyOn(vm.service, 'getSearchedProjects').and.returnValue(returnServicePromise(mockData));
+ spyOn(vm.store, 'setSearchedProjects');
+
+ vm.fetchSearchedProjects(searchQuery);
+ setTimeout(() => {
+ expect(vm.searchQuery).toBe(searchQuery);
+ expect(vm.toggleLoader).toHaveBeenCalledWith(true);
+ expect(vm.service.getSearchedProjects).toHaveBeenCalledWith(searchQuery);
+ expect(vm.toggleSearchProjectsList).toHaveBeenCalledWith(true);
+ expect(vm.store.setSearchedProjects).toHaveBeenCalledWith(mockData);
+ done();
+ }, 0);
+ });
+
+ it('should update props for showing search failure', (done) => {
+ spyOn(vm, 'toggleSearchProjectsList');
+ spyOn(vm.service, 'getSearchedProjects').and.returnValue(returnServicePromise({}, true));
+
+ vm.fetchSearchedProjects(searchQuery);
+ setTimeout(() => {
+ expect(vm.searchQuery).toBe(searchQuery);
+ expect(vm.service.getSearchedProjects).toHaveBeenCalledWith(searchQuery);
+ expect(vm.isSearchFailed).toBeTruthy();
+ expect(vm.toggleSearchProjectsList).toHaveBeenCalledWith(true);
+ done();
+ }, 0);
+ });
+ });
+
+ describe('logCurrentProjectAccess', () => {
+ it('should log current project access via service', (done) => {
+ spyOn(vm.service, 'logProjectAccess');
+
+ vm.currentProject = mockProject;
+ vm.logCurrentProjectAccess();
+
+ setTimeout(() => {
+ expect(vm.service.logProjectAccess).toHaveBeenCalledWith(mockProject);
+ done();
+ }, 1);
+ });
+ });
+
+ describe('handleSearchClear', () => {
+ it('should show frequent projects list when search input is cleared', () => {
+ spyOn(vm.store, 'clearSearchedProjects');
+ spyOn(vm, 'toggleFrequentProjectsList');
+
+ vm.handleSearchClear();
+
+ expect(vm.toggleFrequentProjectsList).toHaveBeenCalledWith(true);
+ expect(vm.store.clearSearchedProjects).toHaveBeenCalled();
+ expect(vm.searchQuery).toBe('');
+ });
+ });
+
+ describe('handleSearchFailure', () => {
+ it('should show failure message within dropdown', () => {
+ spyOn(vm, 'toggleSearchProjectsList');
+
+ vm.handleSearchFailure();
+ expect(vm.toggleSearchProjectsList).toHaveBeenCalledWith(true);
+ expect(vm.isSearchFailed).toBeTruthy();
+ });
+ });
+ });
+
+ describe('created', () => {
+ it('should bind event listeners on eventHub', (done) => {
+ spyOn(eventHub, '$on');
+
+ createComponent().$mount();
+
+ Vue.nextTick(() => {
+ expect(eventHub.$on).toHaveBeenCalledWith('dropdownOpen', jasmine.any(Function));
+ expect(eventHub.$on).toHaveBeenCalledWith('searchProjects', jasmine.any(Function));
+ expect(eventHub.$on).toHaveBeenCalledWith('searchCleared', jasmine.any(Function));
+ expect(eventHub.$on).toHaveBeenCalledWith('searchFailed', jasmine.any(Function));
+ done();
+ });
+ });
+ });
+
+ describe('beforeDestroy', () => {
+ it('should unbind event listeners on eventHub', (done) => {
+ const vm = createComponent();
+ spyOn(eventHub, '$off');
+
+ vm.$mount();
+ vm.$destroy();
+
+ Vue.nextTick(() => {
+ expect(eventHub.$off).toHaveBeenCalledWith('dropdownOpen', jasmine.any(Function));
+ expect(eventHub.$off).toHaveBeenCalledWith('searchProjects', jasmine.any(Function));
+ expect(eventHub.$off).toHaveBeenCalledWith('searchCleared', jasmine.any(Function));
+ expect(eventHub.$off).toHaveBeenCalledWith('searchFailed', jasmine.any(Function));
+ done();
+ });
+ });
+ });
+
+ describe('template', () => {
+ let vm;
+
+ beforeEach(() => {
+ vm = createComponent();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('should render search input', () => {
+ expect(vm.$el.querySelector('.search-input-container')).toBeDefined();
+ });
+
+ it('should render loading animation', (done) => {
+ vm.toggleLoader(true);
+ Vue.nextTick(() => {
+ const loadingEl = vm.$el.querySelector('.loading-animation');
+
+ expect(loadingEl).toBeDefined();
+ expect(loadingEl.classList.contains('prepend-top-20')).toBeTruthy();
+ expect(loadingEl.querySelector('i').getAttribute('aria-label')).toBe('Loading projects');
+ done();
+ });
+ });
+
+ it('should render frequent projects list header', (done) => {
+ vm.toggleFrequentProjectsList(true);
+ 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) => {
+ vm.toggleFrequentProjectsList(true);
+ Vue.nextTick(() => {
+ expect(vm.$el.querySelector('.projects-list-frequent-container')).toBeDefined();
+ done();
+ });
+ });
+
+ it('should render searched projects list', (done) => {
+ vm.toggleSearchProjectsList(true);
+ Vue.nextTick(() => {
+ expect(vm.$el.querySelector('.section-header')).toBe(null);
+ expect(vm.$el.querySelector('.projects-list-search-container')).toBeDefined();
+ done();
+ });
+ });
+ });
+});