From 25cff030d5a8f816777f8909816f7fde74a1c840 Mon Sep 17 00:00:00 2001 From: Martin Hochel Date: Tue, 22 Nov 2022 21:54:59 +0100 Subject: [PATCH 1/7] fix(react-18-tests-v9): enable e2e run on ci and normalize all test scenarios --- apps/react-18-tests-v9/.eslintrc.json | 7 ++--- apps/react-18-tests-v9/package.json | 22 +++++++-------- apps/react-18-tests-v9/src/App.cy.tsx | 25 +++++++++++++++++ .../FluentProvider.test.tsx => App.test.tsx} | 12 ++++---- .../react-18-tests-v9/src/components/.gitkeep | 0 .../FluentProvider/FluentProvider.e2e.tsx | 28 ------------------- apps/react-18-tests-v9/tsconfig.app.json | 4 +-- apps/react-18-tests-v9/tsconfig.cy.json | 4 +-- yarn.lock | 2 +- 9 files changed, 49 insertions(+), 55 deletions(-) create mode 100644 apps/react-18-tests-v9/src/App.cy.tsx rename apps/react-18-tests-v9/src/{components/FluentProvider/FluentProvider.test.tsx => App.test.tsx} (70%) create mode 100644 apps/react-18-tests-v9/src/components/.gitkeep delete mode 100644 apps/react-18-tests-v9/src/components/FluentProvider/FluentProvider.e2e.tsx diff --git a/apps/react-18-tests-v9/.eslintrc.json b/apps/react-18-tests-v9/.eslintrc.json index 6330b1d28391b2..92f2e74b606c9e 100644 --- a/apps/react-18-tests-v9/.eslintrc.json +++ b/apps/react-18-tests-v9/.eslintrc.json @@ -1,8 +1,5 @@ { - "extends": ["plugin:@fluentui/eslint-plugin/react--legacy"], + "extends": ["plugin:@fluentui/eslint-plugin/react"], "root": true, - "rules": { - "deprecation/deprecation": "off", - "prefer-const": "off" - } + "rules": {} } diff --git a/apps/react-18-tests-v9/package.json b/apps/react-18-tests-v9/package.json index a2746dfc8351c6..6738064aa085a9 100644 --- a/apps/react-18-tests-v9/package.json +++ b/apps/react-18-tests-v9/package.json @@ -4,26 +4,26 @@ "version": "1.0.0", "private": true, "scripts": { - "type-check": "tsc -b", - "lint": "just-scripts lint", - "test": "just-scripts test", - "just": "just-scripts", + "type-check": "tsc -b tsconfig.json", + "lint": "eslint --ext .js,.ts,.tsx ./src", + "test": "jest --passWithNoTests", "clean": "just-scripts clean", - "code-style": "just-scripts code-style", - "start": "webpack-dev-server --mode=development --config=webpack.config.js", - "e2e:local": "cypress open --component" + "format": "prettier -w . --ignore-path ../.prettierignore", + "format:check": "yarn format -c", + "start": "webpack-dev-server --mode=development", + "e2e:local": "cypress open --component", + "e2e": "cypress run --component" }, "devDependencies": { "@fluentui/eslint-plugin": "*", - "@fluentui/scripts": "^1.0.0", - "@types/react": "18.0.14", - "@types/react-dom": "18.0.6", - "swc-loader": "^0.2.3" + "@fluentui/scripts": "^1.0.0" }, "dependencies": { "@fluentui/react-button": "^9.1.9", "@fluentui/react-provider": "^9.1.8", "@fluentui/react-theme": "^9.1.2", + "@types/react": "18.0.14", + "@types/react-dom": "18.0.6", "react": "18.2.0", "react-dom": "18.2.0", "tslib": "^2.1.0" diff --git a/apps/react-18-tests-v9/src/App.cy.tsx b/apps/react-18-tests-v9/src/App.cy.tsx new file mode 100644 index 00000000000000..eb843f612206c2 --- /dev/null +++ b/apps/react-18-tests-v9/src/App.cy.tsx @@ -0,0 +1,25 @@ +import * as React from 'react'; +import { mount } from '@cypress/react'; + +import { App } from './App'; + +const providerSelector = '.fui-FluentProvider'; + +describe('App with React 18', () => { + describe('FluentProvider', () => { + it('should apply matching className in strict mode', () => { + mount( + + + , + ); + + cy.get(providerSelector) + .invoke('attr', 'class') + .then($c => { + const elementClass = $c?.split(' ')[1]; + cy.get(`#${elementClass}`).should('not.be.undefined'); + }); + }); + }); +}); diff --git a/apps/react-18-tests-v9/src/components/FluentProvider/FluentProvider.test.tsx b/apps/react-18-tests-v9/src/App.test.tsx similarity index 70% rename from apps/react-18-tests-v9/src/components/FluentProvider/FluentProvider.test.tsx rename to apps/react-18-tests-v9/src/App.test.tsx index 253eda0a4df218..a23567717f84d4 100644 --- a/apps/react-18-tests-v9/src/components/FluentProvider/FluentProvider.test.tsx +++ b/apps/react-18-tests-v9/src/App.test.tsx @@ -2,9 +2,9 @@ import { resetIdsForTests } from '@fluentui/react-utilities'; import { render } from '@testing-library/react'; import * as React from 'react'; -import { FluentProvider } from '@fluentui/react-provider'; +import { App } from './App'; -describe('FluentProvider', () => { +describe('App with React 18', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function const noop = () => {}; @@ -16,14 +16,14 @@ describe('FluentProvider', () => { resetIdsForTests(); }); - describe('FluentProvider in React 18', () => { - it('applies matching className in strict mode', () => { + describe('FluentProvider', () => { + it('should apply matching className in strict mode', () => { const { getByText } = render( - Test + , ); - const element = getByText('Test'); + const element = getByText('Click Me'); const elementProviderClassName = element.className.split(' ')[1]; const matchingStyleTag = document.getElementById(elementProviderClassName); diff --git a/apps/react-18-tests-v9/src/components/.gitkeep b/apps/react-18-tests-v9/src/components/.gitkeep new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/apps/react-18-tests-v9/src/components/FluentProvider/FluentProvider.e2e.tsx b/apps/react-18-tests-v9/src/components/FluentProvider/FluentProvider.e2e.tsx deleted file mode 100644 index c5370614fa705d..00000000000000 --- a/apps/react-18-tests-v9/src/components/FluentProvider/FluentProvider.e2e.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import * as React from 'react'; -import { mount } from '@cypress/react'; -import { Button } from '@fluentui/react-button'; -import { FluentProvider } from '@fluentui/react-provider'; -import { webLightTheme } from '@fluentui/react-theme'; - -const providerSelector = '.fui-FluentProvider'; - -describe('FluentProvider in React 18', () => { - it('applies matching className in strict mode', () => { - mount( - - - - - , - ); - - cy.get(providerSelector) - .invoke('attr', 'class') - .then($c => { - const elementClass = $c?.split(' ')[1]; - cy.get(`#${elementClass}`).should('not.be.undefined'); - }); - - // ; - }); -}); diff --git a/apps/react-18-tests-v9/tsconfig.app.json b/apps/react-18-tests-v9/tsconfig.app.json index 1db28beeecff91..a83db7916f3c11 100644 --- a/apps/react-18-tests-v9/tsconfig.app.json +++ b/apps/react-18-tests-v9/tsconfig.app.json @@ -7,8 +7,8 @@ "declaration": true, "declarationDir": "dist/types", "inlineSources": true, - "types": ["static-assets", "environment", "node"] + "types": ["static-assets", "environment"] }, - "exclude": ["./src/common/**", "**/*.spec.ts", "**/*.spec.tsx", "**/*.test.ts", "**/*.test.tsx"], + "exclude": ["**/*.spec.ts", "**/*.spec.tsx", "**/*.test.ts", "**/*.test.tsx", "**/*.cy.tsx", "**/*.cy.ts"], "include": ["./src/**/*.ts", "./src/**/*.tsx"] } diff --git a/apps/react-18-tests-v9/tsconfig.cy.json b/apps/react-18-tests-v9/tsconfig.cy.json index b9d90a02368fe6..ceda454a1b7cbf 100644 --- a/apps/react-18-tests-v9/tsconfig.cy.json +++ b/apps/react-18-tests-v9/tsconfig.cy.json @@ -3,8 +3,8 @@ "compilerOptions": { "jsx": "react", "isolatedModules": false, - "types": ["node", "cypress", "cypress-storybook/cypress", "cypress-real-events"], + "types": ["node", "cypress", "cypress-real-events"], "lib": ["ES2019", "dom"] }, - "include": ["./src/**/*.e2e.ts", "./src/**/*.e2e.tsx"] + "include": ["./src/**/*.cy.ts", "./src/**/*.cy.tsx"] } diff --git a/yarn.lock b/yarn.lock index 04e2ca97345a8f..c111246a5ce766 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24966,7 +24966,7 @@ swap-case@^1.1.0: lower-case "^1.1.1" upper-case "^1.1.1" -swc-loader@0.2.3, swc-loader@^0.2.3: +swc-loader@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/swc-loader/-/swc-loader-0.2.3.tgz#6792f1c2e4c9ae9bf9b933b3e010210e270c186d" integrity sha512-D1p6XXURfSPleZZA/Lipb3A8pZ17fP4NObZvFCDjK/OKljroqDpPmsBdTraWhVBqUNpcWBQY1imWdoPScRlQ7A== From 5412278f36310d36c725d5c7ecdbbbce6d01fe35 Mon Sep 17 00:00:00 2001 From: Martin Hochel Date: Tue, 22 Nov 2022 21:56:00 +0100 Subject: [PATCH 2/7] feat(scripts): resolve cypress webpack config based on packageJson.version instead hardcoded folder name --- scripts/cypress/cypress.config.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/scripts/cypress/cypress.config.ts b/scripts/cypress/cypress.config.ts index 8571305a55dc2d..e2794de4cc13df 100644 --- a/scripts/cypress/cypress.config.ts +++ b/scripts/cypress/cypress.config.ts @@ -10,6 +10,19 @@ const applyV8WebpackConfig: (config: Configuration) => Configuration = require(' const isLocalRun = !process.env.DEPLOYURL; +function isV8() { + const packageJsonPath = path.join(process.cwd(), 'package.json'); + if (!fs.existsSync(packageJsonPath)) { + return false; + } + + const packageJson: Record = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); + if (typeof packageJson.version !== 'string') { + return false; + } + return packageJson.version.startsWith('8.'); +} + const cypressWebpackConfig = (): Configuration => { const webpackConfig: Configuration = { resolve: { @@ -26,9 +39,9 @@ const cypressWebpackConfig = (): Configuration => { }, }; - const isV8 = path.basename(process.cwd()) === 'react-examples'; + // const isV8 = path.basename(process.cwd()) === 'react-examples'; - if (isV8) { + if (isV8()) { // For v8, reuse the storybook webpack config helper to add required options for building v8, // including the `resolve.alias` config that's currently REQUIRED to make tests re-run when a // component file in @fluentui/react is modified while running in open mode. From cba9aba4e5770ad76179ced2ab1616d78c284a12 Mon Sep 17 00:00:00 2001 From: Martin Hochel Date: Tue, 22 Nov 2022 22:02:20 +0100 Subject: [PATCH 3/7] feat(react-18-tests-v8): enable build-less DX for start,test,e2e and normalize all test scenarios --- apps/react-18-tests-v8/.eslintrc.json | 7 +-- apps/react-18-tests-v8/jest.config.js | 11 +++- apps/react-18-tests-v8/package.json | 19 +++---- apps/react-18-tests-v8/src/App.tsx | 2 +- .../ContextualMenu/ContextualMenu.e2e.tsx | 45 --------------- .../ContextualMenu/ContextualMenu.test.tsx | 55 ------------------- .../ContextualMenuExample.cy.tsx | 19 +++++++ .../ContextualMenuExample.test.tsx | 29 ++++++++++ apps/react-18-tests-v8/tsconfig.app.json | 4 +- apps/react-18-tests-v8/tsconfig.cy.json | 4 +- apps/react-18-tests-v8/webpack.config.js | 48 +++++++++++++--- 11 files changed, 114 insertions(+), 129 deletions(-) delete mode 100644 apps/react-18-tests-v8/src/components/ContextualMenu/ContextualMenu.e2e.tsx delete mode 100644 apps/react-18-tests-v8/src/components/ContextualMenu/ContextualMenu.test.tsx create mode 100644 apps/react-18-tests-v8/src/components/ContextualMenu/ContextualMenuExample.cy.tsx create mode 100644 apps/react-18-tests-v8/src/components/ContextualMenu/ContextualMenuExample.test.tsx diff --git a/apps/react-18-tests-v8/.eslintrc.json b/apps/react-18-tests-v8/.eslintrc.json index 6330b1d28391b2..92f2e74b606c9e 100644 --- a/apps/react-18-tests-v8/.eslintrc.json +++ b/apps/react-18-tests-v8/.eslintrc.json @@ -1,8 +1,5 @@ { - "extends": ["plugin:@fluentui/eslint-plugin/react--legacy"], + "extends": ["plugin:@fluentui/eslint-plugin/react"], "root": true, - "rules": { - "deprecation/deprecation": "off", - "prefer-const": "off" - } + "rules": {} } diff --git a/apps/react-18-tests-v8/jest.config.js b/apps/react-18-tests-v8/jest.config.js index e753472dc5f571..80fcf27512e6f9 100644 --- a/apps/react-18-tests-v8/jest.config.js +++ b/apps/react-18-tests-v8/jest.config.js @@ -1,5 +1,8 @@ // @ts-check +const { resolveMergeStylesSerializer } = require('@fluentui/scripts/jest/jest-resources'); +const getResolveAlias = require('@fluentui/scripts/webpack/getResolveAlias'); + /** * @type {import('@jest/types').Config.InitialOptions} */ @@ -9,12 +12,18 @@ module.exports = { globals: { 'ts-jest': { tsConfig: '/tsconfig.spec.json', - diagnostics: false, + diagnostics: { warnOnly: true, exclude: ['packages/**'] }, }, }, transform: { '^.+\\.tsx?$': 'ts-jest', }, + coverageDirectory: './coverage', setupFilesAfterEnv: ['./config/tests.js'], + moduleNameMapper: { + '\\.(scss)$': '@fluentui/scripts/jest/jest-style-mock.js', + ...getResolveAlias(), + }, + snapshotSerializers: [resolveMergeStylesSerializer()], }; diff --git a/apps/react-18-tests-v8/package.json b/apps/react-18-tests-v8/package.json index fa2a856caadbff..ca9712c2034225 100644 --- a/apps/react-18-tests-v8/package.json +++ b/apps/react-18-tests-v8/package.json @@ -1,30 +1,29 @@ { "name": "@fluentui/react-18-tests-v8", "description": "React 18 test application", - "version": "1.0.0", + "version": "8.0.0", "private": true, "scripts": { "build": "just-scripts build", "clean": "just-scripts clean", - "code-style": "just-scripts code-style", + "format": "prettier -w . --ignore-path ../.prettierignore", + "format:check": "yarn format -c", "e2e": "cypress run --component", "e2e:local": "cypress open --component", - "lint": "just-scripts lint", - "test": "just-scripts test", - "just": "just-scripts", - "start": "webpack-dev-server --mode=development --config=webpack.config.js", + "lint": "eslint --ext .js,.ts.,.tsx ./src", + "test": "jest --passWithNoTests", + "start": "webpack-dev-server --mode=development", "type-check": "tsc -b tsconfig.json" }, "devDependencies": { "@fluentui/eslint-plugin": "*", - "@fluentui/scripts": "^1.0.0", - "@types/react": "18.0.14", - "@types/react-dom": "18.0.6", - "swc-loader": "^0.2.3" + "@fluentui/scripts": "^1.0.0" }, "dependencies": { "@fluentui/react": "^8.103.0", "@fluentui/react-hooks": "^8.6.14", + "@types/react": "18.0.14", + "@types/react-dom": "18.0.6", "react": "18.2.0", "react-dom": "18.2.0", "tslib": "^2.1.0" diff --git a/apps/react-18-tests-v8/src/App.tsx b/apps/react-18-tests-v8/src/App.tsx index 5f294a62059b72..7760bb3b80e63f 100644 --- a/apps/react-18-tests-v8/src/App.tsx +++ b/apps/react-18-tests-v8/src/App.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { ThemeProvider, DefaultButton, PartialTheme, getTheme } from '@fluentui/react'; import { useBoolean } from '@fluentui/react-hooks'; -import { ContextualMenuExample } from './components/index'; +import { ContextualMenuExample } from './components'; // This app is here as a simple sandbox to render v8 controls inside of an React 18 environment. diff --git a/apps/react-18-tests-v8/src/components/ContextualMenu/ContextualMenu.e2e.tsx b/apps/react-18-tests-v8/src/components/ContextualMenu/ContextualMenu.e2e.tsx deleted file mode 100644 index 9b49359a405f16..00000000000000 --- a/apps/react-18-tests-v8/src/components/ContextualMenu/ContextualMenu.e2e.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import * as React from 'react'; -import { mount } from '@cypress/react'; -import { ContextualMenuItemType, DefaultButton, DirectionalHint } from '@fluentui/react'; - -const menuTriggerSelector = '[type="button"]'; -const menuSelector = '[role="menu"]'; - -describe('ContextualMenu in React 18', () => { - const menuProps = { - shouldFocusOnMount: true, - directionalHint: DirectionalHint.bottomLeftEdge, - items: [ - { key: 'newItem', text: 'New', onClick: () => console.log('New clicked') }, - { key: 'divider_1', itemType: ContextualMenuItemType.Divider }, - { key: 'rename', text: 'Rename', onClick: () => console.log('Rename clicked') }, - { key: 'edit', text: 'Edit', onClick: () => console.log('Edit clicked') }, - { key: 'properties', text: 'Properties', onClick: () => console.log('Properties clicked') }, - { key: 'linkNoTarget', text: 'Link same window', href: 'http://bing.com' }, - { key: 'linkWithTarget', text: 'Link new window', href: 'http://bing.com', target: '_blank' }, - { - key: 'disabled', - text: 'Disabled item', - disabled: true, - onClick: () => console.error('Disabled item should not be clickable.'), - }, - ], - }; - - const MenuButton = () => { - return ( - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - - ); - }; - it('renders ContextualMenu when trigger button is clicked', () => { - mount( - - - , - ); - - cy.get(menuTriggerSelector).click().get(menuSelector).should('be.visible'); - }); -}); diff --git a/apps/react-18-tests-v8/src/components/ContextualMenu/ContextualMenu.test.tsx b/apps/react-18-tests-v8/src/components/ContextualMenu/ContextualMenu.test.tsx deleted file mode 100644 index 87f3c5dfa70316..00000000000000 --- a/apps/react-18-tests-v8/src/components/ContextualMenu/ContextualMenu.test.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import * as React from 'react'; -import { render } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import { ContextualMenuItemType, DefaultButton, DirectionalHint } from '@fluentui/react'; - -describe('ContextualMenu in React 18', () => { - // eslint-disable-next-line @typescript-eslint/no-empty-function - const noop = () => {}; - - beforeEach(() => { - jest.spyOn(console, 'warn').mockImplementation(noop); - }); - - const menuProps = { - shouldFocusOnMount: true, - directionalHint: DirectionalHint.bottomLeftEdge, - items: [ - { key: 'newItem', text: 'New', onClick: () => console.log('New clicked') }, - { key: 'divider_1', itemType: ContextualMenuItemType.Divider }, - { key: 'rename', text: 'Rename', onClick: () => console.log('Rename clicked') }, - { key: 'edit', text: 'Edit', onClick: () => console.log('Edit clicked') }, - { key: 'properties', text: 'Properties', onClick: () => console.log('Properties clicked') }, - { key: 'linkNoTarget', text: 'Link same window', href: 'http://bing.com' }, - { key: 'linkWithTarget', text: 'Link new window', href: 'http://bing.com', target: '_blank' }, - { - key: 'disabled', - text: 'Disabled item', - disabled: true, - onClick: () => console.error('Disabled item should not be clickable.'), - }, - ], - }; - - const MenuButton = () => { - return ( - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - - ); - }; - it('renders ContextualMenu when trigger button is clicked', () => { - const { getByRole, queryAllByRole } = render( - - - , - ); - - expect(queryAllByRole('menu').length).toBe(0); - - const menuTrigger = getByRole('button'); - userEvent.click(menuTrigger); - - expect(queryAllByRole('menu').length).toBe(1); - }); -}); diff --git a/apps/react-18-tests-v8/src/components/ContextualMenu/ContextualMenuExample.cy.tsx b/apps/react-18-tests-v8/src/components/ContextualMenu/ContextualMenuExample.cy.tsx new file mode 100644 index 00000000000000..dae6dd6995c2cc --- /dev/null +++ b/apps/react-18-tests-v8/src/components/ContextualMenu/ContextualMenuExample.cy.tsx @@ -0,0 +1,19 @@ +import * as React from 'react'; +import { mount } from '@cypress/react'; + +import { ContextualMenuExample } from './ContextualMenuExample'; + +const menuTriggerSelector = '[type="button"]'; +const menuSelector = '[role="menu"]'; + +describe('ContextualMenu in React 18', () => { + it('renders ContextualMenu when trigger button is clicked', () => { + mount( + + + , + ); + + cy.get(menuTriggerSelector).click().get(menuSelector).should('be.visible'); + }); +}); diff --git a/apps/react-18-tests-v8/src/components/ContextualMenu/ContextualMenuExample.test.tsx b/apps/react-18-tests-v8/src/components/ContextualMenu/ContextualMenuExample.test.tsx new file mode 100644 index 00000000000000..69669e3d16e9d5 --- /dev/null +++ b/apps/react-18-tests-v8/src/components/ContextualMenu/ContextualMenuExample.test.tsx @@ -0,0 +1,29 @@ +import * as React from 'react'; +import { render } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import { ContextualMenuExample } from './ContextualMenuExample'; + +describe('ContextualMenu in React 18', () => { + // eslint-disable-next-line @typescript-eslint/no-empty-function + const noop = () => {}; + + beforeEach(() => { + jest.spyOn(console, 'warn').mockImplementation(noop); + }); + + it('should render ContextualMenu when trigger button is clicked', () => { + const { getByRole, queryAllByRole } = render( + + + , + ); + + expect(queryAllByRole('menu').length).toBe(0); + + const menuTrigger = getByRole('button'); + userEvent.click(menuTrigger); + + expect(queryAllByRole('menu').length).toBe(1); + }); +}); diff --git a/apps/react-18-tests-v8/tsconfig.app.json b/apps/react-18-tests-v8/tsconfig.app.json index 1db28beeecff91..c2f9c89ec5c8d6 100644 --- a/apps/react-18-tests-v8/tsconfig.app.json +++ b/apps/react-18-tests-v8/tsconfig.app.json @@ -7,8 +7,8 @@ "declaration": true, "declarationDir": "dist/types", "inlineSources": true, - "types": ["static-assets", "environment", "node"] + "types": ["static-assets", "environment"] }, - "exclude": ["./src/common/**", "**/*.spec.ts", "**/*.spec.tsx", "**/*.test.ts", "**/*.test.tsx"], + "exclude": ["**/*.spec.ts", "**/*.spec.tsx", "**/*.test.ts", "**/*.test.tsx", "**/*.cy.ts", "**/*.cy.tsx"], "include": ["./src/**/*.ts", "./src/**/*.tsx"] } diff --git a/apps/react-18-tests-v8/tsconfig.cy.json b/apps/react-18-tests-v8/tsconfig.cy.json index b9d90a02368fe6..ceda454a1b7cbf 100644 --- a/apps/react-18-tests-v8/tsconfig.cy.json +++ b/apps/react-18-tests-v8/tsconfig.cy.json @@ -3,8 +3,8 @@ "compilerOptions": { "jsx": "react", "isolatedModules": false, - "types": ["node", "cypress", "cypress-storybook/cypress", "cypress-real-events"], + "types": ["node", "cypress", "cypress-real-events"], "lib": ["ES2019", "dom"] }, - "include": ["./src/**/*.e2e.ts", "./src/**/*.e2e.tsx"] + "include": ["./src/**/*.cy.ts", "./src/**/*.cy.tsx"] } diff --git a/apps/react-18-tests-v8/webpack.config.js b/apps/react-18-tests-v8/webpack.config.js index 65aee357667149..a3b5b14f5be35c 100644 --- a/apps/react-18-tests-v8/webpack.config.js +++ b/apps/react-18-tests-v8/webpack.config.js @@ -1,7 +1,7 @@ const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); -const { TsconfigPathsPlugin } = require('tsconfig-paths-webpack-plugin'); + +const getResolveAlias = require('@fluentui/scripts/webpack/getResolveAlias'); module.exports = () => { return { @@ -12,14 +12,10 @@ module.exports = () => { }, resolve: { extensions: ['.tsx', '.ts', '.js'], - plugins: [ - new TsconfigPathsPlugin({ - configFile: path.resolve(__dirname, '../../tsconfig.base.json'), - }), - ], alias: { react: path.resolve(__dirname, './node_modules/react'), 'react-dom': path.resolve(__dirname, './node_modules/react-dom'), + ...getResolveAlias(), }, }, module: { @@ -27,7 +23,43 @@ module.exports = () => { { test: /\.tsx?$/, exclude: /node_modules/, - use: 'swc-loader', + use: { + // NOTE: swc-loader throws errors on v8 codebase + loader: 'ts-loader', + options: { + transpileOnly: true, + experimentalWatchApi: true, + }, + }, + }, + { + test: /\.scss$/, + enforce: 'pre', + exclude: [/node_modules/], + use: [ + { + loader: '@microsoft/loader-load-themed-styles', // creates style nodes from JS strings + }, + { + loader: 'css-loader', // translates CSS into CommonJS + options: { + esModule: false, + modules: true, + importLoaders: 2, + }, + }, + { + loader: 'postcss-loader', + options: { + postcssOptions: { + plugins: ['autoprefixer'], + }, + }, + }, + { + loader: 'sass-loader', + }, + ], }, ], }, From a44c913a1a74d02a2d624a0bd1c92535b43aa75d Mon Sep 17 00:00:00 2001 From: Martin Hochel Date: Wed, 23 Nov 2022 15:44:25 +0100 Subject: [PATCH 4/7] feat(react-18-tests-v9): use react-components suite with type checking enabled --- apps/react-18-tests-v9/README.md | 18 ++++++++++++++++++ apps/react-18-tests-v9/package.json | 7 ++----- apps/react-18-tests-v9/src/App.tsx | 4 +--- apps/react-18-tests-v9/tsconfig.app.json | 2 +- .../tsconfig.react-compat-check.json | 7 +++++++ 5 files changed, 29 insertions(+), 9 deletions(-) create mode 100644 apps/react-18-tests-v9/tsconfig.react-compat-check.json diff --git a/apps/react-18-tests-v9/README.md b/apps/react-18-tests-v9/README.md index 0082abbe32eb4a..1745f188f14ca3 100644 --- a/apps/react-18-tests-v9/README.md +++ b/apps/react-18-tests-v9/README.md @@ -21,3 +21,21 @@ This file and process will be replaced with Storybook once we are able to get st ``` Add test files for React 18 issues that have been triaged and resolved so that we do not regress. + +### `type-check` + +To be able to type-check cross React versions we need all v9 libraries build up front so we don't type check all v9 implementation rather public API surface. + +For that purpose we use `tsconfig.react-compat-check.json` as target for `type-check` npm script task, which disables path aliases and forces `tsc` to consume linked monorepo build packages. + +**Local machine flow:** + +```sh +lage build --to @fluentui/react-18-tests-v9 + +yarn workspace @fluentui/react-18-tests-v9 type-check +``` + +**CI:** + +lage defines `build` targets to be executed prior to `type-check`. diff --git a/apps/react-18-tests-v9/package.json b/apps/react-18-tests-v9/package.json index 6738064aa085a9..3454b8571fd365 100644 --- a/apps/react-18-tests-v9/package.json +++ b/apps/react-18-tests-v9/package.json @@ -4,10 +4,9 @@ "version": "1.0.0", "private": true, "scripts": { - "type-check": "tsc -b tsconfig.json", + "type-check": "tsc -p tsconfig.react-compat-check.json", "lint": "eslint --ext .js,.ts,.tsx ./src", "test": "jest --passWithNoTests", - "clean": "just-scripts clean", "format": "prettier -w . --ignore-path ../.prettierignore", "format:check": "yarn format -c", "start": "webpack-dev-server --mode=development", @@ -19,9 +18,7 @@ "@fluentui/scripts": "^1.0.0" }, "dependencies": { - "@fluentui/react-button": "^9.1.9", - "@fluentui/react-provider": "^9.1.8", - "@fluentui/react-theme": "^9.1.2", + "@fluentui/react-components": "^9.7.1", "@types/react": "18.0.14", "@types/react-dom": "18.0.6", "react": "18.2.0", diff --git a/apps/react-18-tests-v9/src/App.tsx b/apps/react-18-tests-v9/src/App.tsx index 7264b9cff04e91..0473e5d5cbba32 100644 --- a/apps/react-18-tests-v9/src/App.tsx +++ b/apps/react-18-tests-v9/src/App.tsx @@ -1,7 +1,5 @@ import * as React from 'react'; -import { Button } from '@fluentui/react-button'; -import { FluentProvider } from '@fluentui/react-provider'; -import { webLightTheme } from '@fluentui/react-theme'; +import { webLightTheme, FluentProvider, Button } from '@fluentui/react-components'; // This app is here as a simple sandbox to render v9 controls inside of an React 18 environement. diff --git a/apps/react-18-tests-v9/tsconfig.app.json b/apps/react-18-tests-v9/tsconfig.app.json index a83db7916f3c11..cb6d5e27588417 100644 --- a/apps/react-18-tests-v9/tsconfig.app.json +++ b/apps/react-18-tests-v9/tsconfig.app.json @@ -1,7 +1,7 @@ { "extends": "./tsconfig.json", "compilerOptions": { - "noEmit": false, + "noEmit": true, "lib": ["ES2019", "dom"], "outDir": "dist", "declaration": true, diff --git a/apps/react-18-tests-v9/tsconfig.react-compat-check.json b/apps/react-18-tests-v9/tsconfig.react-compat-check.json new file mode 100644 index 00000000000000..0f82e55cfd403b --- /dev/null +++ b/apps/react-18-tests-v9/tsconfig.react-compat-check.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.app.json", + "compilerOptions": { + "noEmit": true, + "paths": {} + } +} From 35c95fdfa3f3c0069e4aa5f16d06afdafad61640 Mon Sep 17 00:00:00 2001 From: Martin Hochel Date: Wed, 23 Nov 2022 15:45:10 +0100 Subject: [PATCH 5/7] fixup! feat(react-18-tests-v8): enable build-less DX for start,test,e2e and normalize all test scenarios --- apps/react-18-tests-v8/package.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/react-18-tests-v8/package.json b/apps/react-18-tests-v8/package.json index ca9712c2034225..06b738c06205d7 100644 --- a/apps/react-18-tests-v8/package.json +++ b/apps/react-18-tests-v8/package.json @@ -4,16 +4,14 @@ "version": "8.0.0", "private": true, "scripts": { - "build": "just-scripts build", - "clean": "just-scripts clean", + "type-check": "tsc -b tsconfig.json", "format": "prettier -w . --ignore-path ../.prettierignore", "format:check": "yarn format -c", "e2e": "cypress run --component", "e2e:local": "cypress open --component", "lint": "eslint --ext .js,.ts.,.tsx ./src", "test": "jest --passWithNoTests", - "start": "webpack-dev-server --mode=development", - "type-check": "tsc -b tsconfig.json" + "start": "webpack-dev-server --mode=development" }, "devDependencies": { "@fluentui/eslint-plugin": "*", From 64e8615ec30ad17c79c6382f477d14d95de9ca8f Mon Sep 17 00:00:00 2001 From: Martin Hochel Date: Thu, 24 Nov 2022 12:15:19 +0100 Subject: [PATCH 6/7] fixup! fixup! feat(react-18-tests-v8): enable build-less DX for start,test,e2e and normalize all test scenarios --- apps/react-18-tests-v8/webpack.config.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/react-18-tests-v8/webpack.config.js b/apps/react-18-tests-v8/webpack.config.js index a3b5b14f5be35c..4639c0a818a7c5 100644 --- a/apps/react-18-tests-v8/webpack.config.js +++ b/apps/react-18-tests-v8/webpack.config.js @@ -24,11 +24,10 @@ module.exports = () => { test: /\.tsx?$/, exclude: /node_modules/, use: { - // NOTE: swc-loader throws errors on v8 codebase - loader: 'ts-loader', + loader: 'esbuild-loader', options: { - transpileOnly: true, - experimentalWatchApi: true, + loader: 'tsx', + target: 'es2019', }, }, }, From 84e0eab6fb6757fd3db554b38defa74dc53f3312 Mon Sep 17 00:00:00 2001 From: Martin Hochel Date: Fri, 25 Nov 2022 11:48:11 +0100 Subject: [PATCH 7/7] Apply suggestions from code review --- scripts/cypress/cypress.config.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/cypress/cypress.config.ts b/scripts/cypress/cypress.config.ts index e2794de4cc13df..55781205be1d3f 100644 --- a/scripts/cypress/cypress.config.ts +++ b/scripts/cypress/cypress.config.ts @@ -39,7 +39,6 @@ const cypressWebpackConfig = (): Configuration => { }, }; - // const isV8 = path.basename(process.cwd()) === 'react-examples'; if (isV8()) { // For v8, reuse the storybook webpack config helper to add required options for building v8,