mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-15 06:33:55 +01:00
Merge pull request #33868 from overleaf/dk-package-loading-tests
[web] Add tests for pyodide worker streams and output pane rendering GitOrigin-RevId: 41ffc25230be23d68d50c61980cfaf1260a0247d
This commit is contained in:
@@ -302,6 +302,62 @@ describe('<PythonOutputPane />', function () {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('renders stdout, stderr, and info lines with visually distinct CSS classes', function () {
|
||||||
|
const executablePythonFileContents = [
|
||||||
|
'import sys',
|
||||||
|
"print('hello!')",
|
||||||
|
"sys.stderr.write('boom\\n')",
|
||||||
|
'while True:',
|
||||||
|
' pass',
|
||||||
|
].join('\n')
|
||||||
|
const projectFiles = {
|
||||||
|
[pythonExecutableScript.filename]: executablePythonFileContents,
|
||||||
|
}
|
||||||
|
const ProjectProvider = makeProjectProvider(projectFiles)
|
||||||
|
|
||||||
|
cy.mount(
|
||||||
|
<EditorProviders
|
||||||
|
scope={{
|
||||||
|
editor: {
|
||||||
|
sharejs_doc: {
|
||||||
|
doc_id: pythonExecutableScript.file_id,
|
||||||
|
getSnapshot: () => executablePythonFileContents,
|
||||||
|
},
|
||||||
|
currentDocumentId: pythonExecutableScript.file_id,
|
||||||
|
openDocName: pythonExecutableScript.filename,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
providers={{ FileTreePathProvider, ProjectProvider }}
|
||||||
|
>
|
||||||
|
<PythonExecutionProvider>
|
||||||
|
<PythonOutputPane />
|
||||||
|
</PythonExecutionProvider>
|
||||||
|
</EditorProviders>
|
||||||
|
)
|
||||||
|
|
||||||
|
cy.findByRole('button', { name: 'Run Python code' })
|
||||||
|
.should('not.be.disabled')
|
||||||
|
.click()
|
||||||
|
|
||||||
|
cy.findByText('hello!')
|
||||||
|
.should('have.class', 'ide-redesign-python-output-pane-line-stdout')
|
||||||
|
.and('not.have.class', 'ide-redesign-python-output-pane-line-stderr')
|
||||||
|
.and('not.have.class', 'ide-redesign-python-output-pane-line-info')
|
||||||
|
cy.findByText('boom')
|
||||||
|
.should('have.class', 'ide-redesign-python-output-pane-line-stderr')
|
||||||
|
.and('not.have.class', 'ide-redesign-python-output-pane-line-stdout')
|
||||||
|
.and('not.have.class', 'ide-redesign-python-output-pane-line-info')
|
||||||
|
|
||||||
|
cy.findByRole('button', { name: 'Stop Python execution' })
|
||||||
|
.should('not.be.disabled')
|
||||||
|
.click()
|
||||||
|
|
||||||
|
cy.findByText('Execution interrupted')
|
||||||
|
.should('have.class', 'ide-redesign-python-output-pane-line-info')
|
||||||
|
.and('not.have.class', 'ide-redesign-python-output-pane-line-stdout')
|
||||||
|
.and('not.have.class', 'ide-redesign-python-output-pane-line-stderr')
|
||||||
|
})
|
||||||
|
|
||||||
it('can load common python data analysis packages on code execution', function () {
|
it('can load common python data analysis packages on code execution', function () {
|
||||||
const executablePythonFileContents = [
|
const executablePythonFileContents = [
|
||||||
'import tomli',
|
'import tomli',
|
||||||
|
|||||||
+97
@@ -587,6 +587,103 @@ describe('PyodideWorkerClient', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('output-line forwarding', function () {
|
||||||
|
function setupClientWithOutputTracking() {
|
||||||
|
const outputCalls: Parameters<OutputCallback>[] = []
|
||||||
|
const client = new PyodideWorkerClient({
|
||||||
|
baseAssetPath: BASE_ASSET_PATH,
|
||||||
|
createWorker,
|
||||||
|
onOutput: (...args) => {
|
||||||
|
outputCalls.push(args)
|
||||||
|
},
|
||||||
|
fileUploader: fileUploaderStub,
|
||||||
|
})
|
||||||
|
const worker = WorkerMock.instances[0]
|
||||||
|
worker.emitMessage({ type: 'listening' })
|
||||||
|
return { client, worker, outputCalls }
|
||||||
|
}
|
||||||
|
|
||||||
|
it('forwards stdout output-line events to the output callback', function () {
|
||||||
|
const { worker, outputCalls } = setupClientWithOutputTracking()
|
||||||
|
|
||||||
|
worker.emitMessage({
|
||||||
|
type: 'output-line',
|
||||||
|
stream: 'stdout',
|
||||||
|
line: 'hello!',
|
||||||
|
fileId: 'main.py',
|
||||||
|
executionId: 'exec-stdout',
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(outputCalls).to.deep.equal([
|
||||||
|
['stdout', 'hello!', 'main.py', 'exec-stdout'],
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('forwards stderr output-line events to the output callback', function () {
|
||||||
|
const { worker, outputCalls } = setupClientWithOutputTracking()
|
||||||
|
|
||||||
|
worker.emitMessage({
|
||||||
|
type: 'output-line',
|
||||||
|
stream: 'stderr',
|
||||||
|
line: 'boom',
|
||||||
|
fileId: 'main.py',
|
||||||
|
executionId: 'exec-stderr',
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(outputCalls).to.deep.equal([
|
||||||
|
['stderr', 'boom', 'main.py', 'exec-stderr'],
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('forwards info output-line events to the output callback', function () {
|
||||||
|
const { worker, outputCalls } = setupClientWithOutputTracking()
|
||||||
|
|
||||||
|
worker.emitMessage({
|
||||||
|
type: 'output-line',
|
||||||
|
stream: 'info',
|
||||||
|
line: 'Loading numpy from package index',
|
||||||
|
fileId: 'main.py',
|
||||||
|
executionId: 'exec-info',
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(outputCalls).to.deep.equal([
|
||||||
|
['info', 'Loading numpy from package index', 'main.py', 'exec-info'],
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('preserves stream type when forwarding stdout, stderr, and info in sequence', function () {
|
||||||
|
const { worker, outputCalls } = setupClientWithOutputTracking()
|
||||||
|
|
||||||
|
worker.emitMessage({
|
||||||
|
type: 'output-line',
|
||||||
|
stream: 'info',
|
||||||
|
line: 'Loading package',
|
||||||
|
fileId: 'main.py',
|
||||||
|
executionId: 'exec-mixed',
|
||||||
|
})
|
||||||
|
worker.emitMessage({
|
||||||
|
type: 'output-line',
|
||||||
|
stream: 'stdout',
|
||||||
|
line: 'result',
|
||||||
|
fileId: 'main.py',
|
||||||
|
executionId: 'exec-mixed',
|
||||||
|
})
|
||||||
|
worker.emitMessage({
|
||||||
|
type: 'output-line',
|
||||||
|
stream: 'stderr',
|
||||||
|
line: 'warning',
|
||||||
|
fileId: 'main.py',
|
||||||
|
executionId: 'exec-mixed',
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(outputCalls.map(call => call[0])).to.deep.equal([
|
||||||
|
'info',
|
||||||
|
'stdout',
|
||||||
|
'stderr',
|
||||||
|
])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('reset', function () {
|
describe('reset', function () {
|
||||||
it('terminates the current worker and creates a new one', function () {
|
it('terminates the current worker and creates a new one', function () {
|
||||||
const client = new PyodideWorkerClient({
|
const client = new PyodideWorkerClient({
|
||||||
|
|||||||
Reference in New Issue
Block a user