first commit
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
import { expect } from 'chai'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
|
||||
import ChatToggleButton from '../../../../../frontend/js/features/editor-navigation-toolbar/components/chat-toggle-button'
|
||||
|
||||
describe('<ChatToggleButton />', function () {
|
||||
const defaultProps = {
|
||||
chatIsOpen: false,
|
||||
unreadMessageCount: 0,
|
||||
onClick: () => {},
|
||||
}
|
||||
|
||||
it('displays the number of unread messages', function () {
|
||||
const props = {
|
||||
...defaultProps,
|
||||
unreadMessageCount: 113,
|
||||
}
|
||||
render(<ChatToggleButton {...props} />)
|
||||
screen.getByText('113')
|
||||
})
|
||||
|
||||
it("doesn't display the unread messages badge when the number of unread messages is zero", function () {
|
||||
render(<ChatToggleButton {...defaultProps} />)
|
||||
expect(screen.queryByText('0')).to.not.exist
|
||||
})
|
||||
})
|
@@ -0,0 +1,219 @@
|
||||
import sinon from 'sinon'
|
||||
import fetchMock from 'fetch-mock'
|
||||
import { expect } from 'chai'
|
||||
import { screen } from '@testing-library/react'
|
||||
import LayoutDropdownButton from '../../../../../frontend/js/features/editor-navigation-toolbar/components/layout-dropdown-button'
|
||||
import { renderWithEditorContext } from '../../../helpers/render-with-context'
|
||||
import * as eventTracking from '@/infrastructure/event-tracking'
|
||||
|
||||
describe('<LayoutDropdownButton />', function () {
|
||||
let openStub
|
||||
let sendMBSpy
|
||||
const defaultUi = {
|
||||
pdfLayout: 'flat',
|
||||
view: 'pdf',
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
openStub = sinon.stub(window, 'open')
|
||||
sendMBSpy = sinon.spy(eventTracking, 'sendMB')
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
openStub.restore()
|
||||
sendMBSpy.restore()
|
||||
fetchMock.removeRoutes().clearHistory()
|
||||
})
|
||||
|
||||
it('should mark current layout option as selected', async function () {
|
||||
// Selected is aria-label, visually we show a checkmark
|
||||
renderWithEditorContext(<LayoutDropdownButton />, { ui: defaultUi })
|
||||
|
||||
screen.getByRole('button', { name: 'Layout' }).click()
|
||||
|
||||
expect(
|
||||
screen
|
||||
.getByRole('menuitem', {
|
||||
name: 'Editor & PDF',
|
||||
})
|
||||
.getAttribute('aria-selected')
|
||||
).to.equal('false')
|
||||
|
||||
expect(
|
||||
screen
|
||||
.getByRole('menuitem', {
|
||||
name: 'PDF only (hide editor)',
|
||||
})
|
||||
.getAttribute('aria-selected')
|
||||
).to.equal('true')
|
||||
|
||||
expect(
|
||||
screen
|
||||
.getByRole('menuitem', {
|
||||
name: 'Editor only (hide PDF)',
|
||||
})
|
||||
.getAttribute('aria-selected')
|
||||
).to.equal('false')
|
||||
|
||||
expect(
|
||||
screen
|
||||
.getByRole('menuitem', {
|
||||
name: 'PDF in separate tab',
|
||||
})
|
||||
.getAttribute('aria-selected')
|
||||
).to.equal('false')
|
||||
})
|
||||
|
||||
it('should not select any option in history view', function () {
|
||||
// Selected is aria-label, visually we show a checkmark
|
||||
renderWithEditorContext(<LayoutDropdownButton />, {
|
||||
ui: { ...defaultUi, view: 'history' },
|
||||
})
|
||||
|
||||
screen.getByRole('button', { name: 'Layout' }).click()
|
||||
|
||||
expect(
|
||||
screen
|
||||
.getByRole('menuitem', {
|
||||
name: 'Editor & PDF',
|
||||
})
|
||||
.getAttribute('aria-selected')
|
||||
).to.equal('false')
|
||||
|
||||
expect(
|
||||
screen
|
||||
.getByRole('menuitem', {
|
||||
name: 'PDF only (hide editor)',
|
||||
})
|
||||
.getAttribute('aria-selected')
|
||||
).to.equal('false')
|
||||
|
||||
expect(
|
||||
screen
|
||||
.getByRole('menuitem', {
|
||||
name: 'Editor only (hide PDF)',
|
||||
})
|
||||
.getAttribute('aria-selected')
|
||||
).to.equal('false')
|
||||
|
||||
expect(
|
||||
screen
|
||||
.getByRole('menuitem', {
|
||||
name: 'PDF in separate tab',
|
||||
})
|
||||
.getAttribute('aria-selected')
|
||||
).to.equal('false')
|
||||
})
|
||||
|
||||
it('should treat file and editor views the same way', function () {
|
||||
// Selected is aria-label, visually we show a checkmark
|
||||
renderWithEditorContext(<LayoutDropdownButton />, {
|
||||
ui: {
|
||||
pdfLayout: 'flat',
|
||||
view: 'file',
|
||||
},
|
||||
})
|
||||
|
||||
screen.getByRole('button', { name: 'Layout' }).click()
|
||||
|
||||
expect(
|
||||
screen
|
||||
.getByRole('menuitem', {
|
||||
name: 'Editor & PDF',
|
||||
})
|
||||
.getAttribute('aria-selected')
|
||||
).to.equal('false')
|
||||
|
||||
expect(
|
||||
screen
|
||||
.getByRole('menuitem', {
|
||||
name: 'PDF only (hide editor)',
|
||||
})
|
||||
.getAttribute('aria-selected')
|
||||
).to.equal('false')
|
||||
|
||||
expect(
|
||||
screen
|
||||
.getByRole('menuitem', {
|
||||
name: 'Editor only (hide PDF)',
|
||||
})
|
||||
.getAttribute('aria-selected')
|
||||
).to.equal('true')
|
||||
|
||||
expect(
|
||||
screen
|
||||
.getByRole('menuitem', {
|
||||
name: 'PDF in separate tab',
|
||||
})
|
||||
.getAttribute('aria-selected')
|
||||
).to.equal('false')
|
||||
})
|
||||
|
||||
describe('on detach', function () {
|
||||
let originalBroadcastChannel
|
||||
beforeEach(function () {
|
||||
window.BroadcastChannel = originalBroadcastChannel || true // ensure that window.BroadcastChannel is truthy
|
||||
|
||||
renderWithEditorContext(<LayoutDropdownButton />, {
|
||||
ui: { ...defaultUi, view: 'editor' },
|
||||
})
|
||||
|
||||
screen.getByRole('button', { name: 'Layout' }).click()
|
||||
|
||||
screen
|
||||
.getByRole('menuitem', {
|
||||
name: 'PDF in separate tab',
|
||||
})
|
||||
.click()
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
window.BroadcastChannel = originalBroadcastChannel
|
||||
})
|
||||
|
||||
it('should show processing', function () {
|
||||
screen.getByText('Layout processing')
|
||||
})
|
||||
|
||||
it('should record event', function () {
|
||||
sinon.assert.calledWith(sendMBSpy, 'project-layout-detach')
|
||||
})
|
||||
})
|
||||
|
||||
describe('on layout change / reattach', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache.set('ol-detachRole', 'detacher')
|
||||
renderWithEditorContext(<LayoutDropdownButton />, {
|
||||
ui: { ...defaultUi, view: 'editor' },
|
||||
})
|
||||
|
||||
screen.getByRole('button', { name: 'Layout' }).click()
|
||||
|
||||
screen
|
||||
.getByRole('menuitem', {
|
||||
name: 'Editor only (hide PDF)',
|
||||
})
|
||||
.click()
|
||||
})
|
||||
|
||||
it('should not show processing', function () {
|
||||
const processingText = screen.queryByText('Layout processing')
|
||||
expect(processingText).to.not.exist
|
||||
})
|
||||
|
||||
it('should record events', function () {
|
||||
sinon.assert.calledWith(sendMBSpy, 'project-layout-reattach')
|
||||
sinon.assert.calledWith(sendMBSpy, 'project-layout-change', {
|
||||
layout: 'flat',
|
||||
view: 'editor',
|
||||
page: '/detacher',
|
||||
})
|
||||
})
|
||||
|
||||
it('should select new menu item', function () {
|
||||
screen.getByRole('menuitem', {
|
||||
name: 'Editor only (hide PDF)',
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@@ -0,0 +1,104 @@
|
||||
import { expect } from 'chai'
|
||||
import sinon from 'sinon'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
|
||||
import OnlineUsersWidget from '../../../../../frontend/js/features/editor-navigation-toolbar/components/online-users-widget'
|
||||
|
||||
describe('<OnlineUsersWidget />', function () {
|
||||
const defaultProps = {
|
||||
onlineUsers: [
|
||||
{
|
||||
user_id: 'test_user',
|
||||
name: 'test_user',
|
||||
},
|
||||
{
|
||||
user_id: 'another_test_user',
|
||||
name: 'another_test_user',
|
||||
},
|
||||
],
|
||||
goToUser: () => {},
|
||||
}
|
||||
|
||||
describe('with less than 4 users', function () {
|
||||
it('displays user initials', function () {
|
||||
render(<OnlineUsersWidget {...defaultProps} />)
|
||||
screen.getByText('t')
|
||||
screen.getByText('a')
|
||||
})
|
||||
|
||||
it('displays user name in a tooltip', async function () {
|
||||
render(<OnlineUsersWidget {...defaultProps} />)
|
||||
const icon = screen.getByText('t')
|
||||
fireEvent.mouseOver(icon)
|
||||
await screen.findByRole('tooltip', { name: 'test_user' })
|
||||
})
|
||||
|
||||
it('calls "goToUser" when the user initial is clicked', function () {
|
||||
const props = {
|
||||
...defaultProps,
|
||||
goToUser: sinon.stub(),
|
||||
}
|
||||
render(<OnlineUsersWidget {...props} />)
|
||||
|
||||
const icon = screen.getByText('t')
|
||||
fireEvent.click(icon)
|
||||
|
||||
expect(props.goToUser).to.be.calledWith({
|
||||
name: 'test_user',
|
||||
user_id: 'test_user',
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with 4 users and more', function () {
|
||||
const props = {
|
||||
...defaultProps,
|
||||
onlineUsers: defaultProps.onlineUsers.concat([
|
||||
{
|
||||
user_id: 'user_3',
|
||||
name: 'user_3',
|
||||
},
|
||||
{
|
||||
user_id: 'user_4',
|
||||
name: 'user_4',
|
||||
},
|
||||
]),
|
||||
}
|
||||
|
||||
it('displays the count of users', function () {
|
||||
render(<OnlineUsersWidget {...props} />)
|
||||
screen.getByText('4')
|
||||
})
|
||||
|
||||
it('displays user names on hover', function () {
|
||||
render(<OnlineUsersWidget {...props} />)
|
||||
|
||||
const toggleButton = screen.getByRole('button')
|
||||
fireEvent.click(toggleButton)
|
||||
|
||||
screen.getByText('test_user')
|
||||
screen.getByText('another_test_user')
|
||||
screen.getByText('user_3')
|
||||
screen.getByText('user_4')
|
||||
})
|
||||
|
||||
it('calls "goToUser" when the user name is clicked', function () {
|
||||
const testProps = {
|
||||
...props,
|
||||
goToUser: sinon.stub(),
|
||||
}
|
||||
render(<OnlineUsersWidget {...testProps} />)
|
||||
|
||||
const toggleButton = screen.getByRole('button')
|
||||
fireEvent.click(toggleButton)
|
||||
|
||||
const icon = screen.getByText('user_3')
|
||||
fireEvent.click(icon)
|
||||
|
||||
expect(testProps.goToUser).to.be.calledWith({
|
||||
name: 'user_3',
|
||||
user_id: 'user_3',
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@@ -0,0 +1,78 @@
|
||||
import { expect } from 'chai'
|
||||
import sinon from 'sinon'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
|
||||
import ProjectNameEditableLabel from '../../../../../frontend/js/features/editor-navigation-toolbar/components/project-name-editable-label'
|
||||
|
||||
describe('<ProjectNameEditableLabel />', function () {
|
||||
const defaultProps = { projectName: 'test-project', onChange: () => {} }
|
||||
|
||||
it('displays the project name', function () {
|
||||
render(<ProjectNameEditableLabel {...defaultProps} />)
|
||||
screen.getByText('test-project')
|
||||
})
|
||||
|
||||
describe('when the name is editable', function () {
|
||||
const editableProps = { ...defaultProps, hasRenamePermissions: true }
|
||||
|
||||
it('displays an editable input when the edit button is clicked', function () {
|
||||
render(<ProjectNameEditableLabel {...editableProps} />)
|
||||
fireEvent.click(screen.getByRole('button'))
|
||||
screen.getByRole('textbox')
|
||||
})
|
||||
|
||||
it('displays an editable input when the project name is double clicked', function () {
|
||||
render(<ProjectNameEditableLabel {...editableProps} />)
|
||||
fireEvent.doubleClick(screen.getByText('test-project'))
|
||||
screen.getByRole('textbox')
|
||||
})
|
||||
|
||||
it('calls "onChange" when the project name is updated', function () {
|
||||
const props = {
|
||||
...editableProps,
|
||||
onChange: sinon.stub(),
|
||||
}
|
||||
render(<ProjectNameEditableLabel {...props} />)
|
||||
|
||||
fireEvent.doubleClick(screen.getByText('test-project'))
|
||||
const input = screen.getByRole('textbox')
|
||||
|
||||
fireEvent.change(input, { target: { value: 'new project name' } })
|
||||
fireEvent.keyDown(input, { key: 'Enter' })
|
||||
|
||||
expect(props.onChange).to.be.calledWith('new project name')
|
||||
})
|
||||
|
||||
it('calls "onChange" when the input loses focus', function () {
|
||||
const props = {
|
||||
...editableProps,
|
||||
onChange: sinon.stub(),
|
||||
}
|
||||
render(<ProjectNameEditableLabel {...props} />)
|
||||
|
||||
fireEvent.doubleClick(screen.getByText('test-project'))
|
||||
const input = screen.getByRole('textbox')
|
||||
|
||||
fireEvent.change(input, { target: { value: 'new project name' } })
|
||||
|
||||
fireEvent.blur(screen.getByRole('textbox'))
|
||||
|
||||
expect(props.onChange).to.be.calledWith('new project name')
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the name is not editable', function () {
|
||||
const nonEditableProps = { hasRenamePermissions: false, ...defaultProps }
|
||||
|
||||
it('the edit button is not displayed', function () {
|
||||
render(<ProjectNameEditableLabel {...nonEditableProps} />)
|
||||
expect(screen.queryByRole('button')).to.not.exist
|
||||
})
|
||||
|
||||
it('does not display an editable input when the project name is double clicked', function () {
|
||||
render(<ProjectNameEditableLabel {...nonEditableProps} />)
|
||||
fireEvent.doubleClick(screen.getByText('test-project'))
|
||||
expect(screen.queryByRole('textbox')).to.not.exist
|
||||
})
|
||||
})
|
||||
})
|
@@ -0,0 +1,116 @@
|
||||
import { expect } from 'chai'
|
||||
import { screen } from '@testing-library/react'
|
||||
|
||||
import ToolbarHeader from '../../../../../frontend/js/features/editor-navigation-toolbar/components/toolbar-header'
|
||||
import { renderWithEditorContext } from '../../../helpers/render-with-context'
|
||||
|
||||
describe('<ToolbarHeader />', function () {
|
||||
const defaultProps = {
|
||||
onShowLeftMenuClick: () => {},
|
||||
toggleChatOpen: () => {},
|
||||
toggleReviewPanelOpen: () => {},
|
||||
toggleHistoryOpen: () => {},
|
||||
unreadMessageCount: 0,
|
||||
onlineUsers: [],
|
||||
goToUser: () => {},
|
||||
projectName: 'test project',
|
||||
renameProject: () => {},
|
||||
openShareModal: () => {},
|
||||
hasPublishPermissions: true,
|
||||
chatVisible: true,
|
||||
trackChangesVisible: true,
|
||||
handleChangeLayout: () => {},
|
||||
pdfLayout: 'sideBySide',
|
||||
view: 'editor',
|
||||
reattach: () => {},
|
||||
detach: () => {},
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache.set('ol-chatEnabled', true)
|
||||
})
|
||||
|
||||
describe('cobranding logo', function () {
|
||||
it('is not displayed by default', function () {
|
||||
renderWithEditorContext(<ToolbarHeader {...defaultProps} />)
|
||||
expect(screen.queryByRole('link', { name: 'variation' })).to.not.exist
|
||||
})
|
||||
|
||||
it('is displayed when cobranding data is available', function () {
|
||||
const props = {
|
||||
...defaultProps,
|
||||
cobranding: {
|
||||
brandVariationHomeUrl: 'http://cobranding',
|
||||
brandVariationName: 'variation',
|
||||
logoImgUrl: 'http://cobranding/logo',
|
||||
},
|
||||
}
|
||||
renderWithEditorContext(<ToolbarHeader {...props} />)
|
||||
screen.getByRole('link', { name: 'variation' })
|
||||
})
|
||||
})
|
||||
|
||||
describe('track changes toggle button', function () {
|
||||
it('is displayed by default', function () {
|
||||
renderWithEditorContext(<ToolbarHeader {...defaultProps} />)
|
||||
screen.getByText('Review')
|
||||
})
|
||||
|
||||
it('is not displayed when "trackChangesVisible" prop is set to false', function () {
|
||||
const props = {
|
||||
...defaultProps,
|
||||
trackChangesVisible: false,
|
||||
}
|
||||
renderWithEditorContext(<ToolbarHeader {...props} />)
|
||||
expect(screen.queryByText('Review')).to.not.exist
|
||||
})
|
||||
})
|
||||
|
||||
describe('History toggle button', function () {
|
||||
it('is displayed by default', function () {
|
||||
renderWithEditorContext(<ToolbarHeader {...defaultProps} />)
|
||||
screen.getByText('History')
|
||||
})
|
||||
|
||||
it('is not displayed when "isRestrictedTokenMember" prop is set to true', function () {
|
||||
const props = {
|
||||
...defaultProps,
|
||||
isRestrictedTokenMember: true,
|
||||
}
|
||||
renderWithEditorContext(<ToolbarHeader {...props} />)
|
||||
expect(screen.queryByText('History')).to.not.exist
|
||||
})
|
||||
})
|
||||
|
||||
describe('Chat toggle button', function () {
|
||||
it('is displayed by default', function () {
|
||||
renderWithEditorContext(<ToolbarHeader {...defaultProps} />)
|
||||
screen.getByText('Chat')
|
||||
})
|
||||
|
||||
it('is not displayed when "chatVisible" prop is set to false', function () {
|
||||
const props = {
|
||||
...defaultProps,
|
||||
chatVisible: false,
|
||||
}
|
||||
renderWithEditorContext(<ToolbarHeader {...props} />)
|
||||
expect(screen.queryByText('Chat')).to.not.exist
|
||||
})
|
||||
})
|
||||
|
||||
describe('Publish button', function () {
|
||||
it('is displayed by default', function () {
|
||||
renderWithEditorContext(<ToolbarHeader {...defaultProps} />)
|
||||
screen.getByText('Submit')
|
||||
})
|
||||
|
||||
it('is not displayed for users with no publish permissions', function () {
|
||||
const props = {
|
||||
...defaultProps,
|
||||
hasPublishPermissions: false,
|
||||
}
|
||||
renderWithEditorContext(<ToolbarHeader {...props} />)
|
||||
expect(screen.queryByText('Submit')).to.not.exist
|
||||
})
|
||||
})
|
||||
})
|
Reference in New Issue
Block a user