refactor(library): listed_user_game view and one shared schema (V24)

This commit is contained in:
lobo committed 2026-09-30 09:37:16 +02:00
1 parent b499e79c41
commit 9a09d535fc
11 files changed
+118 -83

No files matched your search

@@ -118,8 +118,11 @@ class AccountCleanupRepositoryTest extends AbstractPersistenceTest {
// A new table with user rows must be in the purge list, or "Delete my account" leaves its rows behind.
@Test
void tables_CoverEveryTableWithAUserId() {
List<String> withUserId = jdbc.queryForList("select table_name from information_schema.columns "
+ "where table_schema = 'public' and column_name = 'user_id' order by table_name", String.class);
// Base tables only: a view like listed_user_game has no rows of its own.
List<String> withUserId = jdbc.queryForList("select c.table_name from information_schema.columns c "
+ "join information_schema.tables t on t.table_schema = c.table_schema and t.table_name = c.table_name "
+ "where c.table_schema = 'public' and c.column_name = 'user_id' and t.table_type = 'BASE TABLE' "
+ "order by c.table_name", String.class);
assertThat(AccountCleanupRepository.TABLES).containsExactlyInAnyOrderElementsOf(withUserId);
}
@@ -0,0 +1,23 @@
package core_service.modules.library.repo;
import core_service.shared.test.AbstractPersistenceTest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import static org.junit.jupiter.api.Assertions.assertEquals;
class ListedUserGameViewTest extends AbstractPersistenceTest {
private static final String COLUMNS = "select column_name from information_schema.columns "
+ "where table_schema = 'public' and table_name = ? order by ordinal_position";
@Autowired
private JdbcTemplate jdbc;
@Test
void view_HasEveryColumnOfUserGame() {
assertEquals(jdbc.queryForList(COLUMNS, String.class, "user_game"),
jdbc.queryForList(COLUMNS, String.class, "listed_user_game"));
}
}
@@ -124,6 +124,29 @@ class UserGameRepositoryTest extends AbstractPersistenceTest {
assertEquals(Set.of(220L, 380L), Set.copyOf(userGameRepository.findBacklogAppids(USER_ID)));
}
@Test
void findListedSteamGames_LeavesOutHiddenRemovedAndHandAddedGames() {
userGameRepository.findById(new UserGameId(USER_ID, 380L)).orElseThrow().setHiddenAt(Instant.now());
userGameRepository.findById(new UserGameId(USER_ID, 700L)).orElseThrow().setRemovedAt(Instant.now());
steamGameRepository.save(new SteamGame(999L, "Elden Ring", null, Instant.now()));
userGameRepository.save(UserGame.manual(USER_ID, 999L, "PS5", GameStatus.PLAYING, 60, Instant.now()));
userGameRepository.flush();
assertEquals(Set.of(220L, 620L),
Set.copyOf(userGameRepository.findListedSteamGames(USER_ID).stream().map(UserGame::getAppid).toList()));
}
@Test
void listedUserGameView_LeavesOutHiddenAndRemovedGames() {
userGameRepository.findById(new UserGameId(USER_ID, 380L)).orElseThrow().setHiddenAt(Instant.now());
userGameRepository.findById(new UserGameId(USER_ID, 700L)).orElseThrow().setRemovedAt(Instant.now());
userGameRepository.flush();
assertEquals(Set.of(220L, 620L), Set.copyOf(entityManager.createNativeQuery(
"select appid from listed_user_game where user_id = :userId", Long.class)
.setParameter("userId", USER_ID).getResultList()));
}
@Test
void findAchievementProgress_LeavesOutGamesAddedByHand() {
steamGameRepository.save(new SteamGame(999L, "Elden Ring", null, Instant.now()));
@@ -96,7 +96,7 @@ class AchievementSyncServiceTest extends AbstractUnitTest {
}
private void library(List<UserGame> games, List<GameAchievementSchemaMeta> schemas, List<UserGameAchievementMeta> metas) {
when(userGameRepository.findByUserIdAndRemovedAtIsNull(USER_ID)).thenReturn(games);
when(userGameRepository.findListedSteamGames(USER_ID)).thenReturn(games);
when(schemaMetaRepository.findAllById(any())).thenReturn(schemas);
when(userAchievementMetaRepository.findByUserId(USER_ID)).thenReturn(metas);
}
@@ -117,28 +117,6 @@ class AchievementSyncServiceTest extends AbstractUnitTest {
verify(userAchievementMetaRepository, never()).save(any());
}
@Test
void syncLibrary_GameAddedByHand_AsksSteamNothing() {
UserGame manual = UserGame.manual(USER_ID, 620L, "PS5", core_service.modules.library.domain.GameStatus.PLAYING,
150, Instant.now());
library(List.of(manual), List.of(schema(620L, 10)), List.of());
service.syncLibrary(USER_ID, STEAM_ID);
verifyNoInteractions(steamApiService);
}
@Test
void syncLibrary_HiddenGame_AsksSteamNothing() {
UserGame hidden = game(620L, 120);
hidden.setHiddenAt(Instant.now());
library(List.of(hidden), List.of(), List.of());
service.syncLibrary(USER_ID, STEAM_ID);
verifyNoInteractions(steamApiService);
}
@Test
void syncLibrary_ChangedPlaytime_StoresUnlocksAndThePlaytime() {
library(List.of(game(620L, 150)), List.of(schema(620L, 10)), List.of(unlocks(620L, 3, 120)));
@@ -358,7 +336,7 @@ class AchievementSyncServiceTest extends AbstractUnitTest {
@Test
void syncLibrary_CallWhileRunning_RunsOnceMoreAfterwards() throws Exception {
when(userGameRepository.findByUserIdAndRemovedAtIsNull(USER_ID)).thenReturn(List.of(game(620L, 60)));
when(userGameRepository.findListedSteamGames(USER_ID)).thenReturn(List.of(game(620L, 60)));
when(schemaMetaRepository.findAllById(any())).thenReturn(List.of(schema(620L, 10)));
// The second run sees the row the first run stored.
when(userAchievementMetaRepository.findByUserId(USER_ID))
@@ -378,7 +356,7 @@ class AchievementSyncServiceTest extends AbstractUnitTest {
first.join(5_000);
verify(steamApiService, times(1)).getPlayerAchievements(STEAM_ID, 620L);
verify(userGameRepository, times(2)).findByUserIdAndRemovedAtIsNull(USER_ID);
verify(userGameRepository, times(2)).findListedSteamGames(USER_ID);
}
@Test
@@ -399,8 +377,8 @@ class AchievementSyncServiceTest extends AbstractUnitTest {
AchievementSyncService paced = new AchievementSyncService(userGameRepository, schemaRepository, schemaMetaRepository,
userAchievementRepository, userAchievementMetaRepository, steamApiService,
mock(PlatformTransactionManager.class), 30, pauseMillis);
when(userGameRepository.findByUserIdAndRemovedAtIsNull(1L)).thenReturn(List.of(new UserGame(1L, 620L, 60, Instant.now(), Instant.now())));
when(userGameRepository.findByUserIdAndRemovedAtIsNull(2L)).thenReturn(List.of(new UserGame(2L, 620L, 60, Instant.now(), Instant.now())));
when(userGameRepository.findListedSteamGames(1L)).thenReturn(List.of(new UserGame(1L, 620L, 60, Instant.now(), Instant.now())));
when(userGameRepository.findListedSteamGames(2L)).thenReturn(List.of(new UserGame(2L, 620L, 60, Instant.now(), Instant.now())));
when(schemaMetaRepository.findAllById(any())).thenReturn(List.of(schema(620L, 10)));
when(userAchievementMetaRepository.findByUserId(anyLong())).thenReturn(List.of());
List<Long> steamCallsAtNanos = Collections.synchronizedList(new ArrayList<>());