@girders-elements/core
Version:
Girders Elements is an architectural framework that assists with building data-driven apps with React or React Native.
240 lines (189 loc) • 6 kB
JavaScript
import { mount } from 'enzyme'
import R from 'ramda'
import React from 'react'
import * as Subsystem from '../../subsystem'
import * as Kernel from '../../kernel'
import { EntryPoint, Engine } from '..'
import { defaultSubsystems } from '../../core'
import { ui, update } from '../..'
describe('Engine: wiring everything together', () => {
describe('EntryPoint', () => {
const app = Subsystem.create(() => ({
name: 'app',
}))
const Foo = ({ element }) => (
<div>
{element.get('kind')}: {element.get('text')}
</div>
)
app.ui.register('c1', Foo)
app.ui.register('c2', Foo)
const capitalize = e => e.update('text', R.toUpper)
const capitalizeTitles = n => n.update('scenes', ss => ss.map(capitalize))
app.update.register('nav', '.capitalize', capitalizeTitles)
app.update.register('c1', 'capitalize', capitalize)
let kernel
beforeEach(
() =>
(kernel = Kernel.create([...defaultSubsystems, app], {
kind: 'nav',
scenes: [
{
kind: 'c1',
text: 'Scene 1',
},
{
kind: 'c2',
text: 'Scene 2',
},
],
}))
)
test('multiple entrypoints can be linked with a single kernel inst.', () => {
const ep1 = mount(<EntryPoint kernel={kernel} keyPath={['scenes', 0]} />)
const ep2 = mount(<EntryPoint kernel={kernel} keyPath={['scenes', 1]} />)
expect(ep1).toIncludeText('c1: Scene 1')
expect(ep2).toIncludeText('c2: Scene 2')
})
test('updates work accross different entrypoints', () => {
const ep1 = mount(<EntryPoint kernel={kernel} keyPath={['scenes', 0]} />)
const ep2 = mount(<EntryPoint kernel={kernel} keyPath={['scenes', 1]} />)
ep1
.find(Foo)
.at(0)
.props()
.dispatch({ type: 'capitalize' })
expect(ep1).toIncludeText('c1: SCENE 1')
ep1
.find(Foo)
.at(0)
.props()
.dispatch({ type: '.capitalize' })
expect(ep2).toIncludeText('c2: SCENE 2')
})
})
describe('Entrypoint with mixins', () => {
const Wrapper = Superclass =>
class extends Superclass {
render() {
return <section id="wrapper">{super.render()}</section>
}
}
const app = Subsystem.create(() => ({
name: 'app',
engineMixins: [Wrapper],
}))
const Foo = ({ element }) => (
<div>
{element.get('kind')}: {element.get('text')}
</div>
)
app.ui.register('c1', Foo)
const kernel = Kernel.create([...defaultSubsystems, app], {
kind: 'c1',
text: 'wrapped',
})
test('mixins are applied around the entrypoint', () => {
const e = mount(<EntryPoint kernel={kernel} keyPath={[]} />)
expect(e.find('section#wrapper')).toBePresent()
})
})
describe('Engine', () => {
afterEach(() => {
ui.reset()
})
const twiddlingMiddleware = R.curry((store, next, action) => {
let nextAction
if (action.type === 'twiddle') {
nextAction = { ...action, type: 'capitalize' }
} else {
nextAction = action
}
return next(nextAction)
})
test('classic use (deprecations expected)', () => {
const Foo = ({ element }) => <div>Hello from {element.get('text')}</div>
ui.register('s1', Foo)
update.register('s1', updates => {
updates.register('capitalize', e => e.update('text', R.toUpper))
})
const e = mount(<Engine initState={{ kind: 's1', text: 's1' }} />)
expect(e).toIncludeText('Hello from s1')
e
.find(Foo)
.at(0)
.props()
.dispatch({ type: 'capitalize' })
expect(e).toIncludeText('Hello from S1')
})
test('custom middleware', () => {
const Foo = ({ element }) => <div>Hello from {element.get('text')}</div>
ui.register('m1', Foo)
update.register('m1', updates => {
updates.register('capitalize', e => e.update('text', R.toUpper))
})
const e = mount(
<Engine
initState={{ kind: 'm1', text: 'm1' }}
customMiddleware={[twiddlingMiddleware]}
/>
)
expect(e).toIncludeText('Hello from m1')
e
.find(Foo)
.at(0)
.props()
.dispatch({ type: 'twiddle' })
expect(e).toIncludeText('Hello from M1')
})
test('additionalSubsystems', () => {
const Foo = ({ element }) => <div>Hello from {element.get('text')}</div>
ui.register('ss1', Foo)
update.register('ss1', updates => {
updates.register('capitalize', e => e.update('text', R.toUpper))
})
const twiddler = Subsystem.create(() => ({
name: 'twiddler',
middleware: twiddlingMiddleware,
}))
const e = mount(
<Engine
initState={{ kind: 'ss1', text: 'ss1' }}
additionalSubsystems={[twiddler]}
/>
)
expect(e).toIncludeText('Hello from ss1')
e
.find(Foo)
.at(0)
.props()
.dispatch({ type: 'twiddle' })
expect(e).toIncludeText('Hello from SS1')
})
test('subsystems', () => {
const Foo = ({ element }) => <div>Hello from {element.get('text')}</div>
ui.register('ssx1', Foo)
update.register('ssx1', updates => {
updates.register('capitalize', e => e.update('text', R.toUpper))
})
const twiddler = Subsystem.create(() => ({
name: 'twiddler',
middleware: twiddlingMiddleware,
}))
const e = mount(
<Engine
initState={{ kind: 'ssx1', text: 'ssx1' }}
subsystems={[...defaultSubsystems, twiddler]}
/>
)
expect(e).toIncludeText('Hello from ssx1')
e
.find(Foo)
.at(0)
.props()
.dispatch({ type: 'twiddle' })
expect(e).toIncludeText('Hello from SSX1')
})
})
})