UNPKG

teletype-client-modified

Version:

I have modified the library developed by Atom to make it compatible with non-browser facility. I am using it only for experimentation purposes. I will remove this package post my experiment and raise a PR at Atom to finally merge this package so that this

272 lines (227 loc) 12.1 kB
const assert = require('assert') const {Disposable} = require('event-kit') const {startTestServer} = require('@atom/teletype-server') const {buildPeerPool, clearPeerPools} = require('./helpers/peer-pools') const condition = require('./helpers/condition') const setEqual = require('./helpers/set-equal') const FakePortalDelegate = require('./helpers/fake-portal-delegate') const Portal = require('../lib/portal') suite('Portal', () => { let server suiteSetup(async () => { server = await startTestServer() }) suiteTeardown(() => { return server.stop() }) setup(() => { return server.reset() }) teardown(() => { clearPeerPools() }) suite('join', () => { test('throws and disposes itself when a network error occurs', async () => { const peerPool = await buildPeerPool('guest', server) const portal = new Portal({id: 'id', hostPeerId: 'host', siteId: 2, peerPool}) portal.network.connectTo = function () { throw new Error('an error') } let error try { await portal.join() } catch (e) { error = e } assert.equal(error.message, 'an error') assert(portal.disposed) }) }) test('joining and leaving a portal', async () => { const hostPeerPool = await buildPeerPool('host', server) const guest1PeerPool = await buildPeerPool('guest1', server) const guest2PeerPool = await buildPeerPool('guest2', server) const hostPortal = await buildPortal('portal', hostPeerPool) const guest1Portal = await buildPortal('portal', guest1PeerPool, 'host') const guest2Portal = await buildPortal('portal', guest2PeerPool, 'host') await guest1Portal.join() await guest2Portal.join() assert(setEqual(hostPortal.getActiveSiteIds(), [1, 2, 3])) assert(setEqual(guest1Portal.getActiveSiteIds(), [1, 2, 3])) assert(setEqual(guest2Portal.getActiveSiteIds(), [1, 2, 3])) assert.deepEqual(hostPortal.testDelegate.joinEvents, [2, 3]) assert.deepEqual(guest1Portal.testDelegate.joinEvents, [3]) assert.deepEqual(guest2Portal.testDelegate.joinEvents, []) guest1Portal.dispose() await condition(() => ( setEqual(hostPortal.getActiveSiteIds(), [1, 3]) && setEqual(guest1Portal.getActiveSiteIds(), [2]) && setEqual(guest2Portal.getActiveSiteIds(), [1, 3]) )) assert.deepEqual(hostPortal.testDelegate.leaveEvents, [2]) assert.deepEqual(guest1Portal.testDelegate.leaveEvents, []) assert.deepEqual(guest2Portal.testDelegate.leaveEvents, [2]) // Ensure leave event is not emitted when the host disconnects. hostPortal.dispose() await condition(() => ( setEqual(hostPortal.getActiveSiteIds(), [1]) && setEqual(guest1Portal.getActiveSiteIds(), [2]) && setEqual(guest2Portal.getActiveSiteIds(), [3]) )) assert.deepEqual(hostPortal.testDelegate.leaveEvents, [2]) assert.deepEqual(guest1Portal.testDelegate.leaveEvents, []) assert.deepEqual(guest2Portal.testDelegate.leaveEvents, [2]) assert(guest2Portal.testDelegate.hasHostClosedPortal()) }) test('site identities', async () => { const hostIdentity = {login: 'host'} const guest1Identity = {login: 'guest1'} const guest2Identity = {login: 'guest2'} server.identityProvider.setIdentitiesByToken({ 'host-token': hostIdentity, 'guest1-token': guest1Identity, 'guest2-token': guest2Identity }) const hostPeerPool = await buildPeerPool('host', server) const guest1PeerPool = await buildPeerPool('guest1', server) const guest2PeerPool = await buildPeerPool('guest2', server) const hostPortal = await buildPortal('portal', hostPeerPool) const guest1Portal = await buildPortal('portal', guest1PeerPool, 'host') const guest2Portal = await buildPortal('portal', guest2PeerPool, 'host') await guest1Portal.join() await guest2Portal.join() assert.equal(hostPortal.getSiteIdentity(1).login, hostIdentity.login) assert.equal(hostPortal.getSiteIdentity(2).login, guest1Identity.login) assert.equal(hostPortal.getSiteIdentity(3).login, guest2Identity.login) assert.equal(guest1Portal.getSiteIdentity(1).login, hostIdentity.login) assert.equal(guest1Portal.getSiteIdentity(2).login, guest1Identity.login) assert.equal(guest1Portal.getSiteIdentity(3).login, guest2Identity.login) assert.equal(guest2Portal.getSiteIdentity(1).login, hostIdentity.login) assert.equal(guest2Portal.getSiteIdentity(2).login, guest1Identity.login) assert.equal(guest2Portal.getSiteIdentity(3).login, guest2Identity.login) }) test('notifying delegate of active position of other sites', async () => { const hostPeerPool = await buildPeerPool('host', server) const guestPeerPool = await buildPeerPool('guest', server) const hostPortal = await buildPortal('portal', hostPeerPool) const guestPortal = await buildPortal('portal', guestPeerPool, 'host') const joinPromise = guestPortal.join() await guestPortal.networkConnectionPromise const bufferProxy = await hostPortal.createBufferProxy({uri: 'uri', text: ''}) const editorProxy = await hostPortal.createEditorProxy({bufferProxy}) hostPortal.activateEditorProxy(editorProxy) // Guest has only partially joined, so it's not yet an active site. let activeSiteIds = Object.keys(hostPortal.testDelegate.activePositionsBySiteId) assert.deepEqual(activeSiteIds, ['1']) // When guest finally joins, it becomes an active site. await joinPromise activeSiteIds = Object.keys(hostPortal.testDelegate.activePositionsBySiteId) assert.deepEqual(activeSiteIds, ['1', '2']) }) suite('changing active editor proxy', () => { test('host only notifies guests when active editor proxy has changed', async () => { const hostPeerPool = await buildPeerPool('host', server) const guestPeerPool = await buildPeerPool('guest', server) const hostPortal = await buildPortal('portal', hostPeerPool) const guestPortal = await buildPortal('portal', guestPeerPool, 'host') await guestPortal.join() guestPortal.testDelegate.tetherEditorProxyChangeCount = 0 // Don't notify guests when setting the active editor proxy to the same value it currently has. hostPortal.activateEditorProxy(null) // Set the active editor proxy to a different value to ensure guests are notified only of this change. const originalBufferProxy = await hostPortal.createBufferProxy({uri: 'original-uri', text: ''}) const originalEditorProxy = await hostPortal.createEditorProxy({bufferProxy: originalBufferProxy}) hostPortal.activateEditorProxy(originalEditorProxy) await condition(() => ( guestPortal.testDelegate.getTetherBufferProxyURI() === 'original-uri' && guestPortal.testDelegate.tetherEditorProxyChangeCount === 1 )) }) test('guest gracefully handles race conditions', async () => { const hostPeerPool = await buildPeerPool('host', server) const guestPeerPool = await buildPeerPool('guest', server) const hostPortal = await buildPortal('portal', hostPeerPool) const guestPortal = await buildPortal('portal', guestPeerPool, 'host') await guestPortal.join() guestPortal.testDelegate.tetherEditorProxyChangeCount = 0 // Ensure no race condition occurs on the guest when fetching new editor // proxies for the first time and, at the same time, receiving a request // to switch to a previous value of active editor proxy. const newBufferProxy = await hostPortal.createBufferProxy({uri: 'new-uri', text: ''}) const newEditorProxy = await hostPortal.createEditorProxy({bufferProxy: newBufferProxy}) hostPortal.activateEditorProxy(newEditorProxy) hostPortal.activateEditorProxy(null) await condition(() => ( guestPortal.testDelegate.getTetherBufferProxyURI() === null && guestPortal.testDelegate.tetherEditorProxyChangeCount === 2 )) }) test('guest gracefully handles switching to an editor proxy whose buffer has already been destroyed', async () => { const hostPeerPool = await buildPeerPool('host', server) const guestPeerPool = await buildPeerPool('guest', server) const hostPortal = await buildPortal('portal', hostPeerPool) const guestPortal = await buildPortal('portal', guestPeerPool, 'host') await guestPortal.join() guestPortal.testDelegate.tetherEditorProxyChangeCount = 0 const bufferProxy1 = await hostPortal.createBufferProxy({uri: 'uri-1', text: ''}) const editorProxy1 = await hostPortal.createEditorProxy({bufferProxy: bufferProxy1}) const bufferProxy2 = await hostPortal.createBufferProxy({uri: 'uri-2', text: ''}) const editorProxy2 = await hostPortal.createEditorProxy({bufferProxy: bufferProxy2}) hostPortal.activateEditorProxy(editorProxy1) bufferProxy1.dispose() hostPortal.activateEditorProxy(null) hostPortal.activateEditorProxy(editorProxy2) await condition(() => ( guestPortal.testDelegate.getTetherBufferProxyURI() === 'uri-2' && guestPortal.testDelegate.tetherEditorProxyChangeCount === 1 )) }) test('guest gracefully handles switching to an editor proxy that has already been destroyed', async () => { const hostPeerPool = await buildPeerPool('host', server) const guestPeerPool = await buildPeerPool('guest', server) const hostPortal = await buildPortal('portal', hostPeerPool) const guestPortal = await buildPortal('portal', guestPeerPool, 'host') await guestPortal.join() guestPortal.testDelegate.tetherEditorProxyChangeCount = 0 const bufferProxy1 = await hostPortal.createBufferProxy({uri: 'uri-1', text: ''}) const editorProxy1 = await hostPortal.createEditorProxy({bufferProxy: bufferProxy1}) const bufferProxy2 = await hostPortal.createBufferProxy({uri: 'uri-2', text: ''}) const editorProxy2 = await hostPortal.createEditorProxy({bufferProxy: bufferProxy2}) hostPortal.activateEditorProxy(editorProxy1) editorProxy1.dispose() hostPortal.activateEditorProxy(null) hostPortal.activateEditorProxy(editorProxy2) await condition(() => ( guestPortal.testDelegate.getTetherBufferProxyURI() === 'uri-2' && guestPortal.testDelegate.tetherEditorProxyChangeCount === 1 )) }) test('host gracefully handles guests switching to an editor that has already been destroyed', async () => { const hostPeerPool = await buildPeerPool('host', server) const guestPeerPool = await buildPeerPool('guest', server) const hostPortal = await buildPortal('portal', hostPeerPool) const guestPortal = await buildPortal('portal', guestPeerPool, 'host') await guestPortal.join() const hostBufferProxy1 = await hostPortal.createBufferProxy({uri: 'uri-1', text: ''}) const hostEditorProxy1 = await hostPortal.createEditorProxy({bufferProxy: hostBufferProxy1}) hostPortal.activateEditorProxy(hostEditorProxy1) await condition(() => guestPortal.testDelegate.getTetherBufferProxyURI() === 'uri-1') const guestEditorProxy1 = guestPortal.testDelegate.getTetherEditorProxy() hostEditorProxy1.dispose() guestPortal.activateEditorProxy(null) guestPortal.activateEditorProxy(guestEditorProxy1) const hostBufferProxy2 = await hostPortal.createBufferProxy({uri: 'uri-2', text: ''}) const hostEditorProxy2 = await hostPortal.createEditorProxy({bufferProxy: hostBufferProxy2}) hostPortal.activateEditorProxy(hostEditorProxy2) await condition(() => guestPortal.getEditorProxiesMetadata().find((e) => e.bufferProxyURI === 'uri-2')) }) }) async function buildPortal (portalId, peerPool, hostPeerId) { const siteId = hostPeerId == null ? 1 : null const portal = new Portal({id: portalId, hostPeerId, siteId, peerPool}) await portal.initialize() portal.testDelegate = new FakePortalDelegate() await portal.setDelegate(portal.testDelegate) return portal } })