mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-15 14:43:46 +01:00
Remove sysend dependency (#10852)
GitOrigin-RevId: c3d9601256af8720ab41264609cb5c5c810afbba
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
import { FC } from 'react'
|
||||
import useDetachAction from '../../../../frontend/js/shared/hooks/use-detach-action'
|
||||
import { detachChannel, testDetachChannel } from '../../helpers/detach-channel'
|
||||
import { EditorProviders } from '../../helpers/editor-providers'
|
||||
|
||||
const DetachActionTest: FC<{
|
||||
actionName: string
|
||||
actionFunction: () => void
|
||||
handleClick: (trigger: (value: any) => void) => void
|
||||
}> = ({ actionName, actionFunction, handleClick }) => {
|
||||
const trigger = useDetachAction(
|
||||
actionName,
|
||||
actionFunction,
|
||||
'detacher',
|
||||
'detached'
|
||||
)
|
||||
|
||||
return (
|
||||
<button id="trigger" onClick={() => handleClick(trigger)}>
|
||||
trigger
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
describe('useDetachAction', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
})
|
||||
|
||||
it('broadcast message as sender', function () {
|
||||
window.metaAttributesCache.set('ol-detachRole', 'detacher')
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders>
|
||||
<DetachActionTest
|
||||
actionName="some-action"
|
||||
actionFunction={cy.stub().as('actionFunction')}
|
||||
handleClick={trigger => trigger('foo')}
|
||||
/>
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.spy(detachChannel, 'postMessage').as('postDetachMessage')
|
||||
cy.get('#trigger').click()
|
||||
cy.get('@postDetachMessage').should('be.calledWith', {
|
||||
role: 'detacher',
|
||||
event: 'action-some-action',
|
||||
data: { args: ['foo'] },
|
||||
})
|
||||
cy.get('@actionFunction').should('not.be.called')
|
||||
})
|
||||
|
||||
it('call function as non-sender', function () {
|
||||
cy.mount(
|
||||
<EditorProviders>
|
||||
<DetachActionTest
|
||||
actionName="some-action"
|
||||
actionFunction={cy.stub().as('actionFunction')}
|
||||
handleClick={trigger => trigger('foo')}
|
||||
/>
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.spy(detachChannel, 'postMessage').as('postDetachMessage')
|
||||
cy.get('#trigger').click()
|
||||
cy.get('@postDetachMessage').should('not.be.called')
|
||||
cy.get('@actionFunction').should('be.calledWith', 'foo')
|
||||
})
|
||||
|
||||
it('receive message and call function as target', function () {
|
||||
window.metaAttributesCache.set('ol-detachRole', 'detached')
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders>
|
||||
<DetachActionTest
|
||||
actionName="some-action"
|
||||
actionFunction={cy.stub().as('actionFunction')}
|
||||
handleClick={trigger => trigger('foo')}
|
||||
/>
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.wrap(null).then(() => {
|
||||
testDetachChannel.postMessage({
|
||||
role: 'detached',
|
||||
event: 'action-some-action',
|
||||
data: { args: ['foo'] },
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('@actionFunction').should('be.calledWith', 'foo')
|
||||
})
|
||||
|
||||
it('receive message and does not call function as non-target', function () {
|
||||
window.metaAttributesCache.set('ol-detachRole', 'detacher')
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders>
|
||||
<DetachActionTest
|
||||
actionName="some-action"
|
||||
actionFunction={cy.stub().as('actionFunction')}
|
||||
handleClick={trigger => trigger('foo')}
|
||||
/>
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.wrap(null).then(() => {
|
||||
testDetachChannel.postMessage({
|
||||
role: 'detached',
|
||||
event: 'action-some-action',
|
||||
data: { args: [] },
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('@actionFunction').should('not.be.called')
|
||||
})
|
||||
})
|
||||
@@ -1,82 +0,0 @@
|
||||
import sinon from 'sinon'
|
||||
import { expect } from 'chai'
|
||||
import { renderHookWithEditorContext } from '../../helpers/render-with-context'
|
||||
import sysendTestHelper from '../../helpers/sysend'
|
||||
import useDetachAction from '../../../../frontend/js/shared/hooks/use-detach-action'
|
||||
|
||||
const actionName = 'some-action'
|
||||
const actionFunction = sinon.stub()
|
||||
|
||||
describe('useDetachAction', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
actionFunction.reset()
|
||||
})
|
||||
|
||||
it('broadcast message as sender', async function () {
|
||||
window.metaAttributesCache.set('ol-detachRole', 'detacher')
|
||||
const { result } = renderHookWithEditorContext(() =>
|
||||
useDetachAction(actionName, actionFunction, 'detacher', 'detached')
|
||||
)
|
||||
const triggerFn = result.current
|
||||
sysendTestHelper.resetHistory()
|
||||
|
||||
triggerFn('param')
|
||||
|
||||
expect(sysendTestHelper.getLastBroacastMessage()).to.deep.equal({
|
||||
role: 'detacher',
|
||||
event: `action-${actionName}`,
|
||||
data: { args: ['param'] },
|
||||
})
|
||||
|
||||
sinon.assert.notCalled(actionFunction)
|
||||
})
|
||||
|
||||
it('call function as non-sender', async function () {
|
||||
const { result } = renderHookWithEditorContext(() =>
|
||||
useDetachAction(actionName, actionFunction, 'detacher', 'detached')
|
||||
)
|
||||
const triggerFn = result.current
|
||||
sysendTestHelper.resetHistory()
|
||||
|
||||
triggerFn('param')
|
||||
|
||||
expect(sysendTestHelper.getDetachCalls('broadcast').length).to.equal(0)
|
||||
|
||||
sinon.assert.calledWith(actionFunction, 'param')
|
||||
})
|
||||
|
||||
it('receive message and call function as target', async function () {
|
||||
window.metaAttributesCache.set('ol-detachRole', 'detached')
|
||||
renderHookWithEditorContext(() =>
|
||||
useDetachAction(actionName, actionFunction, 'detacher', 'detached')
|
||||
)
|
||||
|
||||
sysendTestHelper.receiveMessage({
|
||||
role: 'detached',
|
||||
event: `action-${actionName}`,
|
||||
data: { args: ['param'] },
|
||||
})
|
||||
|
||||
sinon.assert.calledWith(actionFunction, 'param')
|
||||
})
|
||||
|
||||
it('receive message and does not call function as non-target', async function () {
|
||||
window.metaAttributesCache.set('ol-detachRole', 'detacher')
|
||||
renderHookWithEditorContext(() =>
|
||||
useDetachAction(actionName, actionFunction, 'detacher', 'detached')
|
||||
)
|
||||
|
||||
sysendTestHelper.receiveMessage({
|
||||
role: 'detached',
|
||||
event: `action-${actionName}`,
|
||||
data: { args: [] },
|
||||
})
|
||||
|
||||
sinon.assert.notCalled(actionFunction)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,244 @@
|
||||
import useDetachLayout from '../../../../frontend/js/shared/hooks/use-detach-layout'
|
||||
import { detachChannel, testDetachChannel } from '../../helpers/detach-channel'
|
||||
import { EditorProviders } from '../../helpers/editor-providers'
|
||||
import { Button, Checkbox, ControlLabel, FormGroup } from 'react-bootstrap'
|
||||
|
||||
const DetachLayoutTest = () => {
|
||||
const { role, reattach, detach, isLinked, isLinking, isRedundant } =
|
||||
useDetachLayout()
|
||||
|
||||
return (
|
||||
<fieldset>
|
||||
<legend>
|
||||
role: <span id="role">{role || 'none'}</span>
|
||||
</legend>
|
||||
<FormGroup>
|
||||
<Checkbox id="isLinked" inline checked={isLinked} readOnly />
|
||||
<ControlLabel>linked</ControlLabel>
|
||||
</FormGroup>
|
||||
<FormGroup>
|
||||
<Checkbox id="isLinking" inline checked={isLinking} readOnly />
|
||||
<ControlLabel>linking</ControlLabel>
|
||||
</FormGroup>
|
||||
<FormGroup>
|
||||
<Checkbox id="isRedundant" inline checked={isRedundant} readOnly />
|
||||
<ControlLabel>redundant</ControlLabel>
|
||||
</FormGroup>
|
||||
<Button id="reattach" onClick={reattach}>
|
||||
reattach
|
||||
</Button>
|
||||
<Button id="detach" onClick={detach}>
|
||||
detach
|
||||
</Button>
|
||||
</fieldset>
|
||||
)
|
||||
}
|
||||
|
||||
describe('useDetachLayout', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
cy.stub(window, 'open').as('openWindow')
|
||||
cy.stub(window, 'close').as('closeWindow')
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
})
|
||||
|
||||
it('detaching', function () {
|
||||
// 1. create hook in normal mode
|
||||
cy.mount(
|
||||
<EditorProviders>
|
||||
<DetachLayoutTest />
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.get('#isLinked').should('not.be.checked')
|
||||
cy.get('#isLinking').should('not.be.checked')
|
||||
cy.get('#role').should('have.text', 'none')
|
||||
|
||||
// 2. detach
|
||||
cy.get('#detach').click()
|
||||
cy.get('@openWindow').should(
|
||||
'be.calledOnceWith',
|
||||
Cypress.sinon.match(/\/detached$/),
|
||||
'_blank'
|
||||
)
|
||||
cy.get('#isLinked').should('not.be.checked')
|
||||
cy.get('#isLinking').should('be.checked')
|
||||
cy.get('#role').should('have.text', 'detacher')
|
||||
})
|
||||
|
||||
it('detacher role', function () {
|
||||
// 1. create hook in detacher mode
|
||||
window.metaAttributesCache.set('ol-detachRole', 'detacher')
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders>
|
||||
<DetachLayoutTest />
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.get('#isLinked').should('not.be.checked')
|
||||
cy.get('#isLinking').should('not.be.checked')
|
||||
cy.get('#role').should('have.text', 'detacher')
|
||||
|
||||
cy.spy(detachChannel, 'postMessage').as('postDetachMessage')
|
||||
|
||||
cy.wrap(null).then(() => {
|
||||
testDetachChannel.postMessage({
|
||||
role: 'detached',
|
||||
event: 'connected',
|
||||
})
|
||||
})
|
||||
|
||||
// 2. simulate connected detached tab
|
||||
cy.get('@postDetachMessage').should('be.calledWith', {
|
||||
role: 'detacher',
|
||||
event: 'up',
|
||||
})
|
||||
|
||||
cy.get('#isLinked').should('be.checked')
|
||||
cy.get('#isLinking').should('not.be.checked')
|
||||
cy.get('#role').should('have.text', 'detacher')
|
||||
|
||||
// 3. simulate closed detached tab
|
||||
cy.wrap(null).then(() => {
|
||||
testDetachChannel.postMessage({
|
||||
role: 'detached',
|
||||
event: 'closed',
|
||||
})
|
||||
})
|
||||
cy.get('#isLinked').should('not.be.checked')
|
||||
cy.get('#isLinking').should('not.be.checked')
|
||||
cy.get('#role').should('have.text', 'detacher')
|
||||
|
||||
// 4. simulate up detached tab
|
||||
cy.wrap(null).then(() => {
|
||||
testDetachChannel.postMessage({
|
||||
role: 'detached',
|
||||
event: 'up',
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('#isLinked').should('be.checked')
|
||||
cy.get('#isLinking').should('not.be.checked')
|
||||
cy.get('#role').should('have.text', 'detacher')
|
||||
|
||||
// 5. reattach
|
||||
cy.get('@postDetachMessage').invoke('resetHistory')
|
||||
cy.get('#reattach').click()
|
||||
|
||||
cy.get('#isLinked').should('not.be.checked')
|
||||
cy.get('#isLinking').should('not.be.checked')
|
||||
cy.get('#role').should('have.text', 'none')
|
||||
cy.get('@postDetachMessage').should('be.calledWith', {
|
||||
role: 'detacher',
|
||||
event: 'reattach',
|
||||
})
|
||||
})
|
||||
|
||||
it('reset detacher role when other detacher tab connects', function () {
|
||||
// 1. create hook in detacher mode
|
||||
window.metaAttributesCache.set('ol-detachRole', 'detacher')
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders>
|
||||
<DetachLayoutTest />
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.get('#isLinked').should('not.be.checked')
|
||||
cy.get('#isLinking').should('not.be.checked')
|
||||
cy.get('#role').should('have.text', 'detacher')
|
||||
|
||||
// 2. simulate other detacher tab
|
||||
cy.wrap(null).then(() => {
|
||||
testDetachChannel.postMessage({
|
||||
role: 'detacher',
|
||||
event: 'up',
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('#isRedundant').should('be.checked')
|
||||
cy.get('#role').should('have.text', 'none')
|
||||
})
|
||||
|
||||
it('detached role', function () {
|
||||
// 1. create hook in detached mode
|
||||
window.metaAttributesCache.set('ol-detachRole', 'detached')
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders>
|
||||
<DetachLayoutTest />
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.get('#isLinked').should('not.be.checked')
|
||||
cy.get('#isLinking').should('not.be.checked')
|
||||
cy.get('#role').should('have.text', 'detached')
|
||||
|
||||
// 2. simulate up detacher tab
|
||||
cy.wrap(null).then(() => {
|
||||
testDetachChannel.postMessage({
|
||||
role: 'detacher',
|
||||
event: 'up',
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('#isLinked').should('be.checked')
|
||||
cy.get('#isLinking').should('not.be.checked')
|
||||
cy.get('#role').should('have.text', 'detached')
|
||||
|
||||
// 3. simulate closed detacher tab
|
||||
cy.wrap(null).then(() => {
|
||||
testDetachChannel.postMessage({
|
||||
role: 'detacher',
|
||||
event: 'closed',
|
||||
})
|
||||
})
|
||||
cy.get('#isLinked').should('not.be.checked')
|
||||
cy.get('#isLinking').should('not.be.checked')
|
||||
cy.get('#role').should('have.text', 'detached')
|
||||
|
||||
// 4. simulate up detacher tab
|
||||
cy.wrap(null).then(() => {
|
||||
testDetachChannel.postMessage({
|
||||
role: 'detacher',
|
||||
event: 'up',
|
||||
})
|
||||
})
|
||||
cy.get('#isLinked').should('be.checked')
|
||||
cy.get('#isLinking').should('not.be.checked')
|
||||
cy.get('#role').should('have.text', 'detached')
|
||||
|
||||
// 5. simulate closed detached tab
|
||||
cy.spy(detachChannel, 'postMessage').as('postDetachMessage')
|
||||
cy.wrap(null).then(() => {
|
||||
testDetachChannel.postMessage({
|
||||
role: 'detached',
|
||||
event: 'closed',
|
||||
})
|
||||
})
|
||||
cy.get('#isLinked').should('be.checked')
|
||||
cy.get('#isLinking').should('not.be.checked')
|
||||
cy.get('#role').should('have.text', 'detached')
|
||||
cy.get('@postDetachMessage').should('be.calledWith', {
|
||||
role: 'detached',
|
||||
event: 'up',
|
||||
})
|
||||
|
||||
// 6. simulate reattach event
|
||||
cy.get('@postDetachMessage').invoke('resetHistory')
|
||||
cy.wrap(null).then(() => {
|
||||
testDetachChannel.postMessage({
|
||||
role: 'detacher',
|
||||
event: 'reattach',
|
||||
})
|
||||
})
|
||||
cy.get('#isLinked').should('not.be.checked')
|
||||
cy.get('#isLinking').should('not.be.checked')
|
||||
cy.get('#role').should('have.text', 'detached')
|
||||
cy.get('@closeWindow').should('be.called')
|
||||
})
|
||||
})
|
||||
@@ -1,210 +0,0 @@
|
||||
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)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
import { FC } from 'react'
|
||||
import useDetachState from '../../../../frontend/js/shared/hooks/use-detach-state'
|
||||
import { EditorProviders } from '../../helpers/editor-providers'
|
||||
import { detachChannel, testDetachChannel } from '../../helpers/detach-channel'
|
||||
|
||||
const DetachStateTest: FC<{
|
||||
stateKey: string
|
||||
defaultValue: any
|
||||
senderRole?: string
|
||||
targetRole?: string
|
||||
handleClick: (setValue: (value: any) => void) => void
|
||||
}> = ({ stateKey, defaultValue, handleClick, senderRole, targetRole }) => {
|
||||
const [value, setValue] = useDetachState(
|
||||
stateKey,
|
||||
defaultValue,
|
||||
senderRole,
|
||||
targetRole
|
||||
)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div id="value">{value}</div>
|
||||
<button id="setValue" onClick={() => handleClick(setValue)}>
|
||||
set value
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
describe('useDetachState', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
})
|
||||
|
||||
it('create and update state', function () {
|
||||
cy.mount(
|
||||
<EditorProviders>
|
||||
<DetachStateTest
|
||||
stateKey="some-key"
|
||||
defaultValue="foobar"
|
||||
handleClick={setValue => {
|
||||
setValue('barbaz')
|
||||
}}
|
||||
/>
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.get('#value').should('have.text', 'foobar')
|
||||
cy.get('#setValue').click()
|
||||
cy.get('#value').should('have.text', 'barbaz')
|
||||
})
|
||||
|
||||
it('broadcast message as sender', function () {
|
||||
window.metaAttributesCache.set('ol-detachRole', 'detacher')
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders>
|
||||
<DetachStateTest
|
||||
stateKey="some-key"
|
||||
defaultValue={null}
|
||||
senderRole="detacher"
|
||||
targetRole="detached"
|
||||
handleClick={setValue => {
|
||||
setValue('barbaz1')
|
||||
}}
|
||||
/>
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.spy(detachChannel, 'postMessage').as('postDetachMessage')
|
||||
cy.get('#setValue').click()
|
||||
cy.get('@postDetachMessage').should('be.calledWith', {
|
||||
role: 'detacher',
|
||||
event: 'state-some-key',
|
||||
data: { value: 'barbaz1' },
|
||||
})
|
||||
})
|
||||
|
||||
it('receive message as target', function () {
|
||||
window.metaAttributesCache.set('ol-detachRole', 'detached')
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders>
|
||||
<DetachStateTest
|
||||
stateKey="some-key"
|
||||
defaultValue={null}
|
||||
senderRole="detacher"
|
||||
targetRole="detached"
|
||||
handleClick={() => {}}
|
||||
/>
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.wrap(null).then(() => {
|
||||
testDetachChannel.postMessage({
|
||||
role: 'detached',
|
||||
event: 'state-some-key',
|
||||
data: { value: 'barbaz2' },
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('#value').should('have.text', 'barbaz2')
|
||||
})
|
||||
})
|
||||
@@ -1,68 +0,0 @@
|
||||
import { act } from '@testing-library/react-hooks'
|
||||
import { expect } from 'chai'
|
||||
import { renderHookWithEditorContext } from '../../helpers/render-with-context'
|
||||
import sysendTestHelper from '../../helpers/sysend'
|
||||
import useDetachState from '../../../../frontend/js/shared/hooks/use-detach-state'
|
||||
|
||||
const stateKey = 'some-key'
|
||||
|
||||
describe('useDetachState', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
})
|
||||
|
||||
it('create and update state', async function () {
|
||||
const defaultValue = 'foobar'
|
||||
const { result } = renderHookWithEditorContext(() =>
|
||||
useDetachState(stateKey, defaultValue)
|
||||
)
|
||||
const [value, setValue] = result.current
|
||||
expect(value).to.equal(defaultValue)
|
||||
expect(setValue).to.be.a('function')
|
||||
|
||||
const newValue = 'barbaz'
|
||||
act(() => {
|
||||
setValue(newValue)
|
||||
})
|
||||
expect(result.current[0]).to.equal(newValue)
|
||||
})
|
||||
|
||||
it('broadcast message as sender', async function () {
|
||||
window.metaAttributesCache.set('ol-detachRole', 'detacher')
|
||||
const { result } = renderHookWithEditorContext(() =>
|
||||
useDetachState(stateKey, null, 'detacher', 'detached')
|
||||
)
|
||||
const [, setValue] = result.current
|
||||
sysendTestHelper.resetHistory()
|
||||
|
||||
const newValue = 'barbaz'
|
||||
act(() => {
|
||||
setValue(newValue)
|
||||
})
|
||||
expect(sysendTestHelper.getLastBroacastMessage()).to.deep.equal({
|
||||
role: 'detacher',
|
||||
event: `state-${stateKey}`,
|
||||
data: { value: newValue },
|
||||
})
|
||||
})
|
||||
|
||||
it('receive message as target', async function () {
|
||||
window.metaAttributesCache.set('ol-detachRole', 'detached')
|
||||
const { result } = renderHookWithEditorContext(() =>
|
||||
useDetachState(stateKey, null, 'detacher', 'detached')
|
||||
)
|
||||
|
||||
const newValue = 'barbaz'
|
||||
sysendTestHelper.receiveMessage({
|
||||
role: 'detached',
|
||||
event: `state-${stateKey}`,
|
||||
data: { value: newValue },
|
||||
})
|
||||
|
||||
expect(result.current[0]).to.equal(newValue)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user