зеркало из https://github.com/nextcloud/spreed.git
JS tests for LeftSidebar
Signed-off-by: Vincent Petry <vincent@nextcloud.com>
This commit is contained in:
Родитель
31c0dae2ae
Коммит
f36ad0b63a
|
@ -25,7 +25,7 @@ module.exports = {
|
|||
// Allow tests in the src and in tests/unit folders
|
||||
testMatch: ['<rootDir>/src/**/*.(spec|test).(ts|js)'],
|
||||
transformIgnorePatterns: [
|
||||
'node_modules/(?!(vue-material-design-icons|@juliushaertl)/)',
|
||||
'node_modules/(?!(vue-material-design-icons|@juliushaertl|tributejs)/)',
|
||||
],
|
||||
resetMocks: false,
|
||||
setupFiles: ['jest-localstorage-mock'],
|
||||
|
|
|
@ -0,0 +1,680 @@
|
|||
import Vuex from 'vuex'
|
||||
import { createLocalVue, mount } from '@vue/test-utils'
|
||||
import VueRouter from 'vue-router'
|
||||
import router from '../../router/router'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import storeConfig from '../../store/storeConfig'
|
||||
import { loadState } from '@nextcloud/initial-state'
|
||||
import { EventBus } from '../../services/EventBus'
|
||||
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
|
||||
import {
|
||||
searchPossibleConversations,
|
||||
searchListedConversations,
|
||||
} from '../../services/conversationsService'
|
||||
|
||||
import LeftSidebar from './LeftSidebar'
|
||||
|
||||
jest.mock('@nextcloud/initial-state', () => ({
|
||||
loadState: jest.fn(),
|
||||
}))
|
||||
jest.mock('../../services/conversationsService', () => ({
|
||||
searchPossibleConversations: jest.fn(),
|
||||
searchListedConversations: jest.fn(),
|
||||
}))
|
||||
|
||||
// short-circuit debounce
|
||||
jest.mock('debounce', () => jest.fn().mockImplementation(fn => fn))
|
||||
|
||||
describe('LeftSidebar.vue', () => {
|
||||
let store
|
||||
let localVue
|
||||
let testStoreConfig
|
||||
let loadStateSettings
|
||||
let conversationsListMock
|
||||
let fetchConversationsAction
|
||||
let addConversationAction
|
||||
let createOneToOneConversationAction
|
||||
|
||||
function mountComponent() {
|
||||
return mount(LeftSidebar, {
|
||||
localVue,
|
||||
router,
|
||||
store,
|
||||
stubs: {
|
||||
// to prevent user status fetching
|
||||
Avatar: true,
|
||||
// to prevent complex dialog logic
|
||||
NewGroupConversation: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers()
|
||||
|
||||
localVue = createLocalVue()
|
||||
localVue.use(Vuex)
|
||||
localVue.use(VueRouter)
|
||||
|
||||
loadStateSettings = {
|
||||
circles_enabled: true,
|
||||
start_conversations: true,
|
||||
}
|
||||
|
||||
loadState.mockImplementation((app, key) => {
|
||||
if (app === 'spreed') {
|
||||
return loadStateSettings[key]
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
testStoreConfig = cloneDeep(storeConfig)
|
||||
|
||||
// note: need a copy because the Vue modifies it when sorting
|
||||
conversationsListMock = jest.fn()
|
||||
fetchConversationsAction = jest.fn()
|
||||
addConversationAction = jest.fn()
|
||||
createOneToOneConversationAction = jest.fn()
|
||||
const getUserIdMock = jest.fn().mockReturnValue('current-user')
|
||||
testStoreConfig.modules.actorStore.getters.getUserId = () => getUserIdMock
|
||||
testStoreConfig.modules.conversationsStore.getters.conversationsList = conversationsListMock
|
||||
testStoreConfig.modules.conversationsStore.actions.fetchConversations = fetchConversationsAction
|
||||
testStoreConfig.modules.conversationsStore.actions.addConversation = addConversationAction
|
||||
testStoreConfig.modules.conversationsStore.actions.createOneToOneConversation = createOneToOneConversationAction
|
||||
|
||||
store = new Vuex.Store(testStoreConfig)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
describe('conversation list', () => {
|
||||
let conversationsList
|
||||
|
||||
beforeEach(() => {
|
||||
conversationsList = [{
|
||||
id: 100,
|
||||
lastActivity: 100,
|
||||
isFavorite: false,
|
||||
name: 'one',
|
||||
displayName: 'one',
|
||||
}, {
|
||||
id: 200,
|
||||
lastActivity: 80,
|
||||
isFavorite: false,
|
||||
name: 'two',
|
||||
displayName: 'two',
|
||||
}, {
|
||||
id: 300,
|
||||
lastActivity: 120,
|
||||
isFavorite: true,
|
||||
name: 'three',
|
||||
displayName: 'three',
|
||||
}]
|
||||
|
||||
// note: need a copy because the Vue modifies it when sorting
|
||||
conversationsListMock.mockImplementation(() => cloneDeep(conversationsList))
|
||||
})
|
||||
|
||||
test('fetches and renders conversation list initially', async() => {
|
||||
const conversationsReceivedEvent = jest.fn()
|
||||
EventBus.$once('conversationsReceived', conversationsReceivedEvent)
|
||||
fetchConversationsAction.mockResolvedValueOnce()
|
||||
|
||||
const wrapper = mountComponent()
|
||||
|
||||
expect(fetchConversationsAction).toHaveBeenCalledWith(expect.anything(), undefined)
|
||||
expect(conversationsListMock).toHaveBeenCalled()
|
||||
|
||||
const appNavEl = wrapper.findComponent({ name: 'AppNavigation' })
|
||||
const listEl = appNavEl.findComponent({ name: 'ConversationsList' })
|
||||
|
||||
expect(listEl.exists()).toBe(true)
|
||||
expect(listEl.props('searchText')).toBe('')
|
||||
expect(listEl.props('initialisedConversations')).toBe(false)
|
||||
|
||||
expect(conversationsReceivedEvent).not.toHaveBeenCalled()
|
||||
|
||||
// move on past the fetchConversation call
|
||||
await wrapper.vm.$nextTick()
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(listEl.props('initialisedConversations')).toBe(true)
|
||||
expect(listEl.props('conversationsList')).toStrictEqual([
|
||||
conversationsList[2],
|
||||
conversationsList[0],
|
||||
conversationsList[1],
|
||||
])
|
||||
|
||||
expect(conversationsReceivedEvent).toHaveBeenCalledWith({
|
||||
singleConversation: false,
|
||||
})
|
||||
})
|
||||
|
||||
test('re-fetches conversations every 30 seconds', async() => {
|
||||
const wrapper = mountComponent()
|
||||
|
||||
expect(fetchConversationsAction).toHaveBeenCalled()
|
||||
|
||||
fetchConversationsAction.mockClear()
|
||||
|
||||
// move past async call
|
||||
await wrapper.vm.$nextTick()
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(fetchConversationsAction).not.toHaveBeenCalled()
|
||||
|
||||
jest.advanceTimersByTime(15000)
|
||||
|
||||
expect(fetchConversationsAction).not.toHaveBeenCalled()
|
||||
|
||||
jest.advanceTimersByTime(20000)
|
||||
|
||||
expect(fetchConversationsAction).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test('re-fetches conversations when receiving bus event', async() => {
|
||||
const wrapper = mountComponent()
|
||||
|
||||
expect(fetchConversationsAction).toHaveBeenCalled()
|
||||
|
||||
fetchConversationsAction.mockClear()
|
||||
|
||||
// move past async call
|
||||
await wrapper.vm.$nextTick()
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(fetchConversationsAction).not.toHaveBeenCalled()
|
||||
|
||||
EventBus.$emit('shouldRefreshConversations')
|
||||
|
||||
// note: debounce was short-circuited so no delay needed
|
||||
expect(fetchConversationsAction).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe('search results', () => {
|
||||
let listedResults
|
||||
let usersResults
|
||||
let groupsResults
|
||||
let circlesResults
|
||||
let conversationsList
|
||||
|
||||
beforeEach(() => {
|
||||
conversationsList = [{
|
||||
id: 100,
|
||||
lastActivity: 100,
|
||||
isFavorite: false,
|
||||
name: 'one',
|
||||
displayName: 'the searched one by display name',
|
||||
lastMessage: {},
|
||||
}, {
|
||||
id: 200,
|
||||
lastActivity: 80,
|
||||
isFavorite: false,
|
||||
name: 'searched by name',
|
||||
displayName: 'another one',
|
||||
lastMessage: {},
|
||||
}, {
|
||||
id: 300,
|
||||
lastActivity: 120,
|
||||
isFavorite: true,
|
||||
name: 'excluded',
|
||||
displayName: 'excluded from results',
|
||||
lastMessage: {},
|
||||
}]
|
||||
|
||||
listedResults = [{
|
||||
id: 1000,
|
||||
name: 'listed one searched',
|
||||
displayName: 'listed one searched',
|
||||
lastMessage: {},
|
||||
token: 'listed-token-1',
|
||||
}, {
|
||||
id: 1001,
|
||||
name: 'listed two searched',
|
||||
displayName: 'listed two searched',
|
||||
lastMessage: {},
|
||||
token: 'listed-token-2',
|
||||
}]
|
||||
usersResults = [{
|
||||
id: 'current-user',
|
||||
label: 'Current User searched',
|
||||
source: 'users',
|
||||
}, {
|
||||
id: 'one-user',
|
||||
label: 'One user searched',
|
||||
source: 'users',
|
||||
}, {
|
||||
id: 'two-user',
|
||||
label: 'Two user searched',
|
||||
source: 'users',
|
||||
}]
|
||||
groupsResults = [{
|
||||
id: 'one-group',
|
||||
label: 'One group searched',
|
||||
source: 'groups',
|
||||
}, {
|
||||
id: 'two-group',
|
||||
label: 'Two group searched',
|
||||
source: 'groups',
|
||||
}]
|
||||
circlesResults = [{
|
||||
id: 'one-circle',
|
||||
label: 'One circle searched',
|
||||
source: 'circles',
|
||||
}, {
|
||||
id: 'two-circle',
|
||||
label: 'Two circle searched',
|
||||
source: 'circles',
|
||||
}]
|
||||
|
||||
// note: need a copy because the Vue modifies it when sorting
|
||||
conversationsListMock.mockImplementation(() => cloneDeep(conversationsList))
|
||||
fetchConversationsAction.mockResolvedValue()
|
||||
})
|
||||
|
||||
async function testSearch(searchTerm, possibleResults, listedResults, loadStateSettingsOverride) {
|
||||
searchPossibleConversations.mockResolvedValueOnce({
|
||||
data: {
|
||||
ocs: {
|
||||
data: possibleResults,
|
||||
},
|
||||
},
|
||||
})
|
||||
searchListedConversations.mockResolvedValueOnce({
|
||||
data: {
|
||||
ocs: {
|
||||
data: listedResults,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if (loadStateSettingsOverride) {
|
||||
loadStateSettings = loadStateSettingsOverride
|
||||
}
|
||||
|
||||
const wrapper = mountComponent()
|
||||
|
||||
expect(fetchConversationsAction).toHaveBeenCalledWith(expect.anything(), undefined)
|
||||
expect(conversationsListMock).toHaveBeenCalled()
|
||||
|
||||
const appNavEl = wrapper.findComponent({ name: 'AppNavigation' })
|
||||
const searchBoxEl = appNavEl.findComponent({ name: 'SearchBox' })
|
||||
expect(searchBoxEl.exists()).toBe(true)
|
||||
|
||||
// move past async call
|
||||
await wrapper.vm.$nextTick()
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
await searchBoxEl.find('input[type="text"]').setValue(searchTerm)
|
||||
expect(searchBoxEl.props('isSearching')).toBe(true)
|
||||
|
||||
await wrapper.vm.$nextTick()
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
return wrapper
|
||||
}
|
||||
|
||||
describe('displaying search results', () => {
|
||||
test('displays search results when search is active', async() => {
|
||||
const wrapper = await testSearch(
|
||||
'search',
|
||||
[...usersResults, ...groupsResults, ...circlesResults],
|
||||
listedResults,
|
||||
{
|
||||
circles_enabled: true,
|
||||
start_conversations: true,
|
||||
}
|
||||
)
|
||||
|
||||
const appNavEl = wrapper.findComponent({ name: 'AppNavigation' })
|
||||
const listEl = appNavEl.findComponent({ name: 'ConversationsList' })
|
||||
|
||||
expect(listEl.exists()).toBe(true)
|
||||
expect(listEl.props('conversationsList')).toStrictEqual([
|
||||
conversationsList[0],
|
||||
conversationsList[1],
|
||||
])
|
||||
|
||||
const listedEls = appNavEl.findAllComponents({ name: 'Conversation' })
|
||||
expect(listedEls.exists()).toBe(true)
|
||||
expect(listedEls.length).toBe(4)
|
||||
expect(listedEls.at(0).props('item')).toStrictEqual(conversationsList[0])
|
||||
expect(listedEls.at(1).props('item')).toStrictEqual(conversationsList[1])
|
||||
expect(listedEls.at(2).props('item')).toStrictEqual(listedResults[0])
|
||||
expect(listedEls.at(3).props('item')).toStrictEqual(listedResults[1])
|
||||
|
||||
const optionsEls = appNavEl.findAllComponents({ name: 'ConversationsOptionsList' })
|
||||
expect(optionsEls.exists()).toBe(true)
|
||||
expect(optionsEls.length).toBe(3)
|
||||
expect(optionsEls.at(0).props('items')).toStrictEqual([usersResults[1], usersResults[2]])
|
||||
expect(optionsEls.at(1).props('items')).toStrictEqual([groupsResults[0], groupsResults[1]])
|
||||
expect(optionsEls.at(2).props('items')).toStrictEqual([circlesResults[0], circlesResults[1]])
|
||||
})
|
||||
test('only shows user search results when cannot create conversations', async() => {
|
||||
const wrapper = await testSearch(
|
||||
'search',
|
||||
[...usersResults, ...groupsResults, ...circlesResults],
|
||||
listedResults,
|
||||
{
|
||||
circles_enabled: true,
|
||||
start_conversations: false,
|
||||
}
|
||||
)
|
||||
|
||||
const appNavEl = wrapper.findComponent({ name: 'AppNavigation' })
|
||||
const listEl = appNavEl.findComponent({ name: 'ConversationsList' })
|
||||
|
||||
expect(listEl.exists()).toBe(true)
|
||||
expect(listEl.props('conversationsList')).toStrictEqual([
|
||||
conversationsList[0],
|
||||
conversationsList[1],
|
||||
])
|
||||
|
||||
const listedEls = appNavEl.findAllComponents({ name: 'Conversation' })
|
||||
expect(listedEls.exists()).toBe(true)
|
||||
expect(listedEls.length).toBe(4)
|
||||
expect(listedEls.at(0).props('item')).toStrictEqual(conversationsList[0])
|
||||
expect(listedEls.at(1).props('item')).toStrictEqual(conversationsList[1])
|
||||
expect(listedEls.at(2).props('item')).toStrictEqual(listedResults[0])
|
||||
expect(listedEls.at(3).props('item')).toStrictEqual(listedResults[1])
|
||||
|
||||
const optionsEls = appNavEl.findAllComponents({ name: 'ConversationsOptionsList' })
|
||||
expect(optionsEls.exists()).toBe(true)
|
||||
expect(optionsEls.at(0).props('items')).toStrictEqual([usersResults[1], usersResults[2]])
|
||||
expect(optionsEls.length).toBe(1)
|
||||
})
|
||||
test('does not show circles results when circles are disabled', async() => {
|
||||
const wrapper = await testSearch(
|
||||
'search',
|
||||
[...usersResults, ...groupsResults],
|
||||
listedResults,
|
||||
{
|
||||
circles_enabled: false,
|
||||
start_conversations: true,
|
||||
}
|
||||
)
|
||||
|
||||
const appNavEl = wrapper.findComponent({ name: 'AppNavigation' })
|
||||
const listEl = appNavEl.findComponent({ name: 'ConversationsList' })
|
||||
|
||||
expect(listEl.exists()).toBe(true)
|
||||
expect(listEl.props('conversationsList')).toStrictEqual([
|
||||
conversationsList[0],
|
||||
conversationsList[1],
|
||||
])
|
||||
|
||||
const listedEls = appNavEl.findAllComponents({ name: 'Conversation' })
|
||||
expect(listedEls.exists()).toBe(true)
|
||||
expect(listedEls.length).toBe(4)
|
||||
expect(listedEls.at(0).props('item')).toStrictEqual(conversationsList[0])
|
||||
expect(listedEls.at(1).props('item')).toStrictEqual(conversationsList[1])
|
||||
expect(listedEls.at(2).props('item')).toStrictEqual(listedResults[0])
|
||||
expect(listedEls.at(3).props('item')).toStrictEqual(listedResults[1])
|
||||
|
||||
const optionsEls = appNavEl.findAllComponents({ name: 'ConversationsOptionsList' })
|
||||
expect(optionsEls.exists()).toBe(true)
|
||||
expect(optionsEls.length).toBe(2)
|
||||
expect(optionsEls.at(0).props('items')).toStrictEqual([usersResults[1], usersResults[2]])
|
||||
expect(optionsEls.at(1).props('items')).toStrictEqual([groupsResults[0], groupsResults[1]])
|
||||
})
|
||||
})
|
||||
|
||||
describe('not found caption', () => {
|
||||
async function testSearchNotFound(searchTerm, possibleResults, listedResults, loadStateSettingsOverride, expectedCaption) {
|
||||
const wrapper = await testSearch(searchTerm, possibleResults, listedResults, loadStateSettingsOverride)
|
||||
|
||||
const appNavEl = wrapper.findComponent({ name: 'AppNavigation' })
|
||||
const listEl = appNavEl.findComponent({ name: 'ConversationsList' })
|
||||
expect(listEl.exists()).toBe(true)
|
||||
const listedEls = appNavEl.findAllComponents({ name: 'Conversation' })
|
||||
expect(listedEls.exists()).toBe(true)
|
||||
expect(listedEls.length).toBe(2)
|
||||
// only filters the existing conversations in the list
|
||||
expect(listedEls.at(0).props('item')).toStrictEqual(conversationsList[0])
|
||||
expect(listedEls.at(1).props('item')).toStrictEqual(conversationsList[1])
|
||||
|
||||
const captionsEls = appNavEl.findAllComponents({ name: 'Caption' })
|
||||
expect(captionsEls.exists()).toBe(true)
|
||||
expect(captionsEls.length).toBeGreaterThan(1)
|
||||
expect(captionsEls.at(0).props('title')).toBe('Conversations')
|
||||
// last dynamic caption for "No search results"
|
||||
expect(captionsEls.at(captionsEls.length - 1).props('title')).toBe(expectedCaption)
|
||||
|
||||
return wrapper
|
||||
}
|
||||
|
||||
test('displays all types in caption when nothing was found', async() => {
|
||||
await testSearchNotFound(
|
||||
'search',
|
||||
[],
|
||||
[],
|
||||
{
|
||||
circles_enabled: true,
|
||||
start_conversations: true,
|
||||
},
|
||||
'Users, groups and circles'
|
||||
)
|
||||
})
|
||||
|
||||
test('displays all types minus circles when nothing was found but circles is disabled', async() => {
|
||||
await testSearchNotFound(
|
||||
'search',
|
||||
[],
|
||||
[],
|
||||
{
|
||||
circles_enabled: false,
|
||||
start_conversations: true,
|
||||
},
|
||||
'Users and groups'
|
||||
)
|
||||
})
|
||||
|
||||
test('displays caption for users and groups not found', async() => {
|
||||
await testSearchNotFound(
|
||||
'search',
|
||||
[...circlesResults],
|
||||
[],
|
||||
{
|
||||
circles_enabled: true,
|
||||
start_conversations: true,
|
||||
},
|
||||
'Users and groups'
|
||||
)
|
||||
})
|
||||
test('displays caption for users not found', async() => {
|
||||
await testSearchNotFound(
|
||||
'search',
|
||||
[...circlesResults, ...groupsResults],
|
||||
[],
|
||||
{
|
||||
circles_enabled: true,
|
||||
start_conversations: true,
|
||||
},
|
||||
'Users'
|
||||
)
|
||||
})
|
||||
test('displays caption for groups not found', async() => {
|
||||
await testSearchNotFound(
|
||||
'search',
|
||||
[...usersResults, ...circlesResults],
|
||||
[],
|
||||
{
|
||||
circles_enabled: true,
|
||||
start_conversations: true,
|
||||
},
|
||||
'Groups'
|
||||
)
|
||||
})
|
||||
test('displays caption for groups and circles not found', async() => {
|
||||
await testSearchNotFound(
|
||||
'search',
|
||||
[...usersResults],
|
||||
[],
|
||||
{
|
||||
circles_enabled: true,
|
||||
start_conversations: true,
|
||||
},
|
||||
'Groups and circles'
|
||||
)
|
||||
})
|
||||
test('displays caption for users and circles not found', async() => {
|
||||
await testSearchNotFound(
|
||||
'search',
|
||||
[...groupsResults],
|
||||
[],
|
||||
{
|
||||
circles_enabled: true,
|
||||
start_conversations: true,
|
||||
},
|
||||
'Users and circles'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('clicking search results', () => {
|
||||
test('joins listed conversation from search result', async() => {
|
||||
const wrapper = await testSearch('search', [], listedResults)
|
||||
|
||||
const appNavEl = wrapper.findComponent({ name: 'AppNavigation' })
|
||||
const listedEls = appNavEl.findAllComponents({ name: 'Conversation' })
|
||||
expect(listedEls.exists()).toBe(true)
|
||||
expect(listedEls.length).toBe(4)
|
||||
await listedEls.at(3).find('a').trigger('click')
|
||||
|
||||
expect(addConversationAction).toHaveBeenCalledWith(expect.anything(), listedResults[1])
|
||||
expect(wrapper.vm.$route.name).toBe('conversation')
|
||||
expect(wrapper.vm.$route.params).toStrictEqual({ token: 'listed-token-2' })
|
||||
})
|
||||
test('creates one to one conversation from user search result', async() => {
|
||||
createOneToOneConversationAction.mockResolvedValue({
|
||||
id: 9999,
|
||||
token: 'new-conversation',
|
||||
})
|
||||
|
||||
const wrapper = await testSearch('search', [...usersResults], [])
|
||||
|
||||
const appNavEl = wrapper.findComponent({ name: 'AppNavigation' })
|
||||
const optionsEls = appNavEl.findAllComponents({ name: 'ConversationsOptionsList' })
|
||||
expect(optionsEls.exists()).toBe(true)
|
||||
await optionsEls.at(0).findAll('a').at(1).trigger('click')
|
||||
|
||||
expect(createOneToOneConversationAction).toHaveBeenCalledWith(expect.anything(), 'two-user')
|
||||
expect(wrapper.vm.$route.name).toBe('conversation')
|
||||
expect(wrapper.vm.$route.params).toStrictEqual({ token: 'new-conversation' })
|
||||
})
|
||||
test('shows group conversation dialog when clicking search result', async() => {
|
||||
const eventHandler = jest.fn()
|
||||
EventBus.$once('NewGroupConversationDialog', eventHandler)
|
||||
|
||||
const wrapper = await testSearch('search', [...groupsResults], [])
|
||||
|
||||
const appNavEl = wrapper.findComponent({ name: 'AppNavigation' })
|
||||
const optionsEls = appNavEl.findAllComponents({ name: 'ConversationsOptionsList' })
|
||||
expect(optionsEls.exists()).toBe(true)
|
||||
await optionsEls.at(0).findAll('a').at(1).trigger('click')
|
||||
|
||||
expect(eventHandler).toHaveBeenCalledWith(groupsResults[1])
|
||||
|
||||
// nothing created yet
|
||||
expect(createOneToOneConversationAction).not.toHaveBeenCalled()
|
||||
expect(addConversationAction).not.toHaveBeenCalled()
|
||||
})
|
||||
test('shows circles conversation dialog when clicking search result', async() => {
|
||||
const eventHandler = jest.fn()
|
||||
EventBus.$once('NewGroupConversationDialog', eventHandler)
|
||||
|
||||
const wrapper = await testSearch('search', [...circlesResults], [])
|
||||
|
||||
const appNavEl = wrapper.findComponent({ name: 'AppNavigation' })
|
||||
const optionsEls = appNavEl.findAllComponents({ name: 'ConversationsOptionsList' })
|
||||
expect(optionsEls.exists()).toBe(true)
|
||||
await optionsEls.at(0).findAll('a').at(1).trigger('click')
|
||||
|
||||
expect(eventHandler).toHaveBeenCalledWith(circlesResults[1])
|
||||
|
||||
// nothing created yet
|
||||
expect(createOneToOneConversationAction).not.toHaveBeenCalled()
|
||||
})
|
||||
test('clears search results when joining user chat', async() => {
|
||||
createOneToOneConversationAction.mockResolvedValue({
|
||||
id: 9999,
|
||||
token: 'new-conversation',
|
||||
})
|
||||
|
||||
const wrapper = await testSearch('search', [...usersResults], [])
|
||||
|
||||
const appNavEl = wrapper.findComponent({ name: 'AppNavigation' })
|
||||
const searchBoxEl = appNavEl.findComponent({ name: 'SearchBox' })
|
||||
const input = searchBoxEl.find('input[type="text"]')
|
||||
expect(input.element.value).toBe('search')
|
||||
|
||||
const optionsEls = appNavEl.findAllComponents({ name: 'ConversationsOptionsList' })
|
||||
expect(optionsEls.exists()).toBe(true)
|
||||
await optionsEls.at(0).findAll('a').at(1).trigger('click')
|
||||
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(searchBoxEl.exists()).toBe(true)
|
||||
expect(input.element.value).toBe('')
|
||||
})
|
||||
test('does not clear search results when clicking group chat', async() => {
|
||||
const wrapper = await testSearch('search', [...groupsResults], [])
|
||||
|
||||
const appNavEl = wrapper.findComponent({ name: 'AppNavigation' })
|
||||
const searchBoxEl = appNavEl.findComponent({ name: 'SearchBox' })
|
||||
const input = searchBoxEl.find('input[type="text"]')
|
||||
expect(input.element.value).toBe('search')
|
||||
|
||||
const optionsEls = appNavEl.findAllComponents({ name: 'ConversationsOptionsList' })
|
||||
expect(optionsEls.exists()).toBe(true)
|
||||
await optionsEls.at(0).findAll('a').at(1).trigger('click')
|
||||
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(searchBoxEl.exists()).toBe(true)
|
||||
expect(input.element.value).toBe('search')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('new conversation button', () => {
|
||||
beforeEach(() => {
|
||||
conversationsListMock.mockReturnValue([])
|
||||
fetchConversationsAction.mockResolvedValueOnce()
|
||||
})
|
||||
test('shows new conversation button if user can start conversations', () => {
|
||||
loadStateSettings.start_conversations = true
|
||||
|
||||
const wrapper = mountComponent()
|
||||
const buttonEl = wrapper.findComponent({ name: 'NewGroupConversation' })
|
||||
expect(buttonEl.exists()).toBe(true)
|
||||
})
|
||||
test('does not show new conversation button if user cannot start conversations', () => {
|
||||
loadStateSettings.start_conversations = false
|
||||
|
||||
const wrapper = mountComponent()
|
||||
const buttonEl = wrapper.findComponent({ name: 'NewGroupConversation' })
|
||||
expect(buttonEl.exists()).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
test('shows settings when clicking the settings button', async() => {
|
||||
conversationsListMock.mockImplementation(() => [])
|
||||
const eventHandler = jest.fn()
|
||||
subscribe('show-settings', eventHandler)
|
||||
const wrapper = mountComponent()
|
||||
|
||||
const appNavEl = wrapper.findComponent({ name: 'AppNavigation' })
|
||||
const button = appNavEl.find('.settings-button')
|
||||
expect(button.exists()).toBe(true)
|
||||
|
||||
await button.trigger('click')
|
||||
|
||||
unsubscribe('show-settings', eventHandler)
|
||||
|
||||
expect(eventHandler).toHaveBeenCalled()
|
||||
})
|
||||
})
|
|
@ -174,8 +174,9 @@ export default {
|
|||
initialisedConversations: false,
|
||||
cancelSearchPossibleConversations: () => {},
|
||||
cancelSearchListedConversations: () => {},
|
||||
// Keeps track of wheteher the conversation list is scrolled to the top or not
|
||||
// Keeps track of whether the conversation list is scrolled to the top or not
|
||||
isScrolledToTop: true,
|
||||
refreshTimer: null,
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -188,6 +189,8 @@ export default {
|
|||
conversations = conversations.filter(conversation => conversation.displayName.toLowerCase().indexOf(lowerSearchText) !== -1 || conversation.name.toLowerCase().indexOf(lowerSearchText) !== -1)
|
||||
}
|
||||
|
||||
// FIXME: this modifies the original array,
|
||||
// maybe should act on a copy or sort already within the store ?
|
||||
return conversations.sort(this.sortConversations)
|
||||
},
|
||||
|
||||
|
@ -250,7 +253,7 @@ export default {
|
|||
|
||||
mounted() {
|
||||
/** Refreshes the conversations every 30 seconds */
|
||||
window.setInterval(() => {
|
||||
this.refreshTimer = window.setInterval(() => {
|
||||
if (!this.isFetchingConversations) {
|
||||
this.fetchConversations()
|
||||
}
|
||||
|
@ -269,6 +272,11 @@ export default {
|
|||
|
||||
this.cancelSearchListedConversations()
|
||||
this.cancelSearchListedConversations = null
|
||||
|
||||
if (this.refreshTimer) {
|
||||
clearInterval(this.refreshTimer)
|
||||
this.refreshTimer = null
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
@ -292,6 +300,7 @@ export default {
|
|||
this.contactsLoading = true
|
||||
|
||||
try {
|
||||
// FIXME: move to conversationsStore
|
||||
this.cancelSearchPossibleConversations('canceled')
|
||||
const { request, cancel } = CancelableRequest(searchPossibleConversations)
|
||||
this.cancelSearchPossibleConversations = cancel
|
||||
|
@ -324,6 +333,7 @@ export default {
|
|||
try {
|
||||
this.listedConversationsLoading = true
|
||||
|
||||
// FIXME: move to conversationsStore
|
||||
this.cancelSearchListedConversations('canceled')
|
||||
const { request, cancel } = CancelableRequest(searchListedConversations)
|
||||
this.cancelSearchListedConversations = cancel
|
||||
|
@ -394,6 +404,7 @@ export default {
|
|||
},
|
||||
|
||||
showSettings() {
|
||||
// FIXME: use local EventBus service instead of the global one
|
||||
emit('show-settings')
|
||||
},
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче