parse-mentions.test.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import { expect } from 'chai'
  2. import {
  3. parseMentions,
  4. sliceMentionSegments,
  5. } from '@/features/review-panel/utils/parse-mentions'
  6. import { UserId } from '@ol-types/user'
  7. describe('parseMentions', function () {
  8. it('should return a single text segment for plain text', function () {
  9. expect(parseMentions('hello world')).to.deep.equal([
  10. { type: 'text', value: 'hello world' },
  11. ])
  12. })
  13. it('should return an empty array for an empty string', function () {
  14. expect(parseMentions('')).to.deep.equal([])
  15. })
  16. it('should parse a single mention', function () {
  17. const userId = 'aabbccddeeff00112233aabb' as UserId
  18. expect(parseMentions(`@[${userId}]`)).to.deep.equal([
  19. { type: 'mention', userId },
  20. ])
  21. })
  22. it('should parse text before and after a mention', function () {
  23. const userId = 'aabbccddeeff00112233aabb' as UserId
  24. expect(parseMentions(`hey @[${userId}] check this`)).to.deep.equal([
  25. { type: 'text', value: 'hey ' },
  26. { type: 'mention', userId },
  27. { type: 'text', value: ' check this' },
  28. ])
  29. })
  30. it('should parse multiple mentions', function () {
  31. const userId1 = 'aabbccddeeff00112233aabb' as UserId
  32. const userId2 = '112233445566778899aabbcc' as UserId
  33. expect(parseMentions(`@[${userId1}] and @[${userId2}]`)).to.deep.equal([
  34. { type: 'mention', userId: userId1 },
  35. { type: 'text', value: ' and ' },
  36. { type: 'mention', userId: userId2 },
  37. ])
  38. })
  39. it('should not match bare @userId without brackets', function () {
  40. expect(parseMentions('@aabbccddeeff00112233aabb')).to.deep.equal([
  41. { type: 'text', value: '@aabbccddeeff00112233aabb' },
  42. ])
  43. })
  44. it('should not match @[...] with non-hex characters', function () {
  45. expect(parseMentions('@[gghhiijjkkllmmnnooppqqrr]')).to.deep.equal([
  46. { type: 'text', value: '@[gghhiijjkkllmmnnooppqqrr]' },
  47. ])
  48. })
  49. it('should not match @[...] with wrong length', function () {
  50. expect(parseMentions('@[aabbcc]')).to.deep.equal([
  51. { type: 'text', value: '@[aabbcc]' },
  52. ])
  53. })
  54. it('should handle adjacent mentions with no text between', function () {
  55. const userId1 = 'aabbccddeeff00112233aabb' as UserId
  56. const userId2 = '112233445566778899aabbcc' as UserId
  57. expect(parseMentions(`@[${userId1}]@[${userId2}]`)).to.deep.equal([
  58. { type: 'mention', userId: userId1 },
  59. { type: 'mention', userId: userId2 },
  60. ])
  61. })
  62. it('should handle a truncated mention as plain text', function () {
  63. expect(parseMentions('@[aabbccddeeff001122')).to.deep.equal([
  64. { type: 'text', value: '@[aabbccddeeff001122' },
  65. ])
  66. })
  67. })
  68. describe('sliceMentionSegments', function () {
  69. const userId = 'aabbccddeeff00112233aabb' as UserId
  70. it('should return all segments when under the limit', function () {
  71. const segments = parseMentions(`hi @[${userId}]`)
  72. const result = sliceMentionSegments(segments, 100)
  73. expect(result).to.deep.equal(segments)
  74. })
  75. it('should truncate a text segment at the limit', function () {
  76. const segments = parseMentions('hello world')
  77. const result = sliceMentionSegments(segments, 5)
  78. expect(result).to.deep.equal([{ type: 'text', value: 'hello' }])
  79. })
  80. it('should drop a mention that crosses the limit', function () {
  81. const segments = parseMentions(`hey @[${userId}]`)
  82. // "hey " = 4 chars, mention = 27 chars raw; limit 10 leaves only 6 for mention
  83. const result = sliceMentionSegments(segments, 10)
  84. expect(result).to.deep.equal([{ type: 'text', value: 'hey ' }])
  85. })
  86. it('should include a mention that fits exactly', function () {
  87. const segments = parseMentions(`hey @[${userId}]`)
  88. // "hey " = 4 chars, mention = 27 chars; limit = 31
  89. const result = sliceMentionSegments(segments, 31)
  90. expect(result).to.deep.equal(segments)
  91. })
  92. it('should return empty array when limit is 0', function () {
  93. const segments = parseMentions('hello')
  94. const result = sliceMentionSegments(segments, 0)
  95. expect(result).to.deep.equal([])
  96. })
  97. it('should handle a mention as the first segment', function () {
  98. const segments = parseMentions(`@[${userId}] done`)
  99. // mention = 27 chars; limit 27 fits the mention but not " done"
  100. const result = sliceMentionSegments(segments, 27)
  101. expect(result).to.deep.equal([{ type: 'mention', userId }])
  102. })
  103. it('should drop a leading mention that does not fit', function () {
  104. const segments = parseMentions(`@[${userId}] done`)
  105. const result = sliceMentionSegments(segments, 10)
  106. expect(result).to.deep.equal([])
  107. })
  108. it('should handle multiple segments with truncation mid-text', function () {
  109. const userId2 = '112233445566778899aabbcc' as UserId
  110. const segments = parseMentions(`@[${userId}] and @[${userId2}]`)
  111. // mention(27) + " and "(5) = 32; limit 35 leaves 3 chars but mention needs 27
  112. const result = sliceMentionSegments(segments, 35)
  113. expect(result).to.deep.equal([
  114. { type: 'mention', userId },
  115. { type: 'text', value: ' and ' },
  116. ])
  117. })
  118. })