From 1720ef19f4d3c29f3f990d6bd8e26d6653cce8bd Mon Sep 17 00:00:00 2001 From: David <33458145+davidmcpowell@users.noreply.github.com> Date: Tue, 21 Oct 2025 11:45:54 +0100 Subject: [PATCH] Merge pull request #29113 from overleaf/dp-settings-modal-tests Add frontend tests for new editor settings modal GitOrigin-RevId: a7142b5b45e9484126d159445f2dddd7d3c86584 --- .../settings-modal/settings-modal.test.tsx | 126 ++++++++++++++++++ .../auto-close-brackets-setting.test.tsx | 51 +++++++ .../settings/auto-complete-setting.test.tsx | 51 +++++++ .../settings/code-check-setting.test.tsx | 51 +++++++ .../settings/compiler-setting.test.tsx | 36 +++++ .../settings/dictionary-setting.test.tsx | 35 +++++ .../settings/editor-theme-setting.test.tsx | 45 +++++++ .../settings/font-family-setting.test.tsx | 35 +++++ .../settings/font-size-setting.test.tsx | 31 +++++ .../settings/image-name-setting.test.tsx | 47 +++++++ .../settings/keybinding-setting.test.tsx | 33 +++++ .../settings/line-height-setting.test.tsx | 33 +++++ .../settings/math-preview-setting.test.tsx | 51 +++++++ .../settings/overall-theme-setting.test.tsx | 99 ++++++++++++++ .../settings/pdf-viewer-setting.test.tsx | 30 +++++ .../settings/root-document-setting.test.tsx | 51 +++++++ .../settings/spell-check-setting.test.tsx | 50 +++++++ 17 files changed, 855 insertions(+) create mode 100644 services/web/test/frontend/features/settings-modal/settings-modal.test.tsx create mode 100644 services/web/test/frontend/features/settings-modal/settings/auto-close-brackets-setting.test.tsx create mode 100644 services/web/test/frontend/features/settings-modal/settings/auto-complete-setting.test.tsx create mode 100644 services/web/test/frontend/features/settings-modal/settings/code-check-setting.test.tsx create mode 100644 services/web/test/frontend/features/settings-modal/settings/compiler-setting.test.tsx create mode 100644 services/web/test/frontend/features/settings-modal/settings/dictionary-setting.test.tsx create mode 100644 services/web/test/frontend/features/settings-modal/settings/editor-theme-setting.test.tsx create mode 100644 services/web/test/frontend/features/settings-modal/settings/font-family-setting.test.tsx create mode 100644 services/web/test/frontend/features/settings-modal/settings/font-size-setting.test.tsx create mode 100644 services/web/test/frontend/features/settings-modal/settings/image-name-setting.test.tsx create mode 100644 services/web/test/frontend/features/settings-modal/settings/keybinding-setting.test.tsx create mode 100644 services/web/test/frontend/features/settings-modal/settings/line-height-setting.test.tsx create mode 100644 services/web/test/frontend/features/settings-modal/settings/math-preview-setting.test.tsx create mode 100644 services/web/test/frontend/features/settings-modal/settings/overall-theme-setting.test.tsx create mode 100644 services/web/test/frontend/features/settings-modal/settings/pdf-viewer-setting.test.tsx create mode 100644 services/web/test/frontend/features/settings-modal/settings/root-document-setting.test.tsx create mode 100644 services/web/test/frontend/features/settings-modal/settings/spell-check-setting.test.tsx diff --git a/services/web/test/frontend/features/settings-modal/settings-modal.test.tsx b/services/web/test/frontend/features/settings-modal/settings-modal.test.tsx new file mode 100644 index 0000000000..b28f19bbb6 --- /dev/null +++ b/services/web/test/frontend/features/settings-modal/settings-modal.test.tsx @@ -0,0 +1,126 @@ +import { screen, render } from '@testing-library/react' +import { expect } from 'chai' +import fetchMock from 'fetch-mock' +import { EditorProviders } from '../../helpers/editor-providers' +import SettingsModal from '@/features/ide-redesign/components/settings/settings-modal' +import { Folder } from '@ol-types/folder' +import { ImageName, OverallThemeMeta } from '@ol-types/project-settings' + +const selectTab = async (tabName: string) => { + const tab = screen.getByRole('tab', { name: tabName }) + expect(tab).to.exist + tab.click() +} + +const assertSettingIsVisible = (settingName: string) => { + expect(screen.getByLabelText(settingName)).to.exist +} + +const TAB_SETTINGS = { + Editor: [ + 'Auto-complete', + 'Auto-close brackets', + 'Code check', + 'Keybindings', + 'PDF Viewer', + 'Reference search', + 'Spellcheck language', + 'Dictionary', + 'Breadcrumbs', + 'Equation preview', + ], + Compiler: [ + 'Main document', + 'Compiler', + 'TeX Live version', + 'Compile mode', + 'Stop on first error', + 'Autocompile', + ], + Appearance: [ + 'Overall theme', + 'Editor theme', + 'Editor font size', + 'Editor font family', + 'Editor line height', + ], +} + +describe('', function () { + const overallThemes: OverallThemeMeta[] = [ + { + name: 'Overall Theme 1', + val: '', + path: 'https://overleaf.com/overalltheme-1.css', + }, + { + name: 'Overall Theme 2', + val: 'light-', + path: 'https://overleaf.com/overalltheme-2.css', + }, + ] + + const editorThemes = ['editortheme-1', 'editortheme-2', 'editortheme-3'] + const legacyEditorThemes = ['legacytheme-1', 'legacytheme-2', 'legacytheme-3'] + + const imageNames: ImageName[] = [ + { + imageDesc: 'Image 1', + imageName: 'img-1', + allowed: true, + }, + { + imageDesc: 'Image 2', + imageName: 'img-2', + allowed: true, + }, + ] + + const rootFolder: Folder = { + _id: 'root-folder-id', + name: 'rootFolder', + docs: [ + { + _id: '123abc', + name: 'main.tex', + }, + ], + fileRefs: [], + folders: [], + } + + let originalSettings: typeof window.metaAttributesCache + + beforeEach(function () { + originalSettings = window.metaAttributesCache.get('ol-ExposedSettings') + window.metaAttributesCache.set('ol-ExposedSettings', { + validRootDocExtensions: ['tex'], + ieeeBrandId: 1234, + }) + window.metaAttributesCache.set('ol-imageNames', imageNames) + window.metaAttributesCache.set('ol-overallThemes', overallThemes) + window.metaAttributesCache.set('ol-editorThemes', editorThemes) + window.metaAttributesCache.set('ol-legacyEditorThemes', legacyEditorThemes) + }) + + afterEach(function () { + fetchMock.removeRoutes().clearHistory() + window.metaAttributesCache.set('ol-ExposedSettings', originalSettings) + }) + + it('Shows all settings options', async function () { + render( + + + + ) + + Object.entries(TAB_SETTINGS).forEach(([tabName, settings]) => { + selectTab(tabName) + settings.forEach(setting => assertSettingIsVisible(setting)) + }) + }) +}) diff --git a/services/web/test/frontend/features/settings-modal/settings/auto-close-brackets-setting.test.tsx b/services/web/test/frontend/features/settings-modal/settings/auto-close-brackets-setting.test.tsx new file mode 100644 index 0000000000..71843fabf8 --- /dev/null +++ b/services/web/test/frontend/features/settings-modal/settings/auto-close-brackets-setting.test.tsx @@ -0,0 +1,51 @@ +import { screen, render } from '@testing-library/react' +import { expect } from 'chai' +import fetchMock from 'fetch-mock' +import { EditorProviders } from '../../../helpers/editor-providers' +import AutoCloseBracketsSetting from '@/features/ide-redesign/components/settings/editor-settings/auto-close-brackets-setting' +import { SettingsModalProvider } from '@/features/ide-redesign/contexts/settings-modal-context' + +describe('', function () { + afterEach(function () { + fetchMock.removeRoutes().clearHistory() + }) + + it('can toggle', async function () { + render( + + + + + + ) + + const saveSettingsMock = fetchMock.post( + `express:/user/settings`, + { + status: 200, + }, + { delay: 0 } + ) + + const toggle = screen.getByLabelText('Auto-close brackets') + const startingCheckedValue = (toggle as HTMLInputElement).checked + + // Toggle the checkbox + toggle.click() + expect((toggle as HTMLInputElement).checked).to.equal(!startingCheckedValue) + expect( + saveSettingsMock.callHistory.called(`/user/settings`, { + body: { autoPairDelimiters: !startingCheckedValue }, + }) + ).to.be.true + + // Toggle back to original value + toggle.click() + expect((toggle as HTMLInputElement).checked).to.equal(startingCheckedValue) + expect( + saveSettingsMock.callHistory.called(`/user/settings`, { + body: { autoPairDelimiters: startingCheckedValue }, + }) + ).to.be.true + }) +}) diff --git a/services/web/test/frontend/features/settings-modal/settings/auto-complete-setting.test.tsx b/services/web/test/frontend/features/settings-modal/settings/auto-complete-setting.test.tsx new file mode 100644 index 0000000000..3c0f33b8a1 --- /dev/null +++ b/services/web/test/frontend/features/settings-modal/settings/auto-complete-setting.test.tsx @@ -0,0 +1,51 @@ +import { screen, render } from '@testing-library/react' +import { expect } from 'chai' +import fetchMock from 'fetch-mock' +import { SettingsModalProvider } from '@/features/ide-redesign/contexts/settings-modal-context' +import { EditorProviders } from '../../../helpers/editor-providers' +import AutoCompleteSetting from '@/features/ide-redesign/components/settings/editor-settings/auto-complete-setting' + +describe('', function () { + afterEach(function () { + fetchMock.removeRoutes().clearHistory() + }) + + it('can toggle', async function () { + render( + + + + + + ) + + const saveSettingsMock = fetchMock.post( + `express:/user/settings`, + { + status: 200, + }, + { delay: 0 } + ) + + const toggle = screen.getByLabelText('Auto-complete') + const startingCheckedValue = (toggle as HTMLInputElement).checked + + // Toggle the checkbox + toggle.click() + expect((toggle as HTMLInputElement).checked).to.equal(!startingCheckedValue) + expect( + saveSettingsMock.callHistory.called(`/user/settings`, { + body: { autoComplete: !startingCheckedValue }, + }) + ).to.be.true + + // Toggle back to original value + toggle.click() + expect((toggle as HTMLInputElement).checked).to.equal(startingCheckedValue) + expect( + saveSettingsMock.callHistory.called(`/user/settings`, { + body: { autoComplete: startingCheckedValue }, + }) + ).to.be.true + }) +}) diff --git a/services/web/test/frontend/features/settings-modal/settings/code-check-setting.test.tsx b/services/web/test/frontend/features/settings-modal/settings/code-check-setting.test.tsx new file mode 100644 index 0000000000..e135a9951a --- /dev/null +++ b/services/web/test/frontend/features/settings-modal/settings/code-check-setting.test.tsx @@ -0,0 +1,51 @@ +import { screen, render } from '@testing-library/react' +import { expect } from 'chai' +import fetchMock from 'fetch-mock' +import { EditorProviders } from '../../../helpers/editor-providers' +import { SettingsModalProvider } from '@/features/ide-redesign/contexts/settings-modal-context' +import CodeCheckSetting from '@/features/ide-redesign/components/settings/editor-settings/code-check-setting' + +describe('', function () { + afterEach(function () { + fetchMock.removeRoutes().clearHistory() + }) + + it('can toggle', async function () { + render( + + + + + + ) + + const saveSettingsMock = fetchMock.post( + `express:/user/settings`, + { + status: 200, + }, + { delay: 0 } + ) + + const toggle = screen.getByLabelText('Code check') + const startingCheckedValue = (toggle as HTMLInputElement).checked + + // Toggle the checkbox + toggle.click() + expect((toggle as HTMLInputElement).checked).to.equal(!startingCheckedValue) + expect( + saveSettingsMock.callHistory.called(`/user/settings`, { + body: { syntaxValidation: !startingCheckedValue }, + }) + ).to.be.true + + // Toggle back to original value + toggle.click() + expect((toggle as HTMLInputElement).checked).to.equal(startingCheckedValue) + expect( + saveSettingsMock.callHistory.called(`/user/settings`, { + body: { syntaxValidation: startingCheckedValue }, + }) + ).to.be.true + }) +}) diff --git a/services/web/test/frontend/features/settings-modal/settings/compiler-setting.test.tsx b/services/web/test/frontend/features/settings-modal/settings/compiler-setting.test.tsx new file mode 100644 index 0000000000..6411c09ebd --- /dev/null +++ b/services/web/test/frontend/features/settings-modal/settings/compiler-setting.test.tsx @@ -0,0 +1,36 @@ +import { screen, within, render } from '@testing-library/react' +import { expect } from 'chai' +import fetchMock from 'fetch-mock' +import { SettingsModalProvider } from '@/features/ide-redesign/contexts/settings-modal-context' +import { EditorProviders } from '../../../helpers/editor-providers' +import CompilerSetting from '@/features/ide-redesign/components/settings/compiler-settings/compiler-setting' + +describe('', function () { + afterEach(function () { + fetchMock.removeRoutes().clearHistory() + }) + + it('shows correct menu', async function () { + render( + + + + + + ) + + const select = screen.getByLabelText('Compiler') + + const optionPdfLaTeX = within(select).getByText('pdfLaTeX') + expect(optionPdfLaTeX.getAttribute('value')).to.equal('pdflatex') + + const optionLaTeX = within(select).getByText('LaTeX') + expect(optionLaTeX.getAttribute('value')).to.equal('latex') + + const optionXeLaTeX = within(select).getByText('XeLaTeX') + expect(optionXeLaTeX.getAttribute('value')).to.equal('xelatex') + + const optionLuaLaTeX = within(select).getByText('LuaLaTeX') + expect(optionLuaLaTeX.getAttribute('value')).to.equal('lualatex') + }) +}) diff --git a/services/web/test/frontend/features/settings-modal/settings/dictionary-setting.test.tsx b/services/web/test/frontend/features/settings-modal/settings/dictionary-setting.test.tsx new file mode 100644 index 0000000000..27949d215a --- /dev/null +++ b/services/web/test/frontend/features/settings-modal/settings/dictionary-setting.test.tsx @@ -0,0 +1,35 @@ +import { fireEvent, screen, within, render } from '@testing-library/react' +import { expect } from 'chai' +import { SettingsModalProvider } from '@/features/ide-redesign/contexts/settings-modal-context' +import { EditorProviders } from '../../../helpers/editor-providers' +import DictionarySetting from '@/features/ide-redesign/components/settings/editor-settings/dictionary-setting' +import RailModals from '@/features/ide-redesign/components/rail/rail-modals' + +describe('', function () { + it('open dictionary modal', function () { + render( + + + + + + + ) + + screen.getByText('Dictionary') + + const button = screen.getByText('Edit') + fireEvent.click(button) + + const modal = screen.getByTestId('dictionary-modal') + + within(modal).getByRole('heading', { name: 'Edit Dictionary' }) + within(modal).getByText('Your custom dictionary is empty.') + + const [, closeButton] = within(modal).getAllByRole('button', { + name: 'Close', + }) + fireEvent.click(closeButton) + expect(screen.getByTestId('dictionary-modal')).to.not.be.null + }) +}) diff --git a/services/web/test/frontend/features/settings-modal/settings/editor-theme-setting.test.tsx b/services/web/test/frontend/features/settings-modal/settings/editor-theme-setting.test.tsx new file mode 100644 index 0000000000..3bd5e6ae1e --- /dev/null +++ b/services/web/test/frontend/features/settings-modal/settings/editor-theme-setting.test.tsx @@ -0,0 +1,45 @@ +import { screen, within, render } from '@testing-library/react' +import { expect } from 'chai' +import fetchMock from 'fetch-mock' +import { SettingsModalProvider } from '@/features/ide-redesign/contexts/settings-modal-context' +import { EditorProviders } from '../../../helpers/editor-providers' +import EditorThemeSetting from '@/features/ide-redesign/components/settings/appearance-settings/editor-theme-setting' + +describe('', function () { + const editorThemes = ['editortheme-1', 'editortheme-2', 'editortheme-3'] + + const legacyEditorThemes = ['legacytheme-1', 'legacytheme-2', 'legacytheme-3'] + + beforeEach(function () { + window.metaAttributesCache.set('ol-editorThemes', editorThemes) + window.metaAttributesCache.set('ol-legacyEditorThemes', legacyEditorThemes) + }) + + afterEach(function () { + fetchMock.removeRoutes().clearHistory() + }) + + it('shows correct menu', async function () { + render( + + + + + + ) + + const select = screen.getByLabelText('Editor theme') + + for (const theme of editorThemes) { + const option = within(select).getByText(theme.replace(/_/g, ' ')) + expect(option.getAttribute('value')).to.equal(theme) + } + + for (const theme of legacyEditorThemes) { + const option = within(select).getByText( + theme.replace(/_/g, ' ') + ' (Legacy)' + ) + expect(option.getAttribute('value')).to.equal(theme) + } + }) +}) diff --git a/services/web/test/frontend/features/settings-modal/settings/font-family-setting.test.tsx b/services/web/test/frontend/features/settings-modal/settings/font-family-setting.test.tsx new file mode 100644 index 0000000000..d08845cdc3 --- /dev/null +++ b/services/web/test/frontend/features/settings-modal/settings/font-family-setting.test.tsx @@ -0,0 +1,35 @@ +import { screen, within, render } from '@testing-library/react' +import { expect } from 'chai' +import fetchMock from 'fetch-mock' +import { SettingsModalProvider } from '@/features/ide-redesign/contexts/settings-modal-context' +import { EditorProviders } from '../../../helpers/editor-providers' +import FontFamilySetting from '@/features/ide-redesign/components/settings/appearance-settings/font-family-setting' + +describe('', function () { + afterEach(function () { + fetchMock.removeRoutes().clearHistory() + }) + + it('shows correct menu', async function () { + render( + + + + + + ) + + const select = screen.getByLabelText('Editor font family') + + const optionMonaco = within(select).getByText('Monaco / Menlo / Consolas') + expect(optionMonaco.getAttribute('value')).to.equal('monaco') + + const optionLucida = within(select).getByText('Lucida / Source Code Pro') + expect(optionLucida.getAttribute('value')).to.equal('lucida') + + const optionOpenDyslexicMono = within(select).getByText('OpenDyslexic Mono') + expect(optionOpenDyslexicMono.getAttribute('value')).to.equal( + 'opendyslexicmono' + ) + }) +}) diff --git a/services/web/test/frontend/features/settings-modal/settings/font-size-setting.test.tsx b/services/web/test/frontend/features/settings-modal/settings/font-size-setting.test.tsx new file mode 100644 index 0000000000..ec49a9317b --- /dev/null +++ b/services/web/test/frontend/features/settings-modal/settings/font-size-setting.test.tsx @@ -0,0 +1,31 @@ +import { screen, within, render } from '@testing-library/react' +import { expect } from 'chai' +import fetchMock from 'fetch-mock' +import { SettingsModalProvider } from '@/features/ide-redesign/contexts/settings-modal-context' +import { EditorProviders } from '../../../helpers/editor-providers' +import FontSizeSetting from '@/features/ide-redesign/components/settings/appearance-settings/font-size-setting' + +describe('', function () { + const sizes = ['10', '11', '12', '13', '14', '16', '18', '20', '22', '24'] + + afterEach(function () { + fetchMock.removeRoutes().clearHistory() + }) + + it('shows correct menu', async function () { + render( + + + + + + ) + + const select = screen.getByLabelText('Editor font size') + + for (const size of sizes) { + const option = within(select).getByText(`${size}px`) + expect(option.getAttribute('value')).to.equal(size) + } + }) +}) diff --git a/services/web/test/frontend/features/settings-modal/settings/image-name-setting.test.tsx b/services/web/test/frontend/features/settings-modal/settings/image-name-setting.test.tsx new file mode 100644 index 0000000000..fdda2d46c8 --- /dev/null +++ b/services/web/test/frontend/features/settings-modal/settings/image-name-setting.test.tsx @@ -0,0 +1,47 @@ +import { screen, within, render } from '@testing-library/react' +import { expect } from 'chai' +import fetchMock from 'fetch-mock' +import type { ImageName } from '../../../../../types/project-settings' +import { SettingsModalProvider } from '@/features/ide-redesign/contexts/settings-modal-context' +import { EditorProviders } from '../../../helpers/editor-providers' +import ImageNameSetting from '@/features/ide-redesign/components/settings/compiler-settings/image-name-setting' + +describe('', function () { + const imageNames: ImageName[] = [ + { + imageDesc: 'Image 1', + imageName: 'img-1', + allowed: true, + }, + { + imageDesc: 'Image 2', + imageName: 'img-2', + allowed: true, + }, + ] + + beforeEach(function () { + window.metaAttributesCache.set('ol-imageNames', imageNames) + }) + + afterEach(function () { + fetchMock.removeRoutes().clearHistory() + }) + + it('shows correct menu', async function () { + render( + + + + + + ) + + const select = screen.getByLabelText('TeX Live version') + + for (const { imageName, imageDesc } of imageNames) { + const option = within(select).getByText(imageDesc) + expect(option.getAttribute('value')).to.equal(imageName) + } + }) +}) diff --git a/services/web/test/frontend/features/settings-modal/settings/keybinding-setting.test.tsx b/services/web/test/frontend/features/settings-modal/settings/keybinding-setting.test.tsx new file mode 100644 index 0000000000..491647da0f --- /dev/null +++ b/services/web/test/frontend/features/settings-modal/settings/keybinding-setting.test.tsx @@ -0,0 +1,33 @@ +import { screen, within, render } from '@testing-library/react' +import { expect } from 'chai' +import fetchMock from 'fetch-mock' +import { EditorProviders } from '../../../helpers/editor-providers' +import { SettingsModalProvider } from '@/features/ide-redesign/contexts/settings-modal-context' +import KeybindingSetting from '@/features/ide-redesign/components/settings/editor-settings/keybinding-setting' + +describe('', function () { + afterEach(function () { + fetchMock.removeRoutes().clearHistory() + }) + + it('shows correct menu', async function () { + render( + + + + + + ) + + const select = screen.getByLabelText('Keybindings') + + const optionNone = within(select).getByText('None') + expect(optionNone.getAttribute('value')).to.equal('default') + + const optionVim = within(select).getByText('Vim') + expect(optionVim.getAttribute('value')).to.equal('vim') + + const optionEmacs = within(select).getByText('Emacs') + expect(optionEmacs.getAttribute('value')).to.equal('emacs') + }) +}) diff --git a/services/web/test/frontend/features/settings-modal/settings/line-height-setting.test.tsx b/services/web/test/frontend/features/settings-modal/settings/line-height-setting.test.tsx new file mode 100644 index 0000000000..72bc117d6f --- /dev/null +++ b/services/web/test/frontend/features/settings-modal/settings/line-height-setting.test.tsx @@ -0,0 +1,33 @@ +import { screen, within, render } from '@testing-library/react' +import { expect } from 'chai' +import fetchMock from 'fetch-mock' +import { EditorProviders } from '../../../helpers/editor-providers' +import { SettingsModalProvider } from '@/features/ide-redesign/contexts/settings-modal-context' +import LineHeightSetting from '@/features/ide-redesign/components/settings/appearance-settings/line-height-setting' + +describe('', function () { + afterEach(function () { + fetchMock.removeRoutes().clearHistory() + }) + + it('shows correct menu', async function () { + render( + + + + + + ) + + const select = screen.getByLabelText('Editor line height') + + const optionCompact = within(select).getByText('Compact') + expect(optionCompact.getAttribute('value')).to.equal('compact') + + const optionNormal = within(select).getByText('Normal') + expect(optionNormal.getAttribute('value')).to.equal('normal') + + const optionWide = within(select).getByText('Wide') + expect(optionWide.getAttribute('value')).to.equal('wide') + }) +}) diff --git a/services/web/test/frontend/features/settings-modal/settings/math-preview-setting.test.tsx b/services/web/test/frontend/features/settings-modal/settings/math-preview-setting.test.tsx new file mode 100644 index 0000000000..f96d768cf3 --- /dev/null +++ b/services/web/test/frontend/features/settings-modal/settings/math-preview-setting.test.tsx @@ -0,0 +1,51 @@ +import { screen, render } from '@testing-library/react' +import { expect } from 'chai' +import fetchMock from 'fetch-mock' +import { EditorProviders } from '../../../helpers/editor-providers' +import { SettingsModalProvider } from '@/features/ide-redesign/contexts/settings-modal-context' +import MathPreviewSetting from '@/features/ide-redesign/components/settings/editor-settings/math-preview-setting' + +describe('', function () { + afterEach(function () { + fetchMock.removeRoutes().clearHistory() + }) + + it('can toggle', async function () { + render( + + + + + + ) + + const saveSettingsMock = fetchMock.post( + `express:/user/settings`, + { + status: 200, + }, + { delay: 0 } + ) + + const toggle = screen.getByLabelText('Equation preview') + const startingCheckedValue = (toggle as HTMLInputElement).checked + + // Toggle the checkbox + toggle.click() + expect((toggle as HTMLInputElement).checked).to.equal(!startingCheckedValue) + expect( + saveSettingsMock.callHistory.called(`/user/settings`, { + body: { mathPreview: !startingCheckedValue }, + }) + ).to.be.true + + // Toggle back to original value + toggle.click() + expect((toggle as HTMLInputElement).checked).to.equal(startingCheckedValue) + expect( + saveSettingsMock.callHistory.called(`/user/settings`, { + body: { mathPreview: startingCheckedValue }, + }) + ).to.be.true + }) +}) diff --git a/services/web/test/frontend/features/settings-modal/settings/overall-theme-setting.test.tsx b/services/web/test/frontend/features/settings-modal/settings/overall-theme-setting.test.tsx new file mode 100644 index 0000000000..9f88363653 --- /dev/null +++ b/services/web/test/frontend/features/settings-modal/settings/overall-theme-setting.test.tsx @@ -0,0 +1,99 @@ +import { screen, within, render } from '@testing-library/react' +import { expect } from 'chai' +import fetchMock from 'fetch-mock' +import SettingsOverallTheme from '../../../../../frontend/js/features/editor-left-menu/components/settings/settings-overall-theme' +import type { OverallThemeMeta } from '../../../../../types/project-settings' +import getMeta from '@/utils/meta' +import { EditorProviders } from '../../../helpers/editor-providers' +import { SettingsModalProvider } from '@/features/ide-redesign/contexts/settings-modal-context' +import OverallThemeSetting from '@/features/ide-redesign/components/settings/appearance-settings/overall-theme-setting' + +const IEEE_BRAND_ID = 1234 +const OTHER_BRAND_ID = 2234 + +describe('', function () { + const overallThemes: OverallThemeMeta[] = [ + { + name: 'Overall Theme 1', + val: '', + path: 'https://overleaf.com/overalltheme-1.css', + }, + { + name: 'Overall Theme 2', + val: 'light-', + path: 'https://overleaf.com/overalltheme-2.css', + }, + ] + + beforeEach(function () { + window.metaAttributesCache.set('ol-overallThemes', overallThemes) + Object.assign(getMeta('ol-ExposedSettings'), { + ieeeBrandId: IEEE_BRAND_ID, + }) + }) + + afterEach(function () { + fetchMock.removeRoutes().clearHistory() + }) + + it('shows correct menu', async function () { + render( + + + + + + ) + + const select = screen.getByLabelText('Overall theme') + + for (const theme of overallThemes) { + const option = within(select).getByText(theme.name) + expect(option.getAttribute('value')).to.equal(theme.val) + } + }) + describe('Branded Project', function () { + it('should hide overall theme picker for IEEE branded projects', function () { + window.metaAttributesCache.set('ol-brandVariation', { + brand_id: IEEE_BRAND_ID, + }) + render( + + + + + + ) + const select = screen.queryByText('Overall theme') + expect(select).to.not.exist + }) + + it('should show overall theme picker for branded projects that are not IEEE', function () { + window.metaAttributesCache.set('ol-brandVariation', { + brand_id: OTHER_BRAND_ID, + }) + render( + + + + + + ) + const select = screen.getByLabelText('Overall theme') + expect(select).to.exist + }) + + it('should show overall theme picker for non branded projects', function () { + window.metaAttributesCache.set('ol-brandVariation', undefined) + render( + + + + + + ) + const select = screen.getByLabelText('Overall theme') + expect(select).to.exist + }) + }) +}) diff --git a/services/web/test/frontend/features/settings-modal/settings/pdf-viewer-setting.test.tsx b/services/web/test/frontend/features/settings-modal/settings/pdf-viewer-setting.test.tsx new file mode 100644 index 0000000000..51c828dedb --- /dev/null +++ b/services/web/test/frontend/features/settings-modal/settings/pdf-viewer-setting.test.tsx @@ -0,0 +1,30 @@ +import { screen, within, render } from '@testing-library/react' +import { expect } from 'chai' +import fetchMock from 'fetch-mock' +import { EditorProviders } from '../../../helpers/editor-providers' +import { SettingsModalProvider } from '@/features/ide-redesign/contexts/settings-modal-context' +import PDFViewerSetting from '@/features/ide-redesign/components/settings/editor-settings/pdf-viewer-setting' + +describe('', function () { + afterEach(function () { + fetchMock.removeRoutes().clearHistory() + }) + + it('shows correct menu', async function () { + render( + + + + + + ) + + const select = screen.getByLabelText('PDF Viewer') + + const optionOverleaf = within(select).getByText('Overleaf') + expect(optionOverleaf.getAttribute('value')).to.equal('pdfjs') + + const optionBrowser = within(select).getByText('Browser') + expect(optionBrowser.getAttribute('value')).to.equal('native') + }) +}) diff --git a/services/web/test/frontend/features/settings-modal/settings/root-document-setting.test.tsx b/services/web/test/frontend/features/settings-modal/settings/root-document-setting.test.tsx new file mode 100644 index 0000000000..35312341b4 --- /dev/null +++ b/services/web/test/frontend/features/settings-modal/settings/root-document-setting.test.tsx @@ -0,0 +1,51 @@ +import { screen, within, render } from '@testing-library/react' +import { expect } from 'chai' +import fetchMock from 'fetch-mock' +import { Folder } from '../../../../../types/folder' +import { SettingsModalProvider } from '@/features/ide-redesign/contexts/settings-modal-context' +import { EditorProviders } from '../../../helpers/editor-providers' +import RootDocumentSetting from '@/features/ide-redesign/components/settings/compiler-settings/root-document-setting' + +describe('', function () { + const rootFolder: Folder = { + _id: 'root-folder-id', + name: 'rootFolder', + docs: [ + { + _id: '123abc', + name: 'main.tex', + }, + ], + fileRefs: [], + folders: [], + } + + let originalSettings: typeof window.metaAttributesCache + + beforeEach(function () { + originalSettings = window.metaAttributesCache.get('ol-ExposedSettings') + window.metaAttributesCache.set('ol-ExposedSettings', { + validRootDocExtensions: ['tex'], + }) + }) + + afterEach(function () { + fetchMock.removeRoutes().clearHistory() + window.metaAttributesCache.set('ol-ExposedSettings', originalSettings) + }) + + it('shows correct menu', async function () { + render( + + + + + + ) + + const select = screen.getByLabelText('Main document') + + const optionOn = within(select).getByText('main.tex') + expect(optionOn.getAttribute('value')).to.equal('123abc') + }) +}) diff --git a/services/web/test/frontend/features/settings-modal/settings/spell-check-setting.test.tsx b/services/web/test/frontend/features/settings-modal/settings/spell-check-setting.test.tsx new file mode 100644 index 0000000000..0d8facb094 --- /dev/null +++ b/services/web/test/frontend/features/settings-modal/settings/spell-check-setting.test.tsx @@ -0,0 +1,50 @@ +import { screen, within, render } from '@testing-library/react' +import { expect } from 'chai' +import fetchMock from 'fetch-mock' +import type { SpellCheckLanguage } from '../../../../../types/project-settings' +import { EditorProviders } from '../../../helpers/editor-providers' +import { SettingsModalProvider } from '@/features/ide-redesign/contexts/settings-modal-context' +import SpellCheckSetting from '@/features/ide-redesign/components/settings/editor-settings/spell-check-setting' + +describe('', function () { + const languages: SpellCheckLanguage[] = [ + { + name: 'Lang 1', + code: 'lang-1', + dic: 'lang_1', + }, + { + name: 'Lang 2', + code: 'lang-2', + dic: 'lang_2', + }, + ] + + beforeEach(function () { + window.metaAttributesCache.set('ol-languages', languages) + }) + + afterEach(function () { + fetchMock.removeRoutes().clearHistory() + }) + + it('shows correct menu', async function () { + render( + + + + + + ) + + const select = screen.getByLabelText('Spellcheck language') + + const optionEmpty = within(select).getByText('Off') + expect(optionEmpty.getAttribute('value')).to.equal('') + + for (const language of languages) { + const option = within(select).getByText(language.name) + expect(option.getAttribute('value')).to.equal(language.code) + } + }) +})