commit
457d954e08
42 changed files with 1706 additions and 1488 deletions
|
@ -29,6 +29,7 @@ module.exports = function (config) {
|
||||||
singleRun: true,
|
singleRun: true,
|
||||||
|
|
||||||
webpack: {
|
webpack: {
|
||||||
|
mode: 'development',
|
||||||
devtool: 'inline-source-map',
|
devtool: 'inline-source-map',
|
||||||
resolve: webpackConfig.resolve,
|
resolve: webpackConfig.resolve,
|
||||||
module: webpackConfig.module
|
module: webpackConfig.module
|
||||||
|
|
1596
package-lock.json
generated
1596
package-lock.json
generated
File diff suppressed because it is too large
Load diff
14
package.json
14
package.json
|
@ -20,11 +20,11 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/ueokande/vim-vixen",
|
"homepage": "https://github.com/ueokande/vim-vixen",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-cli": "^6.26.0",
|
"@babel/cli": "^7.4.4",
|
||||||
|
"@babel/core": "^7.4.4",
|
||||||
|
"@babel/preset-react": "^7.0.0",
|
||||||
"babel-eslint": "^10.0.1",
|
"babel-eslint": "^10.0.1",
|
||||||
"babel-loader": "^7.1.5",
|
"babel-loader": "^8.0.5",
|
||||||
"babel-preset-preact": "^1.1.0",
|
|
||||||
"babel-preset-stage-2": "^6.24.1",
|
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.2.0",
|
||||||
"css-loader": "^2.1.1",
|
"css-loader": "^2.1.1",
|
||||||
"eslint": "^5.16.0",
|
"eslint": "^5.16.0",
|
||||||
|
@ -42,8 +42,10 @@
|
||||||
"lanthan": "git+https://github.com/ueokande/lanthan.git#master",
|
"lanthan": "git+https://github.com/ueokande/lanthan.git#master",
|
||||||
"mocha": "^6.1.4",
|
"mocha": "^6.1.4",
|
||||||
"node-sass": "^4.12.0",
|
"node-sass": "^4.12.0",
|
||||||
"preact": "^8.4.2",
|
"react": "^16.8.6",
|
||||||
"preact-redux": "^2.0.3",
|
"react-dom": "^16.8.6",
|
||||||
|
"react-redux": "^7.0.3",
|
||||||
|
"react-test-renderer": "^16.8.6",
|
||||||
"redux": "^4.0.1",
|
"redux": "^4.0.1",
|
||||||
"redux-promise": "^0.6.0",
|
"redux-promise": "^0.6.0",
|
||||||
"sass-loader": "^7.1.0",
|
"sass-loader": "^7.1.0",
|
||||||
|
|
|
@ -19,9 +19,9 @@ export default class Completions {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
static EMPTY_COMPLETIONS = new Completions([]);
|
|
||||||
|
|
||||||
static empty() {
|
static empty() {
|
||||||
return Completions.EMPTY_COMPLETIONS;
|
return EMPTY_COMPLETIONS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let EMPTY_COMPLETIONS = new Completions([]);
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
import './console.scss';
|
import './console.scss';
|
||||||
import { connect } from 'preact-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Component, h } from 'preact';
|
import React from 'react';
|
||||||
import Input from './console/input';
|
import PropTypes from 'prop-types';
|
||||||
import Completion from './console/completion';
|
import Input from './console/Input';
|
||||||
import Message from './console/message';
|
import Completion from './console/Completion';
|
||||||
|
import Message from './console/Message';
|
||||||
import * as consoleActions from '../../console/actions/console';
|
import * as consoleActions from '../../console/actions/console';
|
||||||
|
|
||||||
const COMPLETION_MAX_ITEMS = 33;
|
const COMPLETION_MAX_ITEMS = 33;
|
||||||
|
|
||||||
class ConsoleComponent extends Component {
|
class Console extends React.Component {
|
||||||
onBlur() {
|
onBlur() {
|
||||||
if (this.props.mode === 'command' || this.props.mode === 'find') {
|
if (this.props.mode === 'command' || this.props.mode === 'find') {
|
||||||
return this.context.store.dispatch(consoleActions.hideCommand());
|
return this.props.dispatch(consoleActions.hideCommand());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,45 +22,45 @@ class ConsoleComponent extends Component {
|
||||||
|
|
||||||
let value = e.target.value;
|
let value = e.target.value;
|
||||||
if (this.props.mode === 'command') {
|
if (this.props.mode === 'command') {
|
||||||
return this.context.store.dispatch(consoleActions.enterCommand(value));
|
return this.props.dispatch(consoleActions.enterCommand(value));
|
||||||
} else if (this.props.mode === 'find') {
|
} else if (this.props.mode === 'find') {
|
||||||
return this.context.store.dispatch(consoleActions.enterFind(value));
|
return this.props.dispatch(consoleActions.enterFind(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
selectNext(e) {
|
selectNext(e) {
|
||||||
this.context.store.dispatch(consoleActions.completionNext());
|
this.props.dispatch(consoleActions.completionNext());
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
selectPrev(e) {
|
selectPrev(e) {
|
||||||
this.context.store.dispatch(consoleActions.completionPrev());
|
this.props.dispatch(consoleActions.completionPrev());
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown(e) {
|
onKeyDown(e) {
|
||||||
if (e.keyCode === KeyboardEvent.DOM_VK_ESCAPE && e.ctrlKey) {
|
if (e.keyCode === KeyboardEvent.DOM_VK_ESCAPE && e.ctrlKey) {
|
||||||
this.context.store.dispatch(consoleActions.hideCommand());
|
this.props.dispatch(consoleActions.hideCommand());
|
||||||
}
|
}
|
||||||
switch (e.keyCode) {
|
switch (e.keyCode) {
|
||||||
case KeyboardEvent.DOM_VK_ESCAPE:
|
case KeyboardEvent.DOM_VK_ESCAPE:
|
||||||
return this.context.store.dispatch(consoleActions.hideCommand());
|
return this.props.dispatch(consoleActions.hideCommand());
|
||||||
case KeyboardEvent.DOM_VK_RETURN:
|
case KeyboardEvent.DOM_VK_RETURN:
|
||||||
return this.doEnter(e);
|
return this.doEnter(e);
|
||||||
case KeyboardEvent.DOM_VK_TAB:
|
case KeyboardEvent.DOM_VK_TAB:
|
||||||
if (e.shiftKey) {
|
if (e.shiftKey) {
|
||||||
this.context.store.dispatch(consoleActions.completionPrev());
|
this.props.dispatch(consoleActions.completionPrev());
|
||||||
} else {
|
} else {
|
||||||
this.context.store.dispatch(consoleActions.completionNext());
|
this.props.dispatch(consoleActions.completionNext());
|
||||||
}
|
}
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
break;
|
break;
|
||||||
case KeyboardEvent.DOM_VK_OPEN_BRACKET:
|
case KeyboardEvent.DOM_VK_OPEN_BRACKET:
|
||||||
if (e.ctrlKey) {
|
if (e.ctrlKey) {
|
||||||
return this.context.store.dispatch(consoleActions.hideCommand());
|
return this.props.dispatch(consoleActions.hideCommand());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KeyboardEvent.DOM_VK_M:
|
case KeyboardEvent.DOM_VK_M:
|
||||||
|
@ -80,11 +81,11 @@ class ConsoleComponent extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onInput(e) {
|
onChange(e) {
|
||||||
let text = e.target.value;
|
let text = e.target.value;
|
||||||
this.context.store.dispatch(consoleActions.setConsoleText(text));
|
this.props.dispatch(consoleActions.setConsoleText(text));
|
||||||
if (this.props.mode === 'command') {
|
if (this.props.mode === 'command') {
|
||||||
this.context.store.dispatch(consoleActions.getCompletions(text));
|
this.props.dispatch(consoleActions.getCompletions(text));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +95,7 @@ class ConsoleComponent extends Component {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (prevProps.mode !== 'command' && this.props.mode === 'command') {
|
if (prevProps.mode !== 'command' && this.props.mode === 'command') {
|
||||||
this.context.store.dispatch(
|
this.props.dispatch(
|
||||||
consoleActions.getCompletions(this.props.consoleText));
|
consoleActions.getCompletions(this.props.consoleText));
|
||||||
this.focus();
|
this.focus();
|
||||||
} else if (prevProps.mode !== 'find' && this.props.mode === 'find') {
|
} else if (prevProps.mode !== 'find' && this.props.mode === 'find') {
|
||||||
|
@ -117,7 +118,7 @@ class ConsoleComponent extends Component {
|
||||||
mode={this.props.mode}
|
mode={this.props.mode}
|
||||||
onBlur={this.onBlur.bind(this)}
|
onBlur={this.onBlur.bind(this)}
|
||||||
onKeyDown={this.onKeyDown.bind(this)}
|
onKeyDown={this.onKeyDown.bind(this)}
|
||||||
onInput={this.onInput.bind(this)}
|
onChange={this.onChange.bind(this)}
|
||||||
value={this.props.consoleText}
|
value={this.props.consoleText}
|
||||||
/>
|
/>
|
||||||
</div>;
|
</div>;
|
||||||
|
@ -126,6 +127,8 @@ class ConsoleComponent extends Component {
|
||||||
return <Message mode={ this.props.mode } >
|
return <Message mode={ this.props.mode } >
|
||||||
{ this.props.messageText }
|
{ this.props.messageText }
|
||||||
</Message>;
|
</Message>;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,5 +138,12 @@ class ConsoleComponent extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Console.propTypes = {
|
||||||
|
mode: PropTypes.string,
|
||||||
|
consoleText: PropTypes.string,
|
||||||
|
messageText: PropTypes.string,
|
||||||
|
children: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
const mapStateToProps = state => state;
|
const mapStateToProps = state => state;
|
||||||
export default connect(mapStateToProps)(ConsoleComponent);
|
export default connect(mapStateToProps)(Console);
|
|
@ -1,29 +1,9 @@
|
||||||
import { Component, h } from 'preact';
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import CompletionItem from './CompletionItem';
|
||||||
|
import CompletionTitle from './CompletionTitle';
|
||||||
|
|
||||||
const CompletionTitle = (props) => {
|
class Completion extends React.Component {
|
||||||
return <li className='vimvixen-console-completion-title' >{props.title}</li>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const CompletionItem = (props) => {
|
|
||||||
let className = 'vimvixen-console-completion-item';
|
|
||||||
if (props.highlight) {
|
|
||||||
className += ' vimvixen-completion-selected';
|
|
||||||
}
|
|
||||||
return <li
|
|
||||||
className={className}
|
|
||||||
style={{ backgroundImage: 'url(' + props.icon + ')' }}
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className='vimvixen-console-completion-item-caption'
|
|
||||||
>{props.caption}</span>
|
|
||||||
<span
|
|
||||||
className='vimvixen-console-completion-item-url'
|
|
||||||
>{props.url}</span>
|
|
||||||
</li>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class CompletionComponent extends Component {
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.state = { viewOffset: 0, select: -1 };
|
this.state = { viewOffset: 0, select: -1 };
|
||||||
|
@ -63,9 +43,13 @@ class CompletionComponent extends Component {
|
||||||
let index = 0;
|
let index = 0;
|
||||||
|
|
||||||
for (let group of this.props.completions) {
|
for (let group of this.props.completions) {
|
||||||
eles.push(<CompletionTitle title={ group.name }/>);
|
eles.push(<CompletionTitle
|
||||||
|
key={`group-${index}`}
|
||||||
|
title={ group.name }
|
||||||
|
/>);
|
||||||
for (let item of group.items) {
|
for (let item of group.items) {
|
||||||
eles.push(<CompletionItem
|
eles.push(<CompletionItem
|
||||||
|
key={`item-${index}`}
|
||||||
icon={item.icon}
|
icon={item.icon}
|
||||||
caption={item.caption}
|
caption={item.caption}
|
||||||
url={item.url}
|
url={item.url}
|
||||||
|
@ -86,4 +70,17 @@ class CompletionComponent extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CompletionComponent;
|
Completion.propTypes = {
|
||||||
|
select: PropTypes.number,
|
||||||
|
size: PropTypes.number,
|
||||||
|
completions: PropTypes.arrayOf(PropTypes.shape({
|
||||||
|
name: PropTypes.string,
|
||||||
|
items: PropTypes.arrayOf(PropTypes.shape({
|
||||||
|
icon: PropTypes.string,
|
||||||
|
caption: PropTypes.string,
|
||||||
|
url: PropTypes.string,
|
||||||
|
})),
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Completion;
|
28
src/console/components/console/CompletionItem.jsx
Normal file
28
src/console/components/console/CompletionItem.jsx
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const CompletionItem = (props) => {
|
||||||
|
let className = 'vimvixen-console-completion-item';
|
||||||
|
if (props.highlight) {
|
||||||
|
className += ' vimvixen-completion-selected';
|
||||||
|
}
|
||||||
|
return <li
|
||||||
|
className={className}
|
||||||
|
style={{ backgroundImage: 'url(' + props.icon + ')' }}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className='vimvixen-console-completion-item-caption'
|
||||||
|
>{props.caption}</span>
|
||||||
|
<span
|
||||||
|
className='vimvixen-console-completion-item-url'
|
||||||
|
>{props.url}</span>
|
||||||
|
</li>;
|
||||||
|
};
|
||||||
|
|
||||||
|
CompletionItem.propTypes = {
|
||||||
|
highlight: PropTypes.bool,
|
||||||
|
caption: PropTypes.string,
|
||||||
|
url: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CompletionItem;
|
14
src/console/components/console/CompletionTitle.jsx
Normal file
14
src/console/components/console/CompletionTitle.jsx
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const CompletionTitle = (props) => {
|
||||||
|
return <li className='vimvixen-console-completion-title'>
|
||||||
|
{props.title}
|
||||||
|
</li>;
|
||||||
|
};
|
||||||
|
|
||||||
|
CompletionTitle.propTypes = {
|
||||||
|
title: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CompletionTitle;
|
|
@ -1,6 +1,7 @@
|
||||||
import { Component, h } from 'preact';
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
export default class InputComponent extends Component {
|
class Input extends React.Component {
|
||||||
focus() {
|
focus() {
|
||||||
this.input.focus();
|
this.input.focus();
|
||||||
}
|
}
|
||||||
|
@ -23,10 +24,20 @@ export default class InputComponent extends Component {
|
||||||
ref={(c) => { this.input = c; }}
|
ref={(c) => { this.input = c; }}
|
||||||
onBlur={this.props.onBlur}
|
onBlur={this.props.onBlur}
|
||||||
onKeyDown={this.props.onKeyDown}
|
onKeyDown={this.props.onKeyDown}
|
||||||
onInput={this.props.onInput}
|
onChange={this.props.onChange}
|
||||||
value={this.props.value}
|
value={this.props.value}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Input.propTypes = {
|
||||||
|
mode: PropTypes.string,
|
||||||
|
value: PropTypes.string,
|
||||||
|
onBlur: PropTypes.func,
|
||||||
|
onKeyDown: PropTypes.func,
|
||||||
|
onChange: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Input;
|
|
@ -1,6 +1,7 @@
|
||||||
import { h } from 'preact';
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
export default function Message(props) {
|
const Message = (props) => {
|
||||||
switch (props.mode) {
|
switch (props.mode) {
|
||||||
case 'error':
|
case 'error':
|
||||||
return (
|
return (
|
||||||
|
@ -15,4 +16,10 @@ export default function Message(props) {
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
Message.propTypes = {
|
||||||
|
children: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Message;
|
|
@ -5,5 +5,7 @@
|
||||||
<title>VimVixen console</title>
|
<title>VimVixen console</title>
|
||||||
<script src='console.js'></script>
|
<script src='console.js'></script>
|
||||||
</head>
|
</head>
|
||||||
<body class='vimvixen-console'></body>
|
<body>
|
||||||
|
<div id='vimvixen-console' class='vimvixen-console'></div>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -3,11 +3,10 @@ import reducers from 'console/reducers';
|
||||||
import { createStore, applyMiddleware } from 'redux';
|
import { createStore, applyMiddleware } from 'redux';
|
||||||
import promise from 'redux-promise';
|
import promise from 'redux-promise';
|
||||||
import * as consoleActions from 'console/actions/console';
|
import * as consoleActions from 'console/actions/console';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
import { Provider } from 'preact-redux';
|
import Console from './components/Console';
|
||||||
import Console from './components/console';
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
import { render, h } from 'preact';
|
|
||||||
|
|
||||||
const store = createStore(
|
const store = createStore(
|
||||||
reducers,
|
reducers,
|
||||||
|
@ -15,11 +14,12 @@ const store = createStore(
|
||||||
);
|
);
|
||||||
|
|
||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
render(
|
let wrapper = document.getElementById('vimvixen-console');
|
||||||
|
ReactDOM.render(
|
||||||
<Provider store={store} >
|
<Provider store={store} >
|
||||||
<Console></Console>
|
<Console></Console>
|
||||||
</Provider>,
|
</Provider>,
|
||||||
document.body);
|
wrapper);
|
||||||
});
|
});
|
||||||
|
|
||||||
const onMessage = (message) => {
|
const onMessage = (message) => {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import actions from 'settings/actions';
|
import actions from 'settings/actions';
|
||||||
import * as validator from 'shared/settings/validator';
|
import * as validator from 'shared/settings/validator';
|
||||||
import KeymapsForm from '../components/form/keymaps-form';
|
|
||||||
import * as settingsValues from 'shared/settings/values';
|
import * as settingsValues from 'shared/settings/values';
|
||||||
import * as settingsStorage from 'shared/settings/storage';
|
import * as settingsStorage from 'shared/settings/storage';
|
||||||
|
import keymaps from '../keymaps';
|
||||||
|
|
||||||
const load = async() => {
|
const load = async() => {
|
||||||
let settings = await settingsStorage.loadRaw();
|
let settings = await settingsStorage.loadRaw();
|
||||||
|
@ -29,8 +29,7 @@ const save = async(settings) => {
|
||||||
const switchToForm = (json) => {
|
const switchToForm = (json) => {
|
||||||
try {
|
try {
|
||||||
validator.validate(JSON.parse(json));
|
validator.validate(JSON.parse(json));
|
||||||
// AllowdOps filters operations, this is dirty dependency
|
let form = settingsValues.formFromJson(json, keymaps.allowedOps);
|
||||||
let form = settingsValues.formFromJson(json, KeymapsForm.AllowdOps);
|
|
||||||
return {
|
return {
|
||||||
type: actions.SETTING_SWITCH_TO_FORM,
|
type: actions.SETTING_SWITCH_TO_FORM,
|
||||||
form,
|
form,
|
||||||
|
@ -61,4 +60,4 @@ const set = (settings) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export { load, save, switchToForm, switchToJson };
|
export { load, save, set, switchToForm, switchToJson };
|
||||||
|
|
|
@ -1,38 +1,34 @@
|
||||||
import './blacklist-form.scss';
|
import './BlacklistForm.scss';
|
||||||
import AddButton from '../ui/add-button';
|
import AddButton from '../ui/AddButton';
|
||||||
import DeleteButton from '../ui/delete-button';
|
import DeleteButton from '../ui/DeleteButton';
|
||||||
import { h, Component } from 'preact';
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
class BlacklistForm extends Component {
|
class BlacklistForm extends React.Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let value = this.props.value;
|
|
||||||
if (!value) {
|
|
||||||
value = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return <div className='form-blacklist-form'>
|
return <div className='form-blacklist-form'>
|
||||||
{
|
{
|
||||||
value.map((url, index) => {
|
this.props.value.map((url, index) => {
|
||||||
return <div key={index} className='form-blacklist-form-row'>
|
return <div key={index} className='form-blacklist-form-row'>
|
||||||
<input data-index={index} type='text' name='url'
|
<input data-index={index} type='text' name='url'
|
||||||
className='column-url' value={url}
|
className='column-url' value={url}
|
||||||
onChange={this.bindValue.bind(this)} />
|
onChange={this.bindValue.bind(this)}
|
||||||
|
onBlur={this.props.onBlur}
|
||||||
|
/>
|
||||||
<DeleteButton data-index={index} name='delete'
|
<DeleteButton data-index={index} name='delete'
|
||||||
onClick={this.bindValue.bind(this)} />
|
onClick={this.bindValue.bind(this)}
|
||||||
|
onBlur={this.props.onBlur}
|
||||||
|
/>
|
||||||
</div>;
|
</div>;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
<AddButton name='add' style='float:right'
|
<AddButton name='add' style={{ float: 'right' }}
|
||||||
onClick={this.bindValue.bind(this)} />
|
onClick={this.bindValue.bind(this)} />
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
bindValue(e) {
|
bindValue(e) {
|
||||||
if (!this.props.onChange) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let name = e.target.name;
|
let name = e.target.name;
|
||||||
let index = e.target.getAttribute('data-index');
|
let index = e.target.getAttribute('data-index');
|
||||||
let next = this.props.value ? this.props.value.slice() : [];
|
let next = this.props.value ? this.props.value.slice() : [];
|
||||||
|
@ -46,7 +42,22 @@ class BlacklistForm extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.props.onChange(next);
|
this.props.onChange(next);
|
||||||
|
if (name === 'delete') {
|
||||||
|
this.props.onBlur();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BlacklistForm.propTypes = {
|
||||||
|
value: PropTypes.arrayOf(PropTypes.string),
|
||||||
|
onChange: PropTypes.func,
|
||||||
|
onBlur: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
BlacklistForm.defaultProps = {
|
||||||
|
value: [],
|
||||||
|
onChange: () => {},
|
||||||
|
onBlur: () => {},
|
||||||
|
};
|
||||||
|
|
||||||
export default BlacklistForm;
|
export default BlacklistForm;
|
51
src/settings/components/form/KeymapsForm.jsx
Normal file
51
src/settings/components/form/KeymapsForm.jsx
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import './KeymapsForm.scss';
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import Input from '../ui/Input';
|
||||||
|
import keymaps from '../../keymaps';
|
||||||
|
|
||||||
|
class KeymapsForm extends React.Component {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <div className='form-keymaps-form'>
|
||||||
|
{
|
||||||
|
keymaps.fields.map((group, index) => {
|
||||||
|
return <div key={index} className='form-keymaps-form-field-group'>
|
||||||
|
{
|
||||||
|
group.map((field) => {
|
||||||
|
let name = field[0];
|
||||||
|
let label = field[1];
|
||||||
|
let value = this.props.value[name] || '';
|
||||||
|
return <Input
|
||||||
|
type='text' id={name} name={name} key={name}
|
||||||
|
label={label} value={value}
|
||||||
|
onChange={this.bindValue.bind(this)}
|
||||||
|
onBlur={this.props.onBlur}
|
||||||
|
/>;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
bindValue(e) {
|
||||||
|
let next = { ...this.props.value };
|
||||||
|
next[e.target.name] = e.target.value;
|
||||||
|
|
||||||
|
this.props.onChange(next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeymapsForm.propTypes = {
|
||||||
|
value: PropTypes.objectOf(PropTypes.string),
|
||||||
|
onChange: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
KeymapsForm.defaultProps = {
|
||||||
|
value: {},
|
||||||
|
onChange: () => {},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default KeymapsForm;
|
|
@ -1,14 +1,12 @@
|
||||||
import './properties-form.scss';
|
import './PropertiesForm.scss';
|
||||||
import { h, Component } from 'preact';
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
class PropertiesForm extends Component {
|
class PropertiesForm extends React.Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let types = this.props.types;
|
let types = this.props.types;
|
||||||
let value = this.props.value;
|
let value = this.props.value;
|
||||||
if (!value) {
|
|
||||||
value = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return <div className='form-properties-form'>
|
return <div className='form-properties-form'>
|
||||||
{
|
{
|
||||||
|
@ -29,6 +27,7 @@ class PropertiesForm extends Component {
|
||||||
className='column-input'
|
className='column-input'
|
||||||
value={value[name] ? value[name] : ''}
|
value={value[name] ? value[name] : ''}
|
||||||
onChange={this.bindValue.bind(this)}
|
onChange={this.bindValue.bind(this)}
|
||||||
|
onBlur={this.props.onBlur}
|
||||||
checked={value[name]}
|
checked={value[name]}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
@ -39,10 +38,6 @@ class PropertiesForm extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
bindValue(e) {
|
bindValue(e) {
|
||||||
if (!this.props.onChange) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let name = e.target.name;
|
let name = e.target.name;
|
||||||
let next = { ...this.props.value };
|
let next = { ...this.props.value };
|
||||||
if (e.target.type.toLowerCase() === 'checkbox') {
|
if (e.target.type.toLowerCase() === 'checkbox') {
|
||||||
|
@ -57,4 +52,14 @@ class PropertiesForm extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PropertiesForm.propTypes = {
|
||||||
|
value: PropTypes.objectOf(PropTypes.any),
|
||||||
|
onChange: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
PropertiesForm.defaultProps = {
|
||||||
|
value: {},
|
||||||
|
onChange: () => {},
|
||||||
|
};
|
||||||
|
|
||||||
export default PropertiesForm;
|
export default PropertiesForm;
|
|
@ -1,15 +1,13 @@
|
||||||
import './search-form.scss';
|
import './SearchForm.scss';
|
||||||
import { h, Component } from 'preact';
|
import React from 'react';
|
||||||
import AddButton from '../ui/add-button';
|
import PropTypes from 'prop-types';
|
||||||
import DeleteButton from '../ui/delete-button';
|
import AddButton from '../ui/AddButton';
|
||||||
|
import DeleteButton from '../ui/DeleteButton';
|
||||||
|
|
||||||
class SearchForm extends Component {
|
class SearchForm extends React.Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let value = this.props.value;
|
let value = this.props.value;
|
||||||
if (!value) {
|
|
||||||
value = { default: '', engines: []};
|
|
||||||
}
|
|
||||||
if (!value.engines) {
|
if (!value.engines) {
|
||||||
value.engines = [];
|
value.engines = [];
|
||||||
}
|
}
|
||||||
|
@ -25,11 +23,15 @@ class SearchForm extends Component {
|
||||||
return <div key={index} className='form-search-form-row'>
|
return <div key={index} className='form-search-form-row'>
|
||||||
<input data-index={index} type='text' name='name'
|
<input data-index={index} type='text' name='name'
|
||||||
className='column-name' value={engine[0]}
|
className='column-name' value={engine[0]}
|
||||||
onChange={this.bindValue.bind(this)} />
|
onChange={this.bindValue.bind(this)}
|
||||||
|
onBlur={this.props.onBlur}
|
||||||
|
/>
|
||||||
<input data-index={index} type='text' name='url'
|
<input data-index={index} type='text' name='url'
|
||||||
placeholder='http://example.com/?q={}'
|
placeholder='http://example.com/?q={}'
|
||||||
className='column-url' value={engine[1]}
|
className='column-url' value={engine[1]}
|
||||||
onChange={this.bindValue.bind(this)} />
|
onChange={this.bindValue.bind(this)}
|
||||||
|
onBlur={this.props.onBlur}
|
||||||
|
/>
|
||||||
<div className='column-option'>
|
<div className='column-option'>
|
||||||
<input data-index={index} type='radio' name='default'
|
<input data-index={index} type='radio' name='default'
|
||||||
checked={value.default === engine[0]}
|
checked={value.default === engine[0]}
|
||||||
|
@ -40,16 +42,12 @@ class SearchForm extends Component {
|
||||||
</div>;
|
</div>;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
<AddButton name='add' style='float:right'
|
<AddButton name='add' style={{ float: 'right' }}
|
||||||
onClick={this.bindValue.bind(this)} />
|
onClick={this.bindValue.bind(this)} />
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
bindValue(e) {
|
bindValue(e) {
|
||||||
if (!this.props.onChange) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let value = this.props.value;
|
let value = this.props.value;
|
||||||
let name = e.target.name;
|
let name = e.target.name;
|
||||||
let index = e.target.getAttribute('data-index');
|
let index = e.target.getAttribute('data-index');
|
||||||
|
@ -72,7 +70,23 @@ class SearchForm extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.props.onChange(next);
|
this.props.onChange(next);
|
||||||
|
if (name === 'delete' || name === 'default') {
|
||||||
|
this.props.onBlur();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SearchForm.propTypes = {
|
||||||
|
value: PropTypes.shape({
|
||||||
|
default: PropTypes.string,
|
||||||
|
engines: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.string)),
|
||||||
|
}),
|
||||||
|
onChange: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
SearchForm.defaultProps = {
|
||||||
|
value: { default: '', engines: []},
|
||||||
|
onChange: () => {},
|
||||||
|
};
|
||||||
|
|
||||||
export default SearchForm;
|
export default SearchForm;
|
|
@ -1,11 +1,11 @@
|
||||||
import './site.scss';
|
import './site.scss';
|
||||||
import { h, Component } from 'preact';
|
import React from 'react';
|
||||||
import { connect } from 'preact-redux';
|
import { connect } from 'react-redux';
|
||||||
import Input from './ui/input';
|
import Input from './ui/Input';
|
||||||
import SearchForm from './form/search-form';
|
import SearchForm from './form/SearchForm';
|
||||||
import KeymapsForm from './form/keymaps-form';
|
import KeymapsForm from './form/KeymapsForm';
|
||||||
import BlacklistForm from './form/blacklist-form';
|
import BlacklistForm from './form/BlacklistForm';
|
||||||
import PropertiesForm from './form/properties-form';
|
import PropertiesForm from './form/PropertiesForm';
|
||||||
import * as properties from 'shared/settings/properties';
|
import * as properties from 'shared/settings/properties';
|
||||||
import * as settingActions from 'settings/actions/setting';
|
import * as settingActions from 'settings/actions/setting';
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ const DO_YOU_WANT_TO_CONTINUE =
|
||||||
'Some settings in JSON can be lost when migrating. ' +
|
'Some settings in JSON can be lost when migrating. ' +
|
||||||
'Do you want to continue?';
|
'Do you want to continue?';
|
||||||
|
|
||||||
class SettingsComponent extends Component {
|
class SettingsComponent extends React.Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.props.dispatch(settingActions.load());
|
this.props.dispatch(settingActions.load());
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ class SettingsComponent extends Component {
|
||||||
<KeymapsForm
|
<KeymapsForm
|
||||||
value={form.keymaps}
|
value={form.keymaps}
|
||||||
onChange={value => this.bindForm('keymaps', value)}
|
onChange={value => this.bindForm('keymaps', value)}
|
||||||
|
onBlur={this.save.bind(this)}
|
||||||
/>
|
/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
|
@ -32,6 +33,7 @@ class SettingsComponent extends Component {
|
||||||
<SearchForm
|
<SearchForm
|
||||||
value={form.search}
|
value={form.search}
|
||||||
onChange={value => this.bindForm('search', value)}
|
onChange={value => this.bindForm('search', value)}
|
||||||
|
onBlur={this.save.bind(this)}
|
||||||
/>
|
/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
|
@ -39,6 +41,7 @@ class SettingsComponent extends Component {
|
||||||
<BlacklistForm
|
<BlacklistForm
|
||||||
value={form.blacklist}
|
value={form.blacklist}
|
||||||
onChange={value => this.bindForm('blacklist', value)}
|
onChange={value => this.bindForm('blacklist', value)}
|
||||||
|
onBlur={this.save.bind(this)}
|
||||||
/>
|
/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
|
@ -47,6 +50,7 @@ class SettingsComponent extends Component {
|
||||||
types={properties.types}
|
types={properties.types}
|
||||||
value={form.properties}
|
value={form.properties}
|
||||||
onChange={value => this.bindForm('properties', value)}
|
onChange={value => this.bindForm('properties', value)}
|
||||||
|
onBlur={this.save.bind(this)}
|
||||||
/>
|
/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>;
|
</div>;
|
||||||
|
@ -61,6 +65,7 @@ class SettingsComponent extends Component {
|
||||||
spellCheck='false'
|
spellCheck='false'
|
||||||
error={error}
|
error={error}
|
||||||
onChange={this.bindJson.bind(this)}
|
onChange={this.bindJson.bind(this)}
|
||||||
|
onBlur={this.save.bind(this)}
|
||||||
value={json}
|
value={json}
|
||||||
/>
|
/>
|
||||||
</div>;
|
</div>;
|
||||||
|
@ -109,7 +114,7 @@ class SettingsComponent extends Component {
|
||||||
form: { ...this.props.form },
|
form: { ...this.props.form },
|
||||||
};
|
};
|
||||||
settings.form[name] = value;
|
settings.form[name] = value;
|
||||||
this.props.dispatch(settingActions.save(settings));
|
this.props.dispatch(settingActions.set(settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
bindJson(e) {
|
bindJson(e) {
|
||||||
|
@ -118,7 +123,7 @@ class SettingsComponent extends Component {
|
||||||
json: e.target.value,
|
json: e.target.value,
|
||||||
form: this.props.form,
|
form: this.props.form,
|
||||||
};
|
};
|
||||||
this.props.dispatch(settingActions.save(settings));
|
this.props.dispatch(settingActions.set(settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
bindSource(e) {
|
bindSource(e) {
|
||||||
|
@ -135,8 +140,10 @@ class SettingsComponent extends Component {
|
||||||
}
|
}
|
||||||
this.props.dispatch(settingActions.switchToForm(this.props.json));
|
this.props.dispatch(settingActions.switchToForm(this.props.json));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let settings = this.context.store.getState();
|
save() {
|
||||||
|
let settings = this.props.store.getState();
|
||||||
this.props.dispatch(settingActions.save(settings));
|
this.props.dispatch(settingActions.save(settings));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import './add-button.scss';
|
import './AddButton.scss';
|
||||||
import { h, Component } from 'preact';
|
import React from 'react';
|
||||||
|
|
||||||
class AddButton extends Component {
|
class AddButton extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return <input
|
return <input
|
||||||
className='ui-add-button' type='button' value='✚'
|
className='ui-add-button' type='button' value='✚'
|
|
@ -1,7 +1,7 @@
|
||||||
import './delete-button.scss';
|
import './DeleteButton.scss';
|
||||||
import { h, Component } from 'preact';
|
import React from 'react';
|
||||||
|
|
||||||
class DeleteButton extends Component {
|
class DeleteButton extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return <input
|
return <input
|
||||||
className='ui-delete-button' type='button' value='✖'
|
className='ui-delete-button' type='button' value='✖'
|
|
@ -1,7 +1,8 @@
|
||||||
import { h, Component } from 'preact';
|
import React from 'react';
|
||||||
import './input.scss';
|
import PropTypes from 'prop-types';
|
||||||
|
import './Input.scss';
|
||||||
|
|
||||||
class Input extends Component {
|
class Input extends React.Component {
|
||||||
|
|
||||||
renderText(props) {
|
renderText(props) {
|
||||||
let inputClassName = props.error ? 'input-error' : '';
|
let inputClassName = props.error ? 'input-error' : '';
|
||||||
|
@ -49,4 +50,11 @@ class Input extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Input.propTypes = {
|
||||||
|
type: PropTypes.string,
|
||||||
|
error: PropTypes.string,
|
||||||
|
label: PropTypes.string,
|
||||||
|
value: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
export default Input;
|
export default Input;
|
|
@ -1,7 +1,8 @@
|
||||||
import { h, render } from 'preact';
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
import SettingsComponent from './components';
|
import SettingsComponent from './components';
|
||||||
import reducer from './reducers/setting';
|
import reducer from './reducers/setting';
|
||||||
import { Provider } from 'preact-redux';
|
import { Provider } from 'react-redux';
|
||||||
import promise from 'redux-promise';
|
import promise from 'redux-promise';
|
||||||
import { createStore, applyMiddleware } from 'redux';
|
import { createStore, applyMiddleware } from 'redux';
|
||||||
|
|
||||||
|
@ -12,9 +13,9 @@ const store = createStore(
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
let wrapper = document.getElementById('vimvixen-settings');
|
let wrapper = document.getElementById('vimvixen-settings');
|
||||||
render(
|
ReactDOM.render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<SettingsComponent />
|
<SettingsComponent store={store} />
|
||||||
</Provider>,
|
</Provider>,
|
||||||
wrapper
|
wrapper
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
import './keymaps-form.scss';
|
const fields = [
|
||||||
import { h, Component } from 'preact';
|
|
||||||
import Input from '../ui/input';
|
|
||||||
|
|
||||||
const KeyMapFields = [
|
|
||||||
[
|
[
|
||||||
['scroll.vertically?{"count":1}', 'Scroll down'],
|
['scroll.vertically?{"count":1}', 'Scroll down'],
|
||||||
['scroll.vertically?{"count":-1}', 'Scroll up'],
|
['scroll.vertically?{"count":-1}', 'Scroll up'],
|
||||||
|
@ -70,49 +66,9 @@ const KeyMapFields = [
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
const AllowdOps = [].concat(...KeyMapFields.map(group => group.map(e => e[0])));
|
const allowedOps = [].concat(...fields.map(group => group.map(e => e[0])));
|
||||||
|
|
||||||
class KeymapsForm extends Component {
|
export default {
|
||||||
|
fields,
|
||||||
render() {
|
allowedOps,
|
||||||
let values = this.props.value;
|
};
|
||||||
if (!values) {
|
|
||||||
values = {};
|
|
||||||
}
|
|
||||||
return <div className='form-keymaps-form'>
|
|
||||||
{
|
|
||||||
KeyMapFields.map((group, index) => {
|
|
||||||
return <div key={index} className='form-keymaps-form-field-group'>
|
|
||||||
{
|
|
||||||
group.map((field) => {
|
|
||||||
let name = field[0];
|
|
||||||
let label = field[1];
|
|
||||||
let value = values[name];
|
|
||||||
return <Input
|
|
||||||
type='text' id={name} name={name} key={name}
|
|
||||||
label={label} value={value}
|
|
||||||
onChange={this.bindValue.bind(this)}
|
|
||||||
/>;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
bindValue(e) {
|
|
||||||
if (!this.props.onChange) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let next = { ...this.props.value };
|
|
||||||
next[e.target.name] = e.target.value;
|
|
||||||
|
|
||||||
this.props.onChange(next);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KeymapsForm.AllowdOps = AllowdOps;
|
|
||||||
|
|
||||||
export default KeymapsForm;
|
|
168
test/console/components/console/Completion.test.jsx
Normal file
168
test/console/components/console/Completion.test.jsx
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
import React from 'react';
|
||||||
|
import Completion from 'console/components/console/Completion'
|
||||||
|
import ReactTestRenderer from 'react-test-renderer';
|
||||||
|
|
||||||
|
describe("console/components/console/completion", () => {
|
||||||
|
let completions = [{
|
||||||
|
name: "Fruit",
|
||||||
|
items: [{ caption: "apple" }, { caption: "banana" }, { caption: "cherry" }],
|
||||||
|
}, {
|
||||||
|
name: "Element",
|
||||||
|
items: [{ caption: "argon" }, { caption: "boron" }, { caption: "carbon" }],
|
||||||
|
}];
|
||||||
|
|
||||||
|
it('renders Completion component', () => {
|
||||||
|
let root = ReactTestRenderer.create(<Completion
|
||||||
|
completions={completions}
|
||||||
|
size={30}
|
||||||
|
/>).root;
|
||||||
|
|
||||||
|
expect(root.children).to.have.lengthOf(1);
|
||||||
|
|
||||||
|
let children = root.children[0].children;
|
||||||
|
expect(children).to.have.lengthOf(8);
|
||||||
|
expect(children[0].props.title).to.equal('Fruit');
|
||||||
|
expect(children[1].props.caption).to.equal('apple');
|
||||||
|
expect(children[2].props.caption).to.equal('banana');
|
||||||
|
expect(children[3].props.caption).to.equal('cherry');
|
||||||
|
expect(children[4].props.title).to.equal('Element');
|
||||||
|
expect(children[5].props.caption).to.equal('argon');
|
||||||
|
expect(children[6].props.caption).to.equal('boron');
|
||||||
|
expect(children[7].props.caption).to.equal('carbon');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('highlight current item', () => {
|
||||||
|
let root = ReactTestRenderer.create(<Completion
|
||||||
|
completions={completions}
|
||||||
|
size={30}
|
||||||
|
select={3}
|
||||||
|
/>).root;
|
||||||
|
|
||||||
|
let children = root.children[0].children;
|
||||||
|
expect(children[5].props.highlight).to.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not highlight any items', () => {
|
||||||
|
let root = ReactTestRenderer.create(<Completion
|
||||||
|
completions={completions}
|
||||||
|
size={30}
|
||||||
|
select={-1}
|
||||||
|
/>).root;
|
||||||
|
|
||||||
|
let children = root.children[0].children;
|
||||||
|
for (let li of children[0].children) {
|
||||||
|
expect(li.props.highlight).not.to.be.ok;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('limits completion items', () => {
|
||||||
|
let root = ReactTestRenderer.create(<Completion
|
||||||
|
completions={completions}
|
||||||
|
size={3}
|
||||||
|
select={-1}
|
||||||
|
/>).root;
|
||||||
|
|
||||||
|
let children = root.children[0].children;
|
||||||
|
expect(children).to.have.lengthOf(3);
|
||||||
|
|
||||||
|
expect(children[0].props.title).to.equal('Fruit');
|
||||||
|
expect(children[1].props.caption).to.equal('apple');
|
||||||
|
expect(children[2].props.caption).to.equal('banana');
|
||||||
|
|
||||||
|
root = ReactTestRenderer.create(<Completion
|
||||||
|
completions={completions}
|
||||||
|
size={3} select={0}
|
||||||
|
/>).root;
|
||||||
|
|
||||||
|
children = root.children[0].children;
|
||||||
|
expect(children[1].props.highlight).to.be.true;
|
||||||
|
})
|
||||||
|
|
||||||
|
it('scrolls up to down with select', () => {
|
||||||
|
let component = ReactTestRenderer.create(<Completion
|
||||||
|
completions={completions}
|
||||||
|
size={3}
|
||||||
|
select={1}
|
||||||
|
/>);
|
||||||
|
let instance = component.getInstance();
|
||||||
|
let root = component.root;
|
||||||
|
|
||||||
|
let children = root.children[0].children;
|
||||||
|
expect(children).to.have.lengthOf(3);
|
||||||
|
expect(children[0].props.title).to.equal('Fruit');
|
||||||
|
expect(children[1].props.caption).to.equal('apple');
|
||||||
|
expect(children[2].props.caption).to.equal('banana');
|
||||||
|
|
||||||
|
component.update(<Completion
|
||||||
|
completions={completions}
|
||||||
|
size={3}
|
||||||
|
select={2}
|
||||||
|
/>);
|
||||||
|
|
||||||
|
children = root.children[0].children;
|
||||||
|
expect(children).to.have.lengthOf(3);
|
||||||
|
expect(children[0].props.caption).to.equal('apple');
|
||||||
|
expect(children[1].props.caption).to.equal('banana');
|
||||||
|
expect(children[2].props.caption).to.equal('cherry');
|
||||||
|
expect(children[2].props.highlight).to.be.true;
|
||||||
|
|
||||||
|
component.update(<Completion
|
||||||
|
completions={completions}
|
||||||
|
size={3}
|
||||||
|
select={3}
|
||||||
|
/>);
|
||||||
|
|
||||||
|
children = root.children[0].children;
|
||||||
|
expect(children).to.have.lengthOf(3);
|
||||||
|
expect(children[0].props.caption).to.equal('cherry');
|
||||||
|
expect(children[1].props.title).to.equal('Element');
|
||||||
|
expect(children[2].props.caption).to.equal('argon');
|
||||||
|
expect(children[2].props.highlight).to.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('scrolls down to up with select', () => {
|
||||||
|
let component = ReactTestRenderer.create(<Completion
|
||||||
|
completions={completions}
|
||||||
|
size={3}
|
||||||
|
select={5}
|
||||||
|
/>);
|
||||||
|
let root = component.root;
|
||||||
|
let instance = component.getInstance();
|
||||||
|
|
||||||
|
let children = root.children[0].children;
|
||||||
|
expect(children).to.have.lengthOf(3);
|
||||||
|
expect(children[0].props.caption).to.equal('argon');
|
||||||
|
expect(children[1].props.caption).to.equal('boron');
|
||||||
|
expect(children[2].props.caption).to.equal('carbon');
|
||||||
|
|
||||||
|
component.update(<Completion
|
||||||
|
completions={completions}
|
||||||
|
size={3}
|
||||||
|
select={4}
|
||||||
|
/>);
|
||||||
|
|
||||||
|
children = root.children[0].children;
|
||||||
|
expect(children[1].props.highlight).to.be.true;
|
||||||
|
|
||||||
|
component.update(<Completion
|
||||||
|
completions={completions}
|
||||||
|
size={3}
|
||||||
|
select={3}
|
||||||
|
/>);
|
||||||
|
|
||||||
|
children = root.children[0].children;
|
||||||
|
expect(children[0].props.highlight).to.be.true;
|
||||||
|
|
||||||
|
component.update(<Completion
|
||||||
|
completions={completions}
|
||||||
|
size={3}
|
||||||
|
select={2}
|
||||||
|
/>);
|
||||||
|
|
||||||
|
children = root.children[0].children;
|
||||||
|
expect(children[0].props.caption).to.equal('cherry');
|
||||||
|
expect(children[1].props.title).to.equal('Element');
|
||||||
|
expect(children[2].props.caption).to.equal('argon');
|
||||||
|
expect(children[0].props.highlight).to.be.true;
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,138 +0,0 @@
|
||||||
import { h, render } from 'preact';
|
|
||||||
import Completion from 'console/components/console/completion'
|
|
||||||
|
|
||||||
describe("console/components/console/completion", () => {
|
|
||||||
let completions = [{
|
|
||||||
name: "Fruit",
|
|
||||||
items: [{ caption: "apple" }, { caption: "banana" }, { caption: "cherry" }],
|
|
||||||
}, {
|
|
||||||
name: "Element",
|
|
||||||
items: [{ caption: "argon" }, { caption: "boron" }, { caption: "carbon" }],
|
|
||||||
}];
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
document.body.innerHTML = '';
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders Completion component', () => {
|
|
||||||
let ul = render(<Completion
|
|
||||||
completions={completions}
|
|
||||||
size={30}
|
|
||||||
/>, document.body);
|
|
||||||
|
|
||||||
expect(ul.children).to.have.lengthOf(8);
|
|
||||||
expect(ul.children[0].textContent).to.equal('Fruit');
|
|
||||||
expect(ul.children[1].textContent).to.equal('apple');
|
|
||||||
expect(ul.children[2].textContent).to.equal('banana');
|
|
||||||
expect(ul.children[3].textContent).to.equal('cherry');
|
|
||||||
expect(ul.children[4].textContent).to.equal('Element');
|
|
||||||
expect(ul.children[5].textContent).to.equal('argon');
|
|
||||||
expect(ul.children[6].textContent).to.equal('boron');
|
|
||||||
expect(ul.children[7].textContent).to.equal('carbon');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('highlight current item', () => {
|
|
||||||
let ul = render(<Completion
|
|
||||||
completions={completions}
|
|
||||||
size={30}
|
|
||||||
select={3}
|
|
||||||
/>, document.body);
|
|
||||||
expect(ul.children[5].className.split(' ')).to.include('vimvixen-completion-selected');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('does not highlight any items', () => {
|
|
||||||
let ul = render(<Completion
|
|
||||||
completions={completions}
|
|
||||||
size={30}
|
|
||||||
select={-1}
|
|
||||||
/>, document.body);
|
|
||||||
for (let li of ul.children) {
|
|
||||||
expect(li.className.split(' ')).not.to.include('vimvixen-completion-selected');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('limits completion items', () => {
|
|
||||||
let ul = render(<Completion
|
|
||||||
completions={completions}
|
|
||||||
size={3}
|
|
||||||
select={-1}
|
|
||||||
/>, document.body);
|
|
||||||
expect(Array.from(ul.children).map(e => e.textContent)).to.deep.equal(['Fruit', 'apple', 'banana']);
|
|
||||||
|
|
||||||
ul = render(<Completion
|
|
||||||
completions={completions}
|
|
||||||
size={3} select={0}
|
|
||||||
/>, document.body, ul);
|
|
||||||
|
|
||||||
expect(Array.from(ul.children).map(e => e.textContent)).to.deep.equal(['Fruit', 'apple', 'banana']);
|
|
||||||
expect(ul.children[1].className.split(' ')).to.include('vimvixen-completion-selected');
|
|
||||||
})
|
|
||||||
|
|
||||||
it('scrolls up to down with select', () => {
|
|
||||||
let ul = render(<Completion
|
|
||||||
completions={completions}
|
|
||||||
size={3}
|
|
||||||
select={1}
|
|
||||||
/>, document.body);
|
|
||||||
|
|
||||||
expect(Array.from(ul.children).map(e => e.textContent)).to.deep.equal(['Fruit', 'apple', 'banana']);
|
|
||||||
expect(ul.children[2].className.split(' ')).to.include('vimvixen-completion-selected');
|
|
||||||
|
|
||||||
ul = render(<Completion
|
|
||||||
completions={completions}
|
|
||||||
size={3}
|
|
||||||
select={2}
|
|
||||||
/>, document.body, ul);
|
|
||||||
|
|
||||||
expect(Array.from(ul.children).map(e => e.textContent)).to.deep.equal(['apple', 'banana', 'cherry']);
|
|
||||||
expect(ul.children[2].className.split(' ')).to.include('vimvixen-completion-selected');
|
|
||||||
|
|
||||||
ul = render(<Completion
|
|
||||||
completions={completions}
|
|
||||||
size={3}
|
|
||||||
select={3}
|
|
||||||
/>, document.body, ul);
|
|
||||||
|
|
||||||
expect(Array.from(ul.children).map(e => e.textContent)).to.deep.equal(['cherry', 'Element', 'argon']);
|
|
||||||
expect(ul.children[2].className.split(' ')).to.include('vimvixen-completion-selected');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('scrolls up to down with select', () => {
|
|
||||||
let ul = render(<Completion
|
|
||||||
completions={completions}
|
|
||||||
size={3}
|
|
||||||
select={5}
|
|
||||||
/>, document.body);
|
|
||||||
|
|
||||||
expect(Array.from(ul.children).map(e => e.textContent)).to.deep.equal(['argon', 'boron', 'carbon']);
|
|
||||||
expect(ul.children[2].className.split(' ')).to.include('vimvixen-completion-selected');
|
|
||||||
|
|
||||||
ul = render(<Completion
|
|
||||||
completions={completions}
|
|
||||||
size={3}
|
|
||||||
select={4}
|
|
||||||
/>, document.body, ul);
|
|
||||||
|
|
||||||
expect(Array.from(ul.children).map(e => e.textContent)).to.deep.equal(['argon', 'boron', 'carbon']);
|
|
||||||
expect(ul.children[1].className.split(' ')).to.include('vimvixen-completion-selected');
|
|
||||||
|
|
||||||
ul = render(<Completion
|
|
||||||
completions={completions}
|
|
||||||
size={3}
|
|
||||||
select={3}
|
|
||||||
/>, document.body, ul);
|
|
||||||
|
|
||||||
expect(Array.from(ul.children).map(e => e.textContent)).to.deep.equal(['argon', 'boron', 'carbon']);
|
|
||||||
expect(ul.children[0].className.split(' ')).to.include('vimvixen-completion-selected');
|
|
||||||
|
|
||||||
ul = render(<Completion
|
|
||||||
completions={completions}
|
|
||||||
size={3}
|
|
||||||
select={2}
|
|
||||||
/>, document.body, ul);
|
|
||||||
|
|
||||||
expect(Array.from(ul.children).map(e => e.textContent)).to.deep.equal(['cherry', 'Element', 'argon']);
|
|
||||||
expect(ul.children[0].className.split(' ')).to.include('vimvixen-completion-selected');
|
|
||||||
});
|
|
||||||
});
|
|
92
test/settings/components/form/BlacklistForm.test.jsx
Normal file
92
test/settings/components/form/BlacklistForm.test.jsx
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import ReactTestRenderer from 'react-test-renderer';
|
||||||
|
import ReactTestUtils from 'react-dom/test-utils';
|
||||||
|
import BlacklistForm from 'settings/components/form/BlacklistForm'
|
||||||
|
|
||||||
|
describe("settings/form/BlacklistForm", () => {
|
||||||
|
describe('render', () => {
|
||||||
|
it('renders BlacklistForm', () => {
|
||||||
|
let root = ReactTestRenderer.create(
|
||||||
|
<BlacklistForm value={['*.slack.com', 'www.google.com/maps']} />,
|
||||||
|
).root;
|
||||||
|
|
||||||
|
let children = root.children[0].children;
|
||||||
|
expect(children).to.have.lengthOf(3);
|
||||||
|
expect(children[0].children[0].props.value).to.equal('*.slack.com');
|
||||||
|
expect(children[1].children[0].props.value).to.equal('www.google.com/maps');
|
||||||
|
expect(children[2].props.name).to.equal('add');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders blank value', () => {
|
||||||
|
let root = ReactTestRenderer.create(<BlacklistForm />).root;
|
||||||
|
|
||||||
|
let children = root.children[0].children;
|
||||||
|
expect(children).to.have.lengthOf(1);
|
||||||
|
expect(children[0].props.name).to.equal('add');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onChange', () => {
|
||||||
|
let container;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
container = document.createElement('div');
|
||||||
|
document.body.appendChild(container);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
document.body.removeChild(container);
|
||||||
|
container = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('invokes onChange event on edit', (done) => {
|
||||||
|
ReactTestUtils.act(() => {
|
||||||
|
ReactDOM.render(<BlacklistForm
|
||||||
|
value={['*.slack.com', 'www.google.com/maps*']}
|
||||||
|
onChange={value => {
|
||||||
|
expect(value).to.have.lengthOf(2);
|
||||||
|
expect(value).to.have.members(['gitter.im', 'www.google.com/maps*']);
|
||||||
|
done();
|
||||||
|
}}
|
||||||
|
/>, container)
|
||||||
|
});
|
||||||
|
|
||||||
|
let input = document.querySelectorAll('input[type=text]')[0];
|
||||||
|
input.value = 'gitter.im';
|
||||||
|
ReactTestUtils.Simulate.change(input);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('invokes onChange event on delete', (done) => {
|
||||||
|
ReactTestUtils.act(() => {
|
||||||
|
ReactDOM.render(<BlacklistForm
|
||||||
|
value={['*.slack.com', 'www.google.com/maps*']}
|
||||||
|
onChange={value => {
|
||||||
|
expect(value).to.have.lengthOf(1);
|
||||||
|
expect(value).to.have.members(['www.google.com/maps*']);
|
||||||
|
done();
|
||||||
|
}}
|
||||||
|
/>, container)
|
||||||
|
});
|
||||||
|
|
||||||
|
let button = document.querySelectorAll('input[type=button]')[0];
|
||||||
|
ReactTestUtils.Simulate.click(button);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('invokes onChange event on add', (done) => {
|
||||||
|
ReactTestUtils.act(() => {
|
||||||
|
ReactDOM.render(<BlacklistForm
|
||||||
|
value={['*.slack.com']}
|
||||||
|
onChange={value => {
|
||||||
|
expect(value).to.have.lengthOf(2);
|
||||||
|
expect(value).to.have.members(['*.slack.com', '']);
|
||||||
|
done();
|
||||||
|
}}
|
||||||
|
/>, container);
|
||||||
|
});
|
||||||
|
|
||||||
|
let button = document.querySelector('input[type=button].ui-add-button');
|
||||||
|
ReactTestUtils.Simulate.click(button);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
64
test/settings/components/form/KeymapsForm.test.jsx
Normal file
64
test/settings/components/form/KeymapsForm.test.jsx
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import ReactTestRenderer from 'react-test-renderer';
|
||||||
|
import ReactTestUtils from 'react-dom/test-utils';
|
||||||
|
import KeymapsForm from 'settings/components/form/KeymapsForm'
|
||||||
|
|
||||||
|
describe("settings/form/KeymapsForm", () => {
|
||||||
|
describe('render', () => {
|
||||||
|
it('renders keymap fields', () => {
|
||||||
|
let root = ReactTestRenderer.create(<KeymapsForm value={{
|
||||||
|
'scroll.vertically?{"count":1}': 'j',
|
||||||
|
'scroll.vertically?{"count":-1}': 'k',
|
||||||
|
}} />).root
|
||||||
|
|
||||||
|
let inputj = root.findByProps({ id: 'scroll.vertically?{"count":1}' });
|
||||||
|
let inputk = root.findByProps({ id: 'scroll.vertically?{"count":-1}' });
|
||||||
|
|
||||||
|
expect(inputj.props.value).to.equal('j');
|
||||||
|
expect(inputk.props.value).to.equal('k');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders blank value', () => {
|
||||||
|
let root = ReactTestRenderer.create(<KeymapsForm />).root;
|
||||||
|
|
||||||
|
let inputj = root.findByProps({ id: 'scroll.vertically?{"count":1}' });
|
||||||
|
let inputk = root.findByProps({ id: 'scroll.vertically?{"count":-1}' });
|
||||||
|
|
||||||
|
expect(inputj.props.value).to.be.empty;
|
||||||
|
expect(inputk.props.value).to.be.empty;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onChange event', () => {
|
||||||
|
let container;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
container = document.createElement('div');
|
||||||
|
document.body.appendChild(container);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
document.body.removeChild(container);
|
||||||
|
container = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('invokes onChange event on edit', (done) => {
|
||||||
|
ReactTestUtils.act(() => {
|
||||||
|
ReactDOM.render(<KeymapsForm
|
||||||
|
value={{
|
||||||
|
'scroll.vertically?{"count":1}': 'j',
|
||||||
|
'scroll.vertically?{"count":-1}': 'k',
|
||||||
|
}}
|
||||||
|
onChange={value => {
|
||||||
|
expect(value['scroll.vertically?{"count":1}']).to.equal('jjj');
|
||||||
|
done();
|
||||||
|
}} />, container);
|
||||||
|
});
|
||||||
|
|
||||||
|
let input = document.getElementById('scroll.vertically?{"count":1}');
|
||||||
|
input.value = 'jjj';
|
||||||
|
ReactTestUtils.Simulate.change(input);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
104
test/settings/components/form/PropertiesForm.test.jsx
Normal file
104
test/settings/components/form/PropertiesForm.test.jsx
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import ReactTestRenderer from 'react-test-renderer';
|
||||||
|
import ReactTestUtils from 'react-dom/test-utils';
|
||||||
|
import PropertiesForm from 'settings/components/form/PropertiesForm'
|
||||||
|
|
||||||
|
describe("settings/form/PropertiesForm", () => {
|
||||||
|
describe('render', () => {
|
||||||
|
it('renders PropertiesForm', () => {
|
||||||
|
let types = {
|
||||||
|
mystr: 'string',
|
||||||
|
mynum: 'number',
|
||||||
|
mybool: 'boolean',
|
||||||
|
empty: 'string',
|
||||||
|
}
|
||||||
|
let value = {
|
||||||
|
mystr: 'abc',
|
||||||
|
mynum: 123,
|
||||||
|
mybool: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
let root = ReactTestRenderer.create(
|
||||||
|
<PropertiesForm types={types} value={value} />,
|
||||||
|
).root
|
||||||
|
|
||||||
|
let input = root.findByProps({ name: 'mystr' });
|
||||||
|
expect(input.props.type).to.equals('text');
|
||||||
|
expect(input.props.value).to.equal('abc');
|
||||||
|
|
||||||
|
input = root.findByProps({ name: 'mynum' });
|
||||||
|
expect(input.props.type).to.equals('number');
|
||||||
|
expect(input.props.value).to.equal(123);
|
||||||
|
|
||||||
|
input = root.findByProps({ name: 'mybool' });
|
||||||
|
expect(input.props.type).to.equals('checkbox');
|
||||||
|
expect(input.props.value).to.equal(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onChange', () => {
|
||||||
|
let container;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
container = document.createElement('div');
|
||||||
|
document.body.appendChild(container);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
document.body.removeChild(container);
|
||||||
|
container = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('invokes onChange event on text changed', (done) => {
|
||||||
|
ReactTestUtils.act(() => {
|
||||||
|
ReactDOM.render(<PropertiesForm
|
||||||
|
types={{ 'myvalue': 'string' }}
|
||||||
|
value={{ 'myvalue': 'abc' }}
|
||||||
|
onChange={value => {
|
||||||
|
expect(value).to.have.property('myvalue', 'abcd');
|
||||||
|
done();
|
||||||
|
}}
|
||||||
|
/>, container);
|
||||||
|
});
|
||||||
|
|
||||||
|
let input = document.querySelector('input[name=myvalue]');
|
||||||
|
input.value = 'abcd'
|
||||||
|
ReactTestUtils.Simulate.change(input);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('invokes onChange event on number changeed', (done) => {
|
||||||
|
ReactTestUtils.act(() => {
|
||||||
|
ReactDOM.render(<PropertiesForm
|
||||||
|
types={{ 'myvalue': 'number' }}
|
||||||
|
value={{ '': 123 }}
|
||||||
|
onChange={value => {
|
||||||
|
expect(value).to.have.property('myvalue', 1234);
|
||||||
|
done();
|
||||||
|
}}
|
||||||
|
/>, container);
|
||||||
|
});
|
||||||
|
|
||||||
|
let input = document.querySelector('input[name=myvalue]');
|
||||||
|
input.value = '1234'
|
||||||
|
ReactTestUtils.Simulate.change(input);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('invokes onChange event on checkbox changed', (done) => {
|
||||||
|
ReactTestUtils.act(() => {
|
||||||
|
ReactDOM.render(<PropertiesForm
|
||||||
|
types={{ 'myvalue': 'boolean' }}
|
||||||
|
value={{ 'myvalue': false }}
|
||||||
|
onChange={value => {
|
||||||
|
expect(value).to.have.property('myvalue', true);
|
||||||
|
done();
|
||||||
|
}}
|
||||||
|
/>, container);
|
||||||
|
});
|
||||||
|
|
||||||
|
let input = document.querySelector('input[name=myvalue]');
|
||||||
|
input.checked = true;
|
||||||
|
ReactTestUtils.Simulate.change(input);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
128
test/settings/components/form/SearchEngineForm.test.jsx
Normal file
128
test/settings/components/form/SearchEngineForm.test.jsx
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import ReactTestRenderer from 'react-test-renderer';
|
||||||
|
import ReactTestUtils from 'react-dom/test-utils';
|
||||||
|
import SearchForm from 'settings/components/form/SearchForm'
|
||||||
|
|
||||||
|
describe("settings/form/SearchForm", () => {
|
||||||
|
describe('render', () => {
|
||||||
|
it('renders SearchForm', () => {
|
||||||
|
let root = ReactTestRenderer.create(<SearchForm value={{
|
||||||
|
default: 'google',
|
||||||
|
engines: [['google', 'google.com'], ['yahoo', 'yahoo.com']],
|
||||||
|
}} />).root;
|
||||||
|
|
||||||
|
let names = root.findAllByProps({ name: 'name' });
|
||||||
|
expect(names).to.have.lengthOf(2);
|
||||||
|
expect(names[0].props.value).to.equal('google');
|
||||||
|
expect(names[1].props.value).to.equal('yahoo');
|
||||||
|
|
||||||
|
let urls = root.findAllByProps({ name: 'url' });
|
||||||
|
expect(urls).to.have.lengthOf(2);
|
||||||
|
expect(urls[0].props.value).to.equal('google.com');
|
||||||
|
expect(urls[1].props.value).to.equal('yahoo.com');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders blank value', () => {
|
||||||
|
let root = ReactTestRenderer.create(<SearchForm />).root;
|
||||||
|
|
||||||
|
let names = root.findAllByProps({ name: 'name' });
|
||||||
|
expect(names).to.be.empty;
|
||||||
|
|
||||||
|
let urls = root.findAllByProps({ name: 'url' });
|
||||||
|
expect(urls).to.be.empty;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders blank engines', () => {
|
||||||
|
let root = ReactTestRenderer.create(
|
||||||
|
<SearchForm value={{ default: 'google' }} />,
|
||||||
|
).root;
|
||||||
|
|
||||||
|
let names = root.findAllByProps({ name: 'name' });
|
||||||
|
expect(names).to.be.empty;
|
||||||
|
|
||||||
|
let urls = root.findAllByProps({ name: 'url' });
|
||||||
|
expect(urls).to.be.empty;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onChange event', () => {
|
||||||
|
let container;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
container = document.createElement('div');
|
||||||
|
document.body.appendChild(container);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
document.body.removeChild(container);
|
||||||
|
container = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('invokes onChange event on edit', (done) => {
|
||||||
|
ReactTestUtils.act(() => {
|
||||||
|
ReactDOM.render(<SearchForm
|
||||||
|
value={{
|
||||||
|
default: 'google',
|
||||||
|
engines: [['google', 'google.com'], ['yahoo', 'yahoo.com']]
|
||||||
|
}}
|
||||||
|
onChange={value => {
|
||||||
|
expect(value.default).to.equal('louvre');
|
||||||
|
expect(value.engines).to.have.lengthOf(2)
|
||||||
|
expect(value.engines).to.have.deep.members(
|
||||||
|
[['louvre', 'google.com'], ['yahoo', 'yahoo.com']]
|
||||||
|
);
|
||||||
|
done();
|
||||||
|
}} />, container);
|
||||||
|
});
|
||||||
|
|
||||||
|
let radio = document.querySelectorAll('input[type=radio]');
|
||||||
|
radio.checked = true;
|
||||||
|
|
||||||
|
let name = document.querySelector('input[name=name]');
|
||||||
|
name.value = 'louvre';
|
||||||
|
|
||||||
|
ReactTestUtils.Simulate.change(name);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('invokes onChange event on delete', (done) => {
|
||||||
|
ReactTestUtils.act(() => {
|
||||||
|
ReactDOM.render(<SearchForm value={{
|
||||||
|
default: 'yahoo',
|
||||||
|
engines: [['louvre', 'google.com'], ['yahoo', 'yahoo.com']]
|
||||||
|
}}
|
||||||
|
onChange={value => {
|
||||||
|
expect(value.default).to.equal('yahoo');
|
||||||
|
expect(value.engines).to.have.lengthOf(1)
|
||||||
|
expect(value.engines).to.have.deep.members(
|
||||||
|
[['yahoo', 'yahoo.com']]
|
||||||
|
);
|
||||||
|
done();
|
||||||
|
}} />, container);
|
||||||
|
});
|
||||||
|
|
||||||
|
let button = document.querySelector('input[type=button]');
|
||||||
|
ReactTestUtils.Simulate.click(button);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('invokes onChange event on add', (done) => {
|
||||||
|
ReactTestUtils.act(() => {
|
||||||
|
ReactDOM.render(<SearchForm value={{
|
||||||
|
default: 'yahoo',
|
||||||
|
engines: [['google', 'google.com']]
|
||||||
|
}}
|
||||||
|
onChange={value => {
|
||||||
|
expect(value.default).to.equal('yahoo');
|
||||||
|
expect(value.engines).to.have.lengthOf(2)
|
||||||
|
expect(value.engines).to.have.deep.members(
|
||||||
|
[['google', 'google.com'], ['', '']],
|
||||||
|
);
|
||||||
|
done();
|
||||||
|
}} />, container);
|
||||||
|
});
|
||||||
|
|
||||||
|
let button = document.querySelector('input[type=button].ui-add-button');
|
||||||
|
ReactTestUtils.Simulate.click(button);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,81 +0,0 @@
|
||||||
import { h, render } from 'preact';
|
|
||||||
import BlacklistForm from 'settings/components/form/blacklist-form'
|
|
||||||
|
|
||||||
describe("settings/form/BlacklistForm", () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
document.body.innerHTML = '';
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('render', () => {
|
|
||||||
it('renders BlacklistForm', () => {
|
|
||||||
render(<BlacklistForm value={['*.slack.com', 'www.google.com/maps']} />, document.body);
|
|
||||||
|
|
||||||
let inputs = document.querySelectorAll('input[type=text]');
|
|
||||||
expect(inputs).to.have.lengthOf(2);
|
|
||||||
expect(inputs[0].value).to.equal('*.slack.com');
|
|
||||||
expect(inputs[1].value).to.equal('www.google.com/maps');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders blank value', () => {
|
|
||||||
render(<BlacklistForm />, document.body);
|
|
||||||
|
|
||||||
let inputs = document.querySelectorAll('input[type=text]');
|
|
||||||
expect(inputs).to.be.empty;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders blank value', () => {
|
|
||||||
render(<BlacklistForm />, document.body);
|
|
||||||
|
|
||||||
let inputs = document.querySelectorAll('input[type=text]');
|
|
||||||
expect(inputs).to.be.empty;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onChange', () => {
|
|
||||||
it('invokes onChange event on edit', (done) => {
|
|
||||||
render(<BlacklistForm
|
|
||||||
value={['*.slack.com', 'www.google.com/maps*']}
|
|
||||||
onChange={value => {
|
|
||||||
expect(value).to.have.lengthOf(2)
|
|
||||||
.and.have.members(['gitter.im', 'www.google.com/maps*']);
|
|
||||||
|
|
||||||
done();
|
|
||||||
}}
|
|
||||||
/>, document.body);
|
|
||||||
|
|
||||||
let input = document.querySelectorAll('input[type=text]')[0];
|
|
||||||
input.value = 'gitter.im';
|
|
||||||
input.dispatchEvent(new Event('change'))
|
|
||||||
});
|
|
||||||
|
|
||||||
it('invokes onChange event on delete', (done) => {
|
|
||||||
render(<BlacklistForm
|
|
||||||
value={['*.slack.com', 'www.google.com/maps*']}
|
|
||||||
onChange={value => {
|
|
||||||
expect(value).to.have.lengthOf(1)
|
|
||||||
.and.have.members(['www.google.com/maps*']);
|
|
||||||
|
|
||||||
done();
|
|
||||||
}}
|
|
||||||
/>, document.body);
|
|
||||||
|
|
||||||
let button = document.querySelectorAll('input[type=button]')[0];
|
|
||||||
button.click();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('invokes onChange event on add', (done) => {
|
|
||||||
render(<BlacklistForm
|
|
||||||
value={['*.slack.com']}
|
|
||||||
onChange={value => {
|
|
||||||
expect(value).to.have.lengthOf(2)
|
|
||||||
.and.have.members(['*.slack.com', '']);
|
|
||||||
|
|
||||||
done();
|
|
||||||
}}
|
|
||||||
/>, document.body);
|
|
||||||
|
|
||||||
let button = document.querySelector('input[type=button].ui-add-button');
|
|
||||||
button.click();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,52 +0,0 @@
|
||||||
import { h, render } from 'preact';
|
|
||||||
import KeymapsForm from 'settings/components/form/keymaps-form'
|
|
||||||
|
|
||||||
describe("settings/form/KeymapsForm", () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
document.body.innerHTML = '';
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('render', () => {
|
|
||||||
it('renders KeymapsForm', () => {
|
|
||||||
render(<KeymapsForm value={{
|
|
||||||
'scroll.vertically?{"count":1}': 'j',
|
|
||||||
'scroll.vertically?{"count":-1}': 'k',
|
|
||||||
}} />, document.body);
|
|
||||||
|
|
||||||
let inputj = document.getElementById('scroll.vertically?{"count":1}');
|
|
||||||
let inputk = document.getElementById('scroll.vertically?{"count":-1}');
|
|
||||||
|
|
||||||
expect(inputj.value).to.equal('j');
|
|
||||||
expect(inputk.value).to.equal('k');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders blank value', () => {
|
|
||||||
render(<KeymapsForm />, document.body);
|
|
||||||
|
|
||||||
let inputj = document.getElementById('scroll.vertically?{"count":1}');
|
|
||||||
let inputk = document.getElementById('scroll.vertically?{"count":-1}');
|
|
||||||
|
|
||||||
expect(inputj.value).to.be.empty;
|
|
||||||
expect(inputk.value).to.be.empty;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onChange event', () => {
|
|
||||||
it('invokes onChange event on edit', (done) => {
|
|
||||||
render(<KeymapsForm
|
|
||||||
value={{
|
|
||||||
'scroll.vertically?{"count":1}': 'j',
|
|
||||||
'scroll.vertically?{"count":-1}': 'k',
|
|
||||||
}}
|
|
||||||
onChange={value => {
|
|
||||||
expect(value['scroll.vertically?{"count":1}']).to.equal('jjj');
|
|
||||||
|
|
||||||
done();
|
|
||||||
}} />, document.body);
|
|
||||||
|
|
||||||
let input = document.getElementById('scroll.vertically?{"count":1}');
|
|
||||||
input.value = 'jjj';
|
|
||||||
input.dispatchEvent(new Event('change'))
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,85 +0,0 @@
|
||||||
import { h, render } from 'preact';
|
|
||||||
import PropertiesForm from 'settings/components/form/properties-form'
|
|
||||||
|
|
||||||
describe("settings/form/PropertiesForm", () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
document.body.innerHTML = '';
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('render', () => {
|
|
||||||
it('renders PropertiesForm', () => {
|
|
||||||
let types = {
|
|
||||||
mystr: 'string',
|
|
||||||
mynum: 'number',
|
|
||||||
mybool: 'boolean',
|
|
||||||
empty: 'string',
|
|
||||||
}
|
|
||||||
let value = {
|
|
||||||
mystr: 'abc',
|
|
||||||
mynum: 123,
|
|
||||||
mybool: true,
|
|
||||||
};
|
|
||||||
render(<PropertiesForm types={types} value={value} />, document.body);
|
|
||||||
|
|
||||||
let strInput = document.querySelector('input[name=mystr]');
|
|
||||||
let numInput = document.querySelector('input[name=mynum]');
|
|
||||||
let boolInput = document.querySelector('input[name=mybool]');
|
|
||||||
let emptyInput = document.querySelector('input[name=empty]');
|
|
||||||
|
|
||||||
expect(strInput.type).to.equals('text');
|
|
||||||
expect(strInput.value).to.equal('abc');
|
|
||||||
expect(numInput.type).to.equals('number');
|
|
||||||
expect(numInput.value).to.equal('123');
|
|
||||||
expect(boolInput.type).to.equals('checkbox');
|
|
||||||
expect(boolInput.checked).to.be.true;
|
|
||||||
expect(emptyInput.type).to.equals('text');
|
|
||||||
expect(emptyInput.value).to.be.empty;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onChange', () => {
|
|
||||||
it('invokes onChange event on text changed', (done) => {
|
|
||||||
render(<PropertiesForm
|
|
||||||
types={{ 'myvalue': 'string' }}
|
|
||||||
value={{ 'myvalue': 'abc' }}
|
|
||||||
onChange={value => {
|
|
||||||
expect(value).to.have.property('myvalue', 'abcd');
|
|
||||||
done();
|
|
||||||
}}
|
|
||||||
/>, document.body);
|
|
||||||
|
|
||||||
let input = document.querySelector('input[name=myvalue]');
|
|
||||||
input.value = 'abcd'
|
|
||||||
input.dispatchEvent(new Event('change'))
|
|
||||||
});
|
|
||||||
|
|
||||||
it('invokes onChange event on number changeed', (done) => {
|
|
||||||
render(<PropertiesForm
|
|
||||||
types={{ 'myvalue': 'number' }}
|
|
||||||
value={{ '': 123 }}
|
|
||||||
onChange={value => {
|
|
||||||
expect(value).to.have.property('myvalue', 1234);
|
|
||||||
done();
|
|
||||||
}}
|
|
||||||
/>, document.body);
|
|
||||||
|
|
||||||
let input = document.querySelector('input[name=myvalue]');
|
|
||||||
input.value = '1234'
|
|
||||||
input.dispatchEvent(new Event('change'))
|
|
||||||
});
|
|
||||||
|
|
||||||
it('invokes onChange event on checkbox changed', (done) => {
|
|
||||||
render(<PropertiesForm
|
|
||||||
types={{ 'myvalue': 'boolean' }}
|
|
||||||
value={{ 'myvalue': false }}
|
|
||||||
onChange={value => {
|
|
||||||
expect(value).to.have.property('myvalue', true);
|
|
||||||
done();
|
|
||||||
}}
|
|
||||||
/>, document.body);
|
|
||||||
|
|
||||||
let input = document.querySelector('input[name=myvalue]');
|
|
||||||
input.click();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,103 +0,0 @@
|
||||||
import { h, render } from 'preact';
|
|
||||||
import SearchForm from 'settings/components/form/search-form'
|
|
||||||
|
|
||||||
describe("settings/form/SearchForm", () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
document.body.innerHTML = '';
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('render', () => {
|
|
||||||
it('renders SearchForm', () => {
|
|
||||||
render(<SearchForm value={{
|
|
||||||
default: 'google',
|
|
||||||
engines: [['google', 'google.com'], ['yahoo', 'yahoo.com']],
|
|
||||||
}} />, document.body);
|
|
||||||
|
|
||||||
let names = document.querySelectorAll('input[name=name]');
|
|
||||||
expect(names).to.have.lengthOf(2);
|
|
||||||
expect(names[0].value).to.equal('google');
|
|
||||||
expect(names[1].value).to.equal('yahoo');
|
|
||||||
|
|
||||||
let urls = document.querySelectorAll('input[name=url]');
|
|
||||||
expect(urls).to.have.lengthOf(2);
|
|
||||||
expect(urls[0].value).to.equal('google.com');
|
|
||||||
expect(urls[1].value).to.equal('yahoo.com');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders blank value', () => {
|
|
||||||
render(<SearchForm />, document.body);
|
|
||||||
|
|
||||||
let names = document.querySelectorAll('input[name=name]');
|
|
||||||
let urls = document.querySelectorAll('input[name=url]');
|
|
||||||
expect(names).to.have.lengthOf(0);
|
|
||||||
expect(urls).to.have.lengthOf(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders blank engines', () => {
|
|
||||||
render(<SearchForm value={{ default: 'google' }} />, document.body);
|
|
||||||
|
|
||||||
let names = document.querySelectorAll('input[name=name]');
|
|
||||||
let urls = document.querySelectorAll('input[name=url]');
|
|
||||||
expect(names).to.have.lengthOf(0);
|
|
||||||
expect(urls).to.have.lengthOf(0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onChange event', () => {
|
|
||||||
it('invokes onChange event on edit', (done) => {
|
|
||||||
render(<SearchForm
|
|
||||||
value={{
|
|
||||||
default: 'google',
|
|
||||||
engines: [['google', 'google.com'], ['yahoo', 'yahoo.com']]
|
|
||||||
}}
|
|
||||||
onChange={value => {
|
|
||||||
expect(value.default).to.equal('louvre');
|
|
||||||
expect(value.engines).to.have.lengthOf(2)
|
|
||||||
.and.have.deep.members([['louvre', 'google.com'], ['yahoo', 'yahoo.com']])
|
|
||||||
|
|
||||||
done();
|
|
||||||
}} />, document.body);
|
|
||||||
|
|
||||||
let radio = document.querySelectorAll('input[type=radio]');
|
|
||||||
radio.checked = true;
|
|
||||||
|
|
||||||
let name = document.querySelector('input[name=name]');
|
|
||||||
name.value = 'louvre';
|
|
||||||
name.dispatchEvent(new Event('change'))
|
|
||||||
});
|
|
||||||
|
|
||||||
it('invokes onChange event on delete', (done) => {
|
|
||||||
render(<SearchForm value={{
|
|
||||||
default: 'yahoo',
|
|
||||||
engines: [['louvre', 'google.com'], ['yahoo', 'yahoo.com']]
|
|
||||||
}}
|
|
||||||
onChange={value => {
|
|
||||||
expect(value.default).to.equal('yahoo');
|
|
||||||
expect(value.engines).to.have.lengthOf(1)
|
|
||||||
.and.have.deep.members([['yahoo', 'yahoo.com']])
|
|
||||||
|
|
||||||
done();
|
|
||||||
}} />, document.body);
|
|
||||||
|
|
||||||
let button = document.querySelector('input[type=button]');
|
|
||||||
button.click();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('invokes onChange event on add', (done) => {
|
|
||||||
render(<SearchForm value={{
|
|
||||||
default: 'yahoo',
|
|
||||||
engines: [['google', 'google.com']]
|
|
||||||
}}
|
|
||||||
onChange={value => {
|
|
||||||
expect(value.default).to.equal('yahoo');
|
|
||||||
expect(value.engines).to.have.lengthOf(2)
|
|
||||||
.and.have.deep.members([['google', 'google.com'], ['', '']])
|
|
||||||
|
|
||||||
done();
|
|
||||||
}} />, document.body);
|
|
||||||
|
|
||||||
let button = document.querySelector('input[type=button].ui-add-button');
|
|
||||||
button.click();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,14 +1,28 @@
|
||||||
import { h, render } from 'preact';
|
import React from 'react';
|
||||||
import Input from 'settings/components/ui/input'
|
import ReactDOM from 'react-dom';
|
||||||
|
import ReactTestUtils from 'react-dom/test-utils';
|
||||||
|
import Input from 'settings/components/ui/Input'
|
||||||
|
|
||||||
describe("settings/ui/Input", () => {
|
describe("settings/ui/Input", () => {
|
||||||
|
let container;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
document.body.innerHTML = '';
|
container = document.createElement('div');
|
||||||
|
document.body.appendChild(container);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
document.body.removeChild(container);
|
||||||
|
container = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
context("type=text", () => {
|
context("type=text", () => {
|
||||||
it('renders text input', () => {
|
it('renders text input', () => {
|
||||||
render(<Input type='text' name='myname' label='myfield' value='myvalue'/>, document.body)
|
ReactTestUtils.act(() => {
|
||||||
|
ReactDOM.render(
|
||||||
|
<Input type='text' name='myname' label='myfield' value='myvalue'/>,
|
||||||
|
container);
|
||||||
|
});
|
||||||
|
|
||||||
let label = document.querySelector('label');
|
let label = document.querySelector('label');
|
||||||
let input = document.querySelector('input');
|
let input = document.querySelector('input');
|
||||||
|
@ -19,20 +33,26 @@ describe("settings/ui/Input", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invoke onChange', (done) => {
|
it('invoke onChange', (done) => {
|
||||||
render(<Input type='text' name='myname' label='myfield' value='myvalue' onChange={(e) => {
|
ReactTestUtils.act(() => {
|
||||||
expect(e.target.value).to.equal('newvalue');
|
ReactDOM.render(<Input type='text' name='myname' label='myfield' value='myvalue' onChange={(e) => {
|
||||||
done();
|
expect(e.target.value).to.equal('newvalue');
|
||||||
}}/>, document.body);
|
done();
|
||||||
|
}}/>, container);
|
||||||
|
});
|
||||||
|
|
||||||
let input = document.querySelector('input');
|
let input = document.querySelector('input');
|
||||||
input.value = 'newvalue';
|
input.value = 'newvalue';
|
||||||
input.dispatchEvent(new Event('change'))
|
ReactTestUtils.Simulate.change(input);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
context("type=radio", () => {
|
context("type=radio", () => {
|
||||||
it('renders radio button', () => {
|
it('renders radio button', () => {
|
||||||
render(<Input type='radio' name='myname' label='myfield' value='myvalue'/>, document.body)
|
ReactTestUtils.act(() => {
|
||||||
|
ReactDOM.render(
|
||||||
|
<Input type='radio' name='myname' label='myfield' value='myvalue'/>,
|
||||||
|
container);
|
||||||
|
});
|
||||||
|
|
||||||
let label = document.querySelector('label');
|
let label = document.querySelector('label');
|
||||||
let input = document.querySelector('input');
|
let input = document.querySelector('input');
|
||||||
|
@ -43,20 +63,27 @@ describe("settings/ui/Input", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invoke onChange', (done) => {
|
it('invoke onChange', (done) => {
|
||||||
render(<Input type='text' name='radio' label='myfield' value='myvalue' onChange={(e) => {
|
ReactTestUtils.act(() => {
|
||||||
expect(e.target.checked).to.be.true;
|
ReactDOM.render(<Input type='text' name='radio' label='myfield' value='myvalue' onChange={(e) => {
|
||||||
done();
|
expect(e.target.checked).to.be.true;
|
||||||
}}/>, document.body);
|
done();
|
||||||
|
}}/>,
|
||||||
|
container);
|
||||||
|
});
|
||||||
|
|
||||||
let input = document.querySelector('input');
|
let input = document.querySelector('input');
|
||||||
input.checked = true;
|
input.checked = true;
|
||||||
input.dispatchEvent(new Event('change'))
|
ReactTestUtils.Simulate.change(input);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
context("type=textarea", () => {
|
context("type=textarea", () => {
|
||||||
it('renders textarea button', () => {
|
it('renders textarea button', () => {
|
||||||
render(<Input type='textarea' name='myname' label='myfield' value='myvalue' error='myerror' />, document.body)
|
ReactTestUtils.act(() => {
|
||||||
|
ReactDOM.render(
|
||||||
|
<Input type='textarea' name='myname' label='myfield' value='myvalue' error='myerror' />,
|
||||||
|
container);
|
||||||
|
});
|
||||||
|
|
||||||
let label = document.querySelector('label');
|
let label = document.querySelector('label');
|
||||||
let textarea = document.querySelector('textarea');
|
let textarea = document.querySelector('textarea');
|
||||||
|
@ -69,14 +96,16 @@ describe("settings/ui/Input", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invoke onChange', (done) => {
|
it('invoke onChange', (done) => {
|
||||||
render(<Input type='textarea' name='myname' label='myfield' value='myvalue' onChange={(e) => {
|
ReactTestUtils.act(() => {
|
||||||
expect(e.target.value).to.equal('newvalue');
|
ReactDOM.render(<Input type='textarea' name='myname' label='myfield' value='myvalue' onChange={(e) => {
|
||||||
done();
|
expect(e.target.value).to.equal('newvalue');
|
||||||
}}/>, document.body);
|
done();
|
||||||
|
}}/>, container);
|
||||||
|
});
|
||||||
|
|
||||||
let input = document.querySelector('textarea');
|
let input = document.querySelector('textarea');
|
||||||
input.value = 'newvalue'
|
input.value = 'newvalue'
|
||||||
input.dispatchEvent(new Event('change'))
|
ReactTestUtils.Simulate.change(input);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -24,7 +24,7 @@ config = {
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
loader: 'babel-loader',
|
loader: 'babel-loader',
|
||||||
query: {
|
query: {
|
||||||
presets: ['preact', 'stage-2']
|
presets: ['@babel/react']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
Reference in a new issue