@verdaccio/ui-components 4.0.0-next-8.4 → 4.0.0-next-8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/build/components/CopyClipboard/CopyToClipBoard.js +2 -2
  3. package/build/components/HeaderInfoDialog/HeaderInfoDialog.js +2 -2
  4. package/build/components/Heading/Heading.js +2 -2
  5. package/build/components/Help/Help.js +1 -1
  6. package/build/components/Icons/SvgIcon.js +2 -2
  7. package/build/components/Label/Label.js +2 -2
  8. package/build/components/LinkExternal/LinkExternal.js +2 -2
  9. package/build/components/NoItems/NoItems.js +2 -2
  10. package/build/components/Package/styles.js +13 -13
  11. package/build/components/Readme/Readme.spec.js +4 -2
  12. package/build/components/Readme/Readme.spec.js.map +1 -1
  13. package/build/components/Readme/utils.js +1 -1
  14. package/build/components/Search/Search.js +13 -2
  15. package/build/components/Search/SearchItem.js +2 -2
  16. package/build/components/TextField/TextField.js +2 -2
  17. package/build/components/Versions/HistoryList.js +6 -1
  18. package/build/components/Versions/__partials__/unsorted-versions.json +37 -0
  19. package/build/sections/Header/HeaderSettingsDialog.js +2 -2
  20. package/build/src/AppTest/App.stories.d.ts +9 -8
  21. package/build/src/components/Author/Author.stories.d.ts +1 -1
  22. package/build/src/components/Engines/Engines.stories.d.ts +1 -1
  23. package/build/src/components/Search/Search.d.ts +3 -1
  24. package/build/src/components/Search/Search.stories.d.ts +6 -8
  25. package/build/src/sections/Detail/Detail.stories.d.ts +8 -7
  26. package/build/src/sections/Header/Header.stories.d.ts +6 -5
  27. package/build/src/sections/Home/Home.stories.d.ts +6 -5
  28. package/build/src/sections/SideBar/Sidebar.stories.d.ts +7 -7
  29. package/build/src/store/api.d.ts +3 -0
  30. package/build/src/utils/token-generate.d.ts +4 -0
  31. package/build/store/api.js +1 -1
  32. package/build/store/models/routes.js +1 -1
  33. package/build/utils/token-generate.js +33 -0
  34. package/build/utils/url.js +19 -9
  35. package/package.json +37 -31
  36. package/src/AppTest/App.stories.tsx +81 -24
  37. package/src/AppTest/AppRoute.test.tsx +6 -2
  38. package/src/components/ActionBar/ActionBar.test.tsx +68 -29
  39. package/src/components/Author/Author.stories.tsx +1 -1
  40. package/src/components/Engines/Engines.stories.tsx +12 -12
  41. package/src/components/Help/Help.tsx +1 -1
  42. package/src/components/Package/Package.test.tsx +9 -0
  43. package/src/components/Package/styles.ts +1 -2
  44. package/src/components/Readme/Readme.spec.tsx +2 -2
  45. package/src/components/Readme/utils.ts +2 -2
  46. package/src/components/Search/Search.stories.tsx +24 -2
  47. package/src/components/Search/Search.tsx +7 -3
  48. package/src/components/Versions/HistoryList.tsx +10 -2
  49. package/src/components/Versions/Versions.test.tsx +11 -0
  50. package/src/components/Versions/__partials__/unsorted-versions.json +37 -0
  51. package/src/layouts/Version/Version.stories.tsx +26 -0
  52. package/src/sections/Detail/Detail.stories.tsx +52 -21
  53. package/src/sections/Header/Header.stories.tsx +33 -10
  54. package/src/sections/Home/Home.stories.tsx +25 -8
  55. package/src/sections/SideBar/Sidebar.stories.tsx +53 -28
  56. package/src/store/api.test.ts +4 -2
  57. package/src/store/api.ts +1 -1
  58. package/src/store/models/login.test.ts +25 -19
  59. package/src/utils/token.test.ts +2 -3
  60. package/src/utils/url.ts +25 -9
  61. package/tsconfig.build.json +2 -2
  62. package/tsconfig.json +3 -2
  63. package/vitest.config.mjs +2 -1
  64. package/vitest/api/glob-sidebar.json +0 -12520
  65. package/vitest/api/got-sidebar.json +0 -23346
  66. package/vitest/api/home-packages.json +0 -40
  67. package/vitest/api/jquery-readme.js +0 -3
  68. package/vitest/api/jquery-sidebar.json +0 -5908
  69. package/vitest/api/search-verdaccio.json +0 -1192
  70. package/vitest/api/storybook-readme.js +0 -3
  71. package/vitest/api/storybook-sidebar.json +0 -53782
  72. package/vitest/api/storybook-v.json +0 -53782
  73. package/vitest/identity.js +0 -29
  74. package/vitest/react-markdown.tsx +0 -7
  75. package/vitest/server-handlers.ts +0 -82
  76. package/vitest/server.ts +0 -6
  77. package/vitest/setup-env.ts +0 -33
  78. package/vitest/setup.ts +0 -40
  79. package/vitest/unit/empty-string.ts +0 -1
  80. package/vitest/unit/empty.ts +0 -1
  81. package/vitest/vitestSerializer.ts +0 -31
  82. /package/{vitest/unit/components/__mocks__/token.ts → src/utils/token-generate.ts} +0 -0
@@ -1,3 +1,5 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { HttpResponse, http } from 'msw';
1
3
  import React from 'react';
2
4
  import { MemoryRouter, Route } from 'react-router';
3
5
 
@@ -5,10 +7,14 @@ import { HeaderInfoDialog } from '../../';
5
7
  import { VersionProvider } from '../../providers';
6
8
  import Header from './Header';
7
9
 
8
- export default {
10
+ type Story = StoryObj<typeof Header>;
11
+ const meta: Meta<typeof Header> = {
9
12
  title: 'Sections/Header',
13
+ component: Header,
10
14
  };
11
15
 
16
+ export default meta;
17
+
12
18
  function CustomInfoDialog({ onCloseDialog, title, isOpen }) {
13
19
  return (
14
20
  <HeaderInfoDialog
@@ -25,12 +31,29 @@ function CustomInfoDialog({ onCloseDialog, title, isOpen }) {
25
31
  );
26
32
  }
27
33
 
28
- export const HeaderAll: any = () => (
29
- <MemoryRouter initialEntries={[`/-/web/detail/storybook`]}>
30
- <Route exact={true} path="/-/web/detail/:package">
31
- <VersionProvider>
32
- <Header HeaderInfoDialog={CustomInfoDialog} />
33
- </VersionProvider>
34
- </Route>
35
- </MemoryRouter>
36
- );
34
+ export const HeaderAll: Story = {
35
+ render: () => (
36
+ <MemoryRouter initialEntries={[`/-/web/detail/storybook`]}>
37
+ <Route exact={true} path="/-/web/detail/:package">
38
+ <VersionProvider>
39
+ <Header HeaderInfoDialog={CustomInfoDialog} />
40
+ </VersionProvider>
41
+ </Route>
42
+ </MemoryRouter>
43
+ ),
44
+ parameters: {
45
+ msw: {
46
+ handlers: [
47
+ http.get('https://my-registry.org/-/verdaccio/data/sidebar/storybook', () => {
48
+ return HttpResponse.json(require('../../../vitest/api/storybook-sidebar.json'));
49
+ }),
50
+ http.get('https://my-registry.org/-/verdaccio/data/package/readme/storybook', () => {
51
+ return HttpResponse.json(require('../../../vitest/api/storybook-readme')());
52
+ }),
53
+ http.get('https://my-registry.org/-/verdaccio/data/search/*', () => {
54
+ return HttpResponse.json(require('../../../vitest/api/search-verdaccio.json'));
55
+ }),
56
+ ],
57
+ },
58
+ },
59
+ };
@@ -1,16 +1,33 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { HttpResponse, http } from 'msw';
1
3
  import React from 'react';
2
4
  import { MemoryRouter, Route } from 'react-router';
3
5
 
4
6
  import Home from './Home';
5
7
 
6
- export default {
8
+ type Story = StoryObj<typeof Home>;
9
+ const meta: Meta<typeof Home> = {
7
10
  title: 'Sections/Home',
11
+ component: Home,
8
12
  };
9
13
 
10
- export const HomeDefault: any = () => (
11
- <MemoryRouter initialEntries={[`/`]}>
12
- <Route exact={true} path="/">
13
- <Home />
14
- </Route>
15
- </MemoryRouter>
16
- );
14
+ export default meta;
15
+
16
+ export const HomeDefault: Story = {
17
+ render: () => (
18
+ <MemoryRouter initialEntries={[`/`]}>
19
+ <Route exact={true} path="/">
20
+ <Home />
21
+ </Route>
22
+ </MemoryRouter>
23
+ ),
24
+ parameters: {
25
+ msw: {
26
+ handlers: [
27
+ http.get('https://my-registry.org/-/verdaccio/data/packages', () => {
28
+ return HttpResponse.json([...require('../../../vitest/api/home.json')]);
29
+ }),
30
+ ],
31
+ },
32
+ },
33
+ };
@@ -1,39 +1,64 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { HttpResponse, http } from 'msw';
1
3
  import React from 'react';
2
4
  import { MemoryRouter, Route } from 'react-router';
3
5
 
4
6
  import { VersionProvider } from '../../providers';
5
7
  import DetailSidebar from './Sidebar';
6
8
 
7
- export default {
9
+ const meta: Meta<typeof DetailSidebar> = {
8
10
  title: 'Sections/Sidebar',
11
+ component: DetailSidebar,
9
12
  };
10
13
 
11
- export const SidebarLatestPackage: any = () => (
12
- <MemoryRouter initialEntries={[`/-/web/detail/storybook`]}>
13
- <Route exact={true} path="/-/web/detail/:package">
14
- <VersionProvider>
15
- <DetailSidebar />
16
- </VersionProvider>
17
- </Route>
18
- </MemoryRouter>
19
- );
14
+ export default meta;
20
15
 
21
- export const SidebarPackageVersion: any = () => (
22
- <MemoryRouter initialEntries={[`/-/web/detail/storybook/v/6.0.26`]}>
23
- <Route exact={true} path="/-/web/detail/:package/v/:version">
24
- <VersionProvider>
25
- <DetailSidebar />
26
- </VersionProvider>
27
- </Route>
28
- </MemoryRouter>
29
- );
16
+ type Story = StoryObj<typeof DetailSidebar>;
30
17
 
31
- export const SidebarNoFounding: any = () => (
32
- <MemoryRouter initialEntries={[`/-/web/detail/jquery`]}>
33
- <Route exact={true} path="/-/web/detail/:package">
34
- <VersionProvider>
35
- <DetailSidebar />
36
- </VersionProvider>
37
- </Route>
38
- </MemoryRouter>
39
- );
18
+ export const SidebarLatestPackage: Story = {
19
+ render: () => (
20
+ <MemoryRouter initialEntries={[`/-/web/detail/storybook`]}>
21
+ <Route exact={true} path="/-/web/detail/:package">
22
+ <VersionProvider>
23
+ <DetailSidebar />
24
+ </VersionProvider>
25
+ </Route>
26
+ </MemoryRouter>
27
+ ),
28
+ parameters: {
29
+ msw: {
30
+ handlers: [
31
+ http.get('https://my-registry.org/-/verdaccio/data/sidebar/storybook', () => {
32
+ return HttpResponse.json(require('../../../vitest/api/storybook-sidebar.json'));
33
+ }),
34
+ http.get('https://my-registry.org/-/verdaccio/data/package/readme/storybook', () => {
35
+ return HttpResponse.json(require('../../../vitest/api/storybook-readme')());
36
+ }),
37
+ ],
38
+ },
39
+ },
40
+ };
41
+
42
+ export const SidebarPackageVersion: Story = {
43
+ render: () => (
44
+ <MemoryRouter initialEntries={[`/-/web/detail/storybook/v/6.0.26`]}>
45
+ <Route exact={true} path="/-/web/detail/:package/v/:version">
46
+ <VersionProvider>
47
+ <DetailSidebar />
48
+ </VersionProvider>
49
+ </Route>
50
+ </MemoryRouter>
51
+ ),
52
+ parameters: {
53
+ msw: {
54
+ handlers: [
55
+ http.get('https://my-registry.org/-/verdaccio/data/sidebar/storybook', () => {
56
+ return HttpResponse.json(require('../../../vitest/api/storybook-sidebar.json'));
57
+ }),
58
+ http.get('https://my-registry.org/-/verdaccio/data/package/readme/storybook', () => {
59
+ return HttpResponse.json(require('../../../vitest/api/storybook-readme')());
60
+ }),
61
+ ],
62
+ },
63
+ },
64
+ };
@@ -1,6 +1,6 @@
1
1
  import { vi } from 'vitest';
2
2
 
3
- import api, { handleResponseType } from './api';
3
+ import api, { CustomError, handleResponseType } from './api';
4
4
 
5
5
  describe('api', () => {
6
6
  describe('handleResponseType', () => {
@@ -142,7 +142,9 @@ describe('api', () => {
142
142
  })
143
143
  );
144
144
 
145
- await expect(api.request('/resource')).rejects.toThrow(new Error('Unknown error'));
145
+ const error = new CustomError('Unknown error');
146
+ error.code = 500;
147
+ await expect(api.request('/resource')).rejects.toThrow(error);
146
148
  });
147
149
 
148
150
  test('when api returns an error 5.x.x', async () => {
package/src/store/api.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import storage from './storage';
2
2
 
3
- class CustomError extends Error {
3
+ export class CustomError extends Error {
4
4
  // @ts-ignore
5
5
  code: number;
6
6
  }
@@ -1,20 +1,24 @@
1
1
  import { vi } from 'vitest';
2
2
 
3
- // import { generateTokenWithTimeRange } from '../../../jest/unit/components/__mocks__/token';
3
+ import { generateTokenWithTimeRange } from '../../utils/token-generate';
4
4
 
5
5
  describe('getDefaultUserState', (): void => {
6
6
  const username = 'xyz';
7
7
 
8
8
  beforeEach(() => {
9
9
  vi.resetModules();
10
+ vi.resetAllMocks();
10
11
  });
11
12
 
12
13
  test('should return state with empty user', async () => {
13
14
  const token = 'token-xx-xx-xx';
14
- vi.doMock('../storage', async (importOriginal) => ({
15
- ...(await importOriginal<typeof import('../storage')>()),
16
- getItem: (key: string) => (key === 'token' ? token : username),
15
+
16
+ vi.doMock('../storage', () => ({
17
+ default: {
18
+ getItem: (key: string) => (key === 'token' ? token : username),
19
+ },
17
20
  }));
21
+
18
22
  const Login = await import('./login');
19
23
  const { getDefaultUserState } = Login;
20
24
  const result = {
@@ -24,19 +28,21 @@ describe('getDefaultUserState', (): void => {
24
28
  expect(getDefaultUserState()).toEqual(result);
25
29
  });
26
30
 
27
- // test('should return state with user from storage', async () => {
28
- // const token = generateTokenWithTimeRange(24);
29
- //
30
- // vi.doMock('../storage', async (importOriginal) => ({
31
- // ...(await importOriginal<typeof import('../storage')>()),
32
- // getItem: (key: string) => (key === 'token' ? token : username),
33
- // }));
34
- // const Login = await import('./login');
35
- // const { getDefaultUserState } = Login;
36
- // const result = {
37
- // token,
38
- // username,
39
- // };
40
- // expect(getDefaultUserState()).toEqual(result);
41
- // });
31
+ test('should return state with user from storage', async () => {
32
+ const token = generateTokenWithTimeRange(24);
33
+
34
+ vi.doMock('../storage', () => ({
35
+ default: {
36
+ getItem: (key: string) => (key === 'token' ? token : username),
37
+ },
38
+ }));
39
+
40
+ const Login = await import('./login');
41
+ const { getDefaultUserState } = Login;
42
+ const result = {
43
+ token,
44
+ username,
45
+ };
46
+ expect(getDefaultUserState()).toEqual(result);
47
+ });
42
48
  });
@@ -1,13 +1,12 @@
1
1
  import { vi } from 'vitest';
2
2
 
3
- /* eslint-disable jest/no-mocks-import */
3
+ import { isTokenExpire } from './token';
4
4
  import {
5
5
  generateInvalidToken,
6
6
  generateTokenWithExpirationAsString,
7
7
  generateTokenWithOutExpiration,
8
8
  generateTokenWithTimeRange,
9
- } from '../../vitest/unit/components/__mocks__/token';
10
- import { isTokenExpire } from './token';
9
+ } from './token-generate';
11
10
 
12
11
  /* eslint-disable no-console */
13
12
  console.error = vi.fn();
package/src/utils/url.ts CHANGED
@@ -45,13 +45,29 @@ export function downloadFile(fileStream: Blob, fileName: string): void {
45
45
  fileLink.href = objectURL;
46
46
  fileLink.download = fileName;
47
47
 
48
- // Without appending to an HTML Element, download dialog does not show up on Firefox
49
- // https://github.com/verdaccio/ui/issues/119
50
- document.documentElement.appendChild(fileLink);
51
- fileLink.click();
52
- // firefox requires remove the object url
53
- setTimeout(() => {
54
- URL.revokeObjectURL(objectURL);
55
- document.documentElement.removeChild(fileLink);
56
- }, 150);
48
+ // Skip actual download in test environment to avoid JSDOM navigation error
49
+ // Check if we're in a test environment (JSDOM)
50
+ const isTestEnvironment =
51
+ (typeof window !== 'undefined' &&
52
+ window.navigator &&
53
+ window.navigator.userAgent &&
54
+ window.navigator.userAgent.includes('Node.js')) ||
55
+ window.navigator.userAgent.includes('jsdom');
56
+
57
+ if (!isTestEnvironment) {
58
+ // Without appending to an HTML Element, download dialog does not show up on Firefox
59
+ // https://github.com/verdaccio/ui/issues/119
60
+ document.documentElement.appendChild(fileLink);
61
+ fileLink.click();
62
+ // firefox requires remove the object url
63
+ setTimeout(() => {
64
+ URL.revokeObjectURL(objectURL);
65
+ document.documentElement.removeChild(fileLink);
66
+ }, 150);
67
+ } else {
68
+ // In test environment, just clean up without triggering navigation
69
+ setTimeout(() => {
70
+ URL.revokeObjectURL(objectURL);
71
+ }, 150);
72
+ }
57
73
  }
@@ -10,10 +10,10 @@
10
10
  "rootDir": ".",
11
11
  "outDir": "./build",
12
12
  "skipLibCheck": true,
13
- "jsx": "react"
13
+ "jsx": "react",
14
+ "types": ["node", "@testing-library/jest-dom"]
14
15
  },
15
16
  "include": ["src/**/*", "./src/types/index.d.ts"],
16
- "types": ["node", "@testing-library/jest-dom"],
17
17
  "typedocOptions": {
18
18
  "categoryOrder": ["Model", "Component", "Provider", "*"],
19
19
  "defaultCategory": "Component",
package/tsconfig.json CHANGED
@@ -10,9 +10,10 @@
10
10
  "outDir": "./build",
11
11
  "preserveSymlinks": true,
12
12
  "jsx": "react",
13
- "allowJs": true
13
+ "allowJs": true,
14
+ "types": ["node", "jest", "@testing-library/jest-dom"]
14
15
  },
15
- "types": ["node", "jest", "@testing-library/jest-dom"],
16
+ "include": ["src/**/*", "vitest/**/*", "src/test/**/*"],
16
17
  "references": [
17
18
  {
18
19
  "path": "../core/types"
package/vitest.config.mjs CHANGED
@@ -7,7 +7,7 @@ export default defineConfig({
7
7
  environment: 'jsdom',
8
8
  globals: true,
9
9
  setupFiles: ['./vitest/setup.ts', './vitest/setup-env.ts'],
10
- exclude: ['node_modules', './build/'],
10
+ exclude: ['**/node_modules/**', '**/build/**'],
11
11
  snapshotFormat: {
12
12
  escapeString: true,
13
13
  printBasicPrototype: true,
@@ -22,6 +22,7 @@ export default defineConfig({
22
22
  '\\.(jpg)$': './vitest/unit/empty.ts',
23
23
  '\\.(md)$': './vitest/unit/empty-string.ts',
24
24
  },
25
+ testTimeout: 20000,
25
26
  },
26
27
  plugins: [
27
28
  react({