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.model.db.imgfloat.SystemAdministrator;
|
||||||
import dev.kruhlmann.imgfloat.repository.SystemAdministratorRepository;
|
import dev.kruhlmann.imgfloat.repository.SystemAdministratorRepository;
|
||||||
|
import dev.kruhlmann.imgfloat.util.StringNormalizer;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -137,6 +137,6 @@ public class SystemAdministratorService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String normalize(String username) {
|
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) {
|
public static String toLowerCaseRoot(String value) {
|
||||||
return value == null ? null : value.toLowerCase(Locale.ROOT);
|
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
|
// Turkish locale would uppercase 'i' to 'İ' but ROOT locale must not
|
||||||
assertThat(StringNormalizer.toLowerCaseRoot("TITLE")).isEqualTo("title");
|
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