diff --git a/appinfo/info.xml b/appinfo/info.xml
index c0ffcae8c..f30077ef6 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -26,7 +26,7 @@ In your Nextcloud instance, simply navigate to **»Apps«**, find the
**»Teams«** and **»Collectives«** apps and enable them.
]]>
- 3.6.1
+ 3.7.0
agpl
CollectiveCloud Team
Collectives
@@ -63,6 +63,7 @@ In your Nextcloud instance, simply navigate to **»Apps«**, find the
OCA\Collectives\Migration\GenerateSlugs
OCA\Collectives\Migration\MigrateBacklinks
+ OCA\Collectives\Migration\MigrateUserFolderSettings
diff --git a/cypress/e2e/files.spec.js b/cypress/e2e/files.spec.js
deleted file mode 100644
index 10bb53361..000000000
--- a/cypress/e2e/files.spec.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-describe('Files app', function() {
- before(function() {
- cy.loginAs('bob')
- cy.deleteAndSeedCollective('Preexisting Collective')
- })
-
- it('has a matching folder', function() {
- const breadcrumbsSelector = '[data-cy-files-content-breadcrumbs] :is(a, button)'
- cy.visit('/apps/files')
-
- cy.openFile('Collectives')
- cy.get(breadcrumbsSelector).should('contain', 'Collectives')
- cy.openFile('Preexisting Collective')
- cy.get(breadcrumbsSelector).should('contain', 'Preexisting Collective')
- cy.fileList().should('contain', 'Readme')
- cy.fileList().should('contain', '.md')
- cy.get('.filelist-collectives-wrapper')
- .should('contain', 'The content of this folder is best viewed in the Collectives app.')
- })
-})
diff --git a/cypress/e2e/page-links.spec.js b/cypress/e2e/page-links.spec.js
index 6c0e487a6..d83e60c85 100644
--- a/cypress/e2e/page-links.spec.js
+++ b/cypress/e2e/page-links.spec.js
@@ -32,7 +32,7 @@ describe('Page link handling', function() {
cy.uploadFile('test.png', 'image/png').then((id) => {
imageId = id
})
- cy.uploadFile('test.pdf', 'application/pdf', 'Collectives/Link%20Testing/').then((id) => {
+ cy.uploadFile('test.pdf', 'application/pdf', '.Collectives/Link%20Testing/').then((id) => {
pdfId = id
})
}).then(() => {
diff --git a/cypress/support/commands.js b/cypress/support/commands.js
index 012c56264..2eede28fa 100644
--- a/cypress/support/commands.js
+++ b/cypress/support/commands.js
@@ -289,7 +289,7 @@ Cypress.Commands.add('seedPageContent', (pagePath, content) => {
? content.substring(0, 200) + '…'
: content
Cypress.log({ message: `${pagePath}, ${contentForLog}` })
- cy.uploadContent(`Collectives/${pagePath}`, content)
+ cy.uploadContent(`.Collectives/${pagePath}`, content)
})
Cypress.Commands.add('uploadFile', (path, mimeType, remotePath = '') => {
diff --git a/cypress/support/navigation.js b/cypress/support/navigation.js
index 60a57fa92..c6d9c4765 100644
--- a/cypress/support/navigation.js
+++ b/cypress/support/navigation.js
@@ -56,5 +56,3 @@ Cypress.Commands.add('clickMenuButton', (title) => {
const FILE_LIST_SELECTOR = '.files-fileList a, [data-cy-files-list-row] [data-cy-files-list-row-name-link]'
Cypress.Commands.add('fileList', () => cy.get(FILE_LIST_SELECTOR))
-
-Cypress.Commands.add('openFile', (name) => cy.fileList().contains(name).click())
diff --git a/docs/content/usage/_index.md b/docs/content/usage/_index.md
index ce87438aa..2514f13dd 100644
--- a/docs/content/usage/_index.md
+++ b/docs/content/usage/_index.md
@@ -5,14 +5,13 @@ weight = 1
alwaysopen = true
+++
-This tutorial will walk you through the collectives app in less than 10
-minutes.
-It assumes you already have a user account on a nextcloud installation
-with the collectives app enabled.
+This tutorial will walk you through the basics of the Collectives app.
+It assumes you already have a user account on a Nextcloud installation
+with the Collectives app enabled.
## ✨ Create a new collective
-Visit the collectives app by clicking its icon in the toolbar at the top
+Visit the Collectives app by clicking its icon in the toolbar at the top
of the screen:

@@ -20,17 +19,17 @@ of the screen:
On the left of the screen you will find a list of all of your
collectives.
It's probably empty if you have not been added to any yet.
-Click "Create new collective" and type a name for your collective.
+Click "New collective" and type a name for your collective.
You can also pick an emoji to easily find your collective later:
-
+
## 🌱 Bring life to your collective
Create pages and share the knowledge that really matters.
-Click the "Create a Page" button in the upper left
+Click the "Add a page" button in the upper left
and a new page will appear.
You can type in a title right away or add some content first
@@ -53,11 +52,20 @@ can even add entire groups to your collectives.
## Also good to know
* Multiple people can edit the same page simultaneously.
-* Link local pages by selecting text and choosing "link file".
- Drag & drop from page list into the editor also works.
+* Link pages by drag & dropping them from the page list into the editor.
* Add templates for future subpages via "Manage templates" in the landing page three-dot-menu.
* Ask [the community](https://help.nextcloud.com/c/apps/collectives/174) for help in case of questions.
## Searching Collectives
-Use the search input on top of the page list (top left) to filter your collecives by page titles. Use the Nextcloud unified search (top right) to search within the contents of Collectives.
+Use the search input on top of the page list (top left) to filter your collectives by page titles. Use the Nextcloud unified search (top right) to search within the contents of Collectives.
+
+## Access the Markdown files via Files app
+
+The pages of your collectives are stored in Markdown files. You can access them via the Files app.
+Per default, the folder is hidden as it's called ".Collectives" (or a translated version of it).
+To access the hidden folder, enable "Show hidden files" in the Files app settings.
+
+You can also change the name of the folder in the Collectives settings. The setting is located at
+the bottom of the Collectives list. If you want the folder to be visible permanently without showing
+other hidden files, set the folder setting to a name without leading dot (e.g. "Collectives").
diff --git a/lib/Fs/UserFolderHelper.php b/lib/Fs/UserFolderHelper.php
index f92ca2122..e13b732dc 100644
--- a/lib/Fs/UserFolderHelper.php
+++ b/lib/Fs/UserFolderHelper.php
@@ -35,7 +35,7 @@ public function getUserFolderSetting(string $userId): string {
$user = $this->userManager->get($userId);
$userLang = $this->l10nFactory->getUserLanguage($user);
$l10n = $this->l10nFactory->get('collectives', $userLang);
- $userCollectivesPath = '/' . $l10n->t('Collectives');
+ $userCollectivesPath = DIRECTORY_SEPARATOR . '.' . $l10n->t('Collectives');
$this->config->setUserValue($userId, 'collectives', 'user_folder', $userCollectivesPath);
}
diff --git a/lib/Migration/MigrateUserFolderSettings.php b/lib/Migration/MigrateUserFolderSettings.php
new file mode 100644
index 000000000..4b4e1e9e4
--- /dev/null
+++ b/lib/Migration/MigrateUserFolderSettings.php
@@ -0,0 +1,80 @@
+appConfig->getValueBool('collectives', 'migrated_user_folder_settings')) {
+ $output->info('User folder settings already migrated');
+ return;
+ }
+
+ $output->info('Migrating user folder settings ...');
+ $output->startProgress();
+
+ $this->userManager->callForSeenUsers(function (IUser $user) use ($output) {
+ $oldDefaultUserFolderPath = DIRECTORY_SEPARATOR . 'Collectives';
+ $newDefaultUserFolderPath = DIRECTORY_SEPARATOR . '.' . 'Collectives';
+ $userFolderPath = $this->config->getUserValue($user->getUID(), 'collectives', 'user_folder', '');
+ if ($userFolderPath === '') {
+ // No user folder path configured, doesn't use Collectives
+ return;
+ }
+
+ if ($userFolderPath === $newDefaultUserFolderPath) {
+ // New default English user folder path, already migrated
+ return;
+ }
+
+ if ($userFolderPath === $oldDefaultUserFolderPath) {
+ // Old default English user folder path, update setting
+ $this->config->setUserValue($user->getUID(), 'collectives', 'user_folder', $newDefaultUserFolderPath);
+ $output->advance();
+ return;
+ }
+
+ $userLang = $this->l10nFactory->getUserLanguage($user);
+ $l10n = $this->l10nFactory->get('collectives', $userLang);
+ $oldDefaultUserFolderPathL10n = DIRECTORY_SEPARATOR . $l10n->t('Collectives');
+ $newDefaultUserFolderPathL10n = DIRECTORY_SEPARATOR . '.' . $l10n->t('Collectives');
+
+ if ($userFolderPath === $oldDefaultUserFolderPathL10n) {
+ // Old default localized user folder path, update setting
+ $this->config->setUserValue($user->getUID(), 'collectives', 'user_folder', $newDefaultUserFolderPathL10n);
+ $output->advance();
+ }
+ });
+
+ $output->finishProgress();
+ $output->info('done');
+
+ $this->appConfig->setValueBool('collectives', 'migrated_user_folder_settings', true);
+ }
+}
diff --git a/playwright/e2e/files.spec.ts b/playwright/e2e/files.spec.ts
new file mode 100644
index 000000000..8d7f435bc
--- /dev/null
+++ b/playwright/e2e/files.spec.ts
@@ -0,0 +1,28 @@
+/**
+ * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import { expect, mergeTests } from '@playwright/test'
+import { test as createCollectivesTest } from '../support/fixtures/create-collectives.ts'
+import { test as filesAppTest } from '../support/fixtures/filesApp.ts'
+import { test as navigationTest } from '../support/fixtures/navigation.ts'
+
+const test = mergeTests(createCollectivesTest, filesAppTest, navigationTest)
+
+test.describe('Files app', () => {
+ test('Collectives folder is visible in files app', async ({ collective, filesApp, setShowHiddenFiles }) => {
+ await collective.openCollective()
+
+ await setShowHiddenFiles(true)
+ await filesApp.open()
+
+ await expect(filesApp.getFileListEntry('.Collectives')).toBeVisible()
+ await filesApp.openFile('.Collectives')
+ await expect(filesApp.getFileListEntry('Test Collective 1')).toBeVisible()
+ await filesApp.hasCollectivesHeader()
+ await filesApp.openFile('Test Collective 1')
+ await expect(filesApp.getFileListEntry('Readme.md')).toBeVisible()
+ await filesApp.hasCollectivesHeader()
+ })
+})
diff --git a/playwright/e2e/settings.spec.ts b/playwright/e2e/settings.spec.ts
index 65d340bb0..2d9023944 100644
--- a/playwright/e2e/settings.spec.ts
+++ b/playwright/e2e/settings.spec.ts
@@ -26,7 +26,7 @@ test.describe('Settings', () => {
await collective.openApp()
})
- test('Can change collectives folder', async ({ getFileListEntry, navigation, openFilesApp, openFile }) => {
+ test('Can change collectives folder', async ({ navigation, filesApp }) => {
const randomFolder = Math.random().toString(36).replace(/[^a-z]+/g, '').slice(0, 10)
await navigation.setUserFolder(randomFolder)
await navigation.openCollectivesSettings()
@@ -34,9 +34,9 @@ test.describe('Settings', () => {
// Input field has new value after setting it
await expect(navigation.collectivesFolderInputEl).toHaveValue(`/${randomFolder}`)
- await openFilesApp()
- await openFile(randomFolder)
- await expect(getFileListEntry(collectiveName1)).toBeVisible()
- await expect(getFileListEntry(collectiveName2)).toBeVisible()
+ await filesApp.open()
+ await filesApp.openFile(randomFolder)
+ await expect(filesApp.getFileListEntry(collectiveName1)).toBeVisible()
+ await expect(filesApp.getFileListEntry(collectiveName2)).toBeVisible()
})
})
diff --git a/playwright/support/fixtures/User.ts b/playwright/support/fixtures/User.ts
index 68919b9ed..f06eccc8d 100644
--- a/playwright/support/fixtures/User.ts
+++ b/playwright/support/fixtures/User.ts
@@ -3,13 +3,14 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
+import { type User as Account } from '@nextcloud/e2e-test-server'
import { type Page } from '@playwright/test'
import { createCollective, trashAndDeleteCollective } from './Collective.ts'
export class User {
constructor(
+ public readonly account: Account,
public readonly page: Page,
- public readonly userId: string,
) {
}
diff --git a/playwright/support/fixtures/create-collectives.ts b/playwright/support/fixtures/create-collectives.ts
index 1be5caddf..cf74f3202 100644
--- a/playwright/support/fixtures/create-collectives.ts
+++ b/playwright/support/fixtures/create-collectives.ts
@@ -56,7 +56,7 @@ export const test = base.extend({
await runOcc([
'collectives:import:markdown',
`--collective-id=${collective.data.id}`,
- `--user-id=${user.userId}`,
+ `--user-id=${user.account.userId}`,
'--',
config.markdownImportPath,
])
diff --git a/playwright/support/fixtures/filesApp.ts b/playwright/support/fixtures/filesApp.ts
index 3bdf23a06..c761385aa 100644
--- a/playwright/support/fixtures/filesApp.ts
+++ b/playwright/support/fixtures/filesApp.ts
@@ -3,25 +3,33 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-import { type Locator } from '@playwright/test'
import { test as baseTest } from '@playwright/test'
+import { FilesAppSection } from '../sections/FilesAppSection.ts'
type FilesAppFixture = {
- openFilesApp: () => Promise
- getFileListEntry: (fileName: string) => Locator
- openFile: (fileName: string) => Promise
+ filesApp: FilesAppSection
+ setShowHiddenFiles: (show: boolean) => Promise
}
export const test = baseTest.extend({
- openFilesApp: ({ page }, use) => use(async () => {
- await page.goto('/apps/files/')
- }),
- getFileListEntry: ({ page }, use) => use((fileName: string) => {
- return page.locator(`[data-cy-files-list-row-name="${fileName}"]`)
- }),
- openFile: ({ page }, use) => use(async (fileName: string) => {
- // Open the file by clicking on it in the file list
- const fileEntry = page.locator(`[data-cy-files-list-row-name="${fileName}"]`)
- await fileEntry.click()
+ filesApp: async ({ page }, use) => {
+ const filesApp = new FilesAppSection(page)
+ await use(filesApp)
+ },
+
+ setShowHiddenFiles: ({ page }, use) => use(async (show: boolean) => {
+ await page.request.put(
+ '/index.php/apps/files/api/v1/config/show_hidden',
+ {
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ data: {
+ value: show,
+ },
+ failOnStatusCode: true,
+ },
+ )
}),
})
diff --git a/playwright/support/fixtures/random-user.ts b/playwright/support/fixtures/random-user.ts
index 3d1e54f2d..20f866162 100644
--- a/playwright/support/fixtures/random-user.ts
+++ b/playwright/support/fixtures/random-user.ts
@@ -3,14 +3,13 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
+import { type User as Account } from '@nextcloud/e2e-test-server'
import { createRandomUser, login } from '@nextcloud/e2e-test-server/playwright'
import { test as base } from '@playwright/test'
import { User } from './User.ts'
-type RandomUser = Awaited>
-
export interface UserFixture {
- randomUser: RandomUser
+ account: Account
user: User
}
@@ -19,24 +18,29 @@ export interface UserFixture {
*/
export const test = base.extend({
// eslint-disable-next-line no-empty-pattern
- randomUser: async ({}, use) => {
- const randomUser = await createRandomUser()
- await use(randomUser)
+ account: async ({}, use) => {
+ const account = await createRandomUser()
+ await use(account)
},
- page: async ({ browser, baseURL, randomUser }, use) => {
+ page: async ({ account, browser, baseURL }, use) => {
// Important: make sure we authenticate in a clean environment by unsetting storage state.
const page = await browser.newPage({
storageState: undefined,
baseURL,
})
- await login(page.request, randomUser)
+ await login(page.request, account)
+ const tokenResponse = await page.request.get('./csrftoken', {
+ failOnStatusCode: true,
+ })
+ const { token } = (await tokenResponse.json()) as { token: string }
+ await page.context().setExtraHTTPHeaders({ requesttoken: token })
await use(page)
await page.close()
},
- user: async ({ page, randomUser }, use) => {
- const user = new User(page, randomUser.userId)
+ user: async ({ account, page }, use) => {
+ const user = new User(account, page)
await use(user)
},
})
diff --git a/playwright/support/sections/FilesAppSection.ts b/playwright/support/sections/FilesAppSection.ts
new file mode 100644
index 000000000..e2466dc37
--- /dev/null
+++ b/playwright/support/sections/FilesAppSection.ts
@@ -0,0 +1,33 @@
+/**
+ * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import { type Locator, type Page } from '@playwright/test'
+import { expect } from '@playwright/test'
+
+export class FilesAppSection {
+ public readonly fileListEl: Locator
+
+ constructor(public readonly page: Page) {
+ this.fileListEl = this.page.locator('.files-list')
+ }
+
+ public async open(): Promise {
+ await this.page.goto('/apps/files/')
+ }
+
+ public getFileListEntry(fileName: string): Locator {
+ return this.fileListEl.locator(`[data-cy-files-list-row-name="${fileName}"]`)
+ }
+
+ public async openFile(fileName: string): Promise {
+ const fileEntry = this.getFileListEntry(fileName)
+ await fileEntry.click()
+ }
+
+ public async hasCollectivesHeader(): Promise {
+ return await expect(this.fileListEl.locator('.filelist-collectives-wrapper'))
+ .toContainText('The content of this folder is best viewed in the Collectives app.')
+ }
+}
diff --git a/tests/Integration/features/mountpoint.feature b/tests/Integration/features/mountpoint.feature
index 064766549..b5eaefee2 100644
--- a/tests/Integration/features/mountpoint.feature
+++ b/tests/Integration/features/mountpoint.feature
@@ -21,16 +21,16 @@ Feature: mountpoint
When user "jane" creates folder "MyCollectives"
And user "jane" sees webdav node "MyCollectives"
And user "jane" creates collective "BehatMountPoint2"
- And user "jane" sees webdav node "Collectives/BehatMountPoint2"
+ And user "jane" sees webdav node ".Collectives/BehatMountPoint2"
Then user "jane" sets setting "user_folder" to value "/MyCollectives"
- And user "jane" fails to see webdav node "Collectives"
+ And user "jane" fails to see webdav node ".Collectives"
And user "jane" sees webdav node "MyCollectives"
And user "jane" sees webdav node "MyCollectives/BehatMountPoint2"
And user "jane" fails to see webdav node "MyCollectives (1)"
- Then user "jane" sets setting "user_folder" to value "/Collectives"
+ Then user "jane" sets setting "user_folder" to value "/.Collectives"
And user "jane" fails to see webdav node "MyCollectives"
- And user "jane" sees webdav node "Collectives"
- And user "jane" sees webdav node "Collectives/BehatMountPoint2"
+ And user "jane" sees webdav node ".Collectives"
+ And user "jane" sees webdav node ".Collectives/BehatMountPoint2"
Then user "jane" trashes and deletes collective "BehatMountPoint2"
Scenario: Rename non-empty node when in conflict with mountpoint
@@ -38,32 +38,32 @@ Feature: mountpoint
And user "jane" creates folder "MyCollectives/subfolder"
And user "jane" sees webdav node "MyCollectives/subfolder"
And user "jane" creates collective "BehatMountPoint3"
- And user "jane" sees webdav node "Collectives/BehatMountPoint3"
+ And user "jane" sees webdav node ".Collectives/BehatMountPoint3"
Then user "jane" sets setting "user_folder" to value "/MyCollectives"
- And user "jane" fails to see webdav node "Collectives"
+ And user "jane" fails to see webdav node ".Collectives"
And user "jane" sees webdav node "MyCollectives"
And user "jane" sees webdav node "MyCollectives/BehatMountPoint3"
And user "jane" fails to see webdav node "MyCollectives/subfolder"
And user "jane" sees webdav node "MyCollectives (1)/subfolder"
- Then user "jane" sets setting "user_folder" to value "/Collectives"
+ Then user "jane" sets setting "user_folder" to value "/.Collectives"
And user "jane" fails to see webdav node "MyCollectives"
- And user "jane" sees webdav node "Collectives"
- And user "jane" sees webdav node "Collectives/BehatMountPoint3"
+ And user "jane" sees webdav node ".Collectives"
+ And user "jane" sees webdav node ".Collectives/BehatMountPoint3"
And user "jane" deletes folder "MyCollectives (1)"
Then user "jane" trashes and deletes collective "BehatMountPoint3"
Scenario: Change collectives user folder for user
When user "bob" creates folder "some"
And user "bob" sets setting "user_folder" to value "/some/folder"
- And user "bob" fails to see webdav node "Collectives"
+ And user "bob" fails to see webdav node ".Collectives"
And user "bob" sees webdav node "some/folder"
Then user "jane" has webdav access to "BehatMountPoint" with permissions "RMGDNVCK"
And user "john" has webdav access to "BehatMountPoint" with permissions "RMGDNVCK"
And user "alice" has webdav access to "BehatMountPoint" with permissions "RMG"
And user "bob" has webdav access to "BehatMountPoint" with permissions "MG"
- Then user "bob" sets setting "user_folder" to value "/Collectives"
+ Then user "bob" sets setting "user_folder" to value "/.Collectives"
And user "bob" fails to see webdav node "some/folder"
- And user "bob" sees webdav node "Collectives"
+ And user "bob" sees webdav node ".Collectives"
And user "bob" deletes folder "some"
Scenario: Trash page via webdav
diff --git a/tests/Unit/Fs/MarkdownHelperTest.php b/tests/Unit/Fs/MarkdownHelperTest.php
index 9287c51af..60a476d3a 100644
--- a/tests/Unit/Fs/MarkdownHelperTest.php
+++ b/tests/Unit/Fs/MarkdownHelperTest.php
@@ -37,7 +37,7 @@ public function linksContentProvider(): array {
['[link](https://example.org/?foo=3#fragment)', [['link', 'https://example.org/?foo=3#fragment', '']]],
['[link](#fragment)', [['link', '#fragment', '']]],
- // With markdown marks in text
+ // With Markdown marks in text
['#Title\n\nLink: [*italic* **bold** link](https://example.org/)\n\nMore text...', [['italic bold link', 'https://example.org/', '']]],
// Multiple links
@@ -100,7 +100,7 @@ public function testGetLinkedPageIds(): void {
$pageInfo = new PageInfo();
$pageInfo->setId(123);
- $pageInfo->setCollectivePath('Collectives/' . $collective->getName());
+ $pageInfo->setCollectivePath('.Collectives/' . $collective->getName());
$pageInfo->setFilePath('page1/pageX');
$pageInfo->setFileName('subpage2.md');
$pageInfo->setTitle('subpage2');
diff --git a/tests/Unit/Fs/UserFolderHelperTest.php b/tests/Unit/Fs/UserFolderHelperTest.php
index 46d8da894..0ad3dcef5 100644
--- a/tests/Unit/Fs/UserFolderHelperTest.php
+++ b/tests/Unit/Fs/UserFolderHelperTest.php
@@ -36,7 +36,7 @@ protected function setUp(): void {
->disableOriginalConstructor()
->getMock();
$this->collectivesUserFolder->method('getName')
- ->willReturn('Collectives');
+ ->willReturn('.Collectives');
$this->userFolder = $this->getMockBuilder(Folder::class)
->disableOriginalConstructor()
@@ -83,7 +83,7 @@ public function testGetUserFolderSetting(): void {
$this->l10n->method('t')
->willReturn('Collectif');
- self::assertEquals('/Collectif', $this->helper->getUserFolderSetting('jane'));
+ self::assertEquals('/.Collectif', $this->helper->getUserFolderSetting('jane'));
$this->config->method('setUserValue')
->willThrowException(new PreConditionNotMetException(''));
diff --git a/tests/Unit/Model/PageInfoTest.php b/tests/Unit/Model/PageInfoTest.php
index 171c6c3c7..49aedcc54 100644
--- a/tests/Unit/Model/PageInfoTest.php
+++ b/tests/Unit/Model/PageInfoTest.php
@@ -22,8 +22,8 @@ public function testFromFile(): void {
$fileMTime = 0;
$fileSize = 100;
$fileName = 'name.md';
- $fileMountPoint = '/files/user/Collectives/collective/';
- $fileCollectivePath = 'Collectives/collective';
+ $fileMountPoint = '/files/user/.Collectives/collective/';
+ $fileCollectivePath = '.Collectives/collective';
$parentInternalPath = 'path/to/file';
$internalPath = $parentInternalPath . '/' . $fileName;
$userId = 'jane';
diff --git a/tests/Unit/Service/AttachmentServiceTest.php b/tests/Unit/Service/AttachmentServiceTest.php
index 2b42686a3..464846817 100644
--- a/tests/Unit/Service/AttachmentServiceTest.php
+++ b/tests/Unit/Service/AttachmentServiceTest.php
@@ -37,7 +37,7 @@ protected function setUp(): void {
->with($this->attachmentFolderName)
->willReturn(true);
$this->parentFolder->method('getRelativePath')
- ->willReturn('/Collectives/x/path/to/' . $this->attachmentFolderName . '/attachmentFile1');
+ ->willReturn('/.Collectives/x/path/to/' . $this->attachmentFolderName . '/attachmentFile1');
$attachmentFolder = $this->createMock(Folder::class);
$attachmentFolder->method('getName')
->willReturn($this->attachmentFolderName);
@@ -45,7 +45,7 @@ protected function setUp(): void {
$attachmentFile->method('getId')
->willReturn(2);
$attachmentFile->method('getPath')
- ->willReturn('/' . $this->userId . '/files/Collectives/x/path/to/' . $this->attachmentFolderName . '/attachmentFile1');
+ ->willReturn('/' . $this->userId . '/files/.Collectives/x/path/to/' . $this->attachmentFolderName . '/attachmentFile1');
$attachmentFile->method('getParent')
->willReturn($attachmentFolder);
$attachmentFile->method('getInternalPath')
@@ -72,7 +72,7 @@ public function testGetAttachments(): void {
'filesize' => null,
'mimetype' => '',
'timestamp' => null,
- 'path' => '/Collectives/x/path/to/' . $this->attachmentFolderName . '/attachmentFile1',
+ 'path' => '/.Collectives/x/path/to/' . $this->attachmentFolderName . '/attachmentFile1',
'internalPath' => '/path/to/' . $this->attachmentFolderName . '/attachmentFile1',
'hasPreview' => false,
'src' => $this->attachmentFolderName . DIRECTORY_SEPARATOR . 'attachmentFile1',
diff --git a/tests/Unit/Service/PageServiceTest.php b/tests/Unit/Service/PageServiceTest.php
index ab31342c6..7cd6a9491 100644
--- a/tests/Unit/Service/PageServiceTest.php
+++ b/tests/Unit/Service/PageServiceTest.php
@@ -204,7 +204,7 @@ private function prepareFile(string $fileName, Folder $parent, IMountPoint $moun
$file->method('getMountPoint')
->willReturn($mountPoint);
$file->method('getInternalPath')
- ->willReturn('Collectives/testfolder/' . $fileName);
+ ->willReturn('.Collectives/testfolder/' . $fileName);
$file->method('getMTime')
->willReturn(0);
$file->method('getSize')
@@ -228,7 +228,7 @@ public function testGetPagesFromFolderWithSubfolderWithoutRecurse(): void {
$mountPoint = $this->getMockBuilder(MountPoint::class)
->disableOriginalConstructor()
->getMock();
- $mountPoint->method('getMountPoint')->willReturn('/files/user/Collectives/collective/');
+ $mountPoint->method('getMountPoint')->willReturn('/files/user/.Collectives/collective/');
$indexFile = $this->prepareFile('Readme.md', $folder, $mountPoint, 101);
$folder->method('get')
@@ -267,7 +267,7 @@ public function testGetPagesFromFolderWithSubfolderWithoutRecurse(): void {
$subfolder->method('getMountPoint')
->willReturn($mountPoint);
$subfolder->method('getInternalPath')
- ->willReturn('Collectives/testfolder/' . $fileName);
+ ->willReturn('.Collectives/testfolder/' . $fileName);
$subfolder->method('getMTime')
->willReturn(0);
$subfolder->method('getSize')
@@ -305,7 +305,7 @@ public function testGetPagesFromFolderRecursive(): void {
->willReturn('testfolder');
$mountPoint = $this->createMock(IMountPoint::class);
- $mountPoint->method('getMountPoint')->willReturn('/files/user/Collectives/collective/');
+ $mountPoint->method('getMountPoint')->willReturn('/files/user/.Collectives/collective/');
$indexFile = $this->prepareFile('Readme.md', $folder, $mountPoint, 101);
$folder->method('get')
@@ -359,7 +359,7 @@ public function testGetPagesFromFolderWithMissingIndex(): void {
$mountPoint = $this->getMockBuilder(MountPoint::class)
->disableOriginalConstructor()
->getMock();
- $mountPoint->method('getMountPoint')->willReturn('/files/user/Collectives/collective/');
+ $mountPoint->method('getMountPoint')->willReturn('/files/user/.Collectives/collective/');
$folder = $this->createMock(Folder::class);
$folder->method('getParent')
@@ -380,7 +380,7 @@ public function testGetPagesFromFolderWithMissingIndex(): void {
$file1->method('getMountPoint')
->willReturn($mountPoint);
$file1->method('getInternalPath')
- ->willReturn('Collectives/testfolder/' . $file1Name);
+ ->willReturn('.Collectives/testfolder/' . $file1Name);
$file1->method('getMTime')
->willReturn(0);
$file1->method('getSize')
@@ -407,7 +407,7 @@ public function testGetPagesFromFolderWithMissingIndex(): void {
$indexFile->method('getMountPoint')
->willReturn($mountPoint);
$indexFile->method('getInternalPath')
- ->willReturn('Collectives/testfolder/Readme.md');
+ ->willReturn('.Collectives/testfolder/Readme.md');
$indexFile->method('getMTime')
->willReturn(0);
$indexFile->method('getSize')