debian-mirror-gitlab/spec/frontend/frequent_items/components/app_spec.js

253 lines
7.9 KiB
JavaScript
Raw Normal View History

2018-11-08 19:23:39 +05:30
import MockAdapter from 'axios-mock-adapter';
import Vue from 'vue';
2020-05-24 23:13:21 +05:30
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
2020-10-24 23:57:45 +05:30
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import waitForPromises from 'helpers/wait_for_promises';
2020-01-01 13:55:28 +05:30
import axios from '~/lib/utils/axios_utils';
2018-11-08 19:23:39 +05:30
import appComponent from '~/frequent_items/components/app.vue';
import eventHub from '~/frequent_items/event_hub';
import { FREQUENT_ITEMS, HOUR_IN_MS } from '~/frequent_items/constants';
import { getTopFrequentItems } from '~/frequent_items/utils';
import { currentSession, mockFrequentProjects, mockSearchedProjects } from '../mock_data';
2021-02-22 17:27:13 +05:30
import { createStore } from '~/frequent_items/store';
2020-05-24 23:13:21 +05:30
useLocalStorageSpy();
2018-11-08 19:23:39 +05:30
let session;
const createComponentWithStore = (namespace = 'projects') => {
session = currentSession[namespace];
gon.api_version = session.apiVersion;
const Component = Vue.extend(appComponent);
2021-02-22 17:27:13 +05:30
const store = createStore();
2018-11-08 19:23:39 +05:30
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', () => {
2020-05-24 23:13:21 +05:30
jest.spyOn(vm, 'fetchFrequentItems').mockImplementation(() => {});
2018-11-08 19:23:39 +05:30
vm.dropdownOpenHandler();
expect(vm.fetchFrequentItems).toHaveBeenCalledWith();
});
});
describe('logItemAccess', () => {
let storage;
beforeEach(() => {
storage = {};
2020-05-24 23:13:21 +05:30
localStorage.setItem.mockImplementation((storageKey, value) => {
2018-11-08 19:23:39 +05:30
storage[storageKey] = value;
});
2020-05-24 23:13:21 +05:30
localStorage.getItem.mockImplementation(storageKey => {
2018-11-08 19:23:39 +05:30
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 => {
2020-05-24 23:13:21 +05:30
jest.spyOn(eventHub, '$on').mockImplementation(() => {});
2018-11-08 19:23:39 +05:30
createComponentWithStore().$mount();
Vue.nextTick(() => {
2020-05-24 23:13:21 +05:30
expect(eventHub.$on).toHaveBeenCalledWith('projects-dropdownOpen', expect.any(Function));
2018-11-08 19:23:39 +05:30
done();
});
});
});
describe('beforeDestroy', () => {
it('should unbind event listeners on eventHub', done => {
2020-05-24 23:13:21 +05:30
jest.spyOn(eventHub, '$off').mockImplementation(() => {});
2018-11-08 19:23:39 +05:30
vm.$mount();
vm.$destroy();
Vue.nextTick(() => {
2020-05-24 23:13:21 +05:30
expect(eventHub.$off).toHaveBeenCalledWith('projects-dropdownOpen', expect.any(Function));
2018-11-08 19:23:39 +05:30
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);
2019-07-07 11:18:12 +05:30
expect(loadingEl.querySelector('span').getAttribute('aria-label')).toBe('Loading projects');
2018-11-08 19:23:39 +05:30
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);
2020-05-24 23:13:21 +05:30
localStorage.getItem.mockImplementation(() => JSON.stringify(mockFrequentProjects));
2018-11-08 19:23:39 +05:30
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');
2018-12-13 13:39:08 +05:30
vm.$nextTick()
2018-11-08 19:23:39 +05:30
.then(() => {
expect(vm.$el.querySelector('.loading-animation')).toBeDefined();
})
2020-05-24 23:13:21 +05:30
.then(waitForPromises)
2018-11-08 19:23:39 +05:30
.then(() => {
expect(vm.$el.querySelectorAll('.frequent-items-list-container li').length).toBe(
2019-12-26 22:10:19 +05:30
mockSearchedProjects.data.length,
2018-11-08 19:23:39 +05:30
);
})
.then(done)
.catch(done.fail);
});
});
});