349 lines
12 KiB
JavaScript
349 lines
12 KiB
JavaScript
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 'spec/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();
|
|
});
|
|
});
|
|
});
|
|
});
|