Merge pull request #3495 from overleaf/ae-prettier-2

Upgrade Prettier to v2

GitOrigin-RevId: 85aa3fa1acb6332c4f58c46165a43d1a51471f33
This commit is contained in:
Alf Eaton
2021-04-15 02:05:22 +00:00
committed by Copybot
parent 930d7ba028
commit 1ebc8a79cb
582 changed files with 20382 additions and 20374 deletions
@@ -10,7 +10,7 @@ import {
} from '../../../helpers/render-with-context'
import { stubMathJax, tearDownMathJaxStubs } from './stubs'
describe('<ChatPane />', function() {
describe('<ChatPane />', function () {
const user = {
id: 'fake_user',
first_name: 'fake_user_first_name',
@@ -32,18 +32,18 @@ describe('<ChatPane />', function() {
}
]
beforeEach(function() {
beforeEach(function () {
fetchMock.reset()
cleanUpContext()
stubMathJax()
})
afterEach(function() {
afterEach(function () {
tearDownMathJaxStubs()
})
it('renders multiple messages', async function() {
it('renders multiple messages', async function () {
fetchMock.get(/messages/, testMessages)
renderWithChatContext(<ChatPane />, { user })
@@ -52,7 +52,7 @@ describe('<ChatPane />', function() {
await screen.findByText('another message')
})
it('A loading spinner is rendered while the messages are loading, then disappears', async function() {
it('A loading spinner is rendered while the messages are loading, then disappears', async function () {
fetchMock.get(/messages/, [])
renderWithChatContext(<ChatPane />, { user })
@@ -60,8 +60,8 @@ describe('<ChatPane />', function() {
await waitForElementToBeRemoved(() => screen.getByText('Loading…'))
})
describe('"send your first message" placeholder', function() {
it('is rendered when there are no messages ', async function() {
describe('"send your first message" placeholder', function () {
it('is rendered when there are no messages ', async function () {
fetchMock.get(/messages/, [])
renderWithChatContext(<ChatPane />, { user })
@@ -69,7 +69,7 @@ describe('<ChatPane />', function() {
await screen.findByText('Send your first message to your collaborators')
})
it('is not rendered when messages are displayed', function() {
it('is not rendered when messages are displayed', function () {
fetchMock.get(/messages/, testMessages)
renderWithChatContext(<ChatPane />, { user })
@@ -5,15 +5,15 @@ import { screen, render, fireEvent } from '@testing-library/react'
import MessageInput from '../../../../../frontend/js/features/chat/components/message-input'
describe('<MessageInput />', function() {
describe('<MessageInput />', function () {
let resetUnreadMessages, sendMessage
beforeEach(function() {
beforeEach(function () {
resetUnreadMessages = sinon.stub()
sendMessage = sinon.stub()
})
it('renders successfully', function() {
it('renders successfully', function () {
render(
<MessageInput
sendMessage={sendMessage}
@@ -24,7 +24,7 @@ describe('<MessageInput />', function() {
screen.getByLabelText('Your Message')
})
it('sends a message after typing and hitting enter', function() {
it('sends a message after typing and hitting enter', function () {
render(
<MessageInput
sendMessage={sendMessage}
@@ -40,7 +40,7 @@ describe('<MessageInput />', function() {
expect(sendMessage).to.be.calledWith('hello world')
})
it('resets the number of unread messages after clicking on the input', function() {
it('resets the number of unread messages after clicking on the input', function () {
render(
<MessageInput
sendMessage={sendMessage}
@@ -6,7 +6,7 @@ import { screen, render, fireEvent } from '@testing-library/react'
import MessageList from '../../../../../frontend/js/features/chat/components/message-list'
import { stubMathJax, tearDownMathJaxStubs } from './stubs'
describe('<MessageList />', function() {
describe('<MessageList />', function () {
const currentUser = {
id: 'fake_user',
first_name: 'fake_user_first_name',
@@ -30,15 +30,15 @@ describe('<MessageList />', function() {
]
}
before(function() {
before(function () {
stubMathJax()
})
after(function() {
after(function () {
tearDownMathJaxStubs()
})
it('renders multiple messages', function() {
it('renders multiple messages', function () {
render(
<MessageList
userId={currentUser.id}
@@ -51,7 +51,7 @@ describe('<MessageList />', function() {
screen.getByText('another message')
})
it('renders a single timestamp for all messages within 5 minutes', function() {
it('renders a single timestamp for all messages within 5 minutes', function () {
const msgs = createMessages()
msgs[0].timestamp = new Date(2019, 6, 3, 4, 23).getTime()
msgs[1].timestamp = new Date(2019, 6, 3, 4, 27).getTime()
@@ -68,7 +68,7 @@ describe('<MessageList />', function() {
expect(screen.queryByText('4:27 am Wed, 3rd Jul 19')).to.not.exist
})
it('renders a timestamp for each messages separated for more than 5 minutes', function() {
it('renders a timestamp for each messages separated for more than 5 minutes', function () {
const msgs = createMessages()
msgs[0].timestamp = new Date(2019, 6, 3, 4, 23).getTime()
msgs[1].timestamp = new Date(2019, 6, 3, 4, 31).getTime()
@@ -85,7 +85,7 @@ describe('<MessageList />', function() {
screen.getByText('4:31 am Wed, 3rd Jul 19')
})
it('resets the number of unread messages after clicking on the input', function() {
it('resets the number of unread messages after clicking on the input', function () {
const resetUnreadMessages = sinon.stub()
render(
<MessageList
@@ -5,24 +5,24 @@ import { render, screen } from '@testing-library/react'
import Message from '../../../../../frontend/js/features/chat/components/message'
import { stubMathJax, tearDownMathJaxStubs } from './stubs'
describe('<Message />', function() {
describe('<Message />', function () {
const currentUser = {
id: 'fake_user',
first_name: 'fake_user_first_name',
email: 'fake@example.com'
}
beforeEach(function() {
beforeEach(function () {
window.user = currentUser
stubMathJax()
})
afterEach(function() {
afterEach(function () {
delete window.user
tearDownMathJaxStubs()
})
it('renders a basic message', function() {
it('renders a basic message', function () {
const message = {
contents: ['a message'],
user: currentUser
@@ -33,7 +33,7 @@ describe('<Message />', function() {
screen.getByText('a message')
})
it('renders a message with multiple contents', function() {
it('renders a message with multiple contents', function () {
const message = {
contents: ['a message', 'another message'],
user: currentUser
@@ -45,7 +45,7 @@ describe('<Message />', function() {
screen.getByText('another message')
})
it('renders HTML links within messages', function() {
it('renders HTML links within messages', function () {
const message = {
contents: [
'a message with a <a href="https://overleaf.com">link to Overleaf</a>'
@@ -58,13 +58,13 @@ describe('<Message />', function() {
screen.getByRole('link', { name: 'https://overleaf.com' })
})
describe('when the message is from the user themselves', function() {
describe('when the message is from the user themselves', function () {
const message = {
contents: ['a message'],
user: currentUser
}
it('does not render the user name nor the email', function() {
it('does not render the user name nor the email', function () {
render(<Message userId={currentUser.id} message={message} />)
expect(screen.queryByText(currentUser.first_name)).to.not.exist
@@ -72,7 +72,7 @@ describe('<Message />', function() {
})
})
describe('when the message is from other user', function() {
describe('when the message is from other user', function () {
const otherUser = {
id: 'other_user',
first_name: 'other_user_first_name'
@@ -83,13 +83,13 @@ describe('<Message />', function() {
user: otherUser
}
it('should render the other user name', function() {
it('should render the other user name', function () {
render(<Message userId={currentUser.id} message={message} />)
screen.getByText(otherUser.first_name)
})
it('should render the other user email when their name is not available', function() {
it('should render the other user email when their name is not available', function () {
const msg = {
contents: message.contents,
user: {
@@ -6,7 +6,7 @@ import {
MESSAGE_LIMIT
} from '../../../../../frontend/js/features/chat/store/chat-store'
describe('ChatStore', function() {
describe('ChatStore', function () {
let store, socket, mockSocketMessage
const user = {
@@ -22,7 +22,7 @@ describe('ChatStore', function() {
user
}
beforeEach(function() {
beforeEach(function () {
fetchMock.reset()
window.csrfToken = 'csrf_tok'
@@ -34,7 +34,7 @@ describe('ChatStore', function() {
store = new ChatStore(user, testProjectId)
})
afterEach(function() {
afterEach(function () {
fetchMock.restore()
delete window._ide
delete window.csrfToken
@@ -42,19 +42,19 @@ describe('ChatStore', function() {
delete window.project_id
})
describe('new message events', function() {
it('subscribes to the socket for new message events', function() {
describe('new message events', function () {
it('subscribes to the socket for new message events', function () {
expect(socket.on).to.be.calledWith('new-chat-message')
})
it('notifies an update event after new messages are received', function() {
it('notifies an update event after new messages are received', function () {
const subscriber = sinon.stub()
store.on('updated', subscriber)
mockSocketMessage(testMessage)
expect(subscriber).to.be.calledOnce
})
it('can unsubscribe from events', function() {
it('can unsubscribe from events', function () {
const subscriber = sinon.stub()
store.on('updated', subscriber)
store.off('updated', subscriber)
@@ -62,7 +62,7 @@ describe('ChatStore', function() {
expect(subscriber).not.to.be.called
})
it('when the message is from other user, it is added to the messages list', function() {
it('when the message is from other user, it is added to the messages list', function () {
mockSocketMessage({ ...testMessage, id: 'other_user_msg' })
expect(store.messages[store.messages.length - 1]).to.deep.equal({
id: 'other_user_msg',
@@ -72,12 +72,12 @@ describe('ChatStore', function() {
})
})
describe('messages sent by the user', function() {
beforeEach(function() {
describe('messages sent by the user', function () {
beforeEach(function () {
fetchMock.post(/messages/, 204)
})
it('are not added to the message list', async function() {
it('are not added to the message list', async function () {
await store.sendMessage(testMessage.content)
const originalMessageList = store.messages.slice(0)
mockSocketMessage(testMessage)
@@ -100,7 +100,7 @@ describe('ChatStore', function() {
})
})
it("don't notify an update event after new messages are received", async function() {
it("don't notify an update event after new messages are received", async function () {
await store.sendMessage(testMessage.content)
const subscriber = sinon.stub()
@@ -110,22 +110,22 @@ describe('ChatStore', function() {
expect(subscriber).not.to.be.called
})
it("have an 'id' property", async function() {
it("have an 'id' property", async function () {
await store.sendMessage(testMessage.content)
expect(typeof store.messages[0].id).to.equal('string')
})
})
})
describe('loadMoreMessages()', function() {
it('aborts the request when the entire message list is loaded', async function() {
describe('loadMoreMessages()', function () {
it('aborts the request when the entire message list is loaded', async function () {
store.atEnd = true
await store.loadMoreMessages()
expect(fetchMock.calls().length).to.equal(0)
expect(store.loading).to.equal(false)
})
it('updates the list of messages', async function() {
it('updates the list of messages', async function () {
const originalMessageList = store.messages.slice(0)
fetchMock.get(/messages/, [testMessage])
await store.loadMoreMessages()
@@ -138,7 +138,7 @@ describe('ChatStore', function() {
})
})
it('notifies an update event for when the loading starts, and a second one once data is available', async function() {
it('notifies an update event for when the loading starts, and a second one once data is available', async function () {
const subscriber = sinon.stub()
store.on('updated', subscriber)
fetchMock.get(/messages/, [testMessage])
@@ -146,14 +146,14 @@ describe('ChatStore', function() {
expect(subscriber).to.be.calledTwice
})
it('marks `atEnd` flag to true when there are no more messages to retrieve', async function() {
it('marks `atEnd` flag to true when there are no more messages to retrieve', async function () {
expect(store.atEnd).to.equal(false)
fetchMock.get(/messages/, [testMessage])
await store.loadMoreMessages()
expect(store.atEnd).to.equal(true)
})
it('marks `atEnd` flag to false when there are still messages to retrieve', async function() {
it('marks `atEnd` flag to false when there are still messages to retrieve', async function () {
const messages = []
for (let i = 0; i < MESSAGE_LIMIT; i++) {
messages.push({ ...testMessage, content: `message #${i}` })
@@ -164,7 +164,7 @@ describe('ChatStore', function() {
expect(store.atEnd).to.equal(false)
})
it('subsequent requests for new messages start at the timestamp of the latest message', async function() {
it('subsequent requests for new messages start at the timestamp of the latest message', async function () {
const messages = []
for (let i = 0; i < MESSAGE_LIMIT - 1; i++) {
// sending enough messages so it doesn't mark `atEnd === true`
@@ -186,12 +186,12 @@ describe('ChatStore', function() {
})
})
describe('sendMessage()', function() {
beforeEach(function() {
describe('sendMessage()', function () {
beforeEach(function () {
fetchMock.post(/messages/, 204)
})
it('appends the message to the list', async function() {
it('appends the message to the list', async function () {
const originalMessageList = store.messages.slice(0)
await store.sendMessage('a message')
expect(store.messages.length).to.equal(originalMessageList.length + 1)
@@ -201,14 +201,14 @@ describe('ChatStore', function() {
expect(lastMessage.timestamp).to.be.greaterThan(0)
})
it('notifies an update event', async function() {
it('notifies an update event', async function () {
const subscriber = sinon.stub()
store.on('updated', subscriber)
await store.sendMessage('a message')
expect(subscriber).to.be.calledOnce
})
it('sends an http POST request to the server', async function() {
it('sends an http POST request to the server', async function () {
await store.sendMessage('a message')
expect(fetchMock.calls().length).to.equal(1)
const body = fetchMock.lastCall()[1].body
@@ -218,7 +218,7 @@ describe('ChatStore', function() {
})
})
it('ignores empty messages', async function() {
it('ignores empty messages', async function () {
const subscriber = sinon.stub()
store.on('updated', subscriber)
await store.sendMessage('')
@@ -227,12 +227,12 @@ describe('ChatStore', function() {
})
})
describe('destroy', function() {
beforeEach(function() {
describe('destroy', function () {
beforeEach(function () {
fetchMock.post(/messages/, 204)
})
it('removes event listeners', async function() {
it('removes event listeners', async function () {
const subscriber = sinon.stub()
store.on('updated', subscriber)
store.destroy()
@@ -29,7 +29,7 @@ function createTestMessageList() {
]
}
describe('prependMessages()', function() {
describe('prependMessages()', function () {
function createTestMessages() {
const message1 = {
id: 'prepended_message',
@@ -41,7 +41,7 @@ describe('prependMessages()', function() {
return [message1, message2]
}
it('to an empty list', function() {
it('to an empty list', function () {
const messages = createTestMessages()
expect(prependMessages([], messages)).to.deep.equal([
{
@@ -53,16 +53,16 @@ describe('prependMessages()', function() {
])
})
describe('when the messages to prepend are from the same user', function() {
describe('when the messages to prepend are from the same user', function () {
let list, messages
beforeEach(function() {
beforeEach(function () {
list = createTestMessageList()
messages = createTestMessages()
messages[0].user = testUser // makes all the messages have the same author
})
it('when the prepended messages are close in time, contents should be merged into the same message', function() {
it('when the prepended messages are close in time, contents should be merged into the same message', function () {
const result = prependMessages(createTestMessageList(), messages)
expect(result.length).to.equal(list.length + 1)
expect(result[0]).to.deep.equal({
@@ -73,7 +73,7 @@ describe('prependMessages()', function() {
})
})
it('when the prepended messages are separated in time, each message is prepended', function() {
it('when the prepended messages are separated in time, each message is prepended', function () {
messages[0].timestamp = messages[1].timestamp - 6 * 60 * 1000 // 6 minutes before the next message
const result = prependMessages(createTestMessageList(), messages)
expect(result.length).to.equal(list.length + 2)
@@ -92,15 +92,15 @@ describe('prependMessages()', function() {
})
})
describe('when the messages to prepend are from different users', function() {
describe('when the messages to prepend are from different users', function () {
let list, messages
beforeEach(function() {
beforeEach(function () {
list = createTestMessageList()
messages = createTestMessages()
})
it('should prepend separate messages to the list', function() {
it('should prepend separate messages to the list', function () {
messages[0].user = otherUser
const result = prependMessages(createTestMessageList(), messages)
expect(result.length).to.equal(list.length + 2)
@@ -119,7 +119,7 @@ describe('prependMessages()', function() {
})
})
it('should merge the prepended messages into the first existing one when user is same user and are close in time', function() {
it('should merge the prepended messages into the first existing one when user is same user and are close in time', function () {
const list = createTestMessageList()
const messages = createTestMessages()
messages[0].user = messages[1].user = list[0].user
@@ -135,7 +135,7 @@ describe('prependMessages()', function() {
})
})
describe('appendMessage()', function() {
describe('appendMessage()', function () {
function createTestMessage() {
return {
id: 'appended_message',
@@ -145,7 +145,7 @@ describe('appendMessage()', function() {
}
}
it('to an empty list', function() {
it('to an empty list', function () {
const testMessage = createTestMessage()
expect(appendMessage([], testMessage)).to.deep.equal([
{
@@ -157,17 +157,17 @@ describe('appendMessage()', function() {
])
})
describe('messages appended shortly after the last message on the list', function() {
describe('messages appended shortly after the last message on the list', function () {
let list, message
beforeEach(function() {
beforeEach(function () {
list = createTestMessageList()
message = createTestMessage()
message.timestamp = list[1].timestamp + 6 * 1000 // 6 seconds after the last message in the list
})
describe('when the author is the same as the last message', function() {
it('should append the content to the last message', function() {
describe('when the author is the same as the last message', function () {
it('should append the content to the last message', function () {
const result = appendMessage(list, message)
expect(result.length).to.equal(list.length)
expect(result[1].contents).to.deep.equal(
@@ -175,18 +175,18 @@ describe('appendMessage()', function() {
)
})
it('should update the last message timestamp', function() {
it('should update the last message timestamp', function () {
const result = appendMessage(list, message)
expect(result[1].timestamp).to.equal(message.timestamp)
})
})
describe('when the author is different than the last message', function() {
beforeEach(function() {
describe('when the author is different than the last message', function () {
beforeEach(function () {
message.user = otherUser
})
it('should append the new message to the list', function() {
it('should append the new message to the list', function () {
const result = appendMessage(list, message)
expect(result.length).to.equal(list.length + 1)
expect(result[2]).to.deep.equal({
@@ -199,16 +199,16 @@ describe('appendMessage()', function() {
})
})
describe('messages appended later after the last message on the list', function() {
describe('messages appended later after the last message on the list', function () {
let list, message
beforeEach(function() {
beforeEach(function () {
list = createTestMessageList()
message = createTestMessage()
message.timestamp = list[1].timestamp + 6 * 60 * 1000 // 6 minutes after the last message in the list
})
it('when the author is the same as the last message, should be appended as new message', function() {
it('when the author is the same as the last message, should be appended as new message', function () {
const result = appendMessage(list, message)
expect(result.length).to.equal(3)
expect(result[2]).to.deep.equal({
@@ -219,7 +219,7 @@ describe('appendMessage()', function() {
})
})
it('when the author is the different than the last message, should be appended as new message', function() {
it('when the author is the different than the last message, should be appended as new message', function () {
message.user = otherUser
const result = appendMessage(list, message)
@@ -5,8 +5,8 @@ import CloneProjectModal from '../../../../../frontend/js/features/clone-project
import sinon from 'sinon'
import fetchMock from 'fetch-mock'
describe('<CloneProjectModal />', function() {
afterEach(function() {
describe('<CloneProjectModal />', function () {
afterEach(function () {
fetchMock.reset()
})
@@ -18,13 +18,13 @@ describe('<CloneProjectModal />', function() {
show: true
}
it('renders the translated modal title', async function() {
it('renders the translated modal title', async function () {
render(<CloneProjectModal {...modalProps} />)
await screen.findByText('Copy Project')
})
it('posts the generated project name', async function() {
it('posts the generated project name', async function () {
fetchMock.post(
'express:/project/:projectId/clone',
{
@@ -81,7 +81,7 @@ describe('<CloneProjectModal />', function() {
})
})
it('handles a generic error response', async function() {
it('handles a generic error response', async function () {
const matcher = 'express:/project/:projectId/clone'
fetchMock.postOnce(matcher, {
@@ -110,7 +110,7 @@ describe('<CloneProjectModal />', function() {
expect(cancelButton.disabled).to.be.false
})
it('handles a specific error response', async function() {
it('handles a specific error response', async function () {
const matcher = 'express:/project/:projectId/clone'
fetchMock.postOnce(matcher, {
@@ -9,19 +9,19 @@ import FileTreeCreateNameInput from '../../../../../../frontend/js/features/file
import FileTreeContext from '../../../../../../frontend/js/features/file-tree/components/file-tree-context'
import FileTreeCreateNameProvider from '../../../../../../frontend/js/features/file-tree/contexts/file-tree-create-name'
describe('<FileTreeCreateNameInput/>', function() {
describe('<FileTreeCreateNameInput/>', function () {
const sandbox = sinon.createSandbox()
beforeEach(function() {
beforeEach(function () {
sandbox.spy(window, 'requestAnimationFrame')
})
afterEach(function() {
afterEach(function () {
sandbox.restore()
cleanup()
})
it('renders an empty input', async function() {
it('renders an empty input', async function () {
render(
<FileTreeContext {...contextProps}>
<FileTreeCreateNameProvider>
@@ -34,7 +34,7 @@ describe('<FileTreeCreateNameInput/>', function() {
await screen.getByPlaceholderText('File Name')
})
it('renders a custom label and placeholder', async function() {
it('renders a custom label and placeholder', async function () {
render(
<FileTreeContext {...contextProps}>
<FileTreeCreateNameProvider>
@@ -50,7 +50,7 @@ describe('<FileTreeCreateNameInput/>', function() {
await screen.getByPlaceholderText('Enter a file name…')
})
it('uses an initial name', async function() {
it('uses an initial name', async function () {
render(
<FileTreeContext {...contextProps}>
<FileTreeCreateNameProvider initialName="test.tex">
@@ -63,7 +63,7 @@ describe('<FileTreeCreateNameInput/>', function() {
expect(input.value).to.equal('test.tex')
})
it('focuses the name', async function() {
it('focuses the name', async function () {
render(
<FileTreeContext {...contextProps}>
<FileTreeCreateNameProvider initialName="test.tex">
@@ -16,13 +16,13 @@ import FileTreeContext from '../../../../../../frontend/js/features/file-tree/co
import { useFileTreeActionable } from '../../../../../../frontend/js/features/file-tree/contexts/file-tree-actionable'
import { useFileTreeMutable } from '../../../../../../frontend/js/features/file-tree/contexts/file-tree-mutable'
describe('<FileTreeModalCreateFile/>', function() {
afterEach(function() {
describe('<FileTreeModalCreateFile/>', function () {
afterEach(function () {
fetchMock.restore()
cleanup()
})
it('handles invalid file names', async function() {
it('handles invalid file names', async function () {
render(
<FileTreeContext {...contextProps}>
<OpenWithMode mode="doc" />
@@ -56,7 +56,7 @@ describe('<FileTreeModalCreateFile/>', function() {
)
})
it('displays an error when the file limit is reached', async function() {
it('displays an error when the file limit is reached', async function () {
const rootFolder = [
{
docs: Array.from({ length: 10 }, (_, index) => ({
@@ -84,7 +84,7 @@ describe('<FileTreeModalCreateFile/>', function() {
)
})
it('displays a warning when the file limit is nearly reached', async function() {
it('displays a warning when the file limit is nearly reached', async function () {
const rootFolder = [
{
docs: Array.from({ length: 9 }, (_, index) => ({
@@ -108,7 +108,7 @@ describe('<FileTreeModalCreateFile/>', function() {
screen.getByText(/This project is approaching the file limit \(\d+\/\d+\)/)
})
it('counts files in nested folders', async function() {
it('counts files in nested folders', async function () {
const rootFolder = [
{
docs: [{ _id: 'entity-1' }],
@@ -150,7 +150,7 @@ describe('<FileTreeModalCreateFile/>', function() {
screen.getByText(/This project is approaching the file limit \(\d+\/\d+\)/)
})
it('creates a new file when the form is submitted', async function() {
it('creates a new file when the form is submitted', async function () {
fetchMock.post('express:/project/:projectId/doc', () => 204)
render(
@@ -173,7 +173,7 @@ describe('<FileTreeModalCreateFile/>', function() {
).to.be.true
})
it('imports a new file from a project', async function() {
it('imports a new file from a project', async function () {
fetchMock
.get('path:/user/projects', {
projects: [
@@ -289,7 +289,7 @@ describe('<FileTreeModalCreateFile/>', function() {
).to.be.true
})
it('import from a URL when the form is submitted', async function() {
it('import from a URL when the form is submitted', async function () {
fetchMock.post('express:/project/:projectId/linked_file', () => 204)
render(
@@ -331,7 +331,7 @@ describe('<FileTreeModalCreateFile/>', function() {
})
// eslint-disable-next-line mocha/no-skipped-tests
it.skip('uploads a new file', async function() {
it.skip('uploads a new file', async function () {
fetchMock.post('express:/project/:projectId/linked_file', () => 204)
render(
@@ -5,8 +5,8 @@ import renderWithContext from '../helpers/render-with-context'
import FileTreeDoc from '../../../../../frontend/js/features/file-tree/components/file-tree-doc'
describe('<FileTreeDoc/>', function() {
it('renders unselected', function() {
describe('<FileTreeDoc/>', function () {
it('renders unselected', function () {
const { container } = renderWithContext(
<FileTreeDoc name="foo.tex" id="123abc" isLinkedFile={false} />
)
@@ -15,7 +15,7 @@ describe('<FileTreeDoc/>', function() {
expect(container.querySelector('i.linked-file-highlight')).to.not.exist
})
it('renders selected', function() {
it('renders selected', function () {
renderWithContext(
<FileTreeDoc name="foo.tex" id="123abc" isLinkedFile={false} />,
{
@@ -42,7 +42,7 @@ describe('<FileTreeDoc/>', function() {
screen.getByRole('menuitem', { name: 'Upload' })
})
it('renders as linked file', function() {
it('renders as linked file', function () {
const { container } = renderWithContext(
<FileTreeDoc name="foo.tex" id="123abc" isLinkedFile />
)
@@ -51,7 +51,7 @@ describe('<FileTreeDoc/>', function() {
expect(container.querySelector('i.linked-file-highlight')).to.exist
})
it('selects', function() {
it('selects', function () {
renderWithContext(<FileTreeDoc name="foo.tex" id="123abc" expanded />, {
contextProps: {
rootFolder: [
@@ -70,7 +70,7 @@ describe('<FileTreeDoc/>', function() {
screen.getByRole('treeitem', { selected: true })
})
it('multi-selects', function() {
it('multi-selects', function () {
renderWithContext(<FileTreeDoc name="foo.tex" id="123abc" expanded />, {
contextProps: {
rootFolder: [
@@ -5,15 +5,15 @@ import renderWithContext from '../helpers/render-with-context'
import FileTreeFolderList from '../../../../../frontend/js/features/file-tree/components/file-tree-folder-list'
describe('<FileTreeFolderList/>', function() {
it('renders empty', function() {
describe('<FileTreeFolderList/>', function () {
it('renders empty', function () {
renderWithContext(<FileTreeFolderList folders={[]} docs={[]} files={[]} />)
screen.queryByRole('tree')
expect(screen.queryByRole('treeitem')).to.not.exist
})
it('renders docs, files and folders', function() {
it('renders docs, files and folders', function () {
const aFolder = {
_id: '456def',
name: 'A Folder',
@@ -33,8 +33,8 @@ describe('<FileTreeFolderList/>', function() {
screen.queryByRole('treeitem', { name: 'file.bib' })
})
describe('selection and multi-selection', function() {
it('without write permissions', function() {
describe('selection and multi-selection', function () {
it('without write permissions', function () {
const docs = [
{ _id: '1', name: '1.tex' },
{ _id: '2', name: '2.tex' }
@@ -69,7 +69,7 @@ describe('<FileTreeFolderList/>', function() {
screen.getByRole('treeitem', { name: '2.tex', selected: false })
})
it('with write permissions', function() {
it('with write permissions', function () {
const docs = [
{ _id: '1', name: '1.tex' },
{ _id: '2', name: '2.tex' },
@@ -5,12 +5,12 @@ import renderWithContext from '../helpers/render-with-context'
import FileTreeFolder from '../../../../../frontend/js/features/file-tree/components/file-tree-folder'
describe('<FileTreeFolder/>', function() {
beforeEach(function() {
describe('<FileTreeFolder/>', function () {
beforeEach(function () {
global.localStorage.clear()
})
it('renders unselected', function() {
it('renders unselected', function () {
renderWithContext(
<FileTreeFolder
name="foo"
@@ -25,7 +25,7 @@ describe('<FileTreeFolder/>', function() {
expect(screen.queryByRole('tree')).to.not.exist
})
it('renders selected', function() {
it('renders selected', function () {
renderWithContext(
<FileTreeFolder
name="foo"
@@ -61,7 +61,7 @@ describe('<FileTreeFolder/>', function() {
expect(screen.queryByRole('tree')).to.not.exist
})
it('expands', function() {
it('expands', function () {
renderWithContext(
<FileTreeFolder
name="foo"
@@ -90,7 +90,7 @@ describe('<FileTreeFolder/>', function() {
screen.getByRole('tree')
})
it('saves the expanded state for the next render', function() {
it('saves the expanded state for the next render', function () {
const { unmount } = renderWithContext(
<FileTreeFolder
name="foo"
@@ -6,20 +6,20 @@ import renderWithContext from '../../helpers/render-with-context'
import FileTreeitemInner from '../../../../../../frontend/js/features/file-tree/components/file-tree-item/file-tree-item-inner'
describe('<FileTreeitemInner />', function() {
describe('<FileTreeitemInner />', function () {
const setContextMenuCoords = sinon.stub()
beforeEach(function() {
beforeEach(function () {
global.requestAnimationFrame = sinon.stub()
})
afterEach(function() {
afterEach(function () {
setContextMenuCoords.reset()
delete global.requestAnimationFrame
})
describe('menu', function() {
it('does not display if file is not selected', function() {
describe('menu', function () {
it('does not display if file is not selected', function () {
renderWithContext(
<FileTreeitemInner id="123abc" name="bar.tex" isSelected={false} />,
{}
@@ -29,8 +29,8 @@ describe('<FileTreeitemInner />', function() {
})
})
describe('context menu', function() {
it('does not display without write permissions', function() {
describe('context menu', function () {
it('does not display without write permissions', function () {
renderWithContext(
<FileTreeitemInner id="123abc" name="bar.tex" isSelected />,
{ contextProps: { hasWritePermissions: false } }
@@ -39,7 +39,7 @@ describe('<FileTreeitemInner />', function() {
expect(screen.queryByRole('menu', { visible: false })).to.not.exist
})
it('open / close', function() {
it('open / close', function () {
const { container } = renderWithContext(
<FileTreeitemInner id="123abc" name="bar.tex" isSelected />
)
@@ -56,8 +56,8 @@ describe('<FileTreeitemInner />', function() {
})
})
describe('name', function() {
it('renders name', function() {
describe('name', function () {
it('renders name', function () {
renderWithContext(
<FileTreeitemInner id="123abc" name="bar.tex" isSelected />
)
@@ -66,7 +66,7 @@ describe('<FileTreeitemInner />', function() {
expect(screen.queryByRole('textbox')).to.not.exist
})
it('starts rename on menu item click', function() {
it('starts rename on menu item click', function () {
renderWithContext(
<FileTreeitemInner id="123abc" name="bar.tex" isSelected />,
{
@@ -5,14 +5,14 @@ import renderWithContext from '../../helpers/render-with-context'
import FileTreeitemMenu from '../../../../../../frontend/js/features/file-tree/components/file-tree-item/file-tree-item-menu'
describe('<FileTreeitemMenu />', function() {
describe('<FileTreeitemMenu />', function () {
const setContextMenuCoords = sinon.stub()
afterEach(function() {
afterEach(function () {
setContextMenuCoords.reset()
})
it('renders dropdown', function() {
it('renders dropdown', function () {
renderWithContext(
<FileTreeitemMenu
id="123abc"
@@ -24,7 +24,7 @@ describe('<FileTreeitemMenu />', function() {
screen.getByRole('menu')
})
it('open / close', function() {
it('open / close', function () {
renderWithContext(
<FileTreeitemMenu
id="123abc"
@@ -6,21 +6,21 @@ import renderWithContext from '../../helpers/render-with-context'
import FileTreeItemName from '../../../../../../frontend/js/features/file-tree/components/file-tree-item/file-tree-item-name'
describe('<FileTreeItemName />', function() {
describe('<FileTreeItemName />', function () {
const sandbox = sinon.createSandbox()
const setIsDraggable = sinon.stub()
beforeEach(function() {
beforeEach(function () {
sandbox.spy(window, 'requestAnimationFrame')
})
afterEach(function() {
afterEach(function () {
sandbox.restore()
setIsDraggable.reset()
cleanup()
})
it('renders name as button', function() {
it('renders name as button', function () {
renderWithContext(
<FileTreeItemName
name="foo.tex"
@@ -33,7 +33,7 @@ describe('<FileTreeItemName />', function() {
expect(screen.queryByRole('textbox')).to.not.exist
})
it("doesn't start renaming on unselected component", function() {
it("doesn't start renaming on unselected component", function () {
renderWithContext(
<FileTreeItemName
name="foo.tex"
@@ -49,7 +49,7 @@ describe('<FileTreeItemName />', function() {
expect(screen.queryByRole('textbox')).to.not.exist
})
it('start renaming on double-click', function() {
it('start renaming on double-click', function () {
renderWithContext(
<FileTreeItemName
name="foo.tex"
@@ -68,7 +68,7 @@ describe('<FileTreeItemName />', function() {
expect(setIsDraggable).to.be.calledWith(false)
})
it('cannot start renaming in read-only', function() {
it('cannot start renaming in read-only', function () {
renderWithContext(
<FileTreeItemName
name="foo.tex"
@@ -88,8 +88,8 @@ describe('<FileTreeItemName />', function() {
expect(screen.queryByRole('textbox')).to.not.exist
})
describe('stop renaming', function() {
beforeEach(function() {
describe('stop renaming', function () {
beforeEach(function () {
renderWithContext(
<FileTreeItemName
name="foo.tex"
@@ -107,7 +107,7 @@ describe('<FileTreeItemName />', function() {
fireEvent.change(input, { target: { value: 'bar.tex' } })
})
it('on Escape', function() {
it('on Escape', function () {
const input = screen.getByRole('textbox')
fireEvent.keyDown(input, { key: 'Escape' })
@@ -6,15 +6,15 @@ import fetchMock from 'fetch-mock'
import FileTreeRoot from '../../../../../frontend/js/features/file-tree/components/file-tree-root'
describe('<FileTreeRoot/>', function() {
describe('<FileTreeRoot/>', function () {
const onSelect = sinon.stub()
const onInit = sinon.stub()
beforeEach(function() {
beforeEach(function () {
global.requestAnimationFrame = sinon.stub()
})
afterEach(function() {
afterEach(function () {
delete global.requestAnimationFrame
fetchMock.restore()
onSelect.reset()
@@ -22,7 +22,7 @@ describe('<FileTreeRoot/>', function() {
global.localStorage.clear()
})
it('renders', function() {
it('renders', function () {
const rootFolder = [
{
_id: 'root-folder-id',
@@ -54,7 +54,7 @@ describe('<FileTreeRoot/>', function() {
expect(container.querySelector('.disconnected-overlay')).to.not.exist
})
it('renders with invalid selected doc in local storage', async function() {
it('renders with invalid selected doc in local storage', async function () {
global.localStorage.setItem(
'doc.open_id.123abc',
JSON.stringify('not-a-valid-id')
@@ -94,7 +94,7 @@ describe('<FileTreeRoot/>', function() {
await waitFor(() => screen.getByRole('button', { name: 'Cancel' }))
})
it('renders disconnected overlay', function() {
it('renders disconnected overlay', function () {
const rootFolder = [
{
_id: 'root-folder-id',
@@ -124,7 +124,7 @@ describe('<FileTreeRoot/>', function() {
expect(container.querySelector('.disconnected-overlay')).to.exist
})
it('fire onSelect', function() {
it('fire onSelect', function () {
const rootFolder = [
{
_id: 'root-folder-id',
@@ -177,7 +177,7 @@ describe('<FileTreeRoot/>', function() {
])
})
it('listen to editor.openDoc', function() {
it('listen to editor.openDoc', function () {
const rootFolder = [
{
_id: 'root-folder-id',
@@ -5,12 +5,12 @@ import renderWithContext from '../helpers/render-with-context'
import FileTreeToolbar from '../../../../../frontend/js/features/file-tree/components/file-tree-toolbar'
describe('<FileTreeToolbar/>', function() {
beforeEach(function() {
describe('<FileTreeToolbar/>', function () {
beforeEach(function () {
global.localStorage.clear()
})
it('without selected files', function() {
it('without selected files', function () {
renderWithContext(<FileTreeToolbar />)
screen.getByRole('button', { name: 'New File' })
@@ -20,7 +20,7 @@ describe('<FileTreeToolbar/>', function() {
expect(screen.queryByRole('button', { name: 'Delete' })).to.not.exist
})
it('read-only', function() {
it('read-only', function () {
renderWithContext(<FileTreeToolbar />, {
contextProps: { hasWritePermissions: false }
})
@@ -28,7 +28,7 @@ describe('<FileTreeToolbar/>', function() {
expect(screen.queryByRole('button')).to.not.exist
})
it('with one selected file', function() {
it('with one selected file', function () {
renderWithContext(<FileTreeToolbar />, {
contextProps: {
rootDocId: '456def',
@@ -5,11 +5,11 @@ import { screen, render, fireEvent } from '@testing-library/react'
import FileTreeRoot from '../../../../../frontend/js/features/file-tree/components/file-tree-root'
describe('FileTree Context Menu Flow', function() {
describe('FileTree Context Menu Flow', function () {
const onSelect = sinon.stub()
const onInit = sinon.stub()
it('opens on contextMenu event', async function() {
it('opens on contextMenu event', async function () {
const rootFolder = [
{
_id: 'root-folder-id',
@@ -43,7 +43,7 @@ describe('FileTree Context Menu Flow', function() {
expect(screen.getAllByRole('menu').length).to.equal(2) // toolbar + menu
})
it("doesn't open in read only mode", async function() {
it("doesn't open in read only mode", async function () {
const rootFolder = [
{
_id: 'root-folder-id',
@@ -7,18 +7,18 @@ import MockedSocket from 'socket.io-mock'
import FileTreeRoot from '../../../../../frontend/js/features/file-tree/components/file-tree-root'
describe('FileTree Create Folder Flow', function() {
describe('FileTree Create Folder Flow', function () {
const onSelect = sinon.stub()
const onInit = sinon.stub()
beforeEach(function() {
beforeEach(function () {
global.requestAnimationFrame = sinon.stub()
window._ide = {
socket: new MockedSocket()
}
})
afterEach(function() {
afterEach(function () {
delete global.requestAnimationFrame
fetchMock.restore()
onSelect.reset()
@@ -26,7 +26,7 @@ describe('FileTree Create Folder Flow', function() {
delete window._ide
})
it('add to root when no files are selected', async function() {
it('add to root when no files are selected', async function () {
const rootFolder = [
{
_id: 'root-folder-id',
@@ -78,7 +78,7 @@ describe('FileTree Create Folder Flow', function() {
await screen.findByRole('treeitem', { name: newFolderName })
})
it('add to folder from folder', async function() {
it('add to folder from folder', async function () {
const rootFolder = [
{
_id: 'root-folder-id',
@@ -148,7 +148,7 @@ describe('FileTree Create Folder Flow', function() {
expect(screen.queryByRole('treeitem', { name: newFolderName })).to.not.exist
})
it('add to folder from child', async function() {
it('add to folder from child', async function () {
const rootFolder = [
{
_id: 'root-folder-id',
@@ -215,7 +215,7 @@ describe('FileTree Create Folder Flow', function() {
expect(screen.queryByRole('treeitem', { name: newFolderName })).to.not.exist
})
it('prevents adding duplicate or invalid names', async function() {
it('prevents adding duplicate or invalid names', async function () {
const rootFolder = [
{
_id: 'root-folder-id',
@@ -278,9 +278,7 @@ describe('FileTree Create Folder Flow', function() {
}
function fakeId() {
return Math.random()
.toString(16)
.replace(/0\./, 'random-test-id-')
return Math.random().toString(16).replace(/0\./, 'random-test-id-')
}
async function getModalCreateButton() {
@@ -7,25 +7,25 @@ import MockedSocket from 'socket.io-mock'
import FileTreeRoot from '../../../../../frontend/js/features/file-tree/components/file-tree-root'
describe('FileTree Delete Entity Flow', function() {
describe('FileTree Delete Entity Flow', function () {
const onSelect = sinon.stub()
const onInit = sinon.stub()
beforeEach(function() {
beforeEach(function () {
window._ide = {
socket: new MockedSocket()
}
})
afterEach(function() {
afterEach(function () {
fetchMock.restore()
onSelect.reset()
onInit.reset()
delete window._ide
})
describe('single entity', function() {
beforeEach(function() {
describe('single entity', function () {
beforeEach(function () {
const rootFolder = [
{
_id: 'root-folder-id',
@@ -57,7 +57,7 @@ describe('FileTree Delete Entity Flow', function() {
fireEvent.click(deleteButton)
})
it('removes item', async function() {
it('removes item', async function () {
const fetchMatcher = /\/project\/\w+\/doc\/\w+/
fetchMock.delete(fetchMatcher, 204)
@@ -88,7 +88,7 @@ describe('FileTree Delete Entity Flow', function() {
expect(lastFetchPath).to.equal('/project/123abc/doc/456def')
})
it('continues delete on 404s', async function() {
it('continues delete on 404s', async function () {
fetchMock.delete(/\/project\/\w+\/doc\/\w+/, 404)
const modalDeleteButton = await getModalDeleteButton()
@@ -119,7 +119,7 @@ describe('FileTree Delete Entity Flow', function() {
})
})
it('aborts delete on error', async function() {
it('aborts delete on error', async function () {
const fetchMatcher = /\/project\/\w+\/doc\/\w+/
fetchMock.delete(fetchMatcher, 500)
@@ -131,8 +131,8 @@ describe('FileTree Delete Entity Flow', function() {
})
})
describe('folders', function() {
beforeEach(function() {
describe('folders', function () {
beforeEach(function () {
const rootFolder = [
{
docs: [{ _id: '456def', name: 'main.tex' }],
@@ -174,15 +174,15 @@ describe('FileTree Delete Entity Flow', function() {
window._ide.socket.socketClient.emit('removeEntity', '123abc')
})
it('removes the folder', function() {
it('removes the folder', function () {
expect(screen.queryByRole('treeitem', { name: 'folder' })).to.not.exist
})
it('leaves the main file selected', function() {
it('leaves the main file selected', function () {
screen.getByRole('treeitem', { name: 'main.tex', selected: true })
})
it('unselect the child entity', async function() {
it('unselect the child entity', async function () {
// as a proxy to check that the child entity has been unselect we start
// a delete and ensure the modal is displayed (the cancel button can be
// selected) This is needed to make sure the test fail.
@@ -192,8 +192,8 @@ describe('FileTree Delete Entity Flow', function() {
})
})
describe('multiple entities', function() {
beforeEach(function() {
describe('multiple entities', function () {
beforeEach(function () {
const rootFolder = [
{
_id: 'root-folder-id',
@@ -229,7 +229,7 @@ describe('FileTree Delete Entity Flow', function() {
fireEvent.click(deleteButton)
})
it('removes all items', async function() {
it('removes all items', async function () {
const fetchMatcher = /\/project\/\w+\/(doc|file)\/\w+/
fetchMock.delete(fetchMatcher, 204)
@@ -7,18 +7,18 @@ import MockedSocket from 'socket.io-mock'
import FileTreeRoot from '../../../../../frontend/js/features/file-tree/components/file-tree-root'
describe('FileTree Rename Entity Flow', function() {
describe('FileTree Rename Entity Flow', function () {
const onSelect = sinon.stub()
const onInit = sinon.stub()
beforeEach(function() {
beforeEach(function () {
window._ide = {
socket: new MockedSocket()
}
global.requestAnimationFrame = sinon.stub()
})
afterEach(function() {
afterEach(function () {
delete global.requestAnimationFrame
fetchMock.restore()
onSelect.reset()
@@ -26,7 +26,7 @@ describe('FileTree Rename Entity Flow', function() {
delete window._ide
})
beforeEach(function() {
beforeEach(function () {
const rootFolder = [
{
_id: 'root-folder-id',
@@ -63,7 +63,7 @@ describe('FileTree Rename Entity Flow', function() {
)
})
it('renames doc', function() {
it('renames doc', function () {
const fetchMatcher = /\/project\/\w+\/doc\/\w+\/rename/
fetchMock.post(fetchMatcher, 204)
@@ -77,7 +77,7 @@ describe('FileTree Rename Entity Flow', function() {
expect(lastFetchBody.name).to.equal('b.tex')
})
it('renames folder', function() {
it('renames folder', function () {
const fetchMatcher = /\/project\/\w+\/folder\/\w+\/rename/
fetchMock.post(fetchMatcher, 204)
@@ -91,7 +91,7 @@ describe('FileTree Rename Entity Flow', function() {
expect(lastFetchBody.name).to.equal('new folder name')
})
it('renames file in subfolder', function() {
it('renames file in subfolder', function () {
const fetchMatcher = /\/project\/\w+\/file\/\w+\/rename/
fetchMock.post(fetchMatcher, 204)
@@ -109,7 +109,7 @@ describe('FileTree Rename Entity Flow', function() {
expect(lastFetchBody.name).to.equal('d.tex')
})
it('reverts rename on error', async function() {
it('reverts rename on error', async function () {
const fetchMatcher = /\/project\/\w+\/doc\/\w+\/rename/
fetchMock.post(fetchMatcher, 500)
@@ -120,7 +120,7 @@ describe('FileTree Rename Entity Flow', function() {
screen.getByRole('treeitem', { name: 'b.tex' })
})
it('shows error modal on invalid filename', async function() {
it('shows error modal on invalid filename', async function () {
const input = initItemRename('a.tex')
fireEvent.change(input, { target: { value: '///' } })
fireEvent.keyDown(input, { key: 'Enter' })
@@ -131,7 +131,7 @@ describe('FileTree Rename Entity Flow', function() {
})
})
it('shows error modal on duplicate filename', async function() {
it('shows error modal on duplicate filename', async function () {
const input = initItemRename('a.tex')
fireEvent.change(input, { target: { value: 'folder' } })
fireEvent.keyDown(input, { key: 'Enter' })
@@ -142,7 +142,7 @@ describe('FileTree Rename Entity Flow', function() {
})
})
it('shows error modal on duplicate filename in subfolder', async function() {
it('shows error modal on duplicate filename in subfolder', async function () {
const expandButton = screen.queryByRole('button', { name: 'Expand' })
if (expandButton) fireEvent.click(expandButton)
@@ -156,7 +156,7 @@ describe('FileTree Rename Entity Flow', function() {
})
})
it('shows error modal on blocked filename', async function() {
it('shows error modal on blocked filename', async function () {
const input = initItemRename('a.tex')
fireEvent.change(input, { target: { value: 'prototype' } })
fireEvent.keyDown(input, { key: 'Enter' })
@@ -167,8 +167,8 @@ describe('FileTree Rename Entity Flow', function() {
})
})
describe('via socket event', function() {
it('renames doc', function() {
describe('via socket event', function () {
it('renames doc', function () {
screen.getByRole('treeitem', { name: 'a.tex' })
window._ide.socket.socketClient.emit(
@@ -2,8 +2,8 @@ import { expect } from 'chai'
import iconTypeFromName from '../../../../../frontend/js/features/file-tree/util/icon-type-from-name'
describe('iconTypeFromName', function() {
it('returns correct icon type', function() {
describe('iconTypeFromName', function () {
it('returns correct icon type', function () {
expect(iconTypeFromName('main.tex')).to.equal('file')
expect(iconTypeFromName('main.png')).to.equal('image')
expect(iconTypeFromName('main.csv')).to.equal('table')
@@ -11,11 +11,11 @@ describe('iconTypeFromName', function() {
expect(iconTypeFromName('main.bib')).to.equal('book')
})
it('handles missing extensions', function() {
it('handles missing extensions', function () {
expect(iconTypeFromName('main')).to.equal('file')
})
it('lowercases extension', function() {
it('lowercases extension', function () {
expect(iconTypeFromName('ZOTERO.BIB')).to.equal('book')
})
})
@@ -10,8 +10,8 @@ const modalProps = {
trackChangesVisible: false
}
describe('<HotkeysModal />', function() {
it('renders the translated modal title', async function() {
describe('<HotkeysModal />', function () {
it('renders the translated modal title', async function () {
const { baseElement } = render(<HotkeysModal {...modalProps} />)
expect(baseElement.querySelector('.modal-title').textContent).to.equal(
@@ -19,14 +19,14 @@ describe('<HotkeysModal />', function() {
)
})
it('renders translated heading with embedded code', function() {
it('renders translated heading with embedded code', function () {
const { baseElement } = render(<HotkeysModal {...modalProps} />)
const results = baseElement.querySelectorAll('h3 code')
expect(results).to.have.length(1)
})
it('renders the hotkey descriptions', function() {
it('renders the hotkey descriptions', function () {
const { baseElement } = render(<HotkeysModal {...modalProps} />)
const hotkeys = baseElement.querySelectorAll(
@@ -35,7 +35,7 @@ describe('<HotkeysModal />', function() {
expect(hotkeys).to.have.length(19)
})
it('adds extra hotkey descriptions when Track Changes is enabled', function() {
it('adds extra hotkey descriptions when Track Changes is enabled', function () {
const { baseElement } = render(
<HotkeysModal {...modalProps} trackChangesVisible />
)
@@ -46,14 +46,14 @@ describe('<HotkeysModal />', function() {
expect(hotkeys).to.have.length(22)
})
it('uses Ctrl for non-macOS', function() {
it('uses Ctrl for non-macOS', function () {
render(<HotkeysModal {...modalProps} />)
expect(screen.getAllByText(/Ctrl/)).to.have.length(16)
expect(screen.queryByText(/Cmd/)).to.not.exist
})
it('uses Cmd for macOS', function() {
it('uses Cmd for macOS', function () {
render(<HotkeysModal {...modalProps} isMac />)
expect(screen.getAllByText(/Cmd/)).to.have.length(16)
@@ -5,14 +5,14 @@ import { screen, render, fireEvent } from '@testing-library/react'
import OutlineItem from '../../../../../frontend/js/features/outline/components/outline-item'
describe('<OutlineItem />', function() {
describe('<OutlineItem />', function () {
const jumpToLine = sinon.stub()
afterEach(function() {
afterEach(function () {
jumpToLine.reset()
})
it('renders basic item', function() {
it('renders basic item', function () {
const outlineItem = {
title: 'Test Title',
line: 1
@@ -24,7 +24,7 @@ describe('<OutlineItem />', function() {
expect(screen.queryByRole('button', { name: 'Collapse' })).to.not.exist
})
it('collapses and expands', function() {
it('collapses and expands', function () {
const outlineItem = {
title: 'Parent',
line: 1,
@@ -44,7 +44,7 @@ describe('<OutlineItem />', function() {
expect(screen.queryByRole('button', { name: 'Child' })).to.not.exist
})
it('highlights', function() {
it('highlights', function () {
const outlineItem = {
title: 'Parent',
line: 1
@@ -61,7 +61,7 @@ describe('<OutlineItem />', function() {
screen.getByRole('treeitem', { current: true })
})
it('highlights when has collapsed highlighted child', function() {
it('highlights when has collapsed highlighted child', function () {
const outlineItem = {
title: 'Parent',
line: 1,
@@ -83,7 +83,7 @@ describe('<OutlineItem />', function() {
screen.getByRole('treeitem', { name: 'Parent', current: true })
})
it('click and double-click jump to location', function() {
it('click and double-click jump to location', function () {
const outlineItem = {
title: 'Parent',
line: 1
@@ -3,10 +3,10 @@ import { screen, render } from '@testing-library/react'
import OutlineList from '../../../../../frontend/js/features/outline/components/outline-list'
describe('<OutlineList />', function() {
describe('<OutlineList />', function () {
const jumpToLine = () => {}
it('renders items', function() {
it('renders items', function () {
const outline = [
{
title: 'Section 1',
@@ -25,7 +25,7 @@ describe('<OutlineList />', function() {
screen.getByRole('treeitem', { name: 'Section 2' })
})
it('renders as root', function() {
it('renders as root', function () {
const outline = [
{
title: 'Section',
@@ -38,7 +38,7 @@ describe('<OutlineList />', function() {
screen.getByRole('tree')
})
it('renders as non-root', function() {
it('renders as non-root', function () {
const outline = [
{
title: 'Section',
@@ -6,7 +6,7 @@ import { screen, fireEvent } from '@testing-library/react'
import OutlinePane from '../../../../../frontend/js/features/outline/components/outline-pane'
import { renderWithEditorContext } from '../../../helpers/render-with-context'
describe('<OutlinePane />', function() {
describe('<OutlinePane />', function () {
const jumpToLine = () => {}
const onToggle = sinon.stub()
const eventTracking = { sendMB: sinon.stub() }
@@ -16,7 +16,7 @@ describe('<OutlinePane />', function() {
}
let originalLocalStorage
before(function() {
before(function () {
originalLocalStorage = global.localStorage
Object.defineProperty(global, 'localStorage', {
@@ -27,20 +27,20 @@ describe('<OutlinePane />', function() {
})
})
afterEach(function() {
afterEach(function () {
onToggle.reset()
eventTracking.sendMB.reset()
global.localStorage.getItem.resetHistory()
global.localStorage.setItem.resetHistory()
})
after(function() {
after(function () {
Object.defineProperty(global, 'localStorage', {
value: originalLocalStorage
})
})
it('renders expanded outline', function() {
it('renders expanded outline', function () {
const outline = [
{
title: 'Section',
@@ -61,7 +61,7 @@ describe('<OutlinePane />', function() {
screen.getByRole('tree')
})
it('renders disabled outline', function() {
it('renders disabled outline', function () {
const outline = []
render(
<OutlinePane
@@ -76,7 +76,7 @@ describe('<OutlinePane />', function() {
expect(screen.queryByRole('tree')).to.be.null
})
it('expand outline and use local storage', function() {
it('expand outline and use local storage', function () {
global.localStorage.getItem.returns(false)
const outline = [
{
@@ -4,10 +4,10 @@ import { screen, render } from '@testing-library/react'
import OutlineRoot from '../../../../../frontend/js/features/outline/components/outline-root'
describe('<OutlineRoot />', function() {
describe('<OutlineRoot />', function () {
const jumpToLine = () => {}
it('renders outline', function() {
it('renders outline', function () {
const outline = [
{
title: 'Section',
@@ -21,7 +21,7 @@ describe('<OutlineRoot />', function() {
expect(screen.queryByRole('link')).to.be.null
})
it('renders placeholder', function() {
it('renders placeholder', function () {
const outline = []
render(<OutlineRoot outline={outline} jumpToLine={jumpToLine} />)
@@ -5,9 +5,9 @@ import {
nestOutline
} from '../../../../frontend/js/features/outline/outline-parser'
describe('OutlineParser', function() {
describe('matchOutline', function() {
it('matches all levels', function() {
describe('OutlineParser', function () {
describe('matchOutline', function () {
it('matches all levels', function () {
const content = `
\\book{Book}
\\part{Part}
@@ -41,7 +41,7 @@ describe('OutlineParser', function() {
])
})
it('matches display titles', function() {
it('matches display titles', function () {
const content = `
\\section{\\label{foo} Label before}
\\section{Label after \\label{foo}}
@@ -59,7 +59,7 @@ describe('OutlineParser', function() {
])
})
it('removes spurious commands after title definition', function() {
it('removes spurious commands after title definition', function () {
const content = `
\\section{Plain title} more text \\href{link}{link}
\\section{\\label{foo} Label before} more text \\href{link}{link}
@@ -71,24 +71,24 @@ describe('OutlineParser', function() {
])
})
it('matches empty sections', function() {
it('matches empty sections', function () {
const outline = matchOutline('\\section{}')
expect(outline).to.deep.equal([{ line: 1, title: '', level: 40 }])
})
it('matches indented sections', function() {
it('matches indented sections', function () {
const outline = matchOutline('\t\\section{Indented}')
expect(outline).to.deep.equal([{ line: 1, title: 'Indented', level: 40 }])
})
it('matches unnumbered sections', function() {
it('matches unnumbered sections', function () {
const outline = matchOutline('\\section*{Unnumbered}')
expect(outline).to.deep.equal([
{ line: 1, title: 'Unnumbered', level: 40 }
])
})
it('matches short titles', function() {
it('matches short titles', function () {
const outline = matchOutline(
'\\chapter[Short Title For TOC]{Very Long Title for Text}'
)
@@ -97,7 +97,7 @@ describe('OutlineParser', function() {
])
})
it('handles spacing', function() {
it('handles spacing', function () {
const content = `
\\section {Weird Spacing}
\\section * {Weird Spacing Unnumbered}
@@ -111,7 +111,7 @@ describe('OutlineParser', function() {
])
})
it("doesn't match commented lines", function() {
it("doesn't match commented lines", function () {
const content = `
% \\section{I should not appear in the outline}
`
@@ -119,7 +119,7 @@ describe('OutlineParser', function() {
expect(outline).to.deep.equal([])
})
it("doesn't match inline sections", function() {
it("doesn't match inline sections", function () {
const content = `
I like to write \\section{inline} on one line.
`
@@ -128,8 +128,8 @@ describe('OutlineParser', function() {
})
})
describe('nestOutline', function() {
it('matches all levels', function() {
describe('nestOutline', function () {
it('matches all levels', function () {
const flatOutline = [
{ line: 10, title: 'Book', level: 10 },
{ line: 20, title: 'Part A', level: 20 },
@@ -4,7 +4,7 @@ import { screen, render } from '@testing-library/react'
import PreviewDownloadButton from '../../../../../frontend/js/features/preview/components/preview-download-button'
describe('<PreviewDownloadButton />', function() {
describe('<PreviewDownloadButton />', function () {
const projectId = 'projectId123'
const pdfDownloadUrl = `/download/project/${projectId}/build/17523aaafdf-1ad9063af140f004/output/output.pdf?compileGroup=priority&popupDownload=true`
@@ -26,17 +26,14 @@ describe('<PreviewDownloadButton />', function() {
)
}
it('should disable the button and dropdown toggle when compiling', function() {
it('should disable the button and dropdown toggle when compiling', function () {
const isCompiling = true
const outputFiles = undefined
renderPreviewDownloadButton(isCompiling, outputFiles)
expect(
screen
.getByText('Download PDF')
.closest('a')
.getAttribute('disabled')
screen.getByText('Download PDF').closest('a').getAttribute('disabled')
).to.exist
const buttons = screen.getAllByRole('button')
expect(buttons.length).to.equal(1) // the dropdown toggle
@@ -45,35 +42,26 @@ describe('<PreviewDownloadButton />', function() {
'Toggle output files list'
)
})
it('should disable the PDF button when there is no PDF', function() {
it('should disable the PDF button when there is no PDF', function () {
const isCompiling = false
const outputFiles = []
renderPreviewDownloadButton(isCompiling, outputFiles)
expect(
screen
.getByText('Download PDF')
.closest('a')
.getAttribute('disabled')
screen.getByText('Download PDF').closest('a').getAttribute('disabled')
).to.exist
})
it('should enable the PDF button when there is a main PDF', function() {
it('should enable the PDF button when there is a main PDF', function () {
const isCompiling = false
const outputFiles = []
renderPreviewDownloadButton(isCompiling, outputFiles, pdfDownloadUrl)
expect(
screen
.getByText('Download PDF')
.closest('a')
.getAttribute('href')
screen.getByText('Download PDF').closest('a').getAttribute('href')
).to.equal(pdfDownloadUrl)
expect(
screen
.getByText('Download PDF')
.closest('a')
.getAttribute('disabled')
screen.getByText('Download PDF').closest('a').getAttribute('disabled')
).to.not.exist
})
it('should enable the dropdown when not compiling', function() {
it('should enable the dropdown when not compiling', function () {
const isCompiling = false
const outputFiles = []
renderPreviewDownloadButton(isCompiling, outputFiles, pdfDownloadUrl)
@@ -82,13 +70,13 @@ describe('<PreviewDownloadButton />', function() {
expect(buttons[0].getAttribute('disabled')).to.not.exist
})
it('should show the button text when prop showText=true', function() {
it('should show the button text when prop showText=true', function () {
const isCompiling = false
const showText = true
renderPreviewDownloadButton(isCompiling, [], pdfDownloadUrl, showText)
expect(screen.getByText('Download PDF').getAttribute('style')).to.be.null
})
it('should not show the button text when prop showText=false', function() {
it('should not show the button text when prop showText=false', function () {
const isCompiling = false
const showText = false
renderPreviewDownloadButton(isCompiling, [], pdfDownloadUrl, showText)
@@ -6,7 +6,7 @@ import PreviewDownloadFileList, {
topFileTypes
} from '../../../../../frontend/js/features/preview/components/preview-download-file-list'
describe('<PreviewDownloadFileList />', function() {
describe('<PreviewDownloadFileList />', function () {
const projectId = 'projectId123'
function makeFile(fileName, main) {
@@ -18,7 +18,7 @@ describe('<PreviewDownloadFileList />', function() {
}
}
it('should list all output files and group them', function() {
it('should list all output files and group them', function () {
const outputFiles = [
makeFile('output.ind'),
makeFile('output.log'),
@@ -55,15 +55,12 @@ describe('<PreviewDownloadFileList />', function() {
.map(file => file.type)
const topMenuItems = menuItems.slice(0, outputTopFileTypes.length)
topMenuItems.forEach(item => {
const fileType = item.textContent
.split('.')
.pop()
.replace(' file', '')
const fileType = item.textContent.split('.').pop().replace(' file', '')
expect(topFileTypes.includes(fileType)).to.be.true
})
})
it('should list all files when there are duplicate types', function() {
it('should list all files when there are duplicate types', function () {
const pdfFile = makeFile('output.pdf', true)
const bblFile = makeFile('output.bbl')
const outputFiles = [Object.assign({}, { ...bblFile }), bblFile, pdfFile]
@@ -76,7 +73,7 @@ describe('<PreviewDownloadFileList />', function() {
expect(bblMenuItems.length).to.equal(2)
})
it('should list the non-main PDF in the dropdown', function() {
it('should list the non-main PDF in the dropdown', function () {
const pdfFile = makeFile('output.pdf', true)
const pdfAltFile = makeFile('alt.pdf')
const outputFiles = [pdfFile, pdfAltFile]
@@ -84,8 +81,8 @@ describe('<PreviewDownloadFileList />', function() {
screen.getAllByRole('menuitem', { name: 'alt.pdf' })
})
describe('list divider and header', function() {
it('should display when there are top files and other files', function() {
describe('list divider and header', function () {
it('should display when there are top files and other files', function () {
const outputFiles = [
makeFile('output.bbl'),
makeFile('output.ind'),
@@ -99,7 +96,7 @@ describe('<PreviewDownloadFileList />', function() {
screen.getByRole('separator')
})
it('should not display when there are top files and no other files', function() {
it('should not display when there are top files and no other files', function () {
const outputFiles = [
makeFile('output.bbl'),
makeFile('output.ind'),
@@ -112,7 +109,7 @@ describe('<PreviewDownloadFileList />', function() {
expect(screen.queryByRole('separator')).to.not.exist
})
it('should not display when there are other files and no top files', function() {
it('should not display when there are other files and no top files', function () {
const outputFiles = [makeFile('output.log')]
render(<PreviewDownloadFileList fileList={outputFiles} />)
@@ -5,10 +5,10 @@ import { screen, render, fireEvent } from '@testing-library/react'
import PreviewLogsPaneEntry from '../../../../../frontend/js/features/preview/components/preview-logs-pane-entry.js'
describe('<PreviewLogsPaneEntry />', function() {
describe('<PreviewLogsPaneEntry />', function () {
const level = 'error'
it('renders a configurable aria-label', function() {
it('renders a configurable aria-label', function () {
const sampleAriaLabel = 'lorem ipsum dolor sit amet'
render(
<PreviewLogsPaneEntry entryAriaLabel={sampleAriaLabel} level={level} />
@@ -16,17 +16,17 @@ describe('<PreviewLogsPaneEntry />', function() {
screen.getByLabelText(sampleAriaLabel)
})
describe('logs pane source location link', function() {
describe('logs pane source location link', function () {
const file = 'foo.tex'
const line = 42
const column = 21
const onSourceLocationClick = sinon.stub()
afterEach(function() {
afterEach(function () {
onSourceLocationClick.reset()
})
it('renders both file and line', function() {
it('renders both file and line', function () {
render(
<PreviewLogsPaneEntry sourceLocation={{ file, line }} level={level} />
)
@@ -35,14 +35,14 @@ describe('<PreviewLogsPaneEntry />', function() {
})
})
it('renders only file when line information is not available', function() {
it('renders only file when line information is not available', function () {
render(<PreviewLogsPaneEntry sourceLocation={{ file }} level={level} />)
screen.getByRole('button', {
name: `Navigate to log position in source code: ${file}`
})
})
it('does not render when file information is not available', function() {
it('does not render when file information is not available', function () {
render(<PreviewLogsPaneEntry level={level} />)
expect(
screen.queryByRole('button', {
@@ -51,7 +51,7 @@ describe('<PreviewLogsPaneEntry />', function() {
).to.not.exist
})
it('calls the callback with file, line and column on click', function() {
it('calls the callback with file, line and column on click', function () {
render(
<PreviewLogsPaneEntry
sourceLocation={{ file, line, column }}
@@ -73,7 +73,7 @@ describe('<PreviewLogsPaneEntry />', function() {
})
})
describe('logs pane entry raw contents', function() {
describe('logs pane entry raw contents', function () {
const rawContent = 'foo bar latex error stuff baz'
// JSDom doesn't compute layout/sizing, so we need to simulate sizing for the elements
@@ -88,7 +88,7 @@ describe('<PreviewLogsPaneEntry />', function() {
'offsetWidth'
)
beforeEach(function() {
beforeEach(function () {
Object.defineProperty(HTMLElement.prototype, 'scrollHeight', {
configurable: true,
value: 500
@@ -99,7 +99,7 @@ describe('<PreviewLogsPaneEntry />', function() {
})
})
afterEach(function() {
afterEach(function () {
Object.defineProperty(
HTMLElement.prototype,
'scrollHeight',
@@ -112,7 +112,7 @@ describe('<PreviewLogsPaneEntry />', function() {
)
})
it('renders collapsed contents by default', function() {
it('renders collapsed contents by default', function () {
render(<PreviewLogsPaneEntry rawContent={rawContent} level={level} />)
screen.getByText(rawContent)
screen.getByRole('button', {
@@ -120,7 +120,7 @@ describe('<PreviewLogsPaneEntry />', function() {
})
})
it('supports expanding contents', function() {
it('supports expanding contents', function () {
render(<PreviewLogsPaneEntry rawContent={rawContent} level={level} />)
screen.getByText(rawContent)
const expandCollapseBtn = screen.getByRole('button', {
@@ -132,19 +132,19 @@ describe('<PreviewLogsPaneEntry />', function() {
})
})
it('should not render at all when there are no log contents', function() {
it('should not render at all when there are no log contents', function () {
const { container } = render(<PreviewLogsPaneEntry level={level} />)
expect(container.querySelector('.log-entry-content')).to.not.exist
})
})
describe('formatted content', function() {
describe('formatted content', function () {
const rawContent = 'foo bar latex error stuff baz'
const formattedContentText = 'foo bar baz'
const formattedContent = <>{formattedContentText}</>
const infoURL = 'www.overleaf.com/learn/latex'
it('renders the hint', function() {
it('renders the hint', function () {
render(
<PreviewLogsPaneEntry
rawContent={rawContent}
@@ -156,7 +156,7 @@ describe('<PreviewLogsPaneEntry />', function() {
screen.getByText(formattedContentText)
})
it('renders the link to learn more', function() {
it('renders the link to learn more', function () {
render(
<PreviewLogsPaneEntry
rawContent={rawContent}
@@ -168,7 +168,7 @@ describe('<PreviewLogsPaneEntry />', function() {
screen.getByRole('link', { name: 'Learn more' })
})
it('does not render the link when it is not available', function() {
it('does not render the link when it is not available', function () {
render(
<PreviewLogsPaneEntry
rawContent={rawContent}
@@ -6,7 +6,7 @@ import { renderWithEditorContext } from '../../../helpers/render-with-context'
const { expect } = require('chai')
describe('<PreviewLogsPane />', function() {
describe('<PreviewLogsPane />', function () {
const sampleError1 = {
content: 'error 1 content',
file: 'main.tex',
@@ -59,8 +59,8 @@ entering extended mode
const noOp = () => {}
const onLogEntryLocationClick = sinon.stub()
describe('with logs', function() {
beforeEach(function() {
describe('with logs', function () {
beforeEach(function () {
renderWithEditorContext(
<PreviewLogsPane
logEntries={logEntries}
@@ -70,7 +70,7 @@ entering extended mode
/>
)
})
it('renders all log entries with appropriate labels', function() {
it('renders all log entries with appropriate labels', function () {
const errorEntries = screen.getAllByLabelText(
`Log entry with level: error`
)
@@ -85,11 +85,11 @@ entering extended mode
expect(typesettingEntries).to.have.lengthOf(typesetting.length)
})
it('renders the raw log', function() {
it('renders the raw log', function () {
screen.getByLabelText('Raw logs from the LaTeX compiler')
})
it('renders a link to location button for every error and warning log entry', function() {
it('renders a link to location button for every error and warning log entry', function () {
logEntries.all.forEach((entry, index) => {
const linkToSourceButton = screen.getByRole('button', {
name: `Navigate to log position in source code: ${entry.file}, ${entry.line}`
@@ -106,7 +106,7 @@ entering extended mode
).to.be.true
})
})
it(' does not render a link to location button for the raw log entry', function() {
it(' does not render a link to location button for the raw log entry', function () {
const rawLogEntry = screen.getByLabelText(
'Raw logs from the LaTeX compiler'
)
@@ -114,7 +114,7 @@ entering extended mode
})
})
describe('with validation issues', function() {
describe('with validation issues', function () {
const sampleValidationIssues = {
sizeCheck: {
resources: [
@@ -125,7 +125,7 @@ entering extended mode
mainFile: true
}
it('renders a validation entry for known issues', function() {
it('renders a validation entry for known issues', function () {
renderWithEditorContext(
<PreviewLogsPane
validationIssues={sampleValidationIssues}
@@ -141,7 +141,7 @@ entering extended mode
)
})
it('ignores unknown issues', function() {
it('ignores unknown issues', function () {
renderWithEditorContext(
<PreviewLogsPane
validationIssues={{ unknownIssue: true }}
@@ -156,14 +156,14 @@ entering extended mode
})
})
describe('with compilation errors', function() {
describe('with compilation errors', function () {
const sampleErrors = {
clsiMaintenance: true,
tooRecentlyCompiled: true,
compileTerminated: true
}
it('renders an error entry for known errors', function() {
it('renders an error entry for known errors', function () {
renderWithEditorContext(
<PreviewLogsPane
errors={sampleErrors}
@@ -177,7 +177,7 @@ entering extended mode
expect(errorEntries).to.have.lengthOf(Object.keys(sampleErrors).length)
})
it('ignores unknown errors', function() {
it('ignores unknown errors', function () {
renderWithEditorContext(
<PreviewLogsPane
errors={{ unknownIssue: true }}
@@ -192,8 +192,8 @@ entering extended mode
})
})
describe('with failing code check', function() {
beforeEach(function() {
describe('with failing code check', function () {
beforeEach(function () {
renderWithEditorContext(
<PreviewLogsPane
logEntries={logEntries}
@@ -204,7 +204,7 @@ entering extended mode
/>
)
})
it('renders a code check failed entry', function() {
it('renders a code check failed entry', function () {
screen.getByText(
'Your code has errors that need to be fixed before the auto-compile can run'
)
@@ -4,7 +4,7 @@ import { screen, render } from '@testing-library/react'
import PreviewLogsToggleButton from '../../../../../frontend/js/features/preview/components/preview-logs-toggle-button'
describe('<PreviewLogsToggleButton />', function() {
describe('<PreviewLogsToggleButton />', function () {
function renderPreviewLogsToggleButton(
logsState,
onToggleLogs,
@@ -25,27 +25,27 @@ describe('<PreviewLogsToggleButton />', function() {
)
}
describe('basic toggle functionality', function() {
describe('basic toggle functionality', function () {
const logsState = {
nErrors: 0,
nWarnings: 0
}
const onToggleLogs = () => {}
it('should render a view logs button when previewing the PDF', function() {
it('should render a view logs button when previewing the PDF', function () {
const showLogs = false
renderPreviewLogsToggleButton(logsState, onToggleLogs, showLogs)
screen.getByText('View logs')
})
it('should render a view PDF button when viewing logs', function() {
it('should render a view PDF button when viewing logs', function () {
const showLogs = true
renderPreviewLogsToggleButton(logsState, onToggleLogs, showLogs)
screen.getByText('View PDF')
})
})
describe('compile status indicator', function() {
describe('compile status indicator', function () {
const showLogs = false
const onToggleLogs = () => {}
it('should render a view logs button by default', function() {
it('should render a view logs button by default', function () {
const logsState = {
nErrors: 0,
nWarnings: 0
@@ -54,7 +54,7 @@ describe('<PreviewLogsToggleButton />', function() {
screen.getByText('View logs')
})
it('should render the code check failed notice', function() {
it('should render the code check failed notice', function () {
const logsState = {
nErrors: 1,
nWarnings: 0
@@ -69,7 +69,7 @@ describe('<PreviewLogsToggleButton />', function() {
screen.getByText('Code check failed')
})
it('should render an error status message when there are errors', function() {
it('should render an error status message when there are errors', function () {
const logsState = {
nErrors: 1,
nWarnings: 0
@@ -78,7 +78,7 @@ describe('<PreviewLogsToggleButton />', function() {
screen.getByText(`This project has errors (${logsState.nErrors})`)
})
it('should render an error status message when there are both errors and warnings', function() {
it('should render an error status message when there are both errors and warnings', function () {
const logsState = {
nErrors: 1,
nWarnings: 1
@@ -87,7 +87,7 @@ describe('<PreviewLogsToggleButton />', function() {
screen.getByText(`This project has errors (${logsState.nErrors})`)
})
it('should render a warning status message when there are warnings but no errors', function() {
it('should render a warning status message when there are warnings but no errors', function () {
const logsState = {
nErrors: 0,
nWarnings: 1
@@ -96,7 +96,7 @@ describe('<PreviewLogsToggleButton />', function() {
screen.getByText(`View warnings (${logsState.nWarnings})`)
})
it('should render 99+ errors when there are more than 99 errors', function() {
it('should render 99+ errors when there are more than 99 errors', function () {
const logsState = {
nErrors: 100,
nWarnings: 0
@@ -104,7 +104,7 @@ describe('<PreviewLogsToggleButton />', function() {
renderPreviewLogsToggleButton(logsState, onToggleLogs, showLogs)
screen.getByText('This project has errors (99+)')
})
it('should show the button text when prop showText=true', function() {
it('should show the button text when prop showText=true', function () {
const logsState = {
nErrors: 0,
nWarnings: 0
@@ -113,7 +113,7 @@ describe('<PreviewLogsToggleButton />', function() {
renderPreviewLogsToggleButton(logsState, onToggleLogs, showLogs, showText)
expect(screen.getByText('View logs').getAttribute('style')).to.be.null
})
it('should not show the button text when prop showText=false', function() {
it('should not show the button text when prop showText=false', function () {
const logsState = {
nErrors: 0,
nWarnings: 0
@@ -3,7 +3,7 @@ import { screen, render, fireEvent } from '@testing-library/react'
import PreviewPane from '../../../../../frontend/js/features/preview/components/preview-pane'
const { expect } = require('chai')
describe('<PreviewPane />', function() {
describe('<PreviewPane />', function () {
const sampleError1 = {
content: 'error 1 content',
file: 'main.tex',
@@ -25,8 +25,8 @@ describe('<PreviewPane />', function() {
message: "Reference `idontexist' on page 1 undefined on input line 30."
}
describe('first error pop-up', function() {
it('renders a first error pop-up with the first error', function() {
describe('first error pop-up', function () {
it('renders a first error pop-up with the first error', function () {
const propsAfterCompileWithErrors = getProps(false, {
errors: [sampleError1, sampleError2],
warnings: [sampleWarning]
@@ -38,7 +38,7 @@ describe('<PreviewPane />', function() {
screen.getByText(sampleError1.message)
})
it('does not render a first error pop-up when there are only warnings', function() {
it('does not render a first error pop-up when there are only warnings', function () {
const propsAfterCompileWithWarningsOnly = getProps(false, {
errors: [],
warnings: [sampleWarning]
@@ -51,7 +51,7 @@ describe('<PreviewPane />', function() {
).to.not.exist
})
it('does not render a first error pop-up when a compile is ongoing', function() {
it('does not render a first error pop-up when a compile is ongoing', function () {
const propsWhileCompiling = getProps(true, {
errors: [sampleError1, sampleError2],
warnings: [sampleWarning]
@@ -64,7 +64,7 @@ describe('<PreviewPane />', function() {
).to.not.exist
})
it('does not render a first error pop-up when viewing logs', function() {
it('does not render a first error pop-up when viewing logs', function () {
const propsWithErrorsViewingLogs = getProps(
false,
{
@@ -82,7 +82,7 @@ describe('<PreviewPane />', function() {
).to.not.exist
})
it('does not render a first error pop-up when going back to the PDF view after viewing logs', function() {
it('does not render a first error pop-up when going back to the PDF view after viewing logs', function () {
const nowTimestamp = Date.now()
const propsWithErrorsViewingLogs = getProps(
false,
@@ -113,7 +113,7 @@ describe('<PreviewPane />', function() {
).to.not.exist
})
it('renders a first error pop-up with updated errors after recompiling', function() {
it('renders a first error pop-up with updated errors after recompiling', function () {
const nowTimestamp = Date.now()
const laterTimestamp = Date.now() + 1000
const propsWithErrorsAfterFirstCompile = getProps(
@@ -144,7 +144,7 @@ describe('<PreviewPane />', function() {
screen.getByText(sampleError2.message)
})
it('allows dismissing the first error pop-up', function() {
it('allows dismissing the first error pop-up', function () {
const propsWithErrors = getProps(false, {
errors: [sampleError1, sampleError2],
warnings: [sampleWarning]
@@ -162,7 +162,7 @@ describe('<PreviewPane />', function() {
).to.not.exist
})
it('does not render the first error pop-up with new recompiles after it being dismissed once', function() {
it('does not render the first error pop-up with new recompiles after it being dismissed once', function () {
const nowTimestamp = Date.now()
const laterTimestamp = Date.now() + 1000
const propsWithErrorsForFirstCompile = getProps(
@@ -197,8 +197,8 @@ describe('<PreviewPane />', function() {
})
})
describe('accessible description of the compile result', function() {
it('renders an accessible description with the errors and warnings count', function() {
describe('accessible description of the compile result', function () {
it('renders an accessible description with the errors and warnings count', function () {
const errors = [sampleError1, sampleError2]
const warnings = [sampleWarning]
const propsWithErrorsAndWarnings = getProps(false, {
@@ -212,7 +212,7 @@ describe('<PreviewPane />', function() {
`${warnings.length} warning${warnings.length > 1 ? 's' : ''}`
)
})
it('renders an accessible description for failed compiles with CLSI errors', function() {
it('renders an accessible description for failed compiles with CLSI errors', function () {
const sampleCLSIError = {
clsiMaintenance: true
}
@@ -231,7 +231,7 @@ describe('<PreviewPane />', function() {
screen.getByText('This project did not compile because of an error')
})
it('renders an accessible description for failed compiles with validation issues', function() {
it('renders an accessible description for failed compiles with validation issues', function () {
const sampleValidationIssue = {
clsiMaintenance: true
}
@@ -4,16 +4,16 @@ import { screen, render, fireEvent } from '@testing-library/react'
import PreviewRecompileButton from '../../../../../frontend/js/features/preview/components/preview-recompile-button'
const { expect } = require('chai')
describe('<PreviewRecompileButton />', function() {
describe('<PreviewRecompileButton />', function () {
let onRecompile, onRecompileFromScratch, onStopCompilation
beforeEach(function() {
beforeEach(function () {
onRecompile = sinon.stub().resolves()
onRecompileFromScratch = sinon.stub().resolves()
onStopCompilation = sinon.stub().resolves()
})
it('renders all items', function() {
it('renders all items', function () {
renderPreviewRecompileButton()
const menuItems = screen.getAllByRole('menuitem')
@@ -39,9 +39,9 @@ describe('<PreviewRecompileButton />', function() {
])
})
describe('Recompile from scratch', function() {
describe('click', function() {
it('should call onRecompileFromScratch', async function() {
describe('Recompile from scratch', function () {
describe('click', function () {
it('should call onRecompileFromScratch', async function () {
renderPreviewRecompileButton()
const button = screen.getByRole('menuitem', {
@@ -51,8 +51,8 @@ describe('<PreviewRecompileButton />', function() {
expect(onRecompileFromScratch).to.have.been.calledOnce
})
})
describe('processing', function() {
it('shows processing view and disable menuItem when recompiling', function() {
describe('processing', function () {
it('shows processing view and disable menuItem when recompiling', function () {
renderPreviewRecompileButton({ isCompiling: true })
screen.getByRole('button', { name: 'Compiling…' })
@@ -75,12 +75,12 @@ describe('<PreviewRecompileButton />', function() {
})
})
it('should show the button text when prop showText=true', function() {
it('should show the button text when prop showText=true', function () {
const showText = true
renderPreviewRecompileButton({}, showText)
expect(screen.getByText('Recompile').getAttribute('style')).to.be.null
})
it('should not show the button text when prop showText=false', function() {
it('should not show the button text when prop showText=false', function () {
const showText = false
renderPreviewRecompileButton({}, showText)
expect(screen.getByText('Recompile').getAttribute('style')).to.equal(
@@ -88,8 +88,8 @@ describe('<PreviewRecompileButton />', function() {
)
})
describe('Autocompile feedback', function() {
it('shows animated visual feedback via CSS class when there are uncompiled changes', function() {
describe('Autocompile feedback', function () {
it('shows animated visual feedback via CSS class when there are uncompiled changes', function () {
const { container } = renderPreviewRecompileButton({
autoCompileHasChanges: true,
autoCompileHasLintingError: false
@@ -103,7 +103,7 @@ describe('<PreviewRecompileButton />', function() {
)
).to.be.true
})
it('does not show animated visual feedback via CSS class when there are no uncompiled changes', function() {
it('does not show animated visual feedback via CSS class when there are no uncompiled changes', function () {
const { container } = renderPreviewRecompileButton({
autoCompileHasChanges: false,
autoCompileHasLintingError: false
@@ -4,7 +4,7 @@ import { expect } from 'chai'
import { screen, render, fireEvent } from '@testing-library/react'
import PreviewToolbar from '../../../../../frontend/js/features/preview/components/preview-toolbar'
describe('<PreviewToolbar />', function() {
describe('<PreviewToolbar />', function () {
const onRecompile = sinon.stub()
const onRecompileFromScratch = sinon.stub()
const onRunSyntaxCheckNow = sinon.stub()
@@ -53,14 +53,14 @@ describe('<PreviewToolbar />', function() {
)
}
it('renders the toolbar', function() {
it('renders the toolbar', function () {
renderPreviewToolbar()
screen.getByText('Recompile')
screen.getByText('Download PDF')
screen.getByText('View logs')
})
it('all toolbar items have "toolbar-item" class and text has "toolbar-text"', function() {
it('all toolbar items have "toolbar-item" class and text has "toolbar-text"', function () {
renderPreviewToolbar()
const toolbar = screen.getByTestId('toolbar-preview')
for (const toolbarSection of toolbar.children) {
@@ -77,7 +77,7 @@ describe('<PreviewToolbar />', function() {
}
})
it('renders a full-screen button with a tooltip when when in split-screen mode', function() {
it('renders a full-screen button with a tooltip when when in split-screen mode', function () {
renderPreviewToolbar()
const btn = screen.getByLabelText('Full screen')
fireEvent.click(btn)
@@ -86,7 +86,7 @@ describe('<PreviewToolbar />', function() {
screen.getByRole('tooltip', { name: 'Full screen' })
})
it('renders a split-screen button with a tooltip when when in full-screen mode', function() {
it('renders a split-screen button with a tooltip when when in full-screen mode', function () {
renderPreviewToolbar({}, {}, false, false)
const btn = screen.getByLabelText('Split screen')
fireEvent.click(btn)
@@ -13,7 +13,7 @@ import fetchMock from 'fetch-mock'
import ShareProjectModal from '../../../../../frontend/js/features/share-project-modal/components/share-project-modal'
import * as locationModule from '../../../../../frontend/js/features/share-project-modal/utils/location'
describe('<ShareProjectModal/>', function() {
describe('<ShareProjectModal/>', function () {
const project = {
_id: 'test-project',
name: 'Test Project',
@@ -88,30 +88,30 @@ describe('<ShareProjectModal/>', function() {
const originalExposedSettings = window.ExposedSettings
before(function() {
before(function () {
window.ExposedSettings = { appName: 'Overleaf' }
})
after(function() {
after(function () {
window.ExposedSettings = originalExposedSettings
})
beforeEach(function() {
beforeEach(function () {
fetchMock.get('/user/contacts', { contacts })
})
afterEach(function() {
afterEach(function () {
fetchMock.restore()
cleanup()
})
it('renders the modal', async function() {
it('renders the modal', async function () {
render(<ShareProjectModal {...modalProps} />)
await screen.findByText('Share Project')
})
it('calls handleHide when a Close button is pressed', async function() {
it('calls handleHide when a Close button is pressed', async function () {
const handleHide = sinon.stub()
render(<ShareProjectModal {...modalProps} handleHide={handleHide} />)
@@ -127,7 +127,7 @@ describe('<ShareProjectModal/>', function() {
expect(handleHide.callCount).to.equal(2)
})
it('handles access level "private"', async function() {
it('handles access level "private"', async function () {
render(
<ShareProjectModal
{...modalProps}
@@ -146,7 +146,7 @@ describe('<ShareProjectModal/>', function() {
.be.null
})
it('handles access level "tokenBased"', async function() {
it('handles access level "tokenBased"', async function () {
render(
<ShareProjectModal
{...modalProps}
@@ -163,7 +163,7 @@ describe('<ShareProjectModal/>', function() {
.not.to.be.null
})
it('handles legacy access level "readAndWrite"', async function() {
it('handles legacy access level "readAndWrite"', async function () {
render(
<ShareProjectModal
{...modalProps}
@@ -177,7 +177,7 @@ describe('<ShareProjectModal/>', function() {
await screen.findByRole('button', { name: 'Make Private' })
})
it('handles legacy access level "readOnly"', async function() {
it('handles legacy access level "readOnly"', async function () {
render(
<ShareProjectModal
{...modalProps}
@@ -191,7 +191,7 @@ describe('<ShareProjectModal/>', function() {
await screen.findByRole('button', { name: 'Make Private' })
})
it('hides actions from non-admins', async function() {
it('hides actions from non-admins', async function () {
const invites = [
{
_id: 'invited-author',
@@ -263,7 +263,7 @@ describe('<ShareProjectModal/>', function() {
expect(screen.queryByRole('button', { name: 'Resend' })).to.be.null
})
it('only shows read-only token link to restricted token members', async function() {
it('only shows read-only token link to restricted token members', async function () {
window.isRestrictedTokenMember = true
render(
@@ -287,7 +287,7 @@ describe('<ShareProjectModal/>', function() {
.be.null
})
it('displays project members and invites', async function() {
it('displays project members and invites', async function () {
const members = [
{
_id: 'member-author',
@@ -344,7 +344,7 @@ describe('<ShareProjectModal/>', function() {
)
})
it('resends an invite', async function() {
it('resends an invite', async function () {
fetchMock.postOnce(
'express:/project/:projectId/invite/:inviteId/resend',
204
@@ -382,7 +382,7 @@ describe('<ShareProjectModal/>', function() {
expect(closeButton.disabled).to.be.false
})
it('revokes an invite', async function() {
it('revokes an invite', async function () {
fetchMock.deleteOnce('express:/project/:projectId/invite/:inviteId', 204)
const invites = [
@@ -416,7 +416,7 @@ describe('<ShareProjectModal/>', function() {
expect(closeButton.disabled).to.be.false
})
it('changes member privileges to read + write', async function() {
it('changes member privileges to read + write', async function () {
fetchMock.putOnce('express:/project/:projectId/users/:userId', 204)
const members = [
@@ -459,7 +459,7 @@ describe('<ShareProjectModal/>', function() {
expect(closeButton.disabled).to.be.false
})
it('removes a member from the project', async function() {
it('removes a member from the project', async function () {
fetchMock.deleteOnce('express:/project/:projectId/users/:userId', 204)
const members = [
@@ -499,7 +499,7 @@ describe('<ShareProjectModal/>', function() {
)
})
it('changes member privileges to owner with confirmation', async function() {
it('changes member privileges to owner with confirmation', async function () {
fetchMock.postOnce('express:/project/:projectId/transfer-ownership', 204)
const members = [
@@ -552,7 +552,7 @@ describe('<ShareProjectModal/>', function() {
reloadStub.restore()
})
it('sends invites to input email addresses', async function() {
it('sends invites to input email addresses', async function () {
render(
<ShareProjectModal
{...modalProps}
@@ -640,7 +640,7 @@ describe('<ShareProjectModal/>', function() {
screen.getByText('An email address is invalid')
})
it('displays a message when the collaborator limit is reached', async function() {
it('displays a message when the collaborator limit is reached', async function () {
const originalUser = window.user
window.user = { allowedFreeTrial: true }
@@ -667,7 +667,7 @@ describe('<ShareProjectModal/>', function() {
window.user = originalUser
})
it('handles server error responses', async function() {
it('handles server error responses', async function () {
render(
<ShareProjectModal
{...modalProps}
@@ -689,7 +689,7 @@ describe('<ShareProjectModal/>', function() {
const submitButton = screen.getByRole('button', { name: 'Share' })
const respondWithError = async function(errorReason) {
const respondWithError = async function (errorReason) {
inputElement.focus()
fireEvent.change(inputElement, {
target: { value: 'invited-author-1@example.com' }
@@ -733,7 +733,7 @@ describe('<ShareProjectModal/>', function() {
)
})
it('handles switching between access levels', async function() {
it('handles switching between access levels', async function () {
fetchMock.post('express:/project/:projectId/settings/admin', 204)
render(
@@ -775,7 +775,7 @@ describe('<ShareProjectModal/>', function() {
)
})
it('avoids selecting unmatched contact', async function() {
it('avoids selecting unmatched contact', async function () {
render(<ShareProjectModal {...modalProps} />)
const [inputElement] = await screen.findAllByLabelText(
@@ -5,8 +5,8 @@ import { expect } from 'chai'
import sinon from 'sinon'
import fetchMock from 'fetch-mock'
describe('<WordCountModal />', function() {
afterEach(function() {
describe('<WordCountModal />', function () {
afterEach(function () {
fetchMock.reset()
cleanup()
})
@@ -18,13 +18,13 @@ describe('<WordCountModal />', function() {
handleHide: sinon.stub()
}
it('renders the translated modal title', async function() {
it('renders the translated modal title', async function () {
render(<WordCountModal {...modalProps} />)
await screen.findByText('Word Count')
})
it('renders a loading message when loading', async function() {
it('renders a loading message when loading', async function () {
fetchMock.get('express:/project/:projectId/wordcount', () => {
return { status: 200, body: { texcount: {} } }
})
@@ -34,7 +34,7 @@ describe('<WordCountModal />', function() {
await screen.findByText('Loading…')
})
it('renders an error message and hides loading message on error', async function() {
it('renders an error message and hides loading message on error', async function () {
fetchMock.get('express:/project/:projectId/wordcount', 500)
render(<WordCountModal {...modalProps} />)
@@ -44,7 +44,7 @@ describe('<WordCountModal />', function() {
expect(screen.queryByText(/Loading/)).to.not.exist
})
it('displays messages', async function() {
it('displays messages', async function () {
fetchMock.get('express:/project/:projectId/wordcount', () => {
return {
status: 200,
@@ -61,7 +61,7 @@ describe('<WordCountModal />', function() {
await screen.findByText('This is a test')
})
it('displays counts data', async function() {
it('displays counts data', async function () {
fetchMock.get('express:/project/:projectId/wordcount', () => {
return {
status: 200,
@@ -13,16 +13,16 @@ import { expect } from 'chai'
import displayNameForUser from '../../../../../frontend/js/ide/history/util/displayNameForUser'
export default describe('displayNameForUser', function() {
beforeEach(function() {
export default describe('displayNameForUser', function () {
beforeEach(function () {
return (window.user = { id: 42 })
})
it("should return 'Anonymous' with no user", function() {
it("should return 'Anonymous' with no user", function () {
return expect(displayNameForUser(null)).to.equal('Anonymous')
})
it("should return 'you' when the user has the same id as the window", function() {
it("should return 'you' when the user has the same id as the window", function () {
return expect(
displayNameForUser({
id: window.user.id,
@@ -33,7 +33,7 @@ export default describe('displayNameForUser', function() {
).to.equal('you')
})
it('should return the first_name and last_name when present', function() {
it('should return the first_name and last_name when present', function () {
return expect(
displayNameForUser({
id: window.user.id + 1,
@@ -44,7 +44,7 @@ export default describe('displayNameForUser', function() {
).to.equal('James Allen')
})
it('should return only the firstAname if no last_name', function() {
it('should return only the firstAname if no last_name', function () {
return expect(
displayNameForUser({
id: window.user.id + 1,
@@ -55,7 +55,7 @@ export default describe('displayNameForUser', function() {
).to.equal('James')
})
it('should return the email username if there are no names', function() {
it('should return the email username if there are no names', function () {
return expect(
displayNameForUser({
id: window.user.id + 1,
@@ -66,7 +66,7 @@ export default describe('displayNameForUser', function() {
).to.equal('james.allen')
})
it("should return the '?' if it has nothing", function() {
it("should return the '?' if it has nothing", function () {
return expect(
displayNameForUser({
id: window.user.id + 1,
@@ -8,12 +8,12 @@ import {
putJSON
} from '../../../frontend/js/infrastructure/fetch-json'
describe('fetchJSON', function() {
before(function() {
describe('fetchJSON', function () {
before(function () {
fetchMock.restore()
})
afterEach(function() {
afterEach(function () {
fetchMock.restore()
})
@@ -22,7 +22,7 @@ describe('fetchJSON', function() {
'Content-Type': 'application/json'
}
it('handles GET requests', function() {
it('handles GET requests', function () {
fetchMock.once(
{ method: 'GET', url: '/test', headers },
{ status: 200, body: { result: 'success' } }
@@ -33,7 +33,7 @@ describe('fetchJSON', function() {
})
})
it('handles 4xx responses', function() {
it('handles 4xx responses', function () {
fetchMock.get('/test', {
status: 400,
body: { message: 'The request was invalid' }
@@ -50,7 +50,7 @@ describe('fetchJSON', function() {
})
})
it('handles 5xx responses', async function() {
it('handles 5xx responses', async function () {
fetchMock.get('/test', { status: 500 })
return expect(getJSON('/test'))
@@ -62,7 +62,7 @@ describe('fetchJSON', function() {
})
})
it('handles POST requests', function() {
it('handles POST requests', function () {
const body = { example: true }
fetchMock.once(
@@ -75,7 +75,7 @@ describe('fetchJSON', function() {
})
})
it('handles PUT requests', function() {
it('handles PUT requests', function () {
const body = { example: true }
fetchMock.once(
@@ -88,7 +88,7 @@ describe('fetchJSON', function() {
})
})
it('handles DELETE requests', function() {
it('handles DELETE requests', function () {
fetchMock.once({ method: 'DELETE', url: '/test', headers }, { status: 204 })
return expect(deleteJSON('/test')).to.eventually.deep.equal({})
@@ -3,19 +3,19 @@ import sinon from 'sinon'
import customLocalStorage from '../../../frontend/js/infrastructure/local-storage'
describe('localStorage', function() {
describe('localStorage', function () {
let originalLocalStorage
before(function() {
before(function () {
originalLocalStorage = global.localStorage
})
after(function() {
after(function () {
Object.defineProperty(global, 'localStorage', {
value: originalLocalStorage
})
})
beforeEach(function() {
beforeEach(function () {
Object.defineProperty(global, 'localStorage', {
value: {
getItem: sinon.stub().returns(null),
@@ -28,12 +28,12 @@ describe('localStorage', function() {
global.console.error = sinon.stub()
})
afterEach(function() {
afterEach(function () {
global.console.error.reset()
Object.defineProperty(global, 'localStorage', { value: undefined })
})
it('getItem', function() {
it('getItem', function () {
expect(customLocalStorage.getItem('foo')).to.be.null
global.localStorage.getItem.returns('false')
@@ -47,7 +47,7 @@ describe('localStorage', function() {
expect(global.console.error).to.be.calledOnce
})
it('setItem', function() {
it('setItem', function () {
customLocalStorage.setItem('foo', 'bar')
expect(global.localStorage.setItem).to.be.calledOnceWith('foo', '"bar"')
global.localStorage.setItem.reset()
@@ -65,7 +65,7 @@ describe('localStorage', function() {
expect(global.console.error).to.be.calledOnce
})
it('clear', function() {
it('clear', function () {
customLocalStorage.clear()
expect(global.localStorage.clear).to.be.calledOnce
@@ -74,7 +74,7 @@ describe('localStorage', function() {
expect(global.console.error).to.be.calledOnce
})
it('removeItem', function() {
it('removeItem', function () {
customLocalStorage.removeItem('foo')
expect(global.localStorage.removeItem).to.be.calledOnceWith('foo')
global.localStorage.removeItem.reset()
@@ -9,7 +9,7 @@
* to fail the tests when prop-types errors.
*/
const originalConsoleError = global.console.error
before(function() {
before(function () {
global.console.error = (message, ...args) => {
// Ensure we still log the error
originalConsoleError(message, ...args)
@@ -23,6 +23,6 @@ before(function() {
})
// Restore the original method
after(function() {
after(function () {
global.console.error = originalConsoleError
})
@@ -4,37 +4,37 @@ import { screen, render } from '@testing-library/react'
import Icon from '../../../../frontend/js/shared/components/icon'
describe('<Icon />', function() {
it('renders basic fa classes', function() {
describe('<Icon />', function () {
it('renders basic fa classes', function () {
const { container } = render(<Icon type="angle-down" />)
const element = container.querySelector('i.fa.fa-angle-down')
expect(element).to.exist
})
it('renders with aria-hidden', function() {
it('renders with aria-hidden', function () {
const { container } = render(<Icon type="angle-down" />)
const element = container.querySelector('i[aria-hidden="true"]')
expect(element).to.exist
})
it('renders accessible label', function() {
it('renders accessible label', function () {
render(<Icon type="angle-down" accessibilityLabel="Accessible Foo" />)
screen.getByText('Accessible Foo')
})
it('renders with spin', function() {
it('renders with spin', function () {
const { container } = render(<Icon type="angle-down" spin />)
const element = container.querySelector('i.fa.fa-angle-down.fa-spin')
expect(element).to.exist
})
it('renders with modifier', function() {
it('renders with modifier', function () {
const { container } = render(<Icon type="angle-down" modifier="2x" />)
const element = container.querySelector('i.fa.fa-angle-down.fa-2x')
expect(element).to.exist
})
it('renders with custom clases', function() {
it('renders with custom clases', function () {
const { container } = render(
<Icon type="angle-down" classes={{ icon: 'custom-icon-class' }} />
)
@@ -44,7 +44,7 @@ describe('<Icon />', function() {
expect(element).to.exist
})
it('renders children', function() {
it('renders children', function () {
const { container } = render(
<Icon type="angle-down">
<Icon type="angle-up" />
@@ -35,11 +35,11 @@ ExpandCollapseTestUI.propTypes = {
expandCollapseArgs: PropTypes.object
}
describe('useExpandCollapse', function() {
describe('useExpandCollapse', function () {
// JSDom doesn't compute layout/sizing, so we need to simulate sizing for the elements
// Here we are simulating that the content is bigger than the `collapsedSize`, so
// the expand-collapse widget is used
beforeEach(function() {
beforeEach(function () {
Object.defineProperty(HTMLElement.prototype, 'scrollHeight', {
configurable: true,
value: 500
@@ -50,7 +50,7 @@ describe('useExpandCollapse', function() {
})
})
afterEach(function() {
afterEach(function () {
Object.defineProperty(
HTMLElement.prototype,
'scrollHeight',
@@ -63,8 +63,8 @@ describe('useExpandCollapse', function() {
)
})
describe('custom CSS classes', function() {
it('supports a custom CSS class', function() {
describe('custom CSS classes', function () {
it('supports a custom CSS class', function () {
const testArgs = {
classes: {
container: 'my-custom-class'
@@ -76,7 +76,7 @@ describe('useExpandCollapse', function() {
const elWithCustomCSSClass = container.querySelector('div')
expect(elWithCustomCSSClass).to.exist
})
it('supports an extra custom CSS class for the collapsed state', function() {
it('supports an extra custom CSS class for the collapsed state', function () {
const testArgs = {
classes: {
containerCollapsed: 'my-custom-collapsed-class'
@@ -91,7 +91,7 @@ describe('useExpandCollapse', function() {
)
expect(elWithCustomCollapsedCSSClass).to.exist
})
it('ignores the collapsed CSS class when expanded', function() {
it('ignores the collapsed CSS class when expanded', function () {
const testArgs = {
initiallyExpanded: true,
classes: {
@@ -107,14 +107,14 @@ describe('useExpandCollapse', function() {
expect(elWithCustomCollapsedCSSClass).to.not.exist
})
})
describe('height and width support via dimension argument', function() {
it('defaults to height', function() {
describe('height and width support via dimension argument', function () {
it('defaults to height', function () {
const { container } = render(<ExpandCollapseTestUI />)
const expandCollapseEl = container.firstChild
expect(expandCollapseEl.style.height).to.not.be.empty
expect(expandCollapseEl.style.width).to.be.empty
})
it('supports width', function() {
it('supports width', function () {
const testArgs = {
dimension: 'width'
}
@@ -126,13 +126,13 @@ describe('useExpandCollapse', function() {
expect(expandCollapseEl.style.width).to.not.be.empty
})
})
describe('collapsed size support via collapsedSize argument', function() {
it('defaults to 0px', function() {
describe('collapsed size support via collapsedSize argument', function () {
it('defaults to 0px', function () {
const { container } = render(<ExpandCollapseTestUI />)
const expandCollapseEl = container.firstChild
expect(expandCollapseEl.style.height).to.equal('0px')
})
it('supports a custom collapsed size', function() {
it('supports a custom collapsed size', function () {
const testArgs = {
collapsedSize: 200
}
@@ -142,7 +142,7 @@ describe('useExpandCollapse', function() {
const expandCollapseEl = container.firstChild
expect(expandCollapseEl.style.height).to.equal('200px')
})
it('supports a custom collapsed size for width', function() {
it('supports a custom collapsed size for width', function () {
const testArgs = {
collapsedSize: 200,
dimension: 'width'
@@ -15,12 +15,12 @@ import sinon from 'sinon'
import EventEmitter from '../../../frontend/js/utils/EventEmitter'
export default describe('EventEmitter', function() {
beforeEach(function() {
export default describe('EventEmitter', function () {
beforeEach(function () {
return (this.eventEmitter = new EventEmitter())
})
it('calls listeners', function() {
it('calls listeners', function () {
const cb1 = sinon.stub()
const cb2 = sinon.stub()
this.eventEmitter.on('foo', cb1)
@@ -32,7 +32,7 @@ export default describe('EventEmitter', function() {
return expect(cb2).to.not.have.been.called
})
it('calls multiple listeners', function() {
it('calls multiple listeners', function () {
const cb1 = sinon.stub()
const cb2 = sinon.stub()
this.eventEmitter.on('foo', cb1)
@@ -44,7 +44,7 @@ export default describe('EventEmitter', function() {
return expect(cb2).to.have.been.called
})
it('calls listeners with namespace', function() {
it('calls listeners with namespace', function () {
const cb1 = sinon.stub()
const cb2 = sinon.stub()
this.eventEmitter.on('foo', cb1)
@@ -56,7 +56,7 @@ export default describe('EventEmitter', function() {
return expect(cb2).to.have.been.called
})
it('removes listeners', function() {
it('removes listeners', function () {
const cb = sinon.stub()
this.eventEmitter.on('foo', cb)
this.eventEmitter.off('foo')
@@ -66,7 +66,7 @@ export default describe('EventEmitter', function() {
return expect(cb).to.not.have.been.called
})
it('removes namespaced listeners', function() {
it('removes namespaced listeners', function () {
const cb = sinon.stub()
this.eventEmitter.on('foo.bar', cb)
this.eventEmitter.off('foo.bar')
@@ -76,7 +76,7 @@ export default describe('EventEmitter', function() {
return expect(cb).to.not.have.been.called
})
it('does not remove unnamespaced listeners if off called with namespace', function() {
it('does not remove unnamespaced listeners if off called with namespace', function () {
const cb1 = sinon.stub()
const cb2 = sinon.stub()
this.eventEmitter.on('foo', cb1)