-
Notifications
You must be signed in to change notification settings - Fork 601
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(fast-element): enable children and slotted filters (#3323)
* feat(fast-element): enable children and slotted filters * doc(fast-element): update roadmap to remove completed task * fix(fast-element): only filter slot/children when there's a real filter
- Loading branch information
1 parent
ca653cc
commit 224df54
Showing
7 changed files
with
317 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
139 changes: 139 additions & 0 deletions
139
packages/web-components/fast-element/src/directives/children.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
import { expect } from "chai"; | ||
import { children, ChildrenBehavior } from "./children"; | ||
import { AttachedBehaviorDirective } from "./directive"; | ||
import { observable } from "../observation/observable"; | ||
import { elements } from "./node-observation"; | ||
import { DOM } from "../dom"; | ||
|
||
describe("The children", () => { | ||
context("template function", () => { | ||
it("returns an AttachedBehaviorDirective", () => { | ||
const directive = children("test"); | ||
expect(directive).to.be.instanceOf(AttachedBehaviorDirective); | ||
}); | ||
}); | ||
|
||
context("directive", () => { | ||
it("creates a ChildrenBehavior", () => { | ||
const directive = children("test") as AttachedBehaviorDirective; | ||
const target = document.createElement("div"); | ||
const behavior = directive.createBehavior(target); | ||
|
||
expect(behavior).to.be.instanceOf(ChildrenBehavior); | ||
}); | ||
}); | ||
|
||
context("behavior", () => { | ||
class Model { | ||
@observable nodes; | ||
} | ||
|
||
function createAndAppendChildren(host: HTMLElement, elementName = "div") { | ||
const children = new Array(10); | ||
|
||
for (let i = 0, ii = children.length; i < ii; ++i) { | ||
const child = document.createElement(i % 1 === 0 ? elementName : "div"); | ||
children[i] = child; | ||
host.appendChild(child); | ||
} | ||
|
||
return children; | ||
} | ||
|
||
function createDOM(elementName: string = "div") { | ||
const host = document.createElement("div"); | ||
const children = createAndAppendChildren(host, elementName); | ||
|
||
return { host, children }; | ||
} | ||
|
||
it("gathers child nodes", () => { | ||
const { host, children } = createDOM(); | ||
const behavior = new ChildrenBehavior(host, { | ||
property: "nodes", | ||
childList: true, | ||
}); | ||
const model = new Model(); | ||
|
||
behavior.bind(model); | ||
|
||
expect(model.nodes).members(children); | ||
}); | ||
|
||
it("gathers child nodes with a filter", () => { | ||
const { host, children } = createDOM("foo-bar"); | ||
const behavior = new ChildrenBehavior(host, { | ||
property: "nodes", | ||
childList: true, | ||
filter: elements("foo-bar"), | ||
}); | ||
const model = new Model(); | ||
|
||
behavior.bind(model); | ||
|
||
expect(model.nodes).members(children.filter(elements("foo-bar"))); | ||
}); | ||
|
||
it("updates child nodes when they change", async () => { | ||
const { host, children } = createDOM("foo-bar"); | ||
const behavior = new ChildrenBehavior(host, { | ||
property: "nodes", | ||
childList: true, | ||
}); | ||
const model = new Model(); | ||
|
||
behavior.bind(model); | ||
|
||
expect(model.nodes).members(children); | ||
|
||
const updatedChildren = children.concat(createAndAppendChildren(host)); | ||
|
||
await DOM.nextUpdate(); | ||
|
||
expect(model.nodes).members(updatedChildren); | ||
}); | ||
|
||
it("updates child nodes when they change with a filter", async () => { | ||
const { host, children } = createDOM("foo-bar"); | ||
const behavior = new ChildrenBehavior(host, { | ||
property: "nodes", | ||
childList: true, | ||
filter: elements("foo-bar"), | ||
}); | ||
const model = new Model(); | ||
|
||
behavior.bind(model); | ||
|
||
expect(model.nodes).members(children); | ||
|
||
const updatedChildren = children.concat(createAndAppendChildren(host)); | ||
|
||
await DOM.nextUpdate(); | ||
|
||
expect(model.nodes).members(updatedChildren.filter(elements("foo-bar"))); | ||
}); | ||
|
||
it("clears and unwatches when unbound", async () => { | ||
const { host, children } = createDOM("foo-bar"); | ||
const behavior = new ChildrenBehavior(host, { | ||
property: "nodes", | ||
childList: true, | ||
}); | ||
const model = new Model(); | ||
|
||
behavior.bind(model); | ||
|
||
expect(model.nodes).members(children); | ||
|
||
behavior.unbind(); | ||
|
||
expect(model.nodes).members([]); | ||
|
||
host.appendChild(document.createElement("div")); | ||
|
||
await DOM.nextUpdate(); | ||
|
||
expect(model.nodes).members([]); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
132 changes: 132 additions & 0 deletions
132
packages/web-components/fast-element/src/directives/slotted.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
import { expect } from "chai"; | ||
import { slotted, SlottedBehavior } from "./slotted"; | ||
import { AttachedBehaviorDirective } from "./directive"; | ||
import { observable } from "../observation/observable"; | ||
import { elements } from "./node-observation"; | ||
import { DOM } from "../dom"; | ||
|
||
describe("The slotted", () => { | ||
context("template function", () => { | ||
it("returns an AttachedBehaviorDirective", () => { | ||
const directive = slotted("test"); | ||
expect(directive).to.be.instanceOf(AttachedBehaviorDirective); | ||
}); | ||
}); | ||
|
||
context("directive", () => { | ||
it("creates a SlottedBehavior", () => { | ||
const directive = slotted("test") as AttachedBehaviorDirective; | ||
const target = document.createElement("slot"); | ||
const behavior = directive.createBehavior(target); | ||
|
||
expect(behavior).to.be.instanceOf(SlottedBehavior); | ||
}); | ||
}); | ||
|
||
context("behavior", () => { | ||
class Model { | ||
@observable nodes; | ||
} | ||
|
||
function createAndAppendChildren(host: HTMLElement, elementName = "div") { | ||
const children = new Array(10); | ||
|
||
for (let i = 0, ii = children.length; i < ii; ++i) { | ||
const child = document.createElement(i % 1 === 0 ? elementName : "div"); | ||
children[i] = child; | ||
host.appendChild(child); | ||
} | ||
|
||
return children; | ||
} | ||
|
||
function createDOM(elementName: string = "div") { | ||
const host = document.createElement("div"); | ||
const slot = document.createElement("slot"); | ||
const shadowRoot = host.attachShadow({ mode: "open" }); | ||
const children = createAndAppendChildren(host, elementName); | ||
|
||
shadowRoot.appendChild(slot); | ||
|
||
return { host, slot, children }; | ||
} | ||
|
||
it("gathers nodes from a slot", () => { | ||
const { host, slot, children } = createDOM(); | ||
const behavior = new SlottedBehavior(slot, { property: "nodes" }); | ||
const model = new Model(); | ||
|
||
behavior.bind(model); | ||
|
||
expect(model.nodes).members(children); | ||
}); | ||
|
||
it("gathers nodes from a slot with a filter", () => { | ||
const { host, slot, children } = createDOM("foo-bar"); | ||
const behavior = new SlottedBehavior(slot, { | ||
property: "nodes", | ||
filter: elements("foo-bar"), | ||
}); | ||
const model = new Model(); | ||
|
||
behavior.bind(model); | ||
|
||
expect(model.nodes).members(children.filter(elements("foo-bar"))); | ||
}); | ||
|
||
it("updates when slotted nodes change", async () => { | ||
const { host, slot, children } = createDOM("foo-bar"); | ||
const behavior = new SlottedBehavior(slot, { property: "nodes" }); | ||
const model = new Model(); | ||
|
||
behavior.bind(model); | ||
|
||
expect(model.nodes).members(children); | ||
|
||
const updatedChildren = children.concat(createAndAppendChildren(host)); | ||
|
||
await DOM.nextUpdate(); | ||
|
||
expect(model.nodes).members(updatedChildren); | ||
}); | ||
|
||
it("updates when slotted nodes change with a filter", async () => { | ||
const { host, slot, children } = createDOM("foo-bar"); | ||
const behavior = new SlottedBehavior(slot, { | ||
property: "nodes", | ||
filter: elements("foo-bar"), | ||
}); | ||
const model = new Model(); | ||
|
||
behavior.bind(model); | ||
|
||
expect(model.nodes).members(children); | ||
|
||
const updatedChildren = children.concat(createAndAppendChildren(host)); | ||
|
||
await DOM.nextUpdate(); | ||
|
||
expect(model.nodes).members(updatedChildren.filter(elements("foo-bar"))); | ||
}); | ||
|
||
it("clears and unwatches when unbound", async () => { | ||
const { host, slot, children } = createDOM("foo-bar"); | ||
const behavior = new SlottedBehavior(slot, { property: "nodes" }); | ||
const model = new Model(); | ||
|
||
behavior.bind(model); | ||
|
||
expect(model.nodes).members(children); | ||
|
||
behavior.unbind(); | ||
|
||
expect(model.nodes).members([]); | ||
|
||
host.appendChild(document.createElement("div")); | ||
|
||
await DOM.nextUpdate(); | ||
|
||
expect(model.nodes).members([]); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters