current-plan-widget.test.tsx 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. import { expect } from 'chai'
  2. import sinon from 'sinon'
  3. import { fireEvent, render, screen } from '@testing-library/react'
  4. import {
  5. CommonsPlanSubscription,
  6. GroupPlanSubscription,
  7. IndividualPlanSubscription,
  8. } from '../../../../../types/project/dashboard/subscription'
  9. import { DeepReadonly } from '../../../../../types/utils'
  10. import * as eventTracking from '@/infrastructure/event-tracking'
  11. import CurrentPlanWidget from '../../../../../frontend/js/features/project-list/components/current-plan-widget/current-plan-widget'
  12. describe('<CurrentPlanWidget />', function () {
  13. const freePlanTooltipMessage =
  14. /click to find out how you could benefit from overleaf premium features/i
  15. const paidPlanTooltipMessage =
  16. /click to find out how to make the most of your overleaf premium features/i
  17. const pausedTooltipMessage =
  18. /click to unpause and reactivate your overleaf premium features/i
  19. let sendMBSpy: sinon.SinonSpy
  20. beforeEach(function () {
  21. sendMBSpy = sinon.spy(eventTracking, 'sendMB')
  22. })
  23. afterEach(function () {
  24. sendMBSpy.restore()
  25. })
  26. describe('paused', function () {
  27. beforeEach(function () {
  28. window.metaAttributesCache.set('ol-usersBestSubscription', {
  29. type: 'individual',
  30. subscription: {
  31. recurlyStatus: {
  32. state: 'paused',
  33. },
  34. },
  35. })
  36. render(<CurrentPlanWidget />)
  37. })
  38. it('shows text and tooltip on mouseover', async function () {
  39. const link = screen.getByRole('link', {
  40. name: /plan is paused/i,
  41. })
  42. fireEvent.mouseOver(link)
  43. await screen.findByRole('tooltip', { name: pausedTooltipMessage })
  44. })
  45. })
  46. describe('free plan', function () {
  47. beforeEach(function () {
  48. window.metaAttributesCache.set('ol-usersBestSubscription', {
  49. type: 'free',
  50. })
  51. render(<CurrentPlanWidget />)
  52. })
  53. it('shows text and tooltip on mouseover', async function () {
  54. const link = screen.getByRole('link', {
  55. name: /you’re on the free plan/i,
  56. })
  57. fireEvent.mouseOver(link)
  58. await screen.findByRole('tooltip', { name: freePlanTooltipMessage })
  59. })
  60. it('clicks on upgrade button', function () {
  61. const upgradeLink = screen.getByRole('link', { name: /upgrade/i })
  62. fireEvent.click(upgradeLink)
  63. expect(sendMBSpy).to.be.calledOnce
  64. expect(sendMBSpy).calledWith('upgrade-button-click', {
  65. source: 'dashboard-top',
  66. page: '/',
  67. 'project-dashboard-react': 'enabled',
  68. 'is-dashboard-sidebar-hidden': false,
  69. 'is-screen-width-less-than-768px': false,
  70. })
  71. })
  72. })
  73. describe('free plan with Personal plan name', function () {
  74. beforeEach(function () {
  75. window.metaAttributesCache.set('ol-usersBestSubscription', {
  76. type: 'individual',
  77. plan: {
  78. name: 'Free',
  79. },
  80. subscription: {
  81. planCode: 'personal',
  82. name: 'Free',
  83. },
  84. featuresPageURL: '/features',
  85. })
  86. render(<CurrentPlanWidget />)
  87. })
  88. it('shows text and tooltip on mouseover', async function () {
  89. const link = screen.getByRole('link', {
  90. name: /you’re on the free plan/i,
  91. })
  92. fireEvent.mouseOver(link)
  93. await screen.findByRole('tooltip', { name: freePlanTooltipMessage })
  94. })
  95. })
  96. describe('paid plan', function () {
  97. describe('trial', function () {
  98. const subscription = {
  99. type: 'individual',
  100. plan: {
  101. name: 'Abc',
  102. },
  103. subscription: {
  104. name: 'Example Name',
  105. },
  106. remainingTrialDays: -1,
  107. } as DeepReadonly<IndividualPlanSubscription>
  108. beforeEach(function () {
  109. window.metaAttributesCache.set('ol-usersBestSubscription', {
  110. ...subscription,
  111. })
  112. })
  113. it('shows remaining days', function () {
  114. const newSubscription: IndividualPlanSubscription = {
  115. ...subscription,
  116. remainingTrialDays: 5,
  117. }
  118. window.metaAttributesCache.set(
  119. 'ol-usersBestSubscription',
  120. newSubscription
  121. )
  122. render(<CurrentPlanWidget />)
  123. screen.getByRole('link', {
  124. name: new RegExp(
  125. `${newSubscription.remainingTrialDays} more days on your overleaf premium trial`,
  126. 'i'
  127. ),
  128. })
  129. })
  130. it('shows last day message', function () {
  131. window.metaAttributesCache.set('ol-usersBestSubscription', {
  132. ...subscription,
  133. remainingTrialDays: 1,
  134. })
  135. render(<CurrentPlanWidget />)
  136. screen.getByRole('link', {
  137. name: /this is the last day of your overleaf premium trial/i,
  138. })
  139. })
  140. })
  141. describe('individual', function () {
  142. const subscription = {
  143. type: 'individual',
  144. plan: {
  145. name: 'Abc',
  146. },
  147. subscription: {
  148. teamName: 'Example Team',
  149. name: 'Example Name',
  150. },
  151. remainingTrialDays: -1,
  152. } as DeepReadonly<IndividualPlanSubscription>
  153. beforeEach(function () {
  154. window.metaAttributesCache.set('ol-usersBestSubscription', {
  155. ...subscription,
  156. })
  157. })
  158. it('shows text and tooltip on mouseover', async function () {
  159. render(<CurrentPlanWidget />)
  160. const link = screen.getByRole('link', {
  161. name: /you’re using overleaf premium/i,
  162. })
  163. fireEvent.mouseOver(link)
  164. await screen.findByRole('tooltip', {
  165. name: new RegExp(`on the ${subscription.plan.name}`, 'i'),
  166. })
  167. await screen.findByRole('tooltip', { name: paidPlanTooltipMessage })
  168. })
  169. })
  170. describe('group', function () {
  171. const subscription = {
  172. type: 'group',
  173. plan: {
  174. name: 'Abc',
  175. },
  176. subscription: {
  177. name: 'Example Name',
  178. },
  179. remainingTrialDays: -1,
  180. } as DeepReadonly<GroupPlanSubscription>
  181. beforeEach(function () {
  182. window.metaAttributesCache.set('ol-usersBestSubscription', {
  183. ...subscription,
  184. })
  185. })
  186. it('shows text and tooltip on mouseover (without subscription team name)', async function () {
  187. render(<CurrentPlanWidget />)
  188. const link = screen.getByRole('link', {
  189. name: /you’re using overleaf premium/i,
  190. })
  191. fireEvent.mouseOver(link)
  192. expect(subscription.subscription.teamName).to.be.undefined
  193. await screen.findByRole('tooltip', {
  194. name: new RegExp(
  195. `on the ${subscription.plan.name} plan as a member of a group subscription`,
  196. 'i'
  197. ),
  198. })
  199. await screen.findByRole('tooltip', { name: paidPlanTooltipMessage })
  200. })
  201. it('shows text and tooltip on mouseover (with subscription team name)', async function () {
  202. const newSubscription = {
  203. ...subscription,
  204. subscription: {
  205. teamName: 'Example Team',
  206. },
  207. }
  208. window.metaAttributesCache.set(
  209. 'ol-usersBestSubscription',
  210. newSubscription
  211. )
  212. render(<CurrentPlanWidget />)
  213. const link = screen.getByRole('link', {
  214. name: /you’re using overleaf premium/i,
  215. })
  216. fireEvent.mouseOver(link)
  217. await screen.findByRole('tooltip', {
  218. name: new RegExp(
  219. `on the ${newSubscription.plan.name} plan as a member of a group subscription, ${newSubscription.subscription.teamName}`,
  220. 'i'
  221. ),
  222. })
  223. await screen.findByRole('tooltip', { name: paidPlanTooltipMessage })
  224. })
  225. })
  226. describe('commons', function () {
  227. it('shows text and tooltip on mouseover', async function () {
  228. const subscription = {
  229. type: 'commons',
  230. plan: {
  231. name: 'Abc',
  232. },
  233. subscription: {
  234. name: 'Example Name',
  235. },
  236. } as DeepReadonly<CommonsPlanSubscription>
  237. window.metaAttributesCache.set('ol-usersBestSubscription', {
  238. ...subscription,
  239. })
  240. render(<CurrentPlanWidget />)
  241. const link = screen.getByRole('link', {
  242. name: /you’re using overleaf premium/i,
  243. })
  244. fireEvent.mouseOver(link)
  245. await screen.findByRole('tooltip', {
  246. name: new RegExp(
  247. `on the ${subscription.plan.name} plan because of your affiliation with ${subscription.subscription.name}`,
  248. 'i'
  249. ),
  250. })
  251. await screen.findByRole('tooltip', { name: paidPlanTooltipMessage })
  252. })
  253. })
  254. })
  255. describe('features page', function () {
  256. const plans = [
  257. { type: 'free' },
  258. {
  259. type: 'individual',
  260. plan: {
  261. name: 'Abc',
  262. },
  263. },
  264. {
  265. type: 'group',
  266. plan: {
  267. name: 'Abc',
  268. },
  269. subscription: {
  270. teamName: 'Example Team',
  271. name: 'Example Name',
  272. },
  273. },
  274. {
  275. type: 'commons',
  276. plan: {
  277. name: 'Abc',
  278. },
  279. subscription: {
  280. name: 'Example Name',
  281. },
  282. },
  283. ]
  284. for (const plan of plans) {
  285. it(`links to features page on ${plan.type} plan`, function () {
  286. window.metaAttributesCache.set('ol-usersBestSubscription', {
  287. ...plan,
  288. })
  289. render(<CurrentPlanWidget />)
  290. const links = screen.getAllByRole('link')
  291. expect(links[0].getAttribute('href')).to.equal(
  292. '/learn/how-to/Overleaf_premium_features'
  293. )
  294. fireEvent.click(links[0])
  295. window.metaAttributesCache.delete('ol-usersBestSubscription')
  296. })
  297. }
  298. })
  299. })