View Javadoc
1   /*
2    * Copyright 2022-2026 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.bremersee.geojson.spring.boot.autoconfigure;
18  
19  import static org.assertj.core.api.Assertions.assertThat;
20  
21  import java.util.Arrays;
22  import java.util.List;
23  import org.bremersee.geojson.GeoJsonFeature;
24  import org.bremersee.geojson.GeoJsonFeatureCollection;
25  import org.bremersee.geojson.GeoJsonGeometryFactory;
26  import org.bremersee.geojson.spring.boot.autoconfigure.app.GeometryEntity;
27  import org.bremersee.geojson.spring.boot.autoconfigure.app.GeometryEntityRepository;
28  import org.bremersee.geojson.spring.boot.autoconfigure.app.TestConfiguration;
29  import org.junit.jupiter.api.MethodOrderer;
30  import org.junit.jupiter.api.Order;
31  import org.junit.jupiter.api.Test;
32  import org.junit.jupiter.api.TestMethodOrder;
33  import org.locationtech.jts.geom.Coordinate;
34  import org.locationtech.jts.geom.Geometry;
35  import org.locationtech.jts.geom.LineString;
36  import org.locationtech.jts.geom.LinearRing;
37  import org.locationtech.jts.geom.MultiPoint;
38  import org.locationtech.jts.geom.Point;
39  import org.locationtech.jts.geom.Polygon;
40  import org.springframework.beans.factory.annotation.Autowired;
41  import org.springframework.boot.test.context.SpringBootTest;
42  import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
43  import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
44  import org.springframework.boot.webtestclient.autoconfigure.AutoConfigureWebTestClient;
45  import org.springframework.context.annotation.ComponentScan;
46  import org.springframework.core.ParameterizedTypeReference;
47  import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
48  import org.springframework.test.annotation.DirtiesContext;
49  import org.springframework.test.annotation.DirtiesContext.ClassMode;
50  import org.springframework.test.web.reactive.server.WebTestClient;
51  import org.testcontainers.containers.MongoDBContainer;
52  import org.testcontainers.junit.jupiter.Container;
53  import org.testcontainers.junit.jupiter.Testcontainers;
54  import org.testcontainers.utility.DockerImageName;
55  import reactor.core.publisher.Mono;
56  
57  /**
58   * The geo json autoconfigure integration test.
59   *
60   * @author Christian Bremer
61   */
62  @Testcontainers
63  @SpringBootTest(
64      classes = {TestConfiguration.class},
65      webEnvironment = WebEnvironment.RANDOM_PORT,
66      properties = {
67          "spring.main.web-application-type=reactive",
68          "spring.data.mongodb.auto-index-creation=true"
69      })
70  @ComponentScan(basePackageClasses = {GeometryEntityRepository.class})
71  @AutoConfigureWebTestClient
72  @EnableMongoRepositories(basePackageClasses = {GeometryEntityRepository.class})
73  @DirtiesContext(classMode = ClassMode.AFTER_CLASS)
74  @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
75  class GeoJsonAutoConfigureIntegrationTest {
76  
77    @Container
78    @ServiceConnection
79    static MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName
80        .parse("mongo:latest"));
81  
82    /**
83     * The Geometry factory.
84     */
85    @Autowired
86    GeoJsonGeometryFactory geometryFactory;
87  
88    /**
89     * The Repository.
90     */
91    @Autowired
92    GeometryEntityRepository repository;
93  
94    /**
95     * The test web client.
96     */
97    @Autowired
98    WebTestClient webClient;
99  
100   /**
101    * Transform.
102    */
103   @Order(10)
104   @Test
105   void transform() {
106     MultiPoint geometry = geometryFactory.createMultiPoint(List.of(
107         geometryFactory.createPoint(1., 2.),
108         geometryFactory.createPoint(6., 7.)
109     ));
110     GeoJsonFeature<Geometry, Object> expected = new GeoJsonFeature<>("987", geometry, true, null);
111     webClient
112         .get()
113         .uri("/geo/transform?id={id}&geometry={geometry}&withBoundingBox={withBoundingBox}",
114             expected.getId(), expected.getGeometry().toText(), true)
115         .exchange()
116         .expectStatus()
117         .isOk()
118         .expectBody(new ParameterizedTypeReference<GeoJsonFeature<Geometry, Object>>() {
119         })
120         .value(response -> assertThat(response).isEqualTo(expected));
121   }
122 
123   /**
124    * Find features.
125    */
126   @Order(20)
127   @Test
128   void findFeatures() {
129     LinearRing ring = geometryFactory.createLinearRing(List.of(
130         new Coordinate(2., 3.),
131         new Coordinate(6., 4.),
132         new Coordinate(6., 8.),
133         new Coordinate(2., 3.)));
134     Polygon polygon = geometryFactory.createPolygon(ring);
135     LineString lineString = geometryFactory.createLineString(Arrays.asList(
136         new Coordinate(2., 3.),
137         new Coordinate(6., 7.)));
138     Point point = geometryFactory.createPoint(7., 8.);
139     List<Geometry> geometries = List.of(point, lineString, polygon);
140 
141     GeoJsonFeatureCollection<Geometry, Object> expected = save(geometries).block();
142 
143     webClient
144         .get()
145         .uri("/geo")
146         .exchange()
147         .expectStatus()
148         .isOk()
149         .expectBody(new ParameterizedTypeReference<GeoJsonFeatureCollection<Geometry, Object>>() {
150         })
151         .value(response -> assertThat(response).isEqualTo(expected));
152   }
153 
154   /**
155    * Save feature.
156    */
157   @Order(30)
158   @Test
159   void saveFeature() {
160     LineString lineString = geometryFactory.createLineString(Arrays.asList(
161         new Coordinate(2., 3.),
162         new Coordinate(6., 7.)));
163     //noinspection unchecked
164     webClient.post()
165         .uri("/geo")
166         .body(Mono.just(lineString), LineString.class)
167         .exchange()
168         .expectStatus()
169         .isOk()
170         .expectBody(new ParameterizedTypeReference<GeoJsonFeature<Geometry, Object>>() {
171         })
172         .value(response -> assertThat(response.getGeometry()).isEqualTo(lineString));
173 
174   }
175 
176   private Mono<GeoJsonFeatureCollection<Geometry, Object>> save(List<Geometry> geometries) {
177     return repository.saveAll(geometries.stream()
178             .map(GeometryEntity::new)
179             .toList())
180         .map(entity -> new GeoJsonFeature<>(entity.getId(), entity.getGeometry(), false, null))
181         .collect(
182             () -> new GeoJsonFeatureCollection<>(
183                 true,
184                 (o1, o2) -> o1.getId().compareToIgnoreCase(o2.getId())),
185             GeoJsonFeatureCollection::add);
186   }
187 
188 }