diff options
Diffstat (limited to 'tests')
29 files changed, 2196 insertions, 2 deletions
diff --git a/tests/Unit/Service/FolderServiceTest.php b/tests/Unit/Service/FolderServiceTest.php index 3e7e98041..3e47c6136 100644 --- a/tests/Unit/Service/FolderServiceTest.php +++ b/tests/Unit/Service/FolderServiceTest.php @@ -65,13 +65,22 @@ class FolderServiceTest extends TestCase protected function setUp(): void { $this->time = 222; + $timeFactory = $this->getMockBuilder(TimeFactory::class) ->disableOriginalConstructor() ->getMock(); - $timeFactory->expects($this->any()) - ->method('getTime') + + $mockDateTime = $this->getMockBuilder(\DateTimeImmutable::class) + ->disableOriginalConstructor() + ->getMock(); + $mockDateTime->expects($this->any()) + ->method('getTimestamp') ->will($this->returnValue($this->time)); + $timeFactory->expects($this->any()) + ->method('now') + ->will($this->returnValue($mockDateTime)); + $this->feedService = $this->getMockBuilder(FeedServiceV2::class) ->disableOriginalConstructor() ->getMock(); diff --git a/tests/javascript/helpers/CSSStub.js b/tests/javascript/helpers/CSSStub.js new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/javascript/helpers/CSSStub.js diff --git a/tests/javascript/unit/OC.ts b/tests/javascript/unit/OC.ts new file mode 100644 index 000000000..cbc7c642e --- /dev/null +++ b/tests/javascript/unit/OC.ts @@ -0,0 +1,38 @@ +export class OC { + + generateUrl(url: any) { + return '' + } + + imagePath(app: any, img: any) { + return '' + } + + linkToRemote(app: any) { + return '' + } + + getLanguage() { + return 'en-GB' + } + + getLocale() { + return 'en_GB' + } + + isUserAdmin() { + return false + } + + L10N = { + translate(app: any, text: any) { + return text + }, + + translatePlural(app: any, text: any) { + return text + }, + } + + config = {} +} diff --git a/tests/javascript/unit/components/AddFeed.spec.ts b/tests/javascript/unit/components/AddFeed.spec.ts new file mode 100644 index 000000000..48be08a79 --- /dev/null +++ b/tests/javascript/unit/components/AddFeed.spec.ts @@ -0,0 +1,91 @@ +import { shallowMount, createLocalVue } from '@vue/test-utils' +import AddFeed from '../../../../src/components/AddFeed.vue' +import { FEED_ACTION_TYPES } from '../../../../src/store/feed' + +describe('AddFeed.vue', () => { + 'use strict' + + const mockDispatch = jest.fn() + const mockStore = { + state: { + folders: { folders: [] }, + feeds: { feeds: [] }, + }, + dispatch: mockDispatch, + } + + let wrapper: any + beforeEach(() => { + const localVue = createLocalVue() + wrapper = shallowMount(AddFeed, { + localVue, + mocks: { + $route: { + query: { + subscribe_to: undefined, + }, + }, + $store: mockStore, + }, + }) + }) + + it('should initialize with default values', () => { + expect(wrapper.vm.$data.createNewFolder).toBeFalsy() + expect(wrapper.vm.$data.autoDiscover).toBeTruthy() + expect(wrapper.vm.$data.withBasicAuth).toBeFalsy() + }) + + it('should dispatch ADD_FEED action to store', async () => { + wrapper.vm.$emit = jest.fn() + + await wrapper.vm.addFeed() + + expect(wrapper.vm.$emit).toBeCalled() + expect(mockDispatch).toBeCalled() + expect(mockDispatch.mock.calls[0][0]).toEqual(FEED_ACTION_TYPES.ADD_FEED) + }) + + it('should check if feed url exists and return true', () => { + wrapper.vm.$data.feedUrl = '' + let response = wrapper.vm.feedUrlExists() + + expect(response).toBeFalsy() + + wrapper.vm.$data.feedUrl = 'http://example.com' + response = wrapper.vm.feedUrlExists() + + expect(response).toBeFalsy() + + wrapper.vm.$data.feedUrl = 'http://example.com' + wrapper.vm.$store.state.feeds.feeds = [{ url: 'http://example.com' }] + response = wrapper.vm.feedUrlExists() + + expect(response).toBeTruthy() + }) + + it('should check if folder name exists when creating folder and return true', () => { + wrapper.vm.$data.newFolderName = '' + let response = wrapper.vm.folderNameExists() + + expect(response).toBeFalsy() + + wrapper.vm.$data.newFolderName = 'test' + response = wrapper.vm.folderNameExists() + + expect(response).toBeFalsy() + + wrapper.vm.$data.newFolderName = 'test' + wrapper.vm.$store.state.folders.folders = [{ name: 'test' }] + response = wrapper.vm.folderNameExists() + + expect(response).toBeFalsy() + + wrapper.vm.$data.newFolderName = 'test' + wrapper.vm.$data.createNewFolder = 'test' + wrapper.vm.$store.state.folders.folders = [{ name: 'test' }] + response = wrapper.vm.folderNameExists() + + expect(response).toBeTruthy() + }) +}) diff --git a/tests/javascript/unit/components/AdminSettings.spec.ts b/tests/javascript/unit/components/AdminSettings.spec.ts new file mode 100644 index 000000000..865b30416 --- /dev/null +++ b/tests/javascript/unit/components/AdminSettings.spec.ts @@ -0,0 +1,64 @@ +import axios from '@nextcloud/axios' +import { createLocalVue, shallowMount, Wrapper } from '@vue/test-utils' +import { showError, showSuccess } from '@nextcloud/dialogs' +import { loadState } from '@nextcloud/initial-state' + +import 'regenerator-runtime/runtime' // NOTE: Required for testing password-confirmation? +import AdminSettings from '../../../../src/components/AdminSettings.vue' + +jest.mock('@nextcloud/axios') +jest.mock('@nextcloud/initial-state') +jest.mock('@nextcloud/router') +jest.mock('@nextcloud/dialogs') + +describe('AdminSettings.vue', () => { + 'use strict' + + let wrapper: Wrapper<AdminSettings> + + beforeAll(() => { + jest.useFakeTimers() + const localVue = createLocalVue(); + (loadState as any).mockReturnValue('') + wrapper = shallowMount(AdminSettings, { localVue }) + }) + + it('should initialize and fetch settings from state', () => { + expect(loadState).toBeCalledTimes(8) + }) + + it('should send post with updated settings', async () => { + jest.spyOn(axios, 'post').mockResolvedValue({ data: {} }); + (wrapper.vm as any).handleResponse = jest.fn() + + await wrapper.vm.$options?.methods?.update.call(wrapper.vm, 'key', 'val') + + expect(axios.post).toBeCalledTimes(1) + }) + + it('should handle bad response', () => { + (showError as any).mockClear() + console.error = jest.fn() + wrapper.vm.$options?.methods?.handleResponse.call(wrapper.vm, { + error: true, + errorMessage: 'FAIL', + }) + + expect(showError).toBeCalledTimes(1) + }) + + it('should handle success response', () => { + wrapper.vm.$options?.methods?.handleResponse.call(wrapper.vm, { + status: 'ok', + }); + (global as any).t = jest.fn() + jest.runAllTimers() + + expect(showSuccess).toBeCalledTimes(1) + }) + + afterAll(() => { + jest.clearAllMocks() + jest.useRealTimers() + }) +}) diff --git a/tests/javascript/unit/components/App.spec.ts b/tests/javascript/unit/components/App.spec.ts new file mode 100644 index 000000000..f1c4096b9 --- /dev/null +++ b/tests/javascript/unit/components/App.spec.ts @@ -0,0 +1,58 @@ +import { shallowMount, createLocalVue, Wrapper } from '@vue/test-utils' + +import App from '../../../../src/App.vue' +import { MUTATIONS } from '../../../../src/store' + +describe('FeedItemDisplay.vue', () => { + 'use strict' + const localVue = createLocalVue() + let wrapper: Wrapper<App> + + const dispatchStub = jest.fn() + const commitStub = jest.fn() + beforeAll(() => { + wrapper = shallowMount(App, { + localVue, + mocks: { + $store: { + state: { + items: { + playingItem: undefined, + }, + app: { + error: undefined, + }, + }, + dispatch: dispatchStub, + commit: commitStub, + }, + }, + }) + }) + + beforeEach(() => { + dispatchStub.mockReset() + commitStub.mockReset() + }) + + it('should send SET_PLAYING_ITEM with undefined to stop playback', () => { + (wrapper.vm as any).stopPlaying() + + expect(commitStub).toBeCalledWith(MUTATIONS.SET_PLAYING_ITEM, undefined) + }) + + it('should stop all video elements in page when playing video', () => { + const pauseStub = jest.fn() + document.getElementsByTagName = jest.fn().mockReturnValue([{ pause: pauseStub }]); + + (wrapper.vm as any).stopVideo() + + expect(pauseStub).toBeCalled() + }) + + it('should remove app state error with commit and undefined', () => { + (wrapper.vm as any).removeError() + + expect(commitStub).toBeCalledWith(MUTATIONS.SET_ERROR, undefined) + }) +}) diff --git a/tests/javascript/unit/components/ShareItem.spec.ts b/tests/javascript/unit/components/ShareItem.spec.ts new file mode 100644 index 000000000..f61c9e82b --- /dev/null +++ b/tests/javascript/unit/components/ShareItem.spec.ts @@ -0,0 +1,75 @@ +import { shallowMount, createLocalVue } from '@vue/test-utils' +import ShareItem from '../../../../src/components/ShareItem.vue' +import { ShareService } from '../../../../src/dataservices/share.service' + +describe('AddFeed.vue', () => { + 'use strict' + + let wrapper: any + beforeEach(() => { + const localVue = createLocalVue() + wrapper = shallowMount(ShareItem, { + localVue, + propsData: { + itemId: 123, + }, + }) + }) + + describe('clickUser()', () => { + it('should add to selected if user not selected before', () => { + wrapper.vm.selected = [] + + wrapper.vm.clickUser({ displayName: 'display', shareName: 'share' }) + + expect(wrapper.vm.selected.length).toEqual(1) + }) + + it('should remove from selected if user is selected before', () => { + wrapper.vm.selected = [{ displayName: 'display', shareName: 'share' }] + + wrapper.vm.clickUser({ displayName: 'display', shareName: 'share' }) + + expect(wrapper.vm.selected.length).toEqual(0) + }) + }) + + describe('searchUsers()', () => { + it('should call ShareService to fetch users to add to user (display) list', async () => { + ShareService.fetchUsers = jest.fn().mockReturnValue({ + data: { + ocs: { + data: { + users: [], + }, + }, + }, + }) + wrapper.vm.userName = 'search' + + await wrapper.vm.searchUsers() + + expect(ShareService.fetchUsers).toBeCalled() + }) + }) + + describe('share()', () => { + it('should call ShareService to share article id with backend', async () => { + ShareService.share = jest.fn() + wrapper.vm.selected = [{ displayName: 'display', shareName: 'share' }] + + await wrapper.vm.share() + + expect(ShareService.share).toBeCalled() + + wrapper.vm.selected = [{ displayName: 'display', shareName: 'share' }, { displayName: 'display2', shareName: 'share2' }] + + await wrapper.vm.share() + + let args = (ShareService.share as any).mock.calls[0] + expect(args[1]).toEqual(['share']) + args = (ShareService.share as any).mock.calls[1] + expect(args[1]).toEqual(['share', 'share2']) + }) + }) +}) diff --git a/tests/javascript/unit/components/Sidebar.spec.ts b/tests/javascript/unit/components/Sidebar.spec.ts new file mode 100644 index 000000000..404dac30a --- /dev/null +++ b/tests/javascript/unit/components/Sidebar.spec.ts @@ -0,0 +1,188 @@ +import { ACTIONS } from '../../../../src/store' +import { Wrapper, shallowMount, createLocalVue } from '@vue/test-utils' + +import AppSidebar from '../../../../src/components/Sidebar.vue' + +describe('Sidebar.vue', () => { + 'use strict' + + let wrapper: Wrapper<AppSidebar> + + const feeds = [{ + id: 1, title: 'first', + }, { + id: 2, title: 'second', folderId: 123, + }] + + beforeAll(() => { + const localVue = createLocalVue() + wrapper = shallowMount(AppSidebar, { + localVue, + mocks: { + $route: { + query: { + subscribe_to: undefined, + }, + }, + $store: { + state: { + feeds, + folders: [], + }, + getters: { + feeds, + }, + dispatch: jest.fn(), + }, + }, + }) + }) + + beforeEach(() => { + (wrapper.vm as any).$store.dispatch.mockReset() + }) + + it('should initialize without showing AddFeed Component', () => { + expect((wrapper.vm as any).$data.showAddFeed).toBeFalsy() + }) + + describe('User Actions', () => { + it('should dispatch message to store with folder name to create new folder', () => { + (wrapper.vm as any).newFolder('abc') + + expect((wrapper.vm as any).$store.dispatch).toHaveBeenCalledWith(ACTIONS.ADD_FOLDERS, { folder: { name: 'abc' } }) + }) + + it('should dispatch message to store with folder object on delete folder', () => { + const folder = {}; + (wrapper.vm as any).deleteFolder(folder) + + expect((wrapper.vm as any).$store.dispatch).toHaveBeenCalledWith(ACTIONS.DELETE_FOLDER, { folder }) + }) + + it('should set showAddFeed to true', () => { + (wrapper.vm as any).showShowAddFeed() + expect(wrapper.vm.$data.showAddFeed).toBeTruthy() + }) + + it('should set showAddFeed to false', () => { + (wrapper.vm as any).closeShowAddFeed() + expect(wrapper.vm.$data.showAddFeed).toBeFalsy() + }) + + it('should call mark feed read for all feeds in state', () => { + window.confirm = jest.fn().mockReturnValue(true); + (wrapper.vm as any).markAllRead() + expect((wrapper.vm as any).$store.dispatch).toHaveBeenCalledTimes(2) + }) + + it('should call mark feed read for all feeds in state with matching folderId', () => { + window.confirm = jest.fn().mockReturnValue(true); + (wrapper.vm as any).markFolderRead({ id: 123 }) + expect((wrapper.vm as any).$store.dispatch).toHaveBeenCalledTimes(1) + }) + + it('should call disptch rename folder with response from user', () => { + const name = 'new name' + window.prompt = jest.fn().mockReturnValue(name); + (wrapper.vm as any).renameFolder({ id: 123 }) + expect((wrapper.vm as any).$store.dispatch).toHaveBeenCalledWith(ACTIONS.FOLDER_SET_NAME, { folder: { id: 123 }, name }) + }) + }) + + describe('SideBarState', () => { + it('should return no top level nav when no folders or feeds', () => { + const topLevelNav = (wrapper.vm.$options.computed?.topLevelNav as any).call({ + $store: { + getters: { + feeds: [], + folders: [], + }, + }, + }) + + expect(topLevelNav).toEqual([]) + }) + + it('should return top level nav with 1 feed', () => { + const feeds: any[] = [{ name: 'feed1', id: 1 }] + const folders: any[] = [] + const topLevelNav = (wrapper.vm.$options.computed?.topLevelNav as any).call({ + $store: { + getters: { + feeds, + folders, + }, + }, + }) + + expect(topLevelNav).toEqual([feeds[0]]) + }) + + it('should return top level nav with 1 folder (with feeds)', () => { + const feeds: any[] = [{ name: 'feed2', id: 2, folderId: 123 }] + const folders: any[] = [{ name: 'abc', id: 123 }] + const topLevelNav = (wrapper.vm.$options.computed?.topLevelNav as any).call({ + $store: { + getters: { + feeds, + folders, + }, + }, + }) + + expect(topLevelNav).toEqual(folders) + }) + + it('should return top level nav with 1 folder (without feed)', () => { + const feeds: any[] = [{ name: 'feed1', id: 1 }] + const folders: any[] = [{ name: 'abc', id: 123 }] + const topLevelNav = (wrapper.vm.$options.computed?.topLevelNav as any).call({ + $store: { + getters: { + feeds, + folders, + }, + }, + }) + + expect(topLevelNav).toEqual([feeds[0], ...folders]) + }) + + it('should return top level nav with feeds and folders', () => { + const feeds: any[] = [{ name: 'feed1', id: 1 }, { name: 'feed2', id: 2, folderId: 123 }] + const folders: any[] = [{ name: 'abc', id: 123 }, { name: 'xyz', id: 234 }] + const topLevelNav = (wrapper.vm.$options.computed?.topLevelNav as any).call({ + $store: { + getters: { + feeds, + folders, + }, + }, + }) + + expect(topLevelNav).toEqual([feeds[0], ...folders]) + }) + + it('should set pinned feeds at beginning top level nav with feeds and folders', () => { + const feeds: any[] = [{ name: 'feed1', id: 1 }, { name: 'feed2', id: 2, folderId: 123 }, { name: 'feed3', id: 3, pinned: true }] + const folders: any[] = [{ name: 'abc', id: 123 }, { name: 'xyz', id: 234 }] + const topLevelNav = (wrapper.vm.$options.computed?.topLevelNav as any).call({ + $store: { + getters: { + feeds, + folders, + }, + }, + }) + + expect(topLevelNav[0].name).toEqual('feed3') + }) + }) + + // TODO: More Template Testing with https://test-utils.vuejs.org/guide/essentials/a-crash-course.html#adding-a-new-todo + + afterEach(() => { + jest.clearAllMocks() + }) +}) diff --git a/tests/javascript/unit/components/SidebarFeedLinkActions.spec.ts b/tests/javascript/unit/components/SidebarFeedLinkActions.spec.ts new file mode 100644 index 000000000..1a4ee6358 --- /dev/null +++ b/tests/javascript/unit/components/SidebarFeedLinkActions.spec.ts @@ -0,0 +1,95 @@ +import { ACTIONS } from '../../../../src/store' +import { Wrapper, shallowMount, createLocalVue } from '@vue/test-utils' + +import SidebarFeedLinkActions from '../../../../src/components/SidebarFeedLinkActions.vue' +import { FEED_UPDATE_MODE, FEED_ORDER } from '../../../../src/dataservices/feed.service' + +describe('SidebarFeedLinkActions.vue', () => { + 'use strict' + + let wrapper: Wrapper<SidebarFeedLinkActions> + + const feeds = [{ + id: 1, title: 'first', + }, { + id: 2, title: 'second', folderId: 123, + }] + + beforeAll(() => { + const localVue = createLocalVue() + wrapper = shallowMount(SidebarFeedLinkActions, { + localVue, + propsData: { + feedId: 1, + }, + mocks: { + $store: { + state: { + feeds, + folders: [], + }, + getters: { + feeds, + }, + dispatch: jest.fn(), + }, + }, + }) + }) + + beforeEach(() => { + (wrapper.vm as any).$store.dispatch.mockReset() + }) + + describe('User Actions', () => { + it('should dispatch message to store with feed object', () => { + (wrapper.vm as any).markRead() + + expect((wrapper.vm as any).$store.dispatch).toHaveBeenCalledWith(ACTIONS.FEED_MARK_READ, { feed: feeds[0] }) + }) + + it('should dispatch message to store with feed object and pinned', () => { + (wrapper.vm as any).setPinned(true) + + expect((wrapper.vm as any).$store.dispatch).toHaveBeenCalledWith(ACTIONS.FEED_SET_PINNED, { feed: feeds[0], pinned: true }) + }) + + it('should dispatch message to store with feed object and fullTextEnabled', () => { + (wrapper.vm as any).setOrdering(FEED_ORDER.NEWEST) + + expect((wrapper.vm as any).$store.dispatch).toHaveBeenCalledWith(ACTIONS.FEED_SET_ORDERING, { feed: feeds[0], ordering: FEED_ORDER.NEWEST }) + }) + + it('should dispatch message to store with feed object and fullTextEnabled', () => { + (wrapper.vm as any).setFullText(true) + + expect((wrapper.vm as any).$store.dispatch).toHaveBeenCalledWith(ACTIONS.FEED_SET_FULL_TEXT, { feed: feeds[0], fullTextEnabled: true }) + }) + + it('should dispatch message to store with feed object and new updateMode', () => { + (wrapper.vm as any).setUpdateMode(FEED_UPDATE_MODE.IGNORE) + + expect((wrapper.vm as any).$store.dispatch).toHaveBeenCalledWith(ACTIONS.FEED_SET_UPDATE_MODE, { feed: feeds[0], updateMode: FEED_UPDATE_MODE.IGNORE }) + }) + + it('should dispatch message to store with feed object on rename feed', () => { + window.prompt = jest.fn().mockReturnValue('test'); + + (wrapper.vm as any).rename() + + expect((wrapper.vm as any).$store.dispatch).toHaveBeenCalledWith(ACTIONS.FEED_SET_TITLE, { feed: feeds[0], title: 'test' }) + }) + + it('should dispatch message to store with feed object on delete feed', () => { + window.confirm = jest.fn().mockReturnValue(true); + + (wrapper.vm as any).deleteFeed() + + expect((wrapper.vm as any).$store.dispatch).toHaveBeenCalledWith(ACTIONS.FEED_DELETE, { feed: feeds[0] }) + }) + }) + + afterEach(() => { + jest.clearAllMocks() + }) +}) diff --git a/tests/javascript/unit/components/feed-display/FeedItemDisplay.spec.ts b/tests/javascript/unit/components/feed-display/FeedItemDisplay.spec.ts new file mode 100644 index 000000000..81c171114 --- /dev/null +++ b/tests/javascript/unit/components/feed-display/FeedItemDisplay.spec.ts @@ -0,0 +1,99 @@ +import { shallowMount, createLocalVue, Wrapper } from '@vue/test-utils' + +import FeedItemDisplay from '../../../../../src/components/feed-display/FeedItemDisplay.vue' +import { ACTIONS, MUTATIONS } from '../../../../../src/store' + +describe('FeedItemDisplay.vue', () => { + 'use strict' + const localVue = createLocalVue() + let wrapper: Wrapper<FeedItemDisplay> + + const mockItem = { + feedId: 1, + title: 'feed item', + pubDate: Date.now() / 1000, + } + const mockFeed = { + id: 1, + } + + const dispatchStub = jest.fn() + const commitStub = jest.fn() + beforeAll(() => { + wrapper = shallowMount(FeedItemDisplay, { + propsData: { + item: mockItem, + }, + localVue, + mocks: { + $store: { + getters: { + feeds: [mockFeed], + }, + state: { + feeds: [], + folders: [], + }, + dispatch: dispatchStub, + commit: commitStub, + }, + }, + }) + }) + + beforeEach(() => { + dispatchStub.mockReset() + commitStub.mockReset() + }) + + it('should send SET_SELECTED_ITEM with undefined id', () => { + (wrapper.vm as any).clearSelected() + + expect(commitStub).toBeCalledWith(MUTATIONS.SET_SELECTED_ITEM, { id: undefined }) + }) + + it('should format date to match locale', () => { + const epoch = Date.now() // Provide an epoch timestamp + const formattedDate = (wrapper.vm as any).formatDate(epoch) + + expect(formattedDate).toEqual(new Date(epoch).toLocaleString()) + }) + + it('should retrieve feed by ID', () => { + const feed = (wrapper.vm as any).getFeed(mockFeed.id) + + expect(feed).toEqual(mockFeed) + }) + + it('should toggle starred state', () => { + wrapper.vm.$props.item.starred = true; + + (wrapper.vm as any).toggleStarred(wrapper.vm.$props.item) + expect(dispatchStub).toHaveBeenCalledWith(ACTIONS.UNSTAR_ITEM, { + item: wrapper.vm.$props.item, + }) + + wrapper.vm.$props.item.starred = false; + + (wrapper.vm as any).toggleStarred(wrapper.vm.$props.item) + expect(dispatchStub).toHaveBeenCalledWith(ACTIONS.STAR_ITEM, { + item: wrapper.vm.$props.item, + }) + }) + + it('should send SET_PLAYING_ITEM with item', () => { + const item = { id: 123 }; + (wrapper.vm as any).playAudio(item) + + expect(commitStub).toBeCalledWith(MUTATIONS.SET_PLAYING_ITEM, item) + }) + + it('should stop all audio elements in page when playing video', () => { + const pauseStub = jest.fn() + document.getElementsByTagName = jest.fn().mockReturnValue([{ pause: pauseStub }]); + + (wrapper.vm as any).stopAudio() + + expect(pauseStub).toBeCalled() + }) +}) diff --git a/tests/javascript/unit/components/feed-display/FeedItemDisplayList.spec.ts b/tests/javascript/unit/components/feed-display/FeedItemDisplayList.spec.ts new file mode 100644 index 000000000..cd11b7ea9 --- /dev/null +++ b/tests/javascript/unit/components/feed-display/FeedItemDisplayList.spec.ts @@ -0,0 +1,66 @@ +import Vuex, { Store } from 'vuex' +import { shallowMount, createLocalVue, Wrapper } from '@vue/test-utils' + +import FeedItemDisplayList from '../../../../../src/components/feed-display/FeedItemDisplayList.vue' +import VirtualScroll from '../../../../../src/components/feed-display/VirtualScroll.vue' +import FeedItemRow from '../../../../../src/components/feed-display/FeedItemRow.vue' + +jest.mock('@nextcloud/axios') + +describe('FeedItemDisplayList.vue', () => { + 'use strict' + const localVue = createLocalVue() + localVue.use(Vuex) + let wrapper: Wrapper<FeedItemDisplayList> +< |