mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-15 14:43:46 +01:00
Merge pull request #3495 from overleaf/ae-prettier-2
Upgrade Prettier to v2 GitOrigin-RevId: 85aa3fa1acb6332c4f58c46165a43d1a51471f33
This commit is contained in:
@@ -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)
|
||||
|
||||
+6
-6
@@ -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, {
|
||||
|
||||
+7
-7
@@ -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">
|
||||
|
||||
+10
-10
@@ -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: [
|
||||
|
||||
+6
-6
@@ -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"
|
||||
|
||||
+11
-11
@@ -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 />,
|
||||
{
|
||||
|
||||
+4
-4
@@ -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"
|
||||
|
||||
+10
-10
@@ -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 },
|
||||
|
||||
+11
-23
@@ -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)
|
||||
|
||||
+9
-12
@@ -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} />)
|
||||
|
||||
+18
-18
@@ -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'
|
||||
)
|
||||
|
||||
+13
-13
@@ -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
|
||||
}
|
||||
|
||||
+13
-13
@@ -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)
|
||||
|
||||
+25
-25
@@ -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(
|
||||
|
||||
+7
-7
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user