Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
* upstream/master: (341 commits)
  Revert "Simplify originalDom check (-4 B)
"
  Simplify originalDom check (-4 B)
  Add back mistakenly removed JSDoc comment
  Remove unnecessary code from `diffChildren` (-16 B)
  Golf createContext (-6 B)
  Fix useContext test spacing
  Remove `dom` parameter from `diff()` (-11 B)
  Move all component diff'ing logic into component diff condition (-6 B)
  fix issue by marking dirty before .render since this can potentially add another entry on the render queue
  add relevant test
  (chore) - remove focusElement (preactjs#1548)
  Update type definition (preactjs#1581)
  Compress code, assume EMPTY_OBJ._children == null
  Refactor out variables from diffChildren
  Compress diffChildren further
  Compress diffChildren further
  Condense code in diffChildren
  Fix infinite loop because of props mutation (preactjs#1577)
  (fix) - Error boundary not applying in array cases (preactjs#1572)
  Add styled-components example (preactjs#1574)
  ...

# Conflicts:
#	.eslintignore
#	compat/mangle.json
#	compat/src/index.js
#	compat/src/internal.d.ts
#	debug/mangle.json
#	hooks/src/index.d.ts
#	hooks/src/index.js
#	hooks/src/internal.d.ts
#	mangle.json
#	package.json
#	src/component.js
#	src/constants.js
#	src/create-context.js
#	src/create-element.js
#	src/diff/children.js
#	src/diff/index.js
#	src/diff/props.js
#	src/index.d.ts
#	src/internal.d.ts
#	src/jsx.d.ts
#	src/render.js
#	src/util.js
  • Loading branch information
lordvlad committed Apr 30, 2019
2 parents 9bedeb0 + 59ee02c commit e019722
Show file tree
Hide file tree
Showing 93 changed files with 8,271 additions and 6,335 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Expand Up @@ -17,5 +17,5 @@ trim_trailing_whitespace = false
# Uglify (or some other tool) always rewrites this file
# without a final newline on build, so disabling that
# editorconfig feature specifically for this file
[mangle.json]
[mangle.json,**/mangle.json]
insert_final_newline = false
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -7,3 +7,4 @@ package-lock.json
.idea
test/ts/**/*.js
coverage
*.sw[op]
3 changes: 3 additions & 0 deletions .travis.yml
@@ -1,5 +1,8 @@
sudo: false

notifications:
email: false

language: node_js

node_js:
Expand Down
4 changes: 2 additions & 2 deletions compat/package.json
Expand Up @@ -5,14 +5,14 @@
"private": true,
"description": "A React compatibility layer for Preact",
"main": "dist/compat.js",
"module": "dist/compat.mjs",
"module": "dist/compat.module.js",
"umd:main": "dist/compat.umd.js",
"source": "src/index.js",
"license": "MIT",
"mangle": {
"regex": "^_"
},
"peerDependencies": {
"preact": "10.0.0-alpha.0"
"preact": "^10.0.0-alpha.0"
}
}
1 change: 1 addition & 0 deletions compat/test-utils.js
@@ -0,0 +1 @@
module.exports = require('preact/test-utils');
8 changes: 4 additions & 4 deletions compat/test/browser/Children.test.js
@@ -1,4 +1,4 @@
import { setupScratch, teardown } from '../../../test/_util/helpers';
import { setupScratch, teardown, serializeHtml } from '../../../test/_util/helpers';
// eslint-disable-next-line no-unused-vars
import React, { Children, render } from '../../src';
import { div, span } from '../../../test/_util/dom';
Expand Down Expand Up @@ -73,12 +73,12 @@ describe('Children', () => {
span('foo'),
span(div('bar'))
].join(''));
expect(scratch.innerHTML).to.equal(expected);
expect(serializeHtml(scratch)).to.equal(expected);
});

it('should work with no children', () => {
render(<Foo />, scratch);
expect(scratch.innerHTML).to.equal('<div></div>');
expect(serializeHtml(scratch)).to.equal('<div></div>');
});
});

Expand All @@ -95,7 +95,7 @@ describe('Children', () => {
span('foo'),
span(div('bar'))
].join(''));
expect(scratch.innerHTML).to.equal(expected);
expect(serializeHtml(scratch)).to.equal(expected);
});
});
});
55 changes: 55 additions & 0 deletions compat/test/browser/compat.test.js
@@ -0,0 +1,55 @@
import { createElement, render } from 'preact';
import { setupScratch, teardown } from '../../../test/_util/helpers';

import React from 'preact/compat'; // eslint-disable-line

describe('imported compat in preact', () => {

let scratch;

beforeEach(() => {
scratch = setupScratch();
});

afterEach(() => {
teardown(scratch);
});

it('should patch events', () => {
let spy = sinon.spy();
render(<div onClick={spy} />, scratch);
scratch.firstChild.click();

expect(spy).to.be.calledOnce;
expect(spy.args[0][0]).to.haveOwnProperty('persist');
expect(typeof spy.args[0][0].persist).to.equal('function');
expect(spy.args[0][0]).to.haveOwnProperty('nativeEvent');
});

it('should normalize ondoubleclick event', () => {
let vnode = <div onDoubleClick={() => null} />;
expect(vnode.props).to.haveOwnProperty('ondblclick');
});

it('should normalize onChange for textarea', () => {
let vnode = <textarea onChange={() => null} />;
expect(vnode.props).to.haveOwnProperty('oninput');
expect(vnode.props).to.not.haveOwnProperty('onchange');

vnode = <textarea oninput={() => null} onChange={() => null} />;
expect(vnode.props).to.haveOwnProperty('oninput');
expect(vnode.props).to.not.haveOwnProperty('onchange');
});

it('should normalize class+className even on components', () => {
function Foo(props) {
return <div class={props.class} className={props.className}>foo</div>;
}
render(<Foo class="foo" />, scratch);
expect(scratch.firstChild.className).to.equal('foo');
render(null, scratch);

render(<Foo className="foo" />, scratch);
expect(scratch.firstChild.className).to.equal('foo');
});
});
18 changes: 17 additions & 1 deletion compat/test/browser/component.test.js
@@ -1,4 +1,5 @@
import { setupScratch, teardown, setupRerender } from '../../../test/_util/helpers';
import { setupRerender } from 'preact/test-utils';
import { setupScratch, teardown } from '../../../test/_util/helpers';
import React from '../../src';

describe('components', () => {
Expand Down Expand Up @@ -78,6 +79,21 @@ describe('components', () => {
expect(React).to.have.property('PureComponent').that.is.a('function');
});

it('should pass props in constructor', () => {
let spy = sinon.spy();
class Foo extends React.PureComponent {
constructor(props) {
super(props);
spy(this.props, props);
}
}

React.render(<Foo foo="bar" />, scratch);

let expected = { foo: 'bar' };
expect(spy).to.be.calledWithMatch(expected, expected);
});

it('should only re-render when props or state change', () => {
class C extends React.PureComponent {
render() {
Expand Down
2 changes: 2 additions & 0 deletions compat/test/browser/exports.test.js
Expand Up @@ -35,6 +35,7 @@ describe('exports', () => {
expect(Compat.Children.toArray).to.exist.and.be.a('function');
expect(Compat.Children.only).to.exist.and.be.a('function');
expect(Compat.unmountComponentAtNode).to.exist.and.be.a('function');
expect(Compat.unstable_batchedUpdates).to.exist.and.be.a('function');
expect(Compat.version).to.exist.and.be.a('string');
});

Expand Down Expand Up @@ -70,6 +71,7 @@ describe('exports', () => {
expect(Named.Children.toArray).to.exist.and.be.a('function');
expect(Named.Children.only).to.exist.and.be.a('function');
expect(Compat.unmountComponentAtNode).to.exist.and.be.a('function');
expect(Compat.unstable_batchedUpdates).to.exist.and.be.a('function');
expect(Named.version).to.exist.and.be.a('string');
});
});
4 changes: 2 additions & 2 deletions compat/test/browser/forwardRef.test.js
Expand Up @@ -167,7 +167,7 @@ describe('forwardRef', () => {
expect(renderCount).to.equal(2);
});

it.skip('should bailout if forwardRef is wrapped in memo', () => {
it('should bailout if forwardRef is wrapped in memo', () => {
const Component = props => <div ref={props.forwardedRef} />;

let renderCount = 0;
Expand Down Expand Up @@ -204,7 +204,7 @@ describe('forwardRef', () => {
expect(renderCount).to.equal(3);
});

it.skip('should custom memo comparisons to compose', () => {
it('should pass ref through memo() with custom comparer function', () => {
const Foo = props => <div ref={props.forwardedRef} />;

let renderCount = 0;
Expand Down
37 changes: 35 additions & 2 deletions compat/test/browser/index.test.js
Expand Up @@ -5,9 +5,11 @@ import React, {
findDOMNode,
Component,
unmountComponentAtNode,
createFactory
createFactory,
unstable_batchedUpdates
} from '../../src';
import { setupScratch, teardown } from '../../../test/_util/helpers';
import { createElement as preactH } from 'preact';
import { setupScratch, teardown, createEvent } from '../../../test/_util/helpers';

let ce = type => document.createElement(type);
let text = text => document.createTextNode(text);
Expand Down Expand Up @@ -171,6 +173,13 @@ describe('preact-compat', () => {
expectToBeNormalized(<input {...props} type="text" />, '<input type="text">');

});

it('should normalize beforeinput event listener', () => {
let spy = sinon.spy();
render(<input onBeforeInput={spy} />, scratch);
scratch.firstChild.dispatchEvent(createEvent('beforeinput'));
expect(spy).to.be.calledOnce;
});
});

describe('Component', () => {
Expand Down Expand Up @@ -229,6 +238,16 @@ describe('preact-compat', () => {
let clone = cloneElement(element);
expect(clone).to.eql(element);
});

it('should work with jsx constructor from core', () => {
function Foo(props) {
return <div>{props.value}</div>;
}

let clone = cloneElement(preactH(Foo), { value: 'foo' });
render(clone, scratch);
expect(scratch.textContent).to.equal('foo');
});
});

describe('findDOMNode()', () => {
Expand Down Expand Up @@ -284,6 +303,20 @@ describe('preact-compat', () => {
});
});

describe('unstable_batchedUpdates', () => {
it('should call the callback', () => {
const spy = sinon.spy();
unstable_batchedUpdates(spy);
expect(spy).to.be.calledOnce;
});

it('should call callback with only one arg', () => {
const spy = sinon.spy();
unstable_batchedUpdates(spy, 'foo', 'bar');
expect(spy).to.be.calledWithExactly('foo');
});
});

it('should patch events', () => {
let spy = sinon.spy();
render(<div onClick={spy} />, scratch);
Expand Down
25 changes: 22 additions & 3 deletions compat/test/browser/jsx.test.js
@@ -1,5 +1,6 @@
import { setupScratch, teardown } from '../../../test/_util/helpers';
import React from '../../src';
import { setupScratch, teardown, serializeHtml } from '../../../test/_util/helpers';
import React, { isValidElement } from '../../src';
import { h as preactH } from 'preact';

describe('jsx', () => {

Expand All @@ -25,6 +26,24 @@ describe('jsx', () => {
expect(jsx.props).to.have.property('className', 'foo bar');

React.render(jsx, scratch);
expect(scratch.innerHTML).to.equal('<div class="foo bar" data-foo="bar"><span id="some_id">inner!</span>ab</div>');
expect(serializeHtml(scratch)).to.equal('<div class="foo bar" data-foo="bar"><span id="some_id">inner!</span>ab</div>');
});

describe('isValidElement', () => {
it('should check return false for invalid arguments', () => {
expect(isValidElement(null)).to.equal(false);
expect(isValidElement(false)).to.equal(false);
expect(isValidElement(true)).to.equal(false);
expect(isValidElement('foo')).to.equal(false);
expect(isValidElement(123)).to.equal(false);
});

it('should detect a preact vnode', () => {
expect(isValidElement(preactH('div'))).to.equal(true);
});

it('should detect a compat vnode', () => {
expect(isValidElement(React.createElement('div'))).to.equal(true);
});
});
});
3 changes: 2 additions & 1 deletion compat/test/browser/memo.test.js
@@ -1,4 +1,5 @@
import { setupScratch, setupRerender, teardown } from '../../../test/_util/helpers';
import { setupRerender } from 'preact/test-utils';
import { setupScratch, teardown } from '../../../test/_util/helpers';
import { Component, render, createElement as h, memo } from '../../src';

/** @jsx h */
Expand Down
50 changes: 50 additions & 0 deletions compat/test/browser/portals.test.js
Expand Up @@ -27,4 +27,54 @@ describe('Portal', () => {

expect(root.innerHTML).to.equal('foobar');
});

it('should not render <undefined> for Portal nodes', () => {
let root = document.createElement('div');
let dialog = document.createElement('div');
dialog.id = 'container';

scratch.appendChild(root);
scratch.appendChild(dialog);

function Dialog() {
return <div>Dialog content</div>;
}

function App() {
return (
<div>
{createPortal(<Dialog />, dialog)}
</div>
);
}

render(<App />, root);
expect(scratch.firstChild.firstChild.childNodes.length).to.equal(0);
});

it('should unmount Portal', () => {
let root = document.createElement('div');
let dialog = document.createElement('div');
dialog.id = 'container';

scratch.appendChild(root);
scratch.appendChild(dialog);

function Dialog() {
return <div>Dialog content</div>;
}

function App() {
return (
<div>
{createPortal(<Dialog />, dialog)}
</div>
);
}

render(<App />, root);
expect(dialog.childNodes.length).to.equal(1);
render(null, root);
expect(dialog.childNodes.length).to.equal(0);
});
});
37 changes: 37 additions & 0 deletions compat/test/browser/select.test.js
@@ -0,0 +1,37 @@
import { setupScratch, teardown } from '../../../test/_util/helpers';
import { render, createElement as h } from '../../src';

/** @jsx h */

describe('Select', () => {
let scratch;

beforeEach(() => {
scratch = setupScratch();
});

afterEach(() => {
teardown(scratch);
});


it('should work with multiple selected (array of values)', () => {
function App() {
return (
<select multiple value={['B', 'C']}>
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
</select>
);
}

render(<App />, scratch);
Array.prototype.slice.call(scratch.firstChild.childNodes).forEach(node => {
if (node.value === 'B' || node.value === 'C') {
expect(node.selected).to.equal(true);
}
});
expect(scratch.firstChild.value).to.equal('B');
});
});

0 comments on commit e019722

Please sign in to comment.