Skip to content

Commit

Permalink
Restrict mapping to the handler method to target and triggered elemen…
Browse files Browse the repository at this point in the history
…t in @HxRequest
  • Loading branch information
xhaggi committed Oct 4, 2023
1 parent 2c463cc commit 2c9952d
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package io.github.wimdeblauwe.htmx.spring.boot.mvc;

import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.mvc.condition.HeadersRequestCondition;
import org.springframework.web.servlet.mvc.condition.RequestCondition;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;
import java.util.ArrayList;

import static io.github.wimdeblauwe.htmx.spring.boot.mvc.HtmxRequestHeader.HX_REQUEST;
import static io.github.wimdeblauwe.htmx.spring.boot.mvc.HtmxRequestHeader.*;

public class HtmxRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
@Override
Expand All @@ -24,7 +26,20 @@ protected RequestCondition<?> getCustomMethodCondition(Method method) {

private RequestCondition<?> createCondition(HxRequest hxRequest) {
if (hxRequest != null) {
return new HeadersRequestCondition(HX_REQUEST.getValue());
var requestHeaders = new ArrayList<String>();
requestHeaders.add(HX_REQUEST.getValue());

if (StringUtils.hasText(hxRequest.target())) {
requestHeaders.add(HX_TARGET.getValue() + "=" + hxRequest.target());
}
if (StringUtils.hasText(hxRequest.triggerId())) {
requestHeaders.add(HX_TRIGGER.getValue() + "=" + hxRequest.triggerId());
}
if (StringUtils.hasText(hxRequest.triggerName())) {
requestHeaders.add(HX_TRIGGER_NAME.getValue() + "=" + hxRequest.triggerName());
}

return new HeadersRequestCondition(requestHeaders.toArray(String[]::new));
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,25 @@
import java.lang.annotation.Target;

/**
* Annotation for mapping htmx requests onto specific handler methods.
* Annotation for mapping htmx requests onto specific handler method.
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface HxRequest {

/**
* Restricts the mapping to the {@code id} of the target element.
*/
String target() default "";

/**
* Restricts the mapping to the {@code id} of the triggered element.
*/
String triggerId() default "";

/**
* Restricts the mapping to the {@code name} of the triggered element.
*/
String triggerName() default "";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package io.github.wimdeblauwe.htmx.spring.boot.mvc;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;

import static io.github.wimdeblauwe.htmx.spring.boot.mvc.HtmxRequestHeader.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WebMvcTest(HtmxRequestMappingHandlerMappingTestController.class)
@WithMockUser
public class HtmxRequestMappingHandlerMappingTest {

@Autowired
private MockMvc mockMvc;
@MockBean
private TestService service;

@Test
void testHxRequestWithTargetBar() throws Exception {
mockMvc.perform(get("/hx-request-with-target")
.header(HX_REQUEST.getValue(), "true")
.header(HX_TARGET.getValue(), "bar"))
.andExpect(status().isOk())
.andExpect(content().string("bar"));
}

@Test
void testHxRequestWithTargetFoo() throws Exception {
mockMvc.perform(get("/hx-request-with-target")
.header(HX_REQUEST.getValue(), "true")
.header(HX_TARGET.getValue(), "foo"))
.andExpect(status().isOk())
.andExpect(content().string("foo"));
}

@Test
void testHxRequestWithTriggerIdBar() throws Exception {
mockMvc.perform(get("/hx-request-with-trigger-id")
.header(HX_REQUEST.getValue(), "true")
.header(HX_TRIGGER.getValue(), "bar"))
.andExpect(status().isOk())
.andExpect(content().string("bar"));
}

@Test
void testHxRequestWithTriggerIdFoo() throws Exception {
mockMvc.perform(get("/hx-request-with-trigger-id")
.header(HX_REQUEST.getValue(), "true")
.header(HX_TRIGGER.getValue(), "foo"))
.andExpect(status().isOk())
.andExpect(content().string("foo"));
}

@Test
void testHxRequestWithTriggerNameBar() throws Exception {
mockMvc.perform(get("/hx-request-with-trigger-name")
.header(HX_REQUEST.getValue(), "true")
.header(HX_TRIGGER_NAME.getValue(), "bar"))
.andExpect(status().isOk())
.andExpect(content().string("bar"));
}

@Test
void testHxRequestWithTriggerNameFoo() throws Exception {
mockMvc.perform(get("/hx-request-with-trigger-name")
.header(HX_REQUEST.getValue(), "true")
.header(HX_TRIGGER_NAME.getValue(), "foo"))
.andExpect(status().isOk())
.andExpect(content().string("foo"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package io.github.wimdeblauwe.htmx.spring.boot.mvc;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HtmxRequestMappingHandlerMappingTestController {

@HxRequest(target = "bar")
@GetMapping("/hx-request-with-target")
@ResponseBody
public String hxRequestWithTargetBar() {
return "bar";
}

@HxRequest(target = "foo")
@GetMapping("/hx-request-with-target")
@ResponseBody
public String hxRequestWithTargetFoo() {
return "foo";
}

@HxRequest(triggerId = "bar")
@GetMapping("/hx-request-with-trigger-id")
@ResponseBody
public String hxRequestWithTriggerIdBar() {
return "bar";
}

@HxRequest(triggerId = "foo")
@GetMapping("/hx-request-with-trigger-id")
@ResponseBody
public String hxRequestWithTriggerIdFoo() {
return "foo";
}

@HxRequest(triggerName = "bar")
@GetMapping("/hx-request-with-trigger-name")
@ResponseBody
public String hxRequestWithTriggerNameBar() {
return "bar";
}

@HxRequest(triggerName = "foo")
@GetMapping("/hx-request-with-trigger-name")
@ResponseBody
public String hxRequestWithTriggerNameFoo() {
return "foo";
}

}

0 comments on commit 2c9952d

Please sign in to comment.