Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement carousel with basic functionality #74

Merged
merged 12 commits into from May 24, 2022
21 changes: 0 additions & 21 deletions client/src/components/App/App.jsx
Expand Up @@ -3,34 +3,13 @@ import styled, { css } from 'styled-components';
import Reviews from 'Reviews/Reviews.jsx';
import Overview from 'Overview/Overview.jsx';

// a very basic example of how to use the styles
// It uses `` as a function call then you put in any css
const Button = styled.button`
background: transparent;
border-radius: 3px;
border: 2px solid palevioletred;
color: palevioletred;
margin: 0.5em 1em;
padding: 0.25em 1em;

/* this is to change style based on a prop */

${(props) => props.test && css`
background: palevioletred;
color: white;
`};
`;

const Container = styled.div`
text-align: center;
`;

function App() {
return (
<Container>
Hello
<Button as="a" href="#">test</Button>
<Button test>test</Button>
<Overview />
<Reviews />
</Container>
Expand Down
5 changes: 0 additions & 5 deletions client/src/components/App/App.test.js

This file was deleted.

41 changes: 41 additions & 0 deletions client/src/components/App/Carousel.jsx
@@ -0,0 +1,41 @@
import React, { useState } from "react";
import PropTypes from "prop-types";

/**
* Display a set of item with buttons to scroll through them
* @param {Array} items The items to be displayed
* @param {Number} size How many items to display at once
*/

function Carousel({ items, size }) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some good general style conventions, put a comment on public exports. Carousel is pretty self explanatory, but could be nice for more complicated ones, and in general for the props that are being passed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call. Added some documentation. The Carousel is shared across the app, but would you suggest documentation on components that only I will be using too?

const [start, setStart] = useState(0);

const decrement = (event) => {
event.preventDefault();
setStart((oldStart) => Math.max(0, oldStart - size));
};

const increment = (event) => {
event.preventDefault();
setStart((oldStart) => Math.min(items.length - size + 1, oldStart + size));
};

return (
<div>
<button type="button" onClick={decrement}>
&lt;
</button>
{items.slice(start, start + size)}
<button type="button" onClick={increment}>
&gt;
</button>
</div>
);
}

Carousel.propTypes = {
items: PropTypes.arrayOf(PropTypes.element).isRequired,
size: PropTypes.number.isRequired,
};

export default Carousel;
62 changes: 62 additions & 0 deletions client/src/components/App/Carousel.test.jsx
@@ -0,0 +1,62 @@
import React from 'react';
import '@testing-library/jest-dom/extend-expect';
import { fireEvent, render, screen } from '@testing-library/react';
import Carousel from 'App/Carousel.jsx';

describe('Carousel', () => {

const range = (start, end) => (
Array(end - start + 1).fill().map((_, i) => i + start)
);

const numbers = range(0, 9);
const size = 4;

const getScreenItems = () => {
const screenItems = [];
numbers.forEach(i => {
const screenItem = screen.queryByText(new RegExp(`^${i}$`));
if (screenItem) {
screenItems.push(screenItem);
}
});
return screenItems;
};

const checkScreenItems = (bounds) => {
numbers.forEach(i => {
const screenItem = screen.queryByText(new RegExp(`^${i}$`));
if (bounds.includes(i)) {
expect(screenItem).toBeVisible();
} else {
expect(screenItem).toBeNull();
}
});
};

beforeEach(() => {
const items = numbers.map(i => (
<div key={i}>{i}</div>
));

render(
<Carousel items={items} size={size} />
);
});

it('should show the correct number of items', () => {
let screenItems = getScreenItems();
expect(screenItems.length).toEqual(size);
});

it('should scroll on button presses', () => {
const backButton = screen.getByText('<');
const forwardButton = screen.getByText('>');

fireEvent.click(forwardButton);
checkScreenItems(range(size, 2 * size - 1));

fireEvent.click(backButton);
checkScreenItems(range(0, size - 1));
});
});
5 changes: 0 additions & 5 deletions client/src/components/Overview/AddToCart.test.js

This file was deleted.

5 changes: 0 additions & 5 deletions client/src/components/Overview/ImageGallery.test.js

This file was deleted.

2 changes: 1 addition & 1 deletion client/src/components/Overview/Overview.jsx
@@ -1,6 +1,6 @@
import React from 'react';
import ImageGallery from 'Overview/ImageGallery.jsx';
import ProductInformation from 'Overview/ProductInformation.jsx'
import ProductInformation from 'Overview/ProductInformation.jsx';

function Overview() {
return (
Expand Down
5 changes: 0 additions & 5 deletions client/src/components/Overview/Overview.test.js

This file was deleted.

5 changes: 0 additions & 5 deletions client/src/components/Overview/ProductInformation.test.js

This file was deleted.

5 changes: 0 additions & 5 deletions client/src/components/Overview/StyleSelector.test.js

This file was deleted.

5 changes: 0 additions & 5 deletions client/src/components/RelatedItems/RelatedItems.test.js

This file was deleted.

5 changes: 0 additions & 5 deletions client/src/components/Reviews/Reviews.test.js

This file was deleted.

7 changes: 6 additions & 1 deletion jest.config.js
Expand Up @@ -79,7 +79,12 @@ module.exports = {
moduleFileExtensions: ['js', 'jsx'],

// A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
// moduleNameMapper: {},
moduleNameMapper: {
'^App(.*)$': '<rootDir>/client/src/components/App$1',
'^Overview(.*)$': '<rootDir>/client/src/components/Overview$1',
'^RelatedItems(.*)$': '<rootDir>/client/src/components/RelatedItems$1',
'^Reviews(.*)$': '<rootDir>/client/src/components/Reviews$1',
},

// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
// modulePathIgnorePatterns: [],
Expand Down