Skip to content

Commit

Permalink
better trigger naming, and switch to example tests
Browse files Browse the repository at this point in the history
  • Loading branch information
will-wow committed Mar 10, 2024
1 parent 396400c commit 2c347fb
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 164 deletions.
2 changes: 1 addition & 1 deletion assets/badge.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions htmx/htmx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,9 @@ func ExampleHX_Trigger_nonStandard() {

func ExampleHX_TriggerExtended() {
fmt.Println(hx.TriggerExtended(
trigger.NewEvent("click").Filter("ctrlKey").Target("#element"),
trigger.NewPoll(time.Second),
trigger.NewIntersectEvent().Root("#element").Threshold(0.2),
trigger.On("click").Filter("ctrlKey").Target("#element"),
trigger.Every(time.Second),
trigger.Intersect().Root("#element").Threshold(0.2),
))
// Output: hx-trigger='click[ctrlKey] target:#element, every 1s, intersect root:#element threshold:0.2'
}
Expand Down
12 changes: 6 additions & 6 deletions htmx/trigger/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,17 @@ const (
Revealed TriggerEvent = "revealed" // triggered when an element is scrolled into the viewport (also useful for lazy-loading). If you are using overflow in css like overflow-y: scroll you should use intersect once instead of revealed.
)

// An Event is a builder to create a new user event hx-trigger.
// An Event is a builder to create a new user Event hx-trigger.
type Event struct {
event TriggerEvent
filter string
modifiers map[Modifier]string
}

// NewEvent starts a builder chain for creating a new hx-trigger for user events.
func NewEvent(event TriggerEvent) *Event {
// On starts a builder chain for creating a new hx-trigger for user events.
func On(eventName TriggerEvent) *Event {
return &Event{
event: event,
event: eventName,
filter: "",
modifiers: map[Modifier]string{},
}
Expand Down Expand Up @@ -201,8 +201,8 @@ type IntersectEvent struct {
Event
}

// NewIntersectEvent configures a trigger that fires once when an element first intersects the viewport. This supports additional options to a normal trigger, [IntersectEvent.Root] and [IntersectEvent.Threshold].
func NewIntersectEvent() *IntersectEvent {
// Intersect configures a trigger that fires once when an element first intersects the viewport. This supports additional options to a normal trigger, [IntersectEvent.Root] and [IntersectEvent.Threshold].
func Intersect() *IntersectEvent {
return &IntersectEvent{
Event{
event: "intersect",
Expand Down
31 changes: 18 additions & 13 deletions htmx/trigger/poll.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,32 @@ import (
)

type Poll struct {
string string
timing time.Duration
filter string
}

// Every creates a new polling trigger.
func Every(timing time.Duration) *Poll {
return &Poll{
timing: timing,
filter: "",
}
}

// trigger is a no-op method to satisfy the Trigger interface.
func (p *Poll) trigger() {}

// String returns the final hx-trigger string.
func (p *Poll) String() string {
return p.string
}

// NewPoll creates a new polling trigger.
func NewPoll(timing time.Duration) *Poll {
return &Poll{
string: fmt.Sprintf("every %s", timing.String()),
if p.filter != "" {
return fmt.Sprintf("every %s [%s]", p.timing.String(), p.filter)
}

return fmt.Sprintf("every %s", p.timing.String())
}

// NewPoll creates a new polling trigger with a javascript expression as a filter. When the timer goes off, the trigger will only occur if the expression evaluates to true.
func NewFilteredPoll(timing time.Duration, filter string) *Poll {
return &Poll{
string: fmt.Sprintf("every %s [%s]", timing.String(), filter),
}
// Filter adds a filter to the polling trigger, so that when the timer goes off, the trigger will only occur if the expression evaluates to true.
func (p *Poll) Filter(filter string) *Poll {
p.filter = filter
return p
}
284 changes: 143 additions & 141 deletions htmx/trigger/trigger_test.go
Original file line number Diff line number Diff line change
@@ -1,150 +1,152 @@
package trigger_test

import (
"testing"
"fmt"
"time"

"github.com/will-wow/typed-htmx-go/htmx/trigger"
)

func TestNewEvent(t *testing.T) {
tests := []struct {
name string
trigger trigger.Trigger
want string
}{
{
name: "simple Event",
trigger: trigger.NewEvent("click"),
want: "click",
},
{
name: "Filter",
trigger: trigger.NewEvent("click").Filter("checkGlobalState()"),
want: "click[checkGlobalState()]",
},
{
name: "Once",
trigger: trigger.NewEvent("click").Once(),
want: "click once",
},
{
name: "Changed",
trigger: trigger.NewEvent("click").Changed(),
want: "click changed",
},
{
name: "Delay",
trigger: trigger.NewEvent("click").Delay(time.Second),
want: "click delay:1s",
},
{
name: "Throttle",
trigger: trigger.NewEvent("click").Throttle(500 * time.Millisecond),
want: "click throttle:500ms",
},
{
name: "From",
trigger: trigger.NewEvent("click").From("#element"),
want: "click from:(#element)",
},
{
name: "From with spaces",
trigger: trigger.NewEvent("click").From("parent > child"),
want: "click from:(parent > child)",
},
{
name: "From non-standard",
trigger: trigger.NewEvent("click").From(trigger.FromDocument),
want: "click from:(document)",
},
{
name: "From relative",
trigger: trigger.NewEvent("click").From(
trigger.FromRelative(trigger.Next, "#alert"),
),
want: "click from:next (#alert)",
},
{
name: "From relative with whitespace",
trigger: trigger.NewEvent("click").From(
trigger.FromRelative(trigger.Next, "#alert > button"),
),
want: "click from:next (#alert > button)",
},
{
name: "Target",
trigger: trigger.NewEvent("click").Target("#element"),
want: "click target:#element",
},
{
name: "Target with spaces",
trigger: trigger.NewEvent("click").Target("parent > child"),
want: "click target:(parent > child)",
},
{
name: "Consume",
trigger: trigger.NewEvent("click").Consume(),
want: "click consume",
},
{
name: "Queue",
trigger: trigger.NewEvent("click").Queue(trigger.First),
want: "click queue:first",
},
{
name: "Clear",
trigger: trigger.NewEvent("click").Consume().Clear(trigger.Consume),
want: "click",
},
{
name: "Ordering multiple",
trigger: trigger.NewEvent("click").Filter("isActive").Queue(trigger.First).Consume().Target("#element").From("#parent > #child"),
want: "click[isActive] consume from:(#parent > #child) queue:first target:#element",
},
{
name: "Intersect",
trigger: trigger.NewIntersectEvent(),
want: "intersect",
},
{
name: "Intersect.Root",
trigger: trigger.NewIntersectEvent().Root("#element"),
want: "intersect root:#element",
},
{
name: "Intersect.Root with spaces",
trigger: trigger.NewIntersectEvent().Root("#parent > #child"),
want: "intersect root:(#parent > #child)",
},
{
name: "Intersect.Threshold",
trigger: trigger.NewIntersectEvent().Threshold(0.2),
want: "intersect threshold:0.2",
},
{
name: "Intersect supports other options",
trigger: trigger.NewIntersectEvent().Root("#element").Delay(time.Second),
want: "intersect delay:1s root:#element",
},
{
name: "Poll",
trigger: trigger.NewPoll(5 * time.Second),
want: "every 5s",
},
{
name: "FilteredPoll",
trigger: trigger.NewFilteredPoll(5*time.Second, "isActive"),
want: "every 5s [isActive]",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := tt.trigger.String()
if got != tt.want {
t.Errorf("got %s, want %s", got, tt.want)
}
})
}
func ExampleOn() {
trig := trigger.On("click")
fmt.Println(trig.String())
// Output: click
}

func ExampleEvent_Filter() {
trig := trigger.On("click").Filter("checkGlobalState()")
fmt.Println(trig.String())
// Output: click[checkGlobalState()]
}

func ExampleEvent_Once() {
trig := trigger.On("click").Once()
fmt.Println(trig.String())
// Output: click once
}

func ExampleEvent_Changed() {
trig := trigger.On("click").Changed()
fmt.Println(trig.String())
// Output: click changed
}

func ExampleEvent_Delay() {
trig := trigger.On("click").Delay(time.Second)
fmt.Println(trig.String())
// Output: click delay:1s
}

func ExampleEvent_Throttle() {
trig := trigger.On("click").Throttle(500 * time.Millisecond)
fmt.Println(trig.String())
// Output: click throttle:500ms
}

func ExampleEvent_From() {
trig := trigger.On("click").From("#element")
fmt.Println(trig.String())
// Output: click from:(#element)
}

func ExampleEvent_From_withSpaces() {
trig := trigger.On("click").From("parent > child")
fmt.Println(trig.String())
// Output: click from:(parent > child)
}

func ExampleEvent_From_nonStandard() {
trig := trigger.On("click").From(trigger.FromDocument)
fmt.Println(trig.String())
// Output: click from:(document)
}

func ExampleFromRelative() {
trig := trigger.On("click").From(trigger.FromRelative(trigger.Next, "#alert"))
fmt.Println(trig.String())
// Output: click from:next (#alert)
}

func ExampleFromRelative_withWhitespace() {
trig := trigger.On("click").From(trigger.FromRelative(trigger.Next, "#alert > button"))
fmt.Println(trig.String())
// Output: click from:next (#alert > button)
}

func ExampleEvent_Target() {
trig := trigger.On("click").Target("#element")
fmt.Println(trig.String())
// Output: click target:#element
}

func ExampleEvent_Target_withSpaces() {
trig := trigger.On("click").Target("parent > child")
fmt.Println(trig.String())
// Output: click target:(parent > child)
}

func ExampleEvent_Consume() {
trig := trigger.On("click").Consume()
fmt.Println(trig.String())
// Output: click consume
}

func ExampleEvent_Queue() {
trig := trigger.On("click").Queue(trigger.First)
fmt.Println(trig.String())
// Output: click queue:first
}

func ExampleEvent_Clear() {
trig := trigger.On("click").Consume().Clear(trigger.Consume)
fmt.Println(trig.String())
// Output: click
}

func ExampleOn_ordering_multiple() {
trig := trigger.On("click").Filter("isActive").Queue(trigger.First).Consume().Target("#element").From("#parent > #child")
fmt.Println(trig.String())
// Output: click[isActive] consume from:(#parent > #child) queue:first target:#element
}

func ExampleIntersect() {
trig := trigger.Intersect()
fmt.Println(trig.String())
// Output: intersect
}

func ExampleIntersectEvent_Root() {
trig := trigger.Intersect().Root("#element")
fmt.Println(trig.String())
// Output: intersect root:#element
}

func ExampleIntersectEvent_Root_withSpaces() {
trig := trigger.Intersect().Root("#parent > #child")
fmt.Println(trig.String())
// Output: intersect root:(#parent > #child)
}

func ExampleIntersectEvent_Threshold() {
trig := trigger.Intersect().Threshold(0.2)
fmt.Println(trig.String())
// Output: intersect threshold:0.2
}

func ExampleIntersect_supportsOtherOptions() {
trig := trigger.Intersect().Root("#element").Delay(time.Second)
fmt.Println(trig.String())
// Output: intersect delay:1s root:#element
}

func ExampleEvery() {
trig := trigger.Every(5 * time.Second)
fmt.Println(trig.String())
// Output: every 5s
}

func ExamplePoll_Filter() {
trig := trigger.Every(5 * time.Second).Filter("isActive")
fmt.Println(trig.String())
// Output: every 5s [isActive]
}

0 comments on commit 2c347fb

Please sign in to comment.