Skip to content

Commit

Permalink
[Live] Fixing tests
Browse files Browse the repository at this point in the history
  • Loading branch information
weaverryan committed Feb 9, 2024
1 parent 61870ee commit 8d989c1
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 76 deletions.
1 change: 1 addition & 0 deletions src/LiveComponent/assets/dist/ComponentRegistry.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Component from './Component';
export declare const resetRegistry: () => void;
export declare const registerComponent: (component: Component) => void;
export declare const unregisterComponent: (component: Component) => void;
export declare const getComponent: (element: HTMLElement) => Promise<Component>;
Expand Down
16 changes: 7 additions & 9 deletions src/LiveComponent/assets/dist/live_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,8 @@ function getElementAsTagText(element) {
: element.outerHTML;
}

const componentMapByElement = new WeakMap();
const componentMapByComponent = new Map();
let componentMapByElement = new WeakMap();
let componentMapByComponent = new Map();
const registerComponent = function (component) {
componentMapByElement.set(component.element, component);
componentMapByComponent.set(component, component.name);
Expand Down Expand Up @@ -193,8 +193,7 @@ const getComponent = function (element) {
const findComponents = function (currentComponent, onlyParents, onlyMatchName) {
const components = [];
componentMapByComponent.forEach((componentName, component) => {
if (onlyParents &&
(currentComponent === component || !component.element.contains(currentComponent.element))) {
if (onlyParents && (currentComponent === component || !component.element.contains(currentComponent.element))) {
return;
}
if (onlyMatchName && componentName !== onlyMatchName) {
Expand Down Expand Up @@ -1418,8 +1417,7 @@ function executeMorphdom(rootFromElement, rootToElement, modifiedFieldElements,
}
}
}
if (fromEl.hasAttribute('data-skip-morph')
|| fromEl.id && fromEl.id !== toEl.id) {
if (fromEl.hasAttribute('data-skip-morph') || (fromEl.id && fromEl.id !== toEl.id)) {
fromEl.innerHTML = toEl.innerHTML;
return true;
}
Expand Down Expand Up @@ -3150,9 +3148,9 @@ class LiveControllerDefault extends Controller {
}
onMutations(mutations) {
mutations.forEach((mutation) => {
if (mutation.type === 'attributes'
&& mutation.attributeName === 'id'
&& this.element.id !== this.component.id) {
if (mutation.type === 'attributes' &&
mutation.attributeName === 'id' &&
this.element.id !== this.component.id) {
this.disconnectComponent();
this.createComponent();
this.connectComponent();
Expand Down
9 changes: 7 additions & 2 deletions src/LiveComponent/assets/src/ComponentRegistry.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import Component from './Component';
import getElementAsTagText from './Util/getElementAsTagText';

const componentMapByElement = new WeakMap<HTMLElement, Component>();
let componentMapByElement = new WeakMap<HTMLElement, Component>();
/**
* The value is the component's name.
*/
const componentMapByComponent = new Map<Component, string>();
let componentMapByComponent = new Map<Component, string>();

export const resetRegistry = function () {
componentMapByElement = new WeakMap<HTMLElement, Component>();
componentMapByComponent = new Map<Component, string>();
}

export const registerComponent = function (component: Component) {
componentMapByElement.set(component.element, component);
Expand Down
6 changes: 2 additions & 4 deletions src/LiveComponent/assets/test/Component/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import Component, { proxifyComponent } from '../../src/Component';
import {BackendAction, BackendInterface} from '../../src/Backend/Backend';
import { StimulusElementDriver } from '../../src/Component/ElementDriver';
import BackendRequest from '../../src/Backend/BackendRequest';
import { Response } from 'node-fetch';
import { waitFor } from '@testing-library/dom';
import BackendResponse from '../../src/Backend/BackendResponse';
import { noopElementDriver } from '../tools';

interface MockBackend extends BackendInterface {
actions: BackendAction[],
Expand All @@ -30,11 +30,9 @@ const makeTestComponent = (): { component: Component, backend: MockBackend } =>
'test-component',
{ firstName: '', product: { name: '' } },
[],
() => [],
null,
null,
backend,
new StimulusElementDriver()
new noopElementDriver(),
);

return {
Expand Down
67 changes: 31 additions & 36 deletions src/LiveComponent/assets/test/ComponentRegistry.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import Component from '../src/Component';
import ComponentRegistry from '../src/ComponentRegistry';
import {
registerComponent,
resetRegistry,
getComponent,
findComponents,
} from '../src/ComponentRegistry';
import BackendRequest from '../src/Backend/BackendRequest';
import { BackendInterface } from '../src/Backend/Backend';
import { Response } from 'node-fetch';
import { StimulusElementDriver } from '../src/Component/ElementDriver';
import { noopElementDriver } from './tools';

const createComponent = (element: HTMLElement, name = 'foo-component'): Component => {
const backend: BackendInterface = {
Expand All @@ -22,61 +27,55 @@ const createComponent = (element: HTMLElement, name = 'foo-component'): Componen
name,
{},
[],
() => [],
null,
null,
backend,
new StimulusElementDriver(),
new noopElementDriver(),
);
};

describe('ComponentRegistry', () => {
it('can add and retrieve components', async () => {
const registry = new ComponentRegistry();
beforeEach(() => {
resetRegistry();
});

it('can add and retrieve components', async () => {
const element1 = document.createElement('div');
const component1 = createComponent(element1);
const element2 = document.createElement('div');
const component2 = createComponent(element2);

registry.registerComponent(element1, component1);
registry.registerComponent(element2, component2);
registerComponent(component1);
registerComponent(component2);

const promise1 = registry.getComponent(element1);
const promise2 = registry.getComponent(element2);
const promise1 = getComponent(element1);
const promise2 = getComponent(element2);
await expect(promise1).resolves.toBe(component1);
await expect(promise2).resolves.toBe(component2);
});

it('fails if component is not found soon', async () => {
const registry = new ComponentRegistry();

const element1 = document.createElement('div');
const promise = registry.getComponent(element1);
const promise = getComponent(element1);
expect.assertions(1);
await expect(promise).rejects.toEqual(new Error('Component not found for element <div></div>'));
});

it('can find components in the simple case', () => {
const registry = new ComponentRegistry();

const element1 = document.createElement('div');
const component1 = createComponent(element1);
const element2 = document.createElement('div');
const component2 = createComponent(element2);

registry.registerComponent(element1, component1);
registry.registerComponent(element2, component2);
registerComponent(component1);
registerComponent(component2);

const otherComponent = createComponent(document.createElement('div'));

const components = registry.findComponents(otherComponent, false, null);
const components = findComponents(otherComponent, false, null);
expect(components).toEqual([component1, component2]);
});

it('can find components with only parents', () => {
const registry = new ComponentRegistry();

const element1 = document.createElement('div');
const component1 = createComponent(element1);
const element2 = document.createElement('div');
Expand All @@ -87,46 +86,42 @@ describe('ComponentRegistry', () => {
// put component 2 inside component 1
element1.appendChild(element2);

registry.registerComponent(element1, component1);
registry.registerComponent(element2, component2);
registry.registerComponent(element3, component3);
registerComponent(component1);
registerComponent(component2);
registerComponent(component3);

const components = registry.findComponents(component2, true, null);
const components = findComponents(component2, true, null);
expect(components).toEqual([component1]);
});

it('can find components by name', () => {
const registry = new ComponentRegistry();

const element1 = document.createElement('div');
const component1 = createComponent(element1, 'component-type1');
const element2 = document.createElement('div');
const component2 = createComponent(element2, 'component-type1');
const element3 = document.createElement('div');
const component3 = createComponent(element3, 'component-type2');

registry.registerComponent(element1, component1);
registry.registerComponent(element2, component2);
registry.registerComponent(element3, component3);
registerComponent(component1);
registerComponent(component2);
registerComponent(component3);

const otherComponent = createComponent(document.createElement('div'));

const components = registry.findComponents(otherComponent, false, 'component-type1');
const components = findComponents(otherComponent, false, 'component-type1');
expect(components).toEqual([component1, component2]);
});

it('will find components including itself', () => {
const registry = new ComponentRegistry();

const element1 = document.createElement('div');
const component1 = createComponent(element1, 'component-type1');
const element2 = document.createElement('div');
const component2 = createComponent(element2, 'component-type1');

registry.registerComponent(element1, component1);
registry.registerComponent(element2, component2);
registerComponent(component1);
registerComponent(component2);

const components = registry.findComponents(component2, false, null);
const components = findComponents(component2, false, null);
expect(components).toEqual([component1, component2]);
});
});
16 changes: 16 additions & 0 deletions src/LiveComponent/assets/test/Util/getElementAsTagText.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { htmlToElement } from '../../src/dom_utils';
import getElementAsTagText from '../../src/Util/getElementAsTagText';

describe('getElementAsTagText', () => {
it('returns self-closing tag correctly', () => {
const element = htmlToElement('<input name="user[firstName]">');

expect(getElementAsTagText(element)).toEqual('<input name="user[firstName]">')
});

it('returns tag text without the innerHTML', () => {
const element = htmlToElement('<div class="foo">Name: <input name="user[firstName]"></div>');

expect(getElementAsTagText(element)).toEqual('<div class="foo">')
});
});
32 changes: 7 additions & 25 deletions src/LiveComponent/assets/test/dom_utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import {
htmlToElement,
getModelDirectiveFromElement,
elementBelongsToThisComponent,
getElementAsTagText,
setValueOnElement
} from '../src/dom_utils';
import ValueStore from '../src/Component/ValueStore';
import Component from '../src/Component';
import Backend from '../src/Backend/Backend';
import {StimulusElementDriver} from '../src/Component/ElementDriver';
import { noopElementDriver } from './tools';

const createStore = function(props: any = {}): ValueStore {
return new ValueStore(props);
Expand Down Expand Up @@ -266,21 +266,17 @@ describe('getModelDirectiveFromInput', () => {
});

describe('elementBelongsToThisComponent', () => {
const createComponent = (html: string, childComponents: Component[] = []) => {
const createComponent = (html: string) => {
const component = new Component(
htmlToElement(html),
'some-component',
{},
[],
() => [],
null,
'some-id-' + Math.floor((Math.random() * 100)),
new Backend(''),
new StimulusElementDriver()
new noopElementDriver(),
);
childComponents.forEach((childComponent) => {
component.addChild(childComponent);
})
component.connect();

return component;
};
Expand All @@ -305,37 +301,23 @@ describe('elementBelongsToThisComponent', () => {
const childComponent = createComponent('<div class="child"></div>');
childComponent.element.appendChild(targetElement);

const component = createComponent('<div class="parent"></div>', [childComponent]);
const component = createComponent('<div class="parent"></div>');
component.element.appendChild(childComponent.element);

expect(elementBelongsToThisComponent(targetElement, childComponent)).toBeTruthy();
//expect(elementBelongsToThisComponent(targetElement, childComponent)).toBeTruthy();
expect(elementBelongsToThisComponent(targetElement, component)).toBeFalsy();
});

it('returns false if element *is* a child controller element', () => {
const childComponent = createComponent('<div class="child"></div>');

const component = createComponent('<div class="parent"></div>', [childComponent]);
const component = createComponent('<div class="parent"></div>');
component.element.appendChild(childComponent.element);

expect(elementBelongsToThisComponent(childComponent.element, component)).toBeFalsy();
});
});

describe('getElementAsTagText', () => {
it('returns self-closing tag correctly', () => {
const element = htmlToElement('<input name="user[firstName]">');

expect(getElementAsTagText(element)).toEqual('<input name="user[firstName]">')
});

it('returns tag text without the innerHTML', () => {
const element = htmlToElement('<div class="foo">Name: <input name="user[firstName]"></div>');

expect(getElementAsTagText(element)).toEqual('<div class="foo">')
});
});

describe('htmlToElement', () => {
it('allows to clone HTMLElement', () => {
const element = htmlToElement('<div class="foo">bar</div>');
Expand Down
24 changes: 24 additions & 0 deletions src/LiveComponent/assets/test/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import BackendRequest from '../src/Backend/BackendRequest';
import { Response } from 'node-fetch';
import { setDeepData } from '../src/data_manipulation_utils';
import LiveControllerDefault from '../src/live_controller';
import { ElementDriver } from '../src/Component/ElementDriver';

let activeTests: FunctionalTest[] = [];

Expand Down Expand Up @@ -463,3 +464,26 @@ export function setCurrentSearch(search: string){
export function expectCurrentSearch (){
return expect(decodeURIComponent(window.location.search));
}

export class noopElementDriver implements ElementDriver {
getBrowserEventsToDispatch(): Array<{ event: string; payload: any }> {
throw new Error('Method not implemented.');
}

getComponentProps(): any {
throw new Error('Method not implemented.');
}

getEventsToEmit(): Array<{
event: string;
data: any;
target: string | null;
componentName: string | null
}> {
throw new Error('Method not implemented.');
}

getModelName(element: HTMLElement): string | null {
throw new Error('Method not implemented.');
}
}

0 comments on commit 8d989c1

Please sign in to comment.