Skip to content
Closed
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
2 changes: 1 addition & 1 deletion docs/docs/cmd/spfx/project/project-upgrade.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ m365 spfx project upgrade [options]

## Remarks

The `spfx project upgrade` command helps you upgrade your SharePoint Framework project to the specified version. If no version is specified, the command will upgrade to the latest version of the SharePoint Framework it supports (v1.20.0).
The `spfx project upgrade` command helps you upgrade your SharePoint Framework project to the specified version. If no version is specified, the command will upgrade to the latest version of the SharePoint Framework it supports (v1.21.0).

This command doesn't change your project files. Instead, it gives you a report with all steps necessary to upgrade your project to the specified version of the SharePoint Framework. Changing project files is error-prone, especially when it comes to updating your solution's code. This is why at this moment, this command produces a report that you can use yourself to perform the necessary updates and verify that everything is working as expected.

Expand Down
8 changes: 8 additions & 0 deletions src/m365/spfx/commands/project/project-doctor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,14 @@ describe(commands.PROJECT_DOCTOR, () => {
assert.strictEqual(findings.length, 0);
});

it('e2e: shows correct number of findings for a valid 1.21.0 project', async () => {
sinon.stub(command as any, 'getProjectRoot').callsFake(_ => path.join(process.cwd(), 'src/m365/spfx/commands/project/test-projects/spfx-1210-webpart-react'));

await command.action(logger, { options: {} } as any);
const findings: FindingToReport[] = log[0];
assert.strictEqual(findings.length, 0);
});

it('passes validation when package manager not specified', async () => {
const actual = await command.validate({ options: {} }, commandInfo);
assert.strictEqual(actual, true);
Expand Down
3 changes: 2 additions & 1 deletion src/m365/spfx/commands/project/project-doctor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ class SpfxProjectDoctorCommand extends BaseProjectCommand {
'1.18.1',
'1.18.2',
'1.19.0',
'1.20.0'
'1.20.0',
'1.21.0'
];

protected get allowedOutputs(): string[] {
Expand Down
25 changes: 25 additions & 0 deletions src/m365/spfx/commands/project/project-doctor/doctor-1.21.0.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { FN002021_DEVDEP_rushstack_eslint_config } from '../project-upgrade/rules/FN002021_DEVDEP_rushstack_eslint_config.js';
import { FN001008_DEP_react } from './rules/FN001008_DEP_react.js';
import { FN001009_DEP_react_dom } from './rules/FN001009_DEP_react_dom.js';
import { FN001035_DEP_fluentui_react } from './rules/FN001035_DEP_fluentui_react.js';
import { FN002004_DEVDEP_gulp } from './rules/FN002004_DEVDEP_gulp.js';
import { FN002007_DEVDEP_ajv } from './rules/FN002007_DEVDEP_ajv.js';
import { FN002013_DEVDEP_types_webpack_env } from './rules/FN002013_DEVDEP_types_webpack_env.js';
import { FN002015_DEVDEP_types_react } from './rules/FN002015_DEVDEP_types_react.js';
import { FN002016_DEVDEP_types_react_dom } from './rules/FN002016_DEVDEP_types_react_dom.js';
import { FN002019_DEVDEP_microsoft_rush_stack_compiler } from './rules/FN002019_DEVDEP_microsoft_rush_stack_compiler.js';
import { FN021001_PKG_spfx_deps_versions_match_project_version } from './rules/FN021001_PKG_spfx_deps_versions_match_project_version.js';

export default [
new FN001008_DEP_react('17'),
new FN001009_DEP_react_dom('17'),
new FN001035_DEP_fluentui_react('^8.106.4'),
new FN002004_DEVDEP_gulp('4.0.2'),
new FN002007_DEVDEP_ajv('^6.12.5'),
new FN002013_DEVDEP_types_webpack_env('~1.15.2'),
new FN002015_DEVDEP_types_react('17'),
new FN002016_DEVDEP_types_react_dom('17'),
new FN002019_DEVDEP_microsoft_rush_stack_compiler(['5.3']),
new FN002021_DEVDEP_rushstack_eslint_config('4.0.1'),
new FN021001_PKG_spfx_deps_versions_match_project_version(true)
];
66 changes: 66 additions & 0 deletions src/m365/spfx/commands/project/project-upgrade.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3371,6 +3371,72 @@ describe(commands.PROJECT_UPGRADE, () => {
});
//#endregion

//#region 1.20.0
it('e2e: shows correct number of findings for upgrading ace 1.20.0 project to 1.21.0', async () => {
sinon.stub(command as any, 'getProjectRoot').callsFake(_ => path.join(process.cwd(), 'src/m365/spfx/commands/project/test-projects/spfx-1200-ace'));

await command.action(logger, { options: { toVersion: '1.21.0', preview: true, output: 'json' } } as any);
const findings: FindingToReport[] = log[0];
assert.strictEqual(findings.length, 14);
});

it('e2e: shows correct number of findings for upgrading application customizer 1.20.0 project to 1.21.0', async () => {
sinon.stub(command as any, 'getProjectRoot').callsFake(_ => path.join(process.cwd(), 'src/m365/spfx/commands/project/test-projects/spfx-1200-applicationcustomizer'));

await command.action(logger, { options: { toVersion: '1.21.0', preview: true, output: 'json' } } as any);
const findings: FindingToReport[] = log[0];
assert.strictEqual(findings.length, 16);
});

it('e2e: shows correct number of findings for upgrading field customizer react 1.20.0 project to 1.21.0', async () => {
sinon.stub(command as any, 'getProjectRoot').callsFake(_ => path.join(process.cwd(), 'src/m365/spfx/commands/project/test-projects/spfx-1200-fieldcustomizer-react'));

await command.action(logger, { options: { toVersion: '1.21.0', preview: true, output: 'json' } } as any);
const findings: FindingToReport[] = log[0];
assert.strictEqual(findings.length, 15);
});

it('e2e: shows correct number of findings for upgrading form customizer react 1.20.0 project to 1.21.0', async () => {
sinon.stub(command as any, 'getProjectRoot').callsFake(_ => path.join(process.cwd(), 'src/m365/spfx/commands/project/test-projects/spfx-1200-formcustomizer-react'));

await command.action(logger, { options: { toVersion: '1.21.0', preview: true, output: 'json' } } as any);
const findings: FindingToReport[] = log[0];
assert.strictEqual(findings.length, 17);
});

it('e2e: shows correct number of findings for upgrading list view command set 1.20.0 project to 1.21.0', async () => {
sinon.stub(command as any, 'getProjectRoot').callsFake(_ => path.join(process.cwd(), 'src/m365/spfx/commands/project/test-projects/spfx-1200-listviewcommandset'));

await command.action(logger, { options: { toVersion: '1.21.0', preview: true, output: 'json' } } as any);
const findings: FindingToReport[] = log[0];
assert.strictEqual(findings.length, 16);
});

it('e2e: shows correct number of findings for upgrading no framework web part 1.20.0 project to 1.21.0', async () => {
sinon.stub(command as any, 'getProjectRoot').callsFake(_ => path.join(process.cwd(), 'src/m365/spfx/commands/project/test-projects/spfx-1200-webpart-nolib'));

await command.action(logger, { options: { toVersion: '1.21.0', preview: true, output: 'json' } } as any);
const findings: FindingToReport[] = log[0];
assert.strictEqual(findings.length, 18);
});

it('e2e: shows correct number of findings for upgrading react web part 1.20.0 project to 1.21.0', async () => {
sinon.stub(command as any, 'getProjectRoot').callsFake(_ => path.join(process.cwd(), 'src/m365/spfx/commands/project/test-projects/spfx-1200-webpart-react'));

await command.action(logger, { options: { toVersion: '1.21.0', preview: true, output: 'json' } } as any);
const findings: FindingToReport[] = log[0];
assert.strictEqual(findings.length, 18);
});

it('e2e: shows correct number of findings for upgrading web part with optional dependencies 1.20.0 project to 1.21.0', async () => {
sinon.stub(command as any, 'getProjectRoot').callsFake(_ => path.join(process.cwd(), 'src/m365/spfx/commands/project/test-projects/spfx-1200-webpart-optionaldeps'));

await command.action(logger, { options: { toVersion: '1.21.0', preview: true, output: 'json' } } as any);
const findings: FindingToReport[] = log[0];
assert.strictEqual(findings.length, 28);
});
//#endregion

//#region superseded rules
it('ignores superseded findings (1.1.0 > 1.2.0)', async () => {
sinon.stub(command as any, 'getProjectRoot').returns(path.join(process.cwd(), 'src/m365/spfx/commands/project/test-projects/spfx-110-webpart-react'));
Expand Down
3 changes: 2 additions & 1 deletion src/m365/spfx/commands/project/project-upgrade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ class SpfxProjectUpgradeCommand extends BaseProjectCommand {
'1.18.1',
'1.18.2',
'1.19.0',
'1.20.0'
'1.20.0',
'1.21.0'
];

public static ERROR_NO_PROJECT_ROOT_FOLDER: number = 1;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { DependencyRule } from "./DependencyRule.js";

export class FN002029_DEVDEP_microsoft_rush_stack_compiler_5_3 extends DependencyRule {
constructor(packageVersion: string) {
super('@microsoft/rush-stack-compiler-5.3', packageVersion, true);
}

get id(): string {
return 'FN002029';
}

get supersedes(): string[] {
return ['FN002010', 'FN002011', 'FN002012', 'FN002017', 'FN002018', 'FN002020', 'FN002028'];
}
}
63 changes: 63 additions & 0 deletions src/m365/spfx/commands/project/project-upgrade/upgrade-1.21.0.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { FN001001_DEP_microsoft_sp_core_library } from './rules/FN001001_DEP_microsoft_sp_core_library.js';
import { FN001002_DEP_microsoft_sp_lodash_subset } from './rules/FN001002_DEP_microsoft_sp_lodash_subset.js';
import { FN001003_DEP_microsoft_sp_office_ui_fabric_core } from './rules/FN001003_DEP_microsoft_sp_office_ui_fabric_core.js';
import { FN001004_DEP_microsoft_sp_webpart_base } from './rules/FN001004_DEP_microsoft_sp_webpart_base.js';
import { FN001011_DEP_microsoft_sp_dialog } from './rules/FN001011_DEP_microsoft_sp_dialog.js';
import { FN001012_DEP_microsoft_sp_application_base } from './rules/FN001012_DEP_microsoft_sp_application_base.js';
import { FN001013_DEP_microsoft_decorators } from './rules/FN001013_DEP_microsoft_decorators.js';
import { FN001014_DEP_microsoft_sp_listview_extensibility } from './rules/FN001014_DEP_microsoft_sp_listview_extensibility.js';
import { FN001021_DEP_microsoft_sp_property_pane } from './rules/FN001021_DEP_microsoft_sp_property_pane.js';
import { FN001023_DEP_microsoft_sp_component_base } from './rules/FN001023_DEP_microsoft_sp_component_base.js';
import { FN001024_DEP_microsoft_sp_diagnostics } from './rules/FN001024_DEP_microsoft_sp_diagnostics.js';
import { FN001025_DEP_microsoft_sp_dynamic_data } from './rules/FN001025_DEP_microsoft_sp_dynamic_data.js';
import { FN001026_DEP_microsoft_sp_extension_base } from './rules/FN001026_DEP_microsoft_sp_extension_base.js';
import { FN001027_DEP_microsoft_sp_http } from './rules/FN001027_DEP_microsoft_sp_http.js';
import { FN001028_DEP_microsoft_sp_list_subscription } from './rules/FN001028_DEP_microsoft_sp_list_subscription.js';
import { FN001029_DEP_microsoft_sp_loader } from './rules/FN001029_DEP_microsoft_sp_loader.js';
import { FN001030_DEP_microsoft_sp_module_interfaces } from './rules/FN001030_DEP_microsoft_sp_module_interfaces.js';
import { FN001031_DEP_microsoft_sp_odata_types } from './rules/FN001031_DEP_microsoft_sp_odata_types.js';
import { FN001032_DEP_microsoft_sp_page_context } from './rules/FN001032_DEP_microsoft_sp_page_context.js';
import { FN001034_DEP_microsoft_sp_adaptive_card_extension_base } from './rules/FN001034_DEP_microsoft_sp_adaptive_card_extension_base.js';
import { FN002001_DEVDEP_microsoft_sp_build_web } from './rules/FN002001_DEVDEP_microsoft_sp_build_web.js';
import { FN002002_DEVDEP_microsoft_sp_module_interfaces } from './rules/FN002002_DEVDEP_microsoft_sp_module_interfaces.js';
import { FN002022_DEVDEP_microsoft_eslint_plugin_spfx } from './rules/FN002022_DEVDEP_microsoft_eslint_plugin_spfx.js';
import { FN002023_DEVDEP_microsoft_eslint_config_spfx } from './rules/FN002023_DEVDEP_microsoft_eslint_config_spfx.js';
import { FN002024_DEVDEP_eslint } from './rules/FN002024_DEVDEP_eslint.js';
import { FN002026_DEVDEP_typescript } from './rules/FN002026_DEVDEP_typescript.js';
import { FN002029_DEVDEP_microsoft_rush_stack_compiler_5_3 } from './rules/FN002029_DEVDEP_microsoft_rush_stack_compiler_5_3.js';
import { FN010001_YORC_version } from './rules/FN010001_YORC_version.js';
import { FN012017_TSC_extends } from './rules/FN012017_TSC_extends.js';
import { FN021003_PKG_engines_node } from './rules/FN021003_PKG_engines_node.js';

export default [
new FN001001_DEP_microsoft_sp_core_library('1.21.0'),
new FN001002_DEP_microsoft_sp_lodash_subset('1.21.0'),
new FN001003_DEP_microsoft_sp_office_ui_fabric_core('1.21.0'),
new FN001004_DEP_microsoft_sp_webpart_base('1.21.0'),
new FN001011_DEP_microsoft_sp_dialog('1.21.0'),
new FN001012_DEP_microsoft_sp_application_base('1.21.0'),
new FN001014_DEP_microsoft_sp_listview_extensibility('1.21.0'),
new FN001021_DEP_microsoft_sp_property_pane('1.21.0'),
new FN001023_DEP_microsoft_sp_component_base('1.21.0'),
new FN001024_DEP_microsoft_sp_diagnostics('1.21.0'),
new FN001025_DEP_microsoft_sp_dynamic_data('1.21.0'),
new FN001026_DEP_microsoft_sp_extension_base('1.21.0'),
new FN001027_DEP_microsoft_sp_http('1.21.0'),
new FN001028_DEP_microsoft_sp_list_subscription('1.21.0'),
new FN001029_DEP_microsoft_sp_loader('1.21.0'),
new FN001030_DEP_microsoft_sp_module_interfaces('1.21.0'),
new FN001031_DEP_microsoft_sp_odata_types('1.21.0'),
new FN001032_DEP_microsoft_sp_page_context('1.21.0'),
new FN001013_DEP_microsoft_decorators('1.21.0'),
new FN001034_DEP_microsoft_sp_adaptive_card_extension_base('1.21.0'),
new FN002001_DEVDEP_microsoft_sp_build_web('1.21.0'),
new FN002002_DEVDEP_microsoft_sp_module_interfaces('1.21.0'),
new FN002024_DEVDEP_eslint('8.57.1'),
new FN002022_DEVDEP_microsoft_eslint_plugin_spfx('1.21.0'),
new FN002023_DEVDEP_microsoft_eslint_config_spfx('1.21.0'),
new FN002026_DEVDEP_typescript('5.3.3'),
new FN002029_DEVDEP_microsoft_rush_stack_compiler_5_3('0.1.0'),
new FN010001_YORC_version('1.21.0'),
new FN012017_TSC_extends('./node_modules/@microsoft/rush-stack-compiler-5.3/includes/tsconfig-web.json'),
new FN021003_PKG_engines_node('>=22.14.0 < 23.0.0')
];
Loading