Skip to content

Commit 4b03c97

Browse files
committed
PreviewNav: update to named export, add custom.d.ts for svg definition, and add props interface
1 parent a77d064 commit 4b03c97

File tree

4 files changed

+86
-21
lines changed

4 files changed

+86
-21
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import React from 'react';
2+
import { render, screen } from '../test-utils';
3+
import { PreviewNav } from './PreviewNav';
4+
5+
describe('PreviewNav', () => {
6+
const owner = { username: 'alice' };
7+
const project = { id: '123', name: 'My Project' };
8+
9+
test('renders with correct links and icons using provided data-testid attributes', () => {
10+
render(<PreviewNav owner={owner} project={project} />);
11+
12+
// Logo link to /alice/sketches
13+
const iconLinkUserSketches = screen.getByTestId('icon-link_user-sketches');
14+
expect(iconLinkUserSketches).toHaveAttribute(
15+
'href',
16+
`/${owner.username}/sketches`
17+
);
18+
19+
// p5js logo icon presence
20+
const iconP5Logo = screen.getByTestId('icon_p5-logo');
21+
expect(iconP5Logo).toBeInTheDocument();
22+
23+
// Current project link to /alice/sketches/123
24+
const linkCurrentProject = screen.getByTestId('link_current-project');
25+
expect(linkCurrentProject).toHaveAttribute(
26+
'href',
27+
`/${owner.username}/sketches/${project.id}`
28+
);
29+
expect(linkCurrentProject).toHaveTextContent(project.name);
30+
31+
// Owner username link to /alice/sketches
32+
const linkUserSketches = screen.getByTestId('link_user-sketches');
33+
expect(linkUserSketches).toHaveAttribute(
34+
'href',
35+
`/${owner.username}/sketches`
36+
);
37+
expect(linkUserSketches).toHaveTextContent(owner.username);
38+
39+
// Edit project code link to /alice/sketches/123
40+
const linkProjectCode = screen.getByTestId('link_project-code');
41+
expect(linkProjectCode).toHaveAttribute(
42+
'href',
43+
`/${owner.username}/sketches/${project.id}`
44+
);
45+
46+
// Code icon presence
47+
const iconCode = screen.getByTestId('icon_code');
48+
expect(iconCode).toBeInTheDocument();
49+
50+
// Check nav container presence
51+
const nav = screen.getByTestId('preview-nav');
52+
expect(nav).toBeInTheDocument();
53+
});
54+
});

client/components/PreviewNav.tsx

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,64 @@
1-
import PropTypes from 'prop-types';
21
import React from 'react';
32
import { Link } from 'react-router-dom';
43
import { useTranslation } from 'react-i18next';
54

65
import LogoIcon from '../images/p5js-logo-small.svg';
76
import CodeIcon from '../images/code.svg';
87

9-
const PreviewNav = ({ owner, project }) => {
8+
interface PreviewNavProps {
9+
owner: { username: string };
10+
project: { name: string; id: string };
11+
}
12+
13+
export const PreviewNav = ({ owner, project }: PreviewNavProps) => {
1014
const { t } = useTranslation();
1115
return (
12-
<nav className="nav preview-nav">
13-
<div className="nav__items-left">
14-
<div className="nav__item-logo">
15-
<Link to={`/${owner.username}/sketches`}>
16+
<nav className="nav preview-nav" data-testid="preview-nav">
17+
<div className="nav__items-left" data-testid="nav-items-left">
18+
<div className="nav__item-logo" data-testid="nav-item-logo">
19+
<Link
20+
to={`/${owner.username}/sketches`}
21+
data-testid="icon-link_user-sketches"
22+
>
1623
<LogoIcon
1724
role="img"
1825
aria-label={t('Common.p5logoARIA')}
1926
focusable="false"
2027
className="svg__logo"
28+
data-testid="icon_p5-logo"
2129
/>
2230
</Link>
2331
</div>
2432
<Link
2533
className="nav__item"
2634
to={`/${owner.username}/sketches/${project.id}`}
35+
data-testid="link_current-project"
2736
>
2837
{project.name}
2938
</Link>
3039
<p className="toolbar__project-owner">{t('PreviewNav.ByUser')}</p>
31-
<Link className="nav__item" to={`/${owner.username}/sketches/`}>
40+
<Link
41+
className="nav__item"
42+
to={`/${owner.username}/sketches`}
43+
data-testid="link_user-sketches"
44+
>
3245
{owner.username}
3346
</Link>
3447
</div>
35-
<div className="nav__items-right">
48+
<div className="nav__items-right" data-testid="nav-items-right">
3649
<Link
3750
to={`/${owner.username}/sketches/${project.id}`}
3851
aria-label={t('PreviewNav.EditSketchARIA')}
52+
data-testid="link_project-code"
3953
>
4054
<CodeIcon
4155
className="preview-nav__editor-svg"
4256
focusable="false"
4357
aria-hidden="true"
58+
data-testid="icon_code"
4459
/>
4560
</Link>
4661
</div>
4762
</nav>
4863
);
4964
};
50-
51-
PreviewNav.propTypes = {
52-
owner: PropTypes.shape({
53-
username: PropTypes.string.isRequired
54-
}).isRequired,
55-
project: PropTypes.shape({
56-
name: PropTypes.string.isRequired,
57-
id: PropTypes.string.isRequired
58-
}).isRequired
59-
};
60-
61-
export default PreviewNav;

client/custom.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
declare module '*.svg' {
2+
import * as React from 'react';
3+
4+
const ReactComponent: React.FunctionComponent<
5+
React.SVGProps<SVGSVGElement> & { title?: string }
6+
>;
7+
export default ReactComponent;
8+
}

client/modules/IDE/pages/FullView.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import Helmet from 'react-helmet';
33
import { useDispatch, useSelector } from 'react-redux';
44
import { useParams } from 'react-router-dom';
55
import PreviewFrame from '../components/PreviewFrame';
6-
import PreviewNav from '../../../components/PreviewNav';
6+
import { PreviewNav } from '../../../components/PreviewNav';
77
import { getProject } from '../actions/project';
88
import { startSketch } from '../actions/ide';
99
import {

0 commit comments

Comments
 (0)