fix some tests
fix merge issues
This commit is contained in:
@ -1,140 +0,0 @@
|
||||
import React from 'react';
|
||||
import SideBar, {SideBarTitle} from '../../elements/SideBar/SideBar';
|
||||
import Tag from '../../elements/Tag/Tag';
|
||||
import videocontainerstyle from '../../elements/VideoContainer/VideoContainer.module.css';
|
||||
|
||||
import {TagPreview} from '../../elements/Preview/Preview';
|
||||
import NewTagPopup from '../../elements/Popups/NewTagPopup/NewTagPopup';
|
||||
import PageTitle, {Line} from '../../elements/PageTitle/PageTitle';
|
||||
import VideoContainer from '../../elements/VideoContainer/VideoContainer';
|
||||
import {callAPI} from '../../utils/Api';
|
||||
|
||||
/**
|
||||
* Component for Category Page
|
||||
* Contains a Tag Overview and loads specific Tag videos in VideoContainer
|
||||
*/
|
||||
class CategoryPage extends React.Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
loadedtags: [],
|
||||
selected: null
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// check if predefined category is set
|
||||
if (this.props.category) {
|
||||
this.fetchVideoData(this.props.category);
|
||||
} else {
|
||||
this.loadTags();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* render the Title and SideBar component for the Category page
|
||||
* @returns {JSX.Element} corresponding jsx element for Title and Sidebar
|
||||
*/
|
||||
renderSideBarATitle() {
|
||||
return (
|
||||
<>
|
||||
<PageTitle
|
||||
title='Categories'
|
||||
subtitle={!this.state.selected ? this.state.loadedtags.length + ' different Tags' : this.state.selected}/>
|
||||
|
||||
<SideBar>
|
||||
<SideBarTitle>Default Tags:</SideBarTitle>
|
||||
<Tag onclick={(tag) => {this.loadTag(tag);}}>All</Tag>
|
||||
<Tag onclick={(tag) => {this.loadTag(tag);}}>FullHd</Tag>
|
||||
<Tag onclick={(tag) => {this.loadTag(tag);}}>LowQuality</Tag>
|
||||
<Tag onclick={(tag) => {this.loadTag(tag);}}>HD</Tag>
|
||||
<Line/>
|
||||
<button data-testid='btnaddtag' className='btn btn-success' onClick={() => {
|
||||
this.setState({popupvisible: true});
|
||||
}}>Add a new Tag!
|
||||
</button>
|
||||
</SideBar></>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
{this.renderSideBarATitle()}
|
||||
|
||||
{this.state.selected ?
|
||||
<>
|
||||
{this.videodata ?
|
||||
<VideoContainer
|
||||
data={this.videodata}/> : null}
|
||||
<button data-testid='backbtn' className='btn btn-success'
|
||||
onClick={this.loadCategoryPageDefault}>Back
|
||||
</button>
|
||||
</> :
|
||||
<div className={videocontainerstyle.maincontent}>
|
||||
{this.state.loadedtags ?
|
||||
this.state.loadedtags.map((m) => (
|
||||
<TagPreview
|
||||
key={m.tag_name}
|
||||
name={m.tag_name}
|
||||
tag_id={m.tag_id}
|
||||
categorybinding={this.loadTag}/>
|
||||
)) :
|
||||
'loading'}
|
||||
</div>
|
||||
}
|
||||
|
||||
{this.state.popupvisible ?
|
||||
<NewTagPopup show={this.state.popupvisible}
|
||||
onHide={() => {
|
||||
console.error("setstatecalled!");
|
||||
this.setState({popupvisible: false});
|
||||
this.loadTags();
|
||||
}}/> :
|
||||
null
|
||||
}
|
||||
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* load a specific tag into a new previewcontainer
|
||||
* @param tagname
|
||||
*/
|
||||
loadTag = (tagname) => {
|
||||
this.fetchVideoData(tagname);
|
||||
};
|
||||
|
||||
/**
|
||||
* fetch data for a specific tag from backend
|
||||
* @param tag tagname
|
||||
*/
|
||||
fetchVideoData(tag) {
|
||||
callAPI('video.php', {action: 'getMovies', tag: tag}, result => {
|
||||
this.videodata = result;
|
||||
this.setState({selected: null}); // needed to trigger the state reload correctly
|
||||
this.setState({selected: tag});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* go back to the default category overview
|
||||
*/
|
||||
loadCategoryPageDefault = () => {
|
||||
this.setState({selected: null});
|
||||
this.loadTags();
|
||||
};
|
||||
|
||||
/**
|
||||
* load all available tags from db.
|
||||
*/
|
||||
loadTags() {
|
||||
callAPI('tags.php', {action: 'getAllTags'}, result => {
|
||||
this.setState({loadedtags: result});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default CategoryPage;
|
@ -1,4 +1,4 @@
|
||||
import {mount, shallow} from 'enzyme';
|
||||
import {shallow} from 'enzyme';
|
||||
import React from 'react';
|
||||
import CategoryPage from './CategoryPage';
|
||||
|
||||
@ -8,22 +8,6 @@ describe('<CategoryPage/>', function () {
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
it('test tag fetch call', done => {
|
||||
global.fetch = global.prepareFetchApi(['first', 'second']);
|
||||
|
||||
const wrapper = shallow(<CategoryPage/>);
|
||||
|
||||
expect(global.fetch).toHaveBeenCalledTimes(1);
|
||||
|
||||
process.nextTick(() => {
|
||||
//callback to close window should have called
|
||||
expect(wrapper.state().loadedtags.length).toBe(2);
|
||||
|
||||
global.fetch.mockClear();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('test new tag popup', function () {
|
||||
const wrapper = shallow(<CategoryPage/>);
|
||||
|
||||
@ -33,63 +17,31 @@ describe('<CategoryPage/>', function () {
|
||||
expect(wrapper.find('NewTagPopup')).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('test setpage callback', done => {
|
||||
global.fetch = global.prepareFetchApi([{}, {}]);
|
||||
|
||||
it('test add popup', function () {
|
||||
const wrapper = shallow(<CategoryPage/>);
|
||||
|
||||
wrapper.setState({
|
||||
loadedtags: [
|
||||
{
|
||||
tag_name: 'testname',
|
||||
tag_id: 42
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
wrapper.find('TagPreview').dive().find('div').first().simulate('click');
|
||||
|
||||
process.nextTick(() => {
|
||||
// expect callback to have loaded correct tag
|
||||
expect(wrapper.state().selected).toBe('testname');
|
||||
|
||||
global.fetch.mockClear();
|
||||
done();
|
||||
});
|
||||
expect(wrapper.find('NewTagPopup')).toHaveLength(0);
|
||||
wrapper.setState({popupvisible: true});
|
||||
expect(wrapper.find('NewTagPopup')).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('test back to category view callback', function () {
|
||||
it('test hiding of popup', function () {
|
||||
const wrapper = shallow(<CategoryPage/>);
|
||||
wrapper.setState({popupvisible: true});
|
||||
|
||||
wrapper.find('NewTagPopup').props().onHide();
|
||||
|
||||
expect(wrapper.find('NewTagPopup')).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('test setting of subtitle', function () {
|
||||
const wrapper = shallow(<CategoryPage/>);
|
||||
|
||||
wrapper.setState({
|
||||
selected: 'test'
|
||||
});
|
||||
expect(wrapper.state().selected).not.toBeNull();
|
||||
wrapper.find('[data-testid="backbtn"]').simulate('click');
|
||||
expect(wrapper.state().selected).toBeNull();
|
||||
});
|
||||
expect(wrapper.find('PageTitle').props().subtitle).not.toBe('testtitle');
|
||||
|
||||
it('load categorypage with predefined tag', function () {
|
||||
const func = jest.fn();
|
||||
CategoryPage.prototype.fetchVideoData = func;
|
||||
|
||||
shallow(<CategoryPage category='fullhd'/>);
|
||||
|
||||
expect(func).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
it('test sidebar tag clicks', function () {
|
||||
const func = jest.fn();
|
||||
|
||||
const wrapper = shallow(<CategoryPage category='fullhd'/>);
|
||||
wrapper.instance().loadTag = func;
|
||||
|
||||
expect(func).toBeCalledTimes(0);
|
||||
wrapper.find('SideBar').find('Tag').forEach(e => {
|
||||
e.dive().simulate('click');
|
||||
});
|
||||
|
||||
expect(func).toBeCalledTimes(4);
|
||||
wrapper.instance().setSubTitle('testtitle');
|
||||
|
||||
// test if prop of title is set correctly
|
||||
expect(wrapper.find('PageTitle').props().subtitle).toBe('testtitle');
|
||||
});
|
||||
});
|
||||
|
83
src/pages/CategoryPage/CategoryPage.tsx
Normal file
83
src/pages/CategoryPage/CategoryPage.tsx
Normal file
@ -0,0 +1,83 @@
|
||||
import React from 'react';
|
||||
import SideBar, {SideBarTitle} from '../../elements/SideBar/SideBar';
|
||||
import Tag from '../../elements/Tag/Tag';
|
||||
import NewTagPopup from '../../elements/Popups/NewTagPopup/NewTagPopup';
|
||||
import PageTitle, {Line} from '../../elements/PageTitle/PageTitle';
|
||||
import {Route, Switch} from 'react-router-dom';
|
||||
import {DefaultTags} from '../../api/GeneralTypes';
|
||||
import {CategoryViewWR} from './CategoryView';
|
||||
import TagView from './TagView';
|
||||
|
||||
|
||||
interface CategoryPageState {
|
||||
popupvisible: boolean;
|
||||
subtitle: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component for Category Page
|
||||
* Contains a Tag Overview and loads specific Tag videos in VideoContainer
|
||||
*/
|
||||
class CategoryPage extends React.Component<{}, CategoryPageState> {
|
||||
constructor(props: {}) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
popupvisible: false,
|
||||
subtitle: ''
|
||||
};
|
||||
|
||||
this.setSubTitle = this.setSubTitle.bind(this);
|
||||
}
|
||||
|
||||
render(): JSX.Element {
|
||||
return (
|
||||
<>
|
||||
<PageTitle
|
||||
title='Categories'
|
||||
subtitle={this.state.subtitle}/>
|
||||
|
||||
<SideBar>
|
||||
<SideBarTitle>Default Tags:</SideBarTitle>
|
||||
<Tag tagInfo={DefaultTags.all}/>
|
||||
<Tag tagInfo={DefaultTags.fullhd}/>
|
||||
<Tag tagInfo={DefaultTags.hd}/>
|
||||
<Tag tagInfo={DefaultTags.lowq}/>
|
||||
|
||||
<Line/>
|
||||
<button data-testid='btnaddtag' className='btn btn-success' onClick={(): void => {
|
||||
this.setState({popupvisible: true});
|
||||
}}>Add a new Tag!
|
||||
</button>
|
||||
</SideBar>
|
||||
<Switch>
|
||||
<Route path='/categories/:id'>
|
||||
<CategoryViewWR setSubTitle={this.setSubTitle}/>
|
||||
</Route>
|
||||
<Route path='/categories'>
|
||||
<TagView setSubTitle={this.setSubTitle}/>
|
||||
</Route>
|
||||
</Switch>
|
||||
|
||||
{this.state.popupvisible ?
|
||||
<NewTagPopup show={this.state.popupvisible}
|
||||
onHide={(): void => {
|
||||
this.setState({popupvisible: false});
|
||||
// this.loadTags();
|
||||
}}/> :
|
||||
null
|
||||
}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* set the subtitle of this page
|
||||
* @param subtitle string as subtitle
|
||||
*/
|
||||
setSubTitle(subtitle: string): void {
|
||||
this.setState({subtitle: subtitle});
|
||||
}
|
||||
}
|
||||
|
||||
export default CategoryPage;
|
24
src/pages/CategoryPage/CategoryView.test.js
Normal file
24
src/pages/CategoryPage/CategoryView.test.js
Normal file
@ -0,0 +1,24 @@
|
||||
import {shallow} from 'enzyme';
|
||||
import React from 'react';
|
||||
import {CategoryView} from './CategoryView';
|
||||
|
||||
describe('<CategoryView/>', function () {
|
||||
function instance() {
|
||||
return shallow(<CategoryView match={{params: {id: 10}}}/>);
|
||||
}
|
||||
|
||||
it('renders without crashing ', function () {
|
||||
const wrapper = instance();
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
it('test backbutton', function () {
|
||||
const wrapper = instance();
|
||||
const func = jest.fn();
|
||||
wrapper.setProps({history: {push: func}});
|
||||
|
||||
expect(func).toHaveBeenCalledTimes(0);
|
||||
wrapper.find('button').simulate('click');
|
||||
expect(func).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
75
src/pages/CategoryPage/CategoryView.tsx
Normal file
75
src/pages/CategoryPage/CategoryView.tsx
Normal file
@ -0,0 +1,75 @@
|
||||
import {RouteComponentProps} from 'react-router';
|
||||
import React from 'react';
|
||||
import {VideoUnloadedType} from '../../api/VideoTypes';
|
||||
import VideoContainer from '../../elements/VideoContainer/VideoContainer';
|
||||
import {callAPI} from '../../utils/Api';
|
||||
import {withRouter} from 'react-router-dom';
|
||||
|
||||
interface CategoryViewProps extends RouteComponentProps<{ id: string }> {
|
||||
setSubTitle: (title: string) => void
|
||||
}
|
||||
|
||||
interface CategoryViewState {
|
||||
loaded: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* plain class (for unit testing only)
|
||||
*/
|
||||
export class CategoryView extends React.Component<CategoryViewProps, CategoryViewState> {
|
||||
private videodata: VideoUnloadedType[] = [];
|
||||
|
||||
constructor(props: CategoryViewProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
loaded: false
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
this.fetchVideoData(parseInt(this.props.match.params.id));
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: Readonly<CategoryViewProps>, prevState: Readonly<CategoryViewState>): void {
|
||||
// trigger video refresh if id changed
|
||||
if (prevProps.match.params.id !== this.props.match.params.id) {
|
||||
this.setState({loaded: false});
|
||||
this.fetchVideoData(parseInt(this.props.match.params.id));
|
||||
}
|
||||
}
|
||||
|
||||
render(): JSX.Element {
|
||||
return (
|
||||
<>
|
||||
{this.state.loaded ?
|
||||
<VideoContainer
|
||||
data={this.videodata}/> : null}
|
||||
|
||||
<button data-testid='backbtn' className='btn btn-success'
|
||||
onClick={(): void => {
|
||||
this.props.history.push('/categories');
|
||||
}}>Back to Categories
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* fetch data for a specific tag from backend
|
||||
* @param id tagid
|
||||
*/
|
||||
fetchVideoData(id: number): void {
|
||||
callAPI<VideoUnloadedType[]>('video.php', {action: 'getMovies', tag: id}, result => {
|
||||
this.videodata = result;
|
||||
this.setState({loaded: true});
|
||||
this.props.setSubTitle(this.videodata.length + ' Videos');
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* export with react Router wrapped (default use)
|
||||
*/
|
||||
export const CategoryViewWR = withRouter(CategoryView);
|
17
src/pages/CategoryPage/TagView.test.js
Normal file
17
src/pages/CategoryPage/TagView.test.js
Normal file
@ -0,0 +1,17 @@
|
||||
import {shallow} from 'enzyme';
|
||||
import React from 'react';
|
||||
import TagView from './TagView';
|
||||
|
||||
describe('<TagView/>', function () {
|
||||
it('renders without crashing ', function () {
|
||||
const wrapper = shallow(<TagView/>);
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
it('test Tag insertion', function () {
|
||||
const wrapper = shallow(<TagView/>);
|
||||
wrapper.setState({loadedtags: [{tag_name: 'test', tag_id: 42}]});
|
||||
|
||||
expect(wrapper.find('TagPreview')).toHaveLength(1);
|
||||
});
|
||||
});
|
55
src/pages/CategoryPage/TagView.tsx
Normal file
55
src/pages/CategoryPage/TagView.tsx
Normal file
@ -0,0 +1,55 @@
|
||||
import {TagType} from '../../api/VideoTypes';
|
||||
import React from 'react';
|
||||
import videocontainerstyle from '../../elements/VideoContainer/VideoContainer.module.css';
|
||||
import {Link} from 'react-router-dom';
|
||||
import {TagPreview} from '../../elements/Preview/Preview';
|
||||
import {callAPI} from '../../utils/Api';
|
||||
|
||||
interface TagViewState {
|
||||
loadedtags: TagType[];
|
||||
}
|
||||
|
||||
interface props {
|
||||
setSubTitle: (title: string) => void
|
||||
}
|
||||
|
||||
class TagView extends React.Component<props, TagViewState> {
|
||||
constructor(props: props) {
|
||||
super(props);
|
||||
|
||||
this.state = {loadedtags: []};
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
this.loadTags();
|
||||
}
|
||||
|
||||
render(): JSX.Element {
|
||||
return (
|
||||
<>
|
||||
<div className={videocontainerstyle.maincontent}>
|
||||
{this.state.loadedtags ?
|
||||
this.state.loadedtags.map((m) => (
|
||||
<Link to={'/categories/' + m.tag_id}><TagPreview
|
||||
key={m.tag_id}
|
||||
name={m.tag_name}
|
||||
tag_id={m.tag_id}/></Link>
|
||||
)) :
|
||||
'loading'}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* load all available tags from db.
|
||||
*/
|
||||
loadTags(): void {
|
||||
callAPI<TagType[]>('tags.php', {action: 'getAllTags'}, result => {
|
||||
this.setState({loadedtags: result});
|
||||
this.props.setSubTitle(result.length + ' different Tags');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default TagView;
|
Reference in New Issue
Block a user