first commit
This commit is contained in:
@@ -0,0 +1 @@
|
||||
Simply use the section and subsection commands, as in this example document! With Overleaf, all the formatting and numbering is handled automatically according to the template you've chosen. If you're using the Visual Editor, you can also create new section and subsections via the buttons in the editor toolbar.
|
@@ -0,0 +1,8 @@
|
||||
@article{greenwade93,
|
||||
author = "George D. Greenwade",
|
||||
title = "The {C}omprehensive {T}ex {A}rchive {N}etwork ({CTAN})",
|
||||
year = "1993",
|
||||
journal = "TUGBoat",
|
||||
volume = "14",
|
||||
number = "3",
|
||||
pages = "342--351"}
|
@@ -0,0 +1 @@
|
||||
module.exports = {}
|
BIN
services/web/cypress/fixtures/build/output-2.pdf
Normal file
BIN
services/web/cypress/fixtures/build/output-2.pdf
Normal file
Binary file not shown.
BIN
services/web/cypress/fixtures/build/output-corrupt.pdf
Normal file
BIN
services/web/cypress/fixtures/build/output-corrupt.pdf
Normal file
Binary file not shown.
@@ -0,0 +1,21 @@
|
||||
log This is pdfTeX, Version 3.14159265-2.6-1.40.21 (TeX Live 2020) (preloaded format=pdflatex 2020.9.10) 8 FEB 2022 16:27
|
||||
entering extended mode
|
||||
\write18 enabled.
|
||||
%&-line parsing enabled.
|
||||
**main.tex
|
||||
(./main.tex
|
||||
LaTeX2e <2020-02-02> patch level 5
|
||||
|
||||
LaTeX Warning: Reference `intorduction' on page 1 undefined on input line 11.
|
||||
|
||||
|
||||
LaTeX Warning: Reference `section1' on page 1 undefined on input line 13.
|
||||
|
||||
[1
|
||||
|
||||
{/usr/local/texlive/2020/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] (/compi
|
||||
le/output.aux)
|
||||
|
||||
LaTeX Warning: There were undefined references.
|
||||
|
||||
)
|
@@ -0,0 +1,10 @@
|
||||
Package rerunfilecheck Info: File `output.out' has not changed.
|
||||
(rerunfilecheck) Checksum: 339DB29951BB30436898BC39909EA4FA;11265.
|
||||
|
||||
Package rerunfilecheck Warning: File `output.brf' has changed.
|
||||
(rerunfilecheck) Rerun to get bibliographical references right.
|
||||
|
||||
Package rerunfilecheck Info: Checksums for `output.brf':
|
||||
(rerunfilecheck) Before: D41D8CD98F00B204E9800998ECF8427E;0
|
||||
(rerunfilecheck) After: DF3260FAD3828D54C5E4E9337E97F7AF;4841.
|
||||
)
|
1
services/web/cypress/fixtures/build/output.blg
Normal file
1
services/web/cypress/fixtures/build/output.blg
Normal file
@@ -0,0 +1 @@
|
||||
This is BibTeX, Version 4.0
|
19
services/web/cypress/fixtures/build/output.log
Normal file
19
services/web/cypress/fixtures/build/output.log
Normal file
@@ -0,0 +1,19 @@
|
||||
The LaTeX compiler output
|
||||
* With a lot of details
|
||||
|
||||
Wrapped in an HTML <pre> element with
|
||||
preformatted text which is to be presented exactly
|
||||
as written in the HTML file
|
||||
|
||||
(whitespace included™)
|
||||
|
||||
The text is typically rendered using a non-proportional ("monospace") font.
|
||||
|
||||
LaTeX Font Info: External font `cmex10' loaded for size
|
||||
(Font) <7> on input line 18.
|
||||
LaTeX Font Info: External font `cmex10' loaded for size
|
||||
(Font) <5> on input line 18.
|
||||
! Undefined control sequence.
|
||||
<recently read> \Zlpha
|
||||
|
||||
main.tex, line 23
|
BIN
services/web/cypress/fixtures/build/output.pdf
Normal file
BIN
services/web/cypress/fixtures/build/output.pdf
Normal file
Binary file not shown.
BIN
services/web/cypress/fixtures/images/gradient.png
Normal file
BIN
services/web/cypress/fixtures/images/gradient.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
12
services/web/cypress/support/component-index.html
Normal file
12
services/web/cypress/support/component-index.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<title>Components App</title>
|
||||
</head>
|
||||
<body>
|
||||
<div data-cy-root></div>
|
||||
</body>
|
||||
</html>
|
12
services/web/cypress/support/component.ts
Normal file
12
services/web/cypress/support/component.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import 'cypress-plugin-tab'
|
||||
import { resetMeta } from './ct/window' // needs to be before i18n
|
||||
import localesPromise from '@/i18n'
|
||||
import './shared/commands'
|
||||
import './shared/exceptions'
|
||||
import './ct/commands'
|
||||
import './ct/codemirror'
|
||||
import '../../test/frontend/helpers/bootstrap-5'
|
||||
|
||||
beforeEach(function () {
|
||||
cy.wrap(localesPromise).then(resetMeta)
|
||||
})
|
4
services/web/cypress/support/ct/codemirror.ts
Normal file
4
services/web/cypress/support/ct/codemirror.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { EditorView } from '@codemirror/view'
|
||||
|
||||
// @ts-ignore (disable EditContext-based editing until stable)
|
||||
EditorView.EDIT_CONTEXT = false
|
14
services/web/cypress/support/ct/commands/index.ts
Normal file
14
services/web/cypress/support/ct/commands/index.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { mount } from 'cypress/react'
|
||||
|
||||
// eslint-disable-next-line no-unused-vars,@typescript-eslint/no-namespace
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace,no-unused-vars
|
||||
namespace Cypress {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
interface Chainable {
|
||||
mount: typeof mount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Cypress.Commands.add('mount', mount)
|
16
services/web/cypress/support/ct/window.ts
Normal file
16
services/web/cypress/support/ct/window.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
export function resetMeta() {
|
||||
window.metaAttributesCache = new Map()
|
||||
window.metaAttributesCache.set('ol-i18n', { currentLangCode: 'en' })
|
||||
window.metaAttributesCache.set('ol-ExposedSettings', {
|
||||
appName: 'Overleaf',
|
||||
validRootDocExtensions: ['tex', 'Rtex', 'ltx', 'Rnw'],
|
||||
fileIgnorePattern:
|
||||
'**/{{__MACOSX,.git,.texpadtmp,.R}{,/**},.!(latexmkrc),*.{dvi,aux,log,toc,out,pdfsync,synctex,synctex(busy),fdb_latexmk,fls,nlo,ind,glo,gls,glg,bbl,blg,doc,docx,gz,swp}}',
|
||||
hasLinkedProjectFileFeature: true,
|
||||
hasLinkedProjectOutputFileFeature: true,
|
||||
hasLinkUrlFeature: true,
|
||||
})
|
||||
}
|
||||
|
||||
// Populate meta for top-level access in modules on import
|
||||
resetMeta()
|
243
services/web/cypress/support/shared/commands/compile.ts
Normal file
243
services/web/cypress/support/shared/commands/compile.ts
Normal file
@@ -0,0 +1,243 @@
|
||||
import { v4 as uuid } from 'uuid'
|
||||
|
||||
const outputFiles = () => {
|
||||
const build = uuid()
|
||||
|
||||
return [
|
||||
{
|
||||
path: 'output.pdf',
|
||||
build,
|
||||
url: `/build/${build}/output.pdf`,
|
||||
type: 'pdf',
|
||||
},
|
||||
{
|
||||
path: 'output.bbl',
|
||||
build,
|
||||
url: `/build/${build}/output.bbl`,
|
||||
type: 'bbl',
|
||||
},
|
||||
{
|
||||
path: 'output.bib',
|
||||
build,
|
||||
url: `/build/${build}/output.bib`,
|
||||
type: 'bib',
|
||||
},
|
||||
{
|
||||
path: 'example.txt',
|
||||
build,
|
||||
url: `/build/${build}/example.txt`,
|
||||
type: 'txt',
|
||||
},
|
||||
{
|
||||
path: 'output.log',
|
||||
build,
|
||||
url: `/build/${build}/output.log`,
|
||||
type: 'log',
|
||||
},
|
||||
{
|
||||
path: 'output.blg',
|
||||
build,
|
||||
url: `/build/${build}/output.blg`,
|
||||
type: 'blg',
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
const compileFromCacheResponse = () => {
|
||||
return {
|
||||
fromCache: true,
|
||||
status: 'success',
|
||||
clsiServerId: 'foo',
|
||||
compileGroup: 'priority',
|
||||
pdfDownloadDomain: 'https://clsi.test-overleaf.com',
|
||||
outputFiles: outputFiles(),
|
||||
options: {
|
||||
rootResourcePath: 'main.tex',
|
||||
imageName: 'texlive-full:2024.1',
|
||||
compiler: 'pdflatex',
|
||||
stopOnFirstError: false,
|
||||
draft: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export const interceptCompileFromCacheRequest = ({
|
||||
times,
|
||||
promise,
|
||||
}: {
|
||||
times: number
|
||||
promise: Promise<void>
|
||||
}) => {
|
||||
return cy.intercept(
|
||||
{ path: '/project/*/output/cached/output.overleaf.json', times },
|
||||
async req => {
|
||||
await promise
|
||||
req.reply({ body: compileFromCacheResponse() })
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
export const interceptCompileRequest = ({ times = 1 } = {}) => {
|
||||
return cy.intercept(
|
||||
{ method: 'POST', pathname: '/project/*/compile', times },
|
||||
{
|
||||
body: {
|
||||
status: 'success',
|
||||
clsiServerId: 'foo',
|
||||
compileGroup: 'priority',
|
||||
pdfDownloadDomain: 'https://clsi.test-overleaf.com',
|
||||
outputFiles: outputFiles(),
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
export const interceptCompile = ({
|
||||
prefix = 'compile',
|
||||
times = 1,
|
||||
cached = false,
|
||||
regular = true,
|
||||
outputPDFFixture = 'output.pdf',
|
||||
} = {}) => {
|
||||
if (cached) {
|
||||
cy.intercept(
|
||||
{ path: '/project/*/output/cached/output.overleaf.json', times },
|
||||
{ body: compileFromCacheResponse() }
|
||||
).as(`${prefix}-cached`)
|
||||
} else {
|
||||
cy.intercept(
|
||||
{ pathname: '/project/*/output/cached/output.overleaf.json', times },
|
||||
{ statusCode: 404 }
|
||||
).as(`${prefix}-cached`)
|
||||
}
|
||||
|
||||
if (regular) {
|
||||
interceptCompileRequest({ times }).as(`${prefix}`)
|
||||
} else {
|
||||
cy.intercept(
|
||||
{ method: 'POST', pathname: '/project/*/compile', times },
|
||||
{
|
||||
body: {
|
||||
status: 'unavailable',
|
||||
clsiServerId: 'foo',
|
||||
compileGroup: 'priority',
|
||||
pdfDownloadDomain: 'https://clsi.test-overleaf.com',
|
||||
outputFiles: [],
|
||||
},
|
||||
}
|
||||
).as(`${prefix}`)
|
||||
}
|
||||
|
||||
cy.intercept(
|
||||
{ pathname: '/build/*/output.pdf', times },
|
||||
{ fixture: `build/${outputPDFFixture},null` }
|
||||
).as(`${prefix}-pdf`)
|
||||
|
||||
cy.intercept(
|
||||
{ pathname: '/build/*/output.log', times },
|
||||
{ fixture: 'build/output.log' }
|
||||
).as(`${prefix}-log`)
|
||||
|
||||
cy.intercept(
|
||||
{ pathname: '/build/*/output.blg', times },
|
||||
{ fixture: 'build/output.blg' }
|
||||
).as(`${prefix}-blg`)
|
||||
}
|
||||
|
||||
export const waitForCompile = ({
|
||||
prefix = 'compile',
|
||||
pdf = false,
|
||||
cached = false,
|
||||
regular = true,
|
||||
} = {}) => {
|
||||
if (cached) {
|
||||
cy.wait(`@${prefix}-cached`)
|
||||
}
|
||||
if (regular) {
|
||||
cy.wait(`@${prefix}`)
|
||||
}
|
||||
return waitForCompileOutput({ prefix, pdf, cached })
|
||||
}
|
||||
|
||||
export const waitForCompileOutput = ({
|
||||
prefix = 'compile',
|
||||
pdf = false,
|
||||
cached = false,
|
||||
} = {}) => {
|
||||
cy.wait(`@${prefix}-log`)
|
||||
.its('request.query.clsiserverid')
|
||||
.should('eq', cached ? 'cache' : 'foo') // straight from cache if cached
|
||||
cy.wait(`@${prefix}-blg`)
|
||||
.its('request.query.clsiserverid')
|
||||
.should('eq', cached ? 'cache' : 'foo') // straight from cache if cached
|
||||
if (pdf) {
|
||||
cy.wait(`@${prefix}-pdf`)
|
||||
.its('request.query.clsiserverid')
|
||||
.should('eq', 'foo') // always from VM first
|
||||
}
|
||||
return cy.wrap(null)
|
||||
}
|
||||
|
||||
export const interceptDeferredCompile = (beforeResponse?: () => void) => {
|
||||
const { promise, resolve } = Promise.withResolvers<void>()
|
||||
|
||||
cy.intercept(
|
||||
{ method: 'POST', url: '/project/*/compile*', times: 1 },
|
||||
req => {
|
||||
if (beforeResponse) {
|
||||
beforeResponse()
|
||||
}
|
||||
|
||||
// only reply once the Promise is resolved
|
||||
promise.then(() => {
|
||||
req.reply({
|
||||
body: {
|
||||
status: 'success',
|
||||
clsiServerId: 'foo',
|
||||
compileGroup: 'priority',
|
||||
pdfDownloadDomain: 'https://clsi.test-overleaf.com',
|
||||
outputFiles: [
|
||||
{
|
||||
path: 'output.pdf',
|
||||
build: '123',
|
||||
url: '/build/123/output.pdf',
|
||||
type: 'pdf',
|
||||
},
|
||||
{
|
||||
path: 'output.log',
|
||||
build: '123',
|
||||
url: '/build/123/output.log',
|
||||
type: 'log',
|
||||
},
|
||||
{
|
||||
path: 'output.blg',
|
||||
build: '123',
|
||||
url: '/build/123/output.blg',
|
||||
type: 'log',
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
return promise
|
||||
}
|
||||
).as('compile')
|
||||
|
||||
cy.intercept(
|
||||
{ pathname: '/build/*/output.pdf', times: 1 },
|
||||
{ fixture: 'build/output.pdf,null' }
|
||||
).as(`compile-pdf`)
|
||||
|
||||
cy.intercept(
|
||||
{ pathname: '/build/*/output.log', times: 1 },
|
||||
{ fixture: 'build/output.log' }
|
||||
).as(`compile-log`)
|
||||
|
||||
cy.intercept(
|
||||
{ pathname: '/build/*/output.blg', times: 1 },
|
||||
{ fixture: 'build/output.blg' }
|
||||
).as(`compile-blg`)
|
||||
|
||||
return cy.wrap(resolve)
|
||||
}
|
5
services/web/cypress/support/shared/commands/events.ts
Normal file
5
services/web/cypress/support/shared/commands/events.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export const interceptEvents = () => {
|
||||
cy.intercept('POST', '/event/*', {
|
||||
statusCode: 204,
|
||||
}).as('createEvent')
|
||||
}
|
56
services/web/cypress/support/shared/commands/index.ts
Normal file
56
services/web/cypress/support/shared/commands/index.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import '@testing-library/cypress/add-commands'
|
||||
import {
|
||||
interceptCompile,
|
||||
interceptCompileFromCacheRequest,
|
||||
waitForCompile,
|
||||
interceptDeferredCompile,
|
||||
interceptCompileRequest,
|
||||
} from './compile'
|
||||
import { interceptEvents } from './events'
|
||||
import { interceptAsync } from './intercept-async'
|
||||
import { interceptFileUpload } from './upload'
|
||||
import { interceptProjectListing } from './project-list'
|
||||
import { interceptLinkedFile } from './linked-file'
|
||||
import { interceptMathJax } from './mathjax'
|
||||
import { interceptMetadata } from './metadata'
|
||||
import { interceptTutorials } from './tutorials'
|
||||
|
||||
// eslint-disable-next-line no-unused-vars,@typescript-eslint/no-namespace
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace,no-unused-vars
|
||||
namespace Cypress {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
interface Chainable {
|
||||
interceptAsync: typeof interceptAsync
|
||||
interceptCompile: typeof interceptCompile
|
||||
interceptCompileRequest: typeof interceptCompileRequest
|
||||
interceptCompileFromCacheRequest: typeof interceptCompileFromCacheRequest
|
||||
interceptEvents: typeof interceptEvents
|
||||
interceptMetadata: typeof interceptMetadata
|
||||
waitForCompile: typeof waitForCompile
|
||||
interceptDeferredCompile: typeof interceptDeferredCompile
|
||||
interceptFileUpload: typeof interceptFileUpload
|
||||
interceptProjectListing: typeof interceptProjectListing
|
||||
interceptLinkedFile: typeof interceptLinkedFile
|
||||
interceptMathJax: typeof interceptMathJax
|
||||
interceptTutorials: typeof interceptTutorials
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Cypress.Commands.add('interceptAsync', interceptAsync)
|
||||
Cypress.Commands.add('interceptCompile', interceptCompile)
|
||||
Cypress.Commands.add('interceptCompileRequest', interceptCompileRequest)
|
||||
Cypress.Commands.add(
|
||||
'interceptCompileFromCacheRequest',
|
||||
interceptCompileFromCacheRequest
|
||||
)
|
||||
Cypress.Commands.add('interceptEvents', interceptEvents)
|
||||
Cypress.Commands.add('interceptMetadata', interceptMetadata)
|
||||
Cypress.Commands.add('waitForCompile', waitForCompile)
|
||||
Cypress.Commands.add('interceptDeferredCompile', interceptDeferredCompile)
|
||||
Cypress.Commands.add('interceptFileUpload', interceptFileUpload)
|
||||
Cypress.Commands.add('interceptProjectListing', interceptProjectListing)
|
||||
Cypress.Commands.add('interceptLinkedFile', interceptLinkedFile)
|
||||
Cypress.Commands.add('interceptMathJax', interceptMathJax)
|
||||
Cypress.Commands.add('interceptTutorials', interceptTutorials)
|
@@ -0,0 +1,19 @@
|
||||
import { RouteHandler, RouteMatcher } from 'cypress/types/net-stubbing'
|
||||
|
||||
export const interceptAsync = (route: RouteMatcher, alias: string) => {
|
||||
const deferred: { resolve: (value: RouteHandler) => void } = {
|
||||
resolve: () => {
|
||||
console.error('This should never be called')
|
||||
},
|
||||
}
|
||||
|
||||
const promise = new Promise<RouteHandler>(resolve => {
|
||||
deferred.resolve = resolve
|
||||
})
|
||||
|
||||
cy.intercept(route, req => {
|
||||
return promise.then(response => req.reply(response))
|
||||
}).as(alias)
|
||||
|
||||
return cy.wrap(deferred)
|
||||
}
|
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')
|
||||
)
|
||||
}
|
32
services/web/cypress/support/shared/commands/mathjax.ts
Normal file
32
services/web/cypress/support/shared/commands/mathjax.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
const MATHJAX_STUB = `
|
||||
window.MathJax = {
|
||||
startup: {
|
||||
promise: Promise.resolve()
|
||||
},
|
||||
svgStylesheet: () => document.createElement("STYLE"),
|
||||
typesetPromise: (elements) => {
|
||||
for (const element of elements) {
|
||||
// This will keep math delimeters around the text
|
||||
element.classList.add('MathJax')
|
||||
}
|
||||
return Promise.resolve()
|
||||
},
|
||||
tex2svgPromise: (content) => {
|
||||
const text = document.createElement('SPAN')
|
||||
text.classList.add('MathJax')
|
||||
text.innerText = content
|
||||
return Promise.resolve(text)
|
||||
},
|
||||
getMetricsFor: () => ({}),
|
||||
texReset: () => {},
|
||||
}
|
||||
`
|
||||
|
||||
export const interceptMathJax = () => {
|
||||
// NOTE: this is just a URL to be intercepted with the stub, not the real (versioned) MathJax URL
|
||||
const url = '/js/libs/mathjax/es5/tex-svg-full.js'
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-mathJaxPath', url)
|
||||
})
|
||||
cy.intercept('GET', url, MATHJAX_STUB).as('mathjax-load-request')
|
||||
}
|
3
services/web/cypress/support/shared/commands/metadata.ts
Normal file
3
services/web/cypress/support/shared/commands/metadata.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export const interceptMetadata = () => {
|
||||
cy.intercept('POST', '/project/*/doc/*/metadata', {})
|
||||
}
|
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' },
|
||||
],
|
||||
})
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
export const interceptTutorials = () => {
|
||||
cy.intercept('POST', '/tutorial/**', {
|
||||
statusCode: 204,
|
||||
}).as('completeTutorial')
|
||||
}
|
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')
|
||||
)
|
||||
}
|
6
services/web/cypress/support/shared/exceptions.ts
Normal file
6
services/web/cypress/support/shared/exceptions.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
Cypress.on('uncaught:exception', err => {
|
||||
// don't fail the test for ResizeObserver error messages
|
||||
if (err.message.includes('ResizeObserver')) {
|
||||
return false
|
||||
}
|
||||
})
|
52
services/web/cypress/support/webpack.cypress.ts
Normal file
52
services/web/cypress/support/webpack.cypress.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { merge } from 'webpack-merge'
|
||||
import path from 'path'
|
||||
import webpack from 'webpack'
|
||||
import HtmlWebpackPlugin from 'html-webpack-plugin'
|
||||
import devConfig from '../../webpack.config.dev'
|
||||
|
||||
const buildConfig = () => {
|
||||
const webpackConfig = merge(devConfig, {
|
||||
output: {
|
||||
workerPublicPath: '/__cypress/src/',
|
||||
},
|
||||
devServer: {
|
||||
static: path.join(__dirname, '../../public'),
|
||||
port: 3200,
|
||||
},
|
||||
stats: 'none',
|
||||
plugins: [
|
||||
new webpack.EnvironmentPlugin({
|
||||
CYPRESS: true,
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.resolve('./component-index.html'),
|
||||
}),
|
||||
],
|
||||
} as any)
|
||||
|
||||
delete webpackConfig.devServer.client
|
||||
|
||||
webpackConfig.entry = {}
|
||||
const addWorker = (name: string, importPath: string) => {
|
||||
webpackConfig.entry[name] = require.resolve(importPath)
|
||||
}
|
||||
|
||||
// add entrypoint under '/' for latex-linter worker
|
||||
addWorker(
|
||||
'latex-linter-worker',
|
||||
'../../frontend/js/features/source-editor/languages/latex/linter/latex-linter.worker'
|
||||
)
|
||||
|
||||
// add entrypoint under '/' for hunspell worker
|
||||
addWorker(
|
||||
'hunspell-worker',
|
||||
'../../frontend/js/features/source-editor/hunspell/hunspell.worker'
|
||||
)
|
||||
|
||||
// add entrypoints under '/' for pdfjs workers
|
||||
addWorker('pdfjs-dist', 'pdfjs-dist/build/pdf.worker.mjs')
|
||||
|
||||
return webpackConfig
|
||||
}
|
||||
|
||||
export const webpackConfig = buildConfig()
|
Reference in New Issue
Block a user