-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
39a1448
commit 7d617b6
Showing
13 changed files
with
296 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export function Component(props = {}) { | ||
this.props = props; | ||
this.render = () => {}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './Component'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export function Node(element, attributes, children) { | ||
this.element = element; | ||
this.attributes = attributes; | ||
this.children = children; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/* eslint-env jest */ | ||
/** @jsx createElement */ | ||
|
||
import { Node } from './Node'; | ||
|
||
describe('Node', () => { | ||
test('Should create a node with provided parameters', () => { | ||
const node = new Node(1, 2, 3); | ||
expect(node.element).toBe(1); | ||
expect(node.attributes).toBe(2); | ||
expect(node.children).toBe(3); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './Node'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { Node } from '../Node'; | ||
|
||
export function createElement(element, attributes, ...children) { | ||
return new Node(element, attributes, children); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* eslint-env jest */ | ||
/** @jsx createElement */ | ||
|
||
import { Node } from '../Node'; | ||
import { createElement } from './createElement'; | ||
|
||
describe('createElement()', () => { | ||
test('Should create node tree with provided data structure', () => { | ||
const withStr = 'over here'; | ||
const withNum = 100; | ||
const tree = ( | ||
<header> | ||
<h1 name="title">Hello!</h1> | ||
<div name="description">Awesome {withStr} <b>fun {withNum}</b>!</div> | ||
</header> | ||
); | ||
|
||
expect(tree).toBeInstanceOf(Node); | ||
|
||
expect(tree.children.length).toBe(2); | ||
expect(tree.children[0]).toBeInstanceOf(Node); | ||
expect(tree.children[0].children.length).toBe(1); | ||
expect(tree.children[0].children[0]).toBe('Hello!'); | ||
|
||
expect(tree.children[1]).toBeInstanceOf(Node); | ||
expect(tree.children[1].children.length).toBe(5); | ||
|
||
expect(tree.children[1].children[0]).toBeString(); | ||
expect(tree.children[1].children[1]).toBeString(); | ||
expect(tree.children[1].children[2]).toBeString(); | ||
|
||
expect(tree.children[1].children[3]).toBeInstanceOf(Node); | ||
expect(tree.children[1].children[3].children.length).toBe(2); | ||
expect(tree.children[1].children[3].children[0]).toBeString(); | ||
expect(tree.children[1].children[3].children[1]).toBeNumber(); | ||
|
||
expect(tree.children[1].children[4]).toBeString(); | ||
}); | ||
|
||
test('Should create node tree with provided props', () => { | ||
const withStr = 'over here'; | ||
const withNum = 100; | ||
const tree = ( | ||
<header> | ||
<h1 name="title">Hello!</h1> | ||
<div name="description">Awesome {withStr} <b>fun {withNum}</b>!</div> | ||
</header> | ||
); | ||
|
||
expect(tree.element).toBe('header'); | ||
expect(tree.attributes).toBeNull(); | ||
|
||
expect(tree.children[0].element).toBe('h1'); | ||
expect(tree.children[0].attributes).toEqual({ name: 'title' }); | ||
expect(tree.children[0].children.length).toBe(1); | ||
expect(tree.children[0].children[0]).toBe('Hello!'); | ||
|
||
expect(tree.children[1].element).toBe('div'); | ||
expect(tree.children[1].attributes).toEqual({ name: 'description' }); | ||
|
||
expect(tree.children[1].children[0]).toBe('Awesome '); | ||
expect(tree.children[1].children[1]).toBe(withStr); | ||
expect(tree.children[1].children[2]).toBe(' '); | ||
|
||
expect(tree.children[1].children[3].element).toBe('b'); | ||
expect(tree.children[1].children[3].attributes).toBeNull(); | ||
expect(tree.children[1].children[3].children[0]).toBe('fun '); | ||
expect(tree.children[1].children[3].children[1]).toBe(withNum); | ||
|
||
expect(tree.children[1].children[4]).toBe('!'); | ||
}); | ||
|
||
test('Should creates node tree with classes and functions', () => { | ||
class MyClass {} | ||
const MyFn = () => 'hello'; | ||
const tree = ( | ||
<MyClass> | ||
<h1>Heading</h1> | ||
<MyFn>Content</MyFn> | ||
</MyClass> | ||
); | ||
|
||
expect(tree.element).toBe(MyClass); | ||
expect(tree.children[0].element).toBeString(); | ||
expect(tree.children[1].element).toBe(MyFn); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './createElement'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export * from './Component'; | ||
export * from './createComponent'; | ||
export * from './render'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './render'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* eslint-env jest */ | ||
/** @jsx createElement */ | ||
|
||
import { createElement } from '../createElement'; | ||
import { render } from './render'; | ||
|
||
describe('render() DOMElements', () => { | ||
test('Should render DOMElements with "className" prop as "class"', () => { | ||
const parentRoot = document.createElement('div'); | ||
const parentElement = <div className="content">Content</div>; | ||
render(parentElement, parentRoot); | ||
|
||
const received = parentRoot.outerHTML; | ||
const expected = '<div class="content">Content</div>'; | ||
expect(received).toBe(expected); | ||
}); | ||
|
||
test('Should render DOMElements with "htmlFor" prop as "for"', () => { | ||
const parentRoot = document.createElement('div'); | ||
const parentElement = <div htmlFor="item">Item</div>; | ||
render(parentElement, parentRoot); | ||
|
||
const received = parentRoot.outerHTML; | ||
const expected = '<div for="item">Item</div>'; | ||
expect(received).toBe(expected); | ||
}); | ||
|
||
test('Should render DOMElements with "style" prop as directly style modifications', () => { | ||
const styles = { fontSize: '14px', color: 'blue' }; | ||
const parentRoot = document.createElement('div'); | ||
const parentElement = <div style={styles}>Item</div>; | ||
render(parentElement, parentRoot); | ||
|
||
const received = parentRoot.outerHTML; | ||
const expected = '<div style="font-size: 14px;color: blue;">Item</div>'; | ||
expect(received).toBe(expected); | ||
}); | ||
|
||
test('Should render DOMElements with provided events, props matching "/^on[A-Z][A-Za-z]+/"', () => { | ||
const onClick = jest.fn(); | ||
const onFocus = jest.fn(); | ||
const parentRoot = document.createElement('div'); | ||
const parentElement = <button onClick={onClick} onFocus={onFocus}>Item</button>; | ||
render(parentElement, parentRoot); | ||
|
||
const button = parentRoot.querySelector('button'); | ||
const clickEvent = new Event('click'); | ||
const focusEvent = new Event('focus'); | ||
button.dispatchEvent(clickEvent); | ||
button.dispatchEvent(focusEvent); | ||
|
||
expect(onClick).toHaveBeenCalledWith(clickEvent); | ||
expect(onFocus).toHaveBeenCalledWith(focusEvent); | ||
}); | ||
|
||
test('Should only render DOMElements strings/numbers and ignore void values', () => { | ||
const parentRoot = document.createElement('div'); | ||
const parentElement = <div>Hello{true} every{undefined}one{null} {10}!</div>; | ||
render(parentElement, parentRoot); | ||
|
||
const received = parentRoot.outerHTML; | ||
const expected = '<div>Hello everyone 10!</div>'; | ||
expect(received).toBe(expected); | ||
}); | ||
|
||
test('Should throw error if DOMElements have invalid types', () => { | ||
const parentRoot = document.createElement('div'); | ||
const parentElement = <div>Hello{{}} everyone{/a/}!</div>; | ||
const fn = () => render(parentElement, parentRoot); | ||
expect(fn).toThrow('Invalid children.'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* eslint-env jest */ | ||
/** @jsx createElement */ | ||
|
||
import { Component } from '../Component'; | ||
import { createElement } from '../createElement'; | ||
import { render } from './render'; | ||
|
||
describe('render() tree', () => { | ||
test('Should render basic HTMLElements tree', () => { | ||
const parentElement = <div name="parent">Hello</div>; | ||
const parentRoot = document.createElement('div'); | ||
render(parentElement, parentRoot); | ||
|
||
const received = parentRoot.outerHTML; | ||
const expected = '<div name="parent">Hello</div>'; | ||
expect(received).toBe(expected); | ||
}); | ||
|
||
test('Should render nested HTMLElements tree', () => { | ||
const parentRoot = document.createElement('div'); | ||
const parentElement = ( | ||
<header className="heading"> | ||
<h1>Hello</h1> | ||
<ul name="nav"> | ||
<li><a href="/">home</a></li> | ||
<li><a href="/about">about</a></li> | ||
</ul> | ||
</header> | ||
); | ||
render(parentElement, parentRoot); | ||
|
||
const received = parentRoot.outerHTML; | ||
const expected = [ | ||
'<header class="heading">', | ||
'<h1>Hello</h1>', | ||
'<ul name="nav">', | ||
'<li><a href="/">home</a></li>', | ||
'<li><a href="/about">about</a></li>', | ||
'</ul>', | ||
'</header>' | ||
].join(''); | ||
expect(received).toBe(expected); | ||
}); | ||
|
||
test('Should render functions components', () => { | ||
const Title = ({ name, children }) => <h1 name={name}>Title: {children}</h1>; | ||
const parentRoot = document.createElement('div'); | ||
const parentElement = ( | ||
<div name="parent"> | ||
<Title name="title">Welcome</Title> | ||
<p>Content</p> | ||
</div> | ||
); | ||
render(parentElement, parentRoot); | ||
|
||
const received = parentRoot.outerHTML; | ||
const expected = '<div name="parent"><h1 name="title">Title: Welcome</h1><p>Content</p></div>'; | ||
expect(received).toBe(expected); | ||
}); | ||
|
||
test('Should render class components', () => { | ||
class Header extends Component { | ||
render() { | ||
const { name, children } = this.props; | ||
return ( | ||
<header name={name}> | ||
<h1 className="title">{children}</h1> | ||
<h2>Best heading ever!</h2> | ||
</header> | ||
); | ||
} | ||
} | ||
|
||
const parentRoot = document.createElement('div'); | ||
const parentElement = ( | ||
<div> | ||
<Header name="header">Welcome</Header> | ||
<p>Content</p> | ||
</div> | ||
); | ||
render(parentElement, parentRoot); | ||
|
||
const received = parentRoot.outerHTML; | ||
const expected = [ | ||
'<div>', | ||
'<header name="header">', | ||
'<h1 class="title">Welcome</h1>', | ||
'<h2>Best heading ever!</h2>', | ||
'</header>', | ||
'</div>' | ||
].join(''); | ||
expect(received).toBe(expected); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
function buildDOM() { | ||
// TODO: | ||
return document.createElement('div'); | ||
} | ||
|
||
export function render(parentElement, parentRoot) { | ||
const domElement = buildDOM(parentElement); | ||
parentRoot.appendChild(domElement); | ||
} |