Skip to content

Commit

Permalink
Merge pull request #26219 from storybookjs/yann/improve-incompatible-…
Browse files Browse the repository at this point in the history
…addon-check

Doctor: Add dynamic check for incompatible Storybook packages
  • Loading branch information
yannbf authored Feb 28, 2024
2 parents a4b5ed0 + d52adbb commit a6c958f
Show file tree
Hide file tree
Showing 12 changed files with 385 additions and 201 deletions.
106 changes: 0 additions & 106 deletions code/lib/cli/src/automigrate/fixes/incompatible-addons.test.ts

This file was deleted.

34 changes: 0 additions & 34 deletions code/lib/cli/src/automigrate/fixes/incompatible-addons.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,12 @@ describe('getMigrationSummary', () => {
You can find more information for a given dependency by running yarn why <package-name>
Please try de-duplicating these dependencies by running yarn dedupe
Please try de-duplicating these dependencies by running yarn dedupe"
You can find more information for a given dependency by running yarn why <package-name>"
`);
});

Expand Down
5 changes: 4 additions & 1 deletion code/lib/cli/src/automigrate/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { FixStatus, allFixes } from './fixes';
import { cleanLog } from './helpers/cleanLog';
import { getMigrationSummary } from './helpers/getMigrationSummary';
import { getStorybookData } from './helpers/mainConfigFile';
import { doctor } from '../doctor';

const logger = console;
const LOG_FILE_NAME = 'migration-storybook.log';
Expand Down Expand Up @@ -83,7 +84,7 @@ export const doAutomigrate = async (options: AutofixOptionsFromCLI) => {
throw new Error('Could not determine main config path');
}

return automigrate({
await automigrate({
...options,
packageManager,
storybookVersion,
Expand All @@ -92,6 +93,8 @@ export const doAutomigrate = async (options: AutofixOptionsFromCLI) => {
configDir,
isUpgrade: false,
});

await doctor({ configDir, packageManager: options.packageManager });
};

export const automigrate = async ({
Expand Down
8 changes: 4 additions & 4 deletions code/lib/cli/src/doctor/getDuplicatedDepsWarnings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,15 @@ export function getDuplicatedDepsWarnings(

messages.push(
'\n',
`You can find more information for a given dependency by running ${chalk.cyan(
`${installationMetadata.infoCommand} <package-name>`
`Please try de-duplicating these dependencies by running ${chalk.cyan(
`${installationMetadata.dedupeCommand}`
)}`
);

messages.push(
'\n',
`Please try de-duplicating these dependencies by running ${chalk.cyan(
`${installationMetadata.dedupeCommand}`
`You can find more information for a given dependency by running ${chalk.cyan(
`${installationMetadata.infoCommand} <package-name>`
)}`
);

Expand Down
158 changes: 158 additions & 0 deletions code/lib/cli/src/doctor/getIncompatibleStorybookPackages.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import { describe, it, expect, vi } from 'vitest';
import type { AnalysedPackage } from './getIncompatibleStorybookPackages';
import {
getIncompatibleStorybookPackages,
getIncompatiblePackagesSummary,
checkPackageCompatibility,
} from './getIncompatibleStorybookPackages';
import type { JsPackageManager } from '@storybook/core-common';

vi.mock('chalk', () => {
return {
default: {
yellow: (str: string) => str,
cyan: (str: string) => str,
bold: (str: string) => str,
},
};
});

vi.mock('./utils', () => ({
getPackageJsonPath: vi.fn(() => Promise.resolve('package.json')),
getPackageJsonOfDependency: vi.fn(() => Promise.resolve({})),
PackageJsonNotFoundError: Error,
}));

const packageManagerMock = {
getAllDependencies: () =>
Promise.resolve({
'@storybook/addon-essentials': '7.0.0',
}),
latestVersion: vi.fn(() => Promise.resolve('8.0.0')),
getPackageJSON: vi.fn(() => Promise.resolve('8.0.0')),
} as any as JsPackageManager;

describe('checkPackageCompatibility', () => {
it('returns that a package is incompatible', async () => {
const packageName = 'my-storybook-package';
vi.mocked(packageManagerMock.getPackageJSON).mockResolvedValueOnce({
name: packageName,
version: '1.0.0',
dependencies: {
'@storybook/core-common': '7.0.0',
},
});
const result = await checkPackageCompatibility(packageName, {
currentStorybookVersion: '8.0.0',
packageManager: packageManagerMock as JsPackageManager,
});
expect(result).toEqual(
expect.objectContaining({
packageName: 'my-storybook-package',
packageVersion: '1.0.0',
hasIncompatibleDependencies: true,
})
);
});

it('returns that a package is compatible', async () => {
const packageName = 'my-storybook-package';
vi.mocked(packageManagerMock.getPackageJSON).mockResolvedValueOnce({
name: packageName,
version: '1.0.0',
dependencies: {
'@storybook/core-common': '8.0.0',
},
});
const result = await checkPackageCompatibility(packageName, {
currentStorybookVersion: '8.0.0',
packageManager: packageManagerMock as JsPackageManager,
});
expect(result).toEqual(
expect.objectContaining({
packageName: 'my-storybook-package',
packageVersion: '1.0.0',
hasIncompatibleDependencies: false,
})
);
});

it('returns that a package is incompatible and because it is core, can be upgraded', async () => {
const packageName = '@storybook/addon-essentials';

vi.mocked(packageManagerMock.getPackageJSON).mockResolvedValueOnce({
name: packageName,
version: '7.0.0',
dependencies: {
'@storybook/core-common': '7.0.0',
},
});

const result = await checkPackageCompatibility(packageName, {
currentStorybookVersion: '8.0.0',
packageManager: packageManagerMock,
});

expect(result).toEqual(
expect.objectContaining({
packageName: '@storybook/addon-essentials',
packageVersion: '7.0.0',
hasIncompatibleDependencies: true,
availableUpdate: '8.0.0',
})
);
});
});

describe('getIncompatibleStorybookPackages', () => {
it('returns an array of incompatible packages', async () => {
vi.mocked(packageManagerMock.getPackageJSON).mockResolvedValueOnce({
name: '@storybook/addon-essentials',
version: '7.0.0',
dependencies: {
'@storybook/core-common': '7.0.0',
},
});

const result = await getIncompatibleStorybookPackages({
currentStorybookVersion: '8.0.0',
packageManager: packageManagerMock as JsPackageManager,
});

expect(result).toEqual([
expect.objectContaining({
packageName: '@storybook/addon-essentials',
hasIncompatibleDependencies: true,
}),
]);
});
});

describe('getIncompatiblePackagesSummary', () => {
it('generates a summary message for incompatible packages', () => {
const analysedPackages: AnalysedPackage[] = [
{
packageName: 'storybook-react',
packageVersion: '1.0.0',
hasIncompatibleDependencies: true,
},
{
packageName: '@storybook/addon-essentials',
packageVersion: '7.0.0',
hasIncompatibleDependencies: true,
availableUpdate: '8.0.0',
},
];
const summary = getIncompatiblePackagesSummary(analysedPackages, '8.0.0');
expect(summary).toMatchInlineSnapshot(`
"The following packages are incompatible with Storybook 8.0.0 as they depend on different major versions of Storybook packages:
- [email protected]
- @storybook/[email protected] (8.0.0 available!)
Please consider updating your packages or contacting the maintainers for compatibility details.
For more on Storybook 8 compatibility, see the linked GitHub issue:
https://github.com/storybookjs/storybook/issues/26031"
`);
});
});
Loading

0 comments on commit a6c958f

Please sign in to comment.