1 package net.sf.okapi.connectors.google.v3;
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.util.List;
9
10 import org.junit.jupiter.api.AfterEach;
11 import org.junit.jupiter.api.BeforeEach;
12 import org.junit.jupiter.api.DisplayName;
13 import org.junit.jupiter.api.Test;
14 import org.junit.jupiter.api.condition.EnabledIf;
15
16 import com.acumenvelocity.ath.common.Const;
17
18 import net.sf.okapi.common.LocaleId;
19 import net.sf.okapi.common.query.QueryResult;
20 import net.sf.okapi.common.resource.TextFragment;
21 import net.sf.okapi.common.resource.TextFragment.TagType;
22
23
24
25
26
27
28
29
30 @DisplayName("GoogleMTv3Connector Integration Tests")
31 @EnabledIf("isCredentialsAvailable")
32 class TestGoogleMTv3Connector_IT {
33
34 private GoogleMTv3Connector connector;
35
36
37 static boolean isCredentialsAvailable() {
38 return System.getenv("ATH_GT_API_KEY") != null || System.getenv("ATH_GCS_SECRET_FILE") != null;
39 }
40
41 @BeforeEach
42 void setUp() {
43 String apiKey = System.getenv("ATH_GT_API_KEY");
44 String credentialsPath = System.getenv("ATH_GCS_SECRET_FILE");
45
46 GoogleMTv3Parameters params = new GoogleMTv3Parameters();
47
48 params.setProjectLocation(Const.US_CENTRAL1_PROJECT_LOCATION);
49 if (apiKey != null && !apiKey.isBlank()) {
50 params.setApiKey(apiKey);
51 }
52 if (credentialsPath != null && !credentialsPath.isBlank()) {
53 params.setCredentialsPath(credentialsPath);
54 }
55 params.setMimeType("text/plain");
56
57 connector = new GoogleMTv3Connector();
58 connector.setParameters(params);
59 connector.setLanguages(LocaleId.ENGLISH, LocaleId.SPANISH);
60 connector.open();
61 }
62
63 @AfterEach
64 void tearDown() {
65 if (connector != null) {
66 connector.close();
67 }
68 }
69
70 @Test
71 @DisplayName("Basic plain text translation EN → ES")
72 void testPlainTextTranslation() {
73 connector.setLanguages(LocaleId.ENGLISH, LocaleId.SPANISH);
74
75 int count = connector.query("Hello, world!");
76
77 assertEquals(1, count);
78 assertTrue(connector.hasNext());
79
80 QueryResult qr = connector.next();
81 assertNotNull(qr);
82 assertEquals(100, qr.getFuzzyScore());
83 assertEquals(net.sf.okapi.common.query.MatchType.MT, qr.matchType);
84
85 String translated = qr.target.getCodedText();
86 assertFalse(translated.equals("Hello, world!"), "Translation should be different from source");
87 assertTrue(
88 translated.toLowerCase().contains("hola") || translated.toLowerCase().contains("mundo"),
89 "Expected Spanish translation, got: " + translated);
90 }
91
92 @Test
93 @DisplayName("Coded text translation with inline tags preserved (EN → FR)")
94 void testCodedTextTranslation() {
95 connector.setLanguages(LocaleId.ENGLISH, LocaleId.FRENCH);
96
97 TextFragment src = new TextFragment();
98 src.append("Click the ");
99 src.append(TagType.OPENING, "b", "<b>");
100 src.append("Save");
101 src.append(TagType.CLOSING, "b", "</b>");
102 src.append(" button to continue.");
103
104 int count = connector.query(src);
105
106 assertEquals(1, count);
107 assertTrue(connector.hasNext());
108
109 QueryResult qr = connector.next();
110 assertNotNull(qr);
111 assertEquals(100, qr.getFuzzyScore());
112
113
114 assertTrue(qr.target.hasCode(), "Target should have codes");
115
116 String targetText = qr.target.toText();
117
118 assertTrue(targetText.toLowerCase().contains("bouton") ||
119 targetText.toLowerCase().contains("enregistrer") ||
120 targetText.toLowerCase().contains("sauvegarder") ||
121 targetText.toLowerCase().contains("cliqu"),
122 "Expected French translation: " + targetText);
123 }
124
125 @Test
126 @DisplayName("Language detection works (source = und → DE)")
127 void testLanguageDetection() {
128 connector.setLanguages(LocaleId.EMPTY, LocaleId.GERMAN);
129
130 int count = connector.query("This is a test sentence in English.");
131
132 assertEquals(1, count);
133 assertTrue(connector.hasNext());
134
135 QueryResult qr = connector.next();
136 assertNotNull(qr);
137
138 String translated = qr.target.getCodedText().toLowerCase();
139 assertTrue(
140 translated.contains("ist") || translated.contains("test") || translated.contains("satz"),
141 "Should be German: " + translated);
142 }
143
144 @Test
145 @DisplayName("getSupportedLanguages returns a large list")
146 void testGetSupportedLanguages() {
147 List<LocaleId> languages = connector.getSupportedLanguages();
148
149 assertNotNull(languages);
150 assertTrue(languages.size() > 130,
151 "Google Translate v3 supports >130 languages, got " + languages.size());
152 assertTrue(languages.contains(LocaleId.fromBCP47("en")));
153 assertTrue(languages.contains(LocaleId.fromBCP47("es")));
154 assertTrue(languages.contains(LocaleId.fromBCP47("zh-CN")));
155 assertTrue(languages.contains(LocaleId.fromBCP47("ja")));
156 }
157
158 @Test
159 @DisplayName("Connector metadata is correct")
160 void testConnectorMetadata() {
161 assertEquals("Google-MTv3", connector.getName());
162 String settings = connector.getSettingsDisplay();
163 assertTrue(settings.contains(Const.US_CENTRAL1_PROJECT_LOCATION));
164 }
165
166 @Test
167 @DisplayName("Empty query returns 0 and no results")
168 void testEmptyQuery() {
169 int count = connector.query("");
170 assertEquals(0, count);
171 assertFalse(connector.hasNext());
172 }
173
174 @Test
175 @DisplayName("Very long text is handled correctly (batching)")
176 void testLongTextBatching() {
177 connector.setLanguages(LocaleId.ENGLISH, LocaleId.JAPANESE);
178
179
180 StringBuilder sb = new StringBuilder();
181
182 for (int i = 0; i < 400; i++) {
183 sb.append("This is a test sentence number ").append(i).append(". ");
184 }
185
186 String longText = sb.toString();
187
188 int count = connector.query(longText);
189
190 assertTrue(count > 0);
191 assertTrue(connector.hasNext());
192
193 QueryResult qr = connector.next();
194 assertNotNull(qr);
195 String translated = qr.target.getCodedText();
196 assertFalse(translated.isBlank());
197 assertFalse(translated.equals(longText), "Should be translated to Japanese");
198 }
199
200 @Test
201 @DisplayName("Batch query with multiple fragments")
202 void testBatchQuery() {
203 connector.setLanguages(LocaleId.ENGLISH, LocaleId.SPANISH);
204
205 List<String> texts = List.of(
206 "Hello",
207 "Goodbye",
208 "Thank you");
209
210 List<List<QueryResult>> results = connector.batchQueryText(texts);
211
212 assertNotNull(results);
213 assertEquals(3, results.size());
214
215 for (List<QueryResult> resultList : results) {
216 assertEquals(1, resultList.size());
217 QueryResult qr = resultList.get(0);
218 assertNotNull(qr.target);
219 assertEquals(100, qr.getFuzzyScore());
220 }
221 }
222 }