Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions cypress/e2e/groupfoldersNavigation.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*!
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import type { User } from '@nextcloud/e2e-test-server/cypress'

import {
PERMISSION_READ,
PERMISSION_WRITE,
addUserToGroup,
createGroup,
createGroupFolder,
deleteGroupFolder,
fileOrFolderExists,
} from './groupfoldersUtils.ts'
import { randHash } from '../utils/index.js'

// Regression coverage for https://github.com/nextcloud/groupfolders/issues/4499:
// clicking a team folder from the Team folders view must navigate to the
// target route *with* the fileid segment (PR #4524) and render content — including
// on repeated navigation, which is where the stale-route / abort-race failures
// used to surface.
describe('Team folders view navigation', () => {
let user: User
let groupFolderId: string
let groupName: string
let groupFolderName: string

beforeEach(() => {
if (groupFolderId) {
deleteGroupFolder(groupFolderId)
}
groupName = `test_group_${randHash()}`
groupFolderName = `test_group_folder_${randHash()}`

cy.createRandomUser().then(_user => {
user = _user
createGroup(groupName).then(() => {
addUserToGroup(groupName, user.userId)
createGroupFolder(groupFolderName, groupName, [PERMISSION_READ, PERMISSION_WRITE])
.then(_id => {
groupFolderId = _id
})
})
})
})

it('clicking a team folder navigates to /apps/files/files/<fileid> with dir query and renders content', () => {
cy.uploadContent(user, new Blob(['hello']), 'text/plain', `/${groupFolderName}/file1.txt`)

cy.login(user)
cy.visit('/apps/files/groupfolders')
cy.location('pathname').should('include', '/apps/files/groupfolders')

// The Team folders view is served by the groupfolders DAV endpoint and keys
// rows by group-folder id rather than mount-point name — locate by fileid.
cy.get('[data-cy-files-list-row-fileid]').should('have.length.at.least', 1)

cy.intercept({ method: 'PROPFIND', url: `**/dav/files/**/${groupFolderName}` }).as('propFindFolder')
cy.get('[data-cy-files-list-row-fileid]').first()
.find('[data-cy-files-list-row-name-link]')
.click({ force: true })
cy.wait('@propFindFolder')

// PR 4524: route must include the fileid segment, not just /apps/files/files?dir=...
cy.location('pathname').should('match', /\/apps\/files\/files\/\d+$/)
cy.location('search').should('contain', `dir=/${groupFolderName}`)

// If exec returns before navigation settles or lets a router rejection bubble,
// the file list stays empty / shows "folder not found".
fileOrFolderExists('file1.txt')
})

it('navigating back to the Team folders view and re-entering the same folder still works', () => {
cy.uploadContent(user, new Blob(['hello']), 'text/plain', `/${groupFolderName}/file1.txt`)

cy.login(user)
cy.visit('/apps/files/groupfolders')
cy.location('pathname').should('include', '/apps/files/groupfolders')
cy.get('[data-cy-files-list-row-fileid]').should('have.length.at.least', 1)

cy.intercept({ method: 'PROPFIND', url: `**/dav/files/**/${groupFolderName}` }).as('propFind1')
cy.get('[data-cy-files-list-row-fileid]').first()
.find('[data-cy-files-list-row-name-link]')
.click({ force: true })
cy.wait('@propFind1')
fileOrFolderExists('file1.txt')

cy.visit('/apps/files/groupfolders')
cy.location('pathname').should('include', '/apps/files/groupfolders')
cy.get('[data-cy-files-list-row-fileid]').should('have.length.at.least', 1)

// Second click — the stale-router path from the bug report.
cy.intercept({ method: 'PROPFIND', url: `**/dav/files/**/${groupFolderName}` }).as('propFind2')
cy.get('[data-cy-files-list-row-fileid]').first()
.find('[data-cy-files-list-row-name-link]')
.click({ force: true })
cy.wait('@propFind2')

cy.location('pathname').should('match', /\/apps\/files\/files\/\d+$/)
fileOrFolderExists('file1.txt')
})
})
7 changes: 3 additions & 4 deletions src/actions/openGroupfolderAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@ export const action: IFileAction = {
enabled: ({ view }) => view.id === appName,

async exec({ nodes }) {
const dir = nodes[0].attributes.mountPoint
window.OCP.Files.Router.goToRoute(
await window.OCP.Files.Router.goToRoute(
null, // use default route
{ view: 'files', fileid: nodes[0].id },
{ dir },
{ dir: nodes[0].attributes.mountPoint },
)
return null
return true
},

default: DefaultType.DEFAULT,
Expand Down
Loading