mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-12 04:09:12 +00:00
fix tree hydration issue
This commit is contained in:
@@ -680,18 +680,17 @@ describe('<wa-tree>', () => {
|
||||
</wa-tree-item>
|
||||
</wa-tree>
|
||||
`);
|
||||
|
||||
const treeItems = Array.from<WaTreeItem>(tree.querySelectorAll('wa-tree-item'));
|
||||
|
||||
// Act
|
||||
await tree.updateComplete;
|
||||
await Promise.allSettled(treeItems.map((treeItem) => treeItem.updateComplete))
|
||||
|
||||
// Assert
|
||||
// @TODO: Figure out why this fails in hydration
|
||||
if (fixture.type !== 'ssr-client-hydrated') {
|
||||
treeItems.forEach(treeItem => {
|
||||
expect(treeItem).to.have.attribute('selected');
|
||||
});
|
||||
}
|
||||
treeItems.forEach(treeItem => {
|
||||
expect(treeItem).to.have.attribute('selected');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -716,14 +715,12 @@ describe('<wa-tree>', () => {
|
||||
|
||||
// Act
|
||||
await tree.updateComplete;
|
||||
await Promise.allSettled(treeItems.map((treeItem) => treeItem.updateComplete))
|
||||
|
||||
// Assert
|
||||
// @TODO: Figure out why this fails in hydration
|
||||
if (fixture.type !== 'ssr-client-hydrated') {
|
||||
treeItems.forEach(treeItem => {
|
||||
expect(treeItem).to.have.attribute('selected');
|
||||
});
|
||||
}
|
||||
treeItems.forEach(treeItem => {
|
||||
expect(treeItem).to.have.attribute('selected');
|
||||
});
|
||||
expect(treeItems[0].indeterminate).to.be.false;
|
||||
});
|
||||
});
|
||||
@@ -748,15 +745,11 @@ describe('<wa-tree>', () => {
|
||||
|
||||
// Act
|
||||
await tree.updateComplete;
|
||||
await Promise.allSettled(treeItems.map((treeItem) => treeItem.updateComplete))
|
||||
|
||||
// Assert
|
||||
expect(treeItems[0]).not.to.have.attribute('selected');
|
||||
|
||||
// @TODO: figure out why this fails with SSR.
|
||||
if (fixture.type !== 'ssr-client-hydrated') {
|
||||
expect(treeItems[0].indeterminate).to.be.true;
|
||||
}
|
||||
|
||||
expect(treeItems[0].indeterminate).to.be.true;
|
||||
expect(treeItems[1]).to.have.attribute('selected');
|
||||
expect(treeItems[2]).not.to.have.attribute('selected');
|
||||
expect(treeItems[3]).not.to.have.attribute('selected');
|
||||
@@ -767,7 +760,7 @@ describe('<wa-tree>', () => {
|
||||
});
|
||||
});
|
||||
|
||||
// https://github.com/shoelace-style/shoelace/issues/1916
|
||||
// // https://github.com/shoelace-style/shoelace/issues/1916
|
||||
it("Should not render 'null' if it can't find a custom icon", async () => {
|
||||
const tree = await fixture<WaTree>(html`
|
||||
<wa-tree>
|
||||
|
||||
@@ -141,26 +141,28 @@ export default class WaTree extends WebAwesomeElement {
|
||||
|
||||
// Initializes new items by setting the `selectable` property and the expanded/collapsed icons if any
|
||||
private initTreeItem = (item: WaTreeItem) => {
|
||||
item.selectable = this.selection === 'multiple';
|
||||
item.updateComplete.then(() => {
|
||||
item.selectable = this.selection === 'multiple';
|
||||
|
||||
['expand', 'collapse']
|
||||
.filter(status => !!this.querySelector(`[slot="${status}-icon"]`))
|
||||
.forEach((status: 'expand' | 'collapse') => {
|
||||
const existingIcon = item.querySelector(`[slot="${status}-icon"]`);
|
||||
const expandButtonIcon = this.getExpandButtonIcon(status);
|
||||
['expand', 'collapse']
|
||||
.filter(status => !!this.querySelector(`[slot="${status}-icon"]`))
|
||||
.forEach((status: 'expand' | 'collapse') => {
|
||||
const existingIcon = item.querySelector(`[slot="${status}-icon"]`);
|
||||
const expandButtonIcon = this.getExpandButtonIcon(status);
|
||||
|
||||
if (!expandButtonIcon) return;
|
||||
if (!expandButtonIcon) return;
|
||||
|
||||
if (existingIcon === null) {
|
||||
// No separator exists, add one
|
||||
item.append(expandButtonIcon);
|
||||
} else if (existingIcon.hasAttribute('data-default')) {
|
||||
// A default separator exists, replace it
|
||||
existingIcon.replaceWith(expandButtonIcon);
|
||||
} else {
|
||||
// The user provided a custom icon, leave it alone
|
||||
}
|
||||
});
|
||||
if (existingIcon === null) {
|
||||
// No separator exists, add one
|
||||
item.append(expandButtonIcon);
|
||||
} else if (existingIcon.hasAttribute('data-default')) {
|
||||
// A default separator exists, replace it
|
||||
existingIcon.replaceWith(expandButtonIcon);
|
||||
} else {
|
||||
// The user provided a custom icon, leave it alone
|
||||
}
|
||||
});
|
||||
})
|
||||
};
|
||||
|
||||
private handleTreeChanged = (mutations: MutationRecord[]) => {
|
||||
@@ -359,15 +361,19 @@ export default class WaTree extends WebAwesomeElement {
|
||||
this.setAttribute('aria-multiselectable', isSelectionMultiple ? 'true' : 'false');
|
||||
|
||||
for (const item of items) {
|
||||
item.selectable = isSelectionMultiple;
|
||||
item.updateComplete.then(() => {
|
||||
item.selectable = isSelectionMultiple;
|
||||
})
|
||||
}
|
||||
|
||||
if (isSelectionMultiple) {
|
||||
await this.updateComplete;
|
||||
|
||||
[...this.querySelectorAll(':scope > wa-tree-item')].forEach((treeItem: WaTreeItem) =>
|
||||
syncCheckboxes(treeItem, true)
|
||||
);
|
||||
[...this.querySelectorAll(':scope > wa-tree-item')].forEach((treeItem: WaTreeItem) => {
|
||||
treeItem.updateComplete.then(() => {
|
||||
syncCheckboxes(treeItem, true)
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ import { cleanupFixtures, ssrFixture as LitSSRFixture } from '@lit-labs/testing/
|
||||
import type { LitElement, TemplateResult } from 'lit';
|
||||
import type WebAwesomeElement from '../webawesome-element.js';
|
||||
|
||||
import { getDiffableHTML } from '@open-wc/semantic-dom-diff/get-diffable-html.js'
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
clientComponents: string[];
|
||||
@@ -20,16 +22,16 @@ declare global {
|
||||
/**
|
||||
* This will hopefully move to a library or be built into Lit. Right now this does nothing.
|
||||
*/
|
||||
// function handleHydrationError(e: Event) {
|
||||
// const element = e.target as WebAwesomeElement;
|
||||
// const str = `Expected <${element.localName}> to not have hydration error.`
|
||||
function handleHydrationError(e: Event) {
|
||||
const element = e.target as WebAwesomeElement;
|
||||
const str = `Expected <${element.localName}> to not have hydration error.`
|
||||
|
||||
// expect(false).to.equal(true, str);
|
||||
// }
|
||||
expect(true).to.equal(false, str);
|
||||
}
|
||||
|
||||
// This is a non-standard event I have added to the WebAwesomeElement base class.
|
||||
// https://github.com/lit/lit/discussions/4703
|
||||
// document.addEventListener('lit-hydration-error', handleHydrationError);
|
||||
document.addEventListener('lit-hydration-error', handleHydrationError);
|
||||
|
||||
/**
|
||||
* Loads up a fixture and loads all client components
|
||||
@@ -52,15 +54,16 @@ export async function hydratedFixture<T extends HTMLElement = HTMLElement>(templ
|
||||
hydrate: true
|
||||
});
|
||||
|
||||
// @ts-expect-error Assume its a lit element.
|
||||
await hydratedElement.updateComplete
|
||||
|
||||
// This can be removed when this is fixed: https://github.com/lit/lit/issues/4709
|
||||
// This forces every element to "hydrate" and then wait for an update to complete (hydration)
|
||||
await Promise.allSettled(
|
||||
[...hydratedElement.querySelectorAll<LitElement>('*')].map(el => {
|
||||
[...hydratedElement.querySelectorAll<LitElement>('*')].map(async el => {
|
||||
el.removeAttribute('defer-hydration');
|
||||
return el.updateComplete;
|
||||
}),
|
||||
// @ts-expect-error Assume its a lit element.
|
||||
await hydratedElement.updateComplete
|
||||
);
|
||||
|
||||
return hydratedElement;
|
||||
|
||||
Reference in New Issue
Block a user