mirror of
https://github.com/imgfloat/server.git
synced 2026-05-08 10:19:35 +00:00
refactor+test: extend StringNormalizer, migrate SystemAdministratorService, add SystemAdministratorServiceTest
- Add StringNormalizer.normalize() (trim + toLowerCase ROOT) for username normalization - Migrate SystemAdministratorService private normalize() to use StringNormalizer.normalize() - Remove now-unused Locale import from SystemAdministratorService - Add StringNormalizerTest coverage for new normalize() method - Add SystemAdministratorServiceTest with 10 unit tests covering all public methods
This commit is contained in:
@@ -2,8 +2,8 @@ package dev.kruhlmann.imgfloat.service;
|
||||
|
||||
import dev.kruhlmann.imgfloat.model.db.imgfloat.SystemAdministrator;
|
||||
import dev.kruhlmann.imgfloat.repository.SystemAdministratorRepository;
|
||||
import dev.kruhlmann.imgfloat.util.StringNormalizer;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Collectors;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -137,6 +137,6 @@ public class SystemAdministratorService {
|
||||
}
|
||||
|
||||
private String normalize(String username) {
|
||||
return username.trim().toLowerCase(Locale.ROOT);
|
||||
return StringNormalizer.normalize(username);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,4 +16,13 @@ public final class StringNormalizer {
|
||||
public static String toLowerCaseRoot(String value) {
|
||||
return value == null ? null : value.toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code value.trim().toLowerCase(Locale.ROOT)}.
|
||||
* Useful for normalizing user-supplied identifiers such as Twitch usernames.
|
||||
* Returns {@code null} if {@code value} is {@code null}.
|
||||
*/
|
||||
public static String normalize(String value) {
|
||||
return value == null ? null : value.trim().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
package dev.kruhlmann.imgfloat.service;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import dev.kruhlmann.imgfloat.model.db.imgfloat.SystemAdministrator;
|
||||
import dev.kruhlmann.imgfloat.repository.SystemAdministratorRepository;
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
class SystemAdministratorServiceTest {
|
||||
|
||||
private SystemAdministratorRepository repo;
|
||||
private Environment environment;
|
||||
private SystemAdministratorService service;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
repo = mock(SystemAdministratorRepository.class);
|
||||
environment = mock(Environment.class);
|
||||
when(environment.getProperty("IMGFLOAT_INITIAL_TWITCH_USERNAME_SYSADMIN")).thenReturn("admin");
|
||||
when(environment.getProperty("org.springframework.boot.test.context.SpringBootTestContextBootstrapper"))
|
||||
.thenReturn(null);
|
||||
service = new SystemAdministratorService(repo, environment);
|
||||
}
|
||||
|
||||
@Test
|
||||
void isSysadminReturnsTrueForInitialSysadmin() {
|
||||
assertThat(service.isSysadmin("admin")).isTrue();
|
||||
assertThat(service.isSysadmin("ADMIN")).isTrue(); // case-insensitive
|
||||
}
|
||||
|
||||
@Test
|
||||
void isSysadminDelegatesToRepositoryForOtherUsers() {
|
||||
when(repo.existsByTwitchUsername("other")).thenReturn(true);
|
||||
assertThat(service.isSysadmin("other")).isTrue();
|
||||
when(repo.existsByTwitchUsername("unknown")).thenReturn(false);
|
||||
assertThat(service.isSysadmin("unknown")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void addSysadminSkipsIfAlreadyExists() {
|
||||
when(repo.existsByTwitchUsername("newuser")).thenReturn(true);
|
||||
service.addSysadmin("newuser");
|
||||
verify(repo, never()).save(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void addSysadminSavesNewUser() {
|
||||
when(repo.existsByTwitchUsername("newuser")).thenReturn(false);
|
||||
service.addSysadmin("newuser");
|
||||
verify(repo).save(any(SystemAdministrator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void addSysadminThrowsForInitialSysadmin() {
|
||||
assertThatThrownBy(() -> service.addSysadmin("admin"))
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessageContaining("initial");
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeSysadminThrowsForInitialSysadmin() {
|
||||
assertThatThrownBy(() -> service.removeSysadmin("admin"))
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessageContaining("initial");
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeSysadminThrowsWhenUserDoesNotExist() {
|
||||
when(repo.deleteByTwitchUsername("nonexistent")).thenReturn(0L);
|
||||
assertThatThrownBy(() -> service.removeSysadmin("nonexistent"))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeSysadminDeletesExistingUser() {
|
||||
when(repo.deleteByTwitchUsername("user")).thenReturn(1L);
|
||||
service.removeSysadmin("user");
|
||||
verify(repo).deleteByTwitchUsername("user");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getInitialSysadminNormalizesUsername() {
|
||||
when(environment.getProperty("IMGFLOAT_INITIAL_TWITCH_USERNAME_SYSADMIN")).thenReturn(" AdminUser ");
|
||||
assertThat(service.getInitialSysadmin()).isEqualTo("adminuser");
|
||||
}
|
||||
|
||||
@Test
|
||||
void listSysadminsIncludesInitialSysadminFromEnvironment() {
|
||||
SystemAdministrator persisted = new SystemAdministrator("other");
|
||||
when(repo.findAllByOrderByTwitchUsernameAsc()).thenReturn(List.of(persisted));
|
||||
List<String> admins = service.listSysadmins();
|
||||
assertThat(admins).contains("admin", "other");
|
||||
}
|
||||
}
|
||||
@@ -33,4 +33,15 @@ class StringNormalizerTest {
|
||||
// Turkish locale would uppercase 'i' to 'İ' but ROOT locale must not
|
||||
assertThat(StringNormalizer.toLowerCaseRoot("TITLE")).isEqualTo("title");
|
||||
}
|
||||
|
||||
@Test
|
||||
void normalizeTrimsAndLowercases() {
|
||||
assertThat(StringNormalizer.normalize(" Hello ")).isEqualTo("hello");
|
||||
assertThat(StringNormalizer.normalize("USER")).isEqualTo("user");
|
||||
}
|
||||
|
||||
@Test
|
||||
void normalizeReturnsNullForNull() {
|
||||
assertThat(StringNormalizer.normalize(null)).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user