Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,29 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react';

jest.mock('@radix-ui/react-form');

jest.mock('react-dom', () => {
const React = jest.requireActual('react');
const actual = jest.requireActual('react-dom');
jest.mock('react', () => {
const actual = jest.requireActual<typeof import('react')>('react');
return {
...actual,
useFormState: <S, P>(
useActionState: <S, P>(
action: (state: S, payload: P) => Promise<S> | S,
initial: S
) => {
const [state, setState] = React.useState<S>(initial);
const [state, setState] = actual.useState<S>(initial);
const formAction = async (payload: P) => {
const result = await action(state, payload);
setState(result);
return result;
};
return [state, formAction];
},
};
});

jest.mock('react-dom', () => {
const actual = jest.requireActual('react-dom');
return {
...actual,
useFormStatus: () => ({
pending: false,
data: null,
Expand Down Expand Up @@ -107,7 +113,9 @@ describe('CouponForm', () => {
expect(screen.getByTestId('coupon-error')).toBeInTheDocument();
});

expect(screen.getByText(/code you entered is invalid/i)).toBeInTheDocument();
expect(
screen.getByText(/code you entered is invalid/i)
).toBeInTheDocument();
expect(screen.getByTestId('coupon-input')).toBeInTheDocument();
expect(screen.queryByTestId('coupon-hascoupon')).not.toBeInTheDocument();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import { Localized } from '@fluent/react';
import * as Form from '@radix-ui/react-form';
import classNames from 'classnames';
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { forwardRef, useEffect, useState } from 'react';
import { useFormState, useFormStatus } from 'react-dom';
import { forwardRef, useActionState, useEffect, useState } from 'react';
import { useFormStatus } from 'react-dom';
import { ButtonVariant } from '../BaseButton';
import { SubmitButton } from '../SubmitButton';
import {
Expand Down Expand Up @@ -157,7 +157,7 @@ const WithoutCoupon = ({
return result;
}
const routeCoupon = useSearchParams().get('coupon') || undefined;
const [, formAction] = useFormState(applyCoupon, null);
const [, formAction] = useActionState(applyCoupon, null);
useEffect(() => {
if (routeCoupon) {
const formData = new FormData();
Expand Down
15 changes: 6 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@
"path-browserify": "^1.0.1",
"pm2": "^7.0.0",
"prettier": "^3.5.3",
"react": "18.3.1",
"react-dom": "18.3.1",
"react": "19.1.0",
"react-dom": "19.1.0",
"react-ga4": "^2.1.0",
"rxjs": "^7.8.1",
"semver": "^7.7.1",
Expand Down Expand Up @@ -221,7 +221,7 @@
"@swc/cli": "0.6.0",
"@swc/core": "1.11.11",
"@swc/jest": "^0.2.36",
"@testing-library/react": "15.0.6",
"@testing-library/react": "^16.3.0",
"@types/babel__core": "^7",
"@types/babel__preset-env": "^7",
"@types/bn.js": "^5",
Expand All @@ -238,9 +238,8 @@
"@types/passport": "^1.0.6",
"@types/passport-http-bearer": "^1.0.36",
"@types/passport-jwt": "^4",
"@types/react": "18.3.1",
"@types/react-dom": "18.3.0",
"@types/react-test-renderer": "^18",
"@types/react": "^19.1.0",
"@types/react-dom": "^19.1.0",
"@types/set-value": "^4",
"@types/superagent": "4.1.11",
"@types/twilio": "^3.19.3",
Expand All @@ -260,7 +259,7 @@
"eslint-plugin-jest": "^27.6.0",
"eslint-plugin-jsx-a11y": "6.10.0",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "5.0.0",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-testing-library": "^7.3.0",
"grunt": "^1.6.1",
"grunt-cli": "^1.4.3",
Expand All @@ -280,7 +279,6 @@
"nx": "21.2.4",
"nx-cloud": "19.1.0",
"postcss": "8.5.12",
"react-test-renderer": "^18.3.1",
"reflect-metadata": "^0.2.1",
"server-only": "^0.0.1",
"storybook": "^8.0.0",
Expand All @@ -301,7 +299,6 @@
"resolutions": {
"@react-pdf/layout": "3.9.1",
"@react-pdf/textkit": "4.3.0",
"@types/react": "18.2.14",
"asn1.js": ">=5.4.1",
"axios": "^1.13.4",
"bn.js": "^5.2.1",
Expand Down
1 change: 1 addition & 0 deletions packages/fxa-admin-panel/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"helmet": "^8.0.0",
"mozlog": "^3.0.2",
"on-headers": "^1.1.0",
"react-hook-form": "^7.54.0",
"react-router": "7.18.0",
"react-scripts": "^5.0.1",
"serve-static": "^1.16.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,10 @@ export const PageRateLimiting = () => {
</label>
<input
id={`rate-limit-${id}`}
name={id}
type={type}
placeholder={label}
className="bg-grey-50 rounded w-full py-2 px-3 placeholder-grey-500"
ref={register}
{...register(id)}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@ export const TableRowXHeader = ({ children, testId }: TableRowXHeaderProps) => {
return (
<tr data-testid={testId}>
{arrayElements.map((element, i) => {
if (React.isValidElement(element) && element.type === 'td') {
if (
React.isValidElement<React.TdHTMLAttributes<HTMLTableCellElement>>(
element
) &&
element.type === 'td'
) {
const {
className: elementClassNames,
children: elementChildren,
Expand Down
12 changes: 11 additions & 1 deletion packages/fxa-react/configs/rescripts.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,10 @@ const configureDevServerCompression = (devServerConfig) => {

setupMiddlewares: (middlewares, devServer) => {
middlewares.unshift(compression({ threshold: '4kb' }));
return devServerConfig.setupMiddlewares?.(middlewares, devServer) || middlewares;
return (
devServerConfig.setupMiddlewares?.(middlewares, devServer) ||
middlewares
);
},
};
};
Expand All @@ -108,6 +111,13 @@ const setModuleNameMapper = (tsconfigBase) => (config) => {
config.transform = {
...config.transform,
'^.+\\.tsx?$': ['ts-jest', { isolatedModules: true }],
// Override CRA's fileTransform for non-JS assets (SVGs, images).
// react-scripts' built-in transform hardcodes Symbol.for('react.element')
// which is incompatible with React 19's element format.
'^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': resolve(
__dirname,
'../../fxa-settings/config/jest/fileTransform.js'
),
};

// ts-jest - Paths mapping - With helper
Expand Down
2 changes: 1 addition & 1 deletion packages/fxa-react/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const { compilerOptions } = require('../../tsconfig.base.json');
module.exports = {
transform: {
'^.+\\.(ts|tsx)?$': ['ts-jest', { isolatedModules: true }],
'^.+\\.svg$': '<rootDir>/svg-transform.js',
'^.+\\.svg$': '<rootDir>/../fxa-settings/config/jest/fileTransform.js',
},
// ts-jest - Paths mapping - With helper
// https://kulshekhar.github.io/ts-jest/docs/getting-started/paths-mapping#jest-config-with-helper
Expand Down
2 changes: 1 addition & 1 deletion packages/fxa-react/lib/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export function useAwait<
initialState || resetPromiseState()
);

const promise = useRef<Promise<TResult | undefined> | undefined>();
const promise = useRef<Promise<TResult | undefined> | undefined>(undefined);

const reset = useCallback(() => {
setState(resetPromiseState());
Expand Down
4 changes: 2 additions & 2 deletions packages/fxa-react/lib/test-utils/localizationProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import AppLocalizationProvider from 'fxa-react/lib/AppLocalizationProvider';
const reportError = () => {};

export function renderWithLocalizationProvider(
children: JSX.Element,
children: React.ReactElement,
messages = { en: ['testo: lol'] }
): ReturnType<typeof render> {
return render(
Expand All @@ -20,7 +20,7 @@ export function renderWithLocalizationProvider(
}

export function withLocalizationProvider(
children: JSX.Element,
children: React.ReactElement,
baseDir = '/locales',
userLocales = navigator.languages || ['en']
) {
Expand Down
36 changes: 0 additions & 36 deletions packages/fxa-react/svg-transform.js

This file was deleted.

21 changes: 7 additions & 14 deletions packages/fxa-settings/config/jest/fileTransform.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
// This file was created by react-scripts' (create-react-app) eject script.
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

'use strict';
// Custom Jest transformer turning file imports into filenames.
// For SVG files, generates a React component matching SVGR's naming convention.
// http://facebook.github.io/jest/docs/en/webpack.html

const path = require('path');
const camelcase = require('camelcase');

// This is a custom Jest transformer turning file imports into filenames.
// http://facebook.github.io/jest/docs/en/webpack.html

module.exports = {
process(src, filename) {
const assetFilename = JSON.stringify(path.basename(filename));
Expand All @@ -25,15 +26,7 @@ module.exports = {
__esModule: true,
default: ${assetFilename},
ReactComponent: React.forwardRef(function ${componentName}(props, ref) {
return {
$$typeof: Symbol.for('react.element'),
type: 'svg',
ref: ref,
key: null,
props: Object.assign({}, props, {
children: ${assetFilename}
})
};
return React.createElement('svg', Object.assign({}, props, { ref: ref }), ${assetFilename});
}),
};`,
};
Expand Down
10 changes: 4 additions & 6 deletions packages/fxa-settings/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
]
},
"transformIgnorePatterns": [
"[/\\\\]node_modules[/\\\\](?!sinon|@mozilla/glean)",
"[/\\\\]node_modules[/\\\\](?!sinon|@mozilla/glean|react-markdown|rehype-raw|unified|remark-.+|rehype-.+|hast-util-.+|mdast-util-.+|micromark.+|unist-util-.+|vfile|decode-named-character-reference|character-entities|devlop|property-information|comma-separated-tokens|space-separated-tokens|zwitch|web-namespaces|ccount|bail|trough|is-plain-obj|trim-lines)",
"^.+\\.module\\.(css|sass|scss)$"
],
"modulePaths": [],
Expand Down Expand Up @@ -130,7 +130,6 @@
"dependencies": {
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@material-ui/core": "v5.0.0-alpha.24",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.3",
"@react-pdf/renderer": "3.2.1",
"@svgr/webpack": "^8.1.0",
Expand Down Expand Up @@ -174,12 +173,12 @@
"react-async-hook": "^4.0.0",
"react-dev-utils": "^12.0.1",
"react-easy-crop": "^5.2.0",
"react-hook-form": "^6.15.8",
"react-markdown": "^8.0.5",
"react-hook-form": "^7.54.0",
"react-markdown": "^9.0.3",
"react-refresh": "^0.16.0",
"react-router": "7.18.0",
"react-webcam": "^7.2.0",
"rehype-raw": "^6.1.1",
"rehype-raw": "^7.0.0",
"resolve": "^1.22.8",
"resolve-url-loader": "^5.0.0",
"sass-loader": "^16.0.3",
Expand All @@ -203,7 +202,6 @@
"@storybook/addon-links": "^8.0.0",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.1.3",
"@testing-library/react-hooks": "^8.0.0",
"@testing-library/user-event": "^14.6.0",
"@types/file-saver": "^2.0.5",
"@types/jest": "26.0.23",
Expand Down
5 changes: 2 additions & 3 deletions packages/fxa-settings/src/components/FormChoice/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const FormChoice = ({
formChoices,
onSubmit,
isSubmitting,
cmsButton
cmsButton,
}: FormChoiceProps) => {
const { register, handleSubmit, watch } = useForm<FormChoiceData>();
const selectedOption = watch('choice');
Expand All @@ -63,9 +63,8 @@ const FormChoice = ({
className="input-radio"
type="radio"
id={choice.id}
name="choice"
value={choice.value}
ref={register({ required: true })}
{...register('choice', { required: true })}
/>
<label
className={classNames(
Expand Down
Loading
Loading