Skip to content

Commit 0e048dd

Browse files
committed
feat: implement team upgrade banner and remove legacy folder share
Signed-off-by: Stefan Dietrich <stefan.dietrich@dataport.de>
1 parent 6f01d95 commit 0e048dd

1 file changed

Lines changed: 134 additions & 4 deletions

File tree

src/teams/team-page/components/CircleDetails.spec.ts

Lines changed: 134 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ import CircleDetails from './CircleDetails.vue'
1818
const loadState = vi.hoisted(() => vi.fn((app: string, key: string, fallback: unknown) => fallback))
1919
const getTeamFolder = vi.hoisted(() => vi.fn<(teamId: string) => Promise<TeamFolder | null>>(async () => null))
2020
const upgradeTeamFolder = vi.hoisted(() => vi.fn<(teamId: string) => Promise<TeamFolder>>(async () => ({ id: 1, mountPoint: 'Team' })))
21+
const showError = vi.hoisted(() => vi.fn())
22+
const showSuccess = vi.hoisted(() => vi.fn())
23+
const axiosGet = vi.hoisted(() => vi.fn(async () => ({ data: { ocs: { data: { resources: [] } } } })))
24+
const axiosPost = vi.hoisted(() => vi.fn(async () => ({ data: { ocs: { data: {} } } })))
2125

2226
vi.mock('@nextcloud/initial-state', () => ({ loadState }))
2327
vi.mock('@nextcloud/auth', () => ({
@@ -34,8 +38,8 @@ vi.mock('@nextcloud/router', async (importOriginal) => {
3438
})
3539
vi.mock('@nextcloud/axios', () => ({
3640
default: {
37-
get: vi.fn(async () => ({ data: { ocs: { data: { resources: [] } } } })),
38-
post: vi.fn(async () => ({ data: { ocs: { data: {} } } })),
41+
get: axiosGet,
42+
post: axiosPost,
3943
request: vi.fn(async () => ({ data: {} })),
4044
},
4145
}))
@@ -45,8 +49,8 @@ vi.mock('@nextcloud/dialogs', () => ({
4549
getFilePickerBuilder: () => ({
4650
setMultiSelect: () => ({ setMimeTypeFilter: () => ({ setType: () => ({ allowDirectories: () => ({ build: () => ({}) }) }) }) }),
4751
}),
48-
showError: vi.fn(),
49-
showSuccess: vi.fn(),
52+
showError,
53+
showSuccess,
5054
}))
5155
vi.mock('@nextcloud/event-bus', () => ({ emit: vi.fn() }))
5256
vi.mock('../../api.ts', () => ({ getTeamFolder, upgradeTeamFolder }))
@@ -149,6 +153,70 @@ describe('CircleDetails folder button', () => {
149153
})
150154
})
151155

156+
describe('CircleDetails team resources', () => {
157+
beforeEach(() => {
158+
vi.clearAllMocks()
159+
})
160+
161+
it('creates and shares a Talk conversation with the team', async () => {
162+
const wrapper = mountDetails()
163+
const resourceInputs = wrapper.vm.resourceInputs as Record<string, string>
164+
const state = wrapper.vm as { activePopover: string | null }
165+
axiosPost
166+
.mockResolvedValueOnce({ data: { ocs: { data: { token: 'room-token' } } } })
167+
.mockResolvedValueOnce({ data: { ocs: { data: {} } } })
168+
resourceInputs.talk = 'Team chat'
169+
state.activePopover = 'talk'
170+
171+
await wrapper.vm.handleResourceCreation({
172+
resourceType: { id: 'talk', label: 'Talk conversation' },
173+
name: 'Team chat',
174+
})
175+
176+
expect(axiosPost).toHaveBeenNthCalledWith(1, '/apps/spreed/api/v4/room', {
177+
roomName: 'Team chat',
178+
roomType: 2,
179+
})
180+
expect(axiosPost).toHaveBeenNthCalledWith(2, '/apps/spreed/api/v4/room/room-token/participants', {
181+
source: 'circles',
182+
newParticipant: 'team-1',
183+
})
184+
expect(resourceInputs.talk).toBe('')
185+
expect(state.activePopover).toBeNull()
186+
expect(showSuccess).toHaveBeenCalledWith('Talk conversation "Team chat" created and shared with team')
187+
})
188+
189+
it('reports unsupported resource types without making a request', async () => {
190+
const wrapper = mountDetails()
191+
192+
await wrapper.vm.handleResourceCreation({
193+
resourceType: { id: 'unsupported', label: 'Unsupported' },
194+
name: 'Ignored',
195+
})
196+
197+
expect(axiosPost).not.toHaveBeenCalled()
198+
expect(showError).toHaveBeenCalledWith('Unknown resource type')
199+
})
200+
201+
it('clears resources when their request fails', async () => {
202+
const wrapper = mountDetails()
203+
wrapper.vm.resources = [{ id: 'resource-1' }] as never[]
204+
const error = new Error('Network error')
205+
const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {})
206+
axiosGet.mockRejectedValueOnce(error)
207+
208+
await wrapper.vm.fetchTeamResources()
209+
210+
expect(axiosGet).toHaveBeenLastCalledWith('/teams/team-1/resources')
211+
expect(wrapper.vm.resources).toEqual([])
212+
expect(consoleError).toHaveBeenCalledWith('Could not fetch team resources', {
213+
error,
214+
circleId: 'team-1',
215+
})
216+
consoleError.mockRestore()
217+
})
218+
})
219+
152220
describe('CircleDetails team folder upgrade banner', () => {
153221
beforeEach(() => {
154222
vi.clearAllMocks()
@@ -182,6 +250,13 @@ describe('CircleDetails team folder upgrade banner', () => {
182250
expect(html).not.toContain('Create team folder')
183251
})
184252

253+
it('does not render the banner for non-members', async () => {
254+
const wrapper = mountDetails({ initiator: null }, { autoCreate: true, providerAvailable: true })
255+
await vi.waitFor(() => expect(wrapper.vm.loadingTeamFolder).toBe(false))
256+
257+
expect(wrapper.html()).not.toContain('This team does not have a team folder yet.')
258+
})
259+
185260
it('hides the banner when a team folder exists', async () => {
186261
const wrapper = mountDetails({}, {
187262
autoCreate: true,
@@ -210,4 +285,59 @@ describe('CircleDetails team folder upgrade banner', () => {
210285
expect(html).toContain('Create one to share files with the whole team.')
211286
expect(html).toContain('Create team folder')
212287
})
288+
289+
it('keeps the banner visible when loading finds no linked folder', async () => {
290+
getTeamFolder.mockRejectedValueOnce({ response: { status: 404 } })
291+
const wrapper = mountDetails()
292+
await vi.waitFor(() => expect(wrapper.vm.loadingTeamFolder).toBe(false))
293+
294+
expect(wrapper.vm.teamFolder).toBeNull()
295+
expect(wrapper.vm.showTeamFolderBanner).toBe(true)
296+
expect(showError).not.toHaveBeenCalled()
297+
})
298+
299+
it('reports an unexpected team-folder loading error', async () => {
300+
getTeamFolder.mockRejectedValueOnce(new Error('Network error'))
301+
const wrapper = mountDetails()
302+
await vi.waitFor(() => expect(wrapper.vm.loadingTeamFolder).toBe(false))
303+
304+
expect(wrapper.vm.teamFolder).toBeNull()
305+
expect(showError).toHaveBeenCalledWith('Could not load team space')
306+
})
307+
308+
it('creates a team folder and navigates to the team', async () => {
309+
const wrapper = mountDetails()
310+
await vi.waitFor(() => expect(wrapper.vm.loadingTeamFolder).toBe(false))
311+
312+
await wrapper.vm.createTeamFolder()
313+
314+
expect(upgradeTeamFolder).toHaveBeenCalledWith('team-1')
315+
expect(wrapper.vm.teamFolder).toEqual({ id: 1, mountPoint: 'Team' })
316+
expect(wrapper.vm.$router.push).toHaveBeenCalledWith({
317+
name: 'team',
318+
params: { teamId: 'team-1' },
319+
})
320+
expect(wrapper.vm.creatingTeamFolder).toBe(false)
321+
})
322+
323+
it('creates a team folder from the banner action', async () => {
324+
const wrapper = mountDetails()
325+
await vi.waitFor(() => expect(wrapper.vm.loadingTeamFolder).toBe(false))
326+
327+
await wrapper.get('.team-folder-banner__action').trigger('click')
328+
329+
expect(upgradeTeamFolder).toHaveBeenCalledWith('team-1')
330+
expect(wrapper.vm.$router.push).toHaveBeenCalled()
331+
})
332+
333+
it('reports a team-folder creation error and clears its loading state', async () => {
334+
upgradeTeamFolder.mockRejectedValueOnce(new Error('Network error'))
335+
const wrapper = mountDetails()
336+
await vi.waitFor(() => expect(wrapper.vm.loadingTeamFolder).toBe(false))
337+
338+
await wrapper.vm.createTeamFolder()
339+
340+
expect(showError).toHaveBeenCalledWith('Could not create the team space')
341+
expect(wrapper.vm.creatingTeamFolder).toBe(false)
342+
})
213343
})

0 commit comments

Comments
 (0)