added tests and css modules for NameContainer components

This commit is contained in:
Wenszel 2023-12-12 20:13:13 +01:00
parent aa6c03ebcb
commit 469a60871a
9 changed files with 118 additions and 35 deletions

View File

@ -1,19 +1,12 @@
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import { CSSTransition } from 'react-transition-group'; import { CSSTransition } from 'react-transition-group';
import './TimerAnimation.js'; import './TimerAnimation.js';
const AnimatedOverlay = ({ time }) => { const AnimatedOverlay = ({ time }) => {
const animationDelay = useMemo(() => 15 - Math.ceil((time - Date.now()) / 1000), [time]); const animationDelay = useMemo(() => 15 - Math.ceil((time - Date.now()) / 1000), [time]);
return ( return (
<CSSTransition <CSSTransition in={true} timeout={0} style={{ animationDelay: `-${animationDelay}s` }} unmountOnExit>
in={true} <div className='overlay' data-testid='animated-overlay'></div>
timeout={0}
classNames='overlay'
style={{ animationDelay: `-${animationDelay}s` }}
unmountOnExit
>
<div className='overlay'></div>
</CSSTransition> </CSSTransition>
); );
}; };

View File

@ -0,0 +1,10 @@
.overlay {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
opacity: 0.9;
animation: timerAnimation 15s linear infinite;
transition-duration: 15s;
}

View File

@ -0,0 +1,20 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import AnimatedOverlay from './AnimatedOverlay';
describe('AnimatedOverlay component', () => {
it('renders without crashing', () => {
render(<AnimatedOverlay time={0} />);
});
it('applies animation delay based on time prop', () => {
const timeNow = Date.now();
const time = timeNow + 5000;
render(<AnimatedOverlay time={time} />);
const overlay = screen.getByTestId('animated-overlay');
const expectedDelay = 15 - Math.ceil((time - timeNow) / 1000);
expect(overlay).toHaveStyle({ animationDelay: `-${expectedDelay}s` });
});
});

View File

@ -4,20 +4,20 @@ const steps = 86;
let count = 0; let count = 0;
let s = 'polygon(50% 50%, 50% 0%, 50% 0%'; let s = 'polygon(50% 50%, 50% 0%, 50% 0%';
for (let i = 50; i <= 100; i += 5) { for (let i = 50; i < 100; i += 5) {
s += `, ${i}% 0%`; s += `, ${i}% 0%`;
handle(); handle();
} }
for (let i = 0; i <= 100; i += 5) { for (let i = 0; i < 100; i += 5) {
s += `, 100% ${i}%`; s += `, 100% ${i}%`;
handle(); handle();
} }
for (let i = 100; i >= 0; i -= 5) { for (let i = 100; i > 0; i -= 5) {
s += `, ${i}% 100%`; s += `, ${i}% 100%`;
handle(); handle();
} }
for (let i = 100; i >= 0; i -= 5) { for (let i = 100; i > 0; i -= 5) {
s += `, 0% ${i}%`; s += `, 0% ${i}%`;
handle(); handle();
} }
@ -52,12 +52,13 @@ function handle() {
keyframes.push(step); keyframes.push(step);
count++; count++;
} }
if (document && document.styleSheets && document.styleSheets[0]) {
document.styleSheets[0].insertRule( document.styleSheets[0].insertRule(
` `
@keyframes timerAnimation { @keyframes timerAnimation {
${keyframes.join('\n')} ${keyframes.join('\n')}
} }
`, `,
document.styleSheets[0].cssRules.length document.styleSheets[0].cssRules.length
); );
}

View File

@ -1,13 +1,11 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import AnimatedOverlay from './AnimatedOverlay/AnimatedOverlay'; import AnimatedOverlay from './AnimatedOverlay/AnimatedOverlay';
import styles from './NameContainer.module.css';
const NameContainer = ({ player, time }) => { const NameContainer = ({ player, time }) => {
return ( return (
<div <div className={styles.container} style={{ backgroundColor: player.ready ? player.color : 'lightgrey' }}>
className='name-container'
style={player.ready ? { backgroundColor: player.color } : { backgroundColor: 'lightgrey' }}
>
<p>{player.name}</p> <p>{player.name}</p>
{player.nowMoving ? <AnimatedOverlay time={time} /> : null} {player.nowMoving ? <AnimatedOverlay time={time} /> : null}
</div> </div>
@ -17,6 +15,7 @@ const NameContainer = ({ player, time }) => {
NameContainer.propTypes = { NameContainer.propTypes = {
player: PropTypes.object, player: PropTypes.object,
time: PropTypes.number, time: PropTypes.number,
testId: PropTypes.string,
}; };
export default NameContainer; export default NameContainer;

View File

@ -0,0 +1,13 @@
.container {
position: relative;
min-width: 100px;
min-height: 50px;
display: flex;
justify-content: center;
align-items: center;
border: 2px solid white;
border-radius: 5px;
color: white;
font-weight: bold;
text-align: center;
}

View File

@ -0,0 +1,58 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import NameContainer from './NameContainer';
import { NOT_READY_COLOR } from '../../../constants/colors';
jest.mock('./AnimatedOverlay/AnimatedOverlay.jsx', () => () => {
return <mock-animated-overlay data-testid='animated-overlay' />;
});
describe('NameContainer component', () => {
let player;
let time;
beforeEach(() => {
player = {
name: 'TestPlayer',
ready: false,
color: 'blue',
nowMoving: false,
};
time = 0;
});
it('renders without crashing', () => {
render(<NameContainer player={player} time={time} />);
});
it('renders player name', () => {
render(<NameContainer player={player} time={time} />);
expect(screen.getByText(player.name)).toBeInTheDocument();
});
it('applies grey color when player is not ready', () => {
player.ready = false;
render(<NameContainer player={player} time={time} testId='name-container' />);
const container = screen.getByText(player.name).closest('div');
expect(container).toHaveStyle({ backgroundColor: NOT_READY_COLOR });
});
it('applies player colors as background when player is ready', () => {
player.ready = true;
render(<NameContainer player={player} time={time} testId='name-container' />);
const container = screen.getByText(player.name).closest('div');
expect(container).toHaveStyle({ backgroundColor: player.color });
});
it('renders AnimatedOverlay when player is nowMoving', () => {
const movingPlayer = { ...player, nowMoving: true };
render(<NameContainer player={movingPlayer} time={time} />);
expect(screen.getByTestId('animated-overlay')).toBeInTheDocument();
});
it('does not render AnimatedOverlay when player is not nowMoving', () => {
render(<NameContainer player={player} time={time} />);
expect(screen.queryByTestId('animated-overlay')).toBeNull();
});
});

2
src/constants/colors.js Normal file
View File

@ -0,0 +1,2 @@
export const NOT_READY_COLOR = 'lightgrey';
export const PLAYER_COLORS = ['red', 'blue', 'green', 'yellow'];

View File

@ -29,19 +29,6 @@ canvas {
flex-direction: row; flex-direction: row;
} }
.name-container {
position: relative;
min-width: 100px;
min-height: 50px;
display: flex;
justify-content: center;
align-items: center;
border: 2px solid white;
border-radius: 5px;
color: white;
font-weight: bold;
text-align: center;
}
.timer { .timer {
background-color: darkblue; background-color: darkblue;
color: white; color: white;