Ensure add comment tooltip doesnt show up without comment permissions (#27273)

* Ensure add comment tooltip doesnt show up without comment permissions

* disable comment option when no permissions in new editor

* add e2e tests

* use server pro for project sharing

* use findByRole for add comment

* remove .only

GitOrigin-RevId: fbef78e0db7678a00d6c602069e16ddeaf23b2f3
This commit is contained in:
Domagoj Kriskovic
2025-07-29 08:05:37 +00:00
committed by Copybot
parent 7c97cbbfe4
commit 9228f2248b
4 changed files with 56 additions and 14 deletions
+45 -6
View File
@@ -14,9 +14,9 @@ import { throttledRecompile } from './helpers/compile'
import { beforeWithReRunOnTestRetry } from './helpers/beforeWithReRunOnTestRetry' import { beforeWithReRunOnTestRetry } from './helpers/beforeWithReRunOnTestRetry'
describe('Project Sharing', function () { describe('Project Sharing', function () {
if (isExcludedBySharding('CE_CUSTOM_2')) return if (isExcludedBySharding('PRO_CUSTOM_2')) return
ensureUserExists({ email: 'user@example.com' }) ensureUserExists({ email: 'user@example.com' })
startWith({ withDataDir: true }) startWith({ withDataDir: true, pro: true })
let projectName: string let projectName: string
beforeWithReRunOnTestRetry(function () { beforeWithReRunOnTestRetry(function () {
@@ -135,22 +135,57 @@ describe('Project Sharing', function () {
cy.findByText('History').should('not.exist') cy.findByText('History').should('not.exist')
} }
function expectCommentAccess() {
cy.findByRole('textbox', { name: /Source Editor editing/i }).should(
'contain.text',
'\\maketitle'
)
cy.findByText('\\maketitle').parent().dblclick()
cy.findByRole('button', { name: 'Add comment' }).should('be.visible')
cy.findByRole('textbox', { name: /Source Editor editing/i }).click()
}
function expectNoCommentAccess() {
cy.findByRole('textbox', { name: /Source Editor editing/i }).should(
'contain.text',
'\\maketitle'
)
cy.findByText('\\maketitle').parent().dblclick()
cy.findByRole('button', { name: 'Add comment' }).should('not.exist')
cy.findByRole('textbox', { name: /Source Editor editing/i }).click()
}
function expectFullReadOnlyAccess() { function expectFullReadOnlyAccess() {
expectContentReadOnlyAccess() expectContentReadOnlyAccess()
expectChatAccess() expectChatAccess()
expectHistoryAccess() expectHistoryAccess()
expectNoCommentAccess()
} }
function expectRestrictedReadOnlyAccess() { function expectRestrictedReadOnlyAccess() {
expectContentReadOnlyAccess() expectContentReadOnlyAccess()
expectNoChatAccess() expectNoChatAccess()
expectNoHistoryAccess() expectNoHistoryAccess()
expectNoCommentAccess()
} }
function expectReadAndWriteAccess() { function expectFullReadAndWriteAccess() {
expectContentWriteAccess() expectContentWriteAccess()
expectChatAccess() expectChatAccess()
expectHistoryAccess() expectHistoryAccess()
expectCommentAccess()
}
function expectAnonymousReadAndWriteAccess() {
expectContentWriteAccess()
expectChatAccess()
expectHistoryAccess()
expectNoCommentAccess()
} }
function expectProjectDashboardEntry() { function expectProjectDashboardEntry() {
@@ -209,7 +244,7 @@ describe('Project Sharing', function () {
it('should grant the collaborator write access', () => { it('should grant the collaborator write access', () => {
login(email) login(email)
openProjectByName(projectName) openProjectByName(projectName)
expectReadAndWriteAccess() expectFullReadAndWriteAccess()
expectEditAuthoredAs('You') expectEditAuthoredAs('You')
expectProjectDashboardEntry() expectProjectDashboardEntry()
}) })
@@ -244,7 +279,7 @@ describe('Project Sharing', function () {
projectName, projectName,
email email
) )
expectReadAndWriteAccess() expectFullReadAndWriteAccess()
expectEditAuthoredAs('You') expectEditAuthoredAs('You')
expectProjectDashboardEntry() expectProjectDashboardEntry()
}) })
@@ -254,6 +289,7 @@ describe('Project Sharing', function () {
describe('with OVERLEAF_ALLOW_PUBLIC_ACCESS=false', () => { describe('with OVERLEAF_ALLOW_PUBLIC_ACCESS=false', () => {
describe('wrap startup', () => { describe('wrap startup', () => {
startWith({ startWith({
pro: true,
vars: { vars: {
OVERLEAF_ALLOW_PUBLIC_ACCESS: 'false', OVERLEAF_ALLOW_PUBLIC_ACCESS: 'false',
}, },
@@ -266,6 +302,7 @@ describe('Project Sharing', function () {
describe('with OVERLEAF_ALLOW_ANONYMOUS_READ_AND_WRITE_SHARING=true', () => { describe('with OVERLEAF_ALLOW_ANONYMOUS_READ_AND_WRITE_SHARING=true', () => {
startWith({ startWith({
pro: true,
vars: { vars: {
OVERLEAF_ALLOW_PUBLIC_ACCESS: 'false', OVERLEAF_ALLOW_PUBLIC_ACCESS: 'false',
OVERLEAF_ALLOW_ANONYMOUS_READ_AND_WRITE_SHARING: 'true', OVERLEAF_ALLOW_ANONYMOUS_READ_AND_WRITE_SHARING: 'true',
@@ -281,6 +318,7 @@ describe('Project Sharing', function () {
describe('with OVERLEAF_ALLOW_PUBLIC_ACCESS=true', () => { describe('with OVERLEAF_ALLOW_PUBLIC_ACCESS=true', () => {
describe('wrap startup', () => { describe('wrap startup', () => {
startWith({ startWith({
pro: true,
vars: { vars: {
OVERLEAF_ALLOW_PUBLIC_ACCESS: 'true', OVERLEAF_ALLOW_PUBLIC_ACCESS: 'true',
}, },
@@ -299,6 +337,7 @@ describe('Project Sharing', function () {
describe('with OVERLEAF_ALLOW_ANONYMOUS_READ_AND_WRITE_SHARING=true', () => { describe('with OVERLEAF_ALLOW_ANONYMOUS_READ_AND_WRITE_SHARING=true', () => {
startWith({ startWith({
pro: true,
vars: { vars: {
OVERLEAF_ALLOW_PUBLIC_ACCESS: 'true', OVERLEAF_ALLOW_PUBLIC_ACCESS: 'true',
OVERLEAF_ALLOW_ANONYMOUS_READ_AND_WRITE_SHARING: 'true', OVERLEAF_ALLOW_ANONYMOUS_READ_AND_WRITE_SHARING: 'true',
@@ -313,7 +352,7 @@ describe('Project Sharing', function () {
it('should grant write access with write link', () => { it('should grant write access with write link', () => {
openProjectViaLinkSharingAsAnon(linkSharingReadAndWrite) openProjectViaLinkSharingAsAnon(linkSharingReadAndWrite)
expectReadAndWriteAccess() expectAnonymousReadAndWriteAccess()
expectEditAuthoredAs('Anonymous') expectEditAuthoredAs('Anonymous')
}) })
}) })
@@ -23,7 +23,7 @@ export const useToolbarMenuBarEditorCommands = () => {
const { t } = useTranslation() const { t } = useTranslation()
const { view: layoutView } = useLayoutContext() const { view: layoutView } = useLayoutContext()
const editorIsVisible = layoutView === 'editor' const editorIsVisible = layoutView === 'editor'
const { trackedWrite } = usePermissionsContext() const { trackedWrite, comment } = usePermissionsContext()
const languageName = state.facet(language)?.name const languageName = state.facet(language)?.name
const isTeXFile = languageName === 'latex' const isTeXFile = languageName === 'latex'
@@ -177,7 +177,7 @@ export const useToolbarMenuBarEditorCommands = () => {
handler: () => { handler: () => {
commands.addComment() commands.addComment()
}, },
disabled: state.selection.main.empty, disabled: !comment || state.selection.main.empty,
}, },
/************************************ /************************************
* Format menu * Format menu
@@ -288,6 +288,7 @@ export const useToolbarMenuBarEditorCommands = () => {
trackedWrite, trackedWrite,
isTeXFile, isTeXFile,
state.selection.main.empty, state.selection.main.empty,
comment,
]) ])
const { toggleSymbolPalette } = useEditorPropertiesContext() const { toggleSymbolPalette } = useEditorPropertiesContext()
@@ -18,7 +18,6 @@ import {
reviewTooltipStateField, reviewTooltipStateField,
} from '@/features/source-editor/extensions/review-tooltip' } from '@/features/source-editor/extensions/review-tooltip'
import { EditorView, getTooltip } from '@codemirror/view' import { EditorView, getTooltip } from '@codemirror/view'
import useViewerPermissions from '@/shared/hooks/use-viewer-permissions'
import usePreviousValue from '@/shared/hooks/use-previous-value' import usePreviousValue from '@/shared/hooks/use-previous-value'
import { useLayoutContext } from '@/shared/context/layout-context' import { useLayoutContext } from '@/shared/context/layout-context'
import { useReviewPanelViewActionsContext } from '../context/review-panel-view-context' import { useReviewPanelViewActionsContext } from '../context/review-panel-view-context'
@@ -35,6 +34,7 @@ import { useEditorPropertiesContext } from '@/features/ide-react/context/editor-
import classNames from 'classnames' import classNames from 'classnames'
import useEventListener from '@/shared/hooks/use-event-listener' import useEventListener from '@/shared/hooks/use-event-listener'
import useReviewPanelLayout from '../hooks/use-review-panel-layout' import useReviewPanelLayout from '../hooks/use-review-panel-layout'
import { usePermissionsContext } from '@/features/ide-react/context/permissions-context'
const EDIT_MODE_SWITCH_WIDGET_HEIGHT = 40 const EDIT_MODE_SWITCH_WIDGET_HEIGHT = 40
const CM_LINE_RIGHT_PADDING = 8 const CM_LINE_RIGHT_PADDING = 8
@@ -43,7 +43,7 @@ const TOOLTIP_SHOW_DELAY = 120
const ReviewTooltipMenu: FC = () => { const ReviewTooltipMenu: FC = () => {
const state = useCodeMirrorStateContext() const state = useCodeMirrorStateContext()
const view = useCodeMirrorViewContext() const view = useCodeMirrorViewContext()
const isViewer = useViewerPermissions() const permissions = usePermissionsContext()
const [show, setShow] = useState(true) const [show, setShow] = useState(true)
const { setView } = useReviewPanelViewActionsContext() const { setView } = useReviewPanelViewActionsContext()
const { openReviewPanel } = useReviewPanelLayout() const { openReviewPanel } = useReviewPanelLayout()
@@ -58,7 +58,7 @@ const ReviewTooltipMenu: FC = () => {
const addComment = useCallback(() => { const addComment = useCallback(() => {
const { main } = view.state.selection const { main } = view.state.selection
if (main.empty) { if (main.empty || !permissions.comment) {
return return
} }
@@ -74,11 +74,11 @@ const ReviewTooltipMenu: FC = () => {
view.dispatch({ effects }) view.dispatch({ effects })
setShow(false) setShow(false)
}, [openReviewPanel, setView, setShow, view]) }, [view, permissions.comment, openReviewPanel, setView])
useEventListener('add-new-review-comment', addComment) useEventListener('add-new-review-comment', addComment)
if (isViewer || !show || !tooltipState) { if (!permissions.comment || !show || !tooltipState) {
return null return null
} }
@@ -16,6 +16,7 @@ import { isSplitTestEnabled } from '@/utils/splitTestUtils'
import { isMac } from '@/shared/utils/os' import { isMac } from '@/shared/utils/os'
import { useProjectContext } from '@/shared/context/project-context' import { useProjectContext } from '@/shared/context/project-context'
import { useEditorPropertiesContext } from '@/features/ide-react/context/editor-properties-context' import { useEditorPropertiesContext } from '@/features/ide-react/context/editor-properties-context'
import { usePermissionsContext } from '@/features/ide-react/context/permissions-context'
export const ToolbarItems: FC<{ export const ToolbarItems: FC<{
state: EditorState state: EditorState
@@ -35,6 +36,7 @@ export const ToolbarItems: FC<{
useEditorPropertiesContext() useEditorPropertiesContext()
const { writefullInstance } = useEditorContext() const { writefullInstance } = useEditorContext()
const { features } = useProjectContext() const { features } = useProjectContext()
const permissions = usePermissionsContext()
const isActive = withinFormattingCommand(state) const isActive = withinFormattingCommand(state)
const symbolPaletteAvailable = getMeta('ol-symbolPaletteAvailable') const symbolPaletteAvailable = getMeta('ol-symbolPaletteAvailable')
@@ -131,7 +133,7 @@ export const ToolbarItems: FC<{
command={commands.wrapInHref} command={commands.wrapInHref}
icon="add_link" icon="add_link"
/> />
{features.trackChangesVisible && ( {features.trackChangesVisible && permissions.comment && (
<ToolbarButton <ToolbarButton
id="toolbar-add-comment" id="toolbar-add-comment"
label={t('add_comment')} label={t('add_comment')}