Skip to content

Commit e38381e

Browse files
committed
abstracting last bits of markup out of component
Fixing bad test exposed by new inability to compare promise resolve callback Removing old child test
1 parent 30619de commit e38381e

File tree

5 files changed

+36
-261
lines changed

5 files changed

+36
-261
lines changed

src/LiveComponent/assets/src/Component/ElementDriver.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ export interface ElementDriver {
1111
getComponentData(rootElement: HTMLElement): any;
1212

1313
getComponentProps(rootElement: HTMLElement): any;
14+
15+
/**
16+
* Given an HtmlElement and a child id, find the root element for that child.
17+
*/
18+
findChildComponentElement(id: string, element: HTMLElement): HTMLElement|null;
19+
20+
/**
21+
* Given an element, find the "key" that should be used to identify it;
22+
*/
23+
getKeyFromElement(element: HTMLElement): string|null;
1424
}
1525

1626
export class StandardElementDriver implements ElementDriver {
@@ -39,4 +49,12 @@ export class StandardElementDriver implements ElementDriver {
3949

4050
return JSON.parse(rootElement.dataset.livePropsValue as string);
4151
}
52+
53+
findChildComponentElement(id: string, element: HTMLElement): HTMLElement|null {
54+
return element.querySelector(`[data-live-id=${id}]`);
55+
}
56+
57+
getKeyFromElement(element: HTMLElement): string|null {
58+
return element.dataset.liveId || null;
59+
}
4260
}

src/LiveComponent/assets/src/Component/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,9 @@ export default class Component {
298298
newElement,
299299
this.unsyncedInputsTracker.getUnsyncedInputs(),
300300
(element: HTMLElement) => getValueFromElement(element, this.valueStore),
301-
Array.from(this.getChildren().values())
301+
Array.from(this.getChildren().values()),
302+
this.elementDriver.findChildComponentElement,
303+
this.elementDriver.getKeyFromElement
302304
);
303305

304306
// reset the modified values back to their client-side version

src/LiveComponent/assets/src/morphdom.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@ export function executeMorphdom(
1515
modifiedElements: Array<HTMLElement>,
1616
getElementValue: (element: HTMLElement) => any,
1717
childComponents: Component[],
18+
findChildComponent: (id: string, element: HTMLElement) => HTMLElement|null,
19+
getKeyFromElement: (element: HTMLElement) => string|null,
1820
) {
1921
const childComponentMap: Map<HTMLElement, Component> = new Map();
2022
childComponents.forEach((childComponent) => {
2123
childComponentMap.set(childComponent.element, childComponent);
22-
// TODO: add driver to make this agnostic
23-
const childComponentToElement = rootToElement.querySelector(`[data-live-id=${childComponent.id}]`)
24+
if (!childComponent.id) {
25+
throw new Error('Child is missing id.');
26+
}
27+
const childComponentToElement = findChildComponent(childComponent.id, rootToElement);
2428
if (childComponentToElement && childComponentToElement.tagName !== childComponent.element.tagName) {
2529
// we need to "correct" the tag name for the child to match the "from"
2630
// so that we always get a "diff", not a remove/add
@@ -35,8 +39,7 @@ export function executeMorphdom(
3539
return;
3640
}
3741

38-
// TODO: abstract out to make this function agnostic of markup
39-
return node.dataset.liveId;
42+
return getKeyFromElement(node);
4043
},
4144
onBeforeElUpdated: (fromEl, toEl) => {
4245
if (fromEl === rootFromElement) {

src/LiveComponent/assets/test/controller/child.test.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,15 @@ describe('LiveController parent -> child component tests', () => {
5151

5252
const parentComponent = test.component;
5353
const childComponent = getComponent(getByTestId(test.element, 'child'));
54+
// setting a marker to help verify THIS exact Component instance continues to be used
55+
childComponent.fingerprint = 'FOO-FINGERPRINT';
5456

5557
// check that the relationships all loaded correctly
5658
expect(parentComponent.getChildren().size).toEqual(1);
57-
expect(parentComponent.getChildren().get('the-child-id')).toEqual(childComponent);
58-
expect(childComponent.getParent()).toEqual(parentComponent);
59+
// check fingerprint instead of checking object equality with childComponent
60+
// because childComponent is actually the proxied Component
61+
expect(parentComponent.getChildren().get('the-child-id')?.fingerprint).toEqual('FOO-FINGERPRINT');
62+
expect(childComponent.getParent()).toBe(parentComponent);
5963

6064
// remove the child
6165
childComponent.element.remove();
@@ -66,7 +70,7 @@ describe('LiveController parent -> child component tests', () => {
6670
// now put it back!
6771
test.element.appendChild(childComponent.element);
6872
await waitFor(() => expect(parentComponent.getChildren().size).toEqual(1));
69-
expect(parentComponent.getChildren().get('the-child-id')).toEqual(childComponent);
73+
expect(parentComponent.getChildren().get('the-child-id')?.fingerprint).toEqual('FOO-FINGERPRINT');
7074
expect(childComponent.getParent()).toEqual(parentComponent);
7175

7276
// now remove the whole darn thing!
@@ -78,7 +82,7 @@ describe('LiveController parent -> child component tests', () => {
7882
// put it *all* back
7983
document.body.appendChild(test.element);
8084
await waitFor(() => expect(parentComponent.getChildren().size).toEqual(1));
81-
expect(parentComponent.getChildren().get('the-child-id')).toEqual(childComponent);
85+
expect(parentComponent.getChildren().get('the-child-id')?.fingerprint).toEqual('FOO-FINGERPRINT');
8286
expect(childComponent.getParent()).toEqual(parentComponent);
8387
});
8488

src/LiveComponent/assets/test/controller/child.test.ts.todo

Lines changed: 0 additions & 252 deletions
This file was deleted.

0 commit comments

Comments
 (0)