UNPKG

@riovir/wc-fontawesome

Version:

Web components for Font Awesome

139 lines (116 loc) 4.57 kB
import { definePropsOn, Prop } from './core'; /** * The structure of the property descriptor is inspired by Hybrids.js * However, the implementation is merely a naive subset of the library. * See: https://hybrids.js.org/core-concepts/descriptors#structure * * One important difference is the lack of a caching mechanism. * Derived values are recomputed on every access and don't trigger * the observe until something accesses them. */ describe('definePropsOn', () => { test('descriptor config is optional resulting in mutable prop', () => { const props = { defaults: { connect: (_host, _key) => { /* ignore */ }, get: (_host, value) => value, set: (_host, value) => value, observe: (_host, _key) => { /* ignore */ }, }, blank: {}, }; const { host } = setup({ props }); const expectMutable = prop => { expect(prop in host).toBe(true); expect(host[prop]).toBe(undefined); host[prop] = 'value'; expect(host[prop]).toBe('value'); }; expectMutable('blank'); expectMutable('defaults'); }); test('calls connect hook on host.connectedCallback()', () => { const descriptor = { connect: jest.fn() }; const { host } = setup({ descriptor, connect: false }); expect(descriptor.connect).not.toHaveBeenCalled(); host.connectedCallback(); expect(descriptor.connect).toHaveBeenCalled(); }); test('calls observe on prop change', () => { const descriptor = { observe: jest.fn() }; const { host } = setup({ props: { descriptor } }); expect(descriptor.observe).not.toHaveBeenCalled(); host.descriptor = 'one'; expect(descriptor.observe).toHaveBeenCalledWith(host, 'one', undefined); host.descriptor = 'two'; expect(descriptor.observe).toHaveBeenCalledWith(host, 'two', 'one'); }); test('set returning undefined prevents update', () => { const descriptor = { set: (_, value) => value === 'invalid' ? undefined : value, observe: jest.fn(), }; const { host } = setup({ props: { descriptor } }); host.descriptor = 'ok'; expect(host.descriptor).toBe('ok'); expect(descriptor.observe).toHaveBeenCalledTimes(1); host.descriptor = 'invalid'; expect(descriptor.observe).toHaveBeenCalledTimes(1); expect(host.descriptor).toBe('ok'); }); test('setting identical value skips observe', () => { const descriptor = { observe: jest.fn() }; const { host } = setup({ props: { descriptor } }); host.descriptor = 'clone'; expect(descriptor.observe).toHaveBeenCalledTimes(1); host.descriptor = 'clone'; expect(descriptor.observe).toHaveBeenCalledTimes(1); }); test('changing derived value triggers observe only when used', () => { const triple = { get: ({ number }) => number * 3, observe: jest.fn() }; const { host } = setup({ props: { number: {}, triple } }); expect(triple.observe).not.toHaveBeenCalled(); host.number = 2; expect(triple.observe).not.toHaveBeenCalled(); // This Hybrids.js would've called this. expect(host.triple).toBe(6); expect(triple.observe).toHaveBeenCalled(); }); function setup({ descriptor, props = { descriptor }, connect = true } = {}) { class TestClass {} const host = new TestClass(); definePropsOn(TestClass, props); connect && host.connectedCallback(); return { host }; } }); describe('Prop factory function', () => { test('connect returns when attribute not set', () => { const { host, connect } = setup({ attribute: 'the-foo' }); connect(host, 'theFoo'); expect(host.theFoo).toBe(undefined); }); test('connect returns when prop is already defined', () => { const { host, connect } = setup({ attribute: 'the-foo' }); host.theFoo = 'test prop'; host.setAttribute('the-foo', 'test attribute'); connect(host, 'theFoo'); expect(host.theFoo).toBe('test attribute'); }); test('sets boolean prop to true when blank attribute is present', () => { const { host, connect } = setup({ attribute: 'the-foo', defaultValue: false }); host.setAttribute('the-foo', ''); connect(host, 'theFoo'); expect(host.theFoo).toBe(true); }); test('sets prop value when attribute is set', () => { const { host, connect } = setup({ attribute: 'the-foo' }); host.setAttribute('the-foo', 'a-string'); connect(host, 'theFoo'); expect(host.theFoo).toBe('a-string'); }); function setup({ attribute, defaultValue = null }) { const prop = Prop({ attribute, defaultValue }); const host = document.createElement('div'); return { host, ...prop }; } });