aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files
diff options
context:
space:
mode:
authorJohn Molakvoæ <skjnldsv@protonmail.com>2022-12-28 15:29:54 +0100
committerJohn Molakvoæ <skjnldsv@protonmail.com>2023-01-04 16:46:14 +0100
commit5b9a8f0407a9e3fe7e00f0fc9284ea986905f1b5 (patch)
tree1363678dab6ed5e1554a7a74bc8a6a1a55bdf785 /apps/files
parent8f1bf13ae3046400ce6248fb13e5515e8e9ed5c4 (diff)
downloadnextcloud-server-5b9a8f0407a9e3fe7e00f0fc9284ea986905f1b5.tar.gz
nextcloud-server-5b9a8f0407a9e3fe7e00f0fc9284ea986905f1b5.zip
Add component testing
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
Diffstat (limited to 'apps/files')
-rw-r--r--apps/files/js/app.js6
-rw-r--r--apps/files/js/filelist.js2
-rw-r--r--apps/files/lib/Controller/ApiController.php4
-rw-r--r--apps/files/lib/Service/UserConfig.php9
-rw-r--r--apps/files/src/views/Navigation.cy.ts118
-rw-r--r--apps/files/src/views/Navigation.vue34
-rw-r--r--apps/files/src/views/Settings.vue20
7 files changed, 161 insertions, 32 deletions
diff --git a/apps/files/js/app.js b/apps/files/js/app.js
index 36d80c03770..f0c3ac5c212 100644
--- a/apps/files/js/app.js
+++ b/apps/files/js/app.js
@@ -136,7 +136,6 @@
this._setupEvents();
// trigger URL change event handlers
- console.debug('F2V init', { ...OC.Util.History.parseUrlQuery(), view: this.navigation?.active?.id })
this._onPopState({ ...OC.Util.History.parseUrlQuery(), view: this.navigation?.active?.id });
this._debouncedPersistShowHiddenFilesState = _.debounce(this._persistShowHiddenFilesState, 1200);
@@ -310,7 +309,6 @@
* Event handler for when the URL changed
*/
_onPopState: function(params) {
- console.debug('F2V onPopState', params);
params = _.extend({
dir: '/',
view: 'files'
@@ -348,7 +346,6 @@
* Change the URL to point to the given dir and view
*/
_changeUrl: function(view, dir, fileId) {
- console.debug('F2V changeUrl', { arguments });
var params = { dir: dir };
if (view !== 'files') {
params.view = view;
@@ -359,16 +356,13 @@
if (currentParams.dir === params.dir && currentParams.view === params.view) {
if (currentParams.fileid !== params.fileid) {
// if only fileid changed or was added, replace instead of push
- console.debug('F2V 1', currentParams.fileid, params.fileid, params);
OC.Util.History.replaceState(this._makeUrlParams(params));
return
}
} else {
- console.debug('F2V 2', params);
OC.Util.History.pushState(this._makeUrlParams(params));
return
}
- console.debug('F2V 3', params, currentParams);
},
/**
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index 4feb7ad990d..a74cc79a83f 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -756,7 +756,6 @@
* Event handler when leaving previously hidden state
*/
_onShow: function(e) {
- console.debug('F2V onShow', [e.dir, e.itemId], e);
OCA.Files.App && OCA.Files.App.updateCurrentFileList(this);
if (e.itemId === this.id) {
this._setCurrentDir('/', false);
@@ -771,7 +770,6 @@
* Event handler for when the URL changed
*/
_onUrlChanged: function(e) {
- console.debug('F2V onUrlChanged', [e.dir], e);
if (e && _.isString(e.dir)) {
var currentDir = this.getCurrentDirectory();
// this._currentDirectory is NULL when fileList is first initialised
diff --git a/apps/files/lib/Controller/ApiController.php b/apps/files/lib/Controller/ApiController.php
index e9d15018d03..76597b7a018 100644
--- a/apps/files/lib/Controller/ApiController.php
+++ b/apps/files/lib/Controller/ApiController.php
@@ -285,13 +285,13 @@ class ApiController extends Controller {
*
* @NoAdminRequired
*
- * @param bool $key
+ * @param string $key
* @param string|bool $value
* @return JSONResponse
*/
public function setConfig(string $key, string|bool $value): JSONResponse {
try {
- $this->userConfig->setConfig($key, $value);
+ $this->userConfig->setConfig($key, (string)$value);
} catch (\InvalidArgumentException $e) {
return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
}
diff --git a/apps/files/lib/Service/UserConfig.php b/apps/files/lib/Service/UserConfig.php
index e3b863c7333..7ccf7008512 100644
--- a/apps/files/lib/Service/UserConfig.php
+++ b/apps/files/lib/Service/UserConfig.php
@@ -41,8 +41,9 @@ class UserConfig {
],
];
- private IConfig $config;
- private IUser|null $user;
+ protected IConfig $config;
+ /** @var \OCP\IUser|null */
+ protected mixed $user = null;
public function __construct(IConfig $config, IUserSession $userSession) {
$this->config = $config;
@@ -98,7 +99,7 @@ class UserConfig {
* @throws \InvalidArgumentException
*/
public function setConfig($key, $value) {
- if (!$this->user) {
+ if ($this->user === null) {
throw new \Exception('No user logged in');
}
@@ -123,7 +124,7 @@ class UserConfig {
* @return array
*/
public function getConfigs(): array {
- if (!$this->user) {
+ if ($this->user === null) {
throw new \Exception('No user logged in');
}
diff --git a/apps/files/src/views/Navigation.cy.ts b/apps/files/src/views/Navigation.cy.ts
new file mode 100644
index 00000000000..1c0ecf6e4b4
--- /dev/null
+++ b/apps/files/src/views/Navigation.cy.ts
@@ -0,0 +1,118 @@
+/* eslint-disable import/first */
+import FolderSvg from '@mdi/svg/svg/folder.svg'
+import ShareSvg from '@mdi/svg/svg/share-variant.svg'
+
+import NavigationService from '../services/Navigation'
+import NavigationView from './Navigation.vue'
+import router from '../router/router.js'
+
+const Navigation = new NavigationService()
+
+console.log(FolderSvg)
+
+describe('Navigation renders', () => {
+ it('renders', () => {
+ cy.mount(NavigationView, {
+ propsData: {
+ Navigation,
+ },
+ })
+
+ cy.get('[data-cy-files-navigation]').should('be.visible')
+ cy.get('[data-cy-files-navigation-settings-button]').should('be.visible')
+ })
+})
+
+describe('Navigation API', () => {
+ it('Check API entries rendering', () => {
+ Navigation.register({
+ id: 'files',
+ name: 'Files',
+ getFiles: () => [],
+ icon: FolderSvg,
+ order: 1,
+ })
+
+ cy.mount(NavigationView, {
+ propsData: {
+ Navigation,
+ },
+ router,
+ })
+
+ cy.get('[data-cy-files-navigation]').should('be.visible')
+ cy.get('[data-cy-files-navigation-item]').should('have.length', 1)
+ cy.get('[data-cy-files-navigation-item="files"]').should('be.visible')
+ cy.get('[data-cy-files-navigation-item="files"]').should('contain.text', 'Files')
+ })
+
+ it('Adds a new entry and render', () => {
+ Navigation.register({
+ id: 'sharing',
+ name: 'Sharing',
+ getFiles: () => [],
+ icon: ShareSvg,
+ order: 2,
+ })
+
+ cy.mount(NavigationView, {
+ propsData: {
+ Navigation,
+ },
+ router,
+ })
+
+ cy.get('[data-cy-files-navigation]').should('be.visible')
+ cy.get('[data-cy-files-navigation-item]').should('have.length', 2)
+ cy.get('[data-cy-files-navigation-item="sharing"]').should('be.visible')
+ cy.get('[data-cy-files-navigation-item="sharing"]').should('contain.text', 'Sharing')
+ })
+
+ it('Adds a new children, render and open menu', () => {
+ Navigation.register({
+ id: 'sharingin',
+ name: 'Shared with me',
+ getFiles: () => [],
+ parent: 'sharing',
+ icon: ShareSvg,
+ order: 1,
+ })
+
+ cy.mount(NavigationView, {
+ propsData: {
+ Navigation,
+ },
+ router,
+ })
+
+ cy.get('[data-cy-files-navigation]').should('be.visible')
+ cy.get('[data-cy-files-navigation-item]').should('have.length', 3)
+
+ // Intercept collapse preference request
+ cy.intercept('POST', '*/apps/files/api/v1/toggleShowFolder/*', {
+ statusCode: 200,
+ }).as('toggleShowFolder')
+
+ // Toggle the sharing entry children
+ cy.get('[data-cy-files-navigation-item="sharing"] button.icon-collapse').should('exist')
+ cy.get('[data-cy-files-navigation-item="sharing"] button.icon-collapse').click({ force: true })
+ cy.wait('@toggleShowFolder')
+
+ // Validate children
+ cy.get('[data-cy-files-navigation-item="sharingin"]').should('be.visible')
+ cy.get('[data-cy-files-navigation-item="sharingin"]').should('contain.text', 'Shared with me')
+
+ })
+
+ it('Throws when adding a duplicate entry', () => {
+ expect(() => {
+ Navigation.register({
+ id: 'files',
+ name: 'Files',
+ getFiles: () => [],
+ icon: FolderSvg,
+ order: 1,
+ })
+ }).to.throw('Navigation id files is already registered')
+ })
+})
diff --git a/apps/files/src/views/Navigation.vue b/apps/files/src/views/Navigation.vue
index 9c543d876c5..0a7edc3bef9 100644
--- a/apps/files/src/views/Navigation.vue
+++ b/apps/files/src/views/Navigation.vue
@@ -20,22 +20,24 @@
-
-->
<template>
- <NcAppNavigation>
+ <NcAppNavigation data-cy-files-navigation>
<template #list>
<NcAppNavigationItem v-for="view in parentViews"
:key="view.id"
:allow-collapse="true"
- :to="{name: 'filelist', params: { view: view.id }}"
+ :data-cy-files-navigation-item="view.id"
:icon="view.iconClass"
:open="view.expanded"
:pinned="view.sticky"
:title="view.name"
+ :to="{name: 'filelist', params: { view: view.id }}"
@update:open="onToggleExpand(view)">
<NcAppNavigationItem v-for="child in childViews[view.id]"
:key="child.id"
- :to="{name: 'filelist', params: { view: child.id }}"
+ :data-cy-files-navigation-item="child.id"
:icon="child.iconClass"
- :title="child.name" />
+ :title="child.name"
+ :to="{name: 'filelist', params: { view: child.id }}" />
</NcAppNavigationItem>
</template>
@@ -44,6 +46,7 @@
<ul class="app-navigation-entry__settings">
<NcAppNavigationItem :aria-label="t('files', 'Open the files app settings')"
:title="t('files', 'Files settings')"
+ data-cy-files-navigation-settings-button
@click.prevent.stop="openSettings">
<Cog slot="icon" :size="20" />
</NcAppNavigationItem>
@@ -52,6 +55,7 @@
<!-- Settings modal-->
<SettingsModal :open="settingsOpened"
+ data-cy-files-navigation-settings
@close="onSettingsClose" />
</NcAppNavigation>
</template>
@@ -60,13 +64,15 @@
import { emit, subscribe } from '@nextcloud/event-bus'
import { generateUrl } from '@nextcloud/router'
import axios from '@nextcloud/axios'
+import Cog from 'vue-material-design-icons/Cog.vue'
import NcAppNavigation from '@nextcloud/vue/dist/Components/NcAppNavigation.js'
import NcAppNavigationItem from '@nextcloud/vue/dist/Components/NcAppNavigationItem.js'
-import Cog from 'vue-material-design-icons/Cog.vue'
-import SettingsModal from './Settings.vue'
-import Navigation from '../services/Navigation.ts'
import logger from '../logger.js'
+import Navigation from '../services/Navigation.ts'
+import SettingsModal from './Settings.vue'
+
+import { translate } from '@nextcloud/l10n'
export default {
name: 'Navigation',
@@ -152,7 +158,7 @@ export default {
*/
showView(view, oldView) {
// Closing any opened sidebar
- OCA.Files?.Sidebar?.close?.()
+ window?.OCA?.Files?.Sidebar?.close?.()
if (view.legacy) {
const newAppContent = document.querySelector('#app-content #app-content-' + this.currentView.id + '.viewcontainer')
@@ -161,9 +167,6 @@ export default {
})
newAppContent.classList.remove('hidden')
- // Legacy event
- console.debug('F2V', $(newAppContent))
-
// Trigger init if not already done
window.jQuery(newAppContent).trigger(new window.jQuery.Event('show'))
@@ -171,7 +174,6 @@ export default {
this.$nextTick(() => {
const { dir = '/' } = OC.Util.History.parseUrlQuery()
const params = { itemId: view.id, dir }
- console.debug('F2V showView events', params, newAppContent);
window.jQuery(newAppContent).trigger(new window.jQuery.Event('show', params))
window.jQuery(newAppContent).trigger(new window.jQuery.Event('urlChanged', params))
})
@@ -212,20 +214,20 @@ export default {
},
/**
- * Open the settings modal and update the settings API entries
+ * Open the settings modal
*/
openSettings() {
this.settingsOpened = true
- OCA.Files.Settings.settings.forEach(setting => setting.open())
},
/**
- * Close the settings modal and update the settings API entries
+ * Close the settings modal
*/
onSettingsClose() {
this.settingsOpened = false
- OCA.Files.Settings.settings.forEach(setting => setting.close())
},
+
+ t: translate,
},
}
</script>
diff --git a/apps/files/src/views/Settings.vue b/apps/files/src/views/Settings.vue
index fdb4343903c..0f8432445aa 100644
--- a/apps/files/src/views/Settings.vue
+++ b/apps/files/src/views/Settings.vue
@@ -67,8 +67,12 @@ import { getCurrentUser } from '@nextcloud/auth'
import { loadState } from '@nextcloud/initial-state'
import { emit } from '@nextcloud/event-bus'
import axios from '@nextcloud/axios'
+import { translate } from '@nextcloud/l10n'
-const userConfig = loadState('files', 'config')
+const userConfig = loadState('files', 'config', {
+ show_hidden: false,
+ crop_image_previews: true,
+})
export default {
name: 'Settings',
@@ -93,7 +97,7 @@ export default {
...userConfig,
// Settings API
- settings: OCA.Files.Settings.settings,
+ settings: window.OCA?.Files?.Settings?.settings || [],
// Webdav infos
webdavUrl: generateRemoteUrl('dav/files/' + encodeURIComponent(getCurrentUser()?.uid)),
@@ -101,6 +105,16 @@ export default {
}
},
+ beforeMount() {
+ // Update the settings API entries state
+ this.settings.forEach(setting => setting.open())
+ },
+
+ beforeDestroy() {
+ // Update the settings API entries state
+ this.settings.forEach(setting => setting.close())
+ },
+
methods: {
onClose() {
this.$emit('close')
@@ -112,6 +126,8 @@ export default {
value,
})
},
+
+ t: translate,
},
}
</script>