homepage reducer unit tests and some code review apply

Signed-off-by: Virginie Ky <virginie.ky@gmail.com>
This commit is contained in:
Virginie Ky 2020-03-05 16:13:44 +01:00
parent 8f24f1537c
commit aaead39d38
9 changed files with 149 additions and 137 deletions

View File

@ -8,17 +8,15 @@ import CardPreview from '../CardPreview';
import Wrapper from './Wrapper';
import Title from './Title';
const Card = ({ file, id, small, selected, onChange }) => {
// TODO - adapt with the real data
const { type, size, name } = file;
// TODO - adapt with the real data
const Card = ({ checked, id, name, size, small, type, onChange, url }) => {
return (
<Wrapper>
<div>
<CardImgWrapper small={small} selected={selected}>
<CardPreview {...file} />
<CardImgWrapper small={small} checked={checked}>
<CardPreview type={type} url={url} />
<div className="card-control-wrapper">
<Checkbox name={id} onChange={onChange} value={selected} />
<Checkbox name={id} onChange={onChange} value={checked} />
</div>
</CardImgWrapper>
<Title fontSize="md" fontWeight="bold" ellipsis>
@ -31,18 +29,24 @@ const Card = ({ file, id, small, selected, onChange }) => {
};
Card.defaultProps = {
file: null,
checked: false,
name: null,
onChange: () => {},
size: 0,
small: false,
selected: false,
type: null,
url: null,
};
Card.propTypes = {
checked: PropTypes.bool,
name: PropTypes.string,
id: PropTypes.string.isRequired,
file: PropTypes.object,
onChange: PropTypes.func,
size: PropTypes.number,
small: PropTypes.bool,
selected: PropTypes.bool,
type: PropTypes.string,
url: PropTypes.string,
};
export default Card;

View File

@ -38,8 +38,8 @@ const CardImgWrapper = styled.div`
return '';
}}
${({ selected }) =>
selected &&
${({ checked }) =>
checked &&
`
.card-control-wrapper {
display: flex;
@ -50,14 +50,14 @@ const CardImgWrapper = styled.div`
`;
CardImgWrapper.defaultProps = {
checked: false,
hasError: false,
selected: false,
small: false,
};
CardImgWrapper.propTypes = {
checked: PropTypes.bool,
hasError: PropTypes.bool,
selected: PropTypes.bool,
small: PropTypes.bool,
};

View File

@ -6,15 +6,9 @@ import Wrapper from './Wrapper';
import Image from './Image';
const CardPreview = ({ url, type }) => {
const renderFile = () => {
if (!url) {
return <FileIcon fileType={type} />;
}
return <Image src={url} />;
};
return <Wrapper isImg={!!url}>{renderFile()}</Wrapper>;
return (
<Wrapper isImg={!!url}>{!url ? <FileIcon fileType={type} /> : <Image src={url} />}</Wrapper>
);
};
CardPreview.defaultProps = {

View File

@ -1,25 +1,10 @@
import styled from 'styled-components';
// TODO : Review this code when API is done
const Wrapper = styled.div`
font-size: 54px;
margin: auto;
color: ${({ type }) => {
switch (type) {
case 'file-pdf':
return '#E26D6D';
case 'file-image':
return '#8AA066';
case 'file-video':
return '#77C69E';
case 'file-code':
return '#515A6D';
case 'file-archive':
return '#715A31';
default:
return '#BDBFC2';
}
}};
// TODO : Review this code when API is done
color: #bdbfc2;
`;
export default Wrapper;

View File

@ -1,10 +0,0 @@
// TODO : Review this code when API is done
{
"archive": ["rar", "zip"],
"code": ["js", "json", "rb", "erb", "txt", "css", "scss", "html", "jsx", "svg"],
"img": ["jpg", "jpeg", "png", "gif", "ico"],
"pdf": ["pdf"],
"powerpoint": ["ppt", "key", "xls"],
"video": ["mov", "avi", "mpg", "mp4", "m4v"],
"word": ["doc", "pages"]
}

View File

@ -4,50 +4,18 @@
* FileIcon
*/
// TODO : Review this code when API is done
import React from 'react';
import PropTypes from 'prop-types';
import { trim } from 'lodash';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import ext from './extensions.json';
import Wrapper from './Wrapper';
function FileIcon({ fileType }) {
const iconType = (() => {
switch (true) {
case ext.archive.includes(trim(fileType, '.')):
return 'file-archive';
case ext.code.includes(trim(fileType, '.')):
return 'file-code';
case ext.img.includes(trim(fileType, '.')):
return 'file-image';
case ext.pdf.includes(trim(fileType, '.')):
return 'file-pdf';
case ext.powerpoint.includes(trim(fileType, '.')):
return 'file-powerpoint';
case ext.video.includes(trim(fileType, '.')):
return 'file-video';
case ext.word.includes(trim(fileType, '.')):
return 'file-word';
default:
return 'file';
}
})();
// TODO : Review this code when API is done
function FileIcon() {
return (
<Wrapper type={iconType}>
<FontAwesomeIcon icon={['far', iconType]} />
<Wrapper type="file">
<FontAwesomeIcon icon={['far', 'file']} />
</Wrapper>
);
}
FileIcon.defaultProps = {
fileType: 'zip',
};
FileIcon.propTypes = {
fileType: PropTypes.string,
};
export default FileIcon;

View File

@ -19,7 +19,7 @@ const List = ({ data, onChange, selectedItems }) => {
<div className="col-xs-12 col-md-6 col-xl-3" key={JSON.stringify(item)}>
<Card
small
selected={selectedItems.includes(item.id)}
checked={selectedItems.includes(item.id)}
onChange={onChange}
{...item}
/>
@ -37,73 +37,57 @@ List.defaultProps = {
data: [
{
id: '0',
file: {
name: 'Chat paysage',
size: 17329,
type: 'image/png',
url:
'https://images.pexels.com/photos/20787/pexels-photo.jpg?auto=compress&cs=tinysrgb&h=350',
},
name: 'Chat paysage',
size: 17329,
type: 'image/png',
url:
'https://images.pexels.com/photos/20787/pexels-photo.jpg?auto=compress&cs=tinysrgb&h=350',
},
{
id: '1',
file: {
name: 'Chat portrait',
size: 17329,
type: 'image/png',
url: 'https://emiliedammedumoulin.com/wp-content/uploads/2018/07/contact-chat-accueil.jpg',
},
name: 'Chat portrait',
size: 17329,
type: 'image/png',
url: 'https://emiliedammedumoulin.com/wp-content/uploads/2018/07/contact-chat-accueil.jpg',
},
{
id: '2',
file: {
name: 'Gif',
size: 17329,
type: 'image/png',
url:
'https://user-images.githubusercontent.com/879561/51321923-54024f00-1a64-11e9-8c37-3308350a59c4.gif',
},
name: 'Gif',
size: 17329,
type: 'image/png',
url:
'https://user-images.githubusercontent.com/879561/51321923-54024f00-1a64-11e9-8c37-3308350a59c4.gif',
},
{
id: '3',
file: {
name: 'Paysage',
size: 17329,
type: 'image/png',
url:
'https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcSyHCXO8D0QQrPDuGstvH9dEwhhB7Qv-3mDMWGpLExyY1CF84cL',
},
name: 'Paysage',
size: 17329,
type: 'image/png',
url:
'https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcSyHCXO8D0QQrPDuGstvH9dEwhhB7Qv-3mDMWGpLExyY1CF84cL',
},
{
id: '4',
file: {
name: 'That kitten is so beautiful that I am not sure to have the place to describe it',
size: 17329,
type: 'image/png',
url:
'https://images.pexels.com/photos/1643457/pexels-photo-1643457.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500',
},
name: 'That kitten is so beautiful that I am not sure to have the place to describe it',
size: 17329,
type: 'image/png',
url:
'https://images.pexels.com/photos/1643457/pexels-photo-1643457.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500',
},
{
id: '5',
file: {
name: 'pdf file',
type: 'pdf',
},
name: 'pdf file',
type: 'pdf',
},
{
id: '6',
file: {
name: 'Zip file',
type: 'zip',
},
name: 'Zip file',
type: 'zip',
},
{
id: '7',
file: {
name: 'Doc file',
type: 'docx',
},
name: 'Doc file',
type: 'docx',
},
],
onChange: () => {},

View File

@ -19,9 +19,7 @@ const reducer = (state, action) => {
}
const index = state.get('dataToDelete').findIndex(item => item === id);
return state.update('dataToDelete', dataToDelete => {
return dataToDelete.splice(index, 1);
});
return state.removeIn(['dataToDelete', index]);
}
default:
return state;

View File

@ -0,0 +1,89 @@
import { fromJS } from 'immutable';
import reducer, { initialState } from '../reducer';
describe('Upload | containers | HomePage | reducer', () => {
it('should update data with received data', () => {
const state = initialState;
const receivedData = [
{
id: 1,
name: 'Capture décran 2020-02-25 à 15.43.44.png',
ext: '.png',
mime: 'image/png',
size: 146.25,
url: '/uploads/ba0c3352c4b14132aed3fcf3110b481c.png',
created_at: '2020-03-04T09:45:32.444Z',
updated_at: '2020-03-04T09:45:32.444Z',
},
{
id: 2,
name: 'photo_2020-02-27 17.07.08.jpeg',
ext: '.jpeg',
mime: 'image/jpeg',
size: 140.64,
url: '/uploads/1d2ac677ea194b48bbe55ecec1b452d6.jpeg',
created_at: '2020-03-04T14:16:35.148Z',
updated_at: '2020-03-04T14:16:35.148Z',
},
];
const action = {
type: 'GET_DATA_SUCCEEDED',
data: receivedData,
};
const expectedState = state.set('data', receivedData);
expect(reducer(state, action)).toEqual(expectedState);
});
it('should add a media to dataToDelete if value is true', () => {
const state = initialState;
const action = {
type: 'ON_CHANGE_DATA_TO_DELETE',
value: true,
id: 2,
};
const expectedState = state.set('dataToDelete', fromJS([2]));
expect(reducer(state, action)).toEqual(expectedState);
});
it('should remove a media to dataToDelete if value is false', () => {
const data = [
{
id: 1,
name: 'Capture décran 2020-02-25 à 15.43.44.png',
ext: '.png',
mime: 'image/png',
size: 146.25,
url: '/uploads/ba0c3352c4b14132aed3fcf3110b481c.png',
created_at: '2020-03-04T09:45:32.444Z',
updated_at: '2020-03-04T09:45:32.444Z',
},
{
id: 2,
name: 'photo_2020-02-27 17.07.08.jpeg',
ext: '.jpeg',
mime: 'image/jpeg',
size: 140.64,
url: '/uploads/1d2ac677ea194b48bbe55ecec1b452d6.jpeg',
created_at: '2020-03-04T14:16:35.148Z',
updated_at: '2020-03-04T14:16:35.148Z',
},
];
const state = initialState.set('data', data).set('dataToDelete', fromJS([1, 2]));
const action = {
type: 'ON_CHANGE_DATA_TO_DELETE',
id: 2,
};
const expectedState = state.set('dataToDelete', fromJS([1]));
expect(reducer(state, action)).toEqual(expectedState);
});
});