How to use buildPackage method in Cypress

Best JavaScript code snippet using cypress

teletype-package.test.js

Source:teletype-package.test.js Github

copy

Full Screen

...46    await atomEnvironments.destroyAtomEnvironments()47  })48  test('sharing and joining a portal', async function () {49    const hostEnv = buildAtomEnvironment()50    const hostPackage = await buildPackage(hostEnv)51    const guestEnv = buildAtomEnvironment()52    const guestPackage = await buildPackage(guestEnv)53    // Ensure we don't emit an add event more than once for a given guest editor54    const observedGuestItems = new Set()55    guestEnv.workspace.onDidAddPaneItem(({item}) => {56      assert(!observedGuestItems.has(item))57      observedGuestItems.add(item)58    })59    const portalId = (await hostPackage.sharePortal()).id60    guestPackage.joinPortal(portalId)61    const hostEditor1 = await hostEnv.workspace.open(temp.path({extension: '.js'}))62    hostEditor1.setText('const hello = "world"')63    hostEditor1.setCursorBufferPosition([0, 4])64    let guestEditor1 = await getNextActiveTextEditorPromise(guestEnv)65    assert.equal(guestEditor1.getText(), 'const hello = "world"')66    assert(!guestEditor1.isModified())67    await condition(() => deepEqual(getCursorDecoratedRanges(hostEditor1), getCursorDecoratedRanges(guestEditor1)))68    hostEditor1.setSelectedBufferRanges([69      [[0, 0], [0, 2]],70      [[0, 4], [0, 6]]71    ])72    guestEditor1.setSelectedBufferRanges([73      [[0, 1], [0, 3]],74      [[0, 5], [0, 7]]75    ])76    await condition(() => deepEqual(getCursorDecoratedRanges(hostEditor1), getCursorDecoratedRanges(guestEditor1)))77    await timeout(guestPackage.tetherDisconnectWindow)78    const hostEditor2 = await hostEnv.workspace.open(temp.path({extension: '.md'}))79    hostEditor2.setText('# Hello, World')80    hostEditor2.setCursorBufferPosition([0, 2])81    const guestEditor2 = await getNextActiveTextEditorPromise(guestEnv)82    assert.equal(guestEditor2.getText(), '# Hello, World')83    await condition(() => deepEqual(getCursorDecoratedRanges(hostEditor2), getCursorDecoratedRanges(guestEditor2)))84    hostEnv.workspace.paneForItem(hostEditor1).activateItem(hostEditor1)85    guestEditor1 = await getNextActiveTextEditorPromise(guestEnv)86    assert.equal(guestEditor1.getText(), 'const hello = "world"')87    assert(!guestEditor1.isModified())88    await condition(() => deepEqual(getCursorDecoratedRanges(hostEditor1), getCursorDecoratedRanges(guestEditor1)))89    assert.equal(observedGuestItems.size, 2)90  })91  suite('portal URIs', () => {92    function handleURI (pack, uri) {93      return pack.handleURI(url.parse(uri), uri)94    }95    test('opening URI for active portal', async () => {96      const hostEnv = buildAtomEnvironment()97      const hostPackage = await buildPackage(hostEnv)98      const guestEnv = buildAtomEnvironment({askBeforeJoiningPortalViaExternalApp: false})99      const guestPackage = await buildPackage(guestEnv)100      const hostPortal = await hostPackage.sharePortal()101      const uri = `atom://teletype/portal/${hostPortal.id}`102      await hostEnv.workspace.open()103      const guestPortal = await handleURI(guestPackage, uri)104      assert.equal(guestPortal.id, hostPortal.id)105      assert.equal(getRemotePaneItems(guestEnv).length, 1)106    })107    test('opening URI for nonexistent portal', async () => {108      const env = buildAtomEnvironment({askBeforeJoiningPortalViaExternalApp: false})109      const pack = await buildPackage(env)110      const notifications = []111      pack.notificationManager.onDidAddNotification((n) => notifications.push(n))112      const uri = 'atom://teletype/portal/00000000-0000-0000-0000-000000000000'113      const portal = await handleURI(pack, uri)114      assert(!portal)115      await condition(() => notifications.find((n) => n.message === 'Portal not found'))116    })117    test('opening URI for inaccessible portal', async () => {118      const hostEnv = buildAtomEnvironment()119      const hostPackage = await buildPackage(hostEnv)120      const TIMEOUT_IN_MILLISECONDS = 1121      const guestEnv = buildAtomEnvironment({askBeforeJoiningPortalViaExternalApp: false})122      const guestPackage = await buildPackage(guestEnv, {peerConnectionTimeout: TIMEOUT_IN_MILLISECONDS})123      const notifications = []124      guestPackage.notificationManager.onDidAddNotification((n) => notifications.push(n))125      const hostPortal = await hostPackage.sharePortal()126      const uri = `atom://teletype/portal/${hostPortal.id}`127      await hostPackage.closeHostPortal()128      const guestPortal = await handleURI(guestPackage, uri)129      assert(!guestPortal)130      await condition(() => notifications.find((n) => n.message === 'Failed to join portal'))131    })132    test('opening malformed URI', async () => {133      const env = buildAtomEnvironment({askBeforeJoiningPortalViaExternalApp: false})134      const pack = await buildPackage(env)135      const notifications = []136      pack.notificationManager.onDidAddNotification((n) => notifications.push(n))137      let portal = await handleURI(pack, 'atom://teletype/some-unsupported-uri')138      assert(!portal)139      await condition(() => notifications.find((n) => n.message === 'Failed to join portal'))140      notifications.length = 0141      portal = await handleURI(pack, 'atom://teletype/portal/42')142      assert(!portal)143      await condition(() => notifications.find((n) => n.message === 'Failed to join portal'))144    })145    test('opening URI when not signed in', async () => {146      const hostEnv = buildAtomEnvironment()147      const hostPackage = await buildPackage(hostEnv)148      const guestEnv = buildAtomEnvironment({askBeforeJoiningPortalViaExternalApp: false})149      const guestPackage = await buildPackage(guestEnv, {signIn: false})150      const hostPortal = await hostPackage.sharePortal()151      const uri = `atom://teletype/portal/${hostPortal.id}`152      await hostEnv.workspace.open()153      const guestPortal = await handleURI(guestPackage, uri)154      assert(!guestPortal)155      assert.equal(getRemotePaneItems(guestEnv).length, 0)156    })157    suite('prompting when opening URI', async () => {158      test('canceling prompt', async () => {159        const hostPackage = await buildPackage(buildAtomEnvironment())160        const hostPortal = await hostPackage.sharePortal()161        const guestEnv = buildAtomEnvironment()162        const guestPackage = await buildPackage(guestEnv)163        const guestPortalPromise = handleURI(guestPackage, getPortalURI(hostPortal.id))164        await condition(() => guestEnv.workspace.getModalPanels().length === 1)165        guestEnv.workspace.getModalPanels()[0].item.cancel()166        assert(!await guestPortalPromise)167        assert.equal(guestEnv.workspace.getModalPanels().length, 0)168      })169      test('allow joining once', async () => {170        const hostPackage1 = await buildPackage(buildAtomEnvironment())171        const hostPortal1 = await hostPackage1.sharePortal()172        const hostPackage2 = await buildPackage(buildAtomEnvironment())173        const hostPortal2 = await hostPackage2.sharePortal()174        const guestEnv = buildAtomEnvironment()175        const guestPackage = await buildPackage(guestEnv)176        const guestPortal1Promise = handleURI(guestPackage, getPortalURI(hostPortal1.id))177        await condition(() => guestEnv.workspace.getModalPanels().length === 1)178        guestEnv.workspace.getModalPanels()[0].item.confirmOnce()179        assert(await guestPortal1Promise)180        assert.equal(guestEnv.workspace.getModalPanels().length, 0)181        // Ensure dialog is shown again when joining another portal.182        handleURI(guestPackage, getPortalURI(hostPortal2.id))183        await condition(() => guestEnv.workspace.getModalPanels().length === 1)184      })185      test('allow joining always', async () => {186        const hostPackage1 = await buildPackage(buildAtomEnvironment())187        const hostPortal1 = await hostPackage1.sharePortal()188        const hostPackage2 = await buildPackage(buildAtomEnvironment())189        const hostPortal2 = await hostPackage2.sharePortal()190        const guestEnv = buildAtomEnvironment()191        const guestPackage = await buildPackage(guestEnv)192        const guestPortal1Promise = handleURI(guestPackage, getPortalURI(hostPortal1.id))193        await condition(() => guestEnv.workspace.getModalPanels().length === 1)194        guestEnv.workspace.getModalPanels()[0].item.confirmAlways()195        assert(await guestPortal1Promise)196        assert.equal(guestEnv.workspace.getModalPanels().length, 0)197        // Ensure dialog is NOT shown again when joining another portal.198        const guestPortal2Promise = handleURI(guestPackage, getPortalURI(hostPortal2.id))199        assert.equal(guestEnv.workspace.getModalPanels().length, 0)200        assert(await guestPortal2Promise)201      })202    })203  })204  suite('remote editor URIs', () => {205    test('opening URIs for editors that the guest has already seen', async () => {206      const hostEnv = buildAtomEnvironment()207      const hostPackage = await buildPackage(hostEnv)208      const guestEnv = buildAtomEnvironment()209      const guestPackage = await buildPackage(guestEnv)210      const portal = await hostPackage.sharePortal()211      await guestPackage.joinPortal(portal.id)212      const hostEditor = await hostEnv.workspace.open(path.join(temp.path(), 'a.md'))213      hostEditor.setText('some text')214      await hostEnv.workspace.open(path.join(temp.path(), 'b.txt'))215      await condition(() => getRemotePaneItems(guestEnv).length === 2)216      let guestEditor = guestEnv.workspace.getPaneItems()[0]217      const editorURI = guestEditor.getURI()218      guestEditor.destroy()219      guestEditor = await guestEnv.workspace.open(editorURI)220      assert(guestEditor.getTitle().endsWith('a.md'))221      assert.equal(guestEditor.getURI(), editorURI)222      assert.equal(guestEditor.getText(), 'some text')223      guestEditor.insertText('abc')224      await condition(() => hostEditor.getText() === guestEditor.getText())225    })226    test('opening URIs for editors that the guest has not yet seen', async () => {227      const hostEnv = buildAtomEnvironment()228      const hostPackage = await buildPackage(hostEnv)229      const guestEnv = buildAtomEnvironment()230      const guestPackage = await buildPackage(guestEnv)231      const portal = await hostPackage.sharePortal()232      const hostEditor = await hostEnv.workspace.open(path.join(temp.path(), 'a.md'))233      const hostEditorProxy = portal.activeEditorProxyForSiteId(1)234      const hostEditorURI = `atom://teletype/portal/${portal.id}/editor/${hostEditorProxy.id}`235      hostEditor.setText('some text')236      await hostEnv.workspace.open(path.join(temp.path(), 'b.txt'))237      guestPackage.joinPortal(portal.id)238      await condition(() => getRemotePaneItems(guestEnv).length === 1)239      const guestEditor = await guestEnv.workspace.open(hostEditorURI)240      assert(guestEditor.getTitle().endsWith('a.md'))241      assert.equal(guestEditor.getURI(), hostEditorURI)242      assert.equal(guestEditor.getText(), 'some text')243      guestEditor.insertText('abc')244      await condition(() => hostEditor.getText() === guestEditor.getText())245    })246    test('opening URIs for editors that do not exist in the portal', async () => {247      const hostEnv = buildAtomEnvironment()248      const hostPackage = await buildPackage(hostEnv)249      const guestEnv = buildAtomEnvironment()250      const guestPackage = await buildPackage(guestEnv)251      const portal = await hostPackage.sharePortal()252      await guestPackage.joinPortal(portal.id)253      const nonexistentEditorURI = `atom://teletype/portal/${portal.id}/editor/999`254      assert.equal(await guestEnv.workspace.open(nonexistentEditorURI), null)255    })256    test('opening URIs when not signed in', async () => {257      const hostEnv = buildAtomEnvironment()258      const hostPackage = await buildPackage(hostEnv)259      const guestEnv = buildAtomEnvironment()260      const guestPackage = await buildPackage(guestEnv, {signIn: false}) // eslint-disable-line no-unused-vars261      const portal = await hostPackage.sharePortal()262      await hostEnv.workspace.open()263      const hostEditorProxy = portal.activeEditorProxyForSiteId(1)264      const hostEditorURI = `atom://teletype/portal/${portal.id}/editor/${hostEditorProxy.id}`265      assert.equal(await guestEnv.workspace.open(hostEditorURI), null)266    })267    test('opening malformed URIs', async () => {268      const hostEnv = buildAtomEnvironment()269      const hostPackage = await buildPackage(hostEnv)270      const guestEnv = buildAtomEnvironment()271      const guestPackage = await buildPackage(guestEnv)272      const portal = await hostPackage.sharePortal()273      await guestPackage.joinPortal(portal.id)274      assert.equal(await guestEnv.workspace.open('atom://teletype/'), null)275      assert.equal(await guestEnv.workspace.open('atom://teletype///'), null)276      await hostEnv.workspace.open()277      const editorProxy = portal.activeEditorProxyForSiteId(1)278      assert.equal(279        await guestEnv.workspace.open(`atom://teletype/x/${portal.id}/y/${editorProxy.id}`),280        null281      )282    })283  })284  test('opening and closing multiple editors on the host', async function () {285    const hostEnv = buildAtomEnvironment()286    const hostPackage = await buildPackage(hostEnv)287    const guestEnv = buildAtomEnvironment()288    const guestPackage = await buildPackage(guestEnv)289    const portalId = (await hostPackage.sharePortal()).id290    guestPackage.joinPortal(portalId)291    const hostEditor1 = await hostEnv.workspace.open()292    const guestEditor1 = await getNextActiveTextEditorPromise(guestEnv)293    assert.equal(getPaneItems(guestEnv).length, 1)294    const hostEditor2 = await hostEnv.workspace.open()295    const guestEditor2 = await getNextActiveTextEditorPromise(guestEnv) // eslint-disable-line no-unused-vars296    assert.equal(getPaneItems(guestEnv).length, 2)297    hostEnv.workspace.paneForItem(hostEditor1).activateItem(hostEditor1)298    assert.equal(await getNextActiveTextEditorPromise(guestEnv), guestEditor1)299    assert.equal(getPaneItems(guestEnv).length, 2)300    hostEditor1.destroy()301    await condition(() => getPaneItems(guestEnv).length === 1)302    hostEditor2.destroy()303    await condition(() => getPaneItems(guestEnv).length === 0)304    await hostEnv.workspace.open()305    const guestEditor3 = await getNextRemotePaneItemPromise(guestEnv)306    assert(guestEditor3 instanceof TextEditor)307    assert.equal(getPaneItems(guestEnv).length, 1)308  })309  test('host joining another portal as a guest', async () => {310    const hostAndGuestEnv = buildAtomEnvironment()311    const hostAndGuestPackage = await buildPackage(hostAndGuestEnv)312    const guestOnlyEnv = buildAtomEnvironment()313    const guestOnlyPackage = await buildPackage(guestOnlyEnv)314    const hostOnlyEnv = buildAtomEnvironment()315    const hostOnlyPackage = await buildPackage(hostOnlyEnv)316    // Start out as a host sharing a portal with a guest (Portal 1)317    const portal1Id = (await hostAndGuestPackage.sharePortal()).id318    await guestOnlyPackage.joinPortal(portal1Id)319    const hostAndGuestLocalEditor = await hostAndGuestEnv.workspace.open(path.join(temp.path(), 'host+guest'))320    const guestOnlyRemotePaneItem1 = await getNextRemotePaneItemPromise(guestOnlyEnv)321    assert(guestOnlyRemotePaneItem1 instanceof TextEditor)322    assert.deepEqual(getPaneItems(guestOnlyEnv), [guestOnlyRemotePaneItem1])323    // While already hosting Portal 1, join Portal 2 as a guest324    const portal2Id = (await hostOnlyPackage.sharePortal()).id325    hostAndGuestPackage.joinPortal(portal2Id)326    hostOnlyEnv.workspace.open(path.join(temp.path(), 'host-only'))327    const hostAndGuestRemotePaneItem = await getNextRemotePaneItemPromise(hostAndGuestEnv)328    await condition(() => deepEqual(getPaneItems(hostAndGuestEnv), [hostAndGuestLocalEditor, hostAndGuestRemotePaneItem]))329    // No transitivity: When Portal 1 host is viewing contents of Portal 2, Portal 1 guests are placed on hold330    assert.equal(hostAndGuestEnv.workspace.getActivePaneItem(), hostAndGuestRemotePaneItem)331    await condition(() => deepEqual(getPaneItems(guestOnlyEnv), [guestOnlyRemotePaneItem1]))332  })333  test('guest sharing another portal as a host', async () => {334    const guestAndHostEnv = buildAtomEnvironment()335    const guestAndHostPackage = await buildPackage(guestAndHostEnv)336    const hostOnlyEnv = buildAtomEnvironment()337    const hostOnlyPackage = await buildPackage(hostOnlyEnv)338    const guestOnlyEnv = buildAtomEnvironment()339    const guestOnlyPackage = await buildPackage(guestOnlyEnv)340    // Start out as a guest in another user's portal (Portal 1)341    const portal1Id = (await hostOnlyPackage.sharePortal()).id342    const guestAndHostPortal1 = await guestAndHostPackage.joinPortal(portal1Id)343    hostOnlyEnv.workspace.open(path.join(temp.path(), 'host-only-buffer-1'))344    const guestAndHostRemotePaneItem1 = await getNextRemotePaneItemPromise(guestAndHostEnv)345    assert.deepEqual(getPaneItems(guestAndHostEnv), [guestAndHostRemotePaneItem1])346    // While already participating as a guest in Portal 1, share a new portal as a host (Portal 2)347    const guestAndHostLocalEditor1 = await guestAndHostEnv.workspace.open(path.join(temp.path(), 'host+guest-buffer-1'))348    assert.deepEqual(getPaneItems(guestAndHostEnv), [guestAndHostRemotePaneItem1, guestAndHostLocalEditor1])349    const portal2Id = (await guestAndHostPackage.sharePortal()).id350    guestOnlyPackage.joinPortal(portal2Id)351    const guestOnlyRemotePaneItem1 = await getNextRemotePaneItemPromise(guestOnlyEnv)352    assert(guestOnlyRemotePaneItem1 instanceof TextEditor)353    assert.deepEqual(getPaneItems(guestOnlyEnv), [guestOnlyRemotePaneItem1])354    guestAndHostPortal1.follow(1) // reconnect tether after disconnecting it due to opening a local editor.355    // Portal 2 host continues to exist as a guest in Portal 1356    hostOnlyEnv.workspace.open(path.join(temp.path(), 'host-only-buffer-2'))357    const guestAndHostRemotePaneItem2 = await getNextRemotePaneItemPromise(guestAndHostEnv)358    assert.deepEqual(getPaneItems(guestAndHostEnv), [guestAndHostRemotePaneItem1, guestAndHostRemotePaneItem2, guestAndHostLocalEditor1])359    assert.deepEqual(getPaneItems(guestOnlyEnv), [guestOnlyRemotePaneItem1])360    // No transitivity: When Portal 2 host is viewing contents of Portal 1, Portal 2 guests can only see contents of Portal 2361    guestAndHostEnv.workspace.getActivePane().activateItemAtIndex(0)362    assert.equal(guestAndHostEnv.workspace.getActivePaneItem(), guestAndHostRemotePaneItem1)363    assert.deepEqual(getPaneItems(guestOnlyEnv), [guestOnlyRemotePaneItem1])364    guestAndHostPortal1.follow(1) // reconnect tether after disconnecting it due to switching to a different editor.365    // As Portal 2 host observes changes in Portal 1, Portal 2 guests continue to only see contents of Portal 2366    await hostOnlyEnv.workspace.open(path.join(temp.path(), 'host-only-buffer-3'))367    const guestAndHostRemotePaneItem3 = await getNextRemotePaneItemPromise(guestAndHostEnv)368    assert.deepEqual(getPaneItems(guestAndHostEnv), [guestAndHostRemotePaneItem1, guestAndHostRemotePaneItem2, guestAndHostRemotePaneItem3, guestAndHostLocalEditor1])369    assert.deepEqual(getPaneItems(guestOnlyEnv), [guestOnlyRemotePaneItem1])370    // When Portal 2 host shares another local buffer, Portal 2 guests see that buffer371    await guestAndHostEnv.workspace.open(path.join(temp.path(), 'host+guest-buffer-2'))372    const guestOnlyRemotePaneItem2 = await getNextRemotePaneItemPromise(guestOnlyEnv)373    assert.deepEqual(getPaneItems(guestOnlyEnv), [guestOnlyRemotePaneItem1, guestOnlyRemotePaneItem2])374  })375  test('host attempting to share another portal', async () => {376    const hostPackage = await buildPackage(buildAtomEnvironment())377    const portal1Id = (await hostPackage.sharePortal()).id378    const portal2Id = (await hostPackage.sharePortal()).id379    assert.equal(portal1Id, portal2Id)380    await hostPackage.closeHostPortal()381    const portal3Id = (await hostPackage.sharePortal()).id382    assert.notEqual(portal3Id, portal1Id)383  })384  test('prompting for an auth token', async () => {385    testServer.identityProvider.setIdentitiesByToken({386      'invalid-token': null,387      'valid-token': {login: 'defunkt'}388    })389    const env = buildAtomEnvironment()390    // Ensure errors make the test fail instead of showing a notification.391    env.notifications.addError = (message) => { throw new Error(message) }392    const pack = await buildPackage(env, {signIn: false})393    await pack.consumeStatusBar(new FakeStatusBar())394    // Show popover when running the "Share Portal" command, but prevent sharing unless user is authenticated.395    assert(!pack.portalStatusBarIndicator.isPopoverVisible())396    assert(!await pack.sharePortal())397    assert(pack.portalStatusBarIndicator.isPopoverVisible())398    // Show popover when running the "Join Portal" command, but prevent sharing unless user is authenticated.399    pack.portalStatusBarIndicator.hidePopover()400    assert(!pack.portalStatusBarIndicator.isPopoverVisible())401    assert(!await pack.joinPortal('some-portal-id'))402    assert(pack.portalStatusBarIndicator.isPopoverVisible())403    const {popoverComponent} = pack.portalStatusBarIndicator404    assert(popoverComponent.refs.signInComponent)405    assert(!popoverComponent.refs.portalListComponent)406    // Enter an invalid token and wait for error message to appear.407    popoverComponent.refs.signInComponent.refs.editor.setText('invalid-token')408    popoverComponent.refs.signInComponent.signIn()409    await condition(() => (410      popoverComponent.refs.signInComponent.props.invalidToken &&411      popoverComponent.refs.signInComponent.refs.editor.getText() === '' &&412      popoverComponent.refs.signInComponent.refs.loginButton.disabled413    ))414    assert.equal(await pack.credentialCache.get('oauth-token'), null)415    assert(!env.workspace.element.classList.contains('teletype-Authenticated'))416    // Show portal list component after entering a valid token.417    popoverComponent.refs.signInComponent.refs.editor.setText('valid-token')418    popoverComponent.refs.signInComponent.signIn()419    await condition(() => (420      !popoverComponent.refs.signInComponent &&421      popoverComponent.refs.portalListComponent422    ))423    assert.equal(await pack.credentialCache.get('oauth-token'), 'valid-token')424    assert(env.workspace.element.classList.contains('teletype-Authenticated'))425    // Go back to sign in component after signing out.426    pack.portalStatusBarIndicator.hidePopover()427    pack.signOut()428    await condition(() => (429      popoverComponent.refs.signInComponent &&430      !popoverComponent.refs.portalListComponent431    ))432    assert(pack.portalStatusBarIndicator.isPopoverVisible())433    assert.equal(await pack.credentialCache.get('oauth-token'), null)434    assert(!env.workspace.element.classList.contains('teletype-Authenticated'))435  })436  test('prompting for a portal URL when joining', async () => {437    const pack = await buildPackage(buildAtomEnvironment())438    await pack.consumeStatusBar(new FakeStatusBar())439    assert(!pack.portalStatusBarIndicator.isPopoverVisible())440    await pack.joinPortal()441    assert(pack.portalStatusBarIndicator.isPopoverVisible())442    const {popoverComponent} = pack.portalStatusBarIndicator443    const {portalListComponent} = popoverComponent.refs444    const {joinPortalComponent} = portalListComponent.refs445    const {portalIdEditor} = joinPortalComponent.refs446    assert(portalIdEditor.element.contains(document.activeElement))447  })448  test('joining the same portal more than once', async () => {449    const host1Env = buildAtomEnvironment()450    const host1Package = await buildPackage(host1Env)451    const host2Env = buildAtomEnvironment()452    const host2Package = await buildPackage(host2Env)453    const guestEnv = buildAtomEnvironment()454    const guestPackage = await buildPackage(guestEnv)455    await host1Env.workspace.open(path.join(temp.path(), 'host-1'))456    const portal1 = await host1Package.sharePortal()457    await host2Env.workspace.open(path.join(temp.path(), 'host-2'))458    const portal2 = await host2Package.sharePortal()459    const guestEditor1Pane = guestEnv.workspace.getActivePane()460    guestPackage.joinPortal(portal1.id)461    guestPackage.joinPortal(portal1.id)462    const guestEditor1 = await getNextRemotePaneItemPromise(guestEnv)463    assert.deepEqual(getPaneItems(guestEnv), [guestEditor1])464    const guestEditor2Pane = guestEditor1Pane.splitRight()465    guestPackage.joinPortal(portal2.id)466    const guestEditor2 = await getNextRemotePaneItemPromise(guestEnv)467    assert.deepEqual(getPaneItems(guestEnv), [guestEditor1, guestEditor2])468    assert.equal(guestEnv.workspace.getActivePaneItem(), guestEditor2)469    assert.equal(guestEnv.workspace.getActivePane(), guestEditor2Pane)470    guestPackage.joinPortal(portal1.id)471    await condition(() => guestEnv.workspace.getActivePaneItem() === guestEditor1)472    assert.deepEqual(guestEnv.workspace.getPaneItems(), [guestEditor1, guestEditor2])473  })474  test('indicating portal status via status bar icon', async () => {475    const isTransmitting = function (statusBar) {476      return statusBar.getRightTiles()[0].item.element.classList.contains('transmitting')477    }478    const host1Env = buildAtomEnvironment()479    const host1Package = await buildPackage(host1Env)480    const host1StatusBar = new FakeStatusBar()481    await host1Package.consumeStatusBar(host1StatusBar)482    assert(!isTransmitting(host1StatusBar))483    const host1Portal = await host1Package.sharePortal()484    await host1Env.workspace.open()485    await condition(() => isTransmitting(host1StatusBar))486    const host2Env = buildAtomEnvironment()487    const host2Package = await buildPackage(host2Env)488    const host2Portal = await host2Package.sharePortal()489    await host2Env.workspace.open()490    const guestEnv = buildAtomEnvironment()491    const guestPackage = await buildPackage(guestEnv)492    const guestStatusBar = new FakeStatusBar()493    await guestPackage.consumeStatusBar(guestStatusBar)494    assert(!isTransmitting(guestStatusBar))495    guestPackage.joinPortal(host1Portal.id)496    await condition(() => isTransmitting(guestStatusBar))497    await guestPackage.joinPortal(host2Portal.id)498    assert(isTransmitting(guestStatusBar))499    await guestPackage.leavePortal()500    assert(isTransmitting(guestStatusBar))501    await guestPackage.leavePortal()502    await condition(() => !isTransmitting(guestStatusBar))503    await host1Package.closeHostPortal()504    await condition(() => !isTransmitting(host1StatusBar))505  })506  test('attempting to join a nonexistent portal', async () => {507    const pack = await buildPackage(buildAtomEnvironment())508    const notifications = []509    pack.notificationManager.onDidAddNotification((n) => notifications.push(n))510    await pack.joinPortal('some-nonexistent-portal-id')511    const errorNotification = notifications.find((n) => n.message === 'Portal not found')512    assert(errorNotification, 'Expected notifications to include "Portal not found" error')513  })514  suite('guest leaving portal', () => {515    test('via explicit leave action', async () => {516      const hostEnv = buildAtomEnvironment()517      const hostPackage = await buildPackage(hostEnv)518      const guestEnv = buildAtomEnvironment()519      const guestPackage = await buildPackage(guestEnv)520      const portal = await hostPackage.sharePortal()521      await guestPackage.joinPortal(portal.id)522      await hostEnv.workspace.open()523      await hostEnv.workspace.open()524      await hostEnv.workspace.open()525      await condition(() => getPaneItems(guestEnv).length === 3)526      await guestPackage.leavePortal()527      await condition(() => getPaneItems(guestEnv).length === 0)528    })529  })530  test('host closing portal', async function () {531    const hostEnv = buildAtomEnvironment()532    const hostPackage = await buildPackage(hostEnv)533    const guestEnv = buildAtomEnvironment()534    const guestPackage = await buildPackage(guestEnv)535    const hostPortal = await hostPackage.sharePortal()536    guestPackage.joinPortal(hostPortal.id)537    await hostEnv.workspace.open()538    await condition(() => getRemotePaneItems(guestEnv).length === 1)539    hostPackage.closeHostPortal()540    await condition(() => getRemotePaneItems(guestEnv).length === 0)541  })542  test('host losing connection', async function () {543    const hostEnv = buildAtomEnvironment()544    const hostPackage = await buildPackage(hostEnv)545    const hostPortal = await hostPackage.sharePortal()546    const guestEnv = buildAtomEnvironment()547    const guestPackage = await buildPackage(guestEnv)548    guestPackage.joinPortal(hostPortal.id)549    await hostEnv.workspace.open()550    await condition(() => getRemotePaneItems(guestEnv).length === 1)551    hostPortal.peerPool.disconnect()552    await condition(() => getRemotePaneItems(guestEnv).length === 0)553  })554  test('host disconnecting while there is an active shared editor', async function () {555    const hostEnv = buildAtomEnvironment()556    const hostPackage = await buildPackage(hostEnv)557    const guestEnv = buildAtomEnvironment()558    const guestPackage = await buildPackage(guestEnv)559    const hostPortal = await hostPackage.sharePortal()560    await guestPackage.joinPortal(hostPortal.id)561    await hostEnv.workspace.open()562    await getNextActiveTextEditorPromise(guestEnv)563    await hostEnv.workspace.open()564    await getNextActiveTextEditorPromise(guestEnv)565    hostPackage.closeHostPortal()566    await condition(() => getRemotePaneItems(guestEnv).length === 0)567  })568  test('peers undoing their own edits', async () => {569    const hostEnv = buildAtomEnvironment()570    const hostPackage = await buildPackage(hostEnv)571    const hostPortal = await hostPackage.sharePortal()572    const hostEditor = await hostEnv.workspace.open()573    const guestEnv = buildAtomEnvironment()574    const guestPackage = await buildPackage(guestEnv)575    guestPackage.joinPortal(hostPortal.id)576    const guestEditor = await getNextActiveTextEditorPromise(guestEnv)577    hostEditor.insertText('h1 ')578    await condition(() => guestEditor.getText() === 'h1 ')579    guestEditor.insertText('g1 ')580    await condition(() => hostEditor.getText() === 'h1 g1 ')581    hostEditor.insertText('h2 ')582    await condition(() => guestEditor.getText() === 'h1 g1 h2 ')583    guestEditor.insertText('g2')584    guestEditor.setTextInBufferRange([[0, 3], [0, 5]], 'g3')585    await condition(() => hostEditor.getText() === 'h1 g3 h2 g2')586    guestEditor.undo()587    assert.equal(guestEditor.getText(), 'h1 g1 h2 g2')588    await condition(() => hostEditor.getText() === 'h1 g1 h2 g2')589    hostEditor.undo()590    assert.equal(hostEditor.getText(), 'h1 g1 g2')591    await condition(() => guestEditor.getText() === 'h1 g1 g2')592    guestEditor.redo()593    assert.equal(guestEditor.getText(), 'h1 g3 g2')594    await condition(() => hostEditor.getText() === 'h1 g3 g2')595    hostEditor.redo()596    assert.equal(hostEditor.getText(), 'h1 g3 h2 g2')597    await condition(() => guestEditor.getText() === 'h1 g3 h2 g2')598    guestEditor.undo()599    assert.equal(guestEditor.getText(), 'h1 g1 h2 g2')600    await condition(() => hostEditor.getText() === 'h1 g1 h2 g2')601    guestEditor.undo()602    assert.equal(guestEditor.getText(), 'h1 g1 h2 ')603    await condition(() => hostEditor.getText() === 'h1 g1 h2 ')604  })605  test('preserving the history when sharing and closing a portal', async () => {606    const hostEnv = buildAtomEnvironment()607    const hostPackage = await buildPackage(hostEnv)608    const hostEditor = await hostEnv.workspace.open()609    hostEditor.insertText('h1 ')610    hostEditor.insertText('h2 ')611    hostEditor.insertText('h3 ')612    hostEditor.undo()613    hostEditor.undo()614    const hostPortal = await hostPackage.sharePortal()615    const guestEnv = buildAtomEnvironment()616    const guestPackage = await buildPackage(guestEnv)617    guestPackage.joinPortal(hostPortal.id)618    const guestEditor = await getNextActiveTextEditorPromise(guestEnv)619    await editorsEqual(guestEditor, hostEditor)620    hostEditor.redo()621    hostEditor.redo()622    assert.equal(hostEditor.getText(), 'h1 h2 h3 ')623    await editorsEqual(guestEditor, hostEditor)624    hostEditor.insertText('h4')625    assert.equal(hostEditor.getText(), 'h1 h2 h3 h4')626    hostEditor.undo()627    hostEditor.undo()628    assert.equal(hostEditor.getText(), 'h1 h2 ')629    await editorsEqual(guestEditor, hostEditor)630    await hostPackage.closeHostPortal()631    hostEditor.redo()632    hostEditor.redo()633    assert.equal(hostEditor.getText(), 'h1 h2 h3 h4')634    hostEditor.undo()635    hostEditor.undo()636    hostEditor.undo()637    assert.equal(hostEditor.getText(), 'h1 ')638  })639  test('undoing and redoing past the history boundaries', async () => {640    const hostEnv = buildAtomEnvironment()641    const hostPackage = await buildPackage(hostEnv)642    const hostPortal = await hostPackage.sharePortal()643    const hostBuffer = new TextBuffer('abcdefg')644    const hostEditor = new TextEditor({buffer: hostBuffer})645    await hostEnv.workspace.open(hostEditor)646    const guestEnv = buildAtomEnvironment()647    const guestPackage = await buildPackage(guestEnv)648    guestPackage.joinPortal(hostPortal.id)649    const guestEditor = await getNextActiveTextEditorPromise(guestEnv)650    hostEditor.undo()651    assert.equal(hostEditor.getText(), 'abcdefg')652    guestEditor.undo()653    assert.equal(guestEditor.getText(), 'abcdefg')654    guestEditor.redo()655    assert.equal(guestEditor.getText(), 'abcdefg')656    hostEditor.redo()657    assert.equal(hostEditor.getText(), 'abcdefg')658  })659  test('checkpoints', async () => {660    const hostEnv = buildAtomEnvironment()661    const hostPackage = await buildPackage(hostEnv)662    const hostEditor = await hostEnv.workspace.open()663    hostEditor.setText('abcdefg')664    const portal = await hostPackage.sharePortal()665    const guestEnv = buildAtomEnvironment()666    const guestPackage = await buildPackage(guestEnv)667    guestPackage.joinPortal(portal.id)668    const guestEditor = await getNextActiveTextEditorPromise(guestEnv)669    const checkpoint = hostEditor.createCheckpoint()670    hostEditor.setCursorBufferPosition([0, 7])671    hostEditor.insertText('h')672    hostEditor.insertText('i')673    hostEditor.insertText('j')674    assert.equal(hostEditor.getText(), 'abcdefghij')675    await editorsEqual(hostEditor, guestEditor)676    const changesSinceCheckpoint = hostEditor.getBuffer().getChangesSinceCheckpoint(checkpoint)677    assert.equal(changesSinceCheckpoint.length, 1)678    assert.deepEqual(changesSinceCheckpoint[0].oldRange, {start: {row: 0, column: 7}, end: {row: 0, column: 7}})679    assert.deepEqual(changesSinceCheckpoint[0].oldText, '')680    assert.deepEqual(changesSinceCheckpoint[0].newRange, {start: {row: 0, column: 7}, end: {row: 0, column: 10}})681    assert.deepEqual(changesSinceCheckpoint[0].newText, 'hij')682    hostEditor.revertToCheckpoint(checkpoint)683    assert.equal(hostEditor.getText(), 'abcdefg')684    await editorsEqual(hostEditor, guestEditor)685  })686  test('reloading a shared editor', async () => {687    const env = buildAtomEnvironment()688    const pack = await buildPackage(env)689    await pack.sharePortal()690    const filePath = path.join(temp.path(), 'standalone.js')691    const editor = await env.workspace.open(filePath)692    editor.setText('hello world!')693    await env.workspace.getActiveTextEditor().save()694    fs.writeFileSync(filePath, 'goodbye world.')695    await env.workspace.getActiveTextEditor().getBuffer().reload()696    assert.equal(editor.getText(), 'goodbye world.')697    editor.undo()698    assert.equal(editor.getText(), 'hello world!')699  })700  test('history serialization', async () => {701    let serializedEnvironment702    {703      const env = buildAtomEnvironment()704      const pack = await buildPackage(env)705      await pack.sharePortal()706      const editor = await env.workspace.open()707      editor.insertText('a')708      editor.insertText('b')709      editor.insertText('c')710      serializedEnvironment = env.serialize({isUnloading: true})711    }712    {713      const env = buildAtomEnvironment()714      await env.deserialize(serializedEnvironment)715      const editor = env.workspace.getActiveTextEditor()716      assert.equal(editor.getText(), 'abc')717      editor.undo()718      assert.equal(editor.getText(), 'ab')719      editor.redo()720      assert.equal(editor.getText(), 'abc')721    }722  })723  suite('host splitting editors', async () => {724    test('supporting distinct selections per editor with a shared undo stack for the buffer', async () => {725      const hostEnv = buildAtomEnvironment()726      const hostPackage = await buildPackage(hostEnv)727      const portal = await hostPackage.sharePortal()728      const guestEnv = buildAtomEnvironment()729      const guestPackage = await buildPackage(guestEnv)730      guestPackage.joinPortal(portal.id)731      const hostEditor1 = await hostEnv.workspace.open()732      hostEditor1.setText('hello = "world"')733      hostEditor1.setCursorBufferPosition([0, 0])734      hostEditor1.insertText('const ')735      hostEnv.workspace.paneForItem(hostEditor1).splitRight({copyActiveItem: true})736      const hostEditor2 = hostEnv.workspace.getActiveTextEditor()737      hostEditor2.setCursorBufferPosition([0, 8])738      assert.equal(hostEditor2.getBuffer(), hostEditor1.getBuffer())739      const guestEditor2 = await getNextActiveTextEditorPromise(guestEnv)740      guestEditor2.setCursorBufferPosition([0, Infinity])741      guestEditor2.insertText('\nconst goodbye = "moon"')742      await editorsEqual(guestEditor2, hostEditor2)743      await timeout(guestPackage.tetherDisconnectWindow)744      hostEditor2.undo()745      assert.equal(hostEditor2.getText(), 'hello = "world"\nconst goodbye = "moon"')746      assert.equal(hostEditor1.getText(), hostEditor2.getText())747      await editorsEqual(hostEditor2, guestEditor2)748      hostEnv.workspace.paneForItem(hostEditor1).activate()749      const guestEditor1 = await getNextActiveTextEditorPromise(guestEnv)750      assert.equal(guestEditor1.getBuffer(), guestEditor2.getBuffer())751      await editorsEqual(guestEditor1, hostEditor1)752      guestEditor1.undo()753      assert.equal(guestEditor1.getText(), 'hello = "world"')754      assert.equal(guestEditor2.getText(), guestEditor1.getText())755      await editorsEqual(guestEditor1, hostEditor1)756    })757    test('remotifying guest editors and buffers', async () => {758      const hostEnv = buildAtomEnvironment()759      const hostPackage = await buildPackage(hostEnv)760      const portal = await hostPackage.sharePortal()761      const guestEnv = buildAtomEnvironment()762      const guestPackage = await buildPackage(guestEnv)763      guestPackage.joinPortal(portal.id)764      const hostEditor1 = await hostEnv.workspace.open(path.join(temp.path(), 'a.txt'))765      const guestEditor1 = await getNextActiveTextEditorPromise(guestEnv)766      hostEnv.workspace.paneForItem(hostEditor1).splitRight({copyActiveItem: true})767      const hostEditor2 = hostEnv.workspace.getActiveTextEditor()768      const guestEditor2 = await getNextActiveTextEditorPromise(guestEnv)769      assert.deepEqual(getPaneItems(guestEnv), [guestEditor1, guestEditor2])770      assert(guestEditor1.isRemote)771      assert(guestEditor1.getTitle().endsWith('a.txt'))772      assert(guestEditor1.getBuffer().getPath().endsWith('a.txt'))773      assert(guestEditor2.isRemote)774      assert(guestEditor2.getTitle().endsWith('a.txt'))775      assert(guestEditor2.getBuffer().getPath().endsWith('a.txt'))776      hostEditor2.destroy()777      await condition(() => deepEqual(getPaneItems(guestEnv), [guestEditor1]))778      assert(guestEditor1.isRemote)779      assert(guestEditor1.getTitle().endsWith('a.txt'))780      assert(guestEditor1.getBuffer().getPath().endsWith('a.txt'))781    })782  })783  test('propagating nested marker layer updates that depend on text updates in a nested transaction', async () => {784    const hostEnv = buildAtomEnvironment()785    const hostPackage = await buildPackage(hostEnv)786    const hostPortal = await hostPackage.sharePortal()787    const hostEditor = await hostEnv.workspace.open()788    const guestEnv = buildAtomEnvironment()789    const guestPackage = await buildPackage(guestEnv)790    guestPackage.joinPortal(hostPortal.id)791    const guestEditor = await getNextActiveTextEditorPromise(guestEnv)792    hostEditor.transact(() => {793      hostEditor.setText('abc\ndef')794      hostEditor.transact(() => {795        hostEditor.setCursorBufferPosition([1, 2])796      })797    })798    await condition(() => deepEqual(getCursorDecoratedRanges(hostEditor), getCursorDecoratedRanges(guestEditor)))799  })800  suite('tethering', () => {801    test('guest following host', async () => {802      const hostEnv = buildAtomEnvironment()803      const hostPackage = await buildPackage(hostEnv)804      const guestEnv = buildAtomEnvironment()805      const guestPackage = await buildPackage(guestEnv)806      const hostPortal = await hostPackage.sharePortal()807      const guestPortal = await guestPackage.joinPortal(hostPortal.id)808      const hostEditor1 = await hostEnv.workspace.open()809      hostEditor1.setText(('x'.repeat(30) + '\n').repeat(30))810      hostEditor1.setCursorBufferPosition([2, 2])811      const hostEditor2 = await hostEnv.workspace.open()812      hostEditor2.setText(('y'.repeat(30) + '\n').repeat(30))813      hostEditor2.setCursorBufferPosition([2, 2])814      await condition(() => guestEnv.workspace.getTextEditors().length === 2)815      await verifyTetheringRules({816        leaderEnv: hostEnv,817        leaderPortal: hostPortal,818        followerEnv: guestEnv,819        followerPortal: guestPortal820      })821    })822    test('host following guest', async () => {823      const hostEnv = buildAtomEnvironment()824      const hostPackage = await buildPackage(hostEnv)825      const guestEnv = buildAtomEnvironment()826      const guestPackage = await buildPackage(guestEnv)827      const hostPortal = await hostPackage.sharePortal()828      const guestPortal = await guestPackage.joinPortal(hostPortal.id)829      const hostEditor1 = await hostEnv.workspace.open()830      hostEditor1.setText(('x'.repeat(30) + '\n').repeat(30))831      hostEditor1.setCursorBufferPosition([2, 2])832      const hostEditor2 = await hostEnv.workspace.open()833      hostEditor2.setText(('y'.repeat(30) + '\n').repeat(30))834      hostEditor2.setCursorBufferPosition([2, 2])835      await condition(() => guestEnv.workspace.getTextEditors().length === 2)836      await verifyTetheringRules({837        leaderEnv: guestEnv,838        leaderPortal: guestPortal,839        followerEnv: hostEnv,840        followerPortal: hostPortal841      })842    })843    test('guest following guest', async () => {844      const hostEnv = buildAtomEnvironment()845      const hostPackage = await buildPackage(hostEnv)846      const guest1Env = buildAtomEnvironment()847      const guest1Package = await buildPackage(guest1Env)848      const guest2Env = buildAtomEnvironment()849      const guest2Package = await buildPackage(guest2Env)850      const hostPortal = await hostPackage.sharePortal()851      const guest1Portal = await guest1Package.joinPortal(hostPortal.id)852      const guest2Portal = await guest2Package.joinPortal(hostPortal.id)853      const hostEditor1 = await hostEnv.workspace.open()854      hostEditor1.setText(('x'.repeat(30) + '\n').repeat(30))855      hostEditor1.setCursorBufferPosition([2, 2])856      const hostEditor2 = await hostEnv.workspace.open()857      hostEditor2.setText(('y'.repeat(30) + '\n').repeat(30))858      hostEditor2.setCursorBufferPosition([2, 2])859      await condition(() => guest1Env.workspace.getTextEditors().length === 2)860      await condition(() => guest2Env.workspace.getTextEditors().length === 2)861      await verifyTetheringRules({862        leaderEnv: guest1Env,863        leaderPortal: guest1Portal,864        followerEnv: guest2Env,865        followerPortal: guest2Portal866      })867    })868    async function verifyTetheringRules ({leaderEnv, leaderPortal, followerEnv, followerPortal}) {869      // Setup DOM for follower's workspace.870      loadPackageStyleSheets(followerEnv)871      const followerWorkspaceElement = followerEnv.views.getView(followerEnv.workspace)872      followerWorkspaceElement.style.height = '100px'873      followerWorkspaceElement.style.width = '250px'874      containerElement.appendChild(followerWorkspaceElement)875      const leaderEditors = leaderEnv.workspace.getTextEditors()876      const followerEditors = followerEnv.workspace.getTextEditors()877      // Reset follow state.878      leaderPortal.unfollow()879      followerPortal.unfollow()880      // Jump to leader cursor and follow it as it moves.881      leaderEnv.workspace.getActivePane().activateItem(leaderEditors[0])882      followerPortal.follow(leaderPortal.siteId)883      await condition(() => (884        followerEnv.workspace.getActivePaneItem() === followerEditors[0] &&885        deepEqual(followerEditors[0].getCursorBufferPosition(), leaderEditors[0].getCursorBufferPosition())886      ))887      leaderEditors[0].setCursorBufferPosition([3, 3])888      await condition(() => deepEqual(followerEditors[0].getCursorBufferPosition(), leaderEditors[0].getCursorBufferPosition()))889      // When followers move their cursor, their cursor does not follow the890      // leader's cursor so long as the leader's cursor stays within the891      // follower's viewport.892      followerEditors[0].setCursorBufferPosition([2, 10])893      leaderEditors[0].setCursorBufferPosition([3, 5])894      leaderEditors[0].insertText('Y')895      await condition(() => followerEditors[0].lineTextForBufferRow(3).includes('Y'))896      assert(followerEditors[0].getCursorBufferPosition().isEqual([2, 10]))897      // When the leader moves their cursor out of the follower's viewport, the898      // follower's cursor moves to the same position if the unfollow period899      // has elapsed.900      await timeout(followerPortal.tetherDisconnectWindow)901      leaderEditors[0].setCursorBufferPosition([20, 10])902      await condition(() => deepEqual(followerEditors[0].getCursorBufferPosition(), leaderEditors[0].getCursorBufferPosition()))903      // If the leader moves to non-visible columns (not just rows), we update904      // the tether.905      await condition(() => followerEditors[0].getFirstVisibleScreenRow() > 0)906      followerEditors[0].setCursorBufferPosition([20, 9])907      await timeout(followerPortal.tetherDisconnectWindow)908      leaderEditors[0].setCursorBufferPosition([20, 30])909      await condition(() => deepEqual(followerEditors[0].getCursorBufferPosition(), leaderEditors[0].getCursorBufferPosition()))910      // Disconnect tether if leader's cursor position moves within the tether911      // disconnect window.912      followerEditors[0].setCursorBufferPosition([20, 29])913      leaderEditors[0].setCursorBufferPosition([0, 0])914      leaderEditors[0].insertText('Y')915      await condition(() => followerEditors[0].lineTextForBufferRow(0).includes('Y'))916      assert(followerEditors[0].getCursorBufferPosition().isEqual([20, 29]))917      await timeout(followerPortal.tetherDisconnectWindow)918      leaderEditors[0].setCursorBufferPosition([1, 0])919      leaderEditors[0].insertText('Y')920      await condition(() => followerEditors[0].lineTextForBufferRow(1).includes('Y'))921      assert(followerEditors[0].getCursorBufferPosition().isEqual([20, 29]))922      // When re-following, ensure that you are taken to the leader's current tab.923      leaderEnv.workspace.paneForItem(leaderEditors[1]).activateItem(leaderEditors[1])924      followerPortal.follow(leaderPortal.siteId)925      await condition(() => deepEqual(followerEditors[1].getCursorBufferPosition(), leaderEditors[1].getCursorBufferPosition()))926      leaderEditors[1].setCursorBufferPosition([4, 4])927      await condition(() => deepEqual(followerEditors[1].getCursorBufferPosition(), leaderEditors[1].getCursorBufferPosition()))928      // Disconnect tether if follower scrolls the tether position out of view.929      followerEditors[1].setCursorBufferPosition([20, 0])930      await timeout(followerPortal.tetherDisconnectWindow)931      leaderEditors[1].setCursorBufferPosition([4, 5])932      leaderEditors[1].insertText('Z')933      await condition(() => followerEditors[1].lineTextForBufferRow(4).includes('Z'))934      assert(followerEditors[1].getCursorBufferPosition().isEqual([20, 0]))935      // Retract follower's tether and ensure it gets disconnected after switching to a different tab.936      followerPortal.follow(leaderPortal.siteId)937      await condition(() => deepEqual(followerEditors[1].getCursorBufferPosition(), leaderEditors[1].getCursorBufferPosition()))938      followerEnv.workspace.getActivePane().activateItem(followerEditors[0])939      await timeout(followerPortal.tetherDisconnectWindow)940      followerEditors[0].setCursorBufferPosition([3, 4])941      leaderEditors[1].setCursorBufferPosition([8, 2])942      leaderEditors[1].insertText('X')943      await condition(() => followerEditors[1].lineTextForBufferRow(8).includes('X'))944      assert.equal(followerEnv.workspace.getActivePaneItem(), followerEditors[0])945      assert(getCursorDecoratedRanges(followerEditors[0]).find((r) => r.isEqual([[3, 4], [3, 4]])))946      assert.equal(leaderEnv.workspace.getActivePaneItem(), leaderEditors[1])947      assert(getCursorDecoratedRanges(leaderEditors[1]).find((r) => r.isEqual([[8, 3], [8, 3]])))948    }949  })950  suite('services', () => {951    test('getRemoteEditors()', async () => {952      testServer.identityProvider.setIdentitiesByToken({953        'token-1': {login: 'user-1'},954        'token-2': {login: 'user-2'}955      })956      const host1Env = buildAtomEnvironment()957      const host1Package = await buildPackage(host1Env, {signIn: false})958      await host1Package.credentialCache.set('oauth-token', 'token-1')959      await host1Package.signInUsingSavedToken()960      const host1EditorA = await host1Env.workspace.open(path.join(temp.path(), 'a')) // eslint-disable-line no-unused-vars961      const host1Portal = await host1Package.sharePortal()962      const host1EditorB = await host1Env.workspace.open(path.join(temp.path(), 'b'))963      const host2Env = buildAtomEnvironment()964      const host2Package = await buildPackage(host2Env, {signIn: false})965      await host2Package.credentialCache.set('oauth-token', 'token-2')966      await host2Package.signInUsingSavedToken()967      const host2EditorC = await host2Env.workspace.open(path.join(temp.path(), 'c')) // eslint-disable-line no-unused-vars968      host2EditorC.setText('some text')969      const host2Portal = await host2Package.sharePortal()970      const host2EditorD = await host2Env.workspace.open(path.join(temp.path(), 'd')) // eslint-disable-line no-unused-vars971      // Create multiple editors for a single buffer (e.g. split panes), ensuring only one of them is returned.972      const host2EditorDCopy = await host2Env.workspace.open(host2EditorD.copy()) // eslint-disable-line no-unused-vars973      const guestEnv = buildAtomEnvironment()974      const guestPackage = await buildPackage(guestEnv)975      const guestService = guestPackage.provideTeletype()976      await guestPackage.joinPortal(host1Portal.id)977      await guestPackage.joinPortal(host2Portal.id)978      host1EditorB.destroy()979      await condition(async () => (await guestService.getRemoteEditors()).length === 3)980      const remoteEditors = await guestService.getRemoteEditors()981      assert.equal(remoteEditors[0].hostGitHubUsername, 'user-1')982      assert.equal(remoteEditors[0].path, host1EditorA.getPath())983      assert.equal(remoteEditors[1].hostGitHubUsername, 'user-2')984      assert.equal(remoteEditors[1].path, host2EditorC.getPath())985      assert.equal(remoteEditors[2].hostGitHubUsername, 'user-2')986      assert.equal(remoteEditors[2].path, host2EditorD.getPath())987      const guestEditorC = await guestEnv.workspace.open(remoteEditors[1].uri)988      assert(guestEditorC.isRemote)989      assert.equal(guestEditorC.getTitle(), '@user-2: c')990      assert.equal(guestEditorC.getURI(), remoteEditors[1].uri)991      assert.equal(guestEditorC.getText(), 'some text')992      guestEditorC.setText('modified text')993      await condition(() => host2EditorC.getText() === 'modified text')994    })995  })996  test('adding and removing workspace element classes when sharing a portal', async () => {997    const hostEnv = buildAtomEnvironment()998    const hostPackage = await buildPackage(hostEnv)999    await hostPackage.sharePortal()1000    assert(hostEnv.workspace.getElement().classList.contains('teletype-Host'))1001    await hostPackage.closeHostPortal()1002    assert(!hostEnv.workspace.getElement().classList.contains('teletype-Host'))1003  })1004  test('reports when the package needs to be upgraded due to an out-of-date protocol version', async () => {1005    const env = buildAtomEnvironment()1006    const pack = await buildPackage(env, {signIn: false})1007    pack.client.initialize = async function () {1008      throw new Errors.ClientOutOfDateError()1009    }1010    await pack.consumeStatusBar(new FakeStatusBar())1011    const {portalStatusBarIndicator} = pack1012    const {popoverComponent} = portalStatusBarIndicator1013    const {packageOutdatedComponent} = popoverComponent.refs1014    assert(portalStatusBarIndicator.element.classList.contains('outdated'))1015    assert(packageOutdatedComponent)1016    assert(!popoverComponent.refs.portalListComponent)1017    assert(!popoverComponent.refs.signInComponent)1018    const openedURIs = []1019    env.workspace.open = (uri) => openedURIs.push(uri)1020    packageOutdatedComponent.refs.viewPackageSettingsButton.click()1021    assert.deepEqual(openedURIs, ['atom://config/updates'])1022  })1023  test('reports errors attempting to initialize the client', async () => {1024    {1025      const env = buildAtomEnvironment()1026      const pack = await buildPackage(env, {signIn: false})1027      pack.client.initialize = async function () {1028        throw new Error('an error')1029      }1030      await pack.consumeStatusBar(new FakeStatusBar())1031      const {popoverComponent} = pack.portalStatusBarIndicator1032      assert(pack.portalStatusBarIndicator.element.classList.contains('initialization-error'))1033      assert(popoverComponent.refs.packageInitializationErrorComponent)1034      assert(popoverComponent.refs.packageInitializationErrorComponent.props.initializationError.message.includes('an error'))1035    }1036  })1037  test('client connection errors', async () => {1038    const env = buildAtomEnvironment()1039    const pack = await buildPackage(env)1040    await pack.sharePortal()1041    env.notifications.clear()1042    pack.client.emitter.emit('connection-error', new ErrorEvent('error', {message: 'connection-error'}))1043    assert.equal(env.notifications.getNotifications().length, 1)1044    const {type, message, options} = env.notifications.getNotifications()[0]1045    const {description} = options1046    assert.equal(type, 'error')1047    assert.equal(message, 'Connection Error')1048    assert(description.includes('connection-error'))1049  })1050  test('reports errors attempting to sign in', async () => {1051    const env = buildAtomEnvironment()1052    const pack = await buildPackage(env, {signIn: false})1053    await pack.consumeStatusBar(new FakeStatusBar())1054    pack.client.signIn = async function () {1055      throw new Error('some error')1056    }1057    const {popoverComponent} = pack.portalStatusBarIndicator1058    popoverComponent.refs.signInComponent.refs.editor.setText('some-token')1059    await popoverComponent.refs.signInComponent.signIn()1060    assert.equal(env.notifications.getNotifications().length, 1)1061    const {type, message, options} = env.notifications.getNotifications()[0]1062    const {description} = options1063    assert.equal(type, 'error')1064    assert.equal(message, 'Failed to authenticate to teletype')1065    assert(description.includes('some error'))1066  })...

Full Screen

Full Screen

package-spec.js

Source:package-spec.js Github

copy

Full Screen

...30    it('does not activate it', function() {31      const packagePath = atom.project32        .getDirectories()[0]33        .resolve('packages/package-with-incompatible-native-module');34      const pack = buildPackage(packagePath);35      expect(pack.isCompatible()).toBe(false);36      expect(pack.incompatibleModules[0].name).toBe('native-module');37      expect(pack.incompatibleModules[0].path).toBe(38        path.join(packagePath, 'node_modules', 'native-module')39      );40    });41    it("utilizes _atomModuleCache if present to determine the package's native dependencies", function() {42      let packagePath = atom.project43        .getDirectories()[0]44        .resolve('packages/package-with-ignored-incompatible-native-module');45      let pack = buildPackage(packagePath);46      expect(pack.getNativeModuleDependencyPaths().length).toBe(1); // doesn't see the incompatible module47      expect(pack.isCompatible()).toBe(true);48      packagePath = __guard__(atom.project.getDirectories()[0], x =>49        x.resolve('packages/package-with-cached-incompatible-native-module')50      );51      pack = buildPackage(packagePath);52      expect(pack.isCompatible()).toBe(false);53    });54    it('caches the incompatible native modules in local storage', function() {55      const packagePath = atom.project56        .getDirectories()[0]57        .resolve('packages/package-with-incompatible-native-module');58      expect(buildPackage(packagePath).isCompatible()).toBe(false);59      expect(global.localStorage.getItem.callCount).toBe(1);60      expect(global.localStorage.setItem.callCount).toBe(1);61      expect(buildPackage(packagePath).isCompatible()).toBe(false);62      expect(global.localStorage.getItem.callCount).toBe(2);63      expect(global.localStorage.setItem.callCount).toBe(1);64    });65    it('logs an error to the console describing the problem', function() {66      const packagePath = atom.project67        .getDirectories()[0]68        .resolve('packages/package-with-incompatible-native-module');69      spyOn(console, 'warn');70      spyOn(atom.notifications, 'addFatalError');71      buildPackage(packagePath).activateNow();72      expect(atom.notifications.addFatalError).not.toHaveBeenCalled();73      expect(console.warn.callCount).toBe(1);74      expect(console.warn.mostRecentCall.args[0]).toContain(75        'it requires one or more incompatible native modules (native-module)'76      );77    });78  });79  describe('::rebuild()', function() {80    beforeEach(function() {81      atom.packages.devMode = false;82      mockLocalStorage();83    });84    afterEach(() => (atom.packages.devMode = true));85    it('returns a promise resolving to the results of `apm rebuild`', function() {86      const packagePath = __guard__(atom.project.getDirectories()[0], x =>87        x.resolve('packages/package-with-index')88      );89      const pack = buildPackage(packagePath);90      const rebuildCallbacks = [];91      spyOn(pack, 'runRebuildProcess').andCallFake(callback =>92        rebuildCallbacks.push(callback)93      );94      const promise = pack.rebuild();95      rebuildCallbacks[0]({96        code: 0,97        stdout: 'stdout output',98        stderr: 'stderr output'99      });100      waitsFor(done =>101        promise.then(function(result) {102          expect(result).toEqual({103            code: 0,104            stdout: 'stdout output',105            stderr: 'stderr output'106          });107          done();108        })109      );110    });111    it('persists build failures in local storage', function() {112      const packagePath = __guard__(atom.project.getDirectories()[0], x =>113        x.resolve('packages/package-with-index')114      );115      const pack = buildPackage(packagePath);116      expect(pack.isCompatible()).toBe(true);117      expect(pack.getBuildFailureOutput()).toBeNull();118      const rebuildCallbacks = [];119      spyOn(pack, 'runRebuildProcess').andCallFake(callback =>120        rebuildCallbacks.push(callback)121      );122      pack.rebuild();123      rebuildCallbacks[0]({ code: 13, stderr: 'It is broken' });124      expect(pack.getBuildFailureOutput()).toBe('It is broken');125      expect(pack.getIncompatibleNativeModules()).toEqual([]);126      expect(pack.isCompatible()).toBe(false);127      // A different package instance has the same failure output (simulates reload)128      const pack2 = buildPackage(packagePath);129      expect(pack2.getBuildFailureOutput()).toBe('It is broken');130      expect(pack2.isCompatible()).toBe(false);131      // Clears the build failure after a successful build132      pack.rebuild();133      rebuildCallbacks[1]({ code: 0, stdout: 'It worked' });134      expect(pack.getBuildFailureOutput()).toBeNull();135      expect(pack2.getBuildFailureOutput()).toBeNull();136    });137    it('sets cached incompatible modules to an empty array when the rebuild completes (there may be a build error, but rebuilding *deletes* native modules)', function() {138      const packagePath = __guard__(atom.project.getDirectories()[0], x =>139        x.resolve('packages/package-with-incompatible-native-module')140      );141      const pack = buildPackage(packagePath);142      expect(pack.getIncompatibleNativeModules().length).toBeGreaterThan(0);143      const rebuildCallbacks = [];144      spyOn(pack, 'runRebuildProcess').andCallFake(callback =>145        rebuildCallbacks.push(callback)146      );147      pack.rebuild();148      expect(pack.getIncompatibleNativeModules().length).toBeGreaterThan(0);149      rebuildCallbacks[0]({ code: 0, stdout: 'It worked' });150      expect(pack.getIncompatibleNativeModules().length).toBe(0);151    });152  });153  describe('theme', function() {154    let [editorElement, theme] = [];155    beforeEach(function() {156      editorElement = document.createElement('atom-text-editor');157      jasmine.attachToDOM(editorElement);158    });159    afterEach(() =>160      waitsForPromise(function() {161        if (theme != null) {162          return Promise.resolve(theme.deactivate());163        }164      })165    );166    describe('when the theme contains a single style file', function() {167      it('loads and applies css', function() {168        expect(getComputedStyle(editorElement).paddingBottom).not.toBe(169          '1234px'170        );171        const themePath = __guard__(atom.project.getDirectories()[0], x =>172          x.resolve('packages/theme-with-index-css')173        );174        theme = buildThemePackage(themePath);175        theme.activate();176        expect(getComputedStyle(editorElement).paddingTop).toBe('1234px');177      });178      it('parses, loads and applies less', function() {179        expect(getComputedStyle(editorElement).paddingBottom).not.toBe(180          '1234px'181        );182        const themePath = __guard__(atom.project.getDirectories()[0], x =>183          x.resolve('packages/theme-with-index-less')184        );185        theme = buildThemePackage(themePath);186        theme.activate();187        expect(getComputedStyle(editorElement).paddingTop).toBe('4321px');188      });189    });190    describe('when the theme contains a package.json file', () =>191      it('loads and applies stylesheets from package.json in the correct order', function() {192        expect(getComputedStyle(editorElement).paddingTop).not.toBe('101px');193        expect(getComputedStyle(editorElement).paddingRight).not.toBe('102px');194        expect(getComputedStyle(editorElement).paddingBottom).not.toBe('103px');195        const themePath = __guard__(atom.project.getDirectories()[0], x =>196          x.resolve('packages/theme-with-package-file')197        );198        theme = buildThemePackage(themePath);199        theme.activate();200        expect(getComputedStyle(editorElement).paddingTop).toBe('101px');201        expect(getComputedStyle(editorElement).paddingRight).toBe('102px');202        expect(getComputedStyle(editorElement).paddingBottom).toBe('103px');203      }));204    describe('when the theme does not contain a package.json file and is a directory', () =>205      it('loads all stylesheet files in the directory', function() {206        expect(getComputedStyle(editorElement).paddingTop).not.toBe('10px');207        expect(getComputedStyle(editorElement).paddingRight).not.toBe('20px');208        expect(getComputedStyle(editorElement).paddingBottom).not.toBe('30px');209        const themePath = __guard__(atom.project.getDirectories()[0], x =>210          x.resolve('packages/theme-without-package-file')211        );212        theme = buildThemePackage(themePath);213        theme.activate();214        expect(getComputedStyle(editorElement).paddingTop).toBe('10px');215        expect(getComputedStyle(editorElement).paddingRight).toBe('20px');216        expect(getComputedStyle(editorElement).paddingBottom).toBe('30px');217      }));218    describe('reloading a theme', function() {219      beforeEach(function() {220        const themePath = __guard__(atom.project.getDirectories()[0], x =>221          x.resolve('packages/theme-with-package-file')222        );223        theme = buildThemePackage(themePath);224        theme.activate();225      });226      it('reloads without readding to the stylesheets list', function() {227        expect(theme.getStylesheetPaths().length).toBe(3);228        theme.reloadStylesheets();229        expect(theme.getStylesheetPaths().length).toBe(3);230      });231    });232    describe('events', function() {233      beforeEach(function() {234        const themePath = __guard__(atom.project.getDirectories()[0], x =>235          x.resolve('packages/theme-with-package-file')236        );237        theme = buildThemePackage(themePath);238        theme.activate();239      });240      it('deactivated event fires on .deactivate()', function() {241        let spy;242        theme.onDidDeactivate((spy = jasmine.createSpy()));243        waitsForPromise(() => Promise.resolve(theme.deactivate()));244        runs(() => expect(spy).toHaveBeenCalled());245      });246    });247  });248  describe('.loadMetadata()', function() {249    let [packagePath, metadata] = [];250    beforeEach(function() {251      packagePath = __guard__(atom.project.getDirectories()[0], x =>252        x.resolve('packages/package-with-different-directory-name')253      );254      metadata = atom.packages.loadPackageMetadata(packagePath, true);255    });256    it('uses the package name defined in package.json', () =>257      expect(metadata.name).toBe('package-with-a-totally-different-name'));258  });259  describe('the initialize() hook', function() {260    it('gets called when the package is activated', function() {261      const packagePath = atom.project262        .getDirectories()[0]263        .resolve('packages/package-with-deserializers');264      const pack = buildPackage(packagePath);265      pack.requireMainModule();266      const { mainModule } = pack;267      spyOn(mainModule, 'initialize');268      expect(mainModule.initialize).not.toHaveBeenCalled();269      pack.activate();270      expect(mainModule.initialize).toHaveBeenCalled();271      expect(mainModule.initialize.callCount).toBe(1);272    });273    it('gets called when a deserializer is used', function() {274      const packagePath = atom.project275        .getDirectories()[0]276        .resolve('packages/package-with-deserializers');277      const pack = buildPackage(packagePath);278      pack.requireMainModule();279      const { mainModule } = pack;280      spyOn(mainModule, 'initialize');281      pack.load();282      expect(mainModule.initialize).not.toHaveBeenCalled();283      atom.deserializers.deserialize({ deserializer: 'Deserializer1', a: 'b' });284      expect(mainModule.initialize).toHaveBeenCalled();285    });286  });287});288function __guard__(value, transform) {289  return typeof value !== 'undefined' && value !== null290    ? transform(value)291    : undefined;...

Full Screen

Full Screen

package.builder.panel.js

Source:package.builder.panel.js Github

copy

Full Screen

1/**2 * Loads the Package Builder3 * 4 * @class MODx.panel.PackageBuilder5 * @extends MODx.panel.Wizard6 * @param {Object} config An object of config properties7 * @xtype panel-package-builder8 */9MODx.panel.PackageBuilder = function(config) {10    config = config || {};11    Ext.applyIf(config,{12        title: _('package_builder')13        ,id: 'panel-package-builder'14        ,layout: 'card'15        ,firstPanel: 'pb-start'16        ,lastPanel: 'pb-build'17        ,txtFinish: _('build')18        ,items: [{19            xtype: 'panel-pb-start'20        },{21            xtype: 'panel-pb-info'22        },{23            xtype: 'panel-pb-autoselects'        24        },{25            xtype: 'panel-pb-selvehicle'26        },{27            xtype: 'panel-pb-build'28        },{29            xtype: 'panel-pb-xml'30        }]31    });32    MODx.panel.PackageBuilder.superclass.constructor.call(this,config);33};34Ext.extend(MODx.panel.PackageBuilder,MODx.panel.Wizard);35Ext.reg('panel-package-builder',MODx.panel.PackageBuilder);36/**37 * 38 * @class MODx.panel.PackageStart39 * @extends MODx.FormPanel40 * @param {Object} config An object of config properties41 * @xtype panel-pb-start42 */43MODx.panel.PackageStart = function(config) {44    config = config || {};45    Ext.applyIf(config,{46        id: 'pb-start'47        ,url: MODx.config.connectors_url+'workspace/builder/index.php'48        ,baseParams: {49            action: 'start'50        }51        ,defaults: { labelSeparator: '', border: false }52        ,items: [{53            html: '<h2>'+_('package_method')+'</h2>'54        },{55            html: '<p>'+_('package_method_desc')+'</p>'56        },{57        	xtype: 'radio'58        	,name: 'method'59        	,boxLabel: _('use_wizard')60        	,inputValue: 'pb-info'61        	,checked: true62        },{63            xtype: 'radio'64            ,name: 'method'65            ,boxLabel: _('use_xml')66            ,inputValue: 'pb-xml'67        }]68        ,listeners: {69            'success': {fn:function(o) {70                var c = o.options;71                var d = o.form.getValues().method;72                Ext.callback(c.proceed,c.scope || this,[d]);73            },scope:this}74        }75    });76    MODx.panel.PackageStart.superclass.constructor.call(this,config);77};78Ext.extend(MODx.panel.PackageStart,MODx.panel.WizardPanel);79Ext.reg('panel-pb-start',MODx.panel.PackageStart);80/**81 * 82 * @class MODx.panel.PackageStart83 * @extends MODx.FormPanel84 * @param {Object} config An object of config properties85 * @xtype panel-pb-start86 */87MODx.panel.PackageXML = function(config) {88    config = config || {};89    Ext.applyIf(config,{90        id: 'pb-xml'91        ,back: 'pb-start'92        ,url: MODx.config.connectors_url+'workspace/builder/index.php'93        ,baseParams: {94            action: 'buildFromXML'95            ,register: 'mgr'96            ,topic: '/workspace/package/builder/'97        }98        ,fileUpload: true99        ,defaults: { labelSeparator: '', border: false }100        ,items: [{101            html: '<h2>'+_('package_build_xml')+'</h2>'102        },{103            html: '<p>'+_('package_build_xml_desc')+'</p>'104        },{105            xtype: 'textfield'106            ,name: 'file'107            ,inputType: 'file'108        }]109        ,listeners: {110            'success': {fn:function(o) {111                var c = o.options;112                this.console.complete();113                Ext.getCmp('pb-info').getForm().reset();114                Ext.callback(c.proceed,c.scope || this,['pb-start']);115            },scope:this}116            ,'beforeSubmit': {fn:function(o) {117            	var topic = '/workspace/package/builder/';118                if (this.console === null) {119                    this.console = MODx.load({120                       xtype: 'modx-console'121                       ,register: 'mgr'122                       ,topic: topic123                    });124                } else {125                    this.console.setRegister('mgr',topic);126                }127                this.console.show(Ext.getBody());128            },scope: this}129        }130    });131    MODx.panel.PackageXML.superclass.constructor.call(this,config);132};133Ext.extend(MODx.panel.PackageXML,MODx.panel.WizardPanel,{134    console: null135});136Ext.reg('panel-pb-xml',MODx.panel.PackageXML);137/**138 * 139 * @class MODx.panel.PackageInfo140 * @extends MODx.FormPanel141 * @param {Object} config An object of config properties142 * @xtype panel-pb-info143 */144MODx.panel.PackageInfo = function(config) {145    config = config || {};146    Ext.applyIf(config,{147        id: 'pb-info'148        ,back: 'pb-start'149        ,url: MODx.config.connectors_url+'workspace/builder/index.php'150        ,baseParams: {151            action: 'create'152        }153        ,defaults: { labelSeparator: '', border: false }154        ,items: [{155            html: '<h2>'+_('package_info')+'</h2>'156        },{157            html: '<p>'+_('package_info_desc')+'</p>'158        },{159            xtype: 'textfield'160            ,fieldLabel: _('name')161            ,name: 'name'162            ,allowBlank: false163        },{164            xtype: 'textfield'165            ,fieldLabel: _('version')166            ,name: 'version'167            ,allowBlank: false168        },{169            xtype: 'textfield'170            ,fieldLabel: _('release')171            ,name: 'release'172            ,allowBlank: false173        },{174            xtype: 'combo-namespace'175            ,fieldLabel: _('namespace')176            ,id: 'pb-namespace'177            ,name: 'namespace'178            ,allowBlank: true179        }]180        ,listeners: {181            'success': {fn:function(o) {182                var c = o.options;183                184                var ns = Ext.getCmp('pb-namespace').getValue();185                var df = ns == 'core' ? false : true; 186                Ext.getCmp('pb-as-cb-ss').setValue(df);187                Ext.getCmp('pb-as-cb-cs').setValue(df);188                Ext.getCmp('pb-as-cb-le').setValue(df);189                Ext.getCmp('pb-as-cb-lf').setValue(df);190                191                Ext.getCmp('grid-vehicle').refresh();192                Ext.callback(c.proceed,c.scope || this,['pb-autoselects']);193            },scope:this}194        }195    });196    MODx.panel.PackageInfo.superclass.constructor.call(this,config);197};198Ext.extend(MODx.panel.PackageInfo,MODx.panel.WizardPanel);199Ext.reg('panel-pb-info',MODx.panel.PackageInfo);200/**201 * 202 * @class MODx.panel.PackageInfo203 * @extends MODx.FormPanel204 * @param {Object} config An object of config properties205 * @xtype panel-pb-info206 */207MODx.panel.PackageAutoSelects = function(config) {208    config = config || {};209    Ext.applyIf(config,{210        id: 'pb-autoselects'211        ,back: 'pb-info'212        ,url: MODx.config.connectors_url+'workspace/builder/index.php'213        ,baseParams: {214            action: 'autoselects'215        }216        ,defaults: { labelSeparator: '', border: false }217        ,items: [{218            html: '<h2>'+_('package_autoselects')+'</h2>'219        },{220            html: '<p>'+_('package_autoselects_desc')+'</p>'221        },{222        	xtype: 'checkboxgroup'223        	,fieldLabel: _('classes')224        	,columns: 1225        	,defaults: {226        	   checked: Ext.getCmp('panel-package-builder').coreSelected ? false : true227        	   ,name: 'classes[]'228        	}229        	,items: [230        		{boxLabel: _('as_system_settings') ,inputValue: 'modSystemSetting' ,id: 'pb-as-cb-ss'}231        		,{boxLabel: _('as_context_settings') ,inputValue: 'modContextSetting' ,id: 'pb-as-cb-cs'}232        		,{boxLabel: _('as_lexicon_entries') ,inputValue: 'modLexiconEntry', id: 'pb-as-cb-le'}233        		,{boxLabel: _('as_lexicon_topics') ,inputValue: 'modLexiconTopic' ,id: 'pb-as-cb-lf'}234    		]235        }]236        ,listeners: {237            'success': {fn:function(o) {238                var c = o.options;239                Ext.getCmp('grid-vehicle').refresh();240                Ext.callback(c.proceed,c.scope || this,['pb-selvehicle']);241            },scope:this}242        }243    });244    MODx.panel.PackageAutoSelects.superclass.constructor.call(this,config);245};246Ext.extend(MODx.panel.PackageAutoSelects,MODx.panel.WizardPanel);247Ext.reg('panel-pb-autoselects',MODx.panel.PackageAutoSelects);248/**249 * 250 * @class MODx.panel.SelectVehicles251 * @extends MODx.FormPanel252 * @param {Object} config An object of config properties253 * @xtype panel-pb-selvehicle254 */255MODx.panel.SelectVehicles = function(config) {256    config = config || {};257    Ext.applyIf(config,{258        id: 'pb-selvehicle'259        ,back: 'pb-autoselects'260        ,url: MODx.config.connectors_url+'workspace/builder/vehicle.php'261        ,baseParams: {262            action: 'create'263        }264        ,defaults: { labelSeparator: '' }265        ,items: [{266            html: '<h2>'+_('vehicles_add')+'</h2>'267            ,border: false268        },{269            html: '<p>'+_('vehicles_desc')+'</p>'270            ,border: false271        },{272            xtype: 'grid-vehicle'273            ,id: 'grid-vehicle'274            ,preventRender: true275        }]276    });277    MODx.panel.SelectVehicles.superclass.constructor.call(this,config);278};279Ext.extend(MODx.panel.SelectVehicles,MODx.panel.WizardPanel,{280    submit: function(o) {281        Ext.callback(o.proceed,o.scope || this,['pb-build']);282    }283});284Ext.reg('panel-pb-selvehicle',MODx.panel.SelectVehicles);285/**286 * 287 * @class MODx.panel.BuildPackage288 * @extends MODx.FormPanel289 * @param {Object} config An object of config properties290 * @xtype panel-pb-build291 */292MODx.panel.BuildPackage = function(config) {293    config = config || {};294    Ext.applyIf(config,{295        id: 'pb-build'296        ,back: 'pb-selvehicle'297        ,url: MODx.config.connectors_url+'workspace/builder/index.php'298        ,baseParams: {299            action: 'build'300            ,register: 'mgr'301            ,topic: '/workspace/package/builder/'302        }303        ,defaults: { labelSeparator: '', border: false }304        ,items: [{305            html: '<h2>'+_('package_build')+'</h2>'306        },{307            html: '<p>'+_('package_build_desc')+'</p>'308        }]309        ,listeners: {310            'success': {fn:function(o) {311                var c = o.options;312                this.console.complete();313                Ext.getCmp('pb-info').getForm().reset();314                Ext.callback(c.proceed,c.scope || this,['pb-start']);315            },scope:this}316            ,'beforeSubmit': {fn:function(o) {317                var topic = '/workspace/package/builder/';318                if (this.console === null) {319                    this.console = MODx.load({320                       xtype: 'modx-console'321                       ,register: 'mgr'322                       ,topic: topic323                    });324                } else {325                    this.console.setRegister('mgr',topic);326                }327                this.console.show(Ext.getBody());328            },scope: this}329        }330    });331    MODx.panel.BuildPackage.superclass.constructor.call(this,config);332};333Ext.extend(MODx.panel.BuildPackage,MODx.panel.WizardPanel,{334    console: null335});...

Full Screen

Full Screen

server.js

Source:server.js Github

copy

Full Screen

1#!/usr/bin/env node2var path = require('path');3var architect = require("architect");4var spawn = require("child_process").spawn;5var fs = require("fs");6// TODO: Need better args parser.7var configName = process.argv[2] || "default";8// when command line arguments are passed into this, we ignore them9// when loading the config file.10if (configName.indexOf("-") === 0) {11   configName = "default";12}13var debug = false;14var packed = false;15var packedName = "";16for (var p = 2; p < process.argv.length; p++) {17   if (process.argv[p] === "-d") {18       debug = true;19       20       // apf debug doesn't exist, or it's older than three days--rebuild it21       if(!path.existsSync("plugins-client/lib.apf/www/apf-packaged/apf_debug.js") ||22          (path.existsSync("plugins-client/lib.apf/www/apf-packaged/apf_debug.js")) &&23          ((new Date() - fs.statSync("plugins-client/lib.apf/www/apf-packaged/apf_debug.js").mtime.valueOf()) / 86400000) >= 3) {24           console.log("Building apfdebug for first run...");25           26           var buildDebug = spawn("npm", ["run-script", "build-debug"]);27           28           buildDebug.stderr.setEncoding("utf8");29           buildDebug.stderr.on('data', function (data) {30              console.error(data);31           });32           33           buildDebug.on('exit', function (code) {34              if (code !== 0) {35                console.error('build-debug process exited with code ' + code);36                process.exit(code);37              }38              boot();39           });40       }41       else42           boot();43   }44   else if (process.argv[p] === "-P") {45       packed = true;46       if (process.argv[p + 1] && process.argv[p + 1].indexOf("-") < 0) // use this specific packed file47            packedName = process.argv[++p];48       else49            packedName = "c9os.min.js";50       configName = "packed";51       if(!path.existsSync("plugins-client/lib.packed/www/" + packedName) && !path.existsSync("plugins-client/lib.packed/www/" + packedName + ".gz")) {52           console.log("Building packed file for first run...Please wait...");53           console.log("   |\\      _,,,---,,_\n" +54                       "   /,`.-'`'    -.  ;-;;,_\n" +55                       "   |,4-  ) )-,_..;\\ (  `'-'\n" +56                       "   '---''(_/--'  `-'\\_)  Felix Lee");57            var buildPackage = spawn("npm", ["run-script", "build-packed"]);58            59            buildPackage.stderr.setEncoding("utf8");60            buildPackage.stderr.on('data', function (data) {61              console.error(data);62            });63            buildPackage.on('exit', function (code) {64              if (code !== 0) {65                console.error('build-package process exited with code ' + code);66                process.exit(code);67              }68              boot();69            });70       }71       else72           boot();73   }74}75if (debug == false && packed == false)76	boot();77function boot() {78	var configPath = path.resolve(__dirname, "./configs/", configName);79	var plugins = require(configPath);80	// server plugins81	plugins.forEach(function(plugin) {82	   if (plugin.packagePath && /\.\/cloud9.core$/.test(plugin.packagePath)) {83	       plugin.debug = debug;84	       plugin.packed = packed;85	       plugin.packedName = packedName;86	   }87	});88  architect.createApp(architect.resolveConfig(plugins, __dirname + "/plugins-server"), function (err, app) {89	   if (err) {90	       console.error("While starting the '%s':", configPath);91	       throw err;92	   }93	   console.log("Started '%s'!", configPath);94	});...

Full Screen

Full Screen

build-package.spec.js

Source:build-package.spec.js Github

copy

Full Screen

...10      dependencies: {11        foo: {}12      }13    };14    const pkg = buildPackage(packageDir, packageLock, logger);15    const actualDependency = pkg.dependencies.find(d => d.name === 'foo');16    expect(actualDependency).toBeTruthy();17    expect(actualDependency.description).toBeFalsy();18    expect(actualDependency.license).toBeFalsy();19    expect(actualDependency.name).toBe('foo');20    expect(actualDependency.version).toBeFalsy();21  });22  it('processes dependencies defined in package.json and installed', () => {23    const packageDir = '.';24    const packageLock = {25      dependencies: {26        jasmine: {}27      }28    };29    const pkg = buildPackage(packageDir, packageLock, logger);30    const expectedDependency = jsonFile.readFileSync(31      './node_modules/jasmine/package.json'32    );33    const actualDependency = pkg.dependencies.find(34      d => d.name === Object.keys(packageLock.dependencies)[0]35    );36    expect(actualDependency).toBeTruthy();37    expect(actualDependency.description).toBe(expectedDependency.description);38    expect(actualDependency.license).toBe(expectedDependency.license);39    expect(actualDependency.name).toBe(expectedDependency.name);40    expect(actualDependency.version).toBe(expectedDependency.version);41  });...

Full Screen

Full Screen

build-module.js

Source:build-module.js Github

copy

Full Screen

...10  packages.forEach(async (pkg) => {11    const target = pkg.dirName;12    const pkgDir = path.resolve(`packages/${target}`);13    await fs.remove(`${pkgDir}/esm`);14    buildPackage(pkg.dirName);15  });16}17function buildPackage(dirName) {18  const pattern = '**/*.ts';19  const cwd = resolvePackagePath(dirName, 'src');20  const files = glob.sync(pattern, { cwd, });21  const targetFiles = files.map((file) => {22    return resolvePackagePath(dirName, 'src', file);23  });24  // build ts -> esm25  {26    const tsConfig = getTsConfig();27    const compilerOptions = tsConfig.compilerOptions;28    compilerOptions.target = ts.ScriptTarget.ES2015;29    compilerOptions.moduleResolution = ts.ModuleResolutionKind.NodeJs;30    compilerOptions.declaration = true;31    compilerOptions.outDir = resolvePackagePath(dirName, 'esm');...

Full Screen

Full Screen

build.js

Source:build.js Github

copy

Full Screen

1/*2    Build everything3 */4import * as gulp from 'gulp'5import * as log from 'fancy-log'6import config from 'assist'7import {blend} from 'assist/blend'8import buildPackage from './package'9import deploy from './deploy'10import publish from './publish'11import run from './run'12function setProd(done) {13    config.profile = 'prod'14    blend(config, config.profiles[config.profile])15    done()16}17function trace(cb) {18    print(`Using: profile ${config.profile}  ${config.debug ? 'debug' : ''}`)19    cb()20}21function noBuild(cb) {22    print(`Skipping: no build action required`)23    cb()24}25function noClean(cb) {26    // print(`Skipping: no clean action taken`)27    cb()28}29gulp.task('build', gulp.series(noBuild))30gulp.task('clean', gulp.series(noClean))31gulp.task('deploy', gulp.series(deploy))32gulp.task('package', gulp.series(buildPackage))33gulp.task('publish', gulp.series(publish))34gulp.task('promote', gulp.series(setProd, trace, buildPackage, publish, deploy))35gulp.task('run', gulp.series(run))...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1const cypress = require('cypress')2const fs = require('fs')3const path = require('path')4const { promisify } = require('util')5const writeFile = promisify(fs.writeFile)6const mkdir = promisify(fs.mkdir)7const rimraf = promisify(require('rimraf'))8const appDir = path.join(__dirname, 'cypress', 'app')9const { buildPackage } = require('@cypress/webpack-preprocessor')10const webpackOptions = {11  resolve: {12  },13  module: {14      {15        options: {16        },17      },18  },19}20rimraf(appDir)21  .then(() => {22    return mkdir(appDir)23  })24  .then(() => {25    return writeFile(path.join(appDir, 'index.js'), 'console.log("hello")')26  })27  .then(() => {28    return writeFile(path.join(appDir, 'index.ts'), 'console.log("hello")')29  })30  .then(() => {31    return writeFile(32      path.join(appDir, 'index.tsx'),33      'console.log("hello")',34  })35  .then(() => {36    return buildPackage(webpackOptions)37  })38  .then((spec) => {39    return writeFile(path.join(__dirname, 'cypress', 'integration', 'spec.js'), spec)40  })41  .then(() => {42    return cypress.open({43      config: {44      },45    })46  })47const { buildPackage } = require('@cypress/webpack-preprocessor')48const webpackOptions = {49}50const options = {51}52buildPackage(options)

Full Screen

Using AI Code Generation

copy

Full Screen

1const cypress = require('cypress')2cypress.run({3  config: {4  },5  reporterOptions: {6  },7}).then((results) => {8  console.log('results', results)9})

Full Screen

Using AI Code Generation

copy

Full Screen

1const cypress = require('cypress')2const fs = require('fs-extra')3const path = require('path')4const runCypressTests = async () => {5  const { runResults } = await cypress.run({6    config: {7    },8  })9  const { totalFailed } = runResults10  if (totalFailed > 0) {11    throw new Error('Cypress tests failed')12  }13}14const buildPackage = async () => {15  const { projectType } = await cypress.config.readConfig()16  const cypressProjectPath = path.dirname(17    require.resolve(`${projectType}/package.json`),18  const cypressProjectDist = path.join(cypressProjectPath, 'dist')19  await fs.remove(cypressProjectDist)20  await cypress.run({21    config: {22    },23  })24}25const cleanUp = async () => {26  await fs.remove('screenshots')27  await fs.remove('cypress/videos')28}29const run = async () => {30  await runCypressTests()31  await buildPackage()32  await cleanUp()33}34run()35const cypress = require('cypress')36const fs = require('fs-extra')37const path = require('path')

Full Screen

Using AI Code Generation

copy

Full Screen

1const cypress = require('cypress');2cypress.run({3    config: {4    },5    config: {6    },7    reporterOptions: {8    },9}).then((results) => {10    console.log(results);11    process.exit(results.totalFailed);12});13describe('Your test case', () => {14    it('Your test case', () => {15        cy.get('input[name="q"]').type('Cypress');16        cy.get('input[value="Google Search"]').click();17        cy.get('h3').should('be.visible');18    });19});

Full Screen

Using AI Code Generation

copy

Full Screen

1import { buildPackage } from '@cypress/browserify-preprocessor'2module.exports = (on, config) => {3  on('file:preprocessor', buildPackage())4}5const browserify = require('@cypress/browserify-preprocessor')6module.exports = (on, config) => {7  on('file:preprocessor', browserify())8}9const browserify = require('@cypress/browserify-preprocessor')10module.exports = (on, config) => {11  on('file:preprocessor', browserify())12}13const browserify = require('@cypress/browserify-preprocessor')14module.exports = (on, config) => {15  on('file:preprocessor', browserify())16}17const browserify = require('@cypress/browserify-preprocessor')18module.exports = (on, config) => {19  on('file:preprocessor', browserify())20}21const browserify = require('@cypress/browserify-preprocessor')22module.exports = (on, config) => {23  on('file:preprocessor', browserify())24}25const browserify = require('@cypress/browserify-preprocessor')26module.exports = (on, config) => {27  on('file:preprocessor', browserify())28}29const browserify = require('@cypress/browserify-preprocessor')30module.exports = (on, config) => {31  on('file:preprocessor', browserify())32}33const browserify = require('@cypress/browserify-preprocessor')34module.exports = (on, config) => {35  on('file:preprocessor', browserify())36}

Full Screen

Using AI Code Generation

copy

Full Screen

1const fs = require('fs')2const cypress = require('cypress')3const packageJson = {4  "scripts": {5  },6  "devDependencies": {7  }8}9  .run({10    config: {11    },12    env: {13    },14    reporterOptions: {15    }16  })17  .then((results) => {18    console.log(results)19  })20  .catch((err) => {21    console.error(err)22  })23fs.writeFile('package.json', JSON.stringify(packageJson), err => {24  if (err) throw err25  console.log('package.json created')26})27const { exec } = require('child_process')28exec('npm install', (err, stdout, stderr) => {29  if (err) {30    console.error(`exec error: ${err}`)31  }32  console.log(`stdout: ${stdout}`)33  console.log(`stderr: ${stderr}`)34})35exec('npm run cy:run', (err, stdout, stderr) => {36  if (err) {37    console.error(`exec error: ${err}`)38  }39  console.log(`stdout: ${stdout}`)40  console.log(`stderr: ${stderr}`)41})42fs.unlink('package.json', err => {43  if (err) throw err44  console.log('package.json deleted')45})46fs.unlink('package-lock.json', err => {47  if (err) throw

Full Screen

Using AI Code Generation

copy

Full Screen

1const cypress = require('cypress');2const fs = require('fs-extra');3const path = require('path');4const appDir = path.dirname(require.main.filename);5const zip = require('adm-zip');6const folderName = 'cypress';7const tempFolder = 'temp';8const zipFolder = 'zip';9const zipFileName = 'cypress.zip';10const zipFilePath = path.join(appDir, zipFolder, zipFileName);11const tempFolderPath = path.join(appDir, tempFolder);12const folderPath = path.join(appDir, folderName);13const cypressZipFilePath = path.join(folderPath, zipFileName);14const cypressZipFolderPath = path.join(folderPath, tempFolder);15const cypressZipFolder = new zip(cypressZipFilePath);16async function buildPackage() {17    await cypress.run({18        config: {19        },20    });21}22async function deleteFolder() {23    await fs.remove(folderPath);24}25async function unzipFile() {26    await cypressZipFolder.extractAllTo(cypressZipFolderPath, true);27}28async function copyFolder() {29    await fs.copy(tempFolderPath, folderPath);30}31async function deleteTempFolder() {32    await fs.remove(tempFolderPath);33}34async function deleteZipFile() {35    await fs.remove(cypressZipFilePath);36}37async function deleteZipFolder() {38    await fs.remove(zipFolder);39}40async function createZipFolder() {41    await fs.mkdir(zipFolder);42}43async function createTempFolder() {44    await fs.mkdir(tempFolder);45}

Full Screen

Using AI Code Generation

copy

Full Screen

1import {buildPackage} from '@cypress/code-coverage/task'2buildPackage(__dirname)3module.exports = (on, config) => {4  require('@cypress/code-coverage/task')(on, config)5}6import '@cypress/code-coverage/support'7{8  "env": {9  }10}11{12}13{14  "scripts": {15  },16  "devDependencies": {17  }18}

Full Screen

Cypress Tutorial

Cypress is a renowned Javascript-based open-source, easy-to-use end-to-end testing framework primarily used for testing web applications. Cypress is a relatively new player in the automation testing space and has been gaining much traction lately, as evidenced by the number of Forks (2.7K) and Stars (42.1K) for the project. LambdaTest’s Cypress Tutorial covers step-by-step guides that will help you learn from the basics till you run automation tests on LambdaTest.

Chapters:

  1. What is Cypress? -
  2. Why Cypress? - Learn why Cypress might be a good choice for testing your web applications.
  3. Features of Cypress Testing - Learn about features that make Cypress a powerful and flexible tool for testing web applications.
  4. Cypress Drawbacks - Although Cypress has many strengths, it has a few limitations that you should be aware of.
  5. Cypress Architecture - Learn more about Cypress architecture and how it is designed to be run directly in the browser, i.e., it does not have any additional servers.
  6. Browsers Supported by Cypress - Cypress is built on top of the Electron browser, supporting all modern web browsers. Learn browsers that support Cypress.
  7. Selenium vs Cypress: A Detailed Comparison - Compare and explore some key differences in terms of their design and features.
  8. Cypress Learning: Best Practices - Take a deep dive into some of the best practices you should use to avoid anti-patterns in your automation tests.
  9. How To Run Cypress Tests on LambdaTest? - Set up a LambdaTest account, and now you are all set to learn how to run Cypress tests.

Certification

You can elevate your expertise with end-to-end testing using the Cypress automation framework and stay one step ahead in your career by earning a Cypress certification. Check out our Cypress 101 Certification.

YouTube

Watch this 3 hours of complete tutorial to learn the basics of Cypress and various Cypress commands with the Cypress testing at LambdaTest.

Run Cypress automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful