summaryrefslogtreecommitdiffstats
path: root/cypress/e2e
diff options
context:
space:
mode:
Diffstat (limited to 'cypress/e2e')
-rw-r--r--cypress/e2e/files/files.cy.ts (renamed from cypress/e2e/files.cy.ts)12
-rw-r--r--cypress/e2e/files/files_sorting.cy.ts262
-rw-r--r--cypress/e2e/settings/apps.cy.ts2
-rw-r--r--cypress/e2e/settings/systemtags.cy.ts138
4 files changed, 404 insertions, 10 deletions
diff --git a/cypress/e2e/files.cy.ts b/cypress/e2e/files/files.cy.ts
index 490ddff2d0e..33261be417e 100644
--- a/cypress/e2e/files.cy.ts
+++ b/cypress/e2e/files/files.cy.ts
@@ -19,21 +19,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
-describe('Login with a new user and open the files app', function() {
- before(function() {
+describe('Files', { testIsolation: true }, () => {
+ beforeEach(() => {
cy.createRandomUser().then((user) => {
cy.login(user)
})
})
- after(function() {
- cy.logout()
- })
-
- it('See the default file welcome.txt in the files list', function() {
+ it('Login with a user and open the files app', () => {
cy.visit('/apps/files')
cy.get('[data-cy-files-list] [data-cy-files-list-row-name="welcome.txt"]').should('be.visible')
- // eslint-disable-next-line cypress/no-unnecessary-waiting -- Wait for all to finish loading
- cy.wait(500)
})
})
diff --git a/cypress/e2e/files/files_sorting.cy.ts b/cypress/e2e/files/files_sorting.cy.ts
new file mode 100644
index 00000000000..b0ce1b6d723
--- /dev/null
+++ b/cypress/e2e/files/files_sorting.cy.ts
@@ -0,0 +1,262 @@
+/**
+ * @copyright Copyright (c) 2022 John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @license AGPL-3.0-or-later
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+describe('Files: Sorting the file list', { testIsolation: true }, () => {
+ let currentUser
+ beforeEach(() => {
+ cy.createRandomUser().then((user) => {
+ currentUser = user
+ cy.login(user)
+ })
+ })
+
+ it('Files are sorted by name ascending by default', () => {
+ cy.uploadContent(currentUser, new Blob(), 'text/plain', '/1 first.txt')
+ .uploadContent(currentUser, new Blob(), 'text/plain', '/z last.txt')
+ .uploadContent(currentUser, new Blob(), 'text/plain', '/A.txt')
+ .uploadContent(currentUser, new Blob(), 'text/plain', '/Ä.txt')
+ .mkdir(currentUser, '/m')
+ .mkdir(currentUser, '/4')
+ cy.login(currentUser)
+ cy.visit('/apps/files')
+
+ cy.get('[data-cy-files-list-row]').each(($row, index) => {
+ switch (index) {
+ case 0: expect($row.attr('data-cy-files-list-row-name')).to.eq('4')
+ break
+ case 1: expect($row.attr('data-cy-files-list-row-name')).to.eq('m')
+ break
+ case 2: expect($row.attr('data-cy-files-list-row-name')).to.eq('1 first.txt')
+ break
+ case 3: expect($row.attr('data-cy-files-list-row-name')).to.eq('A.txt')
+ break
+ case 4: expect($row.attr('data-cy-files-list-row-name')).to.eq('Ä.txt')
+ break
+ case 5: expect($row.attr('data-cy-files-list-row-name')).to.eq('welcome.txt')
+ break
+ case 6: expect($row.attr('data-cy-files-list-row-name')).to.eq('z last.txt')
+ break
+ }
+ })
+ })
+
+ it('Can sort by size', () => {
+ cy.uploadContent(currentUser, new Blob(), 'text/plain', '/1 tiny.txt')
+ .uploadContent(currentUser, new Blob(['a'.repeat(1024)]), 'text/plain', '/z big.txt')
+ .uploadContent(currentUser, new Blob(['a'.repeat(512)]), 'text/plain', '/a medium.txt')
+ .mkdir(currentUser, '/folder')
+ cy.login(currentUser)
+ cy.visit('/apps/files')
+
+ // click sort button
+ cy.get('th').contains('button', 'Size').click()
+ // sorting is set
+ cy.contains('th', 'Size').should('have.attr', 'aria-sort', 'ascending')
+ // Files are sorted
+ cy.get('[data-cy-files-list-row]').each(($row, index) => {
+ switch (index) {
+ case 0: expect($row.attr('data-cy-files-list-row-name')).to.eq('1 tiny.txt')
+ break
+ case 1: expect($row.attr('data-cy-files-list-row-name')).to.eq('folder')
+ break
+ case 2: expect($row.attr('data-cy-files-list-row-name')).to.eq('welcome.txt')
+ break
+ case 3: expect($row.attr('data-cy-files-list-row-name')).to.eq('a medium.txt')
+ break
+ case 4: expect($row.attr('data-cy-files-list-row-name')).to.eq('z big.txt')
+ break
+ }
+ })
+
+ // click sort button
+ cy.get('th').contains('button', 'Size').click()
+ // sorting is set
+ cy.contains('th', 'Size').should('have.attr', 'aria-sort', 'descending')
+ // Files are sorted
+ cy.get('[data-cy-files-list-row]').each(($row, index) => {
+ switch (index) {
+ case 0: expect($row.attr('data-cy-files-list-row-name')).to.eq('z big.txt')
+ break
+ case 1: expect($row.attr('data-cy-files-list-row-name')).to.eq('a medium.txt')
+ break
+ case 2: expect($row.attr('data-cy-files-list-row-name')).to.eq('welcome.txt')
+ break
+ case 3: expect($row.attr('data-cy-files-list-row-name')).to.eq('folder')
+ break
+ case 4: expect($row.attr('data-cy-files-list-row-name')).to.eq('1 tiny.txt')
+ break
+ }
+ })
+ })
+
+ it('Can sort by mtime', () => {
+ cy.uploadContent(currentUser, new Blob(), 'text/plain', '/1.txt', Date.now() / 1000 - 86400 - 1000)
+ .uploadContent(currentUser, new Blob(['a'.repeat(1024)]), 'text/plain', '/z.txt', Date.now() / 1000 - 86400)
+ .uploadContent(currentUser, new Blob(['a'.repeat(512)]), 'text/plain', '/a.txt', Date.now() / 1000 - 86400 - 500)
+ cy.login(currentUser)
+ cy.visit('/apps/files')
+
+ // click sort button
+ cy.get('th').contains('button', 'Modified').click()
+ // sorting is set
+ cy.contains('th', 'Modified').should('have.attr', 'aria-sort', 'ascending')
+ // Files are sorted
+ cy.get('[data-cy-files-list-row]').each(($row, index) => {
+ switch (index) {
+ case 0: expect($row.attr('data-cy-files-list-row-name')).to.eq('welcome.txt') // uploaded right now
+ break
+ case 1: expect($row.attr('data-cy-files-list-row-name')).to.eq('z.txt') // fake time of yesterday
+ break
+ case 2: expect($row.attr('data-cy-files-list-row-name')).to.eq('a.txt') // fake time of yesterday and few minutes
+ break
+ case 3: expect($row.attr('data-cy-files-list-row-name')).to.eq('1.txt') // fake time of yesterday and ~15 minutes ago
+ break
+ }
+ })
+
+ // reverse order
+ cy.get('th').contains('button', 'Modified').click()
+ cy.contains('th', 'Modified').should('have.attr', 'aria-sort', 'descending')
+ cy.get('[data-cy-files-list-row]').each(($row, index) => {
+ switch (index) {
+ case 3: expect($row.attr('data-cy-files-list-row-name')).to.eq('welcome.txt') // uploaded right now
+ break
+ case 2: expect($row.attr('data-cy-files-list-row-name')).to.eq('z.txt') // fake time of yesterday
+ break
+ case 1: expect($row.attr('data-cy-files-list-row-name')).to.eq('a.txt') // fake time of yesterday and few minutes
+ break
+ case 0: expect($row.attr('data-cy-files-list-row-name')).to.eq('1.txt') // fake time of yesterday and ~15 minutes ago
+ break
+ }
+ })
+ })
+
+ it('Favorites are sorted first', () => {
+ cy.uploadContent(currentUser, new Blob(), 'text/plain', '/1.txt', Date.now() / 1000 - 86400 - 1000)
+ .uploadContent(currentUser, new Blob(['a'.repeat(1024)]), 'text/plain', '/z.txt', Date.now() / 1000 - 86400)
+ .uploadContent(currentUser, new Blob(['a'.repeat(512)]), 'text/plain', '/a.txt', Date.now() / 1000 - 86400 - 500)
+ .setFileAsFavorite(currentUser, '/a.txt')
+ cy.login(currentUser)
+ cy.visit('/apps/files')
+
+ cy.log('By name - ascending')
+ cy.get('th').contains('button', 'Name').click()
+ cy.contains('th', 'Name').should('have.attr', 'aria-sort', 'ascending')
+
+ cy.get('[data-cy-files-list-row]').each(($row, index) => {
+ switch (index) {
+ case 0: expect($row.attr('data-cy-files-list-row-name')).to.eq('a.txt')
+ break
+ case 1: expect($row.attr('data-cy-files-list-row-name')).to.eq('1.txt')
+ break
+ case 2: expect($row.attr('data-cy-files-list-row-name')).to.eq('welcome.txt')
+ break
+ case 3: expect($row.attr('data-cy-files-list-row-name')).to.eq('z.txt')
+ break
+ }
+ })
+
+ cy.log('By name - descending')
+ cy.get('th').contains('button', 'Name').click()
+ cy.contains('th', 'Name').should('have.attr', 'aria-sort', 'descending')
+
+ cy.get('[data-cy-files-list-row]').each(($row, index) => {
+ switch (index) {
+ case 0: expect($row.attr('data-cy-files-list-row-name')).to.eq('a.txt')
+ break
+ case 3: expect($row.attr('data-cy-files-list-row-name')).to.eq('1.txt')
+ break
+ case 2: expect($row.attr('data-cy-files-list-row-name')).to.eq('welcome.txt')
+ break
+ case 1: expect($row.attr('data-cy-files-list-row-name')).to.eq('z.txt')
+ break
+ }
+ })
+
+ cy.log('By size - ascending')
+ cy.get('th').contains('button', 'Size').click()
+ cy.contains('th', 'Size').should('have.attr', 'aria-sort', 'ascending')
+
+ cy.get('[data-cy-files-list-row]').each(($row, index) => {
+ switch (index) {
+ case 0: expect($row.attr('data-cy-files-list-row-name')).to.eq('a.txt')
+ break
+ case 1: expect($row.attr('data-cy-files-list-row-name')).to.eq('1.txt')
+ break
+ case 2: expect($row.attr('data-cy-files-list-row-name')).to.eq('welcome.txt')
+ break
+ case 3: expect($row.attr('data-cy-files-list-row-name')).to.eq('z.txt')
+ break
+ }
+ })
+
+ cy.log('By size - descending')
+ cy.get('th').contains('button', 'Size').click()
+ cy.contains('th', 'Size').should('have.attr', 'aria-sort', 'descending')
+
+ cy.get('[data-cy-files-list-row]').each(($row, index) => {
+ switch (index) {
+ case 0: expect($row.attr('data-cy-files-list-row-name')).to.eq('a.txt')
+ break
+ case 3: expect($row.attr('data-cy-files-list-row-name')).to.eq('1.txt')
+ break
+ case 2: expect($row.attr('data-cy-files-list-row-name')).to.eq('welcome.txt')
+ break
+ case 1: expect($row.attr('data-cy-files-list-row-name')).to.eq('z.txt')
+ break
+ }
+ })
+
+ cy.log('By mtime - ascending')
+ cy.get('th').contains('button', 'Modified').click()
+ cy.contains('th', 'Modified').should('have.attr', 'aria-sort', 'ascending')
+
+ cy.get('[data-cy-files-list-row]').each(($row, index) => {
+ switch (index) {
+ case 0: expect($row.attr('data-cy-files-list-row-name')).to.eq('a.txt')
+ break
+ case 1: expect($row.attr('data-cy-files-list-row-name')).to.eq('welcome.txt')
+ break
+ case 2: expect($row.attr('data-cy-files-list-row-name')).to.eq('z.txt')
+ break
+ case 3: expect($row.attr('data-cy-files-list-row-name')).to.eq('1.txt')
+ break
+ }
+ })
+
+ cy.log('By mtime - descending')
+ cy.get('th').contains('button', 'Modified').click()
+ cy.contains('th', 'Modified').should('have.attr', 'aria-sort', 'descending')
+
+ cy.get('[data-cy-files-list-row]').each(($row, index) => {
+ switch (index) {
+ case 0: expect($row.attr('data-cy-files-list-row-name')).to.eq('a.txt')
+ break
+ case 1: expect($row.attr('data-cy-files-list-row-name')).to.eq('1.txt')
+ break
+ case 2: expect($row.attr('data-cy-files-list-row-name')).to.eq('z.txt')
+ break
+ case 3: expect($row.attr('data-cy-files-list-row-name')).to.eq('welcome.txt')
+ break
+ }
+ })
+ })
+})
diff --git a/cypress/e2e/settings/apps.cy.ts b/cypress/e2e/settings/apps.cy.ts
index 516ddd0cf82..8bec0bd00f4 100644
--- a/cypress/e2e/settings/apps.cy.ts
+++ b/cypress/e2e/settings/apps.cy.ts
@@ -125,7 +125,7 @@ describe('Settings: App management', { testIsolation: true }, () => {
it('View app details', () => {
// When I click on the "QA testing" app
- cy.get('#apps-list').contains('tr', 'QA testing').click({ force: true })
+ cy.get('#apps-list').contains('a', 'QA testing').click({ force: true })
// I see that the app details are shown
cy.get('#app-sidebar-vue')
.should('be.visible')
diff --git a/cypress/e2e/settings/systemtags.cy.ts b/cypress/e2e/settings/systemtags.cy.ts
new file mode 100644
index 00000000000..3c9a8b25cf4
--- /dev/null
+++ b/cypress/e2e/settings/systemtags.cy.ts
@@ -0,0 +1,138 @@
+/**
+ * @copyright 2023 Christopher Ng <chrng8@gmail.com>
+ *
+ * @author Christopher Ng <chrng8@gmail.com>
+ *
+ * @license AGPL-3.0-or-later
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+import { User } from '@nextcloud/cypress'
+
+const admin = new User('admin', 'admin')
+
+const tagName = 'foo'
+const updatedTagName = 'bar'
+
+describe('Create system tags', () => {
+ before(() => {
+ cy.login(admin)
+ cy.visit('/settings/admin')
+ })
+
+ it('Can create a tag', () => {
+ cy.get('input#system-tag-name').should('exist').and('have.value', '')
+ cy.get('input#system-tag-name').type(tagName)
+ cy.get('input#system-tag-name').should('have.value', tagName)
+ // submit the form
+ cy.get('input#system-tag-name').type('{enter}')
+
+ // see that the created tag is in the list
+ cy.get('input#system-tags-input').focus()
+ cy.get('input#system-tags-input').invoke('attr', 'aria-controls').then(id => {
+ cy.get(`ul#${id}`).within(() => {
+ cy.contains('li', tagName).should('exist')
+ // ensure only one tag exists
+ cy.get('li').should('have.length', 1)
+ })
+ })
+ })
+})
+
+describe('Update system tags', { testIsolation: false }, () => {
+ before(() => {
+ cy.login(admin)
+ cy.visit('/settings/admin')
+ })
+
+ it('select the tag', () => {
+ // select the tag to edit
+ cy.get('input#system-tags-input').focus()
+ cy.get('input#system-tags-input').invoke('attr', 'aria-controls').then(id => {
+ cy.get(`ul#${id}`).within(() => {
+ cy.contains('li', tagName).should('exist').click()
+ })
+ })
+ // see that the tag name matches the selected tag
+ cy.get('input#system-tag-name').should('exist').and('have.value', tagName)
+ // see that the tag level matches the selected tag
+ cy.get('input#system-tag-level').click()
+ cy.get('input#system-tag-level').siblings('.vs__selected').contains('Public').should('exist')
+ })
+
+ it('update the tag name and level', () => {
+ cy.get('input#system-tag-name').clear()
+ cy.get('input#system-tag-name').type(updatedTagName)
+ cy.get('input#system-tag-name').should('have.value', updatedTagName)
+ // select the new tag level
+ cy.get('input#system-tag-level').focus()
+ cy.get('input#system-tag-level').invoke('attr', 'aria-controls').then(id => {
+ cy.get(`ul#${id}`).within(() => {
+ cy.contains('li', 'Invisible').should('exist').click()
+ })
+ })
+ // submit the form
+ cy.get('input#system-tag-name').type('{enter}')
+ })
+
+ it('see the tag was successfully updated', () => {
+ cy.get('input#system-tags-input').focus()
+ cy.get('input#system-tags-input').invoke('attr', 'aria-controls').then(id => {
+ cy.get(`ul#${id}`).within(() => {
+ cy.contains('li', `${updatedTagName} (invisible)`).should('exist')
+ // ensure only one tag exists
+ cy.get('li').should('have.length', 1)
+ })
+ })
+ })
+})
+
+describe('Delete system tags', { testIsolation: false }, () => {
+ before(() => {
+ cy.login(admin)
+ cy.visit('/settings/admin')
+ })
+
+ it('select the tag', () => {
+ // select the tag to edit
+ cy.get('input#system-tags-input').focus()
+ cy.get('input#system-tags-input').invoke('attr', 'aria-controls').then(id => {
+ cy.get(`ul#${id}`).within(() => {
+ cy.contains('li', `${updatedTagName} (invisible)`).should('exist').click()
+ })
+ })
+ // see that the tag name matches the selected tag
+ cy.get('input#system-tag-name').should('exist').and('have.value', updatedTagName)
+ // see that the tag level matches the selected tag
+ cy.get('input#system-tag-level').focus()
+ cy.get('input#system-tag-level').siblings('.vs__selected').contains('Invisible').should('exist')
+ })
+
+ it('can delete the tag', () => {
+ cy.get('.system-tag-form__row').within(() => {
+ cy.contains('button', 'Delete').should('be.enabled').click()
+ })
+ })
+
+ it('see that the deleted tag is not present', () => {
+ cy.get('input#system-tags-input').focus()
+ cy.get('input#system-tags-input').invoke('attr', 'aria-controls').then(id => {
+ cy.get(`ul#${id}`).within(() => {
+ cy.contains('li', updatedTagName).should('not.exist')
+ })
+ })
+ })
+})