@ahmttyydn/java-integration 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/CHANGELOG.md +762 -0
  2. package/README.md +37 -0
  3. package/package.json +46 -0
  4. package/pom.xml +242 -0
  5. package/scalar-core/pom.xml +92 -0
  6. package/scalar-core/src/main/java/com/scalar/maven/core/ScalarConstants.java +26 -0
  7. package/scalar-core/src/main/java/com/scalar/maven/core/ScalarHtmlRenderer.java +135 -0
  8. package/scalar-core/src/main/java/com/scalar/maven/core/ScalarProperties.java +596 -0
  9. package/scalar-core/src/main/java/com/scalar/maven/core/authentication/ScalarAuthenticationOptions.java +235 -0
  10. package/scalar-core/src/main/java/com/scalar/maven/core/authentication/flows/AuthorizationCodeFlow.java +160 -0
  11. package/scalar-core/src/main/java/com/scalar/maven/core/authentication/flows/ClientCredentialsFlow.java +88 -0
  12. package/scalar-core/src/main/java/com/scalar/maven/core/authentication/flows/ImplicitFlow.java +64 -0
  13. package/scalar-core/src/main/java/com/scalar/maven/core/authentication/flows/OAuthFlow.java +185 -0
  14. package/scalar-core/src/main/java/com/scalar/maven/core/authentication/flows/PasswordFlow.java +134 -0
  15. package/scalar-core/src/main/java/com/scalar/maven/core/authentication/flows/ScalarFlows.java +113 -0
  16. package/scalar-core/src/main/java/com/scalar/maven/core/authentication/schemes/ScalarApiKeySecurityScheme.java +77 -0
  17. package/scalar-core/src/main/java/com/scalar/maven/core/authentication/schemes/ScalarHttpSecurityScheme.java +115 -0
  18. package/scalar-core/src/main/java/com/scalar/maven/core/authentication/schemes/ScalarOAuth2SecurityScheme.java +75 -0
  19. package/scalar-core/src/main/java/com/scalar/maven/core/authentication/schemes/ScalarSecurityScheme.java +45 -0
  20. package/scalar-core/src/main/java/com/scalar/maven/core/config/DefaultHttpClient.java +77 -0
  21. package/scalar-core/src/main/java/com/scalar/maven/core/config/ScalarAgentOptions.java +68 -0
  22. package/scalar-core/src/main/java/com/scalar/maven/core/config/ScalarServer.java +197 -0
  23. package/scalar-core/src/main/java/com/scalar/maven/core/config/ScalarSource.java +151 -0
  24. package/scalar-core/src/main/java/com/scalar/maven/core/enums/CredentialsLocation.java +52 -0
  25. package/scalar-core/src/main/java/com/scalar/maven/core/enums/DeveloperToolsVisibility.java +58 -0
  26. package/scalar-core/src/main/java/com/scalar/maven/core/enums/DocumentDownloadType.java +67 -0
  27. package/scalar-core/src/main/java/com/scalar/maven/core/enums/OperationSorter.java +52 -0
  28. package/scalar-core/src/main/java/com/scalar/maven/core/enums/OperationTitleSource.java +52 -0
  29. package/scalar-core/src/main/java/com/scalar/maven/core/enums/Pkce.java +57 -0
  30. package/scalar-core/src/main/java/com/scalar/maven/core/enums/PropertyOrder.java +53 -0
  31. package/scalar-core/src/main/java/com/scalar/maven/core/enums/ScalarClient.java +208 -0
  32. package/scalar-core/src/main/java/com/scalar/maven/core/enums/ScalarLayout.java +52 -0
  33. package/scalar-core/src/main/java/com/scalar/maven/core/enums/ScalarTarget.java +158 -0
  34. package/scalar-core/src/main/java/com/scalar/maven/core/enums/ScalarTheme.java +102 -0
  35. package/scalar-core/src/main/java/com/scalar/maven/core/enums/TagSorter.java +47 -0
  36. package/scalar-core/src/main/java/com/scalar/maven/core/enums/ThemeMode.java +52 -0
  37. package/scalar-core/src/main/java/com/scalar/maven/core/internal/ScalarConfiguration.java +425 -0
  38. package/scalar-core/src/main/java/com/scalar/maven/core/internal/ScalarConfigurationMapper.java +69 -0
  39. package/scalar-core/src/main/resources/META-INF/resources/webjars/scalar/index.html +22 -0
  40. package/scalar-core/src/test/java/com/scalar/maven/core/ScalarConfigurationTest.java +144 -0
  41. package/scalar-core/src/test/java/com/scalar/maven/core/ScalarHtmlRendererTest.java +104 -0
  42. package/scalar-core/src/test/java/com/scalar/maven/core/ScalarPropertiesTest.java +525 -0
  43. package/scalar-core/src/test/java/com/scalar/maven/core/config/DefaultHttpClientTest.java +61 -0
  44. package/scalar-core/src/test/java/com/scalar/maven/core/config/ScalarAgentOptionsTest.java +80 -0
  45. package/scalar-core/src/test/java/com/scalar/maven/core/config/ScalarServerTest.java +118 -0
  46. package/scalar-core/src/test/java/com/scalar/maven/core/config/ScalarSourceTest.java +105 -0
  47. package/scalar-playground-webflux/pom.xml +52 -0
  48. package/scalar-playground-webflux/src/main/java/com/scalar/maven/playground/CustomScalarWebFluxController.java +34 -0
  49. package/scalar-playground-webflux/src/main/java/com/scalar/maven/playground/PlaygroundApplication.java +27 -0
  50. package/scalar-playground-webflux/src/main/resources/application.properties +7 -0
  51. package/scalar-playground-webmvc/pom.xml +52 -0
  52. package/scalar-playground-webmvc/src/main/java/com/scalar/maven/playground/CustomScalarWebMvcController.java +34 -0
  53. package/scalar-playground-webmvc/src/main/java/com/scalar/maven/playground/PlaygroundApplication.java +27 -0
  54. package/scalar-playground-webmvc/src/main/resources/application.properties +7 -0
  55. package/scalar-webflux/pom.xml +110 -0
  56. package/scalar-webflux/src/main/java/com/scalar/maven/webflux/ScalarWebFluxActuatorEndpoint.java +103 -0
  57. package/scalar-webflux/src/main/java/com/scalar/maven/webflux/ScalarWebFluxAutoConfiguration.java +63 -0
  58. package/scalar-webflux/src/main/java/com/scalar/maven/webflux/ScalarWebFluxController.java +109 -0
  59. package/scalar-webflux/src/main/java/com/scalar/maven/webflux/SpringBootScalarProperties.java +43 -0
  60. package/scalar-webflux/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +2 -0
  61. package/scalar-webflux/src/test/java/com/scalar/maven/webflux/ScalarWebFluxActuatorEndpointTest.java +136 -0
  62. package/scalar-webflux/src/test/java/com/scalar/maven/webflux/ScalarWebFluxControllerTest.java +162 -0
  63. package/scalar-webmvc/pom.xml +103 -0
  64. package/scalar-webmvc/src/main/java/com/scalar/maven/webmvc/ScalarWebMvcActuatorEndpoint.java +97 -0
  65. package/scalar-webmvc/src/main/java/com/scalar/maven/webmvc/ScalarWebMvcAutoConfiguration.java +63 -0
  66. package/scalar-webmvc/src/main/java/com/scalar/maven/webmvc/ScalarWebMvcController.java +103 -0
  67. package/scalar-webmvc/src/main/java/com/scalar/maven/webmvc/SpringBootScalarProperties.java +43 -0
  68. package/scalar-webmvc/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +2 -0
  69. package/scalar-webmvc/src/test/java/com/scalar/maven/webmvc/ScalarWebMvcActuatorEndpointTest.java +128 -0
  70. package/scalar-webmvc/src/test/java/com/scalar/maven/webmvc/ScalarWebMvcControllerTest.java +154 -0
@@ -0,0 +1,63 @@
1
+ package com.scalar.maven.webflux;
2
+
3
+ import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
4
+ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
5
+ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
6
+ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
7
+ import org.springframework.boot.context.properties.EnableConfigurationProperties;
8
+ import org.springframework.context.annotation.Bean;
9
+ import org.springframework.context.annotation.Configuration;
10
+
11
+ /**
12
+ * Auto-configuration for the Scalar API Reference integration in Spring WebFlux applications.
13
+ *
14
+ * <p>
15
+ * This class provides automatic configuration for the Scalar API Reference
16
+ * in Spring Boot WebFlux applications. It automatically creates the necessary beans
17
+ * when the scalar integration is enabled.
18
+ * </p>
19
+ *
20
+ * <p>
21
+ * The auto-configuration is conditional on the {@code scalar.enabled} property
22
+ * being set to {@code true} (which is the default).
23
+ * </p>
24
+ *
25
+ * <p>
26
+ * This configuration:
27
+ * </p>
28
+ * <ul>
29
+ * <li>Enables configuration properties via {@link SpringBootScalarProperties}</li>
30
+ * <li>Creates a {@link ScalarWebFluxController} bean for serving the API reference</li>
31
+ * <li>Creates a {@link ScalarWebFluxActuatorEndpoint} bean when actuator is enabled</li>
32
+ * </ul>
33
+ */
34
+ @Configuration
35
+ @EnableConfigurationProperties(SpringBootScalarProperties.class)
36
+ @ConditionalOnProperty(prefix = "scalar", name = "enabled", havingValue = "true", matchIfMissing = true)
37
+ public class ScalarWebFluxAutoConfiguration {
38
+
39
+ /**
40
+ * Creates a ScalarWebFluxController bean.
41
+ *
42
+ * @return a configured ScalarWebFluxController instance
43
+ */
44
+ @Bean
45
+ @ConditionalOnMissingBean(ScalarWebFluxController.class)
46
+ public ScalarWebFluxController scalarWebFluxController() {
47
+ return new ScalarWebFluxController();
48
+ }
49
+
50
+ /**
51
+ * Creates a ScalarWebFluxActuatorEndpoint bean when actuator support is enabled.
52
+ * This endpoint exposes the Scalar UI at /actuator/scalar.
53
+ *
54
+ * @return a configured ScalarWebFluxActuatorEndpoint instance
55
+ */
56
+ @Bean
57
+ @ConditionalOnProperty(prefix = "scalar", name = "actuatorEnabled", havingValue = "true")
58
+ @ConditionalOnClass(name = "org.springframework.boot.actuate.endpoint.annotation.Endpoint")
59
+ @ConditionalOnAvailableEndpoint(endpoint = ScalarWebFluxActuatorEndpoint.class)
60
+ public ScalarWebFluxActuatorEndpoint scalarWebFluxActuatorEndpoint() {
61
+ return new ScalarWebFluxActuatorEndpoint();
62
+ }
63
+ }
@@ -0,0 +1,109 @@
1
+ package com.scalar.maven.webflux;
2
+
3
+ import com.scalar.maven.core.ScalarConstants;
4
+ import com.scalar.maven.core.ScalarHtmlRenderer;
5
+ import com.scalar.maven.core.ScalarProperties;
6
+ import org.springframework.beans.factory.ObjectProvider;
7
+ import org.springframework.beans.factory.annotation.Autowired;
8
+ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
9
+ import org.springframework.core.io.ByteArrayResource;
10
+ import org.springframework.core.io.Resource;
11
+ import org.springframework.http.MediaType;
12
+ import org.springframework.http.server.reactive.ServerHttpRequest;
13
+ import org.springframework.web.bind.annotation.GetMapping;
14
+ import org.springframework.web.bind.annotation.RestController;
15
+ import reactor.core.publisher.Mono;
16
+ import reactor.core.scheduler.Schedulers;
17
+
18
+ import java.io.IOException;
19
+ import java.nio.charset.StandardCharsets;
20
+
21
+ /**
22
+ * REST controller for serving the Scalar API Reference interface in Spring WebFlux applications.
23
+ *
24
+ * <p>
25
+ * This controller provides endpoints for accessing the Scalar API Reference
26
+ * interface and the associated JavaScript bundle. It automatically configures
27
+ * the interface based on the provided {@link ScalarProperties}.
28
+ * </p>
29
+ *
30
+ * <p>
31
+ * The controller serves two main endpoints:
32
+ * </p>
33
+ * <ul>
34
+ * <li>{@code /scalar} (or custom path) - The main API Reference interface</li>
35
+ * <li>{@code /scalar/scalar.js} (or custom path) - The JavaScript bundle</li>
36
+ * </ul>
37
+ *
38
+ * <p>
39
+ * This controller can be extended to customize behavior by overriding the
40
+ * {@link #configureProperties(ScalarProperties, ServerHttpRequest)} method.
41
+ * </p>
42
+ */
43
+ @RestController
44
+ @ConditionalOnMissingBean(ScalarWebFluxController.class)
45
+ public class ScalarWebFluxController {
46
+
47
+ @Autowired
48
+ private ObjectProvider<SpringBootScalarProperties> propertiesProvider;
49
+
50
+ /**
51
+ * Serves the main API Reference interface.
52
+ *
53
+ * <p>
54
+ * This endpoint returns an HTML page that displays the Scalar API Reference
55
+ * interface. The page is configured with the OpenAPI specification URL from
56
+ * the properties.
57
+ * </p>
58
+ *
59
+ * @param request the HTTP request
60
+ * @return a Mono containing a Resource with the HTML content for the API Reference
61
+ * interface
62
+ */
63
+ @GetMapping(value = "${scalar.path:/scalar}", produces = MediaType.TEXT_HTML_VALUE)
64
+ public final Mono<Resource> getDocs(ServerHttpRequest request) {
65
+ return Mono.fromCallable(() -> {
66
+ ScalarProperties properties = propertiesProvider.getObject();
67
+ ScalarProperties configuredProperties = configureProperties(properties, request);
68
+ String html = ScalarHtmlRenderer.render(configuredProperties);
69
+ Resource resource = new ByteArrayResource(html.getBytes(StandardCharsets.UTF_8));
70
+ return resource;
71
+ })
72
+ .subscribeOn(Schedulers.boundedElastic())
73
+ .onErrorMap(IOException.class, e -> new RuntimeException("Failed to render HTML", e));
74
+ }
75
+
76
+ /**
77
+ * Serves the JavaScript bundle for the Scalar API Reference.
78
+ *
79
+ * <p>
80
+ * This endpoint returns the JavaScript file that powers the Scalar API
81
+ * Reference interface. The file is served with the appropriate MIME type.
82
+ * </p>
83
+ *
84
+ * @return a Mono containing a Resource with the JavaScript bundle
85
+ */
86
+ @GetMapping(value = "${scalar.path:/scalar}/" + ScalarConstants.JS_FILENAME, produces = "application/javascript")
87
+ public final Mono<Resource> getScalarJs() {
88
+ return Mono.fromCallable(() -> {
89
+ byte[] jsContent = ScalarHtmlRenderer.getScalarJsContent();
90
+ Resource resource = new ByteArrayResource(jsContent);
91
+ return resource;
92
+ })
93
+ .subscribeOn(Schedulers.boundedElastic())
94
+ .onErrorMap(IOException.class, e -> new RuntimeException("Failed to load JavaScript bundle", e));
95
+ }
96
+
97
+ /**
98
+ * Hook method that allows subclasses to configure properties before rendering.
99
+ * Override this method to customize the ScalarProperties before they are
100
+ * converted to JSON and rendered.
101
+ *
102
+ * @param properties the properties to configure
103
+ * @param request the HTTP request
104
+ * @return the configured properties
105
+ */
106
+ protected ScalarProperties configureProperties(ScalarProperties properties, ServerHttpRequest request) {
107
+ return properties;
108
+ }
109
+ }
@@ -0,0 +1,43 @@
1
+ package com.scalar.maven.webflux;
2
+
3
+ import com.scalar.maven.core.ScalarProperties;
4
+ import org.springframework.boot.context.properties.ConfigurationProperties;
5
+ import org.springframework.context.annotation.Scope;
6
+
7
+ /**
8
+ * Spring Boot configuration properties wrapper for Scalar API Reference integration.
9
+ *
10
+ * <p>
11
+ * This class extends {@link ScalarProperties} and adds Spring Boot's
12
+ * {@link ConfigurationProperties} annotation to enable automatic property binding
13
+ * from Spring Boot configuration files (e.g., application.properties, application.yml).
14
+ * </p>
15
+ *
16
+ * <p>
17
+ * This wrapper allows the core {@link ScalarProperties} class to remain
18
+ * framework-agnostic while providing Spring Boot-specific functionality in the
19
+ * WebFlux integration module.
20
+ * </p>
21
+ *
22
+ * <p>
23
+ * Example usage in application.properties:
24
+ * </p>
25
+ *
26
+ * <pre>
27
+ * scalar.url=https://example.com/openapi.json
28
+ * scalar.path=/docs
29
+ * scalar.enabled=true
30
+ * scalar.showSidebar=true
31
+ * scalar.hideModels=false
32
+ * scalar.darkMode=true
33
+ * scalar.theme=default
34
+ * scalar.layout=modern
35
+ * </pre>
36
+ */
37
+ @ConfigurationProperties(prefix = "scalar")
38
+ @Scope("prototype")
39
+ public class SpringBootScalarProperties extends ScalarProperties {
40
+ // All functionality is inherited from ScalarProperties
41
+ // This class only adds the @ConfigurationProperties annotation
42
+ }
43
+
@@ -0,0 +1,2 @@
1
+ com.scalar.maven.webflux.ScalarWebFluxAutoConfiguration
2
+
@@ -0,0 +1,136 @@
1
+ package com.scalar.maven.webflux;
2
+
3
+ import org.junit.jupiter.api.BeforeEach;
4
+ import org.junit.jupiter.api.DisplayName;
5
+ import org.junit.jupiter.api.Nested;
6
+ import org.junit.jupiter.api.Test;
7
+ import org.junit.jupiter.api.extension.ExtendWith;
8
+ import org.mockito.Mock;
9
+ import org.mockito.junit.jupiter.MockitoExtension;
10
+ import org.springframework.beans.factory.ObjectProvider;
11
+ import org.springframework.core.io.Resource;
12
+ import org.springframework.http.server.reactive.ServerHttpRequest;
13
+ import org.springframework.test.util.ReflectionTestUtils;
14
+ import reactor.core.publisher.Mono;
15
+ import reactor.test.StepVerifier;
16
+
17
+ import java.io.IOException;
18
+ import java.nio.charset.StandardCharsets;
19
+
20
+ import static org.assertj.core.api.Assertions.assertThat;
21
+ import static org.mockito.Mockito.lenient;
22
+ import static org.mockito.Mockito.when;
23
+
24
+ @ExtendWith(MockitoExtension.class)
25
+ @DisplayName("ScalarWebFluxActuatorEndpoint")
26
+ class ScalarWebFluxActuatorEndpointTest {
27
+
28
+ @Mock
29
+ private SpringBootScalarProperties properties;
30
+
31
+ @Mock
32
+ private ObjectProvider<SpringBootScalarProperties> propertiesProvider;
33
+
34
+ @Mock
35
+ private ServerHttpRequest request;
36
+
37
+ private ScalarWebFluxActuatorEndpoint endpoint;
38
+
39
+ @BeforeEach
40
+ void setUp() {
41
+ lenient().when(propertiesProvider.getObject()).thenReturn(properties);
42
+ endpoint = new ScalarWebFluxActuatorEndpoint();
43
+ ReflectionTestUtils.setField(endpoint, "propertiesProvider", propertiesProvider);
44
+ }
45
+
46
+ @Nested
47
+ @DisplayName("Scalar UI Endpoint")
48
+ class ScalarUiEndpoint {
49
+
50
+ @Test
51
+ @DisplayName("should return HTML with default configuration")
52
+ void shouldReturnHtmlWithDefaultConfiguration() {
53
+ // Given
54
+ when(properties.getUrl()).thenReturn("https://registry.scalar.com/@scalar/apis/galaxy?format=json");
55
+ when(properties.getPageTitle()).thenReturn("Scalar API Reference");
56
+ when(properties.getPath()).thenReturn("/scalar");
57
+
58
+ // When
59
+ Mono<Resource> resourceMono = endpoint.scalarUi(request);
60
+
61
+ // Then
62
+ StepVerifier.create(resourceMono)
63
+ .assertNext(resource -> {
64
+ assertThat(resource).isNotNull();
65
+ assertThat(resource.exists()).isTrue();
66
+ try {
67
+ String html = new String(resource.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
68
+ assertThat(html)
69
+ .contains("<!doctype html>")
70
+ .contains("<title>Scalar API Reference</title>")
71
+ .contains("Scalar.createApiReference('#app',");
72
+ } catch (IOException e) {
73
+ throw new RuntimeException(e);
74
+ }
75
+ })
76
+ .verifyComplete();
77
+ }
78
+
79
+ @Test
80
+ @DisplayName("should return HTML with custom URL")
81
+ void shouldReturnHtmlWithCustomUrl() {
82
+ // Given
83
+ when(properties.getUrl()).thenReturn("https://example.com/api/openapi.json");
84
+ when(properties.getPageTitle()).thenReturn("Scalar API Reference");
85
+ when(properties.getPath()).thenReturn("/scalar");
86
+
87
+ // When
88
+ Mono<Resource> resourceMono = endpoint.scalarUi(request);
89
+
90
+ // Then
91
+ StepVerifier.create(resourceMono)
92
+ .assertNext(resource -> {
93
+ assertThat(resource).isNotNull();
94
+ assertThat(resource.exists()).isTrue();
95
+ try {
96
+ String html = new String(resource.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
97
+ assertThat(html)
98
+ .contains("<!doctype html>")
99
+ .contains("<title>Scalar API Reference</title>");
100
+ } catch (IOException e) {
101
+ throw new RuntimeException(e);
102
+ }
103
+ })
104
+ .verifyComplete();
105
+ }
106
+ }
107
+
108
+ @Nested
109
+ @DisplayName("JavaScript Endpoint")
110
+ class JavaScriptEndpoint {
111
+
112
+ @Test
113
+ @DisplayName("should return JavaScript file with correct content type")
114
+ void shouldReturnJavaScriptFileWithCorrectContentType() {
115
+ // When
116
+ Mono<Resource> resourceMono = endpoint.scalarJs();
117
+
118
+ // Then
119
+ StepVerifier.create(resourceMono)
120
+ .assertNext(resource -> {
121
+ assertThat(resource).isNotNull();
122
+ assertThat(resource.exists()).isTrue();
123
+ try {
124
+ byte[] content = resource.getInputStream().readAllBytes();
125
+ assertThat(content)
126
+ .isNotNull()
127
+ .isNotEmpty();
128
+ } catch (IOException e) {
129
+ throw new RuntimeException(e);
130
+ }
131
+ })
132
+ .verifyComplete();
133
+ }
134
+ }
135
+ }
136
+
@@ -0,0 +1,162 @@
1
+ package com.scalar.maven.webflux;
2
+
3
+ import org.junit.jupiter.api.BeforeEach;
4
+ import org.junit.jupiter.api.DisplayName;
5
+ import org.junit.jupiter.api.Nested;
6
+ import org.junit.jupiter.api.Test;
7
+ import org.junit.jupiter.api.extension.ExtendWith;
8
+ import org.mockito.Mock;
9
+ import org.mockito.junit.jupiter.MockitoExtension;
10
+ import org.springframework.beans.factory.ObjectProvider;
11
+ import org.springframework.core.io.Resource;
12
+ import org.springframework.http.server.reactive.ServerHttpRequest;
13
+ import org.springframework.test.util.ReflectionTestUtils;
14
+ import reactor.core.publisher.Mono;
15
+ import reactor.test.StepVerifier;
16
+
17
+ import java.io.IOException;
18
+ import java.nio.charset.StandardCharsets;
19
+
20
+ import static org.assertj.core.api.Assertions.assertThat;
21
+ import static org.mockito.Mockito.lenient;
22
+ import static org.mockito.Mockito.when;
23
+
24
+ @ExtendWith(MockitoExtension.class)
25
+ @DisplayName("ScalarWebFluxController")
26
+ class ScalarWebFluxControllerTest {
27
+
28
+ @Mock
29
+ private SpringBootScalarProperties properties;
30
+
31
+ @Mock
32
+ private ObjectProvider<SpringBootScalarProperties> propertiesProvider;
33
+
34
+ @Mock
35
+ private ServerHttpRequest request;
36
+
37
+ private ScalarWebFluxController controller;
38
+
39
+ @BeforeEach
40
+ void setUp() {
41
+ lenient().when(propertiesProvider.getObject()).thenReturn(properties);
42
+ controller = new ScalarWebFluxController();
43
+ ReflectionTestUtils.setField(controller, "propertiesProvider", propertiesProvider);
44
+ }
45
+
46
+ @Nested
47
+ @DisplayName("GET /scalar endpoint")
48
+ class GetDocsEndpoint {
49
+
50
+ @Test
51
+ @DisplayName("should return HTML with default configuration")
52
+ void shouldReturnHtmlWithDefaultConfiguration() {
53
+ // Given
54
+ when(properties.getUrl()).thenReturn("https://registry.scalar.com/@scalar/apis/galaxy?format=json");
55
+ when(properties.getPageTitle()).thenReturn("Scalar API Reference");
56
+ when(properties.getPath()).thenReturn("/scalar");
57
+
58
+ // When
59
+ Mono<Resource> resourceMono = controller.getDocs(request);
60
+
61
+ // Then
62
+ StepVerifier.create(resourceMono)
63
+ .assertNext(resource -> {
64
+ assertThat(resource).isNotNull();
65
+ assertThat(resource.exists()).isTrue();
66
+ try {
67
+ String html = new String(resource.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
68
+ assertThat(html)
69
+ .contains("<!doctype html>")
70
+ .contains("<title>Scalar API Reference</title>")
71
+ .contains("Scalar.createApiReference('#app',");
72
+ } catch (IOException e) {
73
+ throw new RuntimeException(e);
74
+ }
75
+ })
76
+ .verifyComplete();
77
+ }
78
+
79
+ @Test
80
+ @DisplayName("should return HTML with custom URL")
81
+ void shouldReturnHtmlWithCustomUrl() {
82
+ // Given
83
+ when(properties.getUrl()).thenReturn("https://example.com/api/openapi.json");
84
+ when(properties.getPageTitle()).thenReturn("Scalar API Reference");
85
+ when(properties.getPath()).thenReturn("/scalar");
86
+
87
+ // When
88
+ Mono<Resource> resourceMono = controller.getDocs(request);
89
+
90
+ // Then
91
+ StepVerifier.create(resourceMono)
92
+ .assertNext(resource -> {
93
+ assertThat(resource).isNotNull();
94
+ assertThat(resource.exists()).isTrue();
95
+ try {
96
+ String html = new String(resource.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
97
+ assertThat(html)
98
+ .contains("<!doctype html>")
99
+ .contains("<title>Scalar API Reference</title>");
100
+ } catch (IOException e) {
101
+ throw new RuntimeException(e);
102
+ }
103
+ })
104
+ .verifyComplete();
105
+ }
106
+
107
+ @Test
108
+ @DisplayName("should return HTML with custom pageTitle")
109
+ void shouldReturnHtmlWithCustomPageTitle() {
110
+ // Given
111
+ when(properties.getPageTitle()).thenReturn("My Custom API Documentation");
112
+ when(properties.getPath()).thenReturn("/scalar");
113
+
114
+ // When
115
+ Mono<Resource> resourceMono = controller.getDocs(request);
116
+
117
+ // Then
118
+ StepVerifier.create(resourceMono)
119
+ .assertNext(resource -> {
120
+ assertThat(resource).isNotNull();
121
+ assertThat(resource.exists()).isTrue();
122
+ try {
123
+ String html = new String(resource.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
124
+ assertThat(html)
125
+ .contains("<title>My Custom API Documentation</title>");
126
+ } catch (IOException e) {
127
+ throw new RuntimeException(e);
128
+ }
129
+ })
130
+ .verifyComplete();
131
+ }
132
+ }
133
+
134
+ @Nested
135
+ @DisplayName("GET /scalar/scalar.js endpoint")
136
+ class GetScalarJsEndpoint {
137
+
138
+ @Test
139
+ @DisplayName("should return JavaScript file with correct content type")
140
+ void shouldReturnJavaScriptFileWithCorrectContentType() {
141
+ // When
142
+ Mono<Resource> resourceMono = controller.getScalarJs();
143
+
144
+ // Then
145
+ StepVerifier.create(resourceMono)
146
+ .assertNext(resource -> {
147
+ assertThat(resource).isNotNull();
148
+ assertThat(resource.exists()).isTrue();
149
+ try {
150
+ byte[] content = resource.getInputStream().readAllBytes();
151
+ assertThat(content)
152
+ .isNotNull()
153
+ .isNotEmpty();
154
+ } catch (IOException e) {
155
+ throw new RuntimeException(e);
156
+ }
157
+ })
158
+ .verifyComplete();
159
+ }
160
+ }
161
+ }
162
+
@@ -0,0 +1,103 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project xmlns="http://maven.apache.org/POM/4.0.0"
3
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
5
+ http://maven.apache.org/xsd/maven-4.0.0.xsd">
6
+ <modelVersion>4.0.0</modelVersion>
7
+
8
+ <parent>
9
+ <groupId>com.scalar.maven</groupId>
10
+ <artifactId>scalar-parent</artifactId>
11
+ <version>0.0.0</version>
12
+ </parent>
13
+
14
+ <artifactId>scalar-webmvc</artifactId>
15
+ <packaging>jar</packaging>
16
+
17
+ <name>Scalar API Reference Spring Boot WebMVC</name>
18
+ <description>Spring Boot WebMVC integration for Scalar API Reference</description>
19
+
20
+ <dependencies>
21
+ <!-- Core module -->
22
+ <dependency>
23
+ <groupId>com.scalar.maven</groupId>
24
+ <artifactId>scalar-core</artifactId>
25
+ <version>${project.version}</version>
26
+ </dependency>
27
+
28
+ <!-- Spring Boot WebMVC -->
29
+ <dependency>
30
+ <groupId>org.springframework.boot</groupId>
31
+ <artifactId>spring-boot-starter-web</artifactId>
32
+ <scope>provided</scope>
33
+ </dependency>
34
+
35
+ <!-- Spring Boot Auto-Configuration -->
36
+ <dependency>
37
+ <groupId>org.springframework.boot</groupId>
38
+ <artifactId>spring-boot-autoconfigure</artifactId>
39
+ <scope>provided</scope>
40
+ </dependency>
41
+
42
+ <!-- Spring Boot Configuration Processor -->
43
+ <dependency>
44
+ <groupId>org.springframework.boot</groupId>
45
+ <artifactId>spring-boot-configuration-processor</artifactId>
46
+ <optional>true</optional>
47
+ </dependency>
48
+
49
+ <!-- Spring Boot Actuator -->
50
+ <dependency>
51
+ <groupId>org.springframework.boot</groupId>
52
+ <artifactId>spring-boot-starter-actuator</artifactId>
53
+ <scope>provided</scope>
54
+ </dependency>
55
+
56
+ <!-- Test Dependencies -->
57
+ <dependency>
58
+ <groupId>org.springframework.boot</groupId>
59
+ <artifactId>spring-boot-starter-test</artifactId>
60
+ <scope>test</scope>
61
+ </dependency>
62
+ </dependencies>
63
+
64
+ <build>
65
+ <plugins>
66
+ <plugin>
67
+ <groupId>org.codehaus.mojo</groupId>
68
+ <artifactId>flatten-maven-plugin</artifactId>
69
+ </plugin>
70
+
71
+ <plugin>
72
+ <groupId>org.apache.maven.plugins</groupId>
73
+ <artifactId>maven-compiler-plugin</artifactId>
74
+ </plugin>
75
+
76
+ <plugin>
77
+ <groupId>org.apache.maven.plugins</groupId>
78
+ <artifactId>maven-surefire-plugin</artifactId>
79
+ </plugin>
80
+
81
+ <plugin>
82
+ <groupId>org.apache.maven.plugins</groupId>
83
+ <artifactId>maven-source-plugin</artifactId>
84
+ </plugin>
85
+
86
+ <plugin>
87
+ <groupId>org.apache.maven.plugins</groupId>
88
+ <artifactId>maven-javadoc-plugin</artifactId>
89
+ </plugin>
90
+
91
+ <plugin>
92
+ <groupId>org.apache.maven.plugins</groupId>
93
+ <artifactId>maven-gpg-plugin</artifactId>
94
+ </plugin>
95
+
96
+ <plugin>
97
+ <groupId>org.sonatype.central</groupId>
98
+ <artifactId>central-publishing-maven-plugin</artifactId>
99
+ </plugin>
100
+ </plugins>
101
+ </build>
102
+ </project>
103
+