diff --git a/package.json b/package.json index 8bcb49a..1ae959d 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@material-ui/core": "3.9.3", "@material-ui/icons": "3.0.2", "@octokit/rest": "16.28.7", + "@testing-library/react": "9.1.0", "@types/enzyme": "3.10.3", "@types/lodash": "4.14.136", "@types/material-ui": "0.21.6", diff --git a/partials/storage/jquery/package.json b/partials/storage/jquery/package.json index 1f76451..e01aea4 100644 --- a/partials/storage/jquery/package.json +++ b/partials/storage/jquery/package.json @@ -4579,6 +4579,70 @@ "tarball": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz" }, "maintainers": [ + { + "name": "dmethvin", + "email": "dave.methvin@gmail.com" + }, + { + "name": "mgol", + "email": "m.goleb@gmail.com" + }, + { + "name": "scott.gonzalez", + "email": "scott.gonzalez@gmail.com" + }, + { + "name": "timmywil", + "email": "4timmywil@gmail.com" + }, + { + "name": "dmethvin", + "email": "dave.methvin@gmail.com" + }, + { + "name": "mgol", + "email": "m.goleb@gmail.com" + }, + { + "name": "scott.gonzalez", + "email": "scott.gonzalez@gmail.com" + }, + { + "name": "timmywil", + "email": "4timmywil@gmail.com" + }, + { + "name": "dmethvin", + "email": "dave.methvin@gmail.com" + }, + { + "name": "mgol", + "email": "m.goleb@gmail.com" + }, + { + "name": "scott.gonzalez", + "email": "scott.gonzalez@gmail.com" + }, + { + "name": "timmywil", + "email": "4timmywil@gmail.com" + }, + { + "name": "dmethvin", + "email": "dave.methvin@gmail.com" + }, + { + "name": "mgol", + "email": "m.goleb@gmail.com" + }, + { + "name": "scott.gonzalez", + "email": "scott.gonzalez@gmail.com" + }, + { + "name": "timmywil", + "email": "4timmywil@gmail.com" + }, { "name": "dmethvin", "email": "dave.methvin@gmail.com" @@ -4916,4 +4980,4 @@ }, "_rev": "60-fed4915c27b9c1e6", "readme": "# jQuery\n\n> jQuery is a fast, small, and feature-rich JavaScript library.\n\nFor information on how to get started and how to use jQuery, please see [jQuery's documentation](http://api.jquery.com/).\nFor source files and issues, please visit the [jQuery repo](https://github.com/jquery/jquery).\n\nIf upgrading, please see the [blog post for 3.3.1](https://blog.jquery.com/2017/03/20/jquery-3.3.1-now-available/). This includes notable differences from the previous version and a more readable changelog.\n\n## Including jQuery\n\nBelow are some of the most common ways to include jQuery.\n\n### Browser\n\n#### Script tag\n\n```html\n\n```\n\n#### Babel\n\n[Babel](http://babeljs.io/) is a next generation JavaScript compiler. One of the features is the ability to use ES6/ES2015 modules now, even though browsers do not yet support this feature natively.\n\n```js\nimport $ from \"jquery\";\n```\n\n#### Browserify/Webpack\n\nThere are several ways to use [Browserify](http://browserify.org/) and [Webpack](https://webpack.github.io/). For more information on using these tools, please refer to the corresponding project's documention. In the script, including jQuery will usually look like this...\n\n```js\nvar $ = require(\"jquery\");\n```\n\n#### AMD (Asynchronous Module Definition)\n\nAMD is a module format built for the browser. For more information, we recommend [require.js' documentation](http://requirejs.org/docs/whyamd.html).\n\n```js\ndefine([\"jquery\"], function($) {\n\n});\n```\n\n### Node\n\nTo include jQuery in [Node](nodejs.org), first install with npm.\n\n```sh\nnpm install jquery\n```\n\nFor jQuery to work in Node, a window with a document is required. Since no such window exists natively in Node, one can be mocked by tools such as [jsdom](https://github.com/tmpvar/jsdom). This can be useful for testing purposes.\n\n```js\nrequire(\"jsdom\").env(\"\", function(err, window) {\n\tif (err) {\n\t\tconsole.error(err);\n\t\treturn;\n\t}\n\n\tvar $ = require(\"jquery\")(window);\n});\n```" -} \ No newline at end of file +} diff --git a/src/components/AvatarTooltip/AvatarTooltip.tsx b/src/components/AvatarTooltip/AvatarTooltip.tsx new file mode 100644 index 0000000..e2244b7 --- /dev/null +++ b/src/components/AvatarTooltip/AvatarTooltip.tsx @@ -0,0 +1,32 @@ +import React, { FC } from 'react'; + +import Avatar from '@material-ui/core/Avatar'; +import Tooltip from '@material-ui/core/Tooltip'; +import { isEmail } from '../../utils/url'; + +export interface AvatarDeveloper { + name: string; + packageName: string; + version: string; + avatar: string; + email: string; +} + +const AvatarTooltip: FC = ({ name, packageName, version, avatar, email }) => { + const avatarComponent = ; + function renderLinkForMail(email, avatarComponent, packageName, version): JSX.Element { + if (!email || isEmail(email) === false) { + return avatarComponent; + } + + return ( + + {avatarComponent} + + ); + } + + return {renderLinkForMail(email, avatarComponent, packageName, version)}; +}; + +export { AvatarTooltip }; diff --git a/src/components/AvatarTooltip/index.ts b/src/components/AvatarTooltip/index.ts new file mode 100644 index 0000000..746d62c --- /dev/null +++ b/src/components/AvatarTooltip/index.ts @@ -0,0 +1,4 @@ +import { AvatarTooltip } from './AvatarTooltip'; + +export { AvatarTooltip }; +export default AvatarTooltip; diff --git a/src/components/Developers/Developers.test.tsx b/src/components/Developers/Developers.test.tsx new file mode 100644 index 0000000..bda8373 --- /dev/null +++ b/src/components/Developers/Developers.test.tsx @@ -0,0 +1,103 @@ +import React from 'react'; +import { mount } from 'enzyme'; +import Developers, { DevelopersType } from './Developers'; +import { Fab } from './styles'; +import { DetailContextProvider } from '../../pages/version/Version'; + +describe('test Developers', () => { + const packageMeta = { + latest: { + packageName: 'foo', + version: '1.0.0', + maintainers: [ + { + name: 'dmethvin', + email: 'dave.methvin@gmail.com', + }, + { + name: 'mgol', + email: 'm.goleb@gmail.com', + }, + ], + contributors: [ + { + name: 'dmethvin', + email: 'dave.methvin@gmail.com', + }, + { + name: 'mgol', + email: 'm.goleb@gmail.com', + }, + ], + }, + }; + + test('should render the component with no items', () => { + const type: DevelopersType = 'maintainers'; + const packageMeta = { + latest: {}, + }; + const wrapper = mount( + // @ts-ignore + + + + ); + + expect(wrapper).toMatchSnapshot(); + }); + + test('should render the component for maintainers with items', () => { + const type: DevelopersType = 'maintainers'; + const wrapper = mount( + // @ts-ignore + + + + ); + + expect(wrapper).toMatchSnapshot(); + }); + + test('should render the component for contributors with items', () => { + const type: DevelopersType = 'contributors'; + const wrapper = mount( + // @ts-ignore + + + + ); + + expect(wrapper).toMatchSnapshot(); + }); + + test('should test onClick the component avatar', () => { + const type: DevelopersType = 'contributors'; + const packageMeta = { + latest: { + packageName: 'foo', + version: '1.0.0', + contributors: [ + { + name: 'dmethvin', + email: 'dave.methvin@gmail.com', + }, + { + name: 'dmethvin2', + email: 'dave2.methvin@gmail.com', + }, + ], + }, + }; + + const wrapper = mount( + // @ts-ignore + + + + ); + + const item2 = wrapper.find(Fab); + item2.simulate('click'); + }); +}); diff --git a/src/components/Developers/Developers.tsx b/src/components/Developers/Developers.tsx index 68d87ca..52f5204 100644 --- a/src/components/Developers/Developers.tsx +++ b/src/components/Developers/Developers.tsx @@ -1,79 +1,59 @@ -import React, { Component } from 'react'; - -import Avatar from '@material-ui/core/Avatar'; +import React, { FC, Fragment } from 'react'; import Add from '@material-ui/icons/Add'; -import Tooltip from '@material-ui/core/Tooltip'; -import { DetailContextConsumer } from '../../pages/version/Version'; +import { DetailContext } from '../../pages/version/Version'; +import { AvatarTooltip } from '../AvatarTooltip'; import { Details, Heading, Content, Fab } from './styles'; -import { isEmail } from '../../utils/url'; + +export type DevelopersType = 'contributors' | 'maintainers'; interface Props { - type: 'contributors' | 'maintainers'; -} -interface State { - visibleDevs: number; + type: DevelopersType; + visibleMax?: number; } -class Developers extends Component { - public state = { - visibleDevs: 6, +export const VISIBLE_MAX = 6; + +const Developers: FC = ({ type, visibleMax }) => { + const [visibleDevs, setVisibleDevs] = React.useState(visibleMax || VISIBLE_MAX); + const { packageMeta } = React.useContext(DetailContext); + + const handleLoadMore = () => { + setVisibleDevs(visibleDevs + VISIBLE_MAX); }; - public render(): JSX.Element { - return ( - - {({ packageMeta }) => { - const { type } = this.props; - const developerType = packageMeta && packageMeta.latest[type]; - if (!developerType || developerType.length === 0) return null; - return this.renderDevelopers(developerType, packageMeta); - }} - - ); - } + const renderDeveloperDetails = ({ name, avatar, email }, packageMeta) => { + const { name: packageName, version } = packageMeta.latest; - public handleLoadMore = () => { - this.setState(prev => ({ visibleDevs: prev.visibleDevs + 6 })); + return ; }; - private renderDevelopers = (developers, packageMeta) => { - const { type } = this.props; - const { visibleDevs } = this.state; + const renderDevelopers = (developers, packageMeta) => { + const listVisibleDevelopers = developers.slice(0, visibleDevs); + return ( - <> + {type} - {developers.slice(0, visibleDevs).map(developer => ( - {this.renderDeveloperDetails(developer, packageMeta)} + {listVisibleDevelopers.map(developer => ( + {renderDeveloperDetails(developer, packageMeta)} ))} {visibleDevs < developers.length && ( - + )} - > + ); }; - private renderLinkForMail(email, avatarComponent, packageName, version): JSX.Element { - if (!email || isEmail(email) === false) { - return avatarComponent; - } - return ( - - {avatarComponent} - - ); + const developerList = packageMeta && packageMeta.latest[type]; + if (!developerList || developerList.length === 0) { + return null; } - private renderDeveloperDetails = ({ name, avatar, email }, packageMeta) => { - const { name: packageName, version } = packageMeta.latest; - - const avatarComponent = ; - return {this.renderLinkForMail(email, avatarComponent, packageName, version)}; - }; -} + return renderDevelopers(developerList, packageMeta); +}; export default Developers; diff --git a/src/components/Developers/__snapshots__/Developers.test.tsx.snap b/src/components/Developers/__snapshots__/Developers.test.tsx.snap new file mode 100644 index 0000000..14aa3af --- /dev/null +++ b/src/components/Developers/__snapshots__/Developers.test.tsx.snap @@ -0,0 +1,5467 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test Developers should render the component for contributors 1`] = ` + + + + + + contributors + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`test Developers should render the component for contributors with items 1`] = ` + + + + + + contributors + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`test Developers should render the component for maintainers 1`] = ` + + + + + + maintainers + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`test Developers should render the component for maintainers with items 1`] = ` + + + + + + maintainers + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`test Developers should render the component with no items 1`] = ` + +`; diff --git a/src/components/Developers/styles.ts b/src/components/Developers/styles.ts index aa2fc23..10eaaff 100644 --- a/src/components/Developers/styles.ts +++ b/src/components/Developers/styles.ts @@ -1,6 +1,7 @@ import styled from 'react-emotion'; import Typography from '@material-ui/core/Typography'; import { default as MuiFab } from '@material-ui/core/Fab'; + import colors from '../../utils/styles/colors'; import { fontWeight } from '../../utils/styles/sizes'; diff --git a/src/components/Footer/__snapshots__/Footer.test.tsx.snap b/src/components/Footer/__snapshots__/Footer.test.tsx.snap index 7320406..aa1ccfc 100644 --- a/src/components/Footer/__snapshots__/Footer.test.tsx.snap +++ b/src/components/Footer/__snapshots__/Footer.test.tsx.snap @@ -1,3 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` component should load the initial state of Footer component 1`] = `" Made with♥onEarthSpainNicaraguaIndiaBrazilChinaAustriaPowered by/ v.1.0.0"`; +exports[` component should load the initial state of Footer component 1`] = `" Made with♥onEarthSpainNicaraguaIndiaBrazilChinaAustriaPowered by/ v.1.0.0"`; diff --git a/src/components/Icon/__snapshots__/Icon.test.tsx.snap b/src/components/Icon/__snapshots__/Icon.test.tsx.snap index f145c7c..3790a33 100644 --- a/src/components/Icon/__snapshots__/Icon.test.tsx.snap +++ b/src/components/Icon/__snapshots__/Icon.test.tsx.snap @@ -1,3 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` component should render the component in default state 1`] = `"Austria"`; +exports[` component should render the component in default state 1`] = `"Austria"`; diff --git a/src/components/Icon/styles.ts b/src/components/Icon/styles.ts index 1dba1b1..e81eace 100644 --- a/src/components/Icon/styles.ts +++ b/src/components/Icon/styles.ts @@ -21,7 +21,7 @@ const getSize = (size: Breakpoint): string => { const commonStyle = ({ size = 'sm' as Breakpoint, pointer, modifiers = null }): string => css` && { display: inline-block; - cursor: ${pointer ? 'pointer' : 'default'}; + cursor: ${pointer ? 'pointer' : 'Developers'}; ${getSize(size)}; ${modifiers && modifiers}; } diff --git a/yarn.lock b/yarn.lock index d943203..56ae08b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1009,7 +1009,7 @@ pirates "^4.0.0" source-map-support "^0.5.9" -"@babel/runtime@7.5.5", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.5": +"@babel/runtime@7.5.5", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5": version "7.5.5" resolved "https://registry.verdaccio.org/@babel%2fruntime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132" integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ== @@ -1628,6 +1628,30 @@ universal-user-agent "^3.0.0" url-template "^2.0.8" +"@sheerun/mutationobserver-shim@^0.3.2": + version "0.3.2" + resolved "https://registry.verdaccio.org/@sheerun%2fmutationobserver-shim/-/mutationobserver-shim-0.3.2.tgz#8013f2af54a2b7d735f71560ff360d3a8176a87b" + integrity sha512-vTCdPp/T/Q3oSqwHmZ5Kpa9oI7iLtGl3RQaA/NyLHikvcrPxACkkKVr/XzkSPJWXHRhKGzVvb0urJsbMlRxi1Q== + +"@testing-library/dom@^6.0.0": + version "6.0.0" + resolved "https://registry.verdaccio.org/@testing-library%2fdom/-/dom-6.0.0.tgz#34e28e69e49bd6347fc64a5dde4c4f9aabbd17d3" + integrity sha512-B5XTz3uMsbqbdR9CZlnwpZjTE3fCWuqRkz/zvDc2Ej/vuHmTM0Ur2v0XPwr7usWfGIBsahEK5HL1E91+4IFiBg== + dependencies: + "@babel/runtime" "^7.5.5" + "@sheerun/mutationobserver-shim" "^0.3.2" + aria-query "3.0.0" + pretty-format "^24.8.0" + wait-for-expect "^1.3.0" + +"@testing-library/react@9.1.0": + version "9.1.0" + resolved "https://registry.verdaccio.org/@testing-library%2freact/-/react-9.1.0.tgz#c00c4ff90c5f9015365f63b7759a57c428b6ab56" + integrity sha512-XMtU8AmGX472c7+qXaaVZ2QpDKPA56vRaVEjlFBPDL8im2erM6DF0KJlwzLcc2wrvfYkcMDbreFyL0vdalubrQ== + dependencies: + "@babel/runtime" "^7.5.5" + "@testing-library/dom" "^6.0.0" + "@types/babel__core@^7.1.0": version "7.1.0" resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.0.tgz#710f2487dda4dcfd010ca6abb2b4dc7394365c51" @@ -2467,7 +2491,7 @@ argv@^0.0.2: resolved "https://registry.npmjs.org/argv/-/argv-0.0.2.tgz#ecbd16f8949b157183711b1bda334f37840185ab" integrity sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas= -aria-query@^3.0.0: +aria-query@3.0.0, aria-query@^3.0.0: version "3.0.0" resolved "https://registry.verdaccio.org/aria-query/-/aria-query-3.0.0.tgz#65b3fcc1ca1155a8c9ae64d6eee297f15d5133cc" integrity sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w= @@ -13943,6 +13967,11 @@ w3c-xmlserializer@^1.1.2: webidl-conversions "^4.0.2" xml-name-validator "^3.0.0" +wait-for-expect@^1.3.0: + version "1.3.0" + resolved "https://registry.verdaccio.org/wait-for-expect/-/wait-for-expect-1.3.0.tgz#65241ce355425f907f5d127bdb5e72c412ff830c" + integrity sha512-8fJU7jiA96HfGPt+P/UilelSAZfhMBJ52YhKzlmZQvKEZU2EcD1GQ0yqGB6liLdHjYtYAoGVigYwdxr5rktvzA== + walker@^1.0.7, walker@~1.0.5: version "1.0.7" resolved "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"