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