Skip to content

Commit 62ce5e5

Browse files
Flossyclaude
andcommitted
Add comprehensive tests for helper utilities and API sources (48 new tests)
Added tests for AuthHelper (9 tests), RestApiClassSource (20 tests), and WebDavClassSource (19 tests). Tests validate authentication configuration, builder patterns, URL handling, and response format processing. Test coverage improved from 22% to 25% instruction coverage. Total test count increased from 163 to 211 tests. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 40daf14 commit 62ce5e5

3 files changed

Lines changed: 513 additions & 0 deletions

File tree

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package org.flossware.jclassloader;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import java.io.IOException;
6+
import java.net.HttpURLConnection;
7+
import java.net.URL;
8+
9+
import static org.junit.jupiter.api.Assertions.*;
10+
11+
/**
12+
* Tests for AuthHelper authentication configuration.
13+
* Note: HttpURLConnection does not allow reading headers back before connection,
14+
* so we test that the methods execute without exceptions.
15+
*/
16+
class AuthHelperTest {
17+
18+
@Test
19+
void testConfigureAuthWithNull() throws IOException {
20+
URL url = new URL("http://example.com");
21+
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
22+
23+
assertDoesNotThrow(() -> {
24+
AuthHelper.configureAuth(connection, null);
25+
});
26+
}
27+
28+
@Test
29+
void testConfigureAuthWithNone() throws IOException {
30+
URL url = new URL("http://example.com");
31+
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
32+
AuthConfig auth = AuthConfig.none();
33+
34+
assertDoesNotThrow(() -> {
35+
AuthHelper.configureAuth(connection, auth);
36+
});
37+
}
38+
39+
@Test
40+
void testConfigureAuthWithBasic() throws IOException {
41+
URL url = new URL("http://example.com");
42+
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
43+
AuthConfig auth = AuthConfig.basic("user", "pass");
44+
45+
assertDoesNotThrow(() -> {
46+
AuthHelper.configureAuth(connection, auth);
47+
});
48+
}
49+
50+
@Test
51+
void testConfigureAuthWithBearer() throws IOException {
52+
URL url = new URL("http://example.com");
53+
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
54+
AuthConfig auth = AuthConfig.bearer("my-token-123");
55+
56+
assertDoesNotThrow(() -> {
57+
AuthHelper.configureAuth(connection, auth);
58+
});
59+
}
60+
61+
@Test
62+
void testConfigureAuthBasicWithSpecialCharacters() throws IOException {
63+
URL url = new URL("http://example.com");
64+
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
65+
AuthConfig auth = AuthConfig.basic("user@domain.com", "p@$$w0rd!");
66+
67+
assertDoesNotThrow(() -> {
68+
AuthHelper.configureAuth(connection, auth);
69+
});
70+
}
71+
72+
@Test
73+
void testConfigureAuthBasicWithEmptyCredentials() throws IOException {
74+
URL url = new URL("http://example.com");
75+
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
76+
AuthConfig auth = AuthConfig.basic("", "");
77+
78+
assertDoesNotThrow(() -> {
79+
AuthHelper.configureAuth(connection, auth);
80+
});
81+
}
82+
83+
@Test
84+
void testConfigureAuthBearerWithLongToken() throws IOException {
85+
URL url = new URL("http://example.com");
86+
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
87+
String longToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";
88+
AuthConfig auth = AuthConfig.bearer(longToken);
89+
90+
assertDoesNotThrow(() -> {
91+
AuthHelper.configureAuth(connection, auth);
92+
});
93+
}
94+
95+
@Test
96+
void testMultipleConfigureAuthCalls() throws IOException {
97+
URL url = new URL("http://example.com");
98+
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
99+
100+
AuthConfig auth1 = AuthConfig.basic("user1", "pass1");
101+
AuthHelper.configureAuth(connection, auth1);
102+
103+
AuthConfig auth2 = AuthConfig.bearer("token123");
104+
assertDoesNotThrow(() -> {
105+
AuthHelper.configureAuth(connection, auth2);
106+
});
107+
}
108+
109+
@Test
110+
void testAuthConfigTypes() {
111+
AuthConfig none = AuthConfig.none();
112+
assertEquals(AuthConfig.AuthType.NONE, none.getAuthType());
113+
114+
AuthConfig basic = AuthConfig.basic("user", "pass");
115+
assertEquals(AuthConfig.AuthType.BASIC, basic.getAuthType());
116+
assertEquals("user", basic.getUsername());
117+
assertEquals("pass", basic.getPassword());
118+
119+
AuthConfig bearer = AuthConfig.bearer("token");
120+
assertEquals(AuthConfig.AuthType.BEARER, bearer.getAuthType());
121+
assertEquals("token", bearer.getToken());
122+
}
123+
}
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
package org.flossware.jclassloader;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import static org.junit.jupiter.api.Assertions.*;
6+
7+
/**
8+
* Tests for RestApiClassSource builder and configuration.
9+
*/
10+
class RestApiClassSourceTest {
11+
12+
@Test
13+
void testBuilderBasic() {
14+
RestApiClassSource source = RestApiClassSource.builder()
15+
.baseUrl("https://api.example.com/classes")
16+
.build();
17+
18+
assertNotNull(source);
19+
assertTrue(source.getDescription().contains("https://api.example.com/classes/"));
20+
}
21+
22+
@Test
23+
void testBuilderWithAuth() {
24+
AuthConfig auth = AuthConfig.basic("user", "pass");
25+
RestApiClassSource source = RestApiClassSource.builder()
26+
.baseUrl("https://api.example.com")
27+
.auth(auth)
28+
.build();
29+
30+
assertTrue(source.getDescription().contains("BASIC"));
31+
}
32+
33+
@Test
34+
void testBuilderWithBearerAuth() {
35+
AuthConfig auth = AuthConfig.bearer("token123");
36+
RestApiClassSource source = RestApiClassSource.builder()
37+
.baseUrl("https://api.example.com")
38+
.auth(auth)
39+
.build();
40+
41+
assertTrue(source.getDescription().contains("BEARER"));
42+
}
43+
44+
@Test
45+
void testBuilderWithHeaders() {
46+
RestApiClassSource source = RestApiClassSource.builder()
47+
.baseUrl("https://api.example.com")
48+
.addHeader("X-Custom-Header", "value")
49+
.addHeader("Accept", "application/octet-stream")
50+
.build();
51+
52+
assertNotNull(source);
53+
}
54+
55+
@Test
56+
void testBuilderWithQueryParams() {
57+
RestApiClassSource source = RestApiClassSource.builder()
58+
.baseUrl("https://api.example.com")
59+
.addQueryParam("version", "1.0")
60+
.addQueryParam("format", "binary")
61+
.build();
62+
63+
assertNotNull(source);
64+
}
65+
66+
@Test
67+
void testBuilderWithClassPathTemplate() {
68+
RestApiClassSource source = RestApiClassSource.builder()
69+
.baseUrl("https://api.example.com")
70+
.classPathTemplate("api/v1/{fullclass}")
71+
.build();
72+
73+
assertNotNull(source);
74+
}
75+
76+
@Test
77+
void testBuilderWithBinaryResponseFormat() {
78+
RestApiClassSource source = RestApiClassSource.builder()
79+
.baseUrl("https://api.example.com")
80+
.responseFormat(RestApiClassSource.ResponseFormat.BINARY)
81+
.build();
82+
83+
assertTrue(source.getDescription().contains("BINARY"));
84+
}
85+
86+
@Test
87+
void testBuilderWithBase64JsonResponseFormat() {
88+
RestApiClassSource source = RestApiClassSource.builder()
89+
.baseUrl("https://api.example.com")
90+
.responseFormat(RestApiClassSource.ResponseFormat.BASE64_JSON_FIELD)
91+
.build();
92+
93+
assertTrue(source.getDescription().contains("BASE64_JSON_FIELD"));
94+
}
95+
96+
@Test
97+
void testBuilderWithDirectResponseFormat() {
98+
RestApiClassSource source = RestApiClassSource.builder()
99+
.baseUrl("https://api.example.com")
100+
.responseFormat(RestApiClassSource.ResponseFormat.DIRECT)
101+
.build();
102+
103+
assertTrue(source.getDescription().contains("DIRECT"));
104+
}
105+
106+
@Test
107+
void testBuilderAddsTrailingSlash() {
108+
RestApiClassSource source = RestApiClassSource.builder()
109+
.baseUrl("https://api.example.com/classes")
110+
.build();
111+
112+
assertTrue(source.getDescription().contains("https://api.example.com/classes/"));
113+
}
114+
115+
@Test
116+
void testBuilderPreservesTrailingSlash() {
117+
RestApiClassSource source = RestApiClassSource.builder()
118+
.baseUrl("https://api.example.com/classes/")
119+
.build();
120+
121+
assertTrue(source.getDescription().contains("https://api.example.com/classes/"));
122+
}
123+
124+
@Test
125+
void testGetDescription() {
126+
RestApiClassSource source = RestApiClassSource.builder()
127+
.baseUrl("https://api.example.com")
128+
.responseFormat(RestApiClassSource.ResponseFormat.BINARY)
129+
.auth(AuthConfig.none())
130+
.build();
131+
132+
String description = source.getDescription();
133+
assertTrue(description.contains("RestApiClassSource"));
134+
assertTrue(description.contains("https://api.example.com/"));
135+
assertTrue(description.contains("format=BINARY"));
136+
assertTrue(description.contains("auth=NONE"));
137+
}
138+
139+
@Test
140+
void testDefaultResponseFormat() {
141+
RestApiClassSource source = RestApiClassSource.builder()
142+
.baseUrl("https://api.example.com")
143+
.build();
144+
145+
assertTrue(source.getDescription().contains("format=BINARY"));
146+
}
147+
148+
@Test
149+
void testDefaultAuthConfig() {
150+
RestApiClassSource source = RestApiClassSource.builder()
151+
.baseUrl("https://api.example.com")
152+
.build();
153+
154+
assertTrue(source.getDescription().contains("auth=NONE"));
155+
}
156+
157+
@Test
158+
void testBuilderNullBaseUrlThrowsException() {
159+
assertThrows(NullPointerException.class, () -> {
160+
RestApiClassSource.builder()
161+
.baseUrl(null)
162+
.build();
163+
});
164+
}
165+
166+
@Test
167+
void testBuilderWithAllOptions() {
168+
RestApiClassSource source = RestApiClassSource.builder()
169+
.baseUrl("https://api.example.com")
170+
.classPathTemplate("v1/classes/{package}/{class}")
171+
.addHeader("X-API-Key", "secret")
172+
.addHeader("Accept", "application/octet-stream")
173+
.addQueryParam("version", "1.0")
174+
.addQueryParam("env", "prod")
175+
.auth(AuthConfig.basic("admin", "pass"))
176+
.responseFormat(RestApiClassSource.ResponseFormat.BASE64_JSON_FIELD)
177+
.build();
178+
179+
String description = source.getDescription();
180+
assertTrue(description.contains("BASE64_JSON_FIELD"));
181+
assertTrue(description.contains("BASIC"));
182+
}
183+
184+
@Test
185+
void testMultipleHeaders() {
186+
RestApiClassSource source = RestApiClassSource.builder()
187+
.baseUrl("https://api.example.com")
188+
.addHeader("Header1", "value1")
189+
.addHeader("Header2", "value2")
190+
.addHeader("Header3", "value3")
191+
.build();
192+
193+
assertNotNull(source);
194+
}
195+
196+
@Test
197+
void testMultipleQueryParams() {
198+
RestApiClassSource source = RestApiClassSource.builder()
199+
.baseUrl("https://api.example.com")
200+
.addQueryParam("param1", "value1")
201+
.addQueryParam("param2", "value2")
202+
.addQueryParam("param3", "value3")
203+
.build();
204+
205+
assertNotNull(source);
206+
}
207+
208+
@Test
209+
void testResponseFormatEnum() {
210+
assertEquals(3, RestApiClassSource.ResponseFormat.values().length);
211+
assertNotNull(RestApiClassSource.ResponseFormat.valueOf("BINARY"));
212+
assertNotNull(RestApiClassSource.ResponseFormat.valueOf("BASE64_JSON_FIELD"));
213+
assertNotNull(RestApiClassSource.ResponseFormat.valueOf("DIRECT"));
214+
}
215+
216+
@Test
217+
void testBuilderChaining() {
218+
RestApiClassSource source = RestApiClassSource.builder()
219+
.baseUrl("https://api.example.com")
220+
.classPathTemplate("{fullclass}")
221+
.addHeader("X-Custom", "value")
222+
.addQueryParam("key", "value")
223+
.auth(AuthConfig.bearer("token"))
224+
.responseFormat(RestApiClassSource.ResponseFormat.BINARY)
225+
.build();
226+
227+
assertNotNull(source);
228+
assertTrue(source.getDescription().contains("BINARY"));
229+
assertTrue(source.getDescription().contains("BEARER"));
230+
}
231+
}

0 commit comments

Comments
 (0)