diff --git a/frontend/cypress/e2e/permissions.spec.ts b/frontend/cypress/e2e/permissions.spec.ts
new file mode 100644
index 000000000..52c3ed117
--- /dev/null
+++ b/frontend/cypress/e2e/permissions.spec.ts
@@ -0,0 +1,115 @@
+/*
+ * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+import type { NotePermissions } from '@hedgedoc/commons'
+
+const mockPermissionChangeApiRoutes = (permission: NotePermissions) => {
+ cy.intercept('PUT', 'api/private/notes/mock-note/metadata/permissions/groups/_EVERYONE', {
+ statusCode: 200,
+ body: permission
+ })
+ cy.intercept('DELETE', 'api/private/notes/mock-note/metadata/permissions/groups/_EVERYONE', {
+ statusCode: 200,
+ body: permission
+ })
+ cy.intercept('PUT', 'api/private/notes/mock-note/metadata/permissions/groups/_LOGGED_IN', {
+ statusCode: 200,
+ body: permission
+ })
+ cy.intercept('DELETE', 'api/private/notes/mock-note/metadata/permissions/groups/_LOGGED_IN', {
+ statusCode: 200,
+ body: permission
+ })
+}
+
+describe('The permission settings modal', () => {
+ beforeEach(() => {
+ cy.visitTestNote()
+ cy.getByCypressId('sidebar-permission-btn').click()
+ })
+
+ it('can be displayed', () => {
+ cy.getByCypressId('permission-modal').should('be.visible')
+ cy.getByCypressId('permission-owner-name').contains('Mock User')
+ cy.getByCypressId('permission-setting-deny_LOGGED_IN').should('have.class', 'btn-secondary')
+ cy.getByCypressId('permission-setting-deny_EVERYONE').should('have.class', 'btn-secondary')
+ })
+
+ it('shows alert icon on invalid settings in special groups', () => {
+ cy.getByCypressId('permission-setting-deny_LOGGED_IN').should('have.class', 'btn-secondary')
+ mockPermissionChangeApiRoutes({
+ owner: 'mock',
+ sharedToUsers: [],
+ sharedToGroups: [
+ {
+ groupName: '_EVERYONE',
+ canEdit: false
+ }
+ ]
+ })
+ cy.getByCypressId('permission-setting-read_EVERYONE').click()
+ cy.get('svg.text-warning.me-2').should('be.visible')
+ mockPermissionChangeApiRoutes({
+ owner: 'mock',
+ sharedToUsers: [],
+ sharedToGroups: [
+ {
+ groupName: '_EVERYONE',
+ canEdit: true
+ }
+ ]
+ })
+ cy.getByCypressId('permission-setting-write_EVERYONE').click()
+ cy.get('svg.text-warning.me-2').should('be.visible')
+ mockPermissionChangeApiRoutes({
+ owner: 'mock',
+ sharedToUsers: [],
+ sharedToGroups: [
+ {
+ groupName: '_EVERYONE',
+ canEdit: false
+ },
+ {
+ groupName: '_LOGGED_IN',
+ canEdit: false
+ }
+ ]
+ })
+ cy.getByCypressId('permission-setting-read_LOGGED_IN').click()
+ cy.get('svg.text-warning.me-2').should('not.exist')
+ mockPermissionChangeApiRoutes({
+ owner: 'mock',
+ sharedToUsers: [],
+ sharedToGroups: [
+ {
+ groupName: '_EVERYONE',
+ canEdit: true
+ },
+ {
+ groupName: '_LOGGED_IN',
+ canEdit: false
+ }
+ ]
+ })
+ cy.getByCypressId('permission-setting-write_EVERYONE').click()
+ cy.get('svg.text-warning.me-2').should('be.visible')
+ mockPermissionChangeApiRoutes({
+ owner: 'mock',
+ sharedToUsers: [],
+ sharedToGroups: [
+ {
+ groupName: '_EVERYONE',
+ canEdit: true
+ },
+ {
+ groupName: '_LOGGED_IN',
+ canEdit: true
+ }
+ ]
+ })
+ cy.getByCypressId('permission-setting-write_LOGGED_IN').click()
+ cy.get('svg.text-warning.me-2').should('not.exist')
+ })
+})
diff --git a/frontend/cypress/support/visit-test-editor.ts b/frontend/cypress/support/visit-test-editor.ts
index b844f9e55..952470528 100644
--- a/frontend/cypress/support/visit-test-editor.ts
+++ b/frontend/cypress/support/visit-test-editor.ts
@@ -6,35 +6,37 @@
import type { Note } from '../../src/api/notes/types'
export const testNoteId = 'test'
+const mockMetadata = {
+ id: testNoteId,
+ aliases: [
+ {
+ name: 'mock-note',
+ primaryAlias: true,
+ noteId: testNoteId
+ }
+ ],
+ primaryAddress: 'mock-note',
+ title: 'Mock Note',
+ description: 'Mocked note for testing',
+ tags: ['test', 'mock', 'cypress'],
+ updatedAt: '2021-04-24T09:27:51.000Z',
+ updateUsername: null,
+ viewCount: 0,
+ version: 2,
+ createdAt: '2021-04-24T09:27:51.000Z',
+ editedBy: [],
+ permissions: {
+ owner: 'mock',
+ sharedToUsers: [],
+ sharedToGroups: []
+ }
+}
beforeEach(() => {
cy.intercept(`api/private/notes/${testNoteId}`, {
content: '',
- metadata: {
- id: testNoteId,
- aliases: [
- {
- name: 'mock-note',
- primaryAlias: true,
- noteId: testNoteId
- }
- ],
- primaryAddress: 'mock-note',
- title: 'Mock Note',
- description: 'Mocked note for testing',
- tags: ['test', 'mock', 'cypress'],
- updatedAt: '2021-04-24T09:27:51.000Z',
- updateUsername: null,
- viewCount: 0,
- version: 2,
- createdAt: '2021-04-24T09:27:51.000Z',
- editedBy: [],
- permissions: {
- owner: 'mock',
- sharedToUsers: [],
- sharedToGroups: []
- }
- },
+ metadata: mockMetadata,
editedByAtPosition: []
} as Note)
+ cy.intercept(`api/private/notes/${testNoteId}/metadata`, mockMetadata)
})
diff --git a/frontend/src/components/editor-page/sidebar/specific-sidebar-entries/permissions-sidebar-entry/permissions-modal/permission-entry-special-group.tsx b/frontend/src/components/editor-page/sidebar/specific-sidebar-entries/permissions-sidebar-entry/permissions-modal/permission-entry-special-group.tsx
index 06fb19c08..344faf513 100644
--- a/frontend/src/components/editor-page/sidebar/specific-sidebar-entries/permissions-sidebar-entry/permissions-modal/permission-entry-special-group.tsx
+++ b/frontend/src/components/editor-page/sidebar/specific-sidebar-entries/permissions-sidebar-entry/permissions-modal/permission-entry-special-group.tsx
@@ -16,6 +16,7 @@ import { ToggleButtonGroup } from 'react-bootstrap'
import { Eye as IconEye, Pencil as IconPencil, SlashCircle as IconSlashCircle } from 'react-bootstrap-icons'
import { useTranslation } from 'react-i18next'
import { PermissionInconsistentAlert } from './permission-inconsistent-alert'
+import { cypressId } from '../../../../../../utils/cypress-attribute'
export interface PermissionEntrySpecialGroupProps {
level: AccessLevel
@@ -101,6 +102,7 @@ export const PermissionEntrySpecialGroup: React.FC
diff --git a/frontend/src/components/editor-page/sidebar/specific-sidebar-entries/permissions-sidebar-entry/permissions-modal/permission-modal.tsx b/frontend/src/components/editor-page/sidebar/specific-sidebar-entries/permissions-sidebar-entry/permissions-modal/permission-modal.tsx
index da59e74e5..c747b4691 100644
--- a/frontend/src/components/editor-page/sidebar/specific-sidebar-entries/permissions-sidebar-entry/permissions-modal/permission-modal.tsx
+++ b/frontend/src/components/editor-page/sidebar/specific-sidebar-entries/permissions-sidebar-entry/permissions-modal/permission-modal.tsx
@@ -11,6 +11,7 @@ import { PermissionSectionSpecialGroups } from './permission-section-special-gro
import { PermissionSectionUsers } from './permission-section-users'
import React from 'react'
import { Modal } from 'react-bootstrap'
+import { cypressId } from '../../../../../../utils/cypress-attribute'
/**
* Modal for viewing and managing the permissions of the note.
@@ -21,7 +22,12 @@ import { Modal } from 'react-bootstrap'
export const PermissionModal: React.FC = ({ show, onHide }) => {
const isOwner = useIsOwner()
return (
-
+
diff --git a/frontend/src/components/editor-page/sidebar/specific-sidebar-entries/permissions-sidebar-entry/permissions-modal/permission-section-owner.tsx b/frontend/src/components/editor-page/sidebar/specific-sidebar-entries/permissions-sidebar-entry/permissions-modal/permission-section-owner.tsx
index 0da3a8cc3..6d49466e4 100644
--- a/frontend/src/components/editor-page/sidebar/specific-sidebar-entries/permissions-sidebar-entry/permissions-modal/permission-section-owner.tsx
+++ b/frontend/src/components/editor-page/sidebar/specific-sidebar-entries/permissions-sidebar-entry/permissions-modal/permission-section-owner.tsx
@@ -12,6 +12,7 @@ import { PermissionOwnerChange } from './permission-owner-change'
import { PermissionOwnerInfo } from './permission-owner-info'
import React, { Fragment, useCallback, useState } from 'react'
import { Trans } from 'react-i18next'
+import { cypressId } from '../../../../../../utils/cypress-attribute'
/**
* Section in the permissions modal for managing the owner of a note.
@@ -50,7 +51,9 @@ export const PermissionSectionOwner: React.FC = ({ disa
- -
+
-
{changeOwner ? (
) : (
diff --git a/frontend/src/components/editor-page/sidebar/specific-sidebar-entries/permissions-sidebar-entry/permissions-sidebar-entry.tsx b/frontend/src/components/editor-page/sidebar/specific-sidebar-entries/permissions-sidebar-entry/permissions-sidebar-entry.tsx
index 6f6e89cbf..dd35f4d95 100644
--- a/frontend/src/components/editor-page/sidebar/specific-sidebar-entries/permissions-sidebar-entry/permissions-sidebar-entry.tsx
+++ b/frontend/src/components/editor-page/sidebar/specific-sidebar-entries/permissions-sidebar-entry/permissions-sidebar-entry.tsx
@@ -10,6 +10,7 @@ import { PermissionModal } from './permissions-modal/permission-modal'
import React, { Fragment } from 'react'
import { Lock as IconLock } from 'react-bootstrap-icons'
import { Trans, useTranslation } from 'react-i18next'
+import { cypressId } from '../../../../../utils/cypress-attribute'
/**
* Renders a button to open the permission modal for the sidebar.
@@ -23,7 +24,12 @@ export const PermissionsSidebarEntry: React.FC = ({ c
return (
-
+
diff --git a/frontend/src/pages/api/private/users/mock.ts b/frontend/src/pages/api/private/users/mock.ts
new file mode 100644
index 000000000..2a790f40e
--- /dev/null
+++ b/frontend/src/pages/api/private/users/mock.ts
@@ -0,0 +1,18 @@
+/*
+ * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+import type { UserInfo } from '../../../../api/users/types'
+import { HttpMethod, respondToMatchingRequest } from '../../../../handler-utils/respond-to-matching-request'
+import type { NextApiRequest, NextApiResponse } from 'next'
+
+const handler = (req: NextApiRequest, res: NextApiResponse): void => {
+ respondToMatchingRequest(HttpMethod.GET, req, res, {
+ username: 'mock',
+ displayName: 'Mock User',
+ photoUrl: ''
+ })
+}
+
+export default handler