yjs.integ.ts 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. import { YDocStatus } from '@growi/core/dist/consts';
  2. import { Types } from 'mongoose';
  3. import type { Server } from 'socket.io';
  4. import { mock } from 'vitest-mock-extended';
  5. import { Revision } from '../../models/revision';
  6. import type { MongodbPersistence } from './extended/mongodb-persistence';
  7. import type { IYjsService } from './yjs';
  8. import { getYjsService, initializeYjsService } from './yjs';
  9. vi.mock('y-socket.io/dist/server', () => {
  10. const YSocketIO = vi.fn();
  11. YSocketIO.prototype.on = vi.fn();
  12. YSocketIO.prototype.initialize = vi.fn();
  13. return { YSocketIO };
  14. });
  15. const ObjectId = Types.ObjectId;
  16. const getPrivateMdbInstance = (yjsService: IYjsService): MongodbPersistence => {
  17. // eslint-disable-next-line dot-notation
  18. return yjsService['mdb'];
  19. };
  20. describe('YjsService', () => {
  21. describe('getYDocStatus()', () => {
  22. beforeAll(async() => {
  23. const ioMock = mock<Server>();
  24. // initialize
  25. initializeYjsService(ioMock);
  26. });
  27. afterAll(async() => {
  28. // flush revisions
  29. await Revision.deleteMany({});
  30. // flush yjs-writings
  31. const yjsService = getYjsService();
  32. const privateMdb = getPrivateMdbInstance(yjsService);
  33. await privateMdb.flushDB();
  34. });
  35. it('returns ISOLATED when neither revisions nor YDocs exists', async() => {
  36. // arrange
  37. const yjsService = getYjsService();
  38. const pageId = new ObjectId();
  39. // act
  40. const result = await yjsService.getYDocStatus(pageId.toString());
  41. // assert
  42. expect(result).toBe(YDocStatus.ISOLATED);
  43. });
  44. it('returns ISOLATED when no revisions exist', async() => {
  45. // arrange
  46. const yjsService = getYjsService();
  47. const pageId = new ObjectId();
  48. const privateMdb = getPrivateMdbInstance(yjsService);
  49. await privateMdb.setTypedMeta(pageId.toString(), 'updatedAt', 1000);
  50. // act
  51. const result = await yjsService.getYDocStatus(pageId.toString());
  52. // assert
  53. expect(result).toBe(YDocStatus.ISOLATED);
  54. });
  55. it('returns NEW when no YDocs exist', async() => {
  56. // arrange
  57. const yjsService = getYjsService();
  58. const pageId = new ObjectId();
  59. await Revision.insertMany([
  60. { pageId, body: '' },
  61. ]);
  62. // act
  63. const result = await yjsService.getYDocStatus(pageId.toString());
  64. // assert
  65. expect(result).toBe(YDocStatus.NEW);
  66. });
  67. it('returns DRAFT when the newer YDocs exist', async() => {
  68. // arrange
  69. const yjsService = getYjsService();
  70. const pageId = new ObjectId();
  71. await Revision.insertMany([
  72. { pageId, body: '' },
  73. ]);
  74. const privateMdb = getPrivateMdbInstance(yjsService);
  75. await privateMdb.setTypedMeta(pageId.toString(), 'updatedAt', (new Date(2034, 1, 1)).getTime());
  76. // act
  77. const result = await yjsService.getYDocStatus(pageId.toString());
  78. // assert
  79. expect(result).toBe(YDocStatus.DRAFT);
  80. });
  81. it('returns SYNCED', async() => {
  82. // arrange
  83. const yjsService = getYjsService();
  84. const pageId = new ObjectId();
  85. await Revision.insertMany([
  86. { pageId, body: '', createdAt: new Date(2025, 1, 1) },
  87. ]);
  88. const privateMdb = getPrivateMdbInstance(yjsService);
  89. await privateMdb.setTypedMeta(pageId.toString(), 'updatedAt', (new Date(2025, 1, 1)).getTime());
  90. // act
  91. const result = await yjsService.getYDocStatus(pageId.toString());
  92. // assert
  93. expect(result).toBe(YDocStatus.SYNCED);
  94. });
  95. it('returns OUTDATED when the latest revision is newer than meta data', async() => {
  96. // arrange
  97. const yjsService = getYjsService();
  98. const pageId = new ObjectId();
  99. await Revision.insertMany([
  100. { pageId, body: '' },
  101. ]);
  102. const privateMdb = getPrivateMdbInstance(yjsService);
  103. await privateMdb.setTypedMeta(pageId.toString(), 'updatedAt', (new Date(2024, 1, 1)).getTime());
  104. // act
  105. const result = await yjsService.getYDocStatus(pageId.toString());
  106. // assert
  107. expect(result).toBe(YDocStatus.OUTDATED);
  108. });
  109. });
  110. });