From 2c347fbb5e3e796631d5fab2e1d588aee82c3081 Mon Sep 17 00:00:00 2001 From: Will Ockelmann-Wagner Date: Sun, 10 Mar 2024 01:33:56 -0800 Subject: [PATCH] better trigger naming, and switch to example tests --- assets/badge.svg | 2 +- htmx/htmx_test.go | 6 +- htmx/trigger/event.go | 12 +- htmx/trigger/poll.go | 31 ++-- htmx/trigger/trigger_test.go | 284 ++++++++++++++++++----------------- 5 files changed, 171 insertions(+), 164 deletions(-) diff --git a/assets/badge.svg b/assets/badge.svg index 13f5994..e90fcc6 100644 --- a/assets/badge.svg +++ b/assets/badge.svg @@ -1 +1 @@ -coverage: 80.5%coverage80.5% \ No newline at end of file +coverage: 80.7%coverage80.7% \ No newline at end of file diff --git a/htmx/htmx_test.go b/htmx/htmx_test.go index b4e9d1d..6700a00 100644 --- a/htmx/htmx_test.go +++ b/htmx/htmx_test.go @@ -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' } diff --git a/htmx/trigger/event.go b/htmx/trigger/event.go index 7d0ed3d..526e11f 100644 --- a/htmx/trigger/event.go +++ b/htmx/trigger/event.go @@ -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{}, } @@ -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", diff --git a/htmx/trigger/poll.go b/htmx/trigger/poll.go index ffbf82c..ccaf39f 100644 --- a/htmx/trigger/poll.go +++ b/htmx/trigger/poll.go @@ -6,7 +6,16 @@ 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. @@ -14,19 +23,15 @@ 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 } diff --git a/htmx/trigger/trigger_test.go b/htmx/trigger/trigger_test.go index d45f5fc..438a28f 100644 --- a/htmx/trigger/trigger_test.go +++ b/htmx/trigger/trigger_test.go @@ -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] }