Improve types for window.metaAttributesCache (#22983)

GitOrigin-RevId: cc962bf7eeaac525267ba04080889b0d58051914
This commit is contained in:
Alf Eaton
2025-01-22 09:39:32 +00:00
committed by Copybot
parent 3295bd20ec
commit 714d9d2a02
11 changed files with 61 additions and 47 deletions

View File

@@ -72,6 +72,7 @@ export interface Meta {
'ol-cannot-reactivate-subscription': boolean
'ol-cannot-use-ai': boolean
'ol-chatEnabled': boolean
'ol-compilesUserContentDomain': string
'ol-countryCode': PricingFormState['country']
'ol-couponCode': PricingFormState['coupon']
'ol-createdAt': Date
@@ -163,9 +164,11 @@ export interface Meta {
'ol-postCheckoutRedirect': string
'ol-postUrl': string
'ol-prefetchedProjectsBlob': GetProjectsResponseBody | undefined
'ol-preventCompileOnLoad'?: boolean
'ol-primaryEmail': { email: string; confirmed: boolean }
'ol-project': any // TODO
'ol-projectHistoryBlobsEnabled': boolean
'ol-projectName': string
'ol-projectSyncSuccessMessage': string
'ol-projectTags': Tag[]
'ol-project_id': string
@@ -232,6 +235,22 @@ export interface Meta {
'ol-wsUrl': string
}
type DeepPartial<T> =
T extends Record<string, any> ? { [P in keyof T]?: DeepPartial<T[P]> } : T
export type PartialMeta = DeepPartial<Meta>
export type MetaAttributesCache<
K extends keyof PartialMeta = keyof PartialMeta,
> = Map<K, PartialMeta[K]>
export type MetaTag = {
[K in keyof Meta]: {
name: K
value: Meta[K]
}
}[keyof Meta]
// cache for parsed values
window.metaAttributesCache = window.metaAttributesCache || new Map()

View File

@@ -1,14 +1,10 @@
import type { Meta } from '@/utils/meta'
type DeepPartial<T> = T extends object
? { [P in keyof T]?: DeepPartial<T[P]> }
: T
import { PartialMeta } from '@/utils/meta'
/**
* Set values on window.metaAttributesCache, for use in Storybook stories
*/
export const useMeta = (meta: DeepPartial<Meta>) => {
export const useMeta = (meta: PartialMeta) => {
for (const [key, value] of Object.entries(meta)) {
window.metaAttributesCache.set(key, value)
window.metaAttributesCache.set(key as keyof PartialMeta, value)
}
}

View File

@@ -2,6 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react'
import { LoadingUI } from '@/features/ide-react/components/loading'
import { EditorProviders } from '../../../test/frontend/helpers/editor-providers'
import { bsVersionDecorator } from '../../../.storybook/utils/with-bootstrap-switcher'
import { PartialMeta } from '@/utils/meta'
const meta: Meta<typeof LoadingUI> = {
title: 'Loading Page / Loading',
@@ -35,7 +36,7 @@ const errorMessages = {
export const LoadingPage: Story = {
render: args => {
for (const [key, value] of Object.entries(errorMessages)) {
window.metaAttributesCache.set(`ol-${key}`, value)
window.metaAttributesCache.set(`ol-${key}` as keyof PartialMeta, value)
}
return (
<EditorProviders>

View File

@@ -11,10 +11,6 @@ describe('<AddSeats />', function () {
cy.window().then(win => {
win.metaAttributesCache.set('ol-groupName', 'My Awesome Team')
win.metaAttributesCache.set('ol-subscriptionId', '123')
win.metaAttributesCache.set(
'ol-subscriptionEndsAt',
'2025-01-01T12:00:00.000Z'
)
win.metaAttributesCache.set('ol-totalLicenses', this.totalLicenses)
win.metaAttributesCache.set('ol-isProfessional', false)
})

View File

@@ -5,8 +5,9 @@ import {
cleanUpContext,
renderWithSubscriptionDashContext,
} from '../../helpers/render-with-subscription-dash-context'
import { Institution } from '../../../../../../types/institution'
const memberships = [
const memberships: Institution[] = [
{
id: 9258,
name: 'Test University',
@@ -16,6 +17,7 @@ const memberships = [
ssoBeta: false,
ssoEnabled: false,
maxConfirmationMonths: 6,
writefullCommonsAccount: false,
},
{
id: 9259,
@@ -26,6 +28,7 @@ const memberships = [
ssoBeta: false,
ssoEnabled: true,
maxConfirmationMonths: 12,
writefullCommonsAccount: false,
},
]

View File

@@ -22,6 +22,7 @@ import {
subscriptionUpdateUrl,
} from '../../../../../../../../frontend/js/features/subscription/data/subscription-url'
import * as useLocationModule from '../../../../../../../../frontend/js/shared/hooks/use-location'
import { MetaTag } from '@/utils/meta'
describe('<ActiveSubscription />', function () {
let sendMBSpy: sinon.SinonSpy
@@ -318,9 +319,9 @@ describe('<ActiveSubscription />', function () {
})
describe('extend trial', function () {
const canExtend = {
const canExtend: MetaTag = {
name: 'ol-userCanExtendTrial',
value: 'true',
value: true,
}
const cancelButtonText = 'No thanks, I still want to cancel'
const extendTrialButtonText = 'Ill take it!'

View File

@@ -23,8 +23,6 @@ import { renderActiveSubscription } from '../../../../../helpers/render-active-s
import * as useLocationModule from '../../../../../../../../../frontend/js/shared/hooks/use-location'
describe('<ChangePlanModal />', function () {
const plansMetaTag = { name: 'ol-plans', value: plans }
let reloadStub: sinon.SinonStub
beforeEach(function () {
@@ -83,7 +81,7 @@ describe('<ChangePlanModal />', function () {
{
metaTags: [
{ name: 'ol-subscription', value: annualActiveSubscription },
plansMetaTag,
{ name: 'ol-plans', value: plans },
],
}
)

View File

@@ -3,22 +3,22 @@ import { screen, within } from '@testing-library/react'
import SuccessfulSubscription from '../../../../../../frontend/js/features/subscription/components/successful-subscription/successful-subscription'
import { renderWithSubscriptionDashContext } from '../../helpers/render-with-subscription-dash-context'
import { annualActiveSubscription } from '../../fixtures/subscriptions'
import { ExposedSettings } from '../../../../../../types/exposed-settings'
describe('successful subscription page', function () {
it('renders the invoices link', function () {
const adminEmail = 'foo@example.com'
const options = {
renderWithSubscriptionDashContext(<SuccessfulSubscription />, {
metaTags: [
{
name: 'ol-ExposedSettings',
value: {
adminEmail,
},
} as ExposedSettings,
},
{ name: 'ol-subscription', value: annualActiveSubscription },
],
}
renderWithSubscriptionDashContext(<SuccessfulSubscription />, options)
})
screen.getByRole('heading', { name: /thanks for subscribing/i })
const alert = screen.getByRole('alert')

View File

@@ -2,30 +2,31 @@ import { ActiveSubscription } from '../../../../../frontend/js/features/subscrip
import { RecurlySubscription } from '../../../../../types/subscription/dashboard/subscription'
import { groupPlans, plans } from '../fixtures/plans'
import { renderWithSubscriptionDashContext } from './render-with-subscription-dash-context'
import { MetaTag } from '@/utils/meta'
import { CurrencyCode } from '../../../../../types/subscription/currency'
export function renderActiveSubscription(
subscription: RecurlySubscription,
tags: { name: string; value: string | object | Array<object> }[] = [],
currencyCode?: string
tags: MetaTag[] = [],
currencyCode?: CurrencyCode
) {
const renderOptions = {
currencyCode,
metaTags: [
...tags,
{ name: 'ol-plans', value: plans },
{
name: 'ol-groupPlans',
value: groupPlans,
},
{ name: 'ol-subscription', value: subscription },
{
name: 'ol-recommendedCurrency',
value: currencyCode || 'USD',
},
],
}
renderWithSubscriptionDashContext(
<ActiveSubscription subscription={subscription} />,
renderOptions
{
currencyCode,
metaTags: [
...tags,
{ name: 'ol-plans', value: plans },
{
name: 'ol-groupPlans',
value: groupPlans,
},
{ name: 'ol-subscription', value: subscription },
{
name: 'ol-recommendedCurrency',
value: currencyCode || 'USD',
},
],
}
)
}

View File

@@ -4,14 +4,12 @@ import { SubscriptionDashboardProvider } from '../../../../../frontend/js/featur
import { groupPriceByUsageTypeAndSize, plans } from '../fixtures/plans'
import fetchMock from 'fetch-mock'
import { SplitTestProvider } from '@/shared/context/split-test-context'
import { MetaTag } from '@/utils/meta'
export function renderWithSubscriptionDashContext(
component: React.ReactElement,
options?: {
metaTags?: {
name: string
value: string | object | Array<object> | boolean
}[]
metaTags?: MetaTag[]
recurlyNotLoaded?: boolean
queryingRecurly?: boolean
currencyCode?: string
@@ -28,7 +26,7 @@ export function renderWithSubscriptionDashContext(
)
options?.metaTags?.forEach(tag =>
window.metaAttributesCache.set(tag.name, tag.value)
window.metaAttributesCache.set(tag!.name, tag!.value)
)
window.metaAttributesCache.set('ol-user', {})

View File

@@ -1,10 +1,11 @@
import 'recurly__recurly-js'
import { ScopeValueStore } from './ide/scope-value-store'
import { MetaAttributesCache } from '@/utils/meta'
declare global {
// eslint-disable-next-line no-unused-vars
interface Window {
metaAttributesCache: Map<string, any>
metaAttributesCache: MetaAttributesCache
_ide: Record<string, unknown> & {
$scope: Record<string, unknown> & {
pdf?: {