JoinProjectTests.js 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107
  1. // TODO: This file was created by bulk-decaffeinate.
  2. // Fix any style issues and re-enable lint.
  3. /*
  4. * decaffeinate suggestions:
  5. * DS101: Remove unnecessary use of Array.from
  6. * DS102: Remove unnecessary code created because of implicit returns
  7. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  8. */
  9. const { expect } = require('chai')
  10. const RealTimeClient = require('./helpers/RealTimeClient')
  11. const MockWebServer = require('./helpers/MockWebServer')
  12. const FixturesManager = require('./helpers/FixturesManager')
  13. const async = require('async')
  14. describe('joinProject', function () {
  15. describe('when authorized', function () {
  16. before(function (done) {
  17. return async.series(
  18. [
  19. cb => {
  20. return FixturesManager.setUpProject(
  21. {
  22. privilegeLevel: 'owner',
  23. project: {
  24. name: 'Test Project',
  25. },
  26. },
  27. (e, { project_id: projectId, user_id: userId }) => {
  28. this.project_id = projectId
  29. this.user_id = userId
  30. return cb(e)
  31. }
  32. )
  33. },
  34. cb => {
  35. this.client = RealTimeClient.connect()
  36. return this.client.on('connectionAccepted', cb)
  37. },
  38. cb => {
  39. return this.client.emit(
  40. 'joinProject',
  41. { project_id: this.project_id },
  42. (error, project, privilegeLevel, protocolVersion) => {
  43. this.project = project
  44. this.privilegeLevel = privilegeLevel
  45. this.protocolVersion = protocolVersion
  46. return cb(error)
  47. }
  48. )
  49. },
  50. ],
  51. done
  52. )
  53. })
  54. it('should get the project from web', function () {
  55. return MockWebServer.joinProject
  56. .calledWith(this.project_id, this.user_id)
  57. .should.equal(true)
  58. })
  59. it('should return the project', function () {
  60. return this.project.should.deep.equal({
  61. name: 'Test Project',
  62. owner: { _id: this.user_id },
  63. })
  64. })
  65. it('should return the privilege level', function () {
  66. return this.privilegeLevel.should.equal('owner')
  67. })
  68. it('should return the protocolVersion', function () {
  69. return this.protocolVersion.should.equal(2)
  70. })
  71. it('should have joined the project room', function (done) {
  72. return RealTimeClient.getConnectedClient(
  73. this.client.socket.sessionid,
  74. (error, client) => {
  75. if (error) return done(error)
  76. expect(Array.from(client.rooms).includes(this.project_id)).to.equal(
  77. true
  78. )
  79. return done()
  80. }
  81. )
  82. })
  83. return it('should have marked the user as connected', function (done) {
  84. return this.client.emit(
  85. 'clientTracking.getConnectedUsers',
  86. (error, users) => {
  87. if (error) return done(error)
  88. let connected = false
  89. for (const user of Array.from(users)) {
  90. if (
  91. user.client_id === this.client.publicId &&
  92. user.user_id === this.user_id
  93. ) {
  94. connected = true
  95. break
  96. }
  97. }
  98. expect(connected).to.equal(true)
  99. return done()
  100. }
  101. )
  102. })
  103. })
  104. describe('when authorized with token', function () {
  105. before(function (done) {
  106. async.series(
  107. [
  108. cb => {
  109. FixturesManager.setUpProject(
  110. {
  111. privilegeLevel: 'owner',
  112. publicAccess: 'readOnly',
  113. project: {
  114. name: 'Test Project',
  115. },
  116. },
  117. (
  118. e,
  119. {
  120. user_id: ownerId,
  121. project_id: projectId,
  122. anonymousAccessToken,
  123. }
  124. ) => {
  125. this.ownerId = ownerId
  126. this.project_id = projectId
  127. this.anonymousAccessToken = anonymousAccessToken
  128. cb(e)
  129. }
  130. )
  131. },
  132. cb => {
  133. RealTimeClient.setSession({}, cb)
  134. },
  135. cb => {
  136. this.client = RealTimeClient.connect()
  137. this.client.on('connectionAccepted', cb)
  138. },
  139. cb => {
  140. this.client.emit(
  141. 'joinProject',
  142. {
  143. project_id: this.project_id,
  144. anonymousAccessToken: this.anonymousAccessToken,
  145. },
  146. (error, project, privilegeLevel, protocolVersion) => {
  147. this.project = project
  148. this.privilegeLevel = privilegeLevel
  149. this.protocolVersion = protocolVersion
  150. cb(error)
  151. }
  152. )
  153. },
  154. ],
  155. done
  156. )
  157. })
  158. it('should get the project from web', function () {
  159. MockWebServer.joinProject
  160. .calledWith(
  161. this.project_id,
  162. 'anonymous-user',
  163. this.anonymousAccessToken
  164. )
  165. .should.equal(true)
  166. })
  167. it('should return the project', function () {
  168. this.project.should.deep.equal({
  169. name: 'Test Project',
  170. owner: { _id: this.ownerId },
  171. })
  172. })
  173. it('should return the privilege level', function () {
  174. this.privilegeLevel.should.equal('readOnly')
  175. })
  176. it('should return the protocolVersion', function () {
  177. this.protocolVersion.should.equal(2)
  178. })
  179. it('should have joined the project room', function (done) {
  180. RealTimeClient.getConnectedClient(
  181. this.client.socket.sessionid,
  182. (error, client) => {
  183. if (error) return done(error)
  184. expect(Array.from(client.rooms).includes(this.project_id)).to.equal(
  185. true
  186. )
  187. done()
  188. }
  189. )
  190. })
  191. it('should have marked the user as connected', function (done) {
  192. this.client.emit('clientTracking.getConnectedUsers', (error, users) => {
  193. if (error) return done(error)
  194. let connected = false
  195. for (const user of Array.from(users)) {
  196. if (user.client_id === this.client.publicId) {
  197. connected = true
  198. break
  199. }
  200. }
  201. expect(connected).to.equal(true)
  202. done()
  203. })
  204. })
  205. })
  206. describe('when not authorized', function () {
  207. before(function (done) {
  208. return async.series(
  209. [
  210. cb => {
  211. return FixturesManager.setUpProject(
  212. {
  213. privilegeLevel: null,
  214. project: {
  215. name: 'Test Project',
  216. },
  217. },
  218. (e, { project_id: projectId, user_id: userId }) => {
  219. this.project_id = projectId
  220. this.user_id = userId
  221. return cb(e)
  222. }
  223. )
  224. },
  225. cb => {
  226. this.client = RealTimeClient.connect()
  227. return this.client.on('connectionAccepted', cb)
  228. },
  229. cb => {
  230. return this.client.emit(
  231. 'joinProject',
  232. { project_id: this.project_id },
  233. (error, project, privilegeLevel, protocolVersion) => {
  234. this.error = error
  235. this.project = project
  236. this.privilegeLevel = privilegeLevel
  237. this.protocolVersion = protocolVersion
  238. return cb()
  239. }
  240. )
  241. },
  242. ],
  243. done
  244. )
  245. })
  246. it('should return an error', function () {
  247. return this.error.message.should.equal('not authorized')
  248. })
  249. return it('should not have joined the project room', function (done) {
  250. return RealTimeClient.getConnectedClient(
  251. this.client.socket.sessionid,
  252. (error, client) => {
  253. if (error) return done(error)
  254. expect(Array.from(client.rooms).includes(this.project_id)).to.equal(
  255. false
  256. )
  257. return done()
  258. }
  259. )
  260. })
  261. })
  262. describe('when not authorized and web replies with a 403', function () {
  263. before(function (done) {
  264. return async.series(
  265. [
  266. cb => {
  267. return FixturesManager.setUpProject(
  268. {
  269. project_id: '403403403403403403403403', // forbidden
  270. privilegeLevel: 'owner',
  271. project: {
  272. name: 'Test Project',
  273. },
  274. },
  275. (e, { project_id: projectId, user_id: userId }) => {
  276. this.project_id = projectId
  277. this.user_id = userId
  278. cb(e)
  279. }
  280. )
  281. },
  282. cb => {
  283. this.client = RealTimeClient.connect()
  284. this.client.on('connectionAccepted', cb)
  285. },
  286. cb => {
  287. this.client.emit(
  288. 'joinProject',
  289. { project_id: this.project_id },
  290. (error, project, privilegeLevel, protocolVersion) => {
  291. this.error = error
  292. this.project = project
  293. this.privilegeLevel = privilegeLevel
  294. this.protocolVersion = protocolVersion
  295. cb()
  296. }
  297. )
  298. },
  299. ],
  300. done
  301. )
  302. })
  303. it('should return an error', function () {
  304. this.error.message.should.equal('not authorized')
  305. })
  306. it('should not have joined the project room', function (done) {
  307. RealTimeClient.getConnectedClient(
  308. this.client.socket.sessionid,
  309. (error, client) => {
  310. if (error) return done(error)
  311. expect(Array.from(client.rooms).includes(this.project_id)).to.equal(
  312. false
  313. )
  314. done()
  315. }
  316. )
  317. })
  318. })
  319. describe('when deleted and web replies with a 404', function () {
  320. before(function (done) {
  321. return async.series(
  322. [
  323. cb => {
  324. return FixturesManager.setUpProject(
  325. {
  326. project_id: '404404404404404404404404', // not-found
  327. privilegeLevel: 'owner',
  328. project: {
  329. name: 'Test Project',
  330. },
  331. },
  332. (e, { project_id: projectId, user_id: userId }) => {
  333. this.project_id = projectId
  334. this.user_id = userId
  335. cb(e)
  336. }
  337. )
  338. },
  339. cb => {
  340. this.client = RealTimeClient.connect()
  341. this.client.on('connectionAccepted', cb)
  342. },
  343. cb => {
  344. this.client.emit(
  345. 'joinProject',
  346. { project_id: this.project_id },
  347. (error, project, privilegeLevel, protocolVersion) => {
  348. this.error = error
  349. this.project = project
  350. this.privilegeLevel = privilegeLevel
  351. this.protocolVersion = protocolVersion
  352. cb()
  353. }
  354. )
  355. },
  356. ],
  357. done
  358. )
  359. })
  360. it('should return an error', function () {
  361. this.error.code.should.equal('ProjectNotFound')
  362. })
  363. it('should not have joined the project room', function (done) {
  364. RealTimeClient.getConnectedClient(
  365. this.client.socket.sessionid,
  366. (error, client) => {
  367. if (error) return done(error)
  368. expect(Array.from(client.rooms).includes(this.project_id)).to.equal(
  369. false
  370. )
  371. done()
  372. }
  373. )
  374. })
  375. })
  376. describe('when invalid', function () {
  377. before(function (done) {
  378. MockWebServer.joinProject.resetHistory()
  379. return async.series(
  380. [
  381. cb => {
  382. this.client = RealTimeClient.connect()
  383. return this.client.on('connectionAccepted', cb)
  384. },
  385. cb => {
  386. return this.client.emit(
  387. 'joinProject',
  388. { project_id: 'invalid-id' },
  389. error => {
  390. this.error = error
  391. return cb()
  392. }
  393. )
  394. },
  395. ],
  396. done
  397. )
  398. })
  399. it('should return an invalid id error', function () {
  400. this.error.message.should.equal('invalid id')
  401. })
  402. it('should not call to web', function () {
  403. MockWebServer.joinProject.called.should.equal(false)
  404. })
  405. })
  406. describe('when joining more than one project', function () {
  407. before(function (done) {
  408. return async.series(
  409. [
  410. cb => {
  411. return FixturesManager.setUpProject(
  412. {
  413. privilegeLevel: 'owner',
  414. project: {
  415. name: 'Other Project',
  416. },
  417. },
  418. (e, { project_id: projectId, user_id: userId }) => {
  419. this.other_project_id = projectId
  420. this.other_user_id = userId
  421. return cb(e)
  422. }
  423. )
  424. },
  425. cb => {
  426. return FixturesManager.setUpProject(
  427. {
  428. user_id: this.other_user_id,
  429. privilegeLevel: 'owner',
  430. project: {
  431. name: 'Test Project',
  432. },
  433. },
  434. (e, { project_id: projectId, user_id: userId }) => {
  435. this.project_id = projectId
  436. this.user_id = userId
  437. return cb(e)
  438. }
  439. )
  440. },
  441. cb => {
  442. this.client = RealTimeClient.connect()
  443. return this.client.on('connectionAccepted', cb)
  444. },
  445. cb => {
  446. return this.client.emit(
  447. 'joinProject',
  448. { project_id: this.project_id },
  449. (error, project, privilegeLevel, protocolVersion) => {
  450. this.project = project
  451. this.privilegeLevel = privilegeLevel
  452. this.protocolVersion = protocolVersion
  453. return cb(error)
  454. }
  455. )
  456. },
  457. cb => {
  458. return this.client.emit(
  459. 'joinProject',
  460. { project_id: this.other_project_id },
  461. error => {
  462. this.error = error
  463. return cb()
  464. }
  465. )
  466. },
  467. ],
  468. done
  469. )
  470. })
  471. return it('should return an error', function () {
  472. this.error.message.should.equal('cannot join multiple projects')
  473. })
  474. })
  475. describe('when over rate limit', function () {
  476. before(function (done) {
  477. return async.series(
  478. [
  479. cb => {
  480. this.client = RealTimeClient.connect()
  481. return this.client.on('connectionAccepted', cb)
  482. },
  483. cb => {
  484. return this.client.emit(
  485. 'joinProject',
  486. { project_id: '429429429429429429429429' }, // rate-limited
  487. error => {
  488. this.error = error
  489. return cb()
  490. }
  491. )
  492. },
  493. ],
  494. done
  495. )
  496. })
  497. return it('should return a TooManyRequests error code', function () {
  498. this.error.message.should.equal('rate-limit hit when joining project')
  499. return this.error.code.should.equal('TooManyRequests')
  500. })
  501. })
  502. describe('when automatically joining the project', function () {
  503. describe('when authorized', function () {
  504. let connectionAcceptedReceived = false
  505. before(function (done) {
  506. async.series(
  507. [
  508. cb => {
  509. FixturesManager.setUpProject(
  510. {
  511. privilegeLevel: 'owner',
  512. project: {
  513. name: 'Test Project',
  514. },
  515. },
  516. (e, { project_id: projectId, user_id: userId }) => {
  517. this.project_id = projectId
  518. this.user_id = userId
  519. cb(e)
  520. }
  521. )
  522. },
  523. cb => {
  524. this.client = RealTimeClient.connect(
  525. `projectId=${this.project_id}`
  526. )
  527. this.client.on('connectionAccepted', () => {
  528. connectionAcceptedReceived = true
  529. })
  530. this.client.on('connectionRejected', cb)
  531. this.client.on(
  532. 'joinProjectResponse',
  533. ({ project, permissionsLevel, protocolVersion }) => {
  534. this.project = project
  535. this.permissionsLevel = permissionsLevel
  536. this.protocolVersion = protocolVersion
  537. cb()
  538. }
  539. )
  540. },
  541. ],
  542. done
  543. )
  544. })
  545. it('should not emit connectionAccepted', function () {
  546. expect(connectionAcceptedReceived).to.equal(false)
  547. })
  548. it('should get the project from web', function () {
  549. MockWebServer.joinProject
  550. .calledWith(this.project_id, this.user_id)
  551. .should.equal(true)
  552. })
  553. it('should return the project', function () {
  554. this.project.should.deep.equal({
  555. name: 'Test Project',
  556. owner: { _id: this.user_id },
  557. })
  558. })
  559. it('should return the privilege level', function () {
  560. this.permissionsLevel.should.equal('owner')
  561. })
  562. it('should return the protocolVersion', function () {
  563. this.protocolVersion.should.equal(2)
  564. })
  565. it('should have joined the project room', function (done) {
  566. RealTimeClient.getConnectedClient(
  567. this.client.socket.sessionid,
  568. (error, client) => {
  569. if (error) return done(error)
  570. expect(Array.from(client.rooms).includes(this.project_id)).to.equal(
  571. true
  572. )
  573. done()
  574. }
  575. )
  576. })
  577. it('should have marked the user as connected', function (done) {
  578. this.client.emit('clientTracking.getConnectedUsers', (error, users) => {
  579. if (error) return done(error)
  580. let connected = false
  581. for (const user of Array.from(users)) {
  582. if (
  583. user.client_id === this.client.publicId &&
  584. user.user_id === this.user_id
  585. ) {
  586. connected = true
  587. break
  588. }
  589. }
  590. expect(connected).to.equal(true)
  591. done()
  592. })
  593. })
  594. })
  595. describe('when authorized with token', function () {
  596. let connectionAcceptedReceived = false
  597. before(function (done) {
  598. async.series(
  599. [
  600. cb => {
  601. FixturesManager.setUpProject(
  602. {
  603. privilegeLevel: 'owner',
  604. publicAccess: 'readOnly',
  605. project: {
  606. name: 'Test Project',
  607. },
  608. },
  609. (
  610. e,
  611. {
  612. user_id: ownerId,
  613. project_id: projectId,
  614. anonymousAccessToken,
  615. }
  616. ) => {
  617. this.ownerId = ownerId
  618. this.project_id = projectId
  619. this.anonymousAccessToken = anonymousAccessToken
  620. cb(e)
  621. }
  622. )
  623. },
  624. cb => {
  625. RealTimeClient.setSession(
  626. {
  627. anonTokenAccess: {
  628. [this.project_id]: this.anonymousAccessToken,
  629. },
  630. },
  631. cb
  632. )
  633. },
  634. cb => {
  635. this.client = RealTimeClient.connect(
  636. `projectId=${this.project_id}`
  637. )
  638. this.client.on('connectionAccepted', () => {
  639. connectionAcceptedReceived = true
  640. })
  641. this.client.on('connectionRejected', cb)
  642. this.client.on(
  643. 'joinProjectResponse',
  644. ({ project, permissionsLevel, protocolVersion }) => {
  645. this.project = project
  646. this.permissionsLevel = permissionsLevel
  647. this.protocolVersion = protocolVersion
  648. cb()
  649. }
  650. )
  651. },
  652. ],
  653. done
  654. )
  655. })
  656. it('should not emit connectionAccepted', function () {
  657. expect(connectionAcceptedReceived).to.equal(false)
  658. })
  659. it('should get the project from web', function () {
  660. MockWebServer.joinProject
  661. .calledWith(
  662. this.project_id,
  663. 'anonymous-user',
  664. this.anonymousAccessToken
  665. )
  666. .should.equal(true)
  667. })
  668. it('should return the project', function () {
  669. this.project.should.deep.equal({
  670. name: 'Test Project',
  671. owner: { _id: this.ownerId },
  672. })
  673. })
  674. it('should return the privilege level', function () {
  675. this.permissionsLevel.should.equal('readOnly')
  676. })
  677. it('should return the protocolVersion', function () {
  678. this.protocolVersion.should.equal(2)
  679. })
  680. it('should have joined the project room', function (done) {
  681. RealTimeClient.getConnectedClient(
  682. this.client.socket.sessionid,
  683. (error, client) => {
  684. if (error) return done(error)
  685. expect(Array.from(client.rooms).includes(this.project_id)).to.equal(
  686. true
  687. )
  688. done()
  689. }
  690. )
  691. })
  692. it('should have marked the user as connected', function (done) {
  693. this.client.emit('clientTracking.getConnectedUsers', (error, users) => {
  694. if (error) return done(error)
  695. let connected = false
  696. for (const user of Array.from(users)) {
  697. if (user.client_id === this.client.publicId) {
  698. connected = true
  699. break
  700. }
  701. }
  702. expect(connected).to.equal(true)
  703. done()
  704. })
  705. })
  706. })
  707. describe('when not authorized', function () {
  708. let joinProjectResponseReceived = false
  709. before(function (done) {
  710. async.series(
  711. [
  712. cb => {
  713. FixturesManager.setUpProject(
  714. {
  715. privilegeLevel: null,
  716. project: {
  717. name: 'Test Project',
  718. },
  719. },
  720. (e, { project_id: projectId, user_id: userId }) => {
  721. this.project_id = projectId
  722. this.user_id = userId
  723. cb(e)
  724. }
  725. )
  726. },
  727. cb => {
  728. this.client = RealTimeClient.connect(
  729. `projectId=${this.project_id}`
  730. )
  731. this.client.on('connectionRejected', err => {
  732. this.error = err
  733. cb()
  734. })
  735. this.client.on('joinProjectResponse', () => {
  736. joinProjectResponseReceived = true
  737. cb()
  738. })
  739. },
  740. ],
  741. done
  742. )
  743. })
  744. it('should not emit joinProjectResponse', function () {
  745. expect(joinProjectResponseReceived).to.equal(false)
  746. })
  747. it('should have disconnected the client', function () {
  748. expect(this.client.socket.connected).to.equal(false)
  749. })
  750. it('should return an error', function () {
  751. this.error.message.should.equal('not authorized')
  752. })
  753. it('should not have joined the project room', function (done) {
  754. RealTimeClient.getConnectedClient(
  755. this.client.socket.sessionid,
  756. error => {
  757. expect(error.message).to.equal('not found')
  758. done()
  759. }
  760. )
  761. })
  762. })
  763. describe('when not authorized and web replies with a 403', function () {
  764. let joinProjectResponseReceived = false
  765. before(function (done) {
  766. async.series(
  767. [
  768. cb => {
  769. FixturesManager.setUpProject(
  770. {
  771. project_id: '403403403403403403403403', // forbidden
  772. privilegeLevel: 'owner',
  773. project: {
  774. name: 'Test Project',
  775. },
  776. },
  777. (e, { project_id: projectId, user_id: userId }) => {
  778. this.project_id = projectId
  779. this.user_id = userId
  780. cb(e)
  781. }
  782. )
  783. },
  784. cb => {
  785. this.client = RealTimeClient.connect(
  786. `projectId=${this.project_id}`
  787. )
  788. this.client.on('connectionRejected', err => {
  789. this.error = err
  790. cb()
  791. })
  792. this.client.on('joinProjectResponse', () => {
  793. joinProjectResponseReceived = true
  794. cb()
  795. })
  796. },
  797. ],
  798. done
  799. )
  800. })
  801. it('should not emit joinProjectResponse', function () {
  802. expect(joinProjectResponseReceived).to.equal(false)
  803. })
  804. it('should have disconnected the client', function () {
  805. expect(this.client.socket.connected).to.equal(false)
  806. })
  807. it('should return an error', function () {
  808. this.error.message.should.equal('not authorized')
  809. })
  810. it('should not have joined the project room', function (done) {
  811. RealTimeClient.getConnectedClient(
  812. this.client.socket.sessionid,
  813. error => {
  814. expect(error.message).to.equal('not found')
  815. done()
  816. }
  817. )
  818. })
  819. })
  820. describe('when deleted and web replies with a 404', function () {
  821. let joinProjectResponseReceived = false
  822. before(function (done) {
  823. async.series(
  824. [
  825. cb => {
  826. FixturesManager.setUpProject(
  827. {
  828. project_id: '404404404404404404404404', // not-found
  829. privilegeLevel: 'owner',
  830. project: {
  831. name: 'Test Project',
  832. },
  833. },
  834. (e, { project_id: projectId, user_id: userId }) => {
  835. this.project_id = projectId
  836. this.user_id = userId
  837. cb(e)
  838. }
  839. )
  840. },
  841. cb => {
  842. this.client = RealTimeClient.connect(
  843. `projectId=${this.project_id}`
  844. )
  845. this.client.on('connectionRejected', err => {
  846. this.error = err
  847. cb()
  848. })
  849. this.client.on('joinProjectResponse', () => {
  850. joinProjectResponseReceived = true
  851. cb()
  852. })
  853. },
  854. ],
  855. done
  856. )
  857. })
  858. it('should not emit joinProjectResponse', function () {
  859. expect(joinProjectResponseReceived).to.equal(false)
  860. })
  861. it('should have disconnected the client', function () {
  862. expect(this.client.socket.connected).to.equal(false)
  863. })
  864. it('should return an error', function () {
  865. this.error.code.should.equal('ProjectNotFound')
  866. })
  867. it('should not have joined the project room', function (done) {
  868. RealTimeClient.getConnectedClient(
  869. this.client.socket.sessionid,
  870. error => {
  871. expect(error.message).to.equal('not found')
  872. done()
  873. }
  874. )
  875. })
  876. })
  877. describe('when invalid', function () {
  878. let joinProjectResponseReceived = false
  879. before(function (done) {
  880. MockWebServer.joinProject.resetHistory()
  881. async.series(
  882. [
  883. cb => {
  884. this.client = RealTimeClient.connect('projectId=invalid-id')
  885. this.client.on('connectionRejected', err => {
  886. this.error = err
  887. cb()
  888. })
  889. this.client.on('joinProjectResponse', () => {
  890. joinProjectResponseReceived = true
  891. cb()
  892. })
  893. },
  894. ],
  895. done
  896. )
  897. })
  898. it('should not emit joinProjectResponse', function () {
  899. expect(joinProjectResponseReceived).to.equal(false)
  900. })
  901. it('should have disconnected the client', function () {
  902. expect(this.client.socket.connected).to.equal(false)
  903. })
  904. it('should return an invalid id error', function () {
  905. this.error.message.should.equal('invalid id')
  906. })
  907. it('should not call to web', function () {
  908. MockWebServer.joinProject.called.should.equal(false)
  909. })
  910. })
  911. describe('when joining more than one project', function () {
  912. before(function (done) {
  913. async.series(
  914. [
  915. cb => {
  916. FixturesManager.setUpProject(
  917. {
  918. privilegeLevel: 'owner',
  919. project: {
  920. name: 'Other Project',
  921. },
  922. },
  923. (e, { project_id: projectId, user_id: userId }) => {
  924. this.other_project_id = projectId
  925. this.other_user_id = userId
  926. cb(e)
  927. }
  928. )
  929. },
  930. cb => {
  931. FixturesManager.setUpProject(
  932. {
  933. user_id: this.other_user_id,
  934. privilegeLevel: 'owner',
  935. project: {
  936. name: 'Test Project',
  937. },
  938. },
  939. (e, { project_id: projectId, user_id: userId }) => {
  940. this.project_id = projectId
  941. this.user_id = userId
  942. cb(e)
  943. }
  944. )
  945. },
  946. cb => {
  947. this.client = RealTimeClient.connect(
  948. `projectId=${this.project_id}`
  949. )
  950. this.client.on('connectionRejected', cb)
  951. this.client.on('joinProjectResponse', () => {
  952. cb()
  953. })
  954. },
  955. cb => {
  956. this.client.emit(
  957. 'joinProject',
  958. { project_id: this.other_project_id },
  959. error => {
  960. this.error = error
  961. cb()
  962. }
  963. )
  964. },
  965. ],
  966. done
  967. )
  968. })
  969. it('should return an error', function () {
  970. this.error.message.should.equal('cannot join multiple projects')
  971. })
  972. })
  973. describe('when over rate limit', function () {
  974. let joinProjectResponseReceived = false
  975. before(function (done) {
  976. async.series(
  977. [
  978. cb => {
  979. this.client = RealTimeClient.connect(
  980. 'projectId=429429429429429429429429'
  981. )
  982. this.client.on('connectionRejected', err => {
  983. this.error = err
  984. cb()
  985. })
  986. this.client.on('joinProjectResponse', () => {
  987. joinProjectResponseReceived = true
  988. cb()
  989. })
  990. },
  991. ],
  992. done
  993. )
  994. })
  995. it('should not emit joinProjectResponse', function () {
  996. expect(joinProjectResponseReceived).to.equal(false)
  997. })
  998. it('should have disconnected the client', function () {
  999. expect(this.client.socket.connected).to.equal(false)
  1000. })
  1001. it('should return a TooManyRequests error code', function () {
  1002. this.error.message.should.equal('rate-limit hit when joining project')
  1003. this.error.code.should.equal('TooManyRequests')
  1004. })
  1005. })
  1006. })
  1007. })