add tests
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
package com.krrishg.config;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class EncryptionServiceTest {
|
||||
|
||||
private Path tempKeyPath;
|
||||
private EncryptionService service;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
try {
|
||||
tempKeyPath = Files.createTempFile("test-encryption", ".key");
|
||||
service = new EncryptionService(tempKeyPath.toString());
|
||||
service.init();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() throws IOException {
|
||||
Files.deleteIfExists(tempKeyPath);
|
||||
}
|
||||
|
||||
@Test
|
||||
void encryptAndDecryptRoundtrip() {
|
||||
String plaintext = "Hello, World!";
|
||||
|
||||
String encrypted = service.encrypt(plaintext);
|
||||
assertNotNull(encrypted);
|
||||
assertNotEquals(plaintext, encrypted);
|
||||
|
||||
String decrypted = service.decrypt(encrypted);
|
||||
assertEquals(plaintext, decrypted);
|
||||
}
|
||||
|
||||
@Test
|
||||
void encryptAndDecryptSpecialCharacters() {
|
||||
String plaintext = "Special chars: !@#$%^&*()_+-=[]{}|;':\",./<>?`~\n\t";
|
||||
|
||||
String encrypted = service.encrypt(plaintext);
|
||||
String decrypted = service.decrypt(encrypted);
|
||||
|
||||
assertEquals(plaintext, decrypted);
|
||||
}
|
||||
|
||||
@Test
|
||||
void encryptAndDecryptEmptyString() {
|
||||
String encrypted = service.encrypt("");
|
||||
String decrypted = service.decrypt(encrypted);
|
||||
|
||||
assertEquals("", decrypted);
|
||||
}
|
||||
|
||||
@Test
|
||||
void differentPlaintextsProduceDifferentCiphertexts() {
|
||||
String encrypted1 = service.encrypt("text1");
|
||||
String encrypted2 = service.encrypt("text2");
|
||||
|
||||
assertNotEquals(encrypted1, encrypted2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void samePlaintextProducedDifferentCiphertextsDueToRandomIv() {
|
||||
String encrypted1 = service.encrypt("same text");
|
||||
String encrypted2 = service.encrypt("same text");
|
||||
|
||||
assertNotEquals(encrypted1, encrypted2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void decryptThrowsOnInvalidData() {
|
||||
assertThrows(RuntimeException.class, () -> service.decrypt("invalid-base64!"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void initCreatesKeyFile() throws IOException {
|
||||
assertTrue(Files.exists(tempKeyPath));
|
||||
assertTrue(Files.size(tempKeyPath) > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void initLoadsExistingKeyFile() {
|
||||
EncryptionService secondService = new EncryptionService(tempKeyPath.toString());
|
||||
secondService.init();
|
||||
|
||||
String plaintext = "Persistent key test";
|
||||
String encrypted = secondService.encrypt(plaintext);
|
||||
String decrypted = secondService.decrypt(encrypted);
|
||||
|
||||
assertEquals(plaintext, decrypted);
|
||||
}
|
||||
}
|
||||
66
backend/src/test/java/com/krrishg/config/GitConfigTest.java
Normal file
66
backend/src/test/java/com/krrishg/config/GitConfigTest.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package com.krrishg.config;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class GitConfigTest {
|
||||
|
||||
@Test
|
||||
void getSiteRepoPathResolvesCorrectly() throws IOException {
|
||||
Path tempDir = Files.createTempDirectory("git-config-test");
|
||||
GitConfig config = new GitConfig();
|
||||
setField(config, "reposPath", tempDir.toString());
|
||||
setField(config, "authorName", "Indie Platform");
|
||||
setField(config, "authorEmail", "git@indie.local");
|
||||
config.init();
|
||||
|
||||
Path repoPath = config.getSiteRepoPath("test-site-id");
|
||||
|
||||
assertEquals(tempDir.resolve("test-site-id"), repoPath);
|
||||
assertEquals("Indie Platform", config.getAuthorName());
|
||||
assertEquals("git@indie.local", config.getAuthorEmail());
|
||||
|
||||
Files.deleteIfExists(tempDir);
|
||||
}
|
||||
|
||||
@Test
|
||||
void initCreatesDirectory() throws IOException {
|
||||
Path tempDir = Files.createTempDirectory("git-config-init-test");
|
||||
Path reposDir = tempDir.resolve("repos");
|
||||
GitConfig config = new GitConfig();
|
||||
setField(config, "reposPath", reposDir.toString());
|
||||
|
||||
assertFalse(Files.exists(reposDir));
|
||||
config.init();
|
||||
assertTrue(Files.exists(reposDir));
|
||||
|
||||
Files.deleteIfExists(reposDir);
|
||||
Files.deleteIfExists(tempDir);
|
||||
}
|
||||
|
||||
@Test
|
||||
void settersUpdateAuthorInfo() {
|
||||
GitConfig config = new GitConfig();
|
||||
|
||||
config.setAuthorName("Custom Author");
|
||||
config.setAuthorEmail("custom@example.com");
|
||||
|
||||
assertEquals("Custom Author", config.getAuthorName());
|
||||
assertEquals("custom@example.com", config.getAuthorEmail());
|
||||
}
|
||||
|
||||
private void setField(Object target, String fieldName, Object value) {
|
||||
try {
|
||||
var field = target.getClass().getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
field.set(target, value);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.krrishg.config;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class MapToJsonConverterTest {
|
||||
|
||||
private final MapToJsonConverter converter = new MapToJsonConverter();
|
||||
|
||||
@Test
|
||||
void convertToDatabaseColumnSerializesMap() {
|
||||
Map<String, String> map = Map.of("key1", "value1", "key2", "value2");
|
||||
|
||||
String json = converter.convertToDatabaseColumn(map);
|
||||
|
||||
assertNotNull(json);
|
||||
assertTrue(json.contains("key1"));
|
||||
assertTrue(json.contains("value1"));
|
||||
assertTrue(json.contains("key2"));
|
||||
assertTrue(json.contains("value2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertToEntityAttributeDeserializesJson() {
|
||||
String json = "{\"a\":\"1\",\"b\":\"2\"}";
|
||||
|
||||
Map<String, String> result = converter.convertToEntityAttribute(json);
|
||||
|
||||
assertEquals(2, result.size());
|
||||
assertEquals("1", result.get("a"));
|
||||
assertEquals("2", result.get("b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void roundtripPreservesMap() {
|
||||
Map<String, String> original = Map.of("alpha", "beta", "gamma", "delta");
|
||||
|
||||
String json = converter.convertToDatabaseColumn(original);
|
||||
Map<String, String> result = converter.convertToEntityAttribute(json);
|
||||
|
||||
assertEquals(original, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertToDatabaseColumnReturnsNullForNullInput() {
|
||||
assertNull(converter.convertToDatabaseColumn(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertToDatabaseColumnReturnsNullForEmptyMap() {
|
||||
assertNull(converter.convertToDatabaseColumn(Map.of()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertToEntityAttributeReturnsEmptyMapForNullInput() {
|
||||
assertEquals(Map.of(), converter.convertToEntityAttribute(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertToEntityAttributeReturnsEmptyMapForBlankInput() {
|
||||
assertEquals(Map.of(), converter.convertToEntityAttribute(""));
|
||||
assertEquals(Map.of(), converter.convertToEntityAttribute(" "));
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertToEntityAttributeThrowsOnMalformedJson() {
|
||||
assertThrows(RuntimeException.class, () ->
|
||||
converter.convertToEntityAttribute("{invalid json}"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
package com.krrishg.controller;
|
||||
|
||||
import com.krrishg.config.EncryptionService;
|
||||
import com.krrishg.config.GlobalExceptionHandler;
|
||||
import com.krrishg.config.JwtAuthenticationToken;
|
||||
import com.krrishg.config.UserPrincipal;
|
||||
import com.krrishg.model.AuthProvider;
|
||||
import com.krrishg.model.User;
|
||||
import com.krrishg.repository.UserRepository;
|
||||
import com.krrishg.support.TestSecurityConfig;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
@WebMvcTest(UserSettingsController.class)
|
||||
@Import({GlobalExceptionHandler.class, TestSecurityConfig.class})
|
||||
class UserSettingsControllerTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@MockBean
|
||||
private UserRepository userRepository;
|
||||
|
||||
@MockBean
|
||||
private EncryptionService encryptionService;
|
||||
|
||||
private UUID userId;
|
||||
private UserPrincipal principal;
|
||||
private JwtAuthenticationToken auth;
|
||||
private User testUser;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
userId = UUID.randomUUID();
|
||||
principal = new UserPrincipal(userId, "user@test.com", "Test User");
|
||||
auth = new JwtAuthenticationToken(principal, "test-token");
|
||||
testUser = User.builder()
|
||||
.id(userId)
|
||||
.email("user@test.com")
|
||||
.name("Test User")
|
||||
.provider(AuthProvider.LOCAL)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getLlmConfigReturnsConfigWithAllFields() throws Exception {
|
||||
Map<String, String> keys = new HashMap<>();
|
||||
keys.put("gemini", "encrypted-gemini-key");
|
||||
Map<String, String> urls = new HashMap<>();
|
||||
urls.put("gemini", "https://custom.gemini.com");
|
||||
Map<String, String> models = new HashMap<>();
|
||||
models.put("gemini", "gemini-2.0-flash");
|
||||
testUser.setLlmApiKeys(keys);
|
||||
testUser.setLlmBaseUrls(urls);
|
||||
testUser.setLlmModels(models);
|
||||
|
||||
when(userRepository.findById(userId)).thenReturn(Optional.of(testUser));
|
||||
|
||||
mockMvc.perform(get("/api/user/llm-config")
|
||||
.with(authentication(auth)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.gemini.configured").value(true))
|
||||
.andExpect(jsonPath("$.gemini.baseUrl").value("https://custom.gemini.com"))
|
||||
.andExpect(jsonPath("$.gemini.model").value("gemini-2.0-flash"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getLlmConfigReturnsMinimalConfigWhenNoUrlsOrModels() throws Exception {
|
||||
Map<String, String> keys = new HashMap<>();
|
||||
keys.put("openai", "encrypted-openai-key");
|
||||
testUser.setLlmApiKeys(keys);
|
||||
|
||||
when(userRepository.findById(userId)).thenReturn(Optional.of(testUser));
|
||||
|
||||
mockMvc.perform(get("/api/user/llm-config")
|
||||
.with(authentication(auth)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.openai.configured").value(true))
|
||||
.andExpect(jsonPath("$.openai.baseUrl").doesNotExist())
|
||||
.andExpect(jsonPath("$.openai.model").doesNotExist());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getLlmConfigReturnsEmptyMapWhenNoKeys() throws Exception {
|
||||
when(userRepository.findById(userId)).thenReturn(Optional.of(testUser));
|
||||
|
||||
mockMvc.perform(get("/api/user/llm-config")
|
||||
.with(authentication(auth)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().json("{}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getLlmConfigReturns400WhenUserNotFound() throws Exception {
|
||||
when(userRepository.findById(userId)).thenReturn(Optional.empty());
|
||||
|
||||
mockMvc.perform(get("/api/user/llm-config")
|
||||
.with(authentication(auth)))
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveLlmConfigSavesApiKey() throws Exception {
|
||||
when(userRepository.findById(userId)).thenReturn(Optional.of(testUser));
|
||||
when(encryptionService.encrypt("sk-test-key")).thenReturn("encrypted-key");
|
||||
|
||||
Map<String, String> request = new HashMap<>();
|
||||
request.put("provider", "openai");
|
||||
request.put("apiKey", "sk-test-key");
|
||||
|
||||
mockMvc.perform(put("/api/user/llm-config")
|
||||
.with(authentication(auth))
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
verify(userRepository).save(any(User.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveLlmConfigSavesBaseUrlAndModel() throws Exception {
|
||||
when(userRepository.findById(userId)).thenReturn(Optional.of(testUser));
|
||||
when(encryptionService.encrypt("key")).thenReturn("encrypted");
|
||||
|
||||
Map<String, String> request = new HashMap<>();
|
||||
request.put("provider", "gemini");
|
||||
request.put("apiKey", "key");
|
||||
request.put("baseUrl", "https://gemini.api.com");
|
||||
request.put("model", "gemini-2.0-flash");
|
||||
|
||||
mockMvc.perform(put("/api/user/llm-config")
|
||||
.with(authentication(auth))
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
verify(userRepository).save(any(User.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveLlmConfigMergesWithExistingConfig() throws Exception {
|
||||
Map<String, String> existingKeys = new HashMap<>();
|
||||
existingKeys.put("gemini", "existing-gemini-key");
|
||||
testUser.setLlmApiKeys(existingKeys);
|
||||
testUser.setLlmBaseUrls(new HashMap<>(Map.of("gemini", "https://gemini.api.com")));
|
||||
|
||||
when(userRepository.findById(userId)).thenReturn(Optional.of(testUser));
|
||||
when(encryptionService.encrypt("new-openai-key")).thenReturn("encrypted-new-key");
|
||||
|
||||
Map<String, String> request = new HashMap<>();
|
||||
request.put("provider", "openai");
|
||||
request.put("apiKey", "new-openai-key");
|
||||
|
||||
mockMvc.perform(put("/api/user/llm-config")
|
||||
.with(authentication(auth))
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
verify(userRepository).save(any(User.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveLlmConfigReturns400WhenProviderIsBlank() throws Exception {
|
||||
Map<String, String> request = new HashMap<>();
|
||||
request.put("provider", "");
|
||||
request.put("apiKey", "key");
|
||||
|
||||
mockMvc.perform(put("/api/user/llm-config")
|
||||
.with(authentication(auth))
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveLlmConfigReturns400WhenProviderIsNull() throws Exception {
|
||||
Map<String, String> request = new HashMap<>();
|
||||
request.put("apiKey", "key");
|
||||
|
||||
mockMvc.perform(put("/api/user/llm-config")
|
||||
.with(authentication(auth))
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveLlmConfigSkipsEmptyApiKey() throws Exception {
|
||||
when(userRepository.findById(userId)).thenReturn(Optional.of(testUser));
|
||||
|
||||
Map<String, String> request = new HashMap<>();
|
||||
request.put("provider", "openai");
|
||||
request.put("apiKey", "");
|
||||
|
||||
mockMvc.perform(put("/api/user/llm-config")
|
||||
.with(authentication(auth))
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
assertNull(testUser.getLlmApiKeys());
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteLlmConfigRemovesProviderConfig() throws Exception {
|
||||
Map<String, String> keys = new HashMap<>();
|
||||
keys.put("gemini", "encrypted-key");
|
||||
keys.put("openai", "encrypted-key");
|
||||
testUser.setLlmApiKeys(keys);
|
||||
testUser.setLlmBaseUrls(new HashMap<>(Map.of("gemini", "url")));
|
||||
testUser.setLlmModels(new HashMap<>(Map.of("gemini", "model")));
|
||||
|
||||
when(userRepository.findById(userId)).thenReturn(Optional.of(testUser));
|
||||
|
||||
mockMvc.perform(delete("/api/user/llm-config/gemini")
|
||||
.with(authentication(auth)))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
verify(userRepository).save(any(User.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteLlmConfigReturns400WhenUserNotFound() throws Exception {
|
||||
when(userRepository.findById(userId)).thenReturn(Optional.empty());
|
||||
|
||||
mockMvc.perform(delete("/api/user/llm-config/openai")
|
||||
.with(authentication(auth)))
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
}
|
||||
62
backend/src/test/java/com/krrishg/dto/AuthResponseTest.java
Normal file
62
backend/src/test/java/com/krrishg/dto/AuthResponseTest.java
Normal file
@@ -0,0 +1,62 @@
|
||||
package com.krrishg.dto;
|
||||
|
||||
import com.krrishg.model.AuthProvider;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class AuthResponseTest {
|
||||
|
||||
@Test
|
||||
void constructorSetsBearerTokenType() {
|
||||
AuthResponse.UserInfo userInfo = new AuthResponse.UserInfo(
|
||||
UUID.randomUUID(), "test@example.com", "Test", null, AuthProvider.LOCAL);
|
||||
|
||||
AuthResponse response = new AuthResponse("access-token", "refresh-token", userInfo);
|
||||
|
||||
assertEquals("access-token", response.getAccessToken());
|
||||
assertEquals("refresh-token", response.getRefreshToken());
|
||||
assertEquals("Bearer", response.getTokenType());
|
||||
assertSame(userInfo, response.getUser());
|
||||
}
|
||||
|
||||
@Test
|
||||
void builderWorksWithTokenType() {
|
||||
AuthResponse.UserInfo userInfo = AuthResponse.UserInfo.builder()
|
||||
.id(UUID.randomUUID())
|
||||
.email("user@example.com")
|
||||
.name("User")
|
||||
.provider(AuthProvider.GOOGLE)
|
||||
.build();
|
||||
|
||||
AuthResponse response = AuthResponse.builder()
|
||||
.accessToken("at")
|
||||
.refreshToken("rt")
|
||||
.tokenType("Custom")
|
||||
.user(userInfo)
|
||||
.build();
|
||||
|
||||
assertEquals("Custom", response.getTokenType());
|
||||
assertEquals("user@example.com", response.getUser().getEmail());
|
||||
}
|
||||
|
||||
@Test
|
||||
void userInfoBuilderSetsAllFields() {
|
||||
UUID id = UUID.randomUUID();
|
||||
AuthResponse.UserInfo userInfo = AuthResponse.UserInfo.builder()
|
||||
.id(id)
|
||||
.email("avatar@example.com")
|
||||
.name("Avatar User")
|
||||
.avatarUrl("https://example.com/avatar.png")
|
||||
.provider(AuthProvider.GITHUB)
|
||||
.build();
|
||||
|
||||
assertEquals(id, userInfo.getId());
|
||||
assertEquals("avatar@example.com", userInfo.getEmail());
|
||||
assertEquals("Avatar User", userInfo.getName());
|
||||
assertEquals("https://example.com/avatar.png", userInfo.getAvatarUrl());
|
||||
assertEquals(AuthProvider.GITHUB, userInfo.getProvider());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.krrishg.dto;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class LLMConfigRequestTest {
|
||||
|
||||
@Test
|
||||
void compactConstructorSetsProviderAndApiKey() {
|
||||
LLMConfigRequest request = new LLMConfigRequest("gemini", "test-key");
|
||||
|
||||
assertEquals("gemini", request.provider());
|
||||
assertEquals("test-key", request.apiKey());
|
||||
assertNull(request.baseUrl());
|
||||
assertNull(request.model());
|
||||
}
|
||||
|
||||
@Test
|
||||
void threeArgConstructorSetsProviderApiKeyAndBaseUrl() {
|
||||
LLMConfigRequest request = new LLMConfigRequest("openai", "sk-test", "https://api.openai.com");
|
||||
|
||||
assertEquals("openai", request.provider());
|
||||
assertEquals("sk-test", request.apiKey());
|
||||
assertEquals("https://api.openai.com", request.baseUrl());
|
||||
assertNull(request.model());
|
||||
}
|
||||
|
||||
@Test
|
||||
void fullConstructorSetsAllFields() {
|
||||
LLMConfigRequest request = new LLMConfigRequest("gemini", "key", "https://custom.url", "gemini-2.0-flash");
|
||||
|
||||
assertEquals("gemini", request.provider());
|
||||
assertEquals("key", request.apiKey());
|
||||
assertEquals("https://custom.url", request.baseUrl());
|
||||
assertEquals("gemini-2.0-flash", request.model());
|
||||
}
|
||||
}
|
||||
30
backend/src/test/java/com/krrishg/dto/LLMOptionsTest.java
Normal file
30
backend/src/test/java/com/krrishg/dto/LLMOptionsTest.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package com.krrishg.dto;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class LLMOptionsTest {
|
||||
|
||||
@Test
|
||||
void builderDefaults() {
|
||||
LLMOptions options = LLMOptions.builder().build();
|
||||
|
||||
assertEquals(0.9, options.getTemperature());
|
||||
assertEquals(4096, options.getMaxTokens());
|
||||
assertEquals(60, options.getTimeoutSeconds());
|
||||
}
|
||||
|
||||
@Test
|
||||
void builderOverridesDefaults() {
|
||||
LLMOptions options = LLMOptions.builder()
|
||||
.temperature(0.5)
|
||||
.maxTokens(2048)
|
||||
.timeoutSeconds(30)
|
||||
.build();
|
||||
|
||||
assertEquals(0.5, options.getTemperature());
|
||||
assertEquals(2048, options.getMaxTokens());
|
||||
assertEquals(30, options.getTimeoutSeconds());
|
||||
}
|
||||
}
|
||||
38
backend/src/test/java/com/krrishg/dto/ReferenceTest.java
Normal file
38
backend/src/test/java/com/krrishg/dto/ReferenceTest.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package com.krrishg.dto;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class ReferenceTest {
|
||||
|
||||
@Test
|
||||
void builderSetsAllFields() {
|
||||
Reference ref = Reference.builder()
|
||||
.type(Reference.ReferenceType.URL)
|
||||
.url("https://example.com")
|
||||
.altText("Example Site")
|
||||
.build();
|
||||
|
||||
assertEquals(Reference.ReferenceType.URL, ref.getType());
|
||||
assertEquals("https://example.com", ref.getUrl());
|
||||
assertEquals("Example Site", ref.getAltText());
|
||||
}
|
||||
|
||||
@Test
|
||||
void builderDefaultsToNull() {
|
||||
Reference ref = Reference.builder().build();
|
||||
|
||||
assertNull(ref.getType());
|
||||
assertNull(ref.getUrl());
|
||||
assertNull(ref.getAltText());
|
||||
}
|
||||
|
||||
@Test
|
||||
void referenceTypeEnumValues() {
|
||||
assertArrayEquals(
|
||||
new Reference.ReferenceType[]{Reference.ReferenceType.URL, Reference.ReferenceType.IMAGE},
|
||||
Reference.ReferenceType.values()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.krrishg.dto;
|
||||
|
||||
import com.krrishg.model.SelfHostedConfig;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class SelfHostedConfigResponseTest {
|
||||
|
||||
@Test
|
||||
void fromMapsAllFields() {
|
||||
UUID id = UUID.randomUUID();
|
||||
UUID siteId = UUID.randomUUID();
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
SelfHostedConfig config = SelfHostedConfig.builder()
|
||||
.id(id)
|
||||
.siteId(siteId)
|
||||
.domain("example.com")
|
||||
.sshHost("192.168.1.1")
|
||||
.sshPort(2222)
|
||||
.sshUser("deploy")
|
||||
.deployPath("/var/www/html")
|
||||
.nginxSitesPath("/etc/nginx/conf.d")
|
||||
.sslEnabled(true)
|
||||
.sslEmail("admin@example.com")
|
||||
.deployedAt(now)
|
||||
.createdAt(now)
|
||||
.updatedAt(now)
|
||||
.build();
|
||||
|
||||
SelfHostedConfigResponse response = SelfHostedConfigResponse.from(config, "ssh-ed25519 AAA...");
|
||||
|
||||
assertEquals(id, response.getId());
|
||||
assertEquals(siteId, response.getSiteId());
|
||||
assertEquals("example.com", response.getDomain());
|
||||
assertEquals("192.168.1.1", response.getSshHost());
|
||||
assertEquals(2222, response.getSshPort());
|
||||
assertEquals("deploy", response.getSshUser());
|
||||
assertEquals("/var/www/html", response.getDeployPath());
|
||||
assertEquals("/etc/nginx/conf.d", response.getNginxSitesPath());
|
||||
assertTrue(response.isSslEnabled());
|
||||
assertEquals("admin@example.com", response.getSslEmail());
|
||||
assertEquals("ssh-ed25519 AAA...", response.getPublicKey());
|
||||
assertEquals(now, response.getDeployedAt());
|
||||
assertEquals(now, response.getCreatedAt());
|
||||
assertEquals(now, response.getUpdatedAt());
|
||||
}
|
||||
|
||||
@Test
|
||||
void fromHandlesNullOptionalFields() {
|
||||
SelfHostedConfig config = SelfHostedConfig.builder()
|
||||
.id(UUID.randomUUID())
|
||||
.siteId(UUID.randomUUID())
|
||||
.domain("example.com")
|
||||
.sshHost("host")
|
||||
.sshUser("user")
|
||||
.build();
|
||||
|
||||
SelfHostedConfigResponse response = SelfHostedConfigResponse.from(config, null);
|
||||
|
||||
assertNull(response.getSslEmail());
|
||||
assertNull(response.getPublicKey());
|
||||
assertNull(response.getDeployedAt());
|
||||
assertFalse(response.isSslEnabled());
|
||||
}
|
||||
}
|
||||
57
backend/src/test/java/com/krrishg/dto/SiteStructureTest.java
Normal file
57
backend/src/test/java/com/krrishg/dto/SiteStructureTest.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package com.krrishg.dto;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class SiteStructureTest {
|
||||
|
||||
@Test
|
||||
void builderSetsAllFields() {
|
||||
Map<String, String> colors = Map.of("primary", "#000", "secondary", "#fff");
|
||||
Map<String, String> fonts = Map.of("heading", "Arial");
|
||||
Map<String, String> spacing = Map.of("margin", "16px");
|
||||
|
||||
SiteStructure.ThemeConfig theme = new SiteStructure.ThemeConfig(colors, fonts, spacing);
|
||||
|
||||
SiteStructure.PageStructure page = SiteStructure.PageStructure.builder()
|
||||
.id("home")
|
||||
.title("Home")
|
||||
.slug("/")
|
||||
.seoTitle("Home Page")
|
||||
.seoDescription("Welcome")
|
||||
.orderIndex(0)
|
||||
.rawHtml("<h1>Hello</h1>")
|
||||
.build();
|
||||
|
||||
SiteStructure structure = SiteStructure.builder()
|
||||
.theme(theme)
|
||||
.pages(List.of(page))
|
||||
.build();
|
||||
|
||||
assertNotNull(structure.getTheme());
|
||||
assertEquals("#000", structure.getTheme().getColors().get("primary"));
|
||||
assertEquals("Arial", structure.getTheme().getFonts().get("heading"));
|
||||
assertEquals("16px", structure.getTheme().getSpacing().get("margin"));
|
||||
|
||||
assertEquals(1, structure.getPages().size());
|
||||
assertEquals("home", structure.getPages().get(0).getId());
|
||||
assertEquals("Home", structure.getPages().get(0).getTitle());
|
||||
assertEquals("/", structure.getPages().get(0).getSlug());
|
||||
assertEquals("Home Page", structure.getPages().get(0).getSeoTitle());
|
||||
assertEquals("Welcome", structure.getPages().get(0).getSeoDescription());
|
||||
assertEquals(0, structure.getPages().get(0).getOrderIndex());
|
||||
assertEquals("<h1>Hello</h1>", structure.getPages().get(0).getRawHtml());
|
||||
}
|
||||
|
||||
@Test
|
||||
void builderHandlesNullOptionalFields() {
|
||||
SiteStructure structure = SiteStructure.builder().build();
|
||||
|
||||
assertNull(structure.getTheme());
|
||||
assertNull(structure.getPages());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.krrishg.model;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class AuthProviderTest {
|
||||
|
||||
@Test
|
||||
void enumValues() {
|
||||
assertArrayEquals(
|
||||
new AuthProvider[]{AuthProvider.LOCAL, AuthProvider.GOOGLE, AuthProvider.GITHUB, AuthProvider.OPENID},
|
||||
AuthProvider.values()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.krrishg.model;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class GenerationVersionTest {
|
||||
|
||||
@Test
|
||||
void builderSetsAllFields() {
|
||||
UUID siteId = UUID.randomUUID();
|
||||
UUID userId = UUID.randomUUID();
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
GenerationVersion version = GenerationVersion.builder()
|
||||
.id("mongo-id")
|
||||
.siteId(siteId)
|
||||
.userId(userId)
|
||||
.versionNumber(1)
|
||||
.prompt("Build a landing page")
|
||||
.fullStructure("{\"theme\":{}}")
|
||||
.createdAt(now)
|
||||
.build();
|
||||
|
||||
assertEquals("mongo-id", version.getId());
|
||||
assertEquals(siteId, version.getSiteId());
|
||||
assertEquals(userId, version.getUserId());
|
||||
assertEquals(1, version.getVersionNumber());
|
||||
assertEquals("Build a landing page", version.getPrompt());
|
||||
assertEquals("{\"theme\":{}}", version.getFullStructure());
|
||||
assertEquals(now, version.getCreatedAt());
|
||||
}
|
||||
|
||||
@Test
|
||||
void builderSupportsReferenceEntries() {
|
||||
GenerationVersion.ReferenceEntry entry = GenerationVersion.ReferenceEntry.builder()
|
||||
.type("IMAGE")
|
||||
.url("https://example.com/img.png")
|
||||
.altText("Screenshot")
|
||||
.build();
|
||||
|
||||
GenerationVersion version = GenerationVersion.builder()
|
||||
.siteId(UUID.randomUUID())
|
||||
.userId(UUID.randomUUID())
|
||||
.versionNumber(2)
|
||||
.prompt("With references")
|
||||
.references(List.of(entry))
|
||||
.build();
|
||||
|
||||
assertEquals(1, version.getReferences().size());
|
||||
assertEquals("IMAGE", version.getReferences().get(0).getType());
|
||||
assertEquals("https://example.com/img.png", version.getReferences().get(0).getUrl());
|
||||
assertEquals("Screenshot", version.getReferences().get(0).getAltText());
|
||||
}
|
||||
|
||||
@Test
|
||||
void noArgsConstructorCreatesEmptyObject() {
|
||||
GenerationVersion version = new GenerationVersion();
|
||||
assertNull(version.getId());
|
||||
assertNull(version.getSiteId());
|
||||
assertEquals(0, version.getVersionNumber());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.krrishg.model;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class SelfHostedConfigTest {
|
||||
|
||||
@Test
|
||||
void prePersistSetsIdAndTimestamps() {
|
||||
SelfHostedConfig config = new SelfHostedConfig();
|
||||
config.setSiteId(UUID.randomUUID());
|
||||
config.setDomain("example.com");
|
||||
config.setSshHost("192.168.1.1");
|
||||
config.setSshUser("deploy");
|
||||
|
||||
assertNull(config.getId());
|
||||
assertNull(config.getCreatedAt());
|
||||
assertNull(config.getUpdatedAt());
|
||||
|
||||
config.onCreate();
|
||||
|
||||
assertNotNull(config.getId());
|
||||
assertNotNull(config.getCreatedAt());
|
||||
assertNotNull(config.getUpdatedAt());
|
||||
}
|
||||
|
||||
@Test
|
||||
void prePersistDoesNotOverrideExistingId() {
|
||||
UUID existingId = UUID.randomUUID();
|
||||
SelfHostedConfig config = SelfHostedConfig.builder()
|
||||
.id(existingId)
|
||||
.siteId(UUID.randomUUID())
|
||||
.domain("example.com")
|
||||
.sshHost("host")
|
||||
.sshUser("user")
|
||||
.build();
|
||||
|
||||
config.onCreate();
|
||||
|
||||
assertEquals(existingId, config.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void preUpdateSetsUpdatedAt() {
|
||||
SelfHostedConfig config = SelfHostedConfig.builder()
|
||||
.siteId(UUID.randomUUID())
|
||||
.domain("example.com")
|
||||
.sshHost("host")
|
||||
.sshUser("user")
|
||||
.build();
|
||||
config.onCreate();
|
||||
|
||||
LocalDateTime original = config.getUpdatedAt();
|
||||
|
||||
config.onUpdate();
|
||||
|
||||
assertTrue(config.getUpdatedAt().isAfter(original));
|
||||
}
|
||||
|
||||
@Test
|
||||
void builderSetsDefaults() {
|
||||
SelfHostedConfig config = SelfHostedConfig.builder()
|
||||
.siteId(UUID.randomUUID())
|
||||
.domain("example.com")
|
||||
.sshHost("host")
|
||||
.sshUser("user")
|
||||
.build();
|
||||
|
||||
assertEquals(22, config.getSshPort());
|
||||
assertEquals("/var/www/{domain}/public", config.getDeployPath());
|
||||
assertEquals("/etc/nginx/sites-available", config.getNginxSitesPath());
|
||||
assertFalse(config.isSslEnabled());
|
||||
}
|
||||
}
|
||||
16
backend/src/test/java/com/krrishg/model/SiteStatusTest.java
Normal file
16
backend/src/test/java/com/krrishg/model/SiteStatusTest.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package com.krrishg.model;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class SiteStatusTest {
|
||||
|
||||
@Test
|
||||
void enumValues() {
|
||||
assertArrayEquals(
|
||||
new SiteStatus[]{SiteStatus.DRAFT, SiteStatus.PUBLISHED},
|
||||
SiteStatus.values()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.krrishg.service;
|
||||
|
||||
import com.krrishg.config.JwtConfig;
|
||||
import com.krrishg.model.AuthProvider;
|
||||
import com.krrishg.model.User;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.RedirectStrategy;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class OAuth2SuccessHandlerTest {
|
||||
|
||||
@Mock
|
||||
private JwtConfig jwtConfig;
|
||||
|
||||
@Mock
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Mock
|
||||
private HttpServletResponse response;
|
||||
|
||||
@Mock
|
||||
private Authentication authentication;
|
||||
|
||||
@Mock
|
||||
private RedirectStrategy redirectStrategy;
|
||||
|
||||
private OAuth2SuccessHandler handler;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
handler = new OAuth2SuccessHandler(jwtConfig);
|
||||
handler.setRedirectStrategy(redirectStrategy);
|
||||
}
|
||||
|
||||
@Test
|
||||
void onAuthenticationSuccessWithOAuth2UserRedirectsWithTokens() throws Exception {
|
||||
CustomOAuth2User oAuth2User = mock(CustomOAuth2User.class);
|
||||
User user = User.builder()
|
||||
.id(UUID.randomUUID())
|
||||
.email("user@example.com")
|
||||
.name("User")
|
||||
.provider(AuthProvider.GOOGLE)
|
||||
.build();
|
||||
when(authentication.getPrincipal()).thenReturn(oAuth2User);
|
||||
when(oAuth2User.getUser()).thenReturn(user);
|
||||
when(jwtConfig.generateAccessToken(user)).thenReturn("access-token-value");
|
||||
when(jwtConfig.generateRefreshToken(user)).thenReturn("refresh-token-value");
|
||||
|
||||
handler.onAuthenticationSuccess(request, response, authentication);
|
||||
|
||||
String expectedRedirect = "http://localhost:4200/oauth2/callback"
|
||||
+ "?accessToken=access-token-value&refreshToken=refresh-token-value";
|
||||
verify(redirectStrategy).sendRedirect(request, response, expectedRedirect);
|
||||
}
|
||||
|
||||
@Test
|
||||
void onAuthenticationSuccessWithNonOAuth2UserCallsSuper() throws Exception {
|
||||
when(authentication.getPrincipal()).thenReturn("plain principal");
|
||||
|
||||
handler.onAuthenticationSuccess(request, response, authentication);
|
||||
|
||||
verify(redirectStrategy).sendRedirect(eq(request), eq(response), anyString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package com.krrishg.service.llm;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class ProviderFactoryTest {
|
||||
|
||||
@Mock
|
||||
private RestTemplateBuilder restTemplateBuilder;
|
||||
|
||||
@Mock
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
private ProviderFactory factory;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
lenient().when(restTemplateBuilder.setConnectTimeout(any(Duration.class))).thenReturn(restTemplateBuilder);
|
||||
lenient().when(restTemplateBuilder.setReadTimeout(any(Duration.class))).thenReturn(restTemplateBuilder);
|
||||
lenient().when(restTemplateBuilder.build()).thenReturn(restTemplate);
|
||||
|
||||
factory = new ProviderFactory(
|
||||
"gemini-2.0-flash",
|
||||
"https://generativelanguage.googleapis.com/v1beta/models",
|
||||
"gpt-4o-mini",
|
||||
"https://api.openai.com/v1/chat/completions",
|
||||
restTemplateBuilder
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createProviderReturnsGeminiProvider() {
|
||||
LLMProvider provider = factory.createProvider("gemini", "test-key");
|
||||
|
||||
assertInstanceOf(GeminiProvider.class, provider);
|
||||
assertEquals("gemini", provider.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createProviderReturnsOpenAIProvider() {
|
||||
LLMProvider provider = factory.createProvider("openai", "sk-test");
|
||||
|
||||
assertInstanceOf(OpenAIProvider.class, provider);
|
||||
assertEquals("openai", provider.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createProviderWithCustomBaseUrl() {
|
||||
LLMProvider provider = factory.createProvider("gemini", "key", "https://custom.url");
|
||||
|
||||
assertInstanceOf(GeminiProvider.class, provider);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createProviderWithCustomBaseUrlAndModel() {
|
||||
LLMProvider provider = factory.createProvider("openai", "key", "https://custom.openai.com", "gpt-4");
|
||||
|
||||
assertInstanceOf(OpenAIProvider.class, provider);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createProviderWithCustomBaseUrlAppendsChatCompletionsForOpenAI() {
|
||||
LLMProvider provider = factory.createProvider("openai", "key", "https://custom.openai.com");
|
||||
|
||||
assertInstanceOf(OpenAIProvider.class, provider);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createProviderWithCustomBaseUrlHandlesTrailingSlashForOpenAI() {
|
||||
LLMProvider provider = factory.createProvider("openai", "key", "https://custom.openai.com/");
|
||||
|
||||
assertInstanceOf(OpenAIProvider.class, provider);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createProviderThrowsOnUnknownProvider() {
|
||||
IllegalArgumentException ex = assertThrows(IllegalArgumentException.class,
|
||||
() -> factory.createProvider("unknown", "key"));
|
||||
|
||||
assertTrue(ex.getMessage().contains("unknown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getAvailableProvidersReturnsBothProviders() {
|
||||
List<String> providers = factory.getAvailableProviders();
|
||||
|
||||
assertEquals(2, providers.size());
|
||||
assertTrue(providers.contains("gemini"));
|
||||
assertTrue(providers.contains("openai"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user