first commit

This commit is contained in:
2025-04-24 13:11:28 +08:00
commit ff9c54d5e4
5960 changed files with 834111 additions and 0 deletions

View File

@@ -0,0 +1,60 @@
import { fireEvent, screen, waitFor } from '@testing-library/react'
import fetchMock from 'fetch-mock'
import sinon from 'sinon'
import { expect } from 'chai'
import ActionsCopyProject from '../../../../../frontend/js/features/editor-left-menu/components/actions-copy-project'
import { renderWithEditorContext } from '../../../helpers/render-with-context'
import * as useLocationModule from '../../../../../frontend/js/shared/hooks/use-location'
describe('<ActionsCopyProject />', function () {
let assignStub
beforeEach(function () {
assignStub = sinon.stub()
this.locationStub = sinon.stub(useLocationModule, 'useLocation').returns({
assign: assignStub,
replace: sinon.stub(),
reload: sinon.stub(),
})
})
afterEach(function () {
this.locationStub.restore()
fetchMock.removeRoutes().clearHistory()
})
it('shows correct modal when clicked', async function () {
renderWithEditorContext(<ActionsCopyProject />)
fireEvent.click(screen.getByRole('button', { name: 'Copy Project' }))
screen.getByPlaceholderText('New Project Name')
})
it('loads the project page when submitted', async function () {
fetchMock.post('express:/project/:id/clone', {
status: 200,
body: {
project_id: 'new-project',
},
})
renderWithEditorContext(<ActionsCopyProject />)
fireEvent.click(screen.getByRole('button', { name: 'Copy Project' }))
const input = screen.getByPlaceholderText('New Project Name')
fireEvent.change(input, { target: { value: 'New Project' } })
const button = screen.getByRole('button', { name: 'Copy' })
button.click()
await waitFor(() => {
expect(button.textContent).to.equal('Copying…')
})
await waitFor(() => {
expect(assignStub).to.have.been.calledOnceWith('/project/new-project')
})
})
})

View File

@@ -0,0 +1,84 @@
import { screen, waitFor } from '@testing-library/react'
import { expect } from 'chai'
import fetchMock from 'fetch-mock'
import ActionsMenu from '../../../../../frontend/js/features/editor-left-menu/components/actions-menu'
import { renderWithEditorContext } from '../../../helpers/render-with-context'
describe('<ActionsMenu />', function () {
beforeEach(function () {
fetchMock.post('express:/project/:projectId/compile', {
status: 'success',
pdfDownloadDomain: 'https://clsi.test-overleaf.com',
outputFiles: [
{
path: 'output.pdf',
build: 'build-123',
url: '/build/build-123/output.pdf',
type: 'pdf',
},
],
})
})
afterEach(function () {
fetchMock.removeRoutes().clearHistory()
})
it('shows correct menu for non-anonymous users', async function () {
window.metaAttributesCache.set('ol-anonymous', false)
renderWithEditorContext(<ActionsMenu />, {
projectId: '123abc',
scope: {
editor: {
sharejs_doc: {
doc_id: 'test-doc',
getSnapshot: () => 'some doc content',
},
},
},
})
screen.getByText('Actions')
screen.getByRole('button', {
name: 'Copy Project',
})
await waitFor(() => {
screen.getByRole('button', {
name: 'Word Count',
})
})
})
it('does not show anything for anonymous users', async function () {
window.metaAttributesCache.set('ol-anonymous', true)
renderWithEditorContext(<ActionsMenu />, {
projectId: '123abc',
scope: {
editor: {
sharejs_doc: {
doc_id: 'test-doc',
getSnapshot: () => 'some doc content',
},
},
},
})
expect(screen.queryByText('Actions')).to.equal(null)
expect(
screen.queryByRole('button', {
name: 'Copy Project',
})
).to.equal(null)
await waitFor(() => {
expect(
screen.queryByRole('button', {
name: 'Word Count',
})
).to.equal(null)
})
})
})

View File

@@ -0,0 +1,65 @@
import { screen, waitFor } from '@testing-library/react'
import { expect } from 'chai'
import fetchMock from 'fetch-mock'
import ActionsWordCount from '../../../../../frontend/js/features/editor-left-menu/components/actions-word-count'
import { renderWithEditorContext } from '../../../helpers/render-with-context'
describe('<ActionsWordCount />', function () {
afterEach(function () {
fetchMock.removeRoutes().clearHistory()
})
it('shows correct modal when clicked after document is compiled', async function () {
const compileEndpoint = 'express:/project/:projectId/compile'
const wordcountEndpoint = 'express:/project/:projectId/wordcount'
fetchMock.post(compileEndpoint, {
status: 'success',
pdfDownloadDomain: 'https://clsi.test-overleaf.com',
outputFiles: [
{
path: 'output.pdf',
build: 'build-123',
url: '/build/build-123/output.pdf',
type: 'pdf',
},
],
})
fetchMock.get(wordcountEndpoint, {
texcount: {
encode: 'ascii',
textWords: 0,
headers: 0,
mathInline: 0,
mathDisplay: 0,
},
})
renderWithEditorContext(<ActionsWordCount />, {
projectId: '123abc',
scope: {
editor: {
sharejs_doc: {
doc_id: 'test-doc',
getSnapshot: () => 'some doc content',
},
},
},
})
// when loading, we don't render the "Word Count" as button yet
expect(screen.queryByRole('button', { name: 'Word Count' })).to.equal(null)
await waitFor(
() => expect(fetchMock.callHistory.called(compileEndpoint)).to.be.true
)
const button = await screen.findByRole('button', { name: 'Word Count' })
button.click()
await waitFor(
() => expect(fetchMock.callHistory.called(wordcountEndpoint)).to.be.true
)
})
})

View File

@@ -0,0 +1,58 @@
import { screen, waitFor } from '@testing-library/react'
import { expect } from 'chai'
import fetchMock from 'fetch-mock'
import DownloadMenu from '../../../../../frontend/js/features/editor-left-menu/components/download-menu'
import { renderWithEditorContext } from '../../../helpers/render-with-context'
describe('<DownloadMenu />', function () {
afterEach(function () {
fetchMock.removeRoutes().clearHistory()
})
it('shows download links with correct url', async function () {
fetchMock.post('express:/project/:projectId/compile', {
clsiServerId: 'foo',
compileGroup: 'priority',
status: 'success',
pdfDownloadDomain: 'https://clsi.test-overleaf.com',
outputFiles: [
{
path: 'output.pdf',
build: 'build-123',
url: '/build/build-123/output.pdf',
type: 'pdf',
},
],
})
renderWithEditorContext(<DownloadMenu />, {
projectId: '123abc',
scope: {
editor: {
sharejs_doc: {
doc_id: 'test-doc',
getSnapshot: () => 'some doc content',
},
},
},
})
const sourceLink = screen.getByRole('link', {
name: 'Source',
})
expect(sourceLink.getAttribute('href')).to.equal(
'/project/123abc/download/zip'
)
await waitFor(() => {
const pdfLink = screen.getByRole('link', {
name: 'PDF',
})
expect(pdfLink.getAttribute('href')).to.equal(
'/download/project/123abc/build/build-123/output/output.pdf?compileGroup=priority&clsiserverid=foo&popupDownload=true'
)
})
})
})

View File

@@ -0,0 +1,29 @@
import { expect } from 'chai'
import { screen, fireEvent, within } from '@testing-library/react'
import HelpContactUs from '../../../../../frontend/js/features/editor-left-menu/components/help-contact-us'
import { renderWithEditorContext } from '../../../helpers/render-with-context'
import fetchMock from 'fetch-mock'
describe('<HelpContactUs />', function () {
beforeEach(function () {
window.metaAttributesCache.set('ol-user', {
email: 'sherlock@holmes.co.uk',
first_name: 'Sherlock',
last_name: 'Holmes',
})
})
afterEach(function () {
fetchMock.removeRoutes().clearHistory()
})
it('open contact us modal when clicked', function () {
renderWithEditorContext(<HelpContactUs />)
expect(screen.queryByRole('dialog')).to.equal(null)
fireEvent.click(screen.getByRole('button', { name: 'Contact Us' }))
const modal = screen.getAllByRole('dialog')[0]
within(modal).getAllByText('Get in touch')
within(modal).getByText('Subject')
})
})

View File

@@ -0,0 +1,12 @@
import { expect } from 'chai'
import { screen, render } from '@testing-library/react'
import HelpDocumentation from '../../../../../frontend/js/features/editor-left-menu/components/help-documentation'
describe('<HelpDocumentation />', function () {
it('has correct href attribute', function () {
render(<HelpDocumentation />)
const link = screen.getByRole('link', { name: 'Documentation' })
expect(link.getAttribute('href')).to.equal('/learn')
})
})

View File

@@ -0,0 +1,39 @@
import { screen } from '@testing-library/react'
import { expect } from 'chai'
import fetchMock from 'fetch-mock'
import HelpMenu from '../../../../../frontend/js/features/editor-left-menu/components/help-menu'
import { renderWithEditorContext } from '../../../helpers/render-with-context'
describe('<HelpMenu />', function () {
beforeEach(function () {
window.metaAttributesCache.set('ol-user', {
email: 'sherlock@holmes.co.uk',
first_name: 'Sherlock',
last_name: 'Holmes',
})
})
afterEach(function () {
fetchMock.removeRoutes().clearHistory()
})
it('shows correct menu if `showSupport` is `true`', function () {
window.metaAttributesCache.set('ol-showSupport', true)
renderWithEditorContext(<HelpMenu />)
screen.getByRole('button', { name: 'Show Hotkeys' })
screen.getByRole('button', { name: 'Contact Us' })
screen.getByRole('link', { name: 'Documentation' })
})
it('shows correct menu if `showSupport` is `false`', function () {
window.metaAttributesCache.set('ol-showSupport', false)
renderWithEditorContext(<HelpMenu />)
screen.getByRole('button', { name: 'Show Hotkeys' })
expect(screen.queryByRole('button', { name: 'Contact Us' })).to.equal(null)
expect(screen.queryByRole('link', { name: 'Documentation' })).to.equal(null)
})
})

View File

@@ -0,0 +1,20 @@
import { expect } from 'chai'
import { screen, fireEvent, within } from '@testing-library/react'
import HelpShowHotkeys from '../../../../../frontend/js/features/editor-left-menu/components/help-show-hotkeys'
import { renderWithEditorContext } from '../../../helpers/render-with-context'
import fetchMock from 'fetch-mock'
describe('<HelpShowHotkeys />', function () {
afterEach(function () {
fetchMock.removeRoutes().clearHistory()
})
it('open hotkeys modal when clicked', function () {
renderWithEditorContext(<HelpShowHotkeys />)
expect(screen.queryByRole('dialog')).to.equal(null)
fireEvent.click(screen.getByRole('button', { name: 'Show Hotkeys' }))
const modal = screen.getAllByRole('dialog')[0]
within(modal).getByText('Common')
})
})

View File

@@ -0,0 +1,30 @@
import { screen, within, render } from '@testing-library/react'
import { expect } from 'chai'
import fetchMock from 'fetch-mock'
import SettingsAutoCloseBrackets from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-auto-close-brackets'
import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
import { EditorProviders } from '../../../../helpers/editor-providers'
describe('<SettingsAutoCloseBrackets />', function () {
afterEach(function () {
fetchMock.removeRoutes().clearHistory()
})
it('shows correct menu', async function () {
render(
<EditorProviders>
<EditorLeftMenuProvider>
<SettingsAutoCloseBrackets />
</EditorLeftMenuProvider>
</EditorProviders>
)
const select = screen.getByLabelText('Auto-close brackets')
const optionOn = within(select).getByText('On')
expect(optionOn.getAttribute('value')).to.equal('true')
const optionOff = within(select).getByText('Off')
expect(optionOff.getAttribute('value')).to.equal('false')
})
})

View File

@@ -0,0 +1,30 @@
import { screen, within, render } from '@testing-library/react'
import { expect } from 'chai'
import fetchMock from 'fetch-mock'
import SettingsAutoComplete from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-auto-complete'
import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
import { EditorProviders } from '../../../../helpers/editor-providers'
describe('<SettingsAutoComplete />', function () {
afterEach(function () {
fetchMock.removeRoutes().clearHistory()
})
it('shows correct menu', async function () {
render(
<EditorProviders>
<EditorLeftMenuProvider>
<SettingsAutoComplete />
</EditorLeftMenuProvider>
</EditorProviders>
)
const select = screen.getByLabelText('Auto-complete')
const optionOn = within(select).getByText('On')
expect(optionOn.getAttribute('value')).to.equal('true')
const optionOff = within(select).getByText('Off')
expect(optionOff.getAttribute('value')).to.equal('false')
})
})

View File

@@ -0,0 +1,36 @@
import { screen, within, render } from '@testing-library/react'
import { expect } from 'chai'
import fetchMock from 'fetch-mock'
import SettingsCompiler from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-compiler'
import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
import { EditorProviders } from '../../../../helpers/editor-providers'
describe('<SettingsCompiler />', function () {
afterEach(function () {
fetchMock.removeRoutes().clearHistory()
})
it('shows correct menu', async function () {
render(
<EditorProviders>
<EditorLeftMenuProvider>
<SettingsCompiler />
</EditorLeftMenuProvider>
</EditorProviders>
)
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')
})
})

View File

@@ -0,0 +1,33 @@
import { fireEvent, screen, within, render } from '@testing-library/react'
import { expect } from 'chai'
import SettingsDictionary from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-dictionary'
import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
import { EditorProviders } from '../../../../helpers/editor-providers'
describe('<SettingsDictionary />', function () {
it('open dictionary modal', function () {
render(
<EditorProviders>
<EditorLeftMenuProvider>
<SettingsDictionary />
</EditorLeftMenuProvider>
</EditorProviders>
)
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
})
})

View File

@@ -0,0 +1,51 @@
import { screen, within, render } from '@testing-library/react'
import { expect } from 'chai'
import fetchMock from 'fetch-mock'
import SettingsDocument from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-document'
import { Folder } from '../../../../../../types/folder'
import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
import { EditorProviders } from '../../../../helpers/editor-providers'
describe('<SettingsDocument />', 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(
<EditorProviders rootFolder={[rootFolder as any]}>
<EditorLeftMenuProvider>
<SettingsDocument />
</EditorLeftMenuProvider>
</EditorProviders>
)
const select = screen.getByLabelText('Main document')
const optionOn = within(select).getByText('main.tex')
expect(optionOn.getAttribute('value')).to.equal('123abc')
})
})

View File

@@ -0,0 +1,45 @@
import { screen, within, render } from '@testing-library/react'
import { expect } from 'chai'
import fetchMock from 'fetch-mock'
import SettingsEditorTheme from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-editor-theme'
import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
import { EditorProviders } from '../../../../helpers/editor-providers'
describe('<SettingsEditorTheme />', 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(
<EditorProviders>
<EditorLeftMenuProvider>
<SettingsEditorTheme />
</EditorLeftMenuProvider>
</EditorProviders>
)
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)
}
})
})

View File

@@ -0,0 +1,35 @@
import { screen, within, render } from '@testing-library/react'
import { expect } from 'chai'
import fetchMock from 'fetch-mock'
import SettingsFontFamily from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-font-family'
import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
import { EditorProviders } from '../../../../helpers/editor-providers'
describe('<SettingsFontFamily />', function () {
afterEach(function () {
fetchMock.removeRoutes().clearHistory()
})
it('shows correct menu', async function () {
render(
<EditorProviders>
<EditorLeftMenuProvider>
<SettingsFontFamily />
</EditorLeftMenuProvider>
</EditorProviders>
)
const select = screen.getByLabelText('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'
)
})
})

View File

@@ -0,0 +1,31 @@
import { screen, within, render } from '@testing-library/react'
import { expect } from 'chai'
import fetchMock from 'fetch-mock'
import SettingsFontSize from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-font-size'
import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
import { EditorProviders } from '../../../../helpers/editor-providers'
describe('<SettingsFontSize />', 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(
<EditorProviders>
<EditorLeftMenuProvider>
<SettingsFontSize />
</EditorLeftMenuProvider>
</EditorProviders>
)
const select = screen.getByLabelText('Font Size')
for (const size of sizes) {
const option = within(select).getByText(`${size}px`)
expect(option.getAttribute('value')).to.equal(size)
}
})
})

View File

@@ -0,0 +1,45 @@
import { screen, within, render } from '@testing-library/react'
import { expect } from 'chai'
import fetchMock from 'fetch-mock'
import SettingsImageName from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-image-name'
import type { AllowedImageName } from '../../../../../../types/project-settings'
import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
import { EditorProviders } from '../../../../helpers/editor-providers'
describe('<SettingsImageName />', function () {
const allowedImageNames: AllowedImageName[] = [
{
imageDesc: 'Image 1',
imageName: 'img-1',
},
{
imageDesc: 'Image 2',
imageName: 'img-2',
},
]
beforeEach(function () {
window.metaAttributesCache.set('ol-allowedImageNames', allowedImageNames)
})
afterEach(function () {
fetchMock.removeRoutes().clearHistory()
})
it('shows correct menu', async function () {
render(
<EditorProviders>
<EditorLeftMenuProvider>
<SettingsImageName />
</EditorLeftMenuProvider>
</EditorProviders>
)
const select = screen.getByLabelText('TeX Live version')
for (const { imageName, imageDesc } of allowedImageNames) {
const option = within(select).getByText(imageDesc)
expect(option.getAttribute('value')).to.equal(imageName)
}
})
})

View File

@@ -0,0 +1,33 @@
import { screen, within, render } from '@testing-library/react'
import { expect } from 'chai'
import fetchMock from 'fetch-mock'
import SettingsKeybindings from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-keybindings'
import { EditorProviders } from '../../../../helpers/editor-providers'
import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
describe('<SettingsKeybindings />', function () {
afterEach(function () {
fetchMock.removeRoutes().clearHistory()
})
it('shows correct menu', async function () {
render(
<EditorProviders>
<EditorLeftMenuProvider>
<SettingsKeybindings />
</EditorLeftMenuProvider>
</EditorProviders>
)
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')
})
})

View File

@@ -0,0 +1,33 @@
import { screen, within, render } from '@testing-library/react'
import { expect } from 'chai'
import fetchMock from 'fetch-mock'
import SettingsLineHeight from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-line-height'
import { EditorProviders } from '../../../../helpers/editor-providers'
import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
describe('<SettingsLineHeight />', function () {
afterEach(function () {
fetchMock.removeRoutes().clearHistory()
})
it('shows correct menu', async function () {
render(
<EditorProviders>
<EditorLeftMenuProvider>
<SettingsLineHeight />
</EditorLeftMenuProvider>
</EditorProviders>
)
const select = screen.getByLabelText('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')
})
})

View File

@@ -0,0 +1,30 @@
import { screen, within, render } from '@testing-library/react'
import { expect } from 'chai'
import fetchMock from 'fetch-mock'
import SettingsMathPreview from '@/features/editor-left-menu/components/settings/settings-math-preview'
import { EditorProviders } from '../../../../helpers/editor-providers'
import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
describe('<SettingsMathPreview />', function () {
afterEach(function () {
fetchMock.removeRoutes().clearHistory()
})
it('shows correct menu', async function () {
render(
<EditorProviders>
<EditorLeftMenuProvider>
<SettingsMathPreview />
</EditorLeftMenuProvider>
</EditorProviders>
)
const select = screen.getByLabelText('Equation preview')
const optionOn = within(select).getByText('On')
expect(optionOn.getAttribute('value')).to.equal('true')
const optionOff = within(select).getByText('Off')
expect(optionOff.getAttribute('value')).to.equal('false')
})
})

View File

@@ -0,0 +1,98 @@
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 { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
const IEEE_BRAND_ID = 1234
const OTHER_BRAND_ID = 2234
describe('<SettingsOverallTheme />', 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(
<EditorProviders>
<EditorLeftMenuProvider>
<SettingsOverallTheme />
</EditorLeftMenuProvider>
</EditorProviders>
)
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(
<EditorProviders>
<EditorLeftMenuProvider>
<SettingsOverallTheme />
</EditorLeftMenuProvider>
</EditorProviders>
)
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(
<EditorProviders>
<EditorLeftMenuProvider>
<SettingsOverallTheme />
</EditorLeftMenuProvider>
</EditorProviders>
)
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(
<EditorProviders>
<EditorLeftMenuProvider>
<SettingsOverallTheme />
</EditorLeftMenuProvider>
</EditorProviders>
)
const select = screen.getByLabelText('Overall theme')
expect(select).to.exist
})
})
})

View File

@@ -0,0 +1,30 @@
import { screen, within, render } from '@testing-library/react'
import { expect } from 'chai'
import fetchMock from 'fetch-mock'
import SettingsPdfViewer from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-pdf-viewer'
import { EditorProviders } from '../../../../helpers/editor-providers'
import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
describe('<SettingsPdfViewer />', function () {
afterEach(function () {
fetchMock.removeRoutes().clearHistory()
})
it('shows correct menu', async function () {
render(
<EditorProviders>
<EditorLeftMenuProvider>
<SettingsPdfViewer />
</EditorLeftMenuProvider>
</EditorProviders>
)
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')
})
})

View File

@@ -0,0 +1,50 @@
import { screen, within, render } from '@testing-library/react'
import { expect } from 'chai'
import fetchMock from 'fetch-mock'
import SettingsSpellCheckLanguage from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-spell-check-language'
import type { SpellCheckLanguage } from '../../../../../../types/project-settings'
import { EditorProviders } from '../../../../helpers/editor-providers'
import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
describe('<SettingsSpellCheckLanguage />', 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(
<EditorProviders>
<EditorLeftMenuProvider>
<SettingsSpellCheckLanguage />
</EditorLeftMenuProvider>
</EditorProviders>
)
const select = screen.getByLabelText('Spell check')
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)
}
})
})

View File

@@ -0,0 +1,30 @@
import { screen, within, render } from '@testing-library/react'
import { expect } from 'chai'
import fetchMock from 'fetch-mock'
import SettingsSyntaxValidation from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-syntax-validation'
import { EditorProviders } from '../../../../helpers/editor-providers'
import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
describe('<SettingsSyntaxValidation />', function () {
afterEach(function () {
fetchMock.removeRoutes().clearHistory()
})
it('shows correct menu', async function () {
render(
<EditorProviders>
<EditorLeftMenuProvider>
<SettingsSyntaxValidation />
</EditorLeftMenuProvider>
</EditorProviders>
)
const select = screen.getByLabelText('Code check')
const optionOn = within(select).getByText('On')
expect(optionOn.getAttribute('value')).to.equal('true')
const optionOff = within(select).getByText('Off')
expect(optionOff.getAttribute('value')).to.equal('false')
})
})