From 607a36b72e0a269b033f51ab3b528b8d862c6736 Mon Sep 17 00:00:00 2001 From: Malik Glossop Date: Tue, 10 Feb 2026 10:58:25 +0100 Subject: [PATCH] Merge pull request #31415 from overleaf/mg-workbench-add-tests Lazy load the Citation Review in the workbench and add test coverage GitOrigin-RevId: cf4da6eb410404e284f126109609b0042e0a3cd1 --- .../frontend/features/workbench/chat.spec.tsx | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 services/web/test/frontend/features/workbench/chat.spec.tsx diff --git a/services/web/test/frontend/features/workbench/chat.spec.tsx b/services/web/test/frontend/features/workbench/chat.spec.tsx new file mode 100644 index 0000000000..06bafe92ae --- /dev/null +++ b/services/web/test/frontend/features/workbench/chat.spec.tsx @@ -0,0 +1,139 @@ +import { consentTutorialKey } from '@modules/workbench/frontend/js/components/chat' +import Workbench from '@modules/workbench/frontend/js/components/workbench' +import { EditorProviders } from '../../helpers/editor-providers' +import { EditorView } from '@codemirror/view' +import type { FC, PropsWithChildren } from 'react' +import { EditorViewContext } from '@/features/ide-react/context/editor-view-context' + +describe('Workbench', { scrollBehavior: false }, function () { + beforeEach(function () { + cy.window().then(win => { + win.metaAttributesCache.set('ol-showAiErrorAssistant', true) + win.metaAttributesCache.set('ol-splitTestVariants', { + 'ai-workbench-release': 'enabled', + }) + win.metaAttributesCache.set('ol-inactiveTutorials', [consentTutorialKey]) + }) + }) + + const EditorViewProvider: FC = ({ children }) => ( + + {children} + + ) + + const Providers: FC> = ({ + children, + aiAssistEnabled = true, + }) => { + return ( + +
{children}
+
+ ) + } + + describe('when AI assist is enabled and consent is given', function () { + it('should show the chat interface', function () { + cy.mount( + + + + ) + + cy.get('textarea').should('exist').and('be.visible') + cy.get('.conversation-footer').should('not.have.attr', 'inert') + + cy.contains('Supporting your research').should('not.exist') + + cy.contains('Get early access').should('not.exist') + + cy.contains('AI can make mistakes').should('exist') + }) + }) + + describe('when AI assist is enabled but consent not yet given', function () { + beforeEach(function () { + cy.window().then(win => { + win.metaAttributesCache.set('ol-inactiveTutorials', []) + }) + + cy.mount( + + + + ) + }) + + it('should show consent screen', function () { + cy.get('.workbench-consent-prompt').should('exist') + cy.contains('Supporting your research').should('be.visible') + + cy.findByRole('button', { name: /accept and continue/i }).should('exist') + + cy.contains('Get early access').should('not.exist') + + cy.get('.conversation-footer').should('have.attr', 'inert', 'true') + }) + + it('should hide consent and show chat after accepting', function () { + cy.intercept('POST', '/user/tutorials/*', { statusCode: 204 }).as( + 'completeTutorial' + ) + cy.intercept('POST', '/tutorial/workbench-consent-release/complete', { + statusCode: 205, + }).as('completeConsentTutorial') + + cy.get('.workbench-consent-prompt').should('be.visible') + + cy.findByRole('button', { name: /accept and continue/i }).click() + + cy.wait('@completeConsentTutorial') + + cy.get('.workbench-consent-prompt').should('not.exist') + }) + }) + + describe('when AI assist is not enabled', function () { + beforeEach(function () { + cy.window().then(win => { + win.metaAttributesCache.set('ol-showAiErrorAssistant', false) + }) + cy.mount( + + + + ) + }) + it('should show upgrade notification', function () { + cy.get('.workbench-upgrade-notification').should('exist') + cy.contains('Get early access').should('be.visible') + + cy.findByRole('button', { name: /get ai assist/i }).should('exist') + + cy.get('.workbench-consent-prompt').should('not.exist') + + cy.get('.conversation-footer').should('have.attr', 'inert', 'true') + }) + + it('should dispatch paywall event when clicking upgrade button', function () { + const paywallSpy = cy.spy().as('paywallSpy') + cy.window().then(win => { + win.addEventListener('aiAssist:showPaywall', paywallSpy) + }) + + cy.findByRole('button', { name: /get ai assist/i }).click() + + // Should dispatch the paywall event + cy.get('@paywallSpy').should('have.been.calledOnce') + }) + }) +})