@verdaccio/ui-components 3.0.0-next-7.7 → 3.0.0-next-7.8

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 (300) hide show
  1. package/.eslintrc +1 -1
  2. package/CHANGELOG.md +6 -0
  3. package/build/Theme/theme.js +3 -3
  4. package/build/components/ActionBar/ActionBar.js +3 -1
  5. package/build/components/ActionBar/ActionBarAction.js +7 -6
  6. package/build/components/Author/Author.js +13 -42
  7. package/build/components/CopyClipboard/utils.js +3 -12
  8. package/build/components/Dependencies/Dependencies.js +12 -13
  9. package/build/components/Dependencies/DependencyBlock.js +5 -4
  10. package/build/components/Developers/DeveloperType.js +12 -0
  11. package/build/components/Developers/Developers.js +20 -22
  12. package/build/components/Developers/Title.js +5 -9
  13. package/build/components/Developers/index.js +4 -4
  14. package/build/components/Distribution/Dist.js +1 -1
  15. package/build/components/Distribution/styles.js +10 -23
  16. package/build/components/Engines/Engines.js +7 -1
  17. package/build/components/Engines/styles.js +6 -6
  18. package/build/components/FundButton/FundButton.js +7 -8
  19. package/build/components/HeaderInfoDialog/HeaderInfoDialog.js +2 -1
  20. package/build/components/Icons/DevsIcons/CommonJS.js +1 -12
  21. package/build/components/Icons/DevsIcons/ES6Module.js +2 -13
  22. package/build/components/Icons/DevsIcons/Git.js +1 -12
  23. package/build/components/Icons/DevsIcons/NodeJS.js +1 -12
  24. package/build/components/Icons/DevsIcons/TypeScript.js +1 -12
  25. package/build/components/Icons/FileBinary.js +11 -5
  26. package/build/components/Icons/Law.js +12 -6
  27. package/build/components/Icons/Managers/Npm.js +1 -12
  28. package/build/components/Icons/Managers/Pnpm.js +1 -12
  29. package/build/components/Icons/Managers/Yarn.js +1 -12
  30. package/build/components/Install/Install.js +23 -18
  31. package/build/components/Install/InstallListItem.js +19 -18
  32. package/build/components/Keywords/KeywordListItems.js +34 -0
  33. package/build/components/Keywords/Keywords.js +39 -0
  34. package/build/{sections/Header/RegistryInfoDialog → components/Keywords}/index.js +2 -2
  35. package/build/components/Link/Link.js +4 -16
  36. package/build/components/Link/index.js +1 -1
  37. package/build/components/LinkExternal/LinkExternal.js +32 -0
  38. package/build/components/LinkExternal/index.js +14 -0
  39. package/build/components/Loading/styles.js +3 -2
  40. package/build/components/LoginDialog/LoginDialog.js +12 -1
  41. package/build/components/LoginDialog/LoginDialogCloseButton.js +3 -2
  42. package/build/components/LoginDialog/LoginDialogForm.js +2 -14
  43. package/build/components/LoginDialog/LoginDialogFormError.js +3 -2
  44. package/build/components/Logo/Logo.js +13 -6
  45. package/build/components/Package/Package.js +43 -34
  46. package/build/components/Package/styles.js +46 -58
  47. package/build/components/Person/Person.js +48 -0
  48. package/build/components/Person/PersonTooltip.js +22 -0
  49. package/build/components/{Package/Tag → Person}/index.js +2 -2
  50. package/build/components/Person/utils.js +17 -0
  51. package/build/components/RawViewer/RawViewer.js +11 -5
  52. package/build/components/Readme/Readme.js +15 -6
  53. package/build/components/Readme/Readme.js.map +1 -1
  54. package/build/components/Readme/Readme.spec.js +19 -0
  55. package/build/components/Readme/Readme.spec.js.map +1 -1
  56. package/build/components/Readme/utils.js +2 -5
  57. package/build/components/RegistryInfoDialog/styles.js +9 -10
  58. package/build/components/Repository/Repository.js +19 -31
  59. package/build/components/Search/AutoComplete/styles.js +4 -41
  60. package/build/components/Search/Search.js +4 -2
  61. package/build/components/Search/SearchItem.js +51 -38
  62. package/build/components/Search/utils.js +23 -0
  63. package/build/components/SettingsMenu/SettingsMenu.js +35 -9
  64. package/build/components/SideBarTitle/SideBarTitle.js +16 -6
  65. package/build/components/UpLinks/UpLinks.js +35 -6
  66. package/build/components/UpLinks/UplinkLink.js +22 -0
  67. package/build/components/UpLinks/styles.js +5 -4
  68. package/build/components/Versions/HistoryList.js +8 -5
  69. package/build/components/Versions/TagList.js +8 -4
  70. package/build/components/Versions/Versions.js +30 -7
  71. package/build/index.js +27 -3
  72. package/build/providers/AppConfigurationProvider/AppConfigurationProvider.js +1 -0
  73. package/build/providers/PersistenceSettingProvider/PersistenceSettingProvider.js +1 -0
  74. package/build/sections/Detail/Detail.js +6 -2
  75. package/build/sections/Detail/Tabs.js +4 -3
  76. package/build/sections/Footer/Footer.js +17 -8
  77. package/build/sections/Footer/styles.js +13 -10
  78. package/build/sections/Header/HeaderLeft.js +14 -17
  79. package/build/sections/Header/HeaderMenu.js +1 -1
  80. package/build/sections/Header/HeaderRight.js +12 -3
  81. package/build/sections/Header/HeaderSettingsDialog.js +2 -2
  82. package/build/sections/Header/styles.js +43 -82
  83. package/build/sections/SideBar/Sidebar.js +10 -15
  84. package/build/src/Theme/ThemeProvider.test.d.ts +1 -0
  85. package/build/src/components/Author/Author.d.ts +0 -5
  86. package/build/src/components/CopyClipboard/CopyToClipBoard.test.d.ts +1 -0
  87. package/build/src/components/Dependencies/Dependencies.d.ts +0 -1
  88. package/build/src/components/Developers/DeveloperType.d.ts +4 -0
  89. package/build/src/components/Developers/Developers.d.ts +1 -4
  90. package/build/src/components/Developers/Title.d.ts +1 -4
  91. package/build/src/components/Developers/index.d.ts +2 -1
  92. package/build/src/components/Distribution/styles.d.ts +0 -1
  93. package/build/src/components/ErrorBoundary/ErrorBoundary.test.d.ts +1 -0
  94. package/build/src/components/HeaderInfoDialog/HeaderInfoDialog.test.d.ts +1 -0
  95. package/build/src/components/Heading/Heading.test.d.ts +1 -0
  96. package/build/src/components/Icons/Icons.test.d.ts +1 -0
  97. package/build/src/components/Install/InstallListItem.d.ts +1 -1
  98. package/build/src/components/Keywords/KeywordListItems.d.ts +5 -0
  99. package/build/src/components/Keywords/Keywords.d.ts +6 -0
  100. package/build/src/components/Keywords/Keywords.stories.d.ts +5 -0
  101. package/build/src/components/Keywords/Keywords.test.d.ts +1 -0
  102. package/build/src/components/Keywords/index.d.ts +1 -0
  103. package/build/src/components/Link/Link.d.ts +0 -3
  104. package/build/src/components/Link/Link.test.d.ts +1 -0
  105. package/build/src/components/Link/index.d.ts +1 -1
  106. package/build/src/components/LinkExternal/LinkExternal.d.ts +3 -0
  107. package/build/src/components/LinkExternal/LinkExternal.test.d.ts +1 -0
  108. package/build/src/components/LinkExternal/index.d.ts +1 -0
  109. package/build/src/components/Logo/Logo.d.ts +1 -0
  110. package/build/src/components/Logo/Logo.stories.d.ts +5 -0
  111. package/build/src/components/Package/Package.d.ts +1 -1
  112. package/build/src/components/Package/styles.d.ts +0 -8
  113. package/build/src/components/Person/Person.d.ts +9 -0
  114. package/build/src/components/Person/Person.test.d.ts +1 -0
  115. package/build/src/components/Person/PersonTooltip.d.ts +6 -0
  116. package/build/src/components/Person/index.d.ts +1 -0
  117. package/build/src/components/Person/utils.d.ts +3 -0
  118. package/build/src/components/Readme/Readme.d.ts +0 -1
  119. package/build/src/components/Search/AutoComplete/styles.d.ts +0 -8
  120. package/build/src/components/Search/utils.d.ts +1 -0
  121. package/build/src/components/SettingsMenu/SettingsMenu.d.ts +2 -2
  122. package/build/src/components/SettingsMenu/SettingsMenu.test.d.ts +1 -0
  123. package/build/src/components/UpLinks/UplinkLink.d.ts +6 -0
  124. package/build/src/components/Versions/Versions.d.ts +1 -0
  125. package/build/src/index.d.ts +4 -1
  126. package/build/src/sections/Detail/Tabs.d.ts +1 -0
  127. package/build/src/sections/Header/styles.d.ts +0 -7
  128. package/build/src/store/models/routes.d.ts +8 -0
  129. package/build/src/store/models/utils.d.ts +1 -0
  130. package/build/src/types/packageMeta.d.ts +7 -5
  131. package/build/src/utils/routes.d.ts +1 -0
  132. package/build/src/utils/utils.d.ts +1 -0
  133. package/build/store/models/configuration.js +2 -1
  134. package/build/store/models/login.js +4 -2
  135. package/build/store/models/manifest.js +5 -3
  136. package/build/store/models/packages.js +4 -2
  137. package/build/store/models/routes.js +18 -0
  138. package/build/store/models/search.js +4 -2
  139. package/build/store/models/utils.js +10 -0
  140. package/build/utils/routes.js +1 -0
  141. package/build/utils/utils.js +20 -1
  142. package/package.json +2 -2
  143. package/src/AppTest/AppRoute.test.tsx +65 -0
  144. package/src/Theme/ThemeProvider.test.tsx +27 -0
  145. package/src/Theme/theme.ts +3 -3
  146. package/src/components/ActionBar/ActionBar.test.tsx +36 -15
  147. package/src/components/ActionBar/ActionBar.tsx +1 -1
  148. package/src/components/ActionBar/ActionBarAction.tsx +8 -5
  149. package/src/components/Author/Author.test.tsx +7 -1
  150. package/src/components/Author/Author.tsx +3 -41
  151. package/src/components/CopyClipboard/CopyToClipBoard.test.tsx +23 -0
  152. package/src/components/CopyClipboard/utils.ts +2 -13
  153. package/src/components/Dependencies/Dependencies.tsx +9 -9
  154. package/src/components/Dependencies/DependencyBlock.tsx +2 -1
  155. package/src/components/Developers/DeveloperType.tsx +4 -0
  156. package/src/components/Developers/Developers.test.tsx +37 -10
  157. package/src/components/Developers/Developers.tsx +13 -13
  158. package/src/components/Developers/Title.tsx +1 -5
  159. package/src/components/Developers/index.ts +2 -1
  160. package/src/components/Distribution/Dist.test.tsx +1 -1
  161. package/src/components/Distribution/Dist.tsx +2 -4
  162. package/src/components/Distribution/styles.ts +0 -6
  163. package/src/components/Engines/Engines.tsx +6 -2
  164. package/src/components/Engines/styles.ts +1 -1
  165. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +39 -0
  166. package/src/components/FundButton/FundButton.tsx +5 -5
  167. package/src/components/HeaderInfoDialog/HeaderInfoDialog.test.tsx +51 -0
  168. package/src/components/HeaderInfoDialog/HeaderInfoDialog.tsx +2 -2
  169. package/src/components/Heading/Heading.test.tsx +20 -0
  170. package/src/components/Icons/DevsIcons/CommonJS.tsx +1 -7
  171. package/src/components/Icons/DevsIcons/ES6Module.tsx +2 -8
  172. package/src/components/Icons/DevsIcons/Git.tsx +1 -7
  173. package/src/components/Icons/DevsIcons/NodeJS.tsx +1 -7
  174. package/src/components/Icons/DevsIcons/TypeScript.tsx +1 -7
  175. package/src/components/Icons/FileBinary.tsx +2 -1
  176. package/src/components/Icons/Icons.stories.tsx +21 -5
  177. package/src/components/Icons/Icons.test.tsx +70 -0
  178. package/src/components/Icons/Law.tsx +2 -1
  179. package/src/components/Icons/Managers/Npm.tsx +1 -7
  180. package/src/components/Icons/Managers/Pnpm.tsx +1 -7
  181. package/src/components/Icons/Managers/Yarn.tsx +1 -7
  182. package/src/components/Install/Install.test.tsx +54 -13
  183. package/src/components/Install/Install.tsx +12 -11
  184. package/src/components/Install/InstallListItem.tsx +12 -11
  185. package/src/components/Keywords/KeywordListItems.tsx +22 -0
  186. package/src/components/Keywords/Keywords.stories.tsx +19 -0
  187. package/src/components/Keywords/Keywords.test.tsx +57 -0
  188. package/src/components/Keywords/Keywords.tsx +35 -0
  189. package/src/components/Keywords/index.ts +1 -0
  190. package/src/components/Link/Link.test.tsx +25 -0
  191. package/src/components/Link/Link.tsx +4 -18
  192. package/src/components/Link/index.ts +1 -1
  193. package/src/components/LinkExternal/LinkExternal.test.tsx +18 -0
  194. package/src/components/LinkExternal/LinkExternal.tsx +22 -0
  195. package/src/components/LinkExternal/index.ts +1 -0
  196. package/src/components/Loading/Loading.test.tsx +8 -5
  197. package/src/components/Loading/styles.ts +1 -0
  198. package/src/components/LoginDialog/LoginDialog.test.tsx +1 -1
  199. package/src/components/LoginDialog/LoginDialog.tsx +10 -1
  200. package/src/components/LoginDialog/LoginDialogCloseButton.tsx +1 -0
  201. package/src/components/LoginDialog/LoginDialogForm.tsx +0 -2
  202. package/src/components/LoginDialog/LoginDialogFormError.tsx +1 -1
  203. package/src/components/Logo/Logo.stories.tsx +16 -0
  204. package/src/components/Logo/Logo.test.tsx +8 -1
  205. package/src/components/Logo/Logo.tsx +19 -3
  206. package/src/components/Package/Package.test.tsx +47 -14
  207. package/src/components/Package/Package.tsx +41 -44
  208. package/src/components/Package/styles.ts +7 -17
  209. package/src/components/PackageList/Packagelist.test.tsx +1 -0
  210. package/src/components/Person/Person.test.tsx +50 -0
  211. package/src/components/Person/Person.tsx +45 -0
  212. package/src/components/Person/PersonTooltip.tsx +26 -0
  213. package/src/components/Person/index.ts +1 -0
  214. package/src/components/Person/utils.ts +20 -0
  215. package/src/components/RawViewer/RawViewer.tsx +8 -4
  216. package/src/components/Readme/Readme.spec.tsx +17 -0
  217. package/src/components/Readme/Readme.tsx +10 -5
  218. package/src/components/Readme/utils.ts +2 -5
  219. package/src/components/RegistryInfoDialog/styles.ts +5 -4
  220. package/src/components/Repository/Repository.tsx +9 -14
  221. package/src/components/Search/AutoComplete/styles.ts +7 -0
  222. package/src/components/Search/Search.test.tsx +36 -9
  223. package/src/components/Search/Search.tsx +4 -2
  224. package/src/components/Search/SearchItem.tsx +19 -8
  225. package/src/components/Search/utils.ts +17 -0
  226. package/src/components/SettingsMenu/SettingsMenu.test.tsx +41 -0
  227. package/src/components/SettingsMenu/SettingsMenu.tsx +48 -10
  228. package/src/components/SideBarTitle/SideBarTitle.tsx +19 -3
  229. package/src/components/UpLinks/UpLinks.test.tsx +7 -0
  230. package/src/components/UpLinks/UpLinks.tsx +38 -15
  231. package/src/components/UpLinks/UplinkLink.tsx +20 -0
  232. package/src/components/UpLinks/styles.ts +1 -0
  233. package/src/components/Versions/HistoryList.tsx +9 -4
  234. package/src/components/Versions/TagList.tsx +4 -3
  235. package/src/components/Versions/Versions.test.tsx +2 -0
  236. package/src/components/Versions/Versions.tsx +57 -32
  237. package/src/index.ts +4 -1
  238. package/src/providers/AppConfigurationProvider/AppConfigurationProvider.tsx +1 -0
  239. package/src/providers/PersistenceSettingProvider/PersistenceSettingProvider.tsx +2 -0
  240. package/src/providers/VersionProvider/VersionProvider.test.tsx +3 -3
  241. package/src/sections/Detail/Detail.test.tsx +8 -1
  242. package/src/sections/Detail/Detail.tsx +11 -4
  243. package/src/sections/Detail/Tabs.tsx +5 -2
  244. package/src/sections/Footer/Footer.tsx +15 -4
  245. package/src/sections/Footer/styles.ts +4 -0
  246. package/src/sections/Header/Header.test.tsx +12 -10
  247. package/src/sections/Header/HeaderLeft.tsx +19 -11
  248. package/src/sections/Header/HeaderMenu.tsx +1 -1
  249. package/src/sections/Header/HeaderRight.tsx +14 -3
  250. package/src/sections/Header/HeaderSettingsDialog.tsx +1 -1
  251. package/src/sections/Header/RegistryInfoContent/RegistryInfoContent.test.tsx +1 -1
  252. package/src/sections/Header/styles.ts +4 -16
  253. package/src/sections/Home/Home.test.tsx +12 -4
  254. package/src/sections/SideBar/Sidebar.test.tsx +20 -13
  255. package/src/sections/SideBar/Sidebar.tsx +5 -9
  256. package/src/store/api.test.ts +16 -0
  257. package/src/store/models/configuration.ts +2 -1
  258. package/src/store/models/login.ts +10 -12
  259. package/src/store/models/manifest.ts +6 -5
  260. package/src/store/models/packages.ts +4 -5
  261. package/src/store/models/routes.ts +10 -0
  262. package/src/store/models/search.ts +4 -2
  263. package/src/store/models/utils.ts +3 -0
  264. package/src/types/packageMeta.ts +7 -5
  265. package/src/utils/routes.ts +1 -0
  266. package/src/utils/utils.test.ts +34 -0
  267. package/src/utils/utils.ts +20 -5
  268. package/tsconfig.json +1 -1
  269. package/build/components/Developers/styles.js +0 -65
  270. package/build/components/Distribution/utils.js +0 -25
  271. package/build/components/Distribution/utilts.spec.js +0 -18
  272. package/build/components/Package/Tag/Tag.js +0 -14
  273. package/build/components/Package/Tag/styles.js +0 -24
  274. package/build/sections/Header/RegistryInfoDialog/RegistryInfoDialog.js +0 -36
  275. package/build/sections/Header/RegistryInfoDialog/styles.js +0 -46
  276. package/build/sections/Header/RegistryInfoDialog/types.js +0 -6
  277. package/build/src/components/Developers/styles.d.ts +0 -11
  278. package/build/src/components/Distribution/utils.d.ts +0 -7
  279. package/build/src/components/Package/Tag/Tag.d.ts +0 -6
  280. package/build/src/components/Package/Tag/index.d.ts +0 -1
  281. package/build/src/components/Package/Tag/styles.d.ts +0 -5
  282. package/build/src/sections/Header/RegistryInfoDialog/RegistryInfoDialog.d.ts +0 -4
  283. package/build/src/sections/Header/RegistryInfoDialog/index.d.ts +0 -1
  284. package/build/src/sections/Header/RegistryInfoDialog/styles.d.ts +0 -13
  285. package/build/src/sections/Header/RegistryInfoDialog/types.d.ts +0 -7
  286. package/src/components/Developers/styles.ts +0 -31
  287. package/src/components/Distribution/utils.ts +0 -32
  288. package/src/components/Distribution/utilts.spec.ts +0 -17
  289. package/src/components/Package/Tag/Tag.test.tsx +0 -15
  290. package/src/components/Package/Tag/Tag.tsx +0 -11
  291. package/src/components/Package/Tag/index.ts +0 -1
  292. package/src/components/Package/Tag/styles.ts +0 -11
  293. package/src/components/Search/AutoComplete/styles.tsx +0 -42
  294. package/src/sections/Header/RegistryInfoDialog/RegistryInfoDialog.tsx +0 -31
  295. package/src/sections/Header/RegistryInfoDialog/index.ts +0 -1
  296. package/src/sections/Header/RegistryInfoDialog/styles.ts +0 -21
  297. package/src/sections/Header/RegistryInfoDialog/types.ts +0 -8
  298. /package/build/components/Icons/DevsIcons/{es6modules.svg → es6module.svg} +0 -0
  299. /package/build/src/{components/Package/Tag/Tag.test.d.ts → AppTest/AppRoute.test.d.ts} +0 -0
  300. /package/src/components/Icons/DevsIcons/{es6modules.svg → es6module.svg} +0 -0
@@ -4,6 +4,7 @@ import { BrowserRouter as Router } from 'react-router-dom';
4
4
  import { api, store } from '../../';
5
5
  import { fireEvent, renderWithStore, screen, waitFor } from '../../test/test-react-testing-library';
6
6
  import Search from './Search';
7
+ import { cleanDescription } from './utils';
7
8
 
8
9
  jest.mock('lodash/debounce', () =>
9
10
  jest.fn((fn) => {
@@ -45,7 +46,7 @@ describe('<Search /> component', () => {
45
46
  });
46
47
 
47
48
  test('handleSearch: when user type package name in search component, show suggestions', async () => {
48
- const { getByPlaceholderText, getAllByText } = renderWithStore(
49
+ const { getByPlaceholderText, findAllByText } = renderWithStore(
49
50
  <ComponentToBeRendered />,
50
51
  store
51
52
  );
@@ -57,14 +58,14 @@ describe('<Search /> component', () => {
57
58
 
58
59
  expect(autoCompleteInput).toHaveAttribute('value', 'verdaccio');
59
60
 
60
- const suggestionsElements = await waitFor(() => getAllByText('verdaccio', { exact: true }));
61
+ const suggestionsElements = await waitFor(() => findAllByText('verdaccio', { exact: true }));
61
62
 
62
63
  expect(suggestionsElements).toHaveLength(1);
63
64
  expect(api.request).toHaveBeenCalledTimes(1);
64
65
  });
65
66
 
66
67
  test('onBlur: should cancel all search requests', async () => {
67
- const { getByPlaceholderText, getAllByText } = renderWithStore(
68
+ const { getByPlaceholderText, findAllByText } = renderWithStore(
68
69
  <ComponentToBeRendered />,
69
70
  store
70
71
  );
@@ -75,7 +76,7 @@ describe('<Search /> component', () => {
75
76
  fireEvent.change(autoCompleteInput, { target: { value: 'verdaccio' } });
76
77
  expect(autoCompleteInput).toHaveAttribute('value', 'verdaccio');
77
78
 
78
- const suggestionsElements = await waitFor(() => getAllByText('verdaccio', { exact: true }));
79
+ const suggestionsElements = await waitFor(() => findAllByText('verdaccio', { exact: true }));
79
80
  expect(suggestionsElements).toHaveLength(1);
80
81
  expect(api.request).toHaveBeenCalledTimes(1);
81
82
 
@@ -110,7 +111,7 @@ describe('<Search /> component', () => {
110
111
  });
111
112
 
112
113
  test('handlePackagesClearRequested: should clear suggestions', async () => {
113
- const { getByPlaceholderText, getAllByText } = renderWithStore(
114
+ const { getByPlaceholderText, findAllByText } = renderWithStore(
114
115
  <ComponentToBeRendered />,
115
116
  store
116
117
  );
@@ -120,18 +121,18 @@ describe('<Search /> component', () => {
120
121
  fireEvent.change(autoCompleteInput, { target: { value: 'verdaccio' } });
121
122
  expect(autoCompleteInput).toHaveAttribute('value', 'verdaccio');
122
123
 
123
- const suggestionsElements = await waitFor(() => getAllByText('verdaccio', { exact: true }));
124
+ const suggestionsElements = await waitFor(() => findAllByText('verdaccio', { exact: true }));
124
125
  expect(suggestionsElements).toHaveLength(1);
125
126
 
126
127
  fireEvent.change(autoCompleteInput, { target: { value: ' ' } });
127
128
  const listBoxElement = screen.queryAllByRole('listbox');
128
- // // when the page redirects, the list box should be empty again
129
+ // when the page redirects, the list box should be empty again
129
130
  expect(listBoxElement).toHaveLength(0);
130
131
  expect(api.request).toHaveBeenCalledTimes(1);
131
132
  });
132
133
 
133
134
  test('handleClickSearch: should change the window location on click or return key', async () => {
134
- const { getByPlaceholderText, getAllByText } = renderWithStore(
135
+ const { getByPlaceholderText, findAllByText } = renderWithStore(
135
136
  <ComponentToBeRendered />,
136
137
  store
137
138
  );
@@ -141,7 +142,7 @@ describe('<Search /> component', () => {
141
142
  fireEvent.change(autoCompleteInput, { target: { value: 'verdaccio' } });
142
143
  expect(autoCompleteInput).toHaveAttribute('value', 'verdaccio');
143
144
 
144
- const suggestionsElements = await waitFor(() => getAllByText('verdaccio', { exact: true }));
145
+ const suggestionsElements = await waitFor(() => findAllByText('verdaccio', { exact: true }));
145
146
  // console.log('suggestionsElements', suggestionsElements);
146
147
  expect(suggestionsElements).toHaveLength(1);
147
148
  // click on the second suggestion
@@ -151,3 +152,29 @@ describe('<Search /> component', () => {
151
152
  expect(listBoxElement).toHaveLength(0);
152
153
  });
153
154
  });
155
+
156
+ describe('cleanDescription', () => {
157
+ test('should return plain text', () => {
158
+ const description = 'Hello, Mars!';
159
+ const output = cleanDescription(description);
160
+ expect(output).toBe(description);
161
+ });
162
+
163
+ test('should remove html tags from description', () => {
164
+ const description = '<h1>verdaccio</h1>';
165
+ const output = cleanDescription(description);
166
+ expect(output).toBe('verdaccio');
167
+ });
168
+
169
+ test('should remove markdown links from description', () => {
170
+ const description = '[verdaccio](https://verdaccio.org)';
171
+ const output = cleanDescription(description);
172
+ expect(output).toBe('verdaccio');
173
+ });
174
+
175
+ test('should remove markdown links', () => {
176
+ const description = '[![NPM version](https://img.shields.io/npm/latest.svg)]';
177
+ const output = cleanDescription(description);
178
+ expect(output).toBe('NPM version');
179
+ });
180
+ });
@@ -9,6 +9,7 @@ import { RouteComponentProps, withRouter } from 'react-router';
9
9
  import { SearchResultWeb } from '@verdaccio/types';
10
10
 
11
11
  import { Dispatch, RootState, useConfig } from '../../';
12
+ import { Route } from '../../utils';
12
13
  import AutoComplete from './AutoComplete';
13
14
  import SearchItem from './SearchItem';
14
15
  import { StyledInputAdornment, StyledTextField } from './styles';
@@ -27,6 +28,7 @@ const Search: React.FC<RouteComponentProps> = ({ history }) => {
27
28
  const { suggestions } = useSelector((state: RootState) => state.search);
28
29
  const isLoading = useSelector((state: RootState) => state?.loading?.models.search);
29
30
  const dispatch = useDispatch<Dispatch>();
31
+
30
32
  /**
31
33
  * Cancel all the requests which are in pending state.
32
34
  */
@@ -60,9 +62,9 @@ const Search: React.FC<RouteComponentProps> = ({ history }) => {
60
62
  if (searchRemote) {
61
63
  // TODO: check this part
62
64
  // @ts-ignore
63
- history.push(`/-/web/detail/${value.package.name}`);
65
+ history.push(`${Route.DETAIL}${value.package.name}`);
64
66
  } else {
65
- history.push(`/-/web/detail/${value.name}`);
67
+ history.push(`${Route.DETAIL}${value.name}`);
66
68
  }
67
69
  break;
68
70
  }
@@ -9,6 +9,8 @@ import Stack from '@mui/material/Stack';
9
9
  import React from 'react';
10
10
  import { useTranslation } from 'react-i18next';
11
11
 
12
+ import { cleanDescription } from './utils';
13
+
12
14
  type SearchItemProps = {
13
15
  name: string;
14
16
  version?: string;
@@ -28,15 +30,23 @@ export const Description = styled('div')<{ theme?: Theme }>(({ theme }) => ({
28
30
  display: 'none',
29
31
  color: theme?.palette?.greyLight2,
30
32
  lineHeight: '1.5rem',
33
+ whiteSpace: 'nowrap',
34
+ textOverflow: 'ellipsis',
35
+ alignItems: 'center',
36
+ overflow: 'hidden',
37
+ paddingLeft: theme.spacing(),
38
+ fontSize: theme?.fontSize.ssm,
39
+ [`@media (min-width: ${theme?.breakPoints.medium}px)`]: {
40
+ display: 'block',
41
+ width: '300px',
42
+ },
31
43
  [`@media (min-width: ${theme?.breakPoints.large}px)`]: {
32
44
  display: 'block',
33
- whiteSpace: 'nowrap',
34
- textOverflow: 'ellipsis',
35
- width: '200px',
36
- alignItems: 'center',
37
- overflow: 'hidden',
38
- paddingLeft: theme.spacing(),
39
- fontSize: theme?.fontSize.ssm,
45
+ width: '500px',
46
+ },
47
+ [`@media (min-width: 1440px)`]: {
48
+ display: 'block',
49
+ width: '600px',
40
50
  },
41
51
  }));
42
52
 
@@ -68,11 +78,12 @@ const SearchItem: React.FC<SearchItemProps> = ({
68
78
  // no action assigned by default
69
79
  };
70
80
  return (
81
+ // eslint-disable-next-line verdaccio/jsx-no-style
71
82
  <li {...props} style={{ flexDirection: 'column' }}>
72
83
  <Wrapper>
73
84
  <NameGroup>
74
85
  <Name>{name}</Name>
75
- {description && <Description>{description}</Description>}
86
+ {description && <Description>{cleanDescription(description)}</Description>}
76
87
  </NameGroup>
77
88
  {version && <Version>{version}</Version>}
78
89
  </Wrapper>
@@ -0,0 +1,17 @@
1
+ function removeHtmlTags(input: string): string {
2
+ let previous;
3
+ do {
4
+ previous = input;
5
+ input = input.replace(/<[^>]*>?/gm, '');
6
+ } while (input !== previous);
7
+ return input;
8
+ }
9
+
10
+ export function cleanDescription(description: string): string {
11
+ let output = description;
12
+ // remove html tags from description (e.g. <h1...>)
13
+ output = removeHtmlTags(output);
14
+ // remove markdown links from description (e.g. [link](url))
15
+ output = output.replace(/\(.*?\)/gm, '').replace(/(\[!?|\])/gm, '');
16
+ return output;
17
+ }
@@ -0,0 +1,41 @@
1
+ import React from 'react';
2
+
3
+ import { fireEvent, render, screen } from '../../test/test-react-testing-library';
4
+ import SettingsMenu from './SettingsMenu';
5
+
6
+ describe('<SettingsMenu />', () => {
7
+ test('should handle menu open and close', async () => {
8
+ render(<SettingsMenu packageName="foo" />);
9
+ const button = screen.getByRole('button');
10
+ fireEvent.click(button);
11
+ await screen.findByRole('menu');
12
+ // TODO onClose
13
+ });
14
+
15
+ test('should handle latest select', () => {
16
+ const { getByRole, getByText } = render(<SettingsMenu packageName="foo" />);
17
+ const button = getByRole('button');
18
+ fireEvent.click(button);
19
+ const menuItem = getByText('sidebar.installation.latest');
20
+ fireEvent.click(menuItem);
21
+ expect(getByText('sidebar.installation.latest')).toBeInTheDocument();
22
+ });
23
+
24
+ test('should handle global select', () => {
25
+ const { getByRole, getByText } = render(<SettingsMenu packageName="foo" />);
26
+ const button = getByRole('button');
27
+ fireEvent.click(button);
28
+ const menuItem = getByText('sidebar.installation.global');
29
+ fireEvent.click(menuItem);
30
+ expect(getByText('sidebar.installation.global')).toBeInTheDocument();
31
+ });
32
+
33
+ test('should handle yarn modern select', () => {
34
+ const { getByRole, getByText } = render(<SettingsMenu packageName="foo" />);
35
+ const button = getByRole('button');
36
+ fireEvent.click(button);
37
+ const menuItem = getByText('sidebar.installation.yarnModern');
38
+ fireEvent.click(menuItem);
39
+ expect(getByText('sidebar.installation.yarnModern')).toBeInTheDocument();
40
+ });
41
+ });
@@ -7,24 +7,42 @@ import MenuItem from '@mui/material/MenuItem';
7
7
  import React from 'react';
8
8
  import { useTranslation } from 'react-i18next';
9
9
 
10
+ import { useConfig } from '../../providers';
10
11
  import { useSettings } from '../../providers/PersistenceSettingProvider';
11
12
 
12
13
  interface Props {
13
14
  packageName: string;
14
15
  }
15
16
 
16
- const InstallListItem: React.FC<Props> = ({ packageName }) => {
17
+ const SettingsMenu: React.FC<Props> = ({ packageName }) => {
17
18
  const { t } = useTranslation();
18
19
  const { localSettings, updateSettings } = useSettings();
20
+ const { configOptions } = useConfig();
19
21
  const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
20
22
  const open = Boolean(anchorEl);
21
23
  const handleOpenMenu = (event: React.MouseEvent<HTMLButtonElement>) => {
22
24
  setAnchorEl(event.currentTarget);
23
25
  };
24
26
 
27
+ const handleLatestSelect = () => {
28
+ updateSettings({
29
+ ...localSettings,
30
+ [packageName]: {
31
+ global: localSettings[packageName]?.global,
32
+ latest: !localSettings[packageName]?.latest,
33
+ },
34
+ });
35
+ setAnchorEl(null);
36
+ };
37
+
25
38
  const handleGlobalSelect = () => {
26
- const statusGlobal = !localSettings[packageName]?.global;
27
- updateSettings({ ...localSettings, [packageName]: { global: statusGlobal } });
39
+ updateSettings({
40
+ ...localSettings,
41
+ [packageName]: {
42
+ global: !localSettings[packageName]?.global,
43
+ latest: localSettings[packageName]?.latest,
44
+ },
45
+ });
28
46
  setAnchorEl(null);
29
47
  };
30
48
 
@@ -38,6 +56,7 @@ const InstallListItem: React.FC<Props> = ({ packageName }) => {
38
56
  setAnchorEl(null);
39
57
  };
40
58
 
59
+ const statusLatest = localSettings[packageName]?.latest;
41
60
  const statusGlobal = localSettings[packageName]?.global;
42
61
  return (
43
62
  <>
@@ -56,31 +75,50 @@ const InstallListItem: React.FC<Props> = ({ packageName }) => {
56
75
  'aria-labelledby': 'basic-button',
57
76
  }}
58
77
  anchorEl={anchorEl}
78
+ anchorOrigin={{
79
+ vertical: 'bottom',
80
+ horizontal: 'right',
81
+ }}
59
82
  id="basic-menu"
60
83
  onClose={handleClose}
61
84
  open={open}
85
+ transformOrigin={{
86
+ vertical: 'top',
87
+ horizontal: 'right',
88
+ }}
62
89
  >
63
- <MenuItem onClick={handleGlobalSelect}>
90
+ <MenuItem onClick={handleLatestSelect}>
64
91
  {' '}
65
- {statusGlobal === true ? (
92
+ {statusLatest === true ? (
66
93
  <ListItemIcon>
67
94
  <Check />
68
95
  </ListItemIcon>
69
96
  ) : null}
70
- {t('sidebar.installation.global')}
97
+ {t('sidebar.installation.latest')}
71
98
  </MenuItem>
72
- <MenuItem onClick={handleGlobalYarnModern}>
99
+ <MenuItem onClick={handleGlobalSelect}>
73
100
  {' '}
74
- {localSettings?.yarnModern ? (
101
+ {statusGlobal === true ? (
75
102
  <ListItemIcon>
76
103
  <Check />
77
104
  </ListItemIcon>
78
105
  ) : null}
79
- {t('sidebar.installation.yarnModern')}
106
+ {t('sidebar.installation.global')}
80
107
  </MenuItem>
108
+ {configOptions?.pkgManagers?.includes('yarn') && (
109
+ <MenuItem onClick={handleGlobalYarnModern}>
110
+ {' '}
111
+ {localSettings?.yarnModern ? (
112
+ <ListItemIcon>
113
+ <Check />
114
+ </ListItemIcon>
115
+ ) : null}
116
+ {t('sidebar.installation.yarnModern')}
117
+ </MenuItem>
118
+ )}
81
119
  </Menu>
82
120
  </>
83
121
  );
84
122
  };
85
123
 
86
- export default InstallListItem;
124
+ export default SettingsMenu;
@@ -20,11 +20,23 @@ interface Props {
20
20
  time: string;
21
21
  }
22
22
 
23
+ const Icon = styled.div<{ theme?: Theme }>(({ theme }) => ({
24
+ marginLeft: theme?.spacing(1),
25
+ }));
26
+
23
27
  const ModuleJS: React.FC<{ module: ModuleType | void }> = ({ module }) => {
24
28
  if (module === 'commonjs') {
25
- return <CommonJS />;
29
+ return (
30
+ <Icon>
31
+ <CommonJS />
32
+ </Icon>
33
+ );
26
34
  } else if (module === 'module') {
27
- return <ES6Modules />;
35
+ return (
36
+ <Icon>
37
+ <ES6Modules />
38
+ </Icon>
39
+ );
28
40
  } else {
29
41
  return null;
30
42
  }
@@ -46,7 +58,11 @@ const DetailSidebarTitle: React.FC<Props> = ({
46
58
  <TitleWrapper>
47
59
  <>
48
60
  {packageName}
49
- {hasTypes && <TypeScript />}
61
+ {hasTypes && (
62
+ <Icon>
63
+ <TypeScript />
64
+ </Icon>
65
+ )}
50
66
  <ModuleJS module={moduleType} />
51
67
  </>
52
68
  </TitleWrapper>
@@ -44,4 +44,11 @@ describe('<UpLinks /> component', () => {
44
44
 
45
45
  expect(wrapper).toMatchSnapshot();
46
46
  });
47
+
48
+ test('should not render if input is missing', () => {
49
+ const wrapper = render(<UpLinks packageMeta={undefined} />);
50
+ // expect nothing to be rendered
51
+ expect(wrapper.queryByTestId('no-uplinks-npm')).toBeNull();
52
+ expect(wrapper.queryByTestId('uplinks')).toBeNull();
53
+ });
47
54
  });
@@ -1,3 +1,6 @@
1
+ import Box from '@mui/material/Box';
2
+ import Card from '@mui/material/Card';
3
+ import CardContent from '@mui/material/CardContent';
1
4
  import List from '@mui/material/List';
2
5
  import ListItem from '@mui/material/ListItem';
3
6
  import React from 'react';
@@ -5,6 +8,7 @@ import { useTranslation } from 'react-i18next';
5
8
 
6
9
  import { utils } from '../../utils';
7
10
  import NoItems from '../NoItems';
11
+ import UpLinkLink from './UplinkLink';
8
12
  import { ListItemText, Spacer, StyledText } from './styles';
9
13
 
10
14
  const UpLinks: React.FC<{ packageMeta: any }> = ({ packageMeta }) => {
@@ -17,24 +21,43 @@ const UpLinks: React.FC<{ packageMeta: any }> = ({ packageMeta }) => {
17
21
  const { _uplinks: uplinks, latest } = packageMeta;
18
22
 
19
23
  if (Object.keys(uplinks).length === 0) {
20
- return <NoItems data-testid="no-uplinks" text={t('uplinks.no-items', { name: latest.name })} />;
24
+ return (
25
+ <Card sx={{ mb: 2 }}>
26
+ <CardContent>
27
+ <NoItems data-testid="no-uplinks" text={t('uplinks.no-items', { name: latest.name })} />
28
+ </CardContent>
29
+ </Card>
30
+ );
21
31
  }
22
32
 
23
33
  return (
24
- <>
25
- <StyledText variant="subtitle1">{t('uplinks.title')}</StyledText>
26
- <List>
27
- {Object.keys(uplinks)
28
- .reverse()
29
- .map((name) => (
30
- <ListItem key={name}>
31
- <ListItemText>{name}</ListItemText>
32
- <Spacer />
33
- <ListItemText>{utils.formatDateDistance(uplinks[name].fetched)}</ListItemText>
34
- </ListItem>
35
- ))}
36
- </List>
37
- </>
34
+ <Card sx={{ mb: 2 }}>
35
+ <CardContent>
36
+ <Box data-testid="uplinks" sx={{ m: 2 }}>
37
+ <StyledText variant="subtitle1">{t('uplinks.title')}</StyledText>
38
+ <List dense={true}>
39
+ {Object.keys(uplinks)
40
+ .reverse()
41
+ .map((name) => (
42
+ <ListItem
43
+ className="version-item"
44
+ data-testid={`uplink-${name}`}
45
+ key={name}
46
+ sx={{ pr: 0 }}
47
+ >
48
+ <ListItemText>
49
+ <UpLinkLink packageName={latest.name} uplinkName={name} />
50
+ </ListItemText>
51
+ <Spacer />
52
+ <ListItemText title={utils.formatDate(uplinks[name].fetched)}>
53
+ {utils.formatDateDistance(uplinks[name].fetched)}
54
+ </ListItemText>
55
+ </ListItem>
56
+ ))}
57
+ </List>
58
+ </Box>
59
+ </CardContent>
60
+ </Card>
38
61
  );
39
62
  };
40
63
 
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+
3
+ import { utils } from '../../utils';
4
+ import LinkExternal from '../LinkExternal';
5
+
6
+ const UpLinkLink: React.FC<{ packageName: string; uplinkName: string }> = ({
7
+ packageName,
8
+ uplinkName,
9
+ }) => {
10
+ const link = utils.getUplink(uplinkName, packageName);
11
+ return link ? (
12
+ <LinkExternal to={link} variant="outline">
13
+ {uplinkName}
14
+ </LinkExternal>
15
+ ) : (
16
+ <>{uplinkName}</>
17
+ );
18
+ };
19
+
20
+ export default UpLinkLink;
@@ -15,6 +15,7 @@ export const Spacer = styled('div')<{ theme?: Theme }>(({ theme }) => ({
15
15
  } `,
16
16
  whiteSpace: 'nowrap',
17
17
  height: '0.5em',
18
+ margin: '0 16px',
18
19
  }));
19
20
 
20
21
  export const ListItemText = styled(MuiListItemText)<{ theme?: Theme }>(({ theme }) => ({
@@ -7,8 +7,8 @@ import { useTranslation } from 'react-i18next';
7
7
 
8
8
  import { useConfig } from '../../providers';
9
9
  import { Time, Versions } from '../../types/packageMeta';
10
- import { utils } from '../../utils';
11
- import { Link } from '../Link';
10
+ import { Route, utils } from '../../utils';
11
+ import Link from '../Link';
12
12
  import { ListItemText, Spacer } from './styles';
13
13
 
14
14
  interface Props {
@@ -40,8 +40,13 @@ const VersionsHistoryList: React.FC<Props> = ({ versions, packageName, time }) =
40
40
  {Object.keys(listVersions)
41
41
  .reverse()
42
42
  .map((version) => (
43
- <ListItem className="version-item" data-testid={`version-${version}`} key={version}>
44
- <Link to={`/-/web/detail/${packageName}/v/${version}`} variant="caption">
43
+ <ListItem
44
+ className="version-item"
45
+ data-testid={`version-${version}`}
46
+ key={version}
47
+ sx={{ pr: 0 }}
48
+ >
49
+ <Link to={`${Route.DETAIL}${packageName}/v/${version}`} variant="outline">
45
50
  <ListItemText disableTypography={false} primary={version}></ListItemText>
46
51
  </Link>
47
52
  {typeof versions[version]?.deprecated === 'string' ? (
@@ -3,7 +3,8 @@ import ListItem from '@mui/material/ListItem';
3
3
  import React from 'react';
4
4
 
5
5
  import { DistTags, Time } from '../../types/packageMeta';
6
- import { Link } from '../Link';
6
+ import { Route } from '../../utils';
7
+ import Link from '../Link';
7
8
  import { ListItemText, Spacer } from './styles';
8
9
 
9
10
  interface Props {
@@ -19,8 +20,8 @@ const VersionsTagList: React.FC<Props> = ({ tags, packageName, time }) => (
19
20
  return time[tags[a]] < time[tags[b]] ? 1 : time[tags[a]] > time[tags[b]] ? -1 : 0;
20
21
  })
21
22
  .map((tag) => (
22
- <ListItem className="version-item" data-testid={`tag-${tag}`} key={tag}>
23
- <Link to={`/-/web/detail/${packageName}/v/${tags[tag]}`} variant="outline">
23
+ <ListItem className="version-item" data-testid={`tag-${tag}`} key={tag} sx={{ pr: 0 }}>
24
+ <Link to={`${Route.DETAIL}${packageName}/v/${tags[tag]}`} variant="outline">
24
25
  <ListItemText>{tag}</ListItemText>
25
26
  </Link>
26
27
  <Spacer />
@@ -45,6 +45,8 @@ describe('<Version /> component', () => {
45
45
  expect(screen.queryAllByTestId('version-list-text')).toHaveLength(65);
46
46
  fireEvent.change(screen.getByRole('textbox'), { target: { value: '2.3.0' } });
47
47
  expect(screen.queryAllByTestId('version-list-text')).toHaveLength(1);
48
+ fireEvent.change(screen.getByRole('textbox'), { target: { value: '' } });
49
+ expect(screen.queryAllByTestId('version-list-text')).toHaveLength(65);
48
50
  });
49
51
 
50
52
  test('should not render versions', () => {