1 package com.acumenvelocity.ath.integration;
2
3 import static org.junit.jupiter.api.Assertions.assertEquals;
4 import static org.junit.jupiter.api.Assertions.assertFalse;
5 import static org.junit.jupiter.api.Assertions.assertNotNull;
6 import static org.junit.jupiter.api.Assertions.assertTrue;
7
8 import java.nio.file.Files;
9 import java.nio.file.Path;
10 import java.util.UUID;
11
12 import org.apache.solr.client.solrj.SolrClient;
13 import org.apache.solr.client.solrj.SolrQuery;
14 import org.apache.solr.client.solrj.response.QueryResponse;
15 import org.apache.solr.common.SolrDocument;
16 import org.junit.jupiter.api.BeforeAll;
17 import org.junit.jupiter.api.MethodOrderer;
18 import org.junit.jupiter.api.Order;
19 import org.junit.jupiter.api.Test;
20 import org.junit.jupiter.api.TestMethodOrder;
21 import org.junitpioneer.jupiter.SetEnvironmentVariable;
22
23 import com.acumenvelocity.ath.common.Const;
24 import com.acumenvelocity.ath.common.JacksonUtil;
25 import com.acumenvelocity.ath.common.SolrUtil;
26 import com.acumenvelocity.ath.model.x.LayeredTextX;
27 import com.acumenvelocity.ath.solr.AthIndex;
28 import com.fasterxml.jackson.databind.JsonNode;
29 import com.fasterxml.jackson.databind.node.ObjectNode;
30
31 @SetEnvironmentVariable(key = "ATH_SOLR_URL", value = "http://localhost:8983/solr")
32 @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
33 public class TestTranslationMemories_IT extends BaseIntegrationTest {
34
35 private static UUID testTmId;
36 private static UUID testUserId;
37 private static UUID testSegmentId;
38
39 @BeforeAll
40 public void setUp() throws Exception {
41 String solrUrl = System.getenv("ATH_SOLR_URL");
42 System.out.println("ATH_SOLR_URL from System.getenv: " + solrUrl);
43
44 if (solrUrl == null) {
45 throw new IllegalStateException("ATH_SOLR_URL is not set");
46 }
47
48 testTmId = UUID.randomUUID();
49 testUserId = UUID.randomUUID();
50 testSegmentId = UUID.randomUUID();
51
52 AthIndex.init();
53 }
54
55 @Test
56 @Order(1)
57 public void testCreateTranslationMemory() throws Exception {
58 Path tmxFile = createTestTmxFile();
59
60 MultipartRequestBody body = new MultipartRequestBody();
61 body.addPart("tm_id", testTmId.toString());
62 body.addFilePart("tm_file", "test.tmx", tmxFile, "application/xml");
63 body.addPart("tm_file_name", "test.tmx");
64 body.addPart("src_lang", "en");
65 body.addPart("trg_lang", "fr");
66 body.addPart("user_id", testUserId.toString());
67
68 HttpResponse response = sendMultipartRequest("/resources/translation-memory", body);
69
70 assertEquals(201, response.getStatusCode(), "Expected HTTP 201");
71
72 JsonNode json = parseJson(response.getBody());
73 assertEquals(201, json.get("code").asInt());
74
75
76 SolrClient solrClient = getSolrClient();
77 SolrQuery segmentQuery = new SolrQuery("tmId:\"" + testTmId + "\"");
78 QueryResponse segResponse = solrClient.query(Const.SOLR_CORE_ATH_TM_SEGMENTS, segmentQuery);
79 assertEquals(2, segResponse.getResults().getNumFound(),
80 "Expected two segments in ATH_TM_SEGMENTS core");
81 assertEquals("en", segResponse.getResults().get(0).getFieldValue(Const.ATH_PROP_SRC_LANG));
82 assertEquals("fr", segResponse.getResults().get(0).getFieldValue(Const.ATH_PROP_TRG_LANG));
83
84
85 SolrQuery tmQuery = new SolrQuery("tmId:\"" + testTmId + "\"");
86 tmQuery.setFields(
87 Const.ATH_PROP_SOLR_ID,
88 Const.ATH_PROP_TM_ID,
89 Const.ATH_PROP_TM_FILE_NAME,
90 Const.ATH_PROP_SRC_LANG,
91 Const.ATH_PROP_TRG_LANG,
92 Const.ATH_PROP_CREATED_BY,
93 Const.ATH_PROP_CREATED_AT,
94 Const.ATH_PROP_UPDATED_BY,
95 Const.ATH_PROP_UPDATED_AT);
96 QueryResponse tmResponse = solrClient.query(Const.SOLR_CORE_ATH_TMS, tmQuery);
97 assertEquals(1, tmResponse.getResults().getNumFound(), "Expected one document in ATH_TMS core");
98 SolrDocument tmDoc = tmResponse.getResults().get(0);
99 assertEquals(testTmId.toString(), tmDoc.getFieldValue(Const.ATH_PROP_TM_ID));
100 assertEquals("test.tmx", tmDoc.getFieldValue(Const.ATH_PROP_TM_FILE_NAME));
101 assertEquals("en", tmDoc.getFieldValue(Const.ATH_PROP_SRC_LANG));
102 assertEquals("fr", tmDoc.getFieldValue(Const.ATH_PROP_TRG_LANG));
103 assertEquals(testUserId.toString(), tmDoc.getFieldValue(Const.ATH_PROP_CREATED_BY));
104 assertEquals(testUserId.toString(), tmDoc.getFieldValue(Const.ATH_PROP_UPDATED_BY));
105 assertNotNull(tmDoc.getFieldValue(Const.ATH_PROP_CREATED_AT), "created_at should not be null");
106 assertNotNull(tmDoc.getFieldValue(Const.ATH_PROP_UPDATED_AT), "updated_at should not be null");
107
108
109 long segmentsCount = SolrUtil.getNumDocuments(Const.SOLR_CORE_ATH_TM_SEGMENTS,
110 "tmId:\"" + testTmId + "\"");
111 assertEquals(2, segmentsCount, "Expected two segments in dynamic count");
112
113 System.out.println("Created TM with ID: " + testTmId);
114 }
115
116 @Test
117 @Order(2)
118 public void testGetTranslationMemories() throws Exception {
119 HttpResponse response = sendGetRequest("/resources/translation-memory");
120
121 assertEquals(200, response.getStatusCode(), "Expected HTTP 200");
122
123 JsonNode json = parseJson(response.getBody());
124 assertTrue(json.has("translation_memories"),
125 "Response should have 'translation_memories' field");
126
127 JsonNode tms = json.get("translation_memories");
128 assertTrue(tms.isArray(), "Translation memories should be an array");
129 assertTrue(tms.size() > 0, "Should have at least one TM");
130
131 System.out.println("Found " + tms.size() + " translation memories");
132 }
133
134 @Test
135 @Order(3)
136 public void testGetTranslationMemoryInfo() throws Exception {
137 HttpResponse response = sendGetRequest("/resources/translation-memory/" + testTmId + "/info");
138
139 assertEquals(200, response.getStatusCode(), "Expected HTTP 200");
140
141 JsonNode json = parseJson(response.getBody());
142 assertTrue(json.has("translation_memory_info"),
143 "Response should have 'translation_memory_info' field");
144
145 JsonNode tmInfo = json.get("translation_memory_info");
146 assertEquals(testTmId.toString(), tmInfo.get("tm_id").asText());
147 assertTrue(tmInfo.has("tm_file_name"));
148 assertEquals("en", tmInfo.get("src_lang").asText());
149 assertEquals("fr", tmInfo.get("trg_lang").asText());
150 assertTrue(tmInfo.has("segments_count"));
151 assertEquals(2, tmInfo.get("segments_count").asLong());
152
153 System.out.println("TM segments count: " + tmInfo.get("segments_count").asLong());
154 }
155
156 @Test
157 @Order(4)
158 public void testGetTranslationMemorySegments() throws Exception {
159 HttpResponse response = sendGetRequest(
160 "/resources/translation-memory/" + testTmId + "/segment");
161
162 assertEquals(200, response.getStatusCode(), "Expected HTTP 200");
163
164 JsonNode json = parseJson(response.getBody());
165 assertTrue(json.has("tm_segments"), "Response should have 'tm_segments' field");
166
167 JsonNode segments = json.get("tm_segments");
168 assertTrue(segments.isArray(), "Segments should be an array");
169 assertEquals(2, segments.size());
170
171 System.out.println("Found " + segments.size() + " TM segments");
172 }
173
174 @Test
175 @Order(5)
176 public void testCreateTranslationMemorySegment() throws Exception {
177 ObjectNode requestBody = objectMapper.createObjectNode();
178 requestBody.put("tm_seg_id", testSegmentId.toString());
179
180 ObjectNode source = objectMapper.createObjectNode();
181 source.put("language", "en");
182 source.put("text", "Test source text");
183 source.set("codes", objectMapper.createArrayNode());
184 requestBody.set("source", source);
185
186 ObjectNode target = objectMapper.createObjectNode();
187 target.put("language", "fr");
188 target.put("text", "Texte source de test");
189 target.set("codes", objectMapper.createArrayNode());
190 requestBody.set("target", target);
191
192 requestBody.put("user_id", testUserId.toString());
193
194 HttpResponse response = sendPostRequest(
195 "/resources/translation-memory/" + testTmId + "/segment", toJson(requestBody));
196
197 assertEquals(201, response.getStatusCode(), "Expected HTTP 201");
198
199
200 SolrClient solrClient = getSolrClient();
201 SolrQuery query = new SolrQuery(
202 "tmSegId:\"" + testSegmentId + "\" AND tmId:\"" + testTmId + "\"");
203 QueryResponse segResponse = solrClient.query(Const.SOLR_CORE_ATH_TM_SEGMENTS, query);
204 assertEquals(1, segResponse.getResults().size(),
205 "Expected one segment in ATH_TM_SEGMENTS core");
206
207 System.out.println("Created TM segment with ID: " + testSegmentId);
208 }
209
210 @Test
211 @Order(6)
212 public void testGetTranslationMemorySegment() throws Exception {
213 HttpResponse response = sendGetRequest(
214 "/resources/translation-memory/" + testTmId + "/segment/" + testSegmentId);
215
216 assertEquals(200, response.getStatusCode(), "Expected HTTP 200");
217
218 JsonNode json = parseJson(response.getBody());
219 assertTrue(json.has("tm_segment"), "Response should have 'tm_segment' field");
220
221 JsonNode segment = json.get("tm_segment");
222 assertEquals(testSegmentId.toString(), segment.get("tm_seg_id").asText());
223 assertEquals(testTmId.toString(), segment.get("tm_id").asText());
224 }
225
226 @Test
227 @Order(7)
228 public void testUpdateTranslationMemorySegment() throws Exception {
229 ObjectNode requestBody = objectMapper.createObjectNode();
230 requestBody.put("tm_seg_id", testSegmentId.toString());
231
232 ObjectNode target = objectMapper.createObjectNode();
233 target.put("language", "fr");
234 target.put("text", "Texte source de test modifié");
235 target.set("codes", objectMapper.createArrayNode());
236 requestBody.set("target", target);
237
238 requestBody.put("user_id", testUserId.toString());
239
240 HttpResponse response = sendPutRequest(
241 "/resources/translation-memory/" + testTmId + "/segment/" + testSegmentId,
242 toJson(requestBody));
243
244 assertEquals(200, response.getStatusCode(), "Expected HTTP 200");
245
246
247 SolrClient solrClient = getSolrClient();
248 SolrQuery query = new SolrQuery(
249 "tmSegId:\"" + testSegmentId + "\" AND tmId:\"" + testTmId + "\"");
250 QueryResponse segResponse = solrClient.query(Const.SOLR_CORE_ATH_TM_SEGMENTS, query);
251 assertEquals(1, segResponse.getResults().size(),
252 "Expected one segment in ATH_TM_SEGMENTS core");
253 String targetJson = segResponse.getResults().get(0).getFieldValue("targetJson").toString();
254 LayeredTextX targetLt = JacksonUtil.fromJson(targetJson, LayeredTextX.class);
255 assertEquals("Texte source de test modifié", targetLt.getText());
256
257 System.out.println("Updated TM segment");
258 }
259
260 @Test
261 @Order(8)
262 public void testExportTranslationMemory() throws Exception {
263 HttpResponse response = sendGetRequest("/resources/translation-memory/" + testTmId);
264
265 assertEquals(200, response.getStatusCode(), "Expected HTTP 200");
266 assertFalse(response.getBody().isEmpty(), "Response body should not be empty");
267
268 System.out.println("Exported TM successfully");
269 }
270
271 @Test
272 @Order(9)
273 public void testUpdateTranslationMemory() throws Exception {
274 Path tmxFile = createTestTmxFile();
275 UUID newUserId = UUID.randomUUID();
276
277
278 MultipartRequestBody body = new MultipartRequestBody();
279 body.addFilePart("tm_file", "update.tmx", tmxFile, "application/xml");
280 body.addPart("tm_file_name", "update.tmx");
281 body.addPart("user_id", newUserId.toString());
282
283 HttpResponse response = sendPutMultipartRequest(
284 "/resources/translation-memory/" + testTmId, body);
285
286 assertEquals(200, response.getStatusCode(), "Expected HTTP 200");
287
288 JsonNode json = parseJson(response.getBody());
289 assertEquals(200, json.get("code").asInt(), "Expected response code 200");
290
291
292 SolrClient solrClient = getSolrClient();
293 SolrQuery segmentQuery = new SolrQuery("tmId:\"" + testTmId + "\"");
294 QueryResponse segResponse = solrClient.query(Const.SOLR_CORE_ATH_TM_SEGMENTS, segmentQuery);
295 assertEquals(3, segResponse.getResults().getNumFound(), "Expected three segments after update (one was already there)");
296
297
298 SolrQuery tmQuery = new SolrQuery("tmId:\"" + testTmId + "\"");
299 tmQuery.setFields(
300 Const.ATH_PROP_SOLR_ID,
301 Const.ATH_PROP_TM_ID,
302 Const.ATH_PROP_TM_FILE_NAME,
303 Const.ATH_PROP_SRC_LANG,
304 Const.ATH_PROP_TRG_LANG,
305 Const.ATH_PROP_CREATED_BY,
306 Const.ATH_PROP_CREATED_AT,
307 Const.ATH_PROP_UPDATED_BY,
308 Const.ATH_PROP_UPDATED_AT);
309 QueryResponse tmResponse = solrClient.query(Const.SOLR_CORE_ATH_TMS, tmQuery);
310 assertEquals(1, tmResponse.getResults().getNumFound(), "Expected one document in ATH_TMS core");
311 SolrDocument tmDoc = tmResponse.getResults().get(0);
312 assertEquals(testTmId.toString(), tmDoc.getFieldValue(Const.ATH_PROP_TM_ID));
313 assertEquals("update.tmx", tmDoc.getFieldValue(Const.ATH_PROP_TM_FILE_NAME));
314 assertNotNull(tmDoc.getFieldValue(Const.ATH_PROP_SRC_LANG), "src_lang should not be null");
315 assertNotNull(tmDoc.getFieldValue(Const.ATH_PROP_TRG_LANG), "trg_lang should not be null");
316 assertNotNull(tmDoc.getFieldValue(Const.ATH_PROP_CREATED_BY), "created_by should not be null");
317 assertNotNull(tmDoc.getFieldValue(Const.ATH_PROP_CREATED_AT), "created_at should not be null");
318 assertNotNull(tmDoc.getFieldValue(Const.ATH_PROP_UPDATED_AT), "updated_at should not be null");
319
320
321 UUID updatedBy = UUID.fromString(SolrUtil.safeGetField(tmDoc, Const.ATH_PROP_UPDATED_BY, null));
322
323 assertTrue(newUserId.equals(updatedBy), "Expected updated_by to equal new user ID");
324
325
326 long segmentsCount = SolrUtil.getNumDocuments(Const.SOLR_CORE_ATH_TM_SEGMENTS,
327 "tmId:\"" + testTmId + "\"");
328 assertEquals(3, segmentsCount, "Expected three segments in dynamic count");
329
330 System.out.println("Updated TM with ID: " + testTmId);
331 }
332
333 @Test
334 @Order(10)
335 public void testDeleteTranslationMemorySegment() throws Exception {
336 HttpResponse response = sendDeleteRequest(
337 "/resources/translation-memory/" + testTmId + "/segment/" + testSegmentId);
338
339 assertEquals(204, response.getStatusCode(), "Expected HTTP 204");
340
341
342 SolrClient solrClient = getSolrClient();
343 SolrQuery query = new SolrQuery(
344 "tmSegId:\"" + testSegmentId + "\" AND tmId:\"" + testTmId + "\"");
345 QueryResponse segResponse = solrClient.query(Const.SOLR_CORE_ATH_TM_SEGMENTS, query);
346 assertEquals(0, segResponse.getResults().getNumFound(),
347 "Segment should be deleted from ATH_TM_SEGMENTS core");
348
349 System.out.println("Deleted TM segment");
350 }
351
352 @Test
353 @Order(11)
354 public void testDeleteTranslationMemory() throws Exception {
355 HttpResponse response = sendDeleteRequest("/resources/translation-memory/" + testTmId);
356
357 assertEquals(204, response.getStatusCode(), "Expected HTTP 204");
358
359
360 SolrClient solrClient = getSolrClient();
361 SolrQuery query = new SolrQuery("tmId:\"" + testTmId + "\"");
362 QueryResponse segResponse = solrClient.query(Const.SOLR_CORE_ATH_TM_SEGMENTS, query);
363 assertEquals(0, segResponse.getResults().getNumFound(),
364 "Segments should be deleted from ATH_TM_SEGMENTS core");
365
366 System.out.println("Deleted TM");
367 }
368
369 private Path createTestTmxFile() throws Exception {
370 String tmxContent = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
371 "<tmx version=\"1.4\">\n" +
372 " <header creationtool=\"test\" creationtoolversion=\"1.0\" " +
373 "datatype=\"plaintext\" segtype=\"sentence\" " +
374 "adminlang=\"en\" srclang=\"en\"/>\n" +
375 " <body>\n" +
376 " <tu>\n" +
377 " <tuv xml:lang=\"en\"><seg>Hello world</seg></tuv>\n" +
378 " <tuv xml:lang=\"fr\"><seg>Bonjour le monde</seg></tuv>\n" +
379 " </tu>\n" +
380 " <tu>\n" +
381 " <tuv xml:lang=\"en\"><seg>Goodbye</seg></tuv>\n" +
382 " <tuv xml:lang=\"fr\"><seg>Au revoir</seg></tuv>\n" +
383 " </tu>\n" +
384 " </body>\n" +
385 "</tmx>";
386
387 Path tmxFile = Files.createTempFile("test", ".tmx");
388 Files.write(tmxFile, tmxContent.getBytes(java.nio.charset.StandardCharsets.UTF_8));
389 tmxFile.toFile().deleteOnExit();
390
391 return tmxFile;
392 }
393
394 private SolrClient getSolrClient() {
395 return AthIndex.getSolr().getClient();
396 }
397 }