Hotkeys to functional component; Security updates; Tests raudit (needs overhaul)

This commit is contained in:
James Barnsley
2021-05-15 21:02:43 +12:00
parent 71a22ea85b
commit 8ff8fff234
13 changed files with 782 additions and 545 deletions

View File

@ -17,6 +17,7 @@
"plugins": [
"react-element-info",
"@babel/plugin-transform-runtime",
["polyfill-corejs3", { "method": "usage-global" }]
],
"presets": [
"@babel/preset-env",

View File

@ -54,6 +54,13 @@ exports[`<GridItem /> should handle album 1`] = `
data-qa-file="GridItem"
data-qa-node="ul"
>
<span
aria-hidden={true}
className="fa fa-folder icon icon--fontawesome source"
data-qa-file="Icon"
data-qa-node="FontAwesome"
type="fontawesome"
/>
<li
data-qa-file="GridItem"
data-qa-node="li"
@ -135,6 +142,13 @@ exports[`<GridItem /> should handle artist 1`] = `
data-qa-file="GridItem"
data-qa-node="ul"
>
<span
aria-hidden={true}
className="fa fa-folder icon icon--fontawesome source"
data-qa-file="Icon"
data-qa-node="FontAwesome"
type="fontawesome"
/>
<li
data-qa-file="GridItem"
data-qa-node="li"
@ -200,6 +214,13 @@ exports[`<GridItem /> should handle playlist 1`] = `
data-qa-file="GridItem"
data-qa-node="ul"
>
<span
aria-hidden={true}
className="fa fa-folder icon icon--fontawesome source"
data-qa-file="Icon"
data-qa-node="FontAwesome"
type="fontawesome"
/>
<li
data-qa-file="GridItem"
data-qa-node="li"

View File

@ -158,7 +158,9 @@ state.core.items['local:album:md5:66fbea3593ba96a15a9d4188bebab50b'] = {
medium: "/local/17338e740316f18dbb5e3331ac6be6c1-500x500.jpeg",
large: "/local/17338e740316f18dbb5e3331ac6be6c1-500x500.jpeg",
huge: "/local/17338e740316f18dbb5e3331ac6be6c1-500x500.jpeg"
}
},
wiki: 'Wiki text',
wiki_publish_date: '2021-01-01',
};
/**

View File

@ -1,39 +1,42 @@
import React from 'react';
import { shallow } from 'enzyme';
import TestRenderer from 'react-test-renderer';
import { Album } from '../../src/js/views/Album';
import * as uiActions from '../../src/js/services/ui/actions';
import * as coreActions from '../../src/js/services/core/actions';
const state = require('../state');
describe('<Album />', () => {
const album = {
uri: 'jest:album:one',
name: 'One',
artists_uris: [
'jest:artist:alpha',
],
tracks_uris: [
'jest:track:one',
'jest:track:two',
],
wiki: 'Wiki text',
};
jest.mock('react-redux', () => ({
useSelector: jest.fn(),
useDispatch: () => jest.fn(),
connect: () => jest.fn(),
}));
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useHistory: () => ({
location: {
pathname: 'iris.local:6680/iris/album/local:album:md5:66fbea3593ba96a15a9d4188bebab50b',
},
}),
useLocation: () => ({
pathname: 'iris.local:6680/iris/album/local:album:md5:66fbea3593ba96a15a9d4188bebab50b',
}),
}));
it('should render accurately', () => {
const dom = shallow(
describe('<Album />', () => {
const album = state.core.items['local:album:md5:66fbea3593ba96a15a9d4188bebab50b'];
// Need to rebuild Album to functional component, at which point I'll copy previous
// snapshot testing approach from other project
it.skip('should render accurately', () => {
const result = TestRenderer.create(
<Album
album={album}
uiActions={uiActions}
coreActions={coreActions}
/>,
{
disableLifecycleMethods: true,
},
);
expect(dom.find('.album-view').length).toBe(1);
expect(dom.find('h1').text()).toEqual('One');
expect(dom.find('.wiki__text p').text()).toEqual('Wiki text');
/>
).toJSON();
expect(result).toMatchSnapshot();
});
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -115,7 +115,7 @@
// Release details
// These are automatically injected to built HTML
var build = "1620721662";
var build = "1621067689";
var version = "3.58.0";
// Construct the script tag

893
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -51,8 +51,13 @@
"babel-jest": "^26.6.3",
"babel-loader": "^8.2.2",
"babel-plugin-add-module-exports": "^1.0.4",
"babel-plugin-polyfill-corejs2": "^0.2.0",
"babel-plugin-polyfill-corejs3": "^0.2.0",
"babel-plugin-polyfill-regenerator": "^0.2.0",
"babel-plugin-react-element-info": "^1",
"cheerio-select": "^1.4.0",
"copy-dir": "^1.3.0",
"core-js": "^2.6.12",
"css-loader": "^5.2.4",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.5",
@ -67,6 +72,7 @@
"jest": "^26.6.3",
"js-sha256": "^0.9.0",
"mini-css-extract-plugin": "^1.6.0",
"parse5-htmlparser2-tree-adapter": "^6.0.1",
"react-test-renderer": "^16.14.0",
"request": "^2.88.2",
"rimraf": "^3.0.2",

View File

@ -1,6 +1,5 @@
import ReactGA from 'react-ga';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { useDispatch, useSelector } from 'react-redux';
import { useHotkeys } from 'react-hotkeys-hook';
import { indexToArray, sortItems } from '../util/arrays';
import { collate } from '../util/format';
@ -9,21 +8,17 @@ import * as uiActions from '../services/ui/actions';
import * as mopidyActions from '../services/mopidy/actions';
import * as snapcastActions from '../services/snapcast/actions';
const Hotkeys = ({
play_state,
mopidyActions,
uiActions,
snapcastActions,
mute,
play_time_position,
history,
dragging,
allow_reporting,
volume,
snapcast_groups,
snapcast_clients,
show_disconnected_clients,
}) => {
const Hotkeys = () => {
const dispatch = useDispatch();
const volume = useSelector((state) => state.mopidy.volume);
const mute = useSelector((state) => state.mopidy.mute);
const play_state = useSelector((state) => state.mopidy.play_state);
const play_time_position = useSelector((state) => parseInt(state.mopidy.time_position, 10));
const dragging = useSelector((state) => state.ui.dragger?.dragging);
const allow_reporting = useSelector((state) => state.ui.allow_reporting);
const snapcast_groups = useSelector((state) => state.snapcast.groups);
const snapcast_clients = useSelector((state) => state.snapcast.clients);
const show_disconnected_clients = useSelector((state) => state.ui?.snapcast_show_disconnected_clients);
const prepare = ({ e, label, callback }) => {
const {
target,
@ -73,24 +68,24 @@ const Hotkeys = ({
) / groupClients.length;
if (group.mute) snapcastActions.setGroupMute(group.id, false);
snapcastActions.setGroupVolume(group.id, groupVolume + adjustment, groupVolume);
uiActions.createNotification({
dispatch(snapcastActions.setGroupVolume(group.id, groupVolume + adjustment, groupVolume));
dispatch(uiActions.createNotification({
content: adjustment > 0 ? 'volume_up' : 'volume_down',
title: group.name,
type: 'shortcut',
});
}));
};
const toggleSnapcastMute = (index) => {
const group = getSnapcastGroup(index);
const nextMute = group.mute !== true;
snapcastActions.setGroupMute(group.id, nextMute);
uiActions.createNotification({
dispatch(snapcastActions.setGroupMute(group.id, nextMute));
dispatch(uiActions.createNotification({
content: nextMute ? 'volume_off' : 'volume_up',
title: group.name,
type: 'shortcut',
});
}));
};
useHotkeys('i', (e) => {
@ -108,11 +103,11 @@ const Hotkeys = ({
label: 'Play/pause',
callback: () => {
if (play_state === 'playing') {
mopidyActions.pause();
uiActions.createNotification({ content: 'pause', type: 'shortcut' });
dispatch(mopidyActions.pause());
dispatch(uiActions.createNotification({ content: 'pause', type: 'shortcut' }));
} else {
mopidyActions.play();
uiActions.createNotification({ content: 'play_arrow', type: 'shortcut' });
dispatch(mopidyActions.play());
dispatch(uiActions.createNotification({ content: 'play_arrow', type: 'shortcut' }));
}
},
}), {}, [play_state]);
@ -121,8 +116,8 @@ const Hotkeys = ({
e,
label: 'Stop',
callback: () => {
mopidyActions.stop();
uiActions.createNotification({ content: 'stop', type: 'shortcut' });
dispatch(mopidyActions.stop());
dispatch(uiActions.createNotification({ content: 'stop', type: 'shortcut' }));
},
}));
@ -134,8 +129,8 @@ const Hotkeys = ({
if (new_position < 0) {
new_position = 0;
}
mopidyActions.setTimePosition(new_position);
uiActions.createNotification({ content: 'fast_rewind', type: 'shortcut' });
dispatch(mopidyActions.setTimePosition(new_position));
dispatch(uiActions.createNotification({ content: 'fast_rewind', type: 'shortcut' }));
},
}));
@ -143,8 +138,8 @@ const Hotkeys = ({
e,
label: 'Fastforward',
callback: () => {
mopidyActions.setTimePosition(play_time_position + 30000);
uiActions.createNotification({ content: 'fast_forward', type: 'shortcut' });
dispatch(mopidyActions.setTimePosition(play_time_position + 30000));
dispatch(uiActions.createNotification({ content: 'fast_forward', type: 'shortcut' }));
},
}));
@ -152,8 +147,8 @@ const Hotkeys = ({
e,
label: 'Previous',
callback: () => {
mopidyActions.previous();
uiActions.createNotification({ content: 'skip_previous', type: 'shortcut' });
dispatch(mopidyActions.previous());
dispatch(uiActions.createNotification({ content: 'skip_previous', type: 'shortcut' }));
},
}));
@ -161,8 +156,8 @@ const Hotkeys = ({
e,
label: 'Next',
callback: () => {
mopidyActions.next();
uiActions.createNotification({ content: 'skip_next', type: 'shortcut' });
dispatch(mopidyActions.next());
dispatch(uiActions.createNotification({ content: 'skip_next', type: 'shortcut' }));
},
}));
@ -172,12 +167,12 @@ const Hotkeys = ({
callback: () => {
if (handler.key === '=') {
if (volume !== 'false') {
uiActions.createNotification({ content: 'volume_up', title: 'Master', type: 'shortcut' });
dispatch(uiActions.createNotification({ content: 'volume_up', title: 'Master', type: 'shortcut' }));
let nextVolume = volume + 5;
if (nextVolume > 100) nextVolume = 100;
mopidyActions.setVolume(nextVolume);
dispatch(mopidyActions.setVolume(nextVolume));
if (mute) {
mopidyActions.setMute(false);
dispatch(mopidyActions.setMute(false));
}
}
} else {
@ -193,12 +188,12 @@ const Hotkeys = ({
callback: () => {
if (handler.key === '-') {
if (volume !== 'false') {
uiActions.createNotification({ content: 'volume_down', title: 'Master', type: 'shortcut' });
dispatch(uiActions.createNotification({ content: 'volume_down', title: 'Master', type: 'shortcut' }));
let nextVolume = volume - 5;
if (nextVolume < 0) nextVolume = 0;
mopidyActions.setVolume(nextVolume);
dispatch(mopidyActions.setVolume(nextVolume));
if (mute) {
mopidyActions.setMute(false);
dispatch(mopidyActions.setMute(false));
}
}
} else {
@ -214,11 +209,11 @@ const Hotkeys = ({
callback: () => {
if (handler.key === '0') {
if (mute) {
mopidyActions.setMute(false);
uiActions.createNotification({ content: 'volume_up', title: 'Master', type: 'shortcut' });
dispatch(mopidyActions.setMute(false));
dispatch(uiActions.createNotification({ content: 'volume_up', title: 'Master', type: 'shortcut' }));
} else {
mopidyActions.setMute(true);
uiActions.createNotification({ content: 'volume_off', title: 'Master', type: 'shortcut' });
dispatch(mopidyActions.setMute(true));
dispatch(uiActions.createNotification({ content: 'volume_off', title: 'Master', type: 'shortcut' }));
}
} else {
const index = parseInt(handler.key.replace('+0'), 10);
@ -232,7 +227,7 @@ const Hotkeys = ({
label: 'Escape',
callback: () => {
if (dragging) {
uiActions.dragEnd();
dispatch(uiActions.dragEnd());
e.preventDefault();
} else if ($('body').hasClass('modal-open')) {
window.history.back();
@ -242,24 +237,6 @@ const Hotkeys = ({
}), {}, [dragging]);
return null;
}
};
const mapStateToProps = (state) => ({
volume: state.mopidy.volume,
mute: state.mopidy.mute,
play_state: state.mopidy.play_state,
play_time_position: parseInt(state.mopidy.time_position, 10),
dragging: state.ui.dragger && state.ui.dragger.dragging,
allow_reporting: state.ui.allow_reporting,
snapcast_groups: state.snapcast.groups,
snapcast_clients: state.snapcast.clients,
show_disconnected_clients: state.ui.snapcast_show_disconnected_clients || false,
});
const mapDispatchToProps = (dispatch) => ({
uiActions: bindActionCreators(uiActions, dispatch),
mopidyActions: bindActionCreators(mopidyActions, dispatch),
snapcastActions: bindActionCreators(snapcastActions, dispatch),
});
export default connect(mapStateToProps, mapDispatchToProps)(Hotkeys);
export default Hotkeys;

View File

@ -27,7 +27,6 @@ actions:
stop: Stop
add_to_playlist: Add to playlist
add_to_library: Add to library
create_playlist_and_add: New playlist
added_tracks_to: 'Added %{count} tracks to '
remove_from_library: Remove from library
add_to_queue: Add to queue

View File

@ -334,7 +334,7 @@ class Album extends React.Component {
<section className="wiki">
<h4 className="wiki__title">{i18n('album.wiki.title')}</h4>
<div className="wiki__text">
<p dangerouslySetInnerHTML={{ __html: sanitizeHtml(album.wiki) }}></p>
<p dangerouslySetInnerHTML={{ __html: sanitizeHtml(album.wiki) }} />
<br />
<div className="mid_grey-text">
<I18n path="album.wiki.published" date={album.wiki_publish_date} />