diff --git a/.github/workflows/release-create-release-candidate-branch.yml b/.github/workflows/release-create-release-candidate-branch.yml index c59aaf2b1..b9c0d72af 100644 --- a/.github/workflows/release-create-release-candidate-branch.yml +++ b/.github/workflows/release-create-release-candidate-branch.yml @@ -28,7 +28,7 @@ jobs: git config user.name "${{ env.GH_USER }}" git config user.email "${{ env.GH_EMAIL }}" git fetch origin ${{ github.ref_name }} - git merge origin/${{ github.ref_name }} + git merge origin/${{ github.ref_name }} --allow-unrelated-histories yarn && yarn workspace @jwp/ott-web run i18next env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test-static-analysis.yml b/.github/workflows/test-static-analysis.yml index 5f4077bae..cdf4c8b39 100644 --- a/.github/workflows/test-static-analysis.yml +++ b/.github/workflows/test-static-analysis.yml @@ -27,7 +27,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} diff --git a/CHANGELOG.md b/CHANGELOG.md index e2dbb8c2f..f0e3d55ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,20 @@ +## [6.11.0](https://github.com/jwplayer/ott-web-app/compare/v6.10.0...v6.11.0) (2025-09-05) + + +### Features + +* add e2e tests for content lists ([#689](https://github.com/jwplayer/ott-web-app/issues/689)) ([fab2ff1](https://github.com/jwplayer/ott-web-app/commit/fab2ff1ef421aa01b532c430e790fd74d1c79f85)) +* add e2e tests for translations ([#687](https://github.com/jwplayer/ott-web-app/issues/687)) ([0bc69a7](https://github.com/jwplayer/ott-web-app/commit/0bc69a7514eff2a61573b034dd7bb6fcf197617d)) +* movie screen by composition ([6f0a73e](https://github.com/jwplayer/ott-web-app/commit/6f0a73e9783169f0f9efbfaff723740b52703466)) +* Reference implementation of the labels filter in the web app ([#682](https://github.com/jwplayer/ott-web-app/issues/682)) ([5184a76](https://github.com/jwplayer/ott-web-app/commit/5184a764511b5cba897acb0c180d8c5fdcd924c4)) + + +### Bug Fixes + +* Fix broken SCA flow payment finalization ([#677](https://github.com/jwplayer/ott-web-app/issues/677)) ([405f5e5](https://github.com/jwplayer/ott-web-app/commit/405f5e5a0310e2188f9bcfdbc7c54594876a48fd)) +* **i18n:** update i18n keys ([#683](https://github.com/jwplayer/ott-web-app/issues/683)) ([c8f9a24](https://github.com/jwplayer/ott-web-app/commit/c8f9a24f2d7c192b5f736096837b3d5d7421d3f7)) +* Trial period displayed incorrectly ([#676](https://github.com/jwplayer/ott-web-app/issues/676)) ([e139359](https://github.com/jwplayer/ott-web-app/commit/e139359e2bdc43248442a090568b082ba2902db9)) + ## [6.10.0](https://github.com/jwplayer/ott-web-app/compare/v6.9.0...v6.10.0) (2025-04-09) diff --git a/configs/eslint-config-jwp/package.json b/configs/eslint-config-jwp/package.json index fcd944b25..b6dd6ef35 100644 --- a/configs/eslint-config-jwp/package.json +++ b/configs/eslint-config-jwp/package.json @@ -7,11 +7,11 @@ "test": "exit 0" }, "devDependencies": { - "@typescript-eslint/eslint-plugin": "^8.17.0", - "@typescript-eslint/parser": "^8.17.0", + "@typescript-eslint/eslint-plugin": "^8.26.1", + "@typescript-eslint/parser": "^8.26.1", "confusing-browser-globals": "^1.0.11", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-react": "^7.37.2", + "eslint-plugin-react": "^7.37.4", "eslint-plugin-react-hooks": "^4.6.2" } } diff --git a/configs/postcss-config-jwp/package.json b/configs/postcss-config-jwp/package.json index af44fa259..6ef9a2d69 100644 --- a/configs/postcss-config-jwp/package.json +++ b/configs/postcss-config-jwp/package.json @@ -8,7 +8,7 @@ "test": "exit 0" }, "devDependencies": { - "postcss": "^8.4.49", + "postcss": "^8.5.3", "postcss-import": "^14.1.0", "postcss-scss": "^4.0.9", "stylelint": "^15.11.0" diff --git a/configs/stylelint-config-jwp/package.json b/configs/stylelint-config-jwp/package.json index 60dd5c856..3e189d1d1 100644 --- a/configs/stylelint-config-jwp/package.json +++ b/configs/stylelint-config-jwp/package.json @@ -10,7 +10,7 @@ "devDependencies": { "stylelint": "^15.11.0", "stylelint-config-recommended-scss": "^13.1.0", - "stylelint-declaration-strict-value": "^1.10.6", + "stylelint-declaration-strict-value": "^1.10.11", "stylelint-order": "^6.0.4", "stylelint-scss": "^5.3.2" } diff --git a/docs/configuration.md b/docs/configuration.md index 0413dce0d..827a72dcf 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -104,8 +104,8 @@ each shelf separately. **content[].contentId** -The eight-character Playlists IDs from the JW Player dashboard. These IDs populate the video "shelves" on your site. * -*contentId** is not required if you use `continue_watching` or `favorites` **type**. +The eight-character Playlists IDs from the JW Player dashboard. These IDs populate the video "shelves" on your site. \* +\*contentId** is not required if you use `continue_watching` or `favorites` **type\*\*. --- @@ -145,6 +145,16 @@ You can change the background color of the shelf with the help of this property --- +**content[].filterTags** (optional) + +You can optionally define a list of comma separated labels which are used to filter shelves. + +The OTT Web App offers a demonstration of its filtering capabilities. This example can be enabled by configuring the `enableLabelsFiltering` custom parameter. + +Filtering by device type, country, and day of week is supported. See the `Home.tsx` file for a code example. + +--- + **styling** Use the `styling` object to define extra styles for your application. @@ -305,11 +315,11 @@ Note, this setting is ignored if Cleeng is not enabled (i.e. there is not Cleeng **integrations.cleeng.monthlyOffer** (optional) If Cleeng is enabled, and you want to show the Payments and Subscription functionality, you need to include at least one -offer ID (either this or the yearly offer property). -The application uses this ID to map to an offer that you've configured in your Cleeng environment under Offers to -represent your monthly subscription. +offer ID (either this or the yearly offer property). +The application uses this ID to map to an offer that you've configured in your Cleeng environment under Offers to +represent your monthly subscription. Note that only the data used from the Cleeng offer is the price, the free days, and the free period, -and the app does not verify if the offer length is actually monthly. +and the app does not verify if the offer length is actually monthly. If no monthly or yearly offer is configured, the Payments section will not be shown. --- diff --git a/knip.config.ts b/knip.config.ts index 21ae954d8..4d14b90da 100644 --- a/knip.config.ts +++ b/knip.config.ts @@ -21,6 +21,7 @@ const config: KnipConfig = { 'packages/ui-react': { entry: ['src/**/*'], ignoreDependencies: [ + '@types/dompurify', // Somehow this is not recognised 'sass-embedded', // Used in Vite 'postcss-config-jwp', // Used in postcss.config ], @@ -29,11 +30,8 @@ const config: KnipConfig = { ignoreDependencies: [ '@codeceptjs/allure-legacy', '@codeceptjs/configure', // Used in e2e tests - '@babel/plugin-proposal-decorators', // Used to build with decorators for ioc resolution - '@babel/core', // Required peer dependency for babel plugins '@jwp/ott-testing', // Used in e2e testing '@types/luxon', // Used in tests - 'babel-plugin-transform-typescript-metadata', // Used to build with decorators for ioc resolution 'core-js', // Conditionally imported at build time 'eslint-plugin-codeceptjs', // Used by apps/web/test-e2e/.eslintrc.cjs 'i18next-parser', diff --git a/package.json b/package.json index a7bcfa42c..843e7a6a1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@jwp/ott", - "version": "6.10.0", + "version": "6.11.0", "private": true, "license": "Apache-2.0", "repository": "https://github.com/jwplayer/ott-web-app.git", @@ -32,37 +32,34 @@ "pre-commit": "yarn depcheck && lint-staged", "prepare": "husky install", "test": "TZ=UTC LC_ALL=en_US.UTF-8 vitest run", + "test-update": "TZ=UTC LC_ALL=en_US.UTF-8 vitest run -u", "test-watch": "TZ=UTC LC_ALL=en_US.UTF-8 vitest", "web": "yarn --cwd platforms/web", "access-bridge": "yarn --cwd platforms/access-bridge" }, "devDependencies": { - "@commitlint/cli": "^19.6.0", - "@commitlint/config-conventional": "^19.6.0", - "@types/node": "^22.10.1", + "@babel/core": "^7.26.10", + "@babel/plugin-proposal-decorators": "^7.25.9", + "@commitlint/cli": "^19.8.0", + "@commitlint/config-conventional": "^19.8.0", + "@types/node": "^22.13.10", "csv-parse": "^5.6.0", "eslint": "^8.57.1", "eslint-config-jwp": "*", "husky": "^6.0.0", - "i18next-parser-workspaces": "^0.2.0", - "knip": "^5.39.1", - "lint-staged": "^15.2.10", + "i18next-parser-workspaces": "^0.2.1", + "knip": "^5.61.2", + "lint-staged": "^15.4.3", "npm-run-all": "^4.1.5", "prettier": "^2.8.8", "read": "^2.1.0", "ts-node": "^10.9.2", - "typescript": "5.7.2", - "vitest": "^2.1.8" + "typescript": "5.8.3", + "vitest": "^3.0.8" }, "resolutions": { - "axios": "^0.29.0", + "axios": "^0.30.0", "cheerio": "1.0.0-rc.12", - "codeceptjs/**/fast-xml-parser": "^4.5.0", - "eslint/**/cross-spawn": "^7.0.6", - "lint-staged/**/cross-spawn": "^7.0.6", - "npm-run-all/**/cross-spawn": "^6.0.6", - "micromatch": ">=4.0.8", - "vitest/**/vite": "^5.4.11", - "ws": ">=5.2.4" + "**/minimatch/brace-expansion": "^1.1.12" } } diff --git a/packages/common/package.json b/packages/common/package.json index bf8ebec41..b1e621684 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -11,15 +11,15 @@ "dependencies": { "@inplayer-org/inplayer.js": "^3.13.28", "date-fns": "^4.1.0", - "fast-xml-parser": "^4.5.0", - "i18next": "^24.0.5", + "fast-xml-parser": "^4.5.3", + "i18next": "^24.2.2", "ini": "^3.0.1", - "inversify": "^6.1.5", + "inversify": "^7.5.4", "jwt-decode": "^4.0.0", "lodash.merge": "^4.6.2", - "react-i18next": "^15.1.3", + "react-i18next": "^15.4.1", "reflect-metadata": "^0.2.2", - "yup": "^1.4.0", + "yup": "^1.6.1", "zustand": "^4.5.5" }, "devDependencies": { @@ -27,9 +27,9 @@ "@types/ini": "^1.3.34", "@types/lodash.merge": "^4.6.9", "eslint-config-jwp": "*", - "jsdom": "^22.1.0", + "jsdom": "^26.0.0", "timezone-mock": "^1.3.6", "vi-fetch": "^0.8.0", - "vitest": "^2.1.8" + "vitest": "^3.0.8" } } diff --git a/packages/common/src/modules/container.ts b/packages/common/src/modules/container.ts index 863b2c514..bd14085ca 100644 --- a/packages/common/src/modules/container.ts +++ b/packages/common/src/modules/container.ts @@ -1,13 +1,13 @@ -import { Container, injectable, type interfaces, inject } from 'inversify'; +import { Container, injectable, type ServiceIdentifier, inject } from 'inversify'; -export const container = new Container({ defaultScope: 'Singleton', skipBaseClassChecks: true }); +export const container = new Container({ defaultScope: 'Singleton' }); export { injectable, inject }; -export function getModule(constructorFunction: interfaces.ServiceIdentifier, required: false): T | undefined; -export function getModule(constructorFunction: interfaces.ServiceIdentifier, required: true): T; -export function getModule(constructorFunction: interfaces.ServiceIdentifier): T; -export function getModule(constructorFunction: interfaces.ServiceIdentifier, required = true): T | undefined { +export function getModule(constructorFunction: ServiceIdentifier, required: false): T | undefined; +export function getModule(constructorFunction: ServiceIdentifier, required: true): T; +export function getModule(constructorFunction: ServiceIdentifier): T; +export function getModule(constructorFunction: ServiceIdentifier, required = true): T | undefined { const module = container.getAll(constructorFunction)[0]; if (required && !module) throw new Error(`Service / Controller '${String(constructorFunction)}' not found`); @@ -15,14 +15,14 @@ export function getModule(constructorFunction: interfaces.ServiceIdentifier(constructorFunction: interfaces.ServiceIdentifier): T[] { +export function getAllModules(constructorFunction: ServiceIdentifier): T[] { return container.getAll(constructorFunction); } -export function getNamedModule(constructorFunction: interfaces.ServiceIdentifier, name: string | null, required: false): T | undefined; -export function getNamedModule(constructorFunction: interfaces.ServiceIdentifier, name: string | null, required: true): T; -export function getNamedModule(constructorFunction: interfaces.ServiceIdentifier, name: string | null): T; -export function getNamedModule(constructorFunction: interfaces.ServiceIdentifier, name: string | null, required = true): T | undefined { +export function getNamedModule(constructorFunction: ServiceIdentifier, name: string | null, required: false): T | undefined; +export function getNamedModule(constructorFunction: ServiceIdentifier, name: string | null, required: true): T; +export function getNamedModule(constructorFunction: ServiceIdentifier, name: string | null): T; +export function getNamedModule(constructorFunction: ServiceIdentifier, name: string | null, required = true): T | undefined { if (!name) { // if no name is given we throw an error to satisfy the non-nullable return type if (required) { @@ -34,7 +34,7 @@ export function getNamedModule(constructorFunction: interfaces.ServiceIdentif let module; try { - module = container.getAllNamed(constructorFunction, name)[0]; + module = container.getAll(constructorFunction, { name })[0]; return module; } catch (err: unknown) { diff --git a/packages/common/src/modules/functions/getApiAccessBridgeUrl.ts b/packages/common/src/modules/functions/getApiAccessBridgeUrl.ts index ac33a02ff..f494f4a39 100644 --- a/packages/common/src/modules/functions/getApiAccessBridgeUrl.ts +++ b/packages/common/src/modules/functions/getApiAccessBridgeUrl.ts @@ -1,4 +1,4 @@ -import type { interfaces } from 'inversify'; +import type { ResolutionContext } from 'inversify'; import AppController from '../../controllers/AppController'; @@ -7,6 +7,6 @@ import AppController from '../../controllers/AppController'; * If the access bridge URL is defined in the application's .ini configuration file, * the function returns the URL. If the value is not defined, it returns `undefined`. */ -export const getApiAccessBridgeUrl = (context: interfaces.Context) => { - return context.container.get(AppController).getApiAccessBridgeUrl(); +export const getApiAccessBridgeUrl = (context: ResolutionContext) => { + return context.get(AppController).getApiAccessBridgeUrl(); }; diff --git a/packages/common/src/modules/functions/getIntegrationType.ts b/packages/common/src/modules/functions/getIntegrationType.ts index 8b3b88678..853a083a1 100644 --- a/packages/common/src/modules/functions/getIntegrationType.ts +++ b/packages/common/src/modules/functions/getIntegrationType.ts @@ -1,4 +1,4 @@ -import type { interfaces } from 'inversify'; +import type { ResolutionContext } from 'inversify'; import AppController from '../../controllers/AppController'; @@ -6,6 +6,6 @@ import AppController from '../../controllers/AppController'; * This function is used to get the integration type from the AppController and is mainly used for getting named * modules from the container registry. */ -export const getIntegrationType = (context: interfaces.Context) => { - return context.container.get(AppController).getIntegrationType(); +export const getIntegrationType = (context: ResolutionContext) => { + return context.get(AppController).getIntegrationType(); }; diff --git a/packages/common/src/modules/register.ts b/packages/common/src/modules/register.ts index f50af0300..4b48f6da6 100644 --- a/packages/common/src/modules/register.ts +++ b/packages/common/src/modules/register.ts @@ -72,8 +72,8 @@ container.bind(CheckoutController).toSelf(); container.bind(AccessController).toSelf(); // EPG services -container.bind(EpgService).to(JWEpgService).whenTargetNamed(EPG_TYPE.jwp); -container.bind(EpgService).to(ViewNexaEpgService).whenTargetNamed(EPG_TYPE.viewNexa); +container.bind(EpgService).to(JWEpgService).whenNamed(EPG_TYPE.jwp); +container.bind(EpgService).to(ViewNexaEpgService).whenNamed(EPG_TYPE.viewNexa); // Functions container.bind(INTEGRATION_TYPE).toDynamicValue(getIntegrationType); @@ -82,14 +82,14 @@ container.bind(API_ACCESS_BRIDGE_URL).toDynamicValue(getApiAccessBridgeUrl); // Cleeng integration container.bind(DETERMINE_INTEGRATION_TYPE).toConstantValue(isCleengIntegrationType); container.bind(CleengService).toSelf(); -container.bind(AccountService).to(CleengAccountService).whenTargetNamed(INTEGRATION.CLEENG); -container.bind(CheckoutService).to(CleengCheckoutService).whenTargetNamed(INTEGRATION.CLEENG); -container.bind(SubscriptionService).to(CleengSubscriptionService).whenTargetNamed(INTEGRATION.CLEENG); +container.bind(AccountService).to(CleengAccountService).whenNamed(INTEGRATION.CLEENG); +container.bind(CheckoutService).to(CleengCheckoutService).whenNamed(INTEGRATION.CLEENG); +container.bind(SubscriptionService).to(CleengSubscriptionService).whenNamed(INTEGRATION.CLEENG); // JWP integration container.bind(DETERMINE_INTEGRATION_TYPE).toConstantValue(isJwpIntegrationType); container.bind(JWPAPIService).toSelf(); container.bind(JWPEntitlementService).toSelf(); -container.bind(AccountService).to(JWPAccountService).whenTargetNamed(INTEGRATION.JWP); -container.bind(CheckoutService).to(JWPCheckoutService).whenTargetNamed(INTEGRATION.JWP); -container.bind(SubscriptionService).to(JWPSubscriptionService).whenTargetNamed(INTEGRATION.JWP); +container.bind(AccountService).to(JWPAccountService).whenNamed(INTEGRATION.JWP); +container.bind(CheckoutService).to(JWPCheckoutService).whenNamed(INTEGRATION.JWP); +container.bind(SubscriptionService).to(JWPSubscriptionService).whenNamed(INTEGRATION.JWP); diff --git a/packages/common/src/services/ApiService.ts b/packages/common/src/services/ApiService.ts index 0f36588c1..368c4e9d6 100644 --- a/packages/common/src/services/ApiService.ts +++ b/packages/common/src/services/ApiService.ts @@ -69,9 +69,9 @@ export default class ApiService { * Transform incoming content lists */ protected transformContentList = (contentList: ContentList, language: string): Playlist => { - const { list, ...rest } = contentList; + const { list, id, ...rest } = contentList; - const playlist: Playlist = { ...rest, playlist: [] }; + const playlist: Playlist = { ...rest, feedid: id, playlist: [] }; playlist.playlist = list.map((item) => { const { custom_params, media_id, description, tags, ...rest } = item; diff --git a/packages/common/src/utils/configSchema.ts b/packages/common/src/utils/configSchema.ts index a24bf5732..c06ad6e79 100644 --- a/packages/common/src/utils/configSchema.ts +++ b/packages/common/src/utils/configSchema.ts @@ -9,6 +9,7 @@ const contentSchema: ObjectSchema = object({ backgroundColor: string().nullable().optional(), type: string().oneOf(['playlist', 'continue_watching', 'favorites', 'content_list']).required(), custom: object().optional(), + filterTags: string().optional(), }).defined(); const menuSchema: ObjectSchema = object().shape({ diff --git a/packages/common/test/mockService.ts b/packages/common/test/mockService.ts index f0b1b7176..368a5116f 100644 --- a/packages/common/test/mockService.ts +++ b/packages/common/test/mockService.ts @@ -1,8 +1,8 @@ -import type { interfaces } from 'inversify'; +import type { ServiceIdentifier } from 'inversify'; import { afterEach } from 'vitest'; type ServiceMockEntry = { - serviceIdentifier: interfaces.ServiceIdentifier; + serviceIdentifier: ServiceIdentifier; implementation: unknown; }; @@ -10,10 +10,9 @@ export type OptionalMembers = { [K in keyof T]?: T[K] }; export let mockedServices: ServiceMockEntry[] = []; -const getName = (serviceIdentifier: interfaces.ServiceIdentifier) => - serviceIdentifier instanceof Function ? serviceIdentifier.name : serviceIdentifier.toString(); +const getName = (serviceIdentifier: ServiceIdentifier) => (serviceIdentifier instanceof Function ? serviceIdentifier.name : serviceIdentifier.toString()); -export const mockService = >(serviceIdentifier: interfaces.ServiceIdentifier, implementation: B, override = false) => { +export const mockService = >(serviceIdentifier: ServiceIdentifier, implementation: B, override = false) => { if (!override && mockedServices.some((mock) => mock.serviceIdentifier === serviceIdentifier)) { throw new Error(`There already is a mocked service for ${getName(serviceIdentifier)}`); } @@ -34,7 +33,7 @@ afterEach(() => { vi.mock('@jwp/ott-common/src/modules/container', async () => { const actual = (await vi.importActual('@jwp/ott-common/src/modules/container')) as Record; - const getModule = (serviceIdentifier: interfaces.ServiceIdentifier) => { + const getModule = (serviceIdentifier: ServiceIdentifier) => { const mockedService = mockedServices.find((current) => current.serviceIdentifier === serviceIdentifier); if (!mockedService) { @@ -44,7 +43,7 @@ vi.mock('@jwp/ott-common/src/modules/container', async () => { return mockedService.implementation; }; - const getAllModules = (serviceIdentifier: interfaces.ServiceIdentifier) => { + const getAllModules = (serviceIdentifier: ServiceIdentifier) => { const mockedService = mockedServices.find((current) => current.serviceIdentifier === serviceIdentifier); return mockedService ? [mockedService.implementation] : []; @@ -54,7 +53,7 @@ vi.mock('@jwp/ott-common/src/modules/container', async () => { ...actual, getModule, getAllModules, - getNamedModule: (serviceIdentifier: interfaces.ServiceIdentifier, _name: string) => { + getNamedModule: (serviceIdentifier: ServiceIdentifier, _name: string) => { return getModule(serviceIdentifier); }, }; diff --git a/packages/common/types/config.ts b/packages/common/types/config.ts index a09ba23bb..c608ba23f 100644 --- a/packages/common/types/config.ts +++ b/packages/common/types/config.ts @@ -51,6 +51,7 @@ export type Content = { featured?: boolean; backgroundColor?: string | null; custom?: Record; + filterTags?: string; }; export type Menu = { diff --git a/packages/hooks-react/package.json b/packages/hooks-react/package.json index 6cfa3651d..7df9eced1 100644 --- a/packages/hooks-react/package.json +++ b/packages/hooks-react/package.json @@ -11,22 +11,22 @@ "dependencies": { "@jwp/ott-common": "*", "date-fns": "^4.1.0", - "i18next": "^24.0.5", + "i18next": "^24.2.2", "planby": "^0.3.0", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-i18next": "^15.1.3", + "react-i18next": "^15.4.1", "react-query": "^3.39.3", "reflect-metadata": "^0.2.2", - "yup": "^1.4.0" + "yup": "^1.6.1" }, "devDependencies": { "@jwp/ott-testing": "*", "@testing-library/react": "^14.3.1", "@types/jwplayer": "^8.31.3", "eslint-config-jwp": "*", - "jsdom": "^22.1.0", + "jsdom": "^26.0.0", "vi-fetch": "^0.8.0", - "vitest": "^2.1.8" + "vitest": "^3.0.8" } } diff --git a/packages/hooks-react/src/useBootstrapApp.ts b/packages/hooks-react/src/useBootstrapApp.ts index ad85e2564..d568f0482 100644 --- a/packages/hooks-react/src/useBootstrapApp.ts +++ b/packages/hooks-react/src/useBootstrapApp.ts @@ -8,8 +8,6 @@ import { CACHE_TIME, STALE_TIME } from '@jwp/ott-common/src/constants'; import { logDebug } from '@jwp/ott-common/src/logger'; import { useTranslation } from 'react-i18next'; -const applicationController = getModule(AppController); - type Resources = { config: Config; configSource: string | undefined; @@ -19,6 +17,7 @@ type Resources = { export type OnReadyCallback = (config: Config | undefined) => void; export const useBootstrapApp = (url: string, onReady: OnReadyCallback) => { + const applicationController = getModule(AppController); const queryClient = useQueryClient(); const { i18n } = useTranslation(); diff --git a/packages/ui-react/package.json b/packages/ui-react/package.json index e80798423..74fd93814 100644 --- a/packages/ui-react/package.json +++ b/packages/ui-react/package.json @@ -13,13 +13,13 @@ "@jwp/ott-common": "*", "@jwp/ott-hooks-react": "*", "@jwp/ott-theme": "*", - "@videodock/tile-slider": "^2.2.0", + "@videodock/tile-slider": "^2.3.0", "classnames": "^2.5.1", "date-fns": "^4.1.0", - "dompurify": "^3.2.2", - "i18next": "^24.0.5", - "inversify": "^6.1.5", - "marked": "^15.0.3", + "dompurify": "^3.2.4", + "i18next": "^24.2.2", + "inversify": "^7.5.4", + "marked": "^15.0.7", "payment": "^2.4.7", "planby": "^0.3.0", "react": "^18.3.1", @@ -27,13 +27,13 @@ "react-dom": "^18.3.1", "react-google-recaptcha": "^3.1.0", "react-helmet": "^6.1.0", - "react-i18next": "^15.1.3", + "react-i18next": "^15.4.1", "react-infinite-scroller": "^1.2.6", "react-query": "^3.39.3", "react-router": "6.14.2", "react-router-dom": "6.14.2", "reflect-metadata": "^0.2.2", - "yup": "^1.4.0" + "yup": "^1.6.1" }, "devDependencies": { "@jwp/ott-testing": "*", @@ -46,13 +46,13 @@ "@types/react-infinite-scroller": "^1.2.5", "@vitejs/plugin-react": "^4.3.4", "eslint-config-jwp": "*", - "jsdom": "^22.1.0", + "jsdom": "^26.0.0", "postcss-config-jwp": "*", - "sass-embedded": "^1.81.1", + "sass-embedded": "^1.85.1", "typescript-plugin-css-modules": "^5.1.0", "vi-fetch": "^0.8.0", "vite-plugin-svgr": "^4.3.0", - "vitest": "^2.1.8", + "vitest": "^3.0.8", "vitest-axe": "^1.0.0-pre.3", "wicg-inert": "^3.1.3" } diff --git a/packages/ui-react/src/components/Button/__snapshots__/Button.test.tsx.snap b/packages/ui-react/src/components/Button/__snapshots__/Button.test.tsx.snap index 849295f57..b21cf1f66 100644 --- a/packages/ui-react/src/components/Button/__snapshots__/Button.test.tsx.snap +++ b/packages/ui-react/src/components/Button/__snapshots__/Button.test.tsx.snap @@ -3,7 +3,7 @@ exports[` reset.not_sure reset.try_again diff --git a/packages/ui-react/src/components/CustomRegisterField/__snapshots__/CustomRegisterField.test.tsx.snap b/packages/ui-react/src/components/CustomRegisterField/__snapshots__/CustomRegisterField.test.tsx.snap index 4e8facf32..e34cb3d16 100644 --- a/packages/ui-react/src/components/CustomRegisterField/__snapshots__/CustomRegisterField.test.tsx.snap +++ b/packages/ui-react/src/components/CustomRegisterField/__snapshots__/CustomRegisterField.test.tsx.snap @@ -3,10 +3,10 @@ exports[` > renders and matches snapshot 1`] = `
> renders and matches snapshot 1`] = ` exports[` > renders and matches snapshot 1`] = `
> renders and matches snapshot > renders and matches snapshot > renders and matches snapshot 1`] = `
> renders and matches snapshot 1`] = `
> renders and matches snapshot 1`] = `
Dialog contents
reset.password_helper_text
> renders and matches snapshot 1`] = ` value="" />
> renders Form 1`] = ` />
a
login.forgot_password

login.not_registered login.sign_up diff --git a/packages/ui-react/src/components/Logo/__snapshots__/Logo.test.tsx.snap b/packages/ui-react/src/components/Logo/__snapshots__/Logo.test.tsx.snap index 795953c0d..8bd7694ba 100644 --- a/packages/ui-react/src/components/Logo/__snapshots__/Logo.test.tsx.snap +++ b/packages/ui-react/src/components/Logo/__snapshots__/Logo.test.tsx.snap @@ -7,7 +7,7 @@ exports[` > renders and matches snapshot 1`] = ` > logo diff --git a/packages/ui-react/src/components/MarkdownComponent/__snapshots__/MarkdownComponent.test.tsx.snap b/packages/ui-react/src/components/MarkdownComponent/__snapshots__/MarkdownComponent.test.tsx.snap index 11a4df90a..729e3ba22 100644 --- a/packages/ui-react/src/components/MarkdownComponent/__snapshots__/MarkdownComponent.test.tsx.snap +++ b/packages/ui-react/src/components/MarkdownComponent/__snapshots__/MarkdownComponent.test.tsx.snap @@ -3,7 +3,7 @@ exports[` > renders and matches snapshot 1`] = `

This is a test markdown string with a diff --git a/packages/ui-react/src/components/MenuButton/__snapshots__/MenuButton.test.tsx.snap b/packages/ui-react/src/components/MenuButton/__snapshots__/MenuButton.test.tsx.snap index 708c0ac7c..6435be357 100644 --- a/packages/ui-react/src/components/MenuButton/__snapshots__/MenuButton.test.tsx.snap +++ b/packages/ui-react/src/components/MenuButton/__snapshots__/MenuButton.test.tsx.snap @@ -3,7 +3,7 @@ exports[` > renders and matches snapshot 1`] = `

diff --git a/packages/ui-react/src/components/ModalCloseButton/__snapshots__/ModalCloseButton.test.tsx.snap b/packages/ui-react/src/components/ModalCloseButton/__snapshots__/ModalCloseButton.test.tsx.snap index 6211ad3ab..a648985f0 100644 --- a/packages/ui-react/src/components/ModalCloseButton/__snapshots__/ModalCloseButton.test.tsx.snap +++ b/packages/ui-react/src/components/ModalCloseButton/__snapshots__/ModalCloseButton.test.tsx.snap @@ -4,12 +4,12 @@ exports[` > renders and matches snapshot 1`] = `

May 5, 2021 @@ -127,20 +127,20 @@ exports[` > renders and matches snapshot 1`] = `

user:payment.price_paid_with

May 5, 2021 @@ -153,20 +153,20 @@ exports[` > renders and matches snapshot 1`] = `

user:payment.price_paid_with

May 5, 2021 @@ -179,10 +179,10 @@ exports[` > renders and matches snapshot 1`] = `

user:payment.price_paid_with
diff --git a/packages/ui-react/src/components/PaymentFailed/__snapshots__/PaymentFailed.test.tsx.snap b/packages/ui-react/src/components/PaymentFailed/__snapshots__/PaymentFailed.test.tsx.snap index 39895c02c..eb28562f9 100644 --- a/packages/ui-react/src/components/PaymentFailed/__snapshots__/PaymentFailed.test.tsx.snap +++ b/packages/ui-react/src/components/PaymentFailed/__snapshots__/PaymentFailed.test.tsx.snap @@ -4,18 +4,18 @@ exports[` > renders and matches snapshot 1`] = `

checkout.payment_error

Error message

> Renders with errors 1`] = `
No way Jose @@ -504,7 +504,7 @@ exports[` > Renders with errors 1`] = `
reset.password_helper_text @@ -105,7 +105,7 @@ exports[` > renders and matches snapshot 1`] = `

registration.already_account login.sign_in diff --git a/packages/ui-react/src/components/RenewSubscriptionForm/__snapshots__/RenewSubscriptionForm.test.tsx.snap b/packages/ui-react/src/components/RenewSubscriptionForm/__snapshots__/RenewSubscriptionForm.test.tsx.snap index 5941dbf5a..4e977af5f 100644 --- a/packages/ui-react/src/components/RenewSubscriptionForm/__snapshots__/RenewSubscriptionForm.test.tsx.snap +++ b/packages/ui-react/src/components/RenewSubscriptionForm/__snapshots__/RenewSubscriptionForm.test.tsx.snap @@ -4,7 +4,7 @@ exports[` > renders and matches snapshot 1`] = `

renew_subscription.renew_your_subscription

@@ -12,7 +12,7 @@ exports[` > renders and matches snapshot 1`] = ` renew_subscription.explanation

@@ -23,7 +23,7 @@ exports[` > renders and matches snapshot 1`] = ` renew_subscription.next_billing_date_on

€ 22,15 @@ -36,7 +36,7 @@ exports[` > renders and matches snapshot 1`] = `

@@ -207,15 +207,15 @@ exports[`Shelf Component tests > Featured shelf 1`] = ` exports[`Shelf Component tests > Regular shelf 1`] = `

Test Shelf

Regular shelf 1`] = ` style="width: 20%; padding-left: 8px; padding-right: 8px;" >

Movie 1

1 common:abbreviation.minutes
@@ -271,32 +271,32 @@ exports[`Shelf Component tests > Regular shelf 1`] = ` style="width: 20%; padding-left: 8px; padding-right: 8px;" >

Movie 2

1 common:abbreviation.minutes
@@ -311,32 +311,32 @@ exports[`Shelf Component tests > Regular shelf 1`] = ` style="width: 20%; padding-left: 8px; padding-right: 8px;" >

Third movie

1 common:abbreviation.minutes
@@ -351,32 +351,32 @@ exports[`Shelf Component tests > Regular shelf 1`] = ` style="width: 20%; padding-left: 8px; padding-right: 8px;" >

Last playlist item

21 common:abbreviation.minutes
diff --git a/packages/ui-react/src/components/Sidebar/__snapshots__/Sidebar.test.tsx.snap b/packages/ui-react/src/components/Sidebar/__snapshots__/Sidebar.test.tsx.snap index 147084db0..04834623b 100644 --- a/packages/ui-react/src/components/Sidebar/__snapshots__/Sidebar.test.tsx.snap +++ b/packages/ui-react/src/components/Sidebar/__snapshots__/Sidebar.test.tsx.snap @@ -24,20 +24,20 @@ exports[` > renders sideBar opened 1`] = ` style="transition: transform 0.3s ease, opacity 0.3s ease; transform: translate(0, 0); opacity: 1; z-index: 15;" >