preview-subscription-change.test.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import sinon from 'sinon'
  2. import { fireEvent, render, screen, waitFor } from '@testing-library/react'
  3. import fetchMock from 'fetch-mock'
  4. import { cloneDeep } from 'lodash'
  5. import PreviewSubscriptionChange from '../../../../../../frontend/js/features/subscription/components/preview-subscription-change/root'
  6. import { SubscriptionChangePreview } from '../../../../../../types/subscription/subscription-change-preview'
  7. import { location } from '@/shared/components/location'
  8. const premiumPreview: SubscriptionChangePreview = {
  9. change: {
  10. type: 'premium-subscription',
  11. plan: { code: 'professional-annual', name: 'Overleaf Professional' },
  12. },
  13. currency: 'USD',
  14. paymentMethod: 'Visa **** 1111',
  15. netTerms: 0,
  16. nextPlan: { annual: true },
  17. immediateCharge: {
  18. subtotal: 100,
  19. tax: 20,
  20. total: 120,
  21. discount: 0,
  22. lineItems: [],
  23. },
  24. nextInvoice: {
  25. date: '2026-05-01T00:00:00.000Z',
  26. plan: { name: 'Overleaf Professional', amount: 100 },
  27. addOns: [],
  28. subtotal: 100,
  29. tax: { rate: 0.2, amount: 20 },
  30. total: 120,
  31. },
  32. }
  33. describe('<PreviewSubscriptionChange/> upgrade variant', function () {
  34. beforeEach(function () {
  35. this.locationWrapperSandbox = sinon.createSandbox()
  36. this.locationWrapperStub = this.locationWrapperSandbox.stub(location)
  37. })
  38. afterEach(function () {
  39. fetchMock.removeRoutes().clearHistory()
  40. this.locationWrapperSandbox.restore()
  41. })
  42. it('renders the "Upgrade to Pro" heading for a professional plan', function () {
  43. window.metaAttributesCache.set(
  44. 'ol-subscriptionChangePreview',
  45. premiumPreview
  46. )
  47. render(<PreviewSubscriptionChange />)
  48. screen.getByRole('heading', { name: /upgrade to pro/i })
  49. })
  50. it('renders the "Upgrade to Standard" heading for a collaborator plan', function () {
  51. const preview = cloneDeep(premiumPreview)
  52. preview.change = {
  53. type: 'premium-subscription',
  54. plan: { code: 'collaborator-annual', name: 'Overleaf Standard' },
  55. }
  56. window.metaAttributesCache.set('ol-subscriptionChangePreview', preview)
  57. render(<PreviewSubscriptionChange />)
  58. screen.getByRole('heading', { name: /upgrade to standard/i })
  59. })
  60. it('renders the payment summary, due today and future payments sections', function () {
  61. window.metaAttributesCache.set(
  62. 'ol-subscriptionChangePreview',
  63. premiumPreview
  64. )
  65. render(<PreviewSubscriptionChange />)
  66. screen.getByRole('heading', { name: /payment summary/i })
  67. screen.getByRole('heading', { name: /due today/i })
  68. screen.getByText(/total today/i)
  69. screen.getByRole('heading', { name: /future payments/i })
  70. })
  71. it('redirects to the thank-you page with upgrade=true after a successful payment', async function () {
  72. fetchMock.post('/user/subscription/update', 200)
  73. window.metaAttributesCache.set(
  74. 'ol-subscriptionChangePreview',
  75. premiumPreview
  76. )
  77. render(<PreviewSubscriptionChange />)
  78. fireEvent.click(screen.getByRole('button', { name: /upgrade now/i }))
  79. await waitFor(() => {
  80. sinon.assert.calledOnce(this.locationWrapperStub.replace)
  81. })
  82. sinon.assert.calledWithMatch(
  83. this.locationWrapperStub.replace,
  84. '/user/subscription/thank-you?upgrade=true'
  85. )
  86. })
  87. })