Skip to content
This repository was archived by the owner on Jan 16, 2022. It is now read-only.

Commit f5c77ff

Browse files
priscilawebdevjuanpicado
authored andcommitted
fix: version Page - Replaces class by func. (#171)
* refactor: updated version page * refactor: rollback context * fix: added version provider
1 parent d69fc1b commit f5c77ff

File tree

12 files changed

+6576
-216
lines changed

12 files changed

+6576
-216
lines changed

src/pages/Version/Version.test.tsx

Lines changed: 32 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,59 @@
11
import React from 'react';
2-
import { render, cleanup } from '@testing-library/react';
32
import { MemoryRouter } from 'react-router';
3+
import { render } from '@testing-library/react';
44
import { waitForElement } from '@testing-library/dom';
55

6-
import vueMetadata from '../../../test/fixtures/metadata/vue.json';
7-
import ErrorBoundary from '../../App/AppError';
6+
import { NOT_FOUND_TEXT } from '../../components/NotFound';
87

98
import Version from './Version';
9+
import { DetailContext } from './context';
10+
import data from './__partials__/data.json';
1011

1112
// :-) we mock this otherways fails on render, some weird issue on material-ui
1213
jest.mock('../../muiComponents/Avatar');
1314

14-
// eslint-disable-next-line react/display-name
15-
jest.mock('../../components/NotFound', () => () => <div>{'Not found'}</div>);
15+
const detailContextValue = {
16+
packageName: 'foo',
17+
packageMeta: data,
18+
readMe: 'Read me!',
19+
enableLoading: jest.fn(),
20+
isLoading: false,
21+
hasNotBeenFound: false,
22+
version: '1.0.0',
23+
};
1624

1725
describe('test Version page', () => {
18-
jest.setTimeout(40000000);
19-
beforeAll(() => {
20-
// FIXME: a better way to mock this
21-
// @ts-ignore
22-
global.window.VERDACCIO_API_URL = 'http://test';
23-
});
24-
25-
afterEach(() => {
26-
cleanup();
27-
});
28-
29-
beforeEach(() => {
30-
jest.resetAllMocks();
31-
// @ts-ignore
32-
fetch.resetMocks();
33-
});
34-
26+
/* eslint-disable react/jsx-max-depth */
3527
test('should render the version page', async () => {
36-
const readmeText = 'test';
37-
// @ts-ignore
38-
fetch.mockResponses(
39-
[[JSON.stringify(vueMetadata)], { status: 200, headers: { 'content-type': 'application/json' } }],
40-
[[`<p align="center">${readmeText}</p>`], { status: 200, headers: { 'content-type': 'text/html' } }]
41-
);
42-
4328
const { getByTestId, getByText } = render(
44-
<ErrorBoundary>
45-
<MemoryRouter>
46-
<Version match={{ params: { ['package']: 'vue' } }}></Version>
47-
</MemoryRouter>
48-
</ErrorBoundary>
29+
<MemoryRouter>
30+
<DetailContext.Provider value={detailContextValue}>
31+
<Version />
32+
</DetailContext.Provider>
33+
</MemoryRouter>
4934
);
50-
51-
// first it display loading
52-
const hasLoading = getByTestId('loading');
53-
expect(hasLoading).toBeTruthy();
54-
5535
// we wait fetch response (mocked above)
5636
await waitForElement(() => getByTestId('version-layout'));
57-
5837
// check whether readme was loaded
59-
const hasReadme = getByText(readmeText);
60-
38+
const hasReadme = getByText(detailContextValue.readMe);
6139
expect(hasReadme).toBeTruthy();
6240
});
6341

6442
test('should render 404 page if the resources are not found', async () => {
65-
// @ts-ignore
66-
fetch.mockResponses(
67-
[[JSON.stringify({})], { status: 404, headers: { 'content-type': 'application/json' } }],
68-
[[``], { status: 404, headers: { 'content-type': 'text/html' } }]
43+
const { getByText } = render(
44+
<MemoryRouter>
45+
<DetailContext.Provider
46+
value={{
47+
...detailContextValue,
48+
hasNotBeenFound: true,
49+
}}>
50+
<Version />
51+
</DetailContext.Provider>
52+
</MemoryRouter>
6953
);
70-
71-
const { getByTestId, getByText } = render(
72-
<ErrorBoundary>
73-
<MemoryRouter>
74-
<Version match={{ params: { ['package']: 'vue' } }}></Version>
75-
</MemoryRouter>
76-
</ErrorBoundary>
77-
);
78-
79-
// first it display loading
80-
const hasLoading = getByTestId('loading');
81-
expect(hasLoading).toBeTruthy();
82-
8354
// we wait fetch response (mocked above)
84-
await waitForElement(() => getByText('Not found'));
85-
86-
// check whether readme was loaded
87-
const hasReadme = getByText('Not found');
88-
89-
expect(hasReadme).toBeTruthy();
55+
const notFoundElement = await waitForElement(() => getByText(NOT_FOUND_TEXT));
56+
expect(notFoundElement).toBeTruthy();
9057
});
9158

9259
// Wanna contribute? Here we some scenarios we need to test

src/pages/Version/Version.tsx

Lines changed: 12 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,24 @@
1-
import React, { useEffect, useState } from 'react';
1+
import React, { useContext } from 'react';
22

3-
import { callDetailPage, callReadme } from '../../utils/calls';
4-
import { buildScopePackage } from '../../utils/package';
53
import Loading from '../../components/Loading/Loading';
64
import NotFound from '../../components/NotFound';
75

8-
import { Layout } from './Layout';
9-
import { DetailContextProvider } from './context';
10-
import { StateInterface } from './types';
6+
import VersionLayout from './VersionLayout';
7+
import { DetailContext } from './context';
118

12-
export function getRouterPackageName(params): string {
13-
const packageName = params.package;
14-
const { scope } = params;
15-
if (scope) {
16-
return buildScopePackage(scope, packageName);
17-
}
18-
19-
return packageName;
20-
}
21-
22-
function fillTitle(text: string): string {
23-
return `Verdaccio - ${text}`;
24-
}
9+
const Version: React.FC = () => {
10+
const detailContext = useContext(DetailContext);
11+
const { isLoading, hasNotBeenFound } = detailContext;
2512

26-
function isVersionValid(packageMeta, packageVersion): boolean {
27-
const hasVersion = typeof packageVersion !== 'undefined';
28-
if (!hasVersion) {
29-
// if is undefined, that means versions does not exist, we continue
30-
return true;
13+
if (isLoading) {
14+
return <Loading />;
3115
}
3216

33-
const hasMatchVersion = Object.keys(packageMeta.versions).includes(packageVersion);
34-
return hasMatchVersion;
35-
}
36-
37-
const Version = ({ match: { params } }) => {
38-
const pkgName = getRouterPackageName(params);
39-
const [readMe, setReadme] = useState();
40-
const [packageName, setPackageName] = useState(pkgName);
41-
// eslint-disable-next-line no-unused-vars
42-
const [packageVersion, setPackageVersion] = useState(params.version);
43-
const [packageMeta, setPackageMeta] = useState();
44-
const [isLoading, setIsLoading] = useState(true);
45-
const [notFound, setNotFound] = useState(false);
46-
47-
useEffect(() => {
48-
(async () => {
49-
try {
50-
const packageMeta = (await callDetailPage(packageName, packageVersion)) as Partial<StateInterface>;
51-
const readMe = (await callReadme(packageName, packageVersion)) as Partial<StateInterface>;
52-
if (isVersionValid(packageMeta, packageVersion)) {
53-
setReadme(readMe);
54-
setPackageMeta(packageMeta);
55-
setIsLoading(false);
56-
} else {
57-
setIsLoading(false);
58-
setNotFound(true);
59-
}
60-
} catch (error) {
61-
setNotFound(true);
62-
setIsLoading(false);
63-
}
64-
})();
65-
}, [packageName, packageVersion]);
66-
67-
useEffect(() => {
68-
if (!packageVersion) {
69-
document.title = fillTitle(packageName);
70-
} else {
71-
document.title = fillTitle(`${packageName}@${packageVersion}`);
72-
}
73-
}, [packageName, packageVersion]);
74-
75-
useEffect(() => {
76-
const pkgName = getRouterPackageName(params);
77-
78-
setPackageName(pkgName);
79-
setPackageVersion(params.version);
80-
}, [params, setPackageName, setPackageVersion]);
81-
82-
const isNotFound = notFound || typeof packageMeta === 'undefined' || typeof packageName === 'undefined' || typeof readMe === 'undefined';
83-
const renderContent = (): React.ReactElement<HTMLElement> => {
84-
if (isLoading) {
85-
return <Loading />;
86-
} else if (isNotFound) {
87-
return <NotFound />;
88-
} else {
89-
return <Layout />;
90-
}
91-
};
17+
if (hasNotBeenFound) {
18+
return <NotFound />;
19+
}
9220

93-
return (
94-
<DetailContextProvider value={{ packageMeta, packageVersion, readMe, packageName, enableLoading: setIsLoading }}>{renderContent()}</DetailContextProvider>
95-
);
21+
return <VersionLayout />;
9622
};
9723

9824
export default Version;
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import React, { useEffect, useState } from 'react';
2+
import { useParams } from 'react-router-dom';
3+
4+
import { callDetailPage, callReadme } from '../../utils/calls';
5+
6+
import getRouterPackageName from './get-route-package-name';
7+
import { DetailContext } from './context';
8+
import isPackageVersionValid from './is-package-version-valid';
9+
10+
interface Params {
11+
scope?: string;
12+
package: string;
13+
version?: string;
14+
}
15+
16+
const VersionContextProvider: React.FC = ({ children }) => {
17+
const { version, package: pkgName, scope } = useParams<Params>();
18+
const [packageName, setPackageName] = useState(getRouterPackageName(pkgName, scope));
19+
const [packageVersion, setPackageVersion] = useState(version);
20+
const [packageMeta, setPackageMeta] = useState();
21+
const [readMe, setReadme] = useState();
22+
const [isLoading, setIsLoading] = useState(true);
23+
const [hasNotBeenFound, setHasNotBeenFound] = useState();
24+
25+
useEffect(() => {
26+
const updatedPackageName = getRouterPackageName(pkgName, scope);
27+
setPackageName(updatedPackageName);
28+
}, [pkgName, scope]);
29+
30+
useEffect(() => {
31+
setPackageVersion(version);
32+
}, [version]);
33+
34+
useEffect(() => {
35+
(async () => {
36+
try {
37+
const packageMeta = await callDetailPage(packageName, packageVersion);
38+
const readMe = await callReadme(packageName, packageVersion);
39+
if (isPackageVersionValid(packageMeta, packageVersion)) {
40+
setReadme(readMe);
41+
setPackageMeta(packageMeta);
42+
setIsLoading(false);
43+
} else {
44+
setIsLoading(false);
45+
setHasNotBeenFound(true);
46+
}
47+
} catch (error) {
48+
setHasNotBeenFound(true);
49+
setIsLoading(false);
50+
}
51+
})();
52+
}, [packageName, packageVersion]);
53+
54+
return (
55+
<DetailContext.Provider
56+
value={{
57+
packageMeta,
58+
packageVersion,
59+
readMe,
60+
packageName,
61+
isLoading,
62+
hasNotBeenFound,
63+
}}>
64+
{children}
65+
</DetailContext.Provider>
66+
);
67+
};
68+
69+
export default VersionContextProvider;
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,20 @@
1-
import React, { FC, ReactElement } from 'react';
1+
import React from 'react';
22
import Grid from '@material-ui/core/Grid';
33

44
import DetailContainer from '../../components/DetailContainer';
55
import DetailSidebar from '../../components/DetailSidebar';
66

7-
function renderDetail(): ReactElement<HTMLElement> {
8-
return <DetailContainer />;
9-
}
10-
11-
function renderSidebar(): ReactElement<HTMLElement> {
12-
return <DetailSidebar />;
13-
}
14-
15-
const Layout: FC<{}> = () => {
7+
const VersionLayout: React.FC = () => {
168
return (
179
<Grid className={'container content'} container={true} data-testid="version-layout" spacing={0}>
1810
<Grid item={true} md={8} xs={12}>
19-
{renderDetail()}
11+
<DetailContainer />
2012
</Grid>
2113
<Grid item={true} md={4} xs={12}>
22-
{renderSidebar()}
14+
<DetailSidebar />
2315
</Grid>
2416
</Grid>
2517
);
2618
};
2719

28-
export { Layout };
20+
export default VersionLayout;

0 commit comments

Comments
 (0)