overleaf/services/web/test/frontend/shared/hooks/use-detach-layout.test.js

211 lines
6.9 KiB
JavaScript
Raw Normal View History

import { waitFor } from '@testing-library/react'
import { act } from '@testing-library/react-hooks'
import { expect } from 'chai'
import sinon from 'sinon'
import { renderHookWithEditorContext } from '../../helpers/render-with-context'
import sysendTestHelper from '../../helpers/sysend'
import useDetachLayout from '../../../../frontend/js/shared/hooks/use-detach-layout'
describe('useDetachLayout', function () {
let openStub
let closeStub
beforeEach(function () {
window.metaAttributesCache = new Map()
openStub = sinon.stub(window, 'open')
closeStub = sinon.stub(window, 'close')
})
afterEach(function () {
window.metaAttributesCache = new Map()
openStub.restore()
closeStub.restore()
})
it('detaching', async function () {
// 1. create hook in normal mode
const { result } = renderHookWithEditorContext(() => useDetachLayout())
expect(result.current.reattach).to.be.a('function')
expect(result.current.detach).to.be.a('function')
expect(result.current.isLinked).to.be.false
expect(result.current.isLinking).to.be.false
expect(result.current.role).to.be.null
// 2. detach
act(() => {
result.current.detach()
})
expect(result.current.isLinked).to.be.false
expect(result.current.isLinking).to.be.true
expect(result.current.role).to.equal('detacher')
sinon.assert.calledOnce(openStub)
sinon.assert.calledWith(
openStub,
'https://www.test-overleaf.com/detached',
'_blank'
)
})
it('detacher role', async function () {
sysendTestHelper.spy.broadcast.resetHistory()
window.metaAttributesCache.set('ol-detachRole', 'detacher')
// 1. create hook in detacher mode
const { result } = renderHookWithEditorContext(() => useDetachLayout())
expect(result.current.reattach).to.be.a('function')
expect(result.current.detach).to.be.a('function')
expect(result.current.isLinked).to.be.false
expect(result.current.isLinking).to.be.false
expect(result.current.role).to.equal('detacher')
const broadcastMessagesCount =
sysendTestHelper.getAllBroacastMessages().length
// 2. simulate connected detached tab
sysendTestHelper.spy.broadcast.resetHistory()
sysendTestHelper.receiveMessage({
role: 'detached',
event: 'connected',
})
expect(sysendTestHelper.getLastBroacastMessage()).to.deep.equal({
role: 'detacher',
event: 'up',
})
expect(result.current.isLinked).to.be.true
expect(result.current.isLinking).to.be.false
expect(result.current.role).to.equal('detacher')
// check that all message were re-broadcast for the new tab
await nextTick() // necessary to ensure all event handler have run
await waitFor(() => {
const reBroadcastMessagesCount =
sysendTestHelper.getAllBroacastMessages().length
expect(reBroadcastMessagesCount).to.equal(broadcastMessagesCount)
})
// 3. simulate closed detached tab
sysendTestHelper.spy.broadcast.resetHistory()
sysendTestHelper.receiveMessage({
role: 'detached',
event: 'closed',
})
expect(result.current.isLinked).to.be.false
expect(result.current.isLinking).to.be.false
expect(result.current.role).to.equal('detacher')
// 4. simulate up detached tab
sysendTestHelper.spy.broadcast.resetHistory()
sysendTestHelper.receiveMessage({
role: 'detached',
event: 'up',
})
expect(result.current.isLinked).to.be.true
expect(result.current.isLinking).to.be.false
expect(result.current.role).to.equal('detacher')
// 5. reattach
sysendTestHelper.spy.broadcast.resetHistory()
act(() => {
result.current.reattach()
})
expect(result.current.isLinked).to.be.false
expect(result.current.isLinking).to.be.false
expect(result.current.role).to.be.null
expect(sysendTestHelper.getLastBroacastMessage()).to.deep.equal({
role: 'detacher',
event: 'reattach',
})
})
it('reset detacher role when other detacher tab connects', function () {
window.metaAttributesCache.set('ol-detachRole', 'detacher')
// 1. create hook in detacher mode
const { result } = renderHookWithEditorContext(() => useDetachLayout())
expect(result.current.reattach).to.be.a('function')
expect(result.current.detach).to.be.a('function')
expect(result.current.isLinked).to.be.false
expect(result.current.isLinking).to.be.false
expect(result.current.role).to.equal('detacher')
// 2. simulate other detacher tab
sysendTestHelper.receiveMessage({
role: 'detacher',
event: 'up',
})
expect(result.current.isRedundant).to.be.true
expect(result.current.role).to.equal(null)
})
it('detached role', async function () {
window.metaAttributesCache.set('ol-detachRole', 'detached')
// 1. create hook in detached mode
const { result } = renderHookWithEditorContext(() => useDetachLayout())
expect(result.current.reattach).to.be.a('function')
expect(result.current.detach).to.be.a('function')
expect(result.current.isLinked).to.be.false
expect(result.current.isLinking).to.be.false
expect(result.current.role).to.equal('detached')
// 2. simulate up detacher tab
sysendTestHelper.spy.broadcast.resetHistory()
sysendTestHelper.receiveMessage({
role: 'detacher',
event: 'up',
})
expect(result.current.isLinked).to.be.true
expect(result.current.isLinking).to.be.false
expect(result.current.role).to.equal('detached')
// 3. simulate closed detacher tab
sysendTestHelper.spy.broadcast.resetHistory()
sysendTestHelper.receiveMessage({
role: 'detacher',
event: 'closed',
})
expect(result.current.isLinked).to.be.false
expect(result.current.isLinking).to.be.false
expect(result.current.role).to.equal('detached')
// 4. simulate up detacher tab
sysendTestHelper.spy.broadcast.resetHistory()
sysendTestHelper.receiveMessage({
role: 'detacher',
event: 'up',
})
expect(result.current.isLinked).to.be.true
expect(result.current.isLinking).to.be.false
expect(result.current.role).to.equal('detached')
// 5. simulate closed detached tab
sysendTestHelper.spy.broadcast.resetHistory()
sysendTestHelper.receiveMessage({
role: 'detached',
event: 'closed',
})
expect(result.current.isLinked).to.be.true
expect(result.current.isLinking).to.be.false
expect(result.current.role).to.equal('detached')
expect(sysendTestHelper.getLastBroacastMessage()).to.deep.equal({
role: 'detached',
event: 'up',
})
// 6. simulate reattach event
sysendTestHelper.spy.broadcast.resetHistory()
sysendTestHelper.receiveMessage({
role: 'detacher',
event: 'reattach',
})
expect(result.current.isLinked).to.be.false
expect(result.current.isLinking).to.be.false
expect(result.current.role).to.equal('detached')
sinon.assert.called(closeStub)
})
})
const nextTick = () => {
return new Promise(resolve => {
setTimeout(resolve)
})
}