View Javadoc
1   package de.juplo.httpresources;
2   
3   import org.junit.jupiter.api.BeforeEach;
4   import org.junit.jupiter.api.Test;
5   import org.mockserver.integration.ClientAndServer;
6   import org.slf4j.Logger;
7   import org.slf4j.LoggerFactory;
8   import org.springframework.beans.factory.annotation.Autowired;
9   import org.springframework.boot.autoconfigure.SpringBootApplication;
10  import org.springframework.boot.test.context.SpringBootTest;
11  import org.springframework.cache.Cache;
12  import org.springframework.context.annotation.Bean;
13  import org.springframework.test.web.servlet.MockMvc;
14  import org.springframework.test.web.servlet.setup.MockMvcBuilders;
15  import org.springframework.web.context.WebApplicationContext;
16  import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
17  import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
18  import org.springframework.web.servlet.resource.VersionResourceResolver;
19  
20  import java.net.URI;
21  import java.time.Clock;
22  import java.time.Instant;
23  import java.time.ZoneId;
24  
25  import static de.juplo.httpresources.TestUtil.LONG_NOW;
26  import static de.juplo.httpresources.TestUtil.read;
27  import static org.mockserver.verify.VerificationTimes.exactly;
28  import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
29  import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
30  import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
31  import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
32  
33  
34  @SpringBootTest({
35      "juplo.http-resources.protocol-resolver.enabled=true"
36      })
37  public class VersionedResourcesIT extends IntegrationTestBase
38  {
39    private final static Logger LOG =
40        LoggerFactory.getLogger(VersionedResourcesIT.class);
41  
42  
43    @Autowired
44    HttpResources resources;
45    @Autowired
46    Cache cache;
47    @Autowired
48    WebApplicationContext context;
49  
50    MockMvc mvc;
51  
52  
53    @BeforeEach
54    public void setUp()
55    {
56      cache.clear();
57      mvc = MockMvcBuilders
58          .webAppContextSetup(context)
59          .alwaysDo(print())
60          .build();
61    }
62  
63  
64    @Test
65    public void testTransformation() throws Exception
66    {
67      LOG.info("<-- start of test-case");
68  
69      mvc
70          .perform(get(URI.create("http://test/css/static.css")))
71          .andExpect(status().isOk())
72          .andExpect(content().string(read("/transformed/css/static.css")));
73      mvc
74          .perform(get(URI.create("http://test/css/sub/static.css")))
75          .andExpect(status().isOk())
76          .andExpect(content().string(read("/transformed/css/static.css")));
77  
78      mvc
79          .perform(get(URI.create("http://test/css/remote.css")))
80          .andExpect(status().isOk())
81          .andExpect(content().string(read("/transformed/css/remote.css")));
82      mvc
83          .perform(get(URI.create("http://test/css/sub/remote.css")))
84          .andExpect(status().isOk())
85          .andExpect(content().string(read("/transformed/css/remote.css")));
86      mvc
87          .perform(get(URI.create("http://test/css/remote-c901f3a6ab390732242f0fc09ca170e7.css")))
88          .andExpect(status().isOk())
89          .andExpect(content().string(read("/transformed/css/remote.css")));
90      mvc
91          .perform(get(URI.create("http://test/css/sub/remote-c901f3a6ab390732242f0fc09ca170e7.css")))
92          .andExpect(status().isOk())
93          .andExpect(content().string(read("/transformed/css/remote.css")));
94  
95      mvc
96          .perform(get(URI.create("http://test/css/fallback.css")))
97          .andExpect(status().isOk())
98          .andExpect(content().string(read("/transformed/css/static.css")));
99      mvc
100         .perform(get(URI.create("http://test/css/sub/fallback.css")))
101         .andExpect(status().isOk())
102         .andExpect(content().string(read("/transformed/css/static.css")));
103     mvc
104         .perform(get(URI.create("http://test/css/fallback-c901f3a6ab390732242f0fc09ca170e7.css")))
105         .andExpect(status().isOk())
106         .andExpect(content().string(read("/transformed/css/static.css")));
107     mvc
108         .perform(get(URI.create("http://test/css/sub/fallback-c901f3a6ab390732242f0fc09ca170e7.css")))
109         .andExpect(status().isOk())
110         .andExpect(content().string(read("/transformed/css/static.css")));
111 
112     mvc
113         .perform(get(URI.create("http://test/css/static-c901f3a6ab390732242f0fc09ca170e7.css")))
114         .andExpect(status().isOk())
115         .andExpect(content().string(read("/transformed/css/static.css")));
116     mvc
117         .perform(get(URI.create("http://test/css/remote.css")))
118         .andExpect(status().isOk())
119         .andExpect(content().string(read("/transformed/css/remote.css")));
120     mvc
121         .perform(get(URI.create("http://test/css/remote-c901f3a6ab390732242f0fc09ca170e7.css")))
122         .andExpect(status().isOk())
123         .andExpect(content().string(read("/transformed/css/remote.css")));
124     mvc
125         .perform(get(URI.create("http://test/css/static-c901f3a6ab390732242f0fc09ca170e7.css")))
126         .andExpect(status().isOk())
127         .andExpect(content().string(read("/transformed/css/static.css")));
128 
129     server.verify(FETCH("/css/remote.css"), exactly(1));
130     server.verify(FETCH("/css/fallback.css"), exactly(8));
131   }
132 
133 
134   @SpringBootApplication
135   public static class Application implements WebMvcConfigurer
136   {
137     @Bean
138     public Clock clock()
139     {
140       return Clock.fixed(Instant.ofEpochMilli(LONG_NOW), ZoneId.systemDefault());
141     }
142 
143     @Bean
144     public VersionResourceResolver versionResourceResolver()
145     {
146       VersionResourceResolver resolver = new VersionResourceResolver();
147       resolver.addFixedVersionStrategy("v12", "/img/**");
148       resolver.addContentVersionStrategy("/**");
149       return resolver;
150     }
151 
152 
153     @Autowired
154     VersionResourceResolver versionResourceResolver;
155     @Autowired
156     ClientAndServer server;
157 
158     @Override
159     public void addResourceHandlers(ResourceHandlerRegistry registry)
160     {
161       registry
162           .addResourceHandler("/**")
163           .addResourceLocations(
164               "classpath:/static/",
165               "http://localhost:" + server.getLocalPort(),
166               "classpath:/fallback/")
167           .resourceChain(true)
168           .addResolver(versionResourceResolver);
169     }
170   }
171 }