Skip to content

Commit 52217c6

Browse files
authored
chore: migrate repo to React 19 (#35434)
1 parent 2444dac commit 52217c6

File tree

270 files changed

+4284
-3469
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

270 files changed

+4284
-3469
lines changed

.github/workflows/pr-vrt.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ jobs:
2424
if: ${{ github.repository_owner == 'microsoft' }}
2525
runs-on: macos-14-xlarge
2626
name: Generate screenshots
27+
timeout-minutes: 60
2728
steps:
2829
- uses: actions/checkout@v4
2930
with:

.github/workflows/pr.yml

Lines changed: 7 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -104,17 +104,17 @@ jobs:
104104
- run: |
105105
yarn install --frozen-lockfile
106106
yarn rit --react 17 --install-deps
107-
yarn rit --react 19 --install-deps
107+
yarn rit --react 18 --install-deps
108108
109-
- name: Verify Cypress installs from RIT temp workspaces (React 17 -> v13, React 19 -> v14)
109+
- name: Verify Cypress installs from RIT temp workspaces (React 17 -> v13, React 18 -> v14)
110110
run: |
111111
"$GITHUB_WORKSPACE"/tmp/rit/react-17/node_modules/.bin/cypress verify
112-
"$GITHUB_WORKSPACE"/tmp/rit/react-19/node_modules/.bin/cypress verify
112+
"$GITHUB_WORKSPACE"/tmp/rit/react-18/node_modules/.bin/cypress verify
113113
114-
- name: React Versions Integration Tests (17,19) - E2E
114+
- name: React Versions Integration Tests (17,18) - E2E
115115
id: e2e
116116
run: |
117-
yarn nx affected -t test-rit--17--e2e,test-rit--19--e2e --exclude='react-19-tests-v9,react-charting,react'
117+
yarn nx affected -t test-rit--17--e2e,test-rit--18--e2e --exclude='react-19-tests-v9,react-charting,react'
118118
119119
- name: Upload Cypress screenshots if exist
120120
uses: actions/upload-artifact@v4
@@ -125,40 +125,9 @@ jobs:
125125
tmp/rit/**/cypress/screenshots/**/*.png
126126
retention-days: 1
127127

128-
- name: React Versions Integration Tests (17,19) - Type-check & Test
128+
- name: React Versions Integration Tests (17,18) - Type-check & Test
129129
run: |
130-
FLUENT_JEST_WORKER=2 yarn nx affected -t test-rit--17--type-check,test-rit--19--type-check,test-rit--17--test,test-rit--19--test --exclude='react-19-tests-v9'
131-
132-
react_19_v9_source_code_typecheck:
133-
if: ${{ github.repository_owner == 'microsoft' }}
134-
runs-on: ubuntu-latest
135-
permissions:
136-
contents: 'read'
137-
actions: 'read'
138-
name: v9 source code type-check against React 19
139-
steps:
140-
- uses: actions/checkout@v4
141-
with:
142-
fetch-depth: 0
143-
144-
- name: Derive appropriate SHAs for base and head for `nx affected` commands
145-
uses: nrwl/nx-set-shas@826660b82addbef3abff5fa871492ebad618c9e1 # v4.3.3
146-
with:
147-
main-branch-name: 'master'
148-
149-
- uses: actions/setup-node@v4
150-
with:
151-
cache: 'yarn'
152-
node-version: '22'
153-
154-
- run: echo number of CPUs "$(getconf _NPROCESSORS_ONLN)"
155-
156-
- run: |
157-
yarn install --frozen-lockfile
158-
yarn rit --react 19 --install-deps
159-
160-
- run: |
161-
yarn nx affected -t test-rit--19--type-check --exclude='*,!react-19-tests-v9'
130+
FLUENT_JEST_WORKER=2 yarn nx affected -t test-rit--17--type-check,test-rit--18--type-check,test-rit--17--test,test-rit--18--test --exclude='react-19-tests-v9'
162131
163132
e2e:
164133
if: ${{ github.repository_owner == 'microsoft' }}

apps/chart-docsite/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
"@fluentui/react-charts": "*",
3030
"@fluentui/react-storybook-addon": "*",
3131
"@fluentui/react-storybook-addon-export-to-sandbox": "*",
32-
"react": "18.3.1",
33-
"react-dom": "18.3.1",
32+
"react": "19.2.0",
33+
"react-dom": "19.2.0",
3434
"tslib": "^2.1.0"
3535
}
3636
}

apps/perf-test-react-components/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
"@fluentui/react-theme": "*",
3030
"@griffel/core": "^1.16.0",
3131
"@microsoft/load-themed-styles": "^1.10.26",
32-
"react": "18.3.1",
33-
"react-dom": "18.3.1",
32+
"react": "19.2.0",
33+
"react-dom": "19.2.0",
3434
"tslib": "^2.1.0"
3535
}
3636
}

apps/perf-test/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
"@fluentui/example-data": "*",
2323
"@fluentui/react": "*",
2424
"@microsoft/load-themed-styles": "^1.10.26",
25-
"react": "18.3.1",
26-
"react-dom": "18.3.1",
25+
"react": "19.2.0",
26+
"react-dom": "19.2.0",
2727
"tslib": "^2.1.0"
2828
}
2929
}

apps/public-docsite-resources/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@
4646
"@fluentui/theme-samples": "*",
4747
"@fluentui/react-monaco-editor": "*",
4848
"office-ui-fabric-core": "^11.0.0",
49-
"react": "18.3.1",
50-
"react-dom": "18.3.1",
49+
"react": "19.2.0",
50+
"react-dom": "19.2.0",
5151
"tslib": "^2.1.0"
5252
}
5353
}

apps/public-docsite-v9/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@
4040
"@fluentui/react-timepicker-compat": "*",
4141
"@griffel/react": "^1.5.22",
4242
"@microsoft/applicationinsights-web": "^3",
43-
"react": "18.3.1",
44-
"react-dom": "18.3.1",
43+
"react": "19.2.0",
44+
"react-dom": "19.2.0",
4545
"react-window": "^1.8.6",
4646
"tslib": "^2.1.0",
4747
"react-hook-form": "^5.7.2",
Lines changed: 87 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
1-
/* eslint-disable react/jsx-key */
1+
/* eslint-disable @typescript-eslint/naming-convention */
2+
23
import * as React from 'react';
3-
import { Source } from '@storybook/addon-docs';
4-
import { createRenderer } from 'react-test-renderer/shallow';
4+
import { render } from '@testing-library/react';
5+
56
import { CodeExample } from './utils.stories';
67

8+
// Mock the Source component to verify it receives correct props
9+
const mockSource = jest.fn(({ code, language }: { code: string; language: string }) => (
10+
<pre data-testid="source" data-language={language}>
11+
<code>{code}</code>
12+
</pre>
13+
));
14+
15+
// `Source` wont be available in the test environment, so we need to mock it to test the code output
16+
jest.mock('@storybook/addon-docs', () => ({
17+
Source: (props: { code: string; language: string }) => mockSource(props),
18+
}));
19+
720
function mockMDXSourceCodeBlock(source: string) {
821
return {
922
props: {
@@ -16,23 +29,22 @@ function mockMDXSourceCodeBlock(source: string) {
1629
} as React.ReactElement;
1730
}
1831

32+
beforeEach(() => {
33+
mockSource.mockClear();
34+
});
35+
1936
test('renders children', () => {
20-
const renderer = createRenderer();
21-
renderer.render(
37+
const { container } = render(
2238
<CodeExample>
2339
<span>Child</span>
2440
</CodeExample>,
2541
);
26-
const result = renderer.getRenderOutput();
2742

28-
expect(result.props).toEqual({
29-
children: 'Child',
30-
});
43+
expect(container.textContent).toBe('Child');
3144
});
3245

3346
test('renders Markdown source blocks', () => {
34-
const renderer = createRenderer();
35-
renderer.render(
47+
const { getByRole, getByTestId } = render(
3648
<CodeExample>
3749
{mockMDXSourceCodeBlock(`\`\`\`js
3850
function test() {
@@ -41,53 +53,60 @@ test('renders Markdown source blocks', () => {
4153
\`\`\``)}
4254
</CodeExample>,
4355
);
44-
const result = renderer.getRenderOutput();
4556

46-
expect(result.props).toEqual({
47-
children: [
48-
<h3>JavaScript</h3>,
49-
<Source
50-
code={`function test() {
57+
// Test that CodeExample correctly parses and renders the header
58+
const heading = getByRole('heading', { level: 3 });
59+
expect(heading.textContent).toBe('JavaScript');
60+
61+
// Verify Source component was called with correct props
62+
expect(mockSource).toHaveBeenCalledWith(
63+
expect.objectContaining({
64+
code: `function test() {
5165
console.log("test");
52-
}`}
53-
language="jsextra"
54-
/>,
55-
],
56-
});
66+
}`,
67+
language: 'jsextra',
68+
}),
69+
);
70+
71+
// Verify Source component rendered correctly
72+
const sourceElement = getByTestId('source');
73+
expect(sourceElement.getAttribute('data-language')).toBe('jsextra');
74+
expect(sourceElement.textContent).toContain('function test()');
5775
});
5876

5977
test('uses JSX for no header JSX source code blocks', () => {
60-
const renderer = createRenderer();
61-
renderer.render(
78+
const { getByRole, getByTestId } = render(
6279
<CodeExample>
6380
{mockMDXSourceCodeBlock(`<div>
6481
<Test title={"Example"} />
6582
</div>`)}
6683
</CodeExample>,
6784
);
68-
const result = renderer.getRenderOutput();
6985

70-
expect(result.props).toEqual({
71-
children: [
72-
<h3>React</h3>,
73-
<Source
74-
code={`<div>
86+
const heading = getByRole('heading', { level: 3 });
87+
expect(heading.textContent).toBe('React');
88+
89+
// Verify Source component was called with JSX language
90+
expect(mockSource).toHaveBeenCalledWith(
91+
expect.objectContaining({
92+
code: `<div>
7593
<Test title={"Example"} />
76-
</div>`}
77-
language="jsx"
78-
/>,
79-
],
80-
});
94+
</div>`,
95+
language: 'jsx',
96+
}),
97+
);
98+
99+
const sourceElement = getByTestId('source');
100+
expect(sourceElement.getAttribute('data-language')).toBe('jsx');
81101
});
82102

83103
test.each([
84104
['html', 'HTML'],
85105
['css', 'CSS'],
86106
['js', 'JavaScript'],
87107
['jsx', 'React'],
88-
] as const)('for language %s uses the header %s', (language, expectedHeader) => {
89-
const renderer = createRenderer();
90-
renderer.render(
108+
])('for language %s uses the header %s', (language, expectedHeader) => {
109+
const { getByRole, getByTestId } = render(
91110
<CodeExample>
92111
{mockMDXSourceCodeBlock(`
93112
\`\`\`${language}
@@ -96,16 +115,27 @@ test.each([
96115
`)}
97116
</CodeExample>,
98117
);
99-
const result = renderer.getRenderOutput();
100118

101-
expect(result.props).toEqual({
102-
children: [<h3>{expectedHeader}</h3>, <Source code={`Code`} language={language === 'js' ? 'jsextra' : language} />],
103-
});
119+
const resolvedLanguage = language === 'js' ? 'jsextra' : language;
120+
121+
const heading = getByRole('heading', { level: 3 });
122+
expect(heading.textContent).toBe(expectedHeader);
123+
124+
// Verify Source component was called with correct language
125+
expect(mockSource).toHaveBeenCalledWith(
126+
expect.objectContaining({
127+
code: 'Code',
128+
language: resolvedLanguage,
129+
}),
130+
);
131+
132+
const sourceElement = getByTestId('source');
133+
expect(sourceElement.getAttribute('data-language')).toBe(resolvedLanguage);
134+
expect(sourceElement.textContent).toBe('Code');
104135
});
105136

106137
test('overrides the default title', () => {
107-
const renderer = createRenderer();
108-
renderer.render(
138+
const { getByRole, getByTestId } = render(
109139
<CodeExample title="Custom title">
110140
{mockMDXSourceCodeBlock(`
111141
\`\`\`js
@@ -114,9 +144,18 @@ test('overrides the default title', () => {
114144
`)}
115145
</CodeExample>,
116146
);
117-
const result = renderer.getRenderOutput();
118147

119-
expect(result.props).toEqual({
120-
children: [<h3>Custom title</h3>, <Source code={`Code`} language="jsextra" />],
121-
});
148+
const heading = getByRole('heading', { level: 3 });
149+
expect(heading.textContent).toBe('Custom title');
150+
151+
// Verify Source component still receives correct code and language
152+
expect(mockSource).toHaveBeenCalledWith(
153+
expect.objectContaining({
154+
code: 'Code',
155+
language: 'jsextra',
156+
}),
157+
);
158+
159+
const sourceElement = getByTestId('source');
160+
expect(sourceElement.getAttribute('data-language')).toBe('jsextra');
122161
});

apps/public-docsite-v9/src/Concepts/Migration/FromV8/Components/Flex/utils.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const codeLanguages = {
3030
js: 'JavaScript',
3131
jsx: 'React',
3232
};
33-
export const CodeExample = (props: { title?: string; children: React.ReactElement }) => {
33+
export const CodeExample = (props: { title?: string; children?: React.ReactElement<any> }) => {
3434
const { title, children } = props;
3535
// Access the raw values from the markdown source code block
3636
const markdownCodeBlockValue: string | undefined = children?.props?.children?.props?.children;

apps/public-docsite/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@
4848
"@fluentui/utilities": "*",
4949
"@microsoft/load-themed-styles": "^1.10.26",
5050
"office-ui-fabric-core": "^11.0.0",
51-
"react": "18.3.1",
52-
"react-dom": "18.3.1",
51+
"react": "19.2.0",
52+
"react-dom": "19.2.0",
5353
"tslib": "^2.1.0",
5454
"whatwg-fetch": "2.0.4"
5555
}

0 commit comments

Comments
 (0)