mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #13077 from overleaf/mj-figure-modal-tests
[web] Add cypress tests for figure modal GitOrigin-RevId: 4debae1c665a68fd7bfa9f0dcfc150bec38a7c64
This commit is contained in:
parent
f4408c3fa6
commit
988fc57574
13 changed files with 514 additions and 6 deletions
|
@ -7,6 +7,9 @@ import {
|
||||||
import { interceptEvents } from './events'
|
import { interceptEvents } from './events'
|
||||||
import { interceptSpelling } from './spelling'
|
import { interceptSpelling } from './spelling'
|
||||||
import { interceptAsync } from './intercept-async'
|
import { interceptAsync } from './intercept-async'
|
||||||
|
import { interceptFileUpload } from './upload'
|
||||||
|
import { interceptProjectListing } from './project-list'
|
||||||
|
import { interceptLinkedFile } from './linked-file'
|
||||||
|
|
||||||
// eslint-disable-next-line no-unused-vars,@typescript-eslint/no-namespace
|
// eslint-disable-next-line no-unused-vars,@typescript-eslint/no-namespace
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -20,6 +23,9 @@ declare global {
|
||||||
interceptSpelling: typeof interceptSpelling
|
interceptSpelling: typeof interceptSpelling
|
||||||
waitForCompile: typeof waitForCompile
|
waitForCompile: typeof waitForCompile
|
||||||
interceptDeferredCompile: typeof interceptDeferredCompile
|
interceptDeferredCompile: typeof interceptDeferredCompile
|
||||||
|
interceptFileUpload: typeof interceptFileUpload
|
||||||
|
interceptProjectListing: typeof interceptProjectListing
|
||||||
|
interceptLinkedFile: typeof interceptLinkedFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,3 +36,6 @@ Cypress.Commands.add('interceptEvents', interceptEvents)
|
||||||
Cypress.Commands.add('interceptSpelling', interceptSpelling)
|
Cypress.Commands.add('interceptSpelling', interceptSpelling)
|
||||||
Cypress.Commands.add('waitForCompile', waitForCompile)
|
Cypress.Commands.add('waitForCompile', waitForCompile)
|
||||||
Cypress.Commands.add('interceptDeferredCompile', interceptDeferredCompile)
|
Cypress.Commands.add('interceptDeferredCompile', interceptDeferredCompile)
|
||||||
|
Cypress.Commands.add('interceptFileUpload', interceptFileUpload)
|
||||||
|
Cypress.Commands.add('interceptProjectListing', interceptProjectListing)
|
||||||
|
Cypress.Commands.add('interceptLinkedFile', interceptLinkedFile)
|
||||||
|
|
12
services/web/cypress/support/shared/commands/linked-file.ts
Normal file
12
services/web/cypress/support/shared/commands/linked-file.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { HttpRequestInterceptor } from 'cypress/types/net-stubbing'
|
||||||
|
|
||||||
|
export const interceptLinkedFile = () => {
|
||||||
|
cy.intercept(
|
||||||
|
{ method: 'POST', url: '/project/*/linked_file' },
|
||||||
|
cy
|
||||||
|
.spy((req: Parameters<HttpRequestInterceptor>[0]) => {
|
||||||
|
req.reply({ statusCode: 200, body: { success: true } })
|
||||||
|
})
|
||||||
|
.as('linked-file-request')
|
||||||
|
)
|
||||||
|
}
|
22
services/web/cypress/support/shared/commands/project-list.ts
Normal file
22
services/web/cypress/support/shared/commands/project-list.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
export const interceptProjectListing = () => {
|
||||||
|
cy.intercept('GET', '/user/projects', {
|
||||||
|
projects: [
|
||||||
|
{
|
||||||
|
_id: 'fake-project-1',
|
||||||
|
accessLevel: 'owner',
|
||||||
|
name: 'My first project',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_id: 'fake-project-2',
|
||||||
|
accessLevel: 'owner',
|
||||||
|
name: 'My second project',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
cy.intercept('GET', '/project/*/entities', {
|
||||||
|
entities: [
|
||||||
|
{ path: '/frog.jpg', type: 'file' },
|
||||||
|
{ path: 'figures/unicorn.png', type: 'file' },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
}
|
18
services/web/cypress/support/shared/commands/upload.ts
Normal file
18
services/web/cypress/support/shared/commands/upload.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { HttpRequestInterceptor } from 'cypress/types/net-stubbing'
|
||||||
|
|
||||||
|
export const interceptFileUpload = () => {
|
||||||
|
cy.intercept(
|
||||||
|
{ method: 'POST', url: /\/project\/.*\/upload/ },
|
||||||
|
cy
|
||||||
|
.spy((req: Parameters<HttpRequestInterceptor>[0]) => {
|
||||||
|
const folderMatch = req.url.match(
|
||||||
|
/project\/.*\/upload\?folder_id=[a-f0-9]{24}/
|
||||||
|
)
|
||||||
|
if (!folderMatch) {
|
||||||
|
req.reply({ statusCode: 500, body: { success: false } })
|
||||||
|
}
|
||||||
|
req.reply({ statusCode: 200, body: { success: true } })
|
||||||
|
})
|
||||||
|
.as('uploadRequest')
|
||||||
|
)
|
||||||
|
}
|
|
@ -274,9 +274,11 @@
|
||||||
"file_already_exists": "",
|
"file_already_exists": "",
|
||||||
"file_already_exists_in_this_location": "",
|
"file_already_exists_in_this_location": "",
|
||||||
"file_name": "",
|
"file_name": "",
|
||||||
|
"file_name_figure_modal": "",
|
||||||
"file_name_in_this_project": "",
|
"file_name_in_this_project": "",
|
||||||
"file_name_in_this_project_figure_modal": "",
|
"file_name_in_this_project_figure_modal": "",
|
||||||
"file_outline": "",
|
"file_outline": "",
|
||||||
|
"file_size": "",
|
||||||
"files_cannot_include_invalid_characters": "",
|
"files_cannot_include_invalid_characters": "",
|
||||||
"find_out_more": "",
|
"find_out_more": "",
|
||||||
"find_out_more_about_institution_login": "",
|
"find_out_more_about_institution_login": "",
|
||||||
|
@ -745,6 +747,7 @@
|
||||||
"remove_collaborator": "",
|
"remove_collaborator": "",
|
||||||
"remove_from_group": "",
|
"remove_from_group": "",
|
||||||
"remove_manager": "",
|
"remove_manager": "",
|
||||||
|
"remove_or_replace_figure": "",
|
||||||
"remove_tag": "",
|
"remove_tag": "",
|
||||||
"removing": "",
|
"removing": "",
|
||||||
"rename": "",
|
"rename": "",
|
||||||
|
@ -799,11 +802,14 @@
|
||||||
"search_whole_word": "",
|
"search_whole_word": "",
|
||||||
"search_within_selection": "",
|
"search_within_selection": "",
|
||||||
"select_a_file": "",
|
"select_a_file": "",
|
||||||
|
"select_a_file_figure_modal": "",
|
||||||
"select_a_payment_method": "",
|
"select_a_payment_method": "",
|
||||||
"select_a_project": "",
|
"select_a_project": "",
|
||||||
|
"select_a_project_figure_modal": "",
|
||||||
"select_all": "",
|
"select_all": "",
|
||||||
"select_all_projects": "",
|
"select_all_projects": "",
|
||||||
"select_an_output_file": "",
|
"select_an_output_file": "",
|
||||||
|
"select_an_output_file_figure_modal": "",
|
||||||
"select_folder_from_project": "",
|
"select_folder_from_project": "",
|
||||||
"select_from_output_files": "",
|
"select_from_output_files": "",
|
||||||
"select_from_project_files": "",
|
"select_from_project_files": "",
|
||||||
|
|
|
@ -20,6 +20,7 @@ export const FigureModalFigureOptions: FC = () => {
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
id="figure-modal-caption"
|
id="figure-modal-caption"
|
||||||
|
data-cy="include-caption-option"
|
||||||
defaultChecked={includeCaption}
|
defaultChecked={includeCaption}
|
||||||
onChange={event => dispatch({ includeCaption: event.target.checked })}
|
onChange={event => dispatch({ includeCaption: event.target.checked })}
|
||||||
/>
|
/>
|
||||||
|
@ -31,6 +32,7 @@ export const FigureModalFigureOptions: FC = () => {
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
id="figure-modal-label"
|
id="figure-modal-label"
|
||||||
|
data-cy="include-label-option"
|
||||||
defaultChecked={includeLabel}
|
defaultChecked={includeLabel}
|
||||||
onChange={event => dispatch({ includeLabel: event.target.checked })}
|
onChange={event => dispatch({ includeLabel: event.target.checked })}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -126,7 +126,7 @@ export const FigureModalOtherProjectSource: FC = () => {
|
||||||
items={projects ?? []}
|
items={projects ?? []}
|
||||||
itemToString={project => (project ? project.name : '')}
|
itemToString={project => (project ? project.name : '')}
|
||||||
itemToKey={item => item._id}
|
itemToKey={item => item._id}
|
||||||
defaultText={t('select_a_project')}
|
defaultText={t('select_a_project_figure_modal')}
|
||||||
label={t('project_figure_modal')}
|
label={t('project_figure_modal')}
|
||||||
disabled={projectsLoading}
|
disabled={projectsLoading}
|
||||||
onSelectedItemChanged={item => {
|
onSelectedItemChanged={item => {
|
||||||
|
@ -201,7 +201,7 @@ const SelectFile = <T extends { path: string }>({
|
||||||
onSelectedItemChange?: (item: T | null | undefined) => any
|
onSelectedItemChange?: (item: T | null | undefined) => any
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
defaultText = defaultText ?? t('select_a_file')
|
defaultText = defaultText ?? t('select_a_file_figure_modal')
|
||||||
label = label ?? t('image_file')
|
label = label ?? t('image_file')
|
||||||
const imageFiles = useMemo(() => files?.filter(isImageEntity), [files])
|
const imageFiles = useMemo(() => files?.filter(isImageEntity), [files])
|
||||||
const empty = loading || !imageFiles || imageFiles.length === 0
|
const empty = loading || !imageFiles || imageFiles.length === 0
|
||||||
|
@ -257,7 +257,7 @@ const SelectFromProjectOutputFiles: FC<{
|
||||||
return (
|
return (
|
||||||
<SelectFile
|
<SelectFile
|
||||||
label={t('output_file')}
|
label={t('output_file')}
|
||||||
defaultText={t('select_an_output_file')}
|
defaultText={t('select_an_output_file_figure_modal')}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
files={entities}
|
files={entities}
|
||||||
disabled={!projectId}
|
disabled={!projectId}
|
||||||
|
|
|
@ -251,6 +251,7 @@ export const FileContainer: FC<{
|
||||||
status: FileUploadStatus
|
status: FileUploadStatus
|
||||||
onDelete?: () => any
|
onDelete?: () => any
|
||||||
}> = ({ name, size, status, onDelete }) => {
|
}> = ({ name, size, status, onDelete }) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
let icon
|
let icon
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case FileUploadStatus.ERROR:
|
case FileUploadStatus.ERROR:
|
||||||
|
@ -280,7 +281,9 @@ export const FileContainer: FC<{
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<div className="file-info">
|
<div className="file-info">
|
||||||
<span className="file-name">{name}</span>
|
<span className="file-name" aria-label={t('file_name_figure_modal')}>
|
||||||
|
{name}
|
||||||
|
</span>
|
||||||
{size !== undefined && (
|
{size !== undefined && (
|
||||||
<FileSize size={size} className="text-small" />
|
<FileSize size={size} className="text-small" />
|
||||||
)}
|
)}
|
||||||
|
@ -288,6 +291,7 @@ export const FileContainer: FC<{
|
||||||
<Button
|
<Button
|
||||||
bsStyle={null}
|
bsStyle={null}
|
||||||
className="btn btn-link p-0"
|
className="btn btn-link p-0"
|
||||||
|
aria-label={t('remove_or_replace_figure')}
|
||||||
onClick={() => onDelete && onDelete()}
|
onClick={() => onDelete && onDelete()}
|
||||||
>
|
>
|
||||||
<Icon fw type="times-circle" className="file-action file-icon" />
|
<Icon fw type="times-circle" className="file-action file-icon" />
|
||||||
|
@ -301,6 +305,7 @@ const FileSize: FC<{ size: number; className?: string }> = ({
|
||||||
size,
|
size,
|
||||||
className,
|
className,
|
||||||
}) => {
|
}) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
const BYTE_UNITS: [string, number][] = [
|
const BYTE_UNITS: [string, number][] = [
|
||||||
['B', 1],
|
['B', 1],
|
||||||
['KB', 1e3],
|
['KB', 1e3],
|
||||||
|
@ -317,7 +322,7 @@ const FileSize: FC<{ size: number; className?: string }> = ({
|
||||||
const [label, bytesPerUnit] = BYTE_UNITS[labelIndex]
|
const [label, bytesPerUnit] = BYTE_UNITS[labelIndex]
|
||||||
const sizeInUnits = Math.round(size / bytesPerUnit)
|
const sizeInUnits = Math.round(size / bytesPerUnit)
|
||||||
return (
|
return (
|
||||||
<span className={className}>
|
<span aria-label={t('file_size')} className={className}>
|
||||||
{sizeInUnits} {label}
|
{sizeInUnits} {label}
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
|
|
|
@ -15,6 +15,7 @@ export const ToolbarButtonMenu: FC<{
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
className="ol-cm-toolbar-button"
|
className="ol-cm-toolbar-button"
|
||||||
|
aria-label={label}
|
||||||
bsStyle={null}
|
bsStyle={null}
|
||||||
onMouseDown={event => {
|
onMouseDown={event => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
@ -45,6 +46,7 @@ export const ToolbarButtonMenu: FC<{
|
||||||
className="ol-cm-toolbar-button-menu-popover"
|
className="ol-cm-toolbar-button-menu-popover"
|
||||||
>
|
>
|
||||||
<ListGroup
|
<ListGroup
|
||||||
|
role="menu"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onToggle(false)
|
onToggle(false)
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -38,6 +38,7 @@ export class EditableGraphicsWidget extends GraphicsWidget {
|
||||||
|
|
||||||
createEditButton(view: EditorView) {
|
createEditButton(view: EditorView) {
|
||||||
const button = document.createElement('button')
|
const button = document.createElement('button')
|
||||||
|
button.setAttribute('aria-label', view.state.phrase('edit_figure'))
|
||||||
this.setEditDispatcher(button, view)
|
this.setEditDispatcher(button, view)
|
||||||
button.classList.add('btn', 'btn-secondary', 'ol-cm-graphics-edit-button')
|
button.classList.add('btn', 'btn-secondary', 'ol-cm-graphics-edit-button')
|
||||||
const buttonLabel = document.createElement('span')
|
const buttonLabel = document.createElement('span')
|
||||||
|
|
|
@ -495,12 +495,14 @@
|
||||||
"file_already_exists_in_this_location": "An item named <0>__fileName__</0> already exists in this location. If you wish to move this file, rename or remove the conflicting file and try again.",
|
"file_already_exists_in_this_location": "An item named <0>__fileName__</0> already exists in this location. If you wish to move this file, rename or remove the conflicting file and try again.",
|
||||||
"file_has_been_deleted": "__filename__ has been deleted",
|
"file_has_been_deleted": "__filename__ has been deleted",
|
||||||
"file_name": "File Name",
|
"file_name": "File Name",
|
||||||
|
"file_name_figure_modal": "File name",
|
||||||
"file_name_in_this_project": "File Name In This Project",
|
"file_name_in_this_project": "File Name In This Project",
|
||||||
"file_name_in_this_project_figure_modal": "File name in this project",
|
"file_name_in_this_project_figure_modal": "File name in this project",
|
||||||
"file_outline": "File outline",
|
"file_outline": "File outline",
|
||||||
"file_restored": "Your file (__filename__) has been recovered.",
|
"file_restored": "Your file (__filename__) has been recovered.",
|
||||||
"file_restored_back_to_editor": "You can go back to the editor and work on it again.",
|
"file_restored_back_to_editor": "You can go back to the editor and work on it again.",
|
||||||
"file_restored_back_to_editor_btn": "Back to editor",
|
"file_restored_back_to_editor_btn": "Back to editor",
|
||||||
|
"file_size": "File size",
|
||||||
"file_too_large": "File too large",
|
"file_too_large": "File too large",
|
||||||
"files_cannot_include_invalid_characters": "File name is empty or contains invalid characters",
|
"files_cannot_include_invalid_characters": "File name is empty or contains invalid characters",
|
||||||
"files_selected": "files selected.",
|
"files_selected": "files selected.",
|
||||||
|
@ -1261,6 +1263,7 @@
|
||||||
"remove_collaborator": "Remove collaborator",
|
"remove_collaborator": "Remove collaborator",
|
||||||
"remove_from_group": "Remove from group",
|
"remove_from_group": "Remove from group",
|
||||||
"remove_manager": "Remove manager",
|
"remove_manager": "Remove manager",
|
||||||
|
"remove_or_replace_figure": "Remove or replace figure",
|
||||||
"remove_tag": "Remove tag __tagName__",
|
"remove_tag": "Remove tag __tagName__",
|
||||||
"removed": "removed",
|
"removed": "removed",
|
||||||
"removing": "Removing",
|
"removing": "Removing",
|
||||||
|
@ -1349,12 +1352,15 @@
|
||||||
"see_changes_in_your_documents_live": "See changes in your documents, live",
|
"see_changes_in_your_documents_live": "See changes in your documents, live",
|
||||||
"see_what_has_been": "See what has been ",
|
"see_what_has_been": "See what has been ",
|
||||||
"select_a_file": "Select a File",
|
"select_a_file": "Select a File",
|
||||||
|
"select_a_file_figure_modal": "Select a file",
|
||||||
"select_a_payment_method": "Select a payment method",
|
"select_a_payment_method": "Select a payment method",
|
||||||
"select_a_project": "Select a Project",
|
"select_a_project": "Select a Project",
|
||||||
|
"select_a_project_figure_modal": "Select a project",
|
||||||
"select_a_zip_file": "Select a .zip file",
|
"select_a_zip_file": "Select a .zip file",
|
||||||
"select_all": "Select all",
|
"select_all": "Select all",
|
||||||
"select_all_projects": "Select all projects",
|
"select_all_projects": "Select all projects",
|
||||||
"select_an_output_file": "Select an Output File",
|
"select_an_output_file": "Select an Output File",
|
||||||
|
"select_an_output_file_figure_modal": "Select an output file",
|
||||||
"select_folder_from_project": "Select folder from project",
|
"select_folder_from_project": "Select folder from project",
|
||||||
"select_from_output_files": "select from output files",
|
"select_from_output_files": "select from output files",
|
||||||
"select_from_project_files": "select from project files",
|
"select_from_project_files": "select from project files",
|
||||||
|
|
|
@ -0,0 +1,390 @@
|
||||||
|
import CodemirrorEditor from '../../../../../frontend/js/features/source-editor/components/codemirror-editor'
|
||||||
|
import { EditorProviders } from '../../../helpers/editor-providers'
|
||||||
|
import { mockScope, rootFolderId } from '../helpers/mock-scope'
|
||||||
|
import { FC } from 'react'
|
||||||
|
|
||||||
|
const Container: FC = ({ children }) => (
|
||||||
|
<div style={{ width: 785, height: 785 }}>{children}</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
const clickToolbarButton = (text: string) => {
|
||||||
|
cy.findByLabelText(text).click()
|
||||||
|
cy.findByLabelText(text).trigger('mouseout')
|
||||||
|
}
|
||||||
|
|
||||||
|
const chooseFileFromComputer = () => {
|
||||||
|
cy.get('@file-input').selectFile(
|
||||||
|
{
|
||||||
|
fileName: 'frog.jpg',
|
||||||
|
contents: Cypress.Buffer.from('image-data'),
|
||||||
|
mimeType: 'image/jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
force: true,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const matchUrl = (urlToMatch: RegExp | string) =>
|
||||||
|
Cypress.sinon.match(req => {
|
||||||
|
if (!req || typeof req.url !== 'string') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (typeof urlToMatch === 'string') {
|
||||||
|
return req.url.endsWith(urlToMatch)
|
||||||
|
}
|
||||||
|
return Boolean(req.url.match(urlToMatch))
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('<FigureModal />', function () {
|
||||||
|
// TODO: rewrite these tests to be in source mode when toolbar is added there
|
||||||
|
// TODO: Write tests for width toggle, when we can match on source code
|
||||||
|
beforeEach(function () {
|
||||||
|
window.metaAttributesCache.set('ol-preventCompileOnLoad', true)
|
||||||
|
window.metaAttributesCache.set('ol-splitTestVariants', {
|
||||||
|
'figure-modal': 'enabled',
|
||||||
|
})
|
||||||
|
window.metaAttributesCache.set(
|
||||||
|
'ol-mathJax3Path',
|
||||||
|
'https://unpkg.com/mathjax@3.2.2/es5/tex-svg-full.js'
|
||||||
|
)
|
||||||
|
cy.interceptEvents()
|
||||||
|
cy.interceptSpelling()
|
||||||
|
|
||||||
|
const content = ''
|
||||||
|
|
||||||
|
const scope = mockScope(content)
|
||||||
|
scope.editor.showVisual = true
|
||||||
|
|
||||||
|
cy.mount(
|
||||||
|
<Container>
|
||||||
|
<EditorProviders scope={scope}>
|
||||||
|
<CodemirrorEditor />
|
||||||
|
</EditorProviders>
|
||||||
|
</Container>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Upload from computer source', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
cy.interceptFileUpload()
|
||||||
|
clickToolbarButton('Insert Figure')
|
||||||
|
cy.findByRole('menu').within(() => {
|
||||||
|
cy.findByText('Upload from computer').click()
|
||||||
|
})
|
||||||
|
cy.findByLabelText('File Uploader')
|
||||||
|
.get('.uppy-Dashboard-input:first')
|
||||||
|
.as('file-input')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Shows file name and size when selecting file', function () {
|
||||||
|
chooseFileFromComputer()
|
||||||
|
cy.findByLabelText('File name').should('have.text', 'frog.jpg')
|
||||||
|
cy.findByLabelText('File size').should('have.text', '10 B')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Uploads file when clicking insert', function () {
|
||||||
|
chooseFileFromComputer()
|
||||||
|
cy.get('@uploadRequest').should('not.have.been.called')
|
||||||
|
cy.findByText('Insert figure').click()
|
||||||
|
cy.get('@uploadRequest').should(
|
||||||
|
'have.been.calledWith',
|
||||||
|
matchUrl(`/project/test-project/upload?folder_id=${rootFolderId}`)
|
||||||
|
)
|
||||||
|
|
||||||
|
cy.get('.cm-content').should(
|
||||||
|
'have.text',
|
||||||
|
'\\begin{figure}\\centeringEnter Caption🏷fig:enter-label\\end{figure}'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Enables insert button when choosing file', function () {
|
||||||
|
cy.findByText('Insert figure').should('be.disabled')
|
||||||
|
chooseFileFromComputer()
|
||||||
|
cy.findByText('Insert figure').should('be.enabled')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Upload from project files source', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
clickToolbarButton('Insert Figure')
|
||||||
|
cy.findByRole('menu').within(() => {
|
||||||
|
cy.findByText('From project files').click()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Lists files from project', function () {
|
||||||
|
cy.findByText('Select image from project files').click()
|
||||||
|
cy.findByRole('listbox')
|
||||||
|
.children()
|
||||||
|
.should('have.length', 2)
|
||||||
|
.should('contain.text', 'frog.jpg')
|
||||||
|
.should('contain.text', 'unicorn.png')
|
||||||
|
.should('contain.text', 'figures/')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Enables insert button when choosing file', function () {
|
||||||
|
cy.findByText('Insert figure').should('be.disabled')
|
||||||
|
cy.findByText('Select image from project files').click()
|
||||||
|
cy.findByRole('listbox').within(() => {
|
||||||
|
cy.findByText('frog.jpg').click()
|
||||||
|
})
|
||||||
|
cy.findByText('Insert figure').should('be.enabled')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Inserts file when pressing insert button', function () {
|
||||||
|
cy.findByText('Select image from project files').click()
|
||||||
|
cy.findByRole('listbox').within(() => {
|
||||||
|
cy.findByText('frog.jpg').click()
|
||||||
|
})
|
||||||
|
cy.findByText('Insert figure').click()
|
||||||
|
cy.get('.cm-content').should(
|
||||||
|
'have.text',
|
||||||
|
'\\begin{figure}\\centeringEnter Caption🏷fig:enter-label\\end{figure}'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('From another project source', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
cy.interceptProjectListing()
|
||||||
|
cy.interceptCompile()
|
||||||
|
cy.interceptLinkedFile()
|
||||||
|
clickToolbarButton('Insert Figure')
|
||||||
|
cy.findByRole('menu').within(() => {
|
||||||
|
cy.findByText('From another project').click()
|
||||||
|
})
|
||||||
|
cy.findByText('Select a project').parent().as('project-dropdown')
|
||||||
|
cy.findByText('Select a file').parent().as('file-dropdown')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('List projects and files in projects', function () {
|
||||||
|
cy.findByText('Insert figure').should('be.disabled')
|
||||||
|
cy.get('@file-dropdown').should('have.class', 'disabled')
|
||||||
|
cy.get('@project-dropdown').click()
|
||||||
|
cy.findByRole('listbox').as('project-select')
|
||||||
|
cy.get('@project-select').children().should('have.length', 2)
|
||||||
|
cy.get('@project-select').within(() => {
|
||||||
|
cy.findByText('My first project').click()
|
||||||
|
})
|
||||||
|
cy.get('@file-dropdown').should('not.have.class', 'disabled')
|
||||||
|
cy.get('@file-dropdown').click()
|
||||||
|
cy.findByRole('listbox').as('file-select')
|
||||||
|
cy.get('@file-select').children().should('have.length', 2)
|
||||||
|
cy.get('@file-select').should('contain.text', 'frog.jpg')
|
||||||
|
cy.get('@file-select').should('contain.text', 'figures/unicorn.png')
|
||||||
|
cy.get('@file-select').within(() => {
|
||||||
|
cy.findByText('frog.jpg').click()
|
||||||
|
})
|
||||||
|
cy.findByText('Insert figure').should('be.enabled')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Enables insert button when choosing file', function () {
|
||||||
|
cy.findByText('Insert figure').should('be.disabled')
|
||||||
|
cy.get('@project-dropdown').click()
|
||||||
|
cy.findByRole('listbox').within(() => {
|
||||||
|
cy.findByText('My first project').click()
|
||||||
|
})
|
||||||
|
cy.get('@file-dropdown').click()
|
||||||
|
cy.findByRole('listbox').within(() => {
|
||||||
|
cy.findByText('frog.jpg').click()
|
||||||
|
})
|
||||||
|
cy.findByText('Insert figure').should('be.enabled')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Creates linked file when pressing insert', function () {
|
||||||
|
cy.get('@project-dropdown').click()
|
||||||
|
cy.findByRole('listbox').within(() => {
|
||||||
|
cy.findByText('My first project').click()
|
||||||
|
})
|
||||||
|
cy.get('@file-dropdown').click()
|
||||||
|
cy.findByRole('listbox').within(() => {
|
||||||
|
cy.findByText('frog.jpg').click()
|
||||||
|
})
|
||||||
|
cy.findByText('Insert figure').click()
|
||||||
|
cy.get('@linked-file-request').should('have.been.calledWithMatch', {
|
||||||
|
body: {
|
||||||
|
provider: 'project_file',
|
||||||
|
data: {
|
||||||
|
source_entity_path: '/frog.jpg',
|
||||||
|
source_project_id: 'fake-project-1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
cy.get('.cm-content').should(
|
||||||
|
'have.text',
|
||||||
|
'\\begin{figure}\\centeringEnter Caption🏷fig:enter-label\\end{figure}'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Creates linked output file when pressing insert', function () {
|
||||||
|
cy.get('@project-dropdown').click()
|
||||||
|
cy.findByRole('listbox').within(() => {
|
||||||
|
cy.findByText('My first project').click()
|
||||||
|
})
|
||||||
|
cy.findByText('select from output files').click()
|
||||||
|
cy.findByText('Select an output file').parent().as('output-file-dropdown')
|
||||||
|
cy.get('@output-file-dropdown').click()
|
||||||
|
cy.findByRole('listbox').within(() => {
|
||||||
|
cy.findByText('output.pdf').click()
|
||||||
|
})
|
||||||
|
cy.findByText('Insert figure').click()
|
||||||
|
cy.get('@linked-file-request').should('have.been.calledWithMatch', {
|
||||||
|
body: {
|
||||||
|
provider: 'project_output_file',
|
||||||
|
data: {
|
||||||
|
source_output_file_path: 'output.pdf',
|
||||||
|
source_project_id: 'fake-project-1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
cy.get('.cm-content').should(
|
||||||
|
'have.text',
|
||||||
|
'\\begin{figure}\\centeringEnter Caption🏷fig:enter-label\\end{figure}'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('From URL source', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
cy.interceptLinkedFile()
|
||||||
|
clickToolbarButton('Insert Figure')
|
||||||
|
cy.findByRole('menu').within(() => {
|
||||||
|
cy.findByText('From URL').click()
|
||||||
|
})
|
||||||
|
cy.findByLabelText('File name in this project').as(
|
||||||
|
'relocated-file-name-input'
|
||||||
|
)
|
||||||
|
cy.findByLabelText('Image URL').as('image-url-input')
|
||||||
|
cy.get('[data-cy="include-label-option"]').as('include-label-checkbox')
|
||||||
|
cy.get('[data-cy="include-caption-option"]').as(
|
||||||
|
'include-caption-checkbox'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Auto fills name based on url', function () {
|
||||||
|
cy.get('@image-url-input').type('https://my-fake-website.com/frog.jpg')
|
||||||
|
cy.get('@relocated-file-name-input').should('have.value', 'frog.jpg')
|
||||||
|
cy.get('@relocated-file-name-input').type('pig')
|
||||||
|
cy.get('@relocated-file-name-input').should('have.value', 'pig.jpg')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Enables insert button when name and url is available', function () {
|
||||||
|
cy.findByText('Insert figure').should('be.disabled')
|
||||||
|
cy.get('@image-url-input').type('https://my-fake-website.com/frog.jpg')
|
||||||
|
cy.findByText('Insert figure').should('be.enabled')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Adds linked file when pressing insert', function () {
|
||||||
|
cy.get('@image-url-input').type('https://my-fake-website.com/frog.jpg')
|
||||||
|
cy.findByText('Insert figure').click()
|
||||||
|
|
||||||
|
cy.get('@linked-file-request').should('have.been.calledWithMatch', {
|
||||||
|
body: {
|
||||||
|
provider: 'url',
|
||||||
|
data: {
|
||||||
|
url: 'https://my-fake-website.com/frog.jpg',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
cy.get('.cm-content').should(
|
||||||
|
'have.text',
|
||||||
|
'\\begin{figure}\\centeringEnter Caption🏷fig:enter-label\\end{figure}'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Editing existing figure', function () {
|
||||||
|
it('Parses existing label and caption', function () {
|
||||||
|
cy.get('.cm-content').type(
|
||||||
|
`\\begin{{}figure}
|
||||||
|
\\centering
|
||||||
|
\\includegraphics[width=0.5\\linewidth]{{}frog.jpg}
|
||||||
|
\\caption{{}My caption}
|
||||||
|
\\label{{}fig:my-label}
|
||||||
|
\\end{{}figure}`,
|
||||||
|
{ delay: 0 }
|
||||||
|
)
|
||||||
|
cy.get('[aria-label="Edit figure"]').click()
|
||||||
|
cy.get('[data-cy="include-caption-option"]').should('be.checked')
|
||||||
|
cy.get('[data-cy="include-label-option"]').should('be.checked')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Parses existing width', function () {
|
||||||
|
cy.get('.cm-content').type(
|
||||||
|
`\\begin{{}figure}
|
||||||
|
\\centering
|
||||||
|
\\includegraphics[width=0.75\\linewidth]{{}frog.jpg}
|
||||||
|
\\caption{{}My caption}
|
||||||
|
\\label{{}fig:my-label}
|
||||||
|
\\end{{}figure}`,
|
||||||
|
{ delay: 0 }
|
||||||
|
)
|
||||||
|
cy.get('[aria-label="Edit figure"]').click()
|
||||||
|
cy.get('[value="0.75"]').should('be.checked')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Removes existing label when unchecked', function () {
|
||||||
|
cy.get('.cm-content').type(
|
||||||
|
`\\begin{{}figure}
|
||||||
|
\\centering
|
||||||
|
\\includegraphics[width=0.75\\linewidth]{{}frog.jpg}
|
||||||
|
\\label{{}fig:my-label}
|
||||||
|
\\end{{}figure}`,
|
||||||
|
{ delay: 0 }
|
||||||
|
)
|
||||||
|
cy.get('[aria-label="Edit figure"]').click()
|
||||||
|
cy.get('[data-cy="include-label-option"]').click()
|
||||||
|
cy.get('[data-cy="include-label-option"]').should('not.be.checked')
|
||||||
|
cy.findByText('Done').click()
|
||||||
|
cy.get('.cm-content').should(
|
||||||
|
'have.text',
|
||||||
|
'\\begin{figure}\\centering\\end{figure}'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Removes existing caption when unchecked', function () {
|
||||||
|
cy.get('.cm-content').type(
|
||||||
|
`\\begin{{}figure}
|
||||||
|
\\centering
|
||||||
|
\\includegraphics[width=0.75\\linewidth]{{}frog.jpg}
|
||||||
|
\\caption{{}My caption}
|
||||||
|
\\label{{}fig:my-label}
|
||||||
|
\\end{{}figure}`,
|
||||||
|
{ delay: 0 }
|
||||||
|
)
|
||||||
|
cy.get('[aria-label="Edit figure"]').click()
|
||||||
|
cy.get('[data-cy="include-caption-option"]').click()
|
||||||
|
cy.get('[data-cy="include-caption-option"]').should('not.be.checked')
|
||||||
|
cy.findByText('Done').click()
|
||||||
|
cy.get('.cm-content').should(
|
||||||
|
'have.text',
|
||||||
|
'\\begin{figure}\\centering🏷fig:my-label\\end{figure}'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Preserves other content when removing figure', function () {
|
||||||
|
cy.get('.cm-content').type(
|
||||||
|
`text above
|
||||||
|
\\begin{{}figure}
|
||||||
|
\\centering
|
||||||
|
\\includegraphics[width=0.75\\linewidth]{{}frog.jpg}
|
||||||
|
\\caption{{}My caption}
|
||||||
|
\\label{{}fig:my-label}
|
||||||
|
\\end{{}figure}
|
||||||
|
text below`,
|
||||||
|
{ delay: 0 }
|
||||||
|
)
|
||||||
|
cy.get('[aria-label="Edit figure"]').click()
|
||||||
|
cy.get('[aria-label="Remove or replace figure"]').click()
|
||||||
|
cy.findByText('Delete figure').click()
|
||||||
|
cy.get('.cm-content').should('have.text', 'text abovetext below')
|
||||||
|
})
|
||||||
|
|
||||||
|
// TODO: Add tests for replacing image when we can match on image path
|
||||||
|
// TODO: Add tests for changing image size when we can match on figure width
|
||||||
|
})
|
||||||
|
})
|
|
@ -1,8 +1,43 @@
|
||||||
import { docId, mockDoc } from './mock-doc'
|
import { docId, mockDoc } from './mock-doc'
|
||||||
import { Folder } from '../../../../../types/folder'
|
import { Folder } from '../../../../../types/folder'
|
||||||
|
export const rootFolderId = '012345678901234567890123'
|
||||||
|
export const figuresFolderId = '123456789012345678901234'
|
||||||
|
export const figureId = '234567890123456789012345'
|
||||||
export const mockScope = (content?: string) => {
|
export const mockScope = (content?: string) => {
|
||||||
return {
|
return {
|
||||||
|
rootFolder: {
|
||||||
|
id: rootFolderId,
|
||||||
|
name: 'rootFolder',
|
||||||
|
selected: false,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: docId,
|
||||||
|
name: 'test.tex',
|
||||||
|
selected: false,
|
||||||
|
type: 'doc',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: figuresFolderId,
|
||||||
|
name: 'figures',
|
||||||
|
selected: false,
|
||||||
|
type: 'folder',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: figureId,
|
||||||
|
name: 'frog.jpg',
|
||||||
|
selected: false,
|
||||||
|
type: 'file',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'fake-figure-id',
|
||||||
|
name: 'unicorn.png',
|
||||||
|
selected: false,
|
||||||
|
type: 'file',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
settings: {
|
settings: {
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontFamily: 'monaco',
|
fontFamily: 'monaco',
|
||||||
|
|
Loading…
Reference in a new issue