2021-03-18 05:52:36 -04:00
|
|
|
|
import { expect } from 'chai'
|
2021-06-21 06:01:45 -04:00
|
|
|
|
import * as sinon from 'sinon'
|
2021-06-23 05:37:08 -04:00
|
|
|
|
import { useEffect } from 'react'
|
2022-01-10 10:46:46 -05:00
|
|
|
|
import { screen, fireEvent, cleanup, waitFor } from '@testing-library/react'
|
2021-03-18 05:52:36 -04:00
|
|
|
|
import fetchMock from 'fetch-mock'
|
|
|
|
|
import PropTypes from 'prop-types'
|
|
|
|
|
|
2022-01-10 10:46:46 -05:00
|
|
|
|
import renderWithContext from '../../helpers/render-with-context'
|
2021-03-18 05:52:36 -04:00
|
|
|
|
import FileTreeModalCreateFile from '../../../../../../frontend/js/features/file-tree/components/modals/file-tree-modal-create-file'
|
|
|
|
|
import { useFileTreeActionable } from '../../../../../../frontend/js/features/file-tree/contexts/file-tree-actionable'
|
2022-01-10 10:47:01 -05:00
|
|
|
|
import { useFileTreeData } from '../../../../../../frontend/js/shared/context/file-tree-data-context'
|
2021-03-18 05:52:36 -04:00
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
|
describe('<FileTreeModalCreateFile/>', function () {
|
2021-07-27 09:26:51 -04:00
|
|
|
|
beforeEach(function () {
|
|
|
|
|
window.csrfToken = 'token'
|
|
|
|
|
})
|
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
|
afterEach(function () {
|
2021-07-27 09:26:51 -04:00
|
|
|
|
delete window.csrfToken
|
2021-03-18 05:52:36 -04:00
|
|
|
|
fetchMock.restore()
|
|
|
|
|
cleanup()
|
|
|
|
|
})
|
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
|
it('handles invalid file names', async function () {
|
2022-01-10 10:46:46 -05:00
|
|
|
|
renderWithContext(<OpenWithMode mode="doc" />)
|
2021-03-18 05:52:36 -04:00
|
|
|
|
|
|
|
|
|
const submitButton = screen.getByRole('button', { name: 'Create' })
|
|
|
|
|
|
|
|
|
|
const input = screen.getByLabelText('File Name')
|
|
|
|
|
expect(input.value).to.equal('name.tex')
|
|
|
|
|
expect(submitButton.disabled).to.be.false
|
|
|
|
|
expect(screen.queryAllByRole('alert')).to.be.empty
|
|
|
|
|
|
|
|
|
|
fireEvent.change(input, { target: { value: '' } })
|
|
|
|
|
expect(submitButton.disabled).to.be.true
|
|
|
|
|
screen.getByRole(
|
|
|
|
|
(role, element) =>
|
|
|
|
|
role === 'alert' && element.textContent.match(/File name is empty/)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
await fireEvent.change(input, { target: { value: 'test.tex' } })
|
|
|
|
|
expect(submitButton.disabled).to.be.false
|
|
|
|
|
expect(screen.queryAllByRole('alert')).to.be.empty
|
|
|
|
|
|
|
|
|
|
await fireEvent.change(input, { target: { value: 'oops/i/did/it/again' } })
|
|
|
|
|
expect(submitButton.disabled).to.be.true
|
|
|
|
|
screen.getByRole(
|
|
|
|
|
(role, element) =>
|
|
|
|
|
role === 'alert' &&
|
|
|
|
|
element.textContent.match(/contains invalid characters/)
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
|
it('displays an error when the file limit is reached', async function () {
|
2021-03-18 05:52:36 -04:00
|
|
|
|
const rootFolder = [
|
|
|
|
|
{
|
2022-01-10 10:46:46 -05:00
|
|
|
|
_id: 'root-folder-id',
|
|
|
|
|
name: 'rootFolder',
|
2021-03-18 05:52:36 -04:00
|
|
|
|
docs: Array.from({ length: 10 }, (_, index) => ({
|
2021-04-27 03:52:58 -04:00
|
|
|
|
_id: `entity-${index}`,
|
2021-03-18 05:52:36 -04:00
|
|
|
|
})),
|
|
|
|
|
fileRefs: [],
|
2021-04-27 03:52:58 -04:00
|
|
|
|
folders: [],
|
|
|
|
|
},
|
2021-03-18 05:52:36 -04:00
|
|
|
|
]
|
|
|
|
|
|
2022-01-10 10:46:46 -05:00
|
|
|
|
renderWithContext(<OpenWithMode mode="doc" />, {
|
2022-01-10 10:47:01 -05:00
|
|
|
|
contextProps: { rootFolder },
|
2022-01-10 10:46:46 -05:00
|
|
|
|
})
|
2021-03-18 05:52:36 -04:00
|
|
|
|
|
|
|
|
|
screen.getByRole(
|
|
|
|
|
(role, element) =>
|
|
|
|
|
role === 'alert' &&
|
|
|
|
|
element.textContent.match(/This project has reached the \d+ file limit/)
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
|
it('displays a warning when the file limit is nearly reached', async function () {
|
2021-03-18 05:52:36 -04:00
|
|
|
|
const rootFolder = [
|
|
|
|
|
{
|
2022-01-10 10:46:46 -05:00
|
|
|
|
_id: 'root-folder-id',
|
|
|
|
|
name: 'rootFolder',
|
2021-03-18 05:52:36 -04:00
|
|
|
|
docs: Array.from({ length: 9 }, (_, index) => ({
|
2021-04-27 03:52:58 -04:00
|
|
|
|
_id: `entity-${index}`,
|
2021-03-18 05:52:36 -04:00
|
|
|
|
})),
|
|
|
|
|
fileRefs: [],
|
2021-04-27 03:52:58 -04:00
|
|
|
|
folders: [],
|
|
|
|
|
},
|
2021-03-18 05:52:36 -04:00
|
|
|
|
]
|
|
|
|
|
|
2022-01-10 10:46:46 -05:00
|
|
|
|
renderWithContext(<OpenWithMode mode="doc" />, {
|
2022-01-10 10:47:01 -05:00
|
|
|
|
contextProps: { rootFolder },
|
2022-01-10 10:46:46 -05:00
|
|
|
|
})
|
2021-03-18 05:52:36 -04:00
|
|
|
|
|
|
|
|
|
screen.getByText(/This project is approaching the file limit \(\d+\/\d+\)/)
|
|
|
|
|
})
|
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
|
it('counts files in nested folders', async function () {
|
2021-03-18 05:52:36 -04:00
|
|
|
|
const rootFolder = [
|
|
|
|
|
{
|
2022-01-10 10:46:46 -05:00
|
|
|
|
_id: 'root-folder-id',
|
|
|
|
|
name: 'rootFolder',
|
2022-06-08 04:28:46 -04:00
|
|
|
|
docs: [{ _id: 'doc-1' }],
|
2021-03-18 05:52:36 -04:00
|
|
|
|
fileRefs: [],
|
|
|
|
|
folders: [
|
|
|
|
|
{
|
2022-06-08 04:28:46 -04:00
|
|
|
|
docs: [{ _id: 'doc-2' }],
|
2021-03-18 05:52:36 -04:00
|
|
|
|
fileRefs: [],
|
|
|
|
|
folders: [
|
|
|
|
|
{
|
|
|
|
|
docs: [
|
2022-06-08 04:28:46 -04:00
|
|
|
|
{ _id: 'doc-3' },
|
|
|
|
|
{ _id: 'doc-4' },
|
|
|
|
|
{ _id: 'doc-5' },
|
|
|
|
|
{ _id: 'doc-6' },
|
|
|
|
|
{ _id: 'doc-7' },
|
2021-03-18 05:52:36 -04:00
|
|
|
|
],
|
|
|
|
|
fileRefs: [],
|
2021-04-27 03:52:58 -04:00
|
|
|
|
folders: [],
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
2021-03-18 05:52:36 -04:00
|
|
|
|
]
|
|
|
|
|
|
2022-01-10 10:46:46 -05:00
|
|
|
|
renderWithContext(<OpenWithMode mode="doc" />, {
|
2022-01-10 10:47:01 -05:00
|
|
|
|
contextProps: { rootFolder },
|
2022-01-10 10:46:46 -05:00
|
|
|
|
})
|
2021-03-18 05:52:36 -04:00
|
|
|
|
|
|
|
|
|
screen.getByText(/This project is approaching the file limit \(\d+\/\d+\)/)
|
|
|
|
|
})
|
|
|
|
|
|
2022-06-08 04:28:46 -04:00
|
|
|
|
it('counts folders toward the limit', async function () {
|
|
|
|
|
const rootFolder = [
|
|
|
|
|
{
|
|
|
|
|
_id: 'root-folder-id',
|
|
|
|
|
name: 'rootFolder',
|
|
|
|
|
docs: [{ _id: 'doc-1' }],
|
|
|
|
|
fileRefs: [],
|
|
|
|
|
folders: [
|
|
|
|
|
{ docs: [], fileRefs: [], folders: [] },
|
|
|
|
|
{ docs: [], fileRefs: [], folders: [] },
|
|
|
|
|
{ docs: [], fileRefs: [], folders: [] },
|
|
|
|
|
{ docs: [], fileRefs: [], folders: [] },
|
|
|
|
|
{ docs: [], fileRefs: [], folders: [] },
|
|
|
|
|
{ docs: [], fileRefs: [], folders: [] },
|
|
|
|
|
{ docs: [], fileRefs: [], folders: [] },
|
|
|
|
|
{ docs: [], fileRefs: [], folders: [] },
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
renderWithContext(<OpenWithMode mode="doc" />, {
|
|
|
|
|
contextProps: { rootFolder },
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
screen.getByText(/This project is approaching the file limit \(\d+\/\d+\)/)
|
|
|
|
|
})
|
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
|
it('creates a new file when the form is submitted', async function () {
|
2021-03-18 05:52:36 -04:00
|
|
|
|
fetchMock.post('express:/project/:projectId/doc', () => 204)
|
|
|
|
|
|
2022-01-10 10:46:46 -05:00
|
|
|
|
renderWithContext(<OpenWithMode mode="doc" />)
|
2021-03-18 05:52:36 -04:00
|
|
|
|
|
|
|
|
|
const input = screen.getByLabelText('File Name')
|
|
|
|
|
await fireEvent.change(input, { target: { value: 'test.tex' } })
|
|
|
|
|
|
|
|
|
|
const submitButton = screen.getByRole('button', { name: 'Create' })
|
|
|
|
|
|
|
|
|
|
await fireEvent.click(submitButton)
|
|
|
|
|
|
|
|
|
|
expect(
|
|
|
|
|
fetchMock.called('express:/project/:projectId/doc', {
|
2022-01-10 10:46:46 -05:00
|
|
|
|
body: {
|
|
|
|
|
parent_folder_id: 'root-folder-id',
|
|
|
|
|
name: 'test.tex',
|
|
|
|
|
},
|
2021-03-18 05:52:36 -04:00
|
|
|
|
})
|
|
|
|
|
).to.be.true
|
|
|
|
|
})
|
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
|
it('imports a new file from a project', async function () {
|
2021-03-18 05:52:36 -04:00
|
|
|
|
fetchMock
|
|
|
|
|
.get('path:/user/projects', {
|
|
|
|
|
projects: [
|
|
|
|
|
{
|
|
|
|
|
_id: 'test-project',
|
2021-04-27 03:52:58 -04:00
|
|
|
|
name: 'This Project',
|
2021-03-18 05:52:36 -04:00
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
_id: 'project-1',
|
2021-04-27 03:52:58 -04:00
|
|
|
|
name: 'Project One',
|
2021-03-18 05:52:36 -04:00
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
_id: 'project-2',
|
2021-04-27 03:52:58 -04:00
|
|
|
|
name: 'Project Two',
|
|
|
|
|
},
|
|
|
|
|
],
|
2021-03-18 05:52:36 -04:00
|
|
|
|
})
|
|
|
|
|
.get('express:/project/:projectId/entities', {
|
|
|
|
|
entities: [
|
|
|
|
|
{
|
2021-04-27 03:52:58 -04:00
|
|
|
|
path: '/foo.tex',
|
2021-03-18 05:52:36 -04:00
|
|
|
|
},
|
|
|
|
|
{
|
2021-04-27 03:52:58 -04:00
|
|
|
|
path: '/bar.tex',
|
|
|
|
|
},
|
|
|
|
|
],
|
2021-03-18 05:52:36 -04:00
|
|
|
|
})
|
|
|
|
|
.post('express:/project/:projectId/compile', {
|
|
|
|
|
status: 'success',
|
|
|
|
|
outputFiles: [
|
|
|
|
|
{
|
|
|
|
|
build: 'test',
|
2021-04-27 03:52:58 -04:00
|
|
|
|
path: 'baz.jpg',
|
2021-03-18 05:52:36 -04:00
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
build: 'test',
|
2021-04-27 03:52:58 -04:00
|
|
|
|
path: 'ball.jpg',
|
|
|
|
|
},
|
|
|
|
|
],
|
2021-03-18 05:52:36 -04:00
|
|
|
|
})
|
|
|
|
|
.post('express:/project/:projectId/linked_file', () => 204)
|
|
|
|
|
|
2022-01-10 10:46:46 -05:00
|
|
|
|
renderWithContext(<OpenWithMode mode="project" />)
|
2021-03-18 05:52:36 -04:00
|
|
|
|
|
|
|
|
|
// initial state, no project selected
|
|
|
|
|
const projectInput = screen.getByLabelText('Select a Project')
|
|
|
|
|
expect(projectInput.disabled).to.be.true
|
|
|
|
|
await waitFor(() => {
|
|
|
|
|
expect(projectInput.disabled).to.be.false
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// the submit button should be disabled
|
|
|
|
|
const submitButton = screen.getByRole('button', { name: 'Create' })
|
|
|
|
|
expect(submitButton.disabled).to.be.true
|
|
|
|
|
|
|
|
|
|
// the source file selector should be disabled
|
|
|
|
|
const fileInput = screen.getByLabelText('Select a File')
|
|
|
|
|
expect(fileInput.disabled).to.be.true
|
|
|
|
|
// TODO: check for options length, excluding current project
|
|
|
|
|
|
|
|
|
|
// select a project
|
|
|
|
|
await fireEvent.change(projectInput, { target: { value: 'project-2' } }) // TODO: getByRole('option')?
|
|
|
|
|
|
|
|
|
|
// wait for the source file selector to be enabled
|
|
|
|
|
await waitFor(() => {
|
|
|
|
|
expect(fileInput.disabled).to.be.false
|
|
|
|
|
})
|
|
|
|
|
expect(screen.queryByLabelText('Select a File')).not.to.be.null
|
|
|
|
|
expect(screen.queryByLabelText('Select an Output File')).to.be.null
|
|
|
|
|
expect(submitButton.disabled).to.be.true
|
|
|
|
|
|
|
|
|
|
// TODO: check for fileInput options length, excluding current project
|
|
|
|
|
|
|
|
|
|
// click on the button to toggle between source and output files
|
|
|
|
|
const sourceTypeButton = screen.getByRole('button', {
|
2021-07-30 04:57:41 -04:00
|
|
|
|
// NOTE: When changing the label, update the other tests with this label as well.
|
2021-04-27 03:52:58 -04:00
|
|
|
|
name: 'select from output files',
|
2021-03-18 05:52:36 -04:00
|
|
|
|
})
|
|
|
|
|
await fireEvent.click(sourceTypeButton)
|
|
|
|
|
|
|
|
|
|
// wait for the output file selector to be enabled
|
|
|
|
|
const entityInput = screen.getByLabelText('Select an Output File')
|
|
|
|
|
await waitFor(() => {
|
|
|
|
|
expect(entityInput.disabled).to.be.false
|
|
|
|
|
})
|
|
|
|
|
expect(screen.queryByLabelText('Select a File')).to.be.null
|
|
|
|
|
expect(screen.queryByLabelText('Select an Output File')).not.to.be.null
|
|
|
|
|
expect(submitButton.disabled).to.be.true
|
|
|
|
|
|
|
|
|
|
// TODO: check for entityInput options length, excluding current project
|
|
|
|
|
await fireEvent.change(entityInput, { target: { value: 'ball.jpg' } }) // TODO: getByRole('option')?
|
|
|
|
|
|
|
|
|
|
await waitFor(() => {
|
|
|
|
|
expect(submitButton.disabled).to.be.false
|
|
|
|
|
})
|
|
|
|
|
await fireEvent.click(submitButton)
|
|
|
|
|
|
|
|
|
|
expect(
|
|
|
|
|
fetchMock.called('express:/project/:projectId/linked_file', {
|
|
|
|
|
body: {
|
|
|
|
|
name: 'ball.jpg',
|
|
|
|
|
provider: 'project_output_file',
|
2022-01-10 10:46:46 -05:00
|
|
|
|
parent_folder_id: 'root-folder-id',
|
2021-03-18 05:52:36 -04:00
|
|
|
|
data: {
|
|
|
|
|
source_project_id: 'project-2',
|
|
|
|
|
source_output_file_path: 'ball.jpg',
|
2021-04-27 03:52:58 -04:00
|
|
|
|
build_id: 'test',
|
|
|
|
|
},
|
|
|
|
|
},
|
2021-03-18 05:52:36 -04:00
|
|
|
|
})
|
|
|
|
|
).to.be.true
|
|
|
|
|
})
|
|
|
|
|
|
2021-07-30 04:57:41 -04:00
|
|
|
|
describe('when the output files feature is not available', function () {
|
|
|
|
|
const flagBefore = window.ExposedSettings.hasLinkedProjectOutputFileFeature
|
|
|
|
|
before(function () {
|
|
|
|
|
window.ExposedSettings.hasLinkedProjectOutputFileFeature = false
|
|
|
|
|
})
|
|
|
|
|
after(function () {
|
|
|
|
|
window.ExposedSettings.hasLinkedProjectOutputFileFeature = flagBefore
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should not show the import from output file mode', async function () {
|
|
|
|
|
fetchMock.get('path:/user/projects', {
|
|
|
|
|
projects: [
|
|
|
|
|
{
|
|
|
|
|
_id: 'test-project',
|
|
|
|
|
name: 'This Project',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
_id: 'project-1',
|
|
|
|
|
name: 'Project One',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
_id: 'project-2',
|
|
|
|
|
name: 'Project Two',
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
})
|
|
|
|
|
|
2022-01-10 10:46:46 -05:00
|
|
|
|
renderWithContext(<OpenWithMode mode="project" />)
|
2021-07-30 04:57:41 -04:00
|
|
|
|
|
|
|
|
|
// should not show the toggle
|
|
|
|
|
expect(
|
|
|
|
|
screen.queryByRole('button', {
|
|
|
|
|
name: 'select from output files',
|
|
|
|
|
})
|
|
|
|
|
).to.be.null
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
|
it('import from a URL when the form is submitted', async function () {
|
2021-03-18 05:52:36 -04:00
|
|
|
|
fetchMock.post('express:/project/:projectId/linked_file', () => 204)
|
|
|
|
|
|
2022-01-10 10:46:46 -05:00
|
|
|
|
renderWithContext(<OpenWithMode mode="url" />)
|
2021-03-18 05:52:36 -04:00
|
|
|
|
|
|
|
|
|
const urlInput = screen.getByLabelText('URL to fetch the file from')
|
|
|
|
|
const nameInput = screen.getByLabelText('File Name In This Project')
|
|
|
|
|
|
|
|
|
|
await fireEvent.change(urlInput, {
|
2021-04-27 03:52:58 -04:00
|
|
|
|
target: { value: 'https://example.com/example.tex' },
|
2021-03-18 05:52:36 -04:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// check that the name has updated automatically
|
|
|
|
|
expect(nameInput.value).to.equal('example.tex')
|
|
|
|
|
|
|
|
|
|
await fireEvent.change(nameInput, {
|
2021-04-27 03:52:58 -04:00
|
|
|
|
target: { value: 'test.tex' },
|
2021-03-18 05:52:36 -04:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// check that the name can still be edited manually
|
|
|
|
|
expect(nameInput.value).to.equal('test.tex')
|
|
|
|
|
|
|
|
|
|
const submitButton = screen.getByRole('button', { name: 'Create' })
|
|
|
|
|
|
|
|
|
|
await fireEvent.click(submitButton)
|
|
|
|
|
|
|
|
|
|
expect(
|
|
|
|
|
fetchMock.called('express:/project/:projectId/linked_file', {
|
|
|
|
|
body: {
|
|
|
|
|
name: 'test.tex',
|
|
|
|
|
provider: 'url',
|
2022-01-10 10:46:46 -05:00
|
|
|
|
parent_folder_id: 'root-folder-id',
|
2021-04-27 03:52:58 -04:00
|
|
|
|
data: { url: 'https://example.com/example.tex' },
|
|
|
|
|
},
|
2021-03-18 05:52:36 -04:00
|
|
|
|
})
|
|
|
|
|
).to.be.true
|
|
|
|
|
})
|
|
|
|
|
|
2021-06-21 06:01:45 -04:00
|
|
|
|
it('uploads a dropped file', async function () {
|
|
|
|
|
const xhr = sinon.useFakeXMLHttpRequest()
|
|
|
|
|
const requests = []
|
|
|
|
|
xhr.onCreate = request => {
|
|
|
|
|
requests.push(request)
|
|
|
|
|
}
|
2021-03-18 05:52:36 -04:00
|
|
|
|
|
2022-01-10 10:46:46 -05:00
|
|
|
|
renderWithContext(<OpenWithMode mode="upload" />)
|
2021-03-18 05:52:36 -04:00
|
|
|
|
|
|
|
|
|
// the submit button should not be present
|
|
|
|
|
expect(screen.queryByRole('button', { name: 'Create' })).to.be.null
|
|
|
|
|
|
2023-10-17 04:41:40 -04:00
|
|
|
|
await waitFor(() => {
|
|
|
|
|
const dropzone = screen.getByLabelText('File Uploader')
|
2021-03-18 05:52:36 -04:00
|
|
|
|
|
2023-10-17 04:41:40 -04:00
|
|
|
|
expect(dropzone).not.to.be.null
|
2021-03-18 05:52:36 -04:00
|
|
|
|
|
2023-10-17 04:41:40 -04:00
|
|
|
|
fireEvent.drop(dropzone, {
|
|
|
|
|
dataTransfer: {
|
|
|
|
|
files: [new File(['test'], 'test.tex', { type: 'text/plain' })],
|
|
|
|
|
},
|
|
|
|
|
})
|
2021-03-18 05:52:36 -04:00
|
|
|
|
})
|
|
|
|
|
|
2021-06-21 06:01:45 -04:00
|
|
|
|
await waitFor(() => expect(requests).to.have.length(1))
|
|
|
|
|
|
|
|
|
|
const [request] = requests
|
2022-01-10 10:46:46 -05:00
|
|
|
|
expect(request.url).to.equal(
|
|
|
|
|
'/project/123abc/upload?folder_id=root-folder-id'
|
|
|
|
|
)
|
2021-06-21 06:01:45 -04:00
|
|
|
|
expect(request.method).to.equal('POST')
|
|
|
|
|
|
|
|
|
|
xhr.restore()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('uploads a pasted file', async function () {
|
|
|
|
|
const xhr = sinon.useFakeXMLHttpRequest()
|
|
|
|
|
const requests = []
|
|
|
|
|
xhr.onCreate = request => {
|
|
|
|
|
requests.push(request)
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-10 10:46:46 -05:00
|
|
|
|
renderWithContext(<OpenWithMode mode="upload" />)
|
2021-06-21 06:01:45 -04:00
|
|
|
|
|
|
|
|
|
// the submit button should not be present
|
|
|
|
|
expect(screen.queryByRole('button', { name: 'Create' })).to.be.null
|
|
|
|
|
|
2023-10-17 04:41:40 -04:00
|
|
|
|
await waitFor(() => {
|
|
|
|
|
const dropzone = screen.getByLabelText('File Uploader')
|
2021-06-21 06:01:45 -04:00
|
|
|
|
|
2023-10-17 04:41:40 -04:00
|
|
|
|
expect(dropzone).not.to.be.null
|
2021-06-21 06:01:45 -04:00
|
|
|
|
|
2023-10-17 04:41:40 -04:00
|
|
|
|
fireEvent.paste(dropzone, {
|
|
|
|
|
clipboardData: {
|
|
|
|
|
files: [new File(['test'], 'test.tex', { type: 'text/plain' })],
|
|
|
|
|
},
|
|
|
|
|
})
|
2021-06-21 06:01:45 -04:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
await waitFor(() => expect(requests).to.have.length(1))
|
|
|
|
|
|
|
|
|
|
const [request] = requests
|
2022-01-10 10:46:46 -05:00
|
|
|
|
expect(request.url).to.equal(
|
|
|
|
|
'/project/123abc/upload?folder_id=root-folder-id'
|
|
|
|
|
)
|
2021-06-21 06:01:45 -04:00
|
|
|
|
expect(request.method).to.equal('POST')
|
|
|
|
|
|
|
|
|
|
xhr.restore()
|
2021-03-18 05:52:36 -04:00
|
|
|
|
})
|
2021-07-27 09:26:51 -04:00
|
|
|
|
|
|
|
|
|
it('displays upload errors', async function () {
|
|
|
|
|
const xhr = sinon.useFakeXMLHttpRequest()
|
|
|
|
|
const requests = []
|
|
|
|
|
xhr.onCreate = request => {
|
|
|
|
|
requests.push(request)
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-10 10:46:46 -05:00
|
|
|
|
renderWithContext(<OpenWithMode mode="upload" />)
|
2021-07-27 09:26:51 -04:00
|
|
|
|
|
|
|
|
|
// the submit button should not be present
|
|
|
|
|
expect(screen.queryByRole('button', { name: 'Create' })).to.be.null
|
|
|
|
|
|
2023-10-17 04:41:40 -04:00
|
|
|
|
await waitFor(() => {
|
|
|
|
|
const dropzone = screen.getByLabelText('File Uploader')
|
2021-07-27 09:26:51 -04:00
|
|
|
|
|
2023-10-17 04:41:40 -04:00
|
|
|
|
expect(dropzone).not.to.be.null
|
2021-07-27 09:26:51 -04:00
|
|
|
|
|
2023-10-17 04:41:40 -04:00
|
|
|
|
fireEvent.paste(dropzone, {
|
|
|
|
|
clipboardData: {
|
|
|
|
|
files: [new File(['test'], 'tes!t.tex', { type: 'text/plain' })],
|
|
|
|
|
},
|
|
|
|
|
})
|
2021-07-27 09:26:51 -04:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
await waitFor(() => expect(requests).to.have.length(1))
|
|
|
|
|
|
|
|
|
|
const [request] = requests
|
2022-01-10 10:46:46 -05:00
|
|
|
|
expect(request.url).to.equal(
|
|
|
|
|
'/project/123abc/upload?folder_id=root-folder-id'
|
|
|
|
|
)
|
2021-07-27 09:26:51 -04:00
|
|
|
|
expect(request.method).to.equal('POST')
|
|
|
|
|
|
|
|
|
|
request.respond(
|
|
|
|
|
422,
|
|
|
|
|
{ 'Content-Type': 'application/json' },
|
|
|
|
|
'{ "success": false, "error": "invalid_filename" }'
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
await screen.findByText(
|
2021-08-16 10:59:04 -04:00
|
|
|
|
`Upload failed: check that the file name doesn’t contain special characters, trailing/leading whitespace or more than 150 characters`
|
2021-07-27 09:26:51 -04:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
xhr.restore()
|
|
|
|
|
})
|
2021-03-18 05:52:36 -04:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
function OpenWithMode({ mode }) {
|
|
|
|
|
const { newFileCreateMode, startCreatingFile } = useFileTreeActionable()
|
|
|
|
|
|
2022-01-10 10:47:01 -05:00
|
|
|
|
const { fileCount } = useFileTreeData()
|
2021-03-18 05:52:36 -04:00
|
|
|
|
|
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
|
useEffect(() => startCreatingFile(mode), [])
|
|
|
|
|
|
|
|
|
|
if (!fileCount || !newFileCreateMode) {
|
|
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return <FileTreeModalCreateFile />
|
|
|
|
|
}
|
|
|
|
|
OpenWithMode.propTypes = {
|
2021-04-27 03:52:58 -04:00
|
|
|
|
mode: PropTypes.string.isRequired,
|
2021-03-18 05:52:36 -04:00
|
|
|
|
}
|