From cb0a73ee3ba77cc7b86b13ffcb34bfb91a243fe4 Mon Sep 17 00:00:00 2001 From: Luka Tarman Date: Tue, 16 Jan 2024 16:02:42 +0100 Subject: [PATCH] finished refactoring game identifier # refactored/updated game.service.js also # added appropriate tests # removed unused tests # removed unused imports # removed unused triedVia steam app methods # updated steam app tests --- .../game-identifier/game.identifier.js | 106 ++--- .../game-identifier/game.identifier.spec.js | 365 +++++------------- .../game-identifier/services/game.service.js | 30 +- .../services/game.service.spec.js | 211 ++++------ backend/src/main.js | 9 +- backend/src/models/steam.app.js | 26 -- backend/src/models/steam.app.spec.js | 61 +++ 7 files changed, 305 insertions(+), 503 deletions(-) diff --git a/backend/src/features/game-identifier/game.identifier.js b/backend/src/features/game-identifier/game.identifier.js index a6d9d0ca..c2dff0b1 100644 --- a/backend/src/features/game-identifier/game.identifier.js +++ b/backend/src/features/game-identifier/game.identifier.js @@ -1,7 +1,5 @@ import { - updateMissingDetails, updateMissingReleaseDates, - recordAttemptsViaSteamDb, recordHtmlAttempts, getGames, getIds, @@ -61,10 +59,7 @@ export class GameIdentifier { } async #identifyTypes(steamApps, source) { - const htmlDetailsPages = await this.#getSteamAppsHtmlDetailsPagesNR64( - steamApps, - source, - ); + const htmlDetailsPages = await this.#getSteamAppsHtmlDetailsPages(steamApps, source); const updatedSteamApps = recordHtmlAttempts(steamApps, htmlDetailsPages, source); @@ -73,7 +68,7 @@ export class GameIdentifier { return [games, updatedSteamApps]; } - async #getSteamAppsHtmlDetailsPagesNR64(steamApps, source) { + async #getSteamAppsHtmlDetailsPages(steamApps, source) { const detailsPages = []; for (let steamApp of steamApps) { @@ -104,34 +99,48 @@ export class GameIdentifier { this.#options.batchSize, ); - if (games.length === 0) { - this.#logger.debugc( - `no games without details in db, retrying in ${ - this.#options.globalIterationDelay - } ms`, - ); - return; - } + if (this.#gamesIsEmpty(games, "details")) return; + + const steamApps = await this.#steamAppsRepository.getSteamAppsById(getIds(games)); - const steamApps = await this.#steamAppsRepository.getSteamAppsById( - games.map((game) => game.id), + const [updatedGames, updatedSteamApps] = await this.#updateMissingDetails( + games, + steamApps, ); - const htmlDetailsPages = await this.#getSteamDbHtmlDetailsPages(games); + this.#persistUpdatedDetails(updatedGames, updatedSteamApps); + }; - const updatedApps = recordAttemptsViaSteamDb(steamApps, htmlDetailsPages); + #gamesIsEmpty = (games, message) => { + if (games.length === 0) return true; - updateMissingDetails(games, htmlDetailsPages); + this.#logger.debugc( + `no games without ${message} in db, retrying in ${ + this.#options.globalIterationDelay + } ms`, + ); - this.#persistMissingProperties(games, updatedApps); + return false; }; - async #getSteamDbHtmlDetailsPages(games) { + async #updateMissingDetails(games, steamApps) { + const source = ValidDataSources.validDataSources.steamDb; + + const htmlDetailsPages = await this.#getGamesHtmlDetailsPages(games, source); + + const updatedSteamApps = recordAttemptsViaSource(steamApps, htmlDetailsPages, source); + + const updatedGames = updateGamesMissingDetails(games, htmlDetailsPages); + + return [updatedGames, updatedSteamApps]; + } + + async #getGamesHtmlDetailsPages(games, source) { const htmlDetailsPages = []; for (let game of games) { // TODO https://github.com/lukatarman/steam-game-stats/issues/192 - const htmlPage = await this.#steamClient.getSteamDbHtmlDetailsPage(game.id); + const htmlPage = await this.#steamClient.getSourceHtmlDetailsPage(game.id, source); htmlDetailsPages.push({ page: htmlPage, id: game.id }); await delay(this.#options.unitDelay); @@ -140,11 +149,9 @@ export class GameIdentifier { return htmlDetailsPages; } - async #persistMissingProperties(games, appsWithoutPages) { - if (appsWithoutPages.length !== 0) { - this.#logger.debugc(`persisting ${appsWithoutPages.length} apps without pages`); - this.#steamAppsRepository.updateSteamAppsById(appsWithoutPages); - } + async #persistUpdatedDetails(games, updatedApps) { + this.#logger.debugc(`persisting ${updatedApps.length} apps without pages`); + this.#steamAppsRepository.updateSteamAppsById(updatedApps); this.#logger.debugc(`persisting ${games.length} games with updated details`); await this.#gamesRepository.updateGameDetails(games); @@ -157,36 +164,35 @@ export class GameIdentifier { this.#options.batchSize, ); - if (games.length === 0) { - this.#logger.debugc( - `no games without release dates in db, retrying in ${ - this.#options.iterationDelay - } ms`, - ); - return; - } + if (this.#gamesIsEmpty(games, "release dates")) return; - const steamApps = await this.#steamAppsRepository.getSteamAppsById( - games.map((game) => game.id), + const steamApps = await this.#steamAppsRepository.getSteamAppsById(getIds(games)); + + const [updatedGames, updatedSteamApps] = await this.#updateMissingReleaseDates( + games, + steamApps, ); - const htmlDetailsPages = await this.#getSteamDbHtmlDetailsPages(games); + this.#persistReleaseDates(updatedGames, updatedSteamApps); + }; - const updatedApps = recordAttemptsViaSteamDb(steamApps, htmlDetailsPages); + async #updateMissingReleaseDates(games, steamApps) { + const source = ValidDataSources.validDataSources.steamDb; - updateMissingReleaseDates(games, htmlDetailsPages); + const htmlDetailsPages = await this.#getGamesHtmlDetailsPages(games, source); - this.#persistReleaseDates(games, updatedApps); - }; + const updatedSteamApps = recordAttemptsViaSource(steamApps, htmlDetailsPages, source); - #persistReleaseDates = async (games, appsWithoutPages) => { - if (appsWithoutPages.length !== 0) { - this.#logger.debugc(`persisting ${appsWithoutPages.length} apps without pages`); - this.#steamAppsRepository.updateSteamAppsById(appsWithoutPages); - } + const updatedGames = updateMissingReleaseDates(games, htmlDetailsPages); - this.#logger.debugc(`persisting ${games.length} games with updated release dates`); + return [updatedGames, updatedSteamApps]; + } + + async #persistReleaseDates(games, steamApps) { + this.#logger.debugc(`persisting ${steamApps.length} apps without pages`); + this.#steamAppsRepository.updateSteamAppsById(steamApps); + this.#logger.debugc(`persisting ${games.length} games with updated release dates`); await this.#gamesRepository.updateReleaseDates(games); - }; + } } diff --git a/backend/src/features/game-identifier/game.identifier.spec.js b/backend/src/features/game-identifier/game.identifier.spec.js index 49c2eb0f..2b0fbc8e 100644 --- a/backend/src/features/game-identifier/game.identifier.spec.js +++ b/backend/src/features/game-identifier/game.identifier.spec.js @@ -1,9 +1,10 @@ import { GameIdentifier } from "./game.identifier.js"; -import { SteamApp } from "../../models/steam.app.js"; import { getGames, - recordAttemptsViaSteamDb, + getIds, + recordAttemptsViaSource, recordHtmlAttempts, + updateGamesMissingDetails, updateMissingReleaseDates, } from "./services/game.service.js"; import { HistoryCheck } from "../../models/history.check.js"; @@ -546,8 +547,8 @@ describe("game.identifier.js", function () { expect(this.steamAppsRepository.getSteamAppsById).toHaveBeenCalledTimes(0); }); - it("getSteamDbHtmlDetailsPage was not called", function () { - expect(this.steamClientMock.getSteamDbHtmlDetailsPage).toHaveBeenCalledTimes(0); + it("getSourceHtmlDetailsPage was not called", function () { + expect(this.steamClientMock.getSourceHtmlDetailsPage).toHaveBeenCalledTimes(0); }); it("updateSteamAppsById was not called", function () { @@ -561,22 +562,27 @@ describe("game.identifier.js", function () { describe("Finds two games with missing properties,", function () { beforeAll(async function () { - this.steamApps = getXSampleSteamApps(2); + this.source = ValidDataSources.validDataSources.steamDb; - this.games = getXGamesWithoutDetails(2); + const steamApps = getXSampleSteamApps(2); + + const games = getXGamesWithoutDetails(2); const pages = [counterStrikeHtmlDetailsSteamDb, riskOfRainHtmlDetailsSteamDb]; this.htmlDetailsPages = createHtmlDetailsPages(pages); - this.updatedApps = recordAttemptsViaSteamDb( - this.steamApps, + this.updatedGames = updateGamesMissingDetails(games, this.htmlDetailsPages); + + this.updatedApps = recordAttemptsViaSource( + steamApps, this.htmlDetailsPages, + this.source, ); this.steamClientMock = createSteamMock(pages); - this.steamAppsRepository = createSteamAppsRepositoryMock(this.steamApps); - this.gamesRepository = createGamesRepositoryMock(this.games); + this.steamAppsRepository = createSteamAppsRepositoryMock(steamApps); + this.gamesRepository = createGamesRepositoryMock(games); this.historyChecksRepository = createHistoryChecksRepositoryMock(); this.identifier = new GameIdentifier( @@ -599,28 +605,18 @@ describe("game.identifier.js", function () { expect(this.gamesRepository.getGamesWithoutDetails).toHaveBeenCalledWith(1); }); - it("getGamesWithoutDetails was called before getSteamDbHtmlDetailsPage", function () { - expect(this.gamesRepository.getGamesWithoutDetails).toHaveBeenCalledBefore( - this.steamClientMock.getSteamDbHtmlDetailsPage, - ); - }); - - it("getSteamDbHtmlDetailsPage was called twice", function () { - expect(this.steamClientMock.getSteamDbHtmlDetailsPage).toHaveBeenCalledTimes(2); + it("getSourceHtmlDetailsPage was called twice", function () { + expect(this.steamClientMock.getSourceHtmlDetailsPage).toHaveBeenCalledTimes(2); }); - it("getSteamDbHtmlDetailsPage was called with the correct ids", function () { - expect(this.steamClientMock.getSteamDbHtmlDetailsPage).toHaveBeenCalledWith( - this.games[0].id, + it("getSourceHtmlDetailsPage was called with the correct arguments", function () { + expect(this.steamClientMock.getSourceHtmlDetailsPage).toHaveBeenCalledWith( + this.updatedGames[0].id, + this.source, ); - expect(this.steamClientMock.getSteamDbHtmlDetailsPage).toHaveBeenCalledWith( - this.games[1].id, - ); - }); - - it("getSteamDbHtmlDetailsPage was called before updateSteamAppsById", function () { - expect(this.steamClientMock.getSteamDbHtmlDetailsPage).toHaveBeenCalledBefore( - this.steamAppsRepository.updateSteamAppsById, + expect(this.steamClientMock.getSourceHtmlDetailsPage).toHaveBeenCalledWith( + this.updatedGames[1].id, + this.source, ); }); @@ -634,18 +630,14 @@ describe("game.identifier.js", function () { ); }); - it("updateSteamAppsById was called before updateSteamAppsById", function () { - expect(this.steamAppsRepository.updateSteamAppsById).toHaveBeenCalledBefore( - this.gamesRepository.updateGameDetails, - ); - }); - it("updateGameDetails was called once", function () { expect(this.gamesRepository.updateGameDetails).toHaveBeenCalledTimes(1); }); it("updateGameDetails was called with the correct argument", function () { - expect(this.gamesRepository.updateGameDetails).toHaveBeenCalledWith(this.games); + expect(this.gamesRepository.updateGameDetails).toHaveBeenCalledWith( + this.updatedGames, + ); }); }); }); @@ -682,8 +674,8 @@ describe("game.identifier.js", function () { expect(this.steamAppsRepository.getSteamAppsById).toHaveBeenCalledTimes(0); }); - it("getSteamDbHtmlDetailsPage was not called", function () { - expect(this.steamClientMock.getSteamDbHtmlDetailsPage).toHaveBeenCalledTimes(0); + it("getSourceHtmlDetailsPage was not called", function () { + expect(this.steamClientMock.getSourceHtmlDetailsPage).toHaveBeenCalledTimes(0); }); it("updateSteamAppsById was not called", function () { @@ -696,244 +688,100 @@ describe("game.identifier.js", function () { }); describe("Finds two games with missing release dates", function () { - describe("with no empty html pages", function () { - beforeAll(async function () { - this.games = getXGamesWithoutDetails(2); - - const apps = getXSampleSteamApps(2); - - const pages = [counterStrikeHtmlDetailsSteamDb, riskOfRainHtmlDetailsSteamDb]; - - const updatedPages = createHtmlDetailsPages(pages); - - this.updatedApps = recordAttemptsViaSteamDb(apps, updatedPages); - - this.steamClientMock = createSteamMock([ - counterStrikeHtmlDetailsSteamDb, - riskOfRainHtmlDetailsSteamDb, - ]); - this.steamAppsRepository = createSteamAppsRepositoryMock(apps); - this.gamesRepository = createGamesRepositoryMock(this.games); - this.historyChecksRepository = createHistoryChecksRepositoryMock(); - - this.identifier = new GameIdentifier( - this.steamClientMock, - this.steamAppsRepository, - this.gamesRepository, - this.historyChecksRepository, - createLoggerMock(), - createConfigMock(2).features, - ); - - await this.identifier.updateGamesWithoutReleaseDates(); - }); - - it("getGamesWithoutReleaseDates was called once", function () { - expect(this.gamesRepository.getGamesWithoutReleaseDates).toHaveBeenCalledTimes( - 1, - ); - }); - - it("getGamesWithoutReleaseDates was called with the correct batch size", function () { - expect(this.gamesRepository.getGamesWithoutReleaseDates).toHaveBeenCalledWith( - 2, - ); - }); - - it("getGamesWithoutReleaseDates was called before getSteamAppsById", function () { - expect(this.gamesRepository.getGamesWithoutReleaseDates).toHaveBeenCalledBefore( - this.steamAppsRepository.getSteamAppsById, - ); - }); - - it("getSteamAppsById was called once", function () { - expect(this.steamAppsRepository.getSteamAppsById).toHaveBeenCalledTimes(1); - }); - - it("getSteamAppsById was called with the correct argument", function () { - expect(this.steamAppsRepository.getSteamAppsById).toHaveBeenCalledWith( - this.games.map((game) => game.id), - ); - }); + beforeAll(async function () { + const games = getXGamesWithoutDetails(2); - it("getSteamAppsById was called before getSteamDbHtmlDetailsPage", function () { - expect(this.steamAppsRepository.getSteamAppsById).toHaveBeenCalledBefore( - this.steamClientMock.getSteamDbHtmlDetailsPage, - ); - }); + const apps = getXSampleSteamApps(2); - it("getSteamDbHtmlDetailsPage was called twice", function () { - expect(this.steamClientMock.getSteamDbHtmlDetailsPage).toHaveBeenCalledTimes(2); - }); + const pages = [counterStrikeHtmlDetailsSteamDb, riskOfRainHtmlDetailsSteamDb]; - it("getSteamDbHtmlDetailsPage was called with the correct ids", function () { - expect(this.steamClientMock.getSteamDbHtmlDetailsPage).toHaveBeenCalledWith( - this.games[0].id, - ); - expect(this.steamClientMock.getSteamDbHtmlDetailsPage).toHaveBeenCalledWith( - this.games[1].id, - ); - }); + const updatedPages = createHtmlDetailsPages(pages); - it("getSteamDbHtmlDetailsPage was called before updateSteamAppsById", function () { - expect(this.steamClientMock.getSteamDbHtmlDetailsPage).toHaveBeenCalledBefore( - this.steamAppsRepository.updateSteamAppsById, - ); - }); + this.source = ValidDataSources.validDataSources.steamDb; - it("updateSteamAppsById was called once", function () { - expect(this.steamAppsRepository.updateSteamAppsById).toHaveBeenCalledTimes(1); - }); + this.updatedApps = recordAttemptsViaSource(apps, updatedPages, this.source); - it("updateSteamAppsById was called with the correct argument", function () { - expect(this.steamAppsRepository.updateSteamAppsById).toHaveBeenCalledWith( - this.updatedApps, - ); - }); + this.updatedGames = updateMissingReleaseDates(games, updatedPages); - it("updateSteamAppsById was called before updateReleaseDates", function () { - expect(this.steamAppsRepository.updateSteamAppsById).toHaveBeenCalledBefore( - this.gamesRepository.updateReleaseDates, - ); - }); + this.steamClientMock = createSteamMock([ + counterStrikeHtmlDetailsSteamDb, + riskOfRainHtmlDetailsSteamDb, + ]); + this.steamAppsRepository = createSteamAppsRepositoryMock(apps); + this.gamesRepository = createGamesRepositoryMock(games); + this.historyChecksRepository = createHistoryChecksRepositoryMock(); - it("updateReleaseDates was called once", function () { - expect(this.gamesRepository.updateReleaseDates).toHaveBeenCalledTimes(1); - }); + this.identifier = new GameIdentifier( + this.steamClientMock, + this.steamAppsRepository, + this.gamesRepository, + this.historyChecksRepository, + createLoggerMock(), + createConfigMock(2).features, + ); - it("updateReleaseDates was called with the correct argument", function () { - expect(this.gamesRepository.updateReleaseDates).toHaveBeenCalledWith( - this.games, - ); - }); + await this.identifier.updateGamesWithoutReleaseDates(); }); - describe("with one empty html page", function () { - beforeAll(async function () { - const steamApps = getXSampleSteamApps(2); - - this.games = getXGamesWithoutDetails(2); - - const pages = [counterStrikeHtmlDetailsSteamDb, ""]; - - this.steamClientMock = createSteamMock(pages); - - const htmlPages = createHtmlDetailsPages(pages); - - this.updatedApps = recordAttemptsViaSteamDb(steamApps, htmlPages); - - updateMissingReleaseDates(this.games, htmlPages); - - this.steamAppsRepository = createSteamAppsRepositoryMock(steamApps); - this.gamesRepository = createGamesRepositoryMock(this.games); - this.historyChecksRepository = createHistoryChecksRepositoryMock(); - - this.identifier = new GameIdentifier( - this.steamClientMock, - this.steamAppsRepository, - this.gamesRepository, - this.historyChecksRepository, - createLoggerMock(), - createConfigMock(2).features, - ); - - await this.identifier.updateGamesWithoutReleaseDates(); - }); - - it("getGamesWithoutReleaseDates was called once", function () { - expect(this.gamesRepository.getGamesWithoutReleaseDates).toHaveBeenCalledTimes( - 1, - ); - }); - - it("getGamesWithoutReleaseDates was called with the correct batch size", function () { - expect(this.gamesRepository.getGamesWithoutReleaseDates).toHaveBeenCalledWith( - 2, - ); - }); - - it("getGamesWithoutReleaseDates was called before getSteamAppsById", function () { - expect(this.gamesRepository.getGamesWithoutReleaseDates).toHaveBeenCalledBefore( - this.steamAppsRepository.getSteamAppsById, - ); - }); - - it("getSteamAppsById was called once", function () { - expect(this.steamAppsRepository.getSteamAppsById).toHaveBeenCalledTimes(1); - }); - - it("getSteamAppsById was called with the correct argument", function () { - expect(this.steamAppsRepository.getSteamAppsById).toHaveBeenCalledWith( - this.games.map((game) => game.id), - ); - }); + it("getGamesWithoutReleaseDates was called once", function () { + expect(this.gamesRepository.getGamesWithoutReleaseDates).toHaveBeenCalledTimes(1); + }); - it("getSteamAppsById was called before getSteamDbHtmlDetailsPage", function () { - expect(this.steamAppsRepository.getSteamAppsById).toHaveBeenCalledBefore( - this.steamClientMock.getSteamDbHtmlDetailsPage, - ); - }); + it("getGamesWithoutReleaseDates was called with the correct batch size", function () { + expect(this.gamesRepository.getGamesWithoutReleaseDates).toHaveBeenCalledWith(2); + }); - it("getSteamDbHtmlDetailsPage was called twice", function () { - expect(this.steamClientMock.getSteamDbHtmlDetailsPage).toHaveBeenCalledTimes(2); - }); + it("getSteamAppsById was called once", function () { + expect(this.steamAppsRepository.getSteamAppsById).toHaveBeenCalledTimes(1); + }); - it("getSteamDbHtmlDetailsPage was called with the correct ids", function () { - expect(this.steamClientMock.getSteamDbHtmlDetailsPage).toHaveBeenCalledWith( - this.games[0].id, - ); - expect(this.steamClientMock.getSteamDbHtmlDetailsPage).toHaveBeenCalledWith( - this.games[1].id, - ); - }); + it("getSteamAppsById was called with the correct argument", function () { + expect(this.steamAppsRepository.getSteamAppsById).toHaveBeenCalledWith( + getIds(this.updatedGames), + ); + }); - it("getSteamDbHtmlDetailsPage was called before updateSteamAppsById", function () { - expect(this.steamClientMock.getSteamDbHtmlDetailsPage).toHaveBeenCalledBefore( - this.steamAppsRepository.updateSteamAppsById, - ); - }); + it("getSourceHtmlDetailsPage was called twice", function () { + expect(this.steamClientMock.getSourceHtmlDetailsPage).toHaveBeenCalledTimes(2); + }); - it("updateSteamAppsById was called once", function () { - expect(this.steamAppsRepository.updateSteamAppsById).toHaveBeenCalledTimes(1); - }); + it("getSourceHtmlDetailsPage was called with the correct ids", function () { + expect(this.steamClientMock.getSourceHtmlDetailsPage).toHaveBeenCalledWith( + this.updatedGames[0].id, + this.source, + ); + expect(this.steamClientMock.getSourceHtmlDetailsPage).toHaveBeenCalledWith( + this.updatedGames[1].id, + this.source, + ); + }); - it("updateSteamAppsById was called with the correct argument", function () { - expect(this.steamAppsRepository.updateSteamAppsById).toHaveBeenCalledWith( - this.updatedApps, - ); - }); + it("updateSteamAppsById was called once", function () { + expect(this.steamAppsRepository.updateSteamAppsById).toHaveBeenCalledTimes(1); + }); - it("updateSteamAppsById was called before updateReleaseDates", function () { - expect(this.steamAppsRepository.updateSteamAppsById).toHaveBeenCalledBefore( - this.gamesRepository.updateReleaseDates, - ); - }); + it("updateSteamAppsById was called with the correct argument", function () { + expect(this.steamAppsRepository.updateSteamAppsById).toHaveBeenCalledWith( + this.updatedApps, + ); + }); - it("updateReleaseDates was called once", function () { - expect(this.gamesRepository.updateReleaseDates).toHaveBeenCalledTimes(1); - }); + it("updateReleaseDates was called once", function () { + expect(this.gamesRepository.updateReleaseDates).toHaveBeenCalledTimes(1); + }); - it("updateReleaseDates was called with the correct argument", function () { - expect(this.gamesRepository.updateReleaseDates).toHaveBeenCalledWith( - this.games, - ); - }); + it("updateReleaseDates was called with the correct argument", function () { + expect(this.gamesRepository.updateReleaseDates).toHaveBeenCalledWith( + this.updatedGames, + ); }); }); }); }); function createSteamMock(args) { - const spyObj = jasmine.createSpyObj("steamClient", [ - "getSteamAppHtmlDetailsPage", - "getSteamchartsGameHtmlDetailsPage", - "getSteamDbHtmlDetailsPage", - "getSourceHtmlDetailsPage", - ]); - - spyObj.getSteamAppHtmlDetailsPage.and.returnValues(...args); - spyObj.getSteamchartsGameHtmlDetailsPage.and.returnValues(...args); - spyObj.getSteamDbHtmlDetailsPage.and.returnValues(...args); + const spyObj = jasmine.createSpyObj("steamClient", ["getSourceHtmlDetailsPage"]); + spyObj.getSourceHtmlDetailsPage.and.returnValues(...args); return spyObj; @@ -954,6 +802,7 @@ function createGamesRepositoryMock(gamesRepoRet) { updateGameDetails: Promise.resolve(undefined), getGamesWithoutReleaseDates: Promise.resolve(gamesRepoRet), updateReleaseDates: Promise.resolve(undefined), + getSourceHtmlDetailsPage: Promise.resolve(gamesRepoRet), }); } @@ -962,19 +811,3 @@ function createHistoryChecksRepositoryMock() { insertManyHistoryChecks: Promise.resolve(undefined), }); } - -function instantiateAndMark(apps, pages) { - const instantiatedApps = SteamApp.manyFromSteamApi(apps); - - const updatedApps = instantiatedApps.map((app, i) => { - if (pages[i].page === "") app.failedViaSteamchartsWeb(); - if (pages[i].page) { - app.type = SteamApp.validTypes.game; - } - app.triedViaSteamchartsWeb(); - - return app; - }); - - return updatedApps; -} diff --git a/backend/src/features/game-identifier/services/game.service.js b/backend/src/features/game-identifier/services/game.service.js index 0666ff40..b45bf86f 100644 --- a/backend/src/features/game-identifier/services/game.service.js +++ b/backend/src/features/game-identifier/services/game.service.js @@ -125,18 +125,6 @@ export function recordAttemptsViaSource(steamApps, htmlDetailsPages, source) { }); } -export function recordAttemptsViaSteamDb(steamApps, htmlDetailsPages, source) { - return steamApps.map((app) => { - const appCopy = app.copy(); - appCopy.triedViaSteamDb(); - - const currentPage = htmlDetailsPages.find((page) => page.id == app.appid); - if (currentPage.page === "") appCopy.failedViaSteamDb(); - - return appCopy; - }); -} - export function updateGamesMissingDetails(games, htmlDetailsPages) { return htmlDetailsPages.map(({ page }, i) => { const gameCopy = games[i].copy(); @@ -151,16 +139,6 @@ export function updateGamesMissingDetails(games, htmlDetailsPages) { }); } -export function updateMissingDetails(games, htmlDetailsPages) { - htmlDetailsPages.forEach(({ page }, i) => { - games[i].updateGameDetails( - getSteamDbDevelopers(page), - getSteamDbGenres(page), - getSteamDbDescription(page), - ); - }); -} - export function getSteamDbDevelopers(page) { const { document } = parseHTML(page); @@ -200,8 +178,12 @@ export function getSteamDbDescription(page) { } export function updateMissingReleaseDates(games, htmlDetailsPages) { - games.forEach((game, i) => { - game.updateReleaseDate(getSteamDbReleaseDate(htmlDetailsPages[i].page)); + return games.map((game, i) => { + const gameCopy = game.copy(); + + gameCopy.updateReleaseDate(getSteamDbReleaseDate(htmlDetailsPages[i].page)); + + return gameCopy; }); } diff --git a/backend/src/features/game-identifier/services/game.service.spec.js b/backend/src/features/game-identifier/services/game.service.spec.js index 03c2bea6..e40b60a9 100644 --- a/backend/src/features/game-identifier/services/game.service.spec.js +++ b/backend/src/features/game-identifier/services/game.service.spec.js @@ -3,19 +3,18 @@ import { getDevelopers, getGenres, getGameDescription, - updateMissingDetails, getSteamDbReleaseDate, getSteamDbDevelopers, getSteamDbGenres, getSteamDbDescription, updateMissingReleaseDates, - recordAttemptsViaSteamDb, recordHtmlAttempts, getGames, getSteamWebAppType, recordAttemptsViaSource, updateGamesMissingDetails, getSteamchartsAppType, + getIds, } from "./game.service.js"; import { animaddicts2gameHtmlDetailsPage } from "../../../../assets/steam-details-pages/animaddicts.2.game.html.details.page.js"; import { feartressGameHtmlDetailsPage } from "../../../../assets/steam-details-pages/feartress.game.html.details.page.js"; @@ -31,7 +30,10 @@ import { ValidDataSources } from "../../../models/valid.data.sources.js"; import { counterStrikeHtmlDetailsSteamDb } from "../../../../assets/steamdb-details-pages/counter.strike.html.details.page.js"; import { riskOfRainHtmlDetailsSteamDb } from "../../../../assets/steamdb-details-pages/risk.of.rain.html.details.page.js"; import { karmazooHtmlDetailsPageSteamDb } from "../../../../assets/steamdb-details-pages/karmazoo.html.details.page.js"; -import { getXsteamchartsInstantiatedGames } from "../../../models/game.mocks.js"; +import { + getXGamesWithoutDetails, + getXsteamchartsInstantiatedGames, +} from "../../../models/game.mocks.js"; import { createHtmlDetailsPages } from "../../../../assets/html.details.pages.mock.js"; import { getXSampleSteamApps } from "../../../models/steam.app.mocks.js"; import { crushTheCastleHtmlDetailsSteamcharts } from "../../../../assets/steamcharts-details-pages/crush.the.castle.legacy.collection.html.details.page.js"; @@ -46,6 +48,8 @@ describe("game.service.js", () => { const source = ValidDataSources.validDataSources.steamDb; this.result = recordHtmlAttempts(apps, pages, source); + + apps[0].appid = 5; }); it("the first attempt is correctly recorded", function () { @@ -63,6 +67,10 @@ describe("game.service.js", () => { ValidDataSources.validDataSources.steamDb, ]); }); + + it("the resulting steam app is a copy", function () { + expect(this.result[0].appid).toBe(1); + }); }); }); @@ -329,124 +337,92 @@ describe("game.service.js", () => { }); }); - describe(".recordAttemptsViaSource", function () { - describe("if one of the pages is empty", function () { + describe(".getIds", () => { + describe("if two games are passed in", function () { beforeAll(function () { - const source = ValidDataSources.validDataSources.steamDb; - this.apps = getXSampleSteamApps(2); - - this.pages = createHtmlDetailsPages([counterStrikeHtmlDetailsSteamDb, ""]); + const games = getXGamesWithoutDetails(2); - this.result = recordAttemptsViaSource(this.apps, this.pages, source); + this.result = getIds(games); }); - it("the first app has the correct values", function () { - expect(this.result[0].triedVia).toEqual([ - ValidDataSources.validDataSources.steamDb, - ]); - expect(this.result[0].failedVia).toEqual([]); - }); - - it("the second app has the correct values", function () { - expect(this.result[1].triedVia).toEqual([ - ValidDataSources.validDataSources.steamDb, - ]); - expect(this.result[1].failedVia).toEqual([ - ValidDataSources.validDataSources.steamDb, - ]); + it("two ids are returned", function () { + expect(this.result[0]).toBe(1); + expect(this.result[1]).toBe(2); }); }); + }); - describe("if none of the pages are empty", function () { - beforeAll(function () { - this.apps = getXSampleSteamApps(2); - - this.pages = createHtmlDetailsPages([ - counterStrikeHtmlDetailsSteamDb, - karmazooHtmlDetailsPageSteamDb, - ]); - - this.result = recordAttemptsViaSteamDb(this.apps, this.pages); - }); - - it("the first app has the correct values", function () { - expect(this.result[0].triedVia).toEqual([ - ValidDataSources.validDataSources.steamDb, - ]); - expect(this.result[0].failedVia).toEqual([]); - }); + describe(".recordAttemptsViaSource", function () { + describe("via steamDb", function () { + describe("if one of the pages is empty", function () { + beforeAll(function () { + const source = ValidDataSources.validDataSources.steamDb; + this.apps = getXSampleSteamApps(2); - it("the second app has the correct values", function () { - expect(this.result[1].triedVia).toEqual([ - ValidDataSources.validDataSources.steamDb, - ]); - expect(this.result[1].failedVia).toEqual([]); - }); - }); - }); + this.pages = createHtmlDetailsPages([counterStrikeHtmlDetailsSteamDb, ""]); - describe(".recordAttemptsViaSteamDb", function () { - describe("if one of the pages is empty", function () { - beforeAll(function () { - this.apps = getXSampleSteamApps(2); + this.result = recordAttemptsViaSource(this.apps, this.pages, source); - this.pages = createHtmlDetailsPages([counterStrikeHtmlDetailsSteamDb, ""]); + this.apps[0].appid = 5; + this.apps[1].appid = 5; + }); - this.result = recordAttemptsViaSteamDb(this.apps, this.pages); - }); + it("the first app has the correct values", function () { + expect(this.result[0].triedVia).toEqual([ + ValidDataSources.validDataSources.steamDb, + ]); + expect(this.result[0].failedVia).toEqual([]); + }); - it("the first app has the correct values", function () { - expect(this.result[0].triedVia).toEqual([ - ValidDataSources.validDataSources.steamDb, - ]); - expect(this.result[0].failedVia).toEqual([]); - }); + it("the second app has the correct values", function () { + expect(this.result[1].triedVia).toEqual([ + ValidDataSources.validDataSources.steamDb, + ]); + expect(this.result[1].failedVia).toEqual([ + ValidDataSources.validDataSources.steamDb, + ]); + }); - it("the second app has the correct values", function () { - expect(this.result[1].triedVia).toEqual([ - ValidDataSources.validDataSources.steamDb, - ]); - expect(this.result[1].failedVia).toEqual([ - ValidDataSources.validDataSources.steamDb, - ]); + it("the resulting apps are copies", function () { + expect(this.result[0].appid).toBe(1); + expect(this.result[1].appid).toBe(2); + }); }); - }); - describe("if none of the pages are empty", function () { - beforeAll(function () { - this.apps = getXSampleSteamApps(2); + describe("if none of the pages are empty", function () { + beforeAll(function () { + const source = ValidDataSources.validDataSources.steamDb; + this.apps = getXSampleSteamApps(2); - this.pages = createHtmlDetailsPages([ - counterStrikeHtmlDetailsSteamDb, - karmazooHtmlDetailsPageSteamDb, - ]); + this.pages = createHtmlDetailsPages([ + counterStrikeHtmlDetailsSteamDb, + karmazooHtmlDetailsPageSteamDb, + ]); - this.result = recordAttemptsViaSteamDb(this.apps, this.pages); - }); + this.result = recordAttemptsViaSource(this.apps, this.pages, source); - it("the first app has the correct values", function () { - expect(this.result[0].triedVia).toEqual([ - ValidDataSources.validDataSources.steamDb, - ]); - expect(this.result[0].failedVia).toEqual([]); - }); + this.apps[0].appid = 5; + this.apps[1].appid = 5; + }); - it("the second app has the correct values", function () { - expect(this.result[1].triedVia).toEqual([ - ValidDataSources.validDataSources.steamDb, - ]); - expect(this.result[1].failedVia).toEqual([]); - }); - }); + it("the first app has the correct values", function () { + expect(this.result[0].triedVia).toEqual([ + ValidDataSources.validDataSources.steamDb, + ]); + expect(this.result[0].failedVia).toEqual([]); + }); - describe("when the result contains a value,", function () { - beforeAll(function () { - this.app = getXSampleSteamApps(1); - this.steamApp = SteamApp.oneFromSteamApi(this.app); - }); + it("the second app has the correct values", function () { + expect(this.result[1].triedVia).toEqual([ + ValidDataSources.validDataSources.steamDb, + ]); + expect(this.result[1].failedVia).toEqual([]); + }); - it("the function returns the steamApp. The type property is 'game'", function () { - expect(this.result.type).toBe(SteamApp.validTypes.game); + it("the resulting apps are copies", function () { + expect(this.result[0].appid).toBe(1); + expect(this.result[1].appid).toBe(2); + }); }); }); }); @@ -486,41 +462,6 @@ describe("game.service.js", () => { }); }); - describe(".updateMissingDetails.", function () { - describe("When we try to update two games with missing details,", function () { - beforeAll(function () { - this.games = getXsteamchartsInstantiatedGames(2); - - const htmlDetailsPages = createHtmlDetailsPages([ - counterStrikeHtmlDetailsSteamDb, - riskOfRainHtmlDetailsSteamDb, - ]); - - updateMissingDetails(this.games, htmlDetailsPages); - }); - - it("two games are returned", function () { - expect(this.games.length).toBe(2); - }); - - it("the first game's details are updated", function () { - expect(this.games[0].developers).toEqual(["Valve", "Hidden Path Entertainment"]); - expect(this.games[0].genres).toEqual(["Action", "Free to Play"]); - expect(this.games[0].description).toBe( - "Counter-Strike: Global Offensive (CS: GO) expands upon the team-based action gameplay that it pioneered when it was launched 19 years ago. CS: GO features new maps, characters, weapons, and game modes, and delivers updated versions of the classic CS content (de_dust2, etc.).", - ); - }); - - it("the second game's details are updated", function () { - expect(this.games[1].developers).toEqual(["Hopoo Games"]); - expect(this.games[1].genres).toEqual(["Action", "Indie"]); - expect(this.games[1].description).toBe( - "Escape a chaotic alien planet by fighting through hordes of frenzied monsters – with your friends, or on your own. Combine loot in surprising ways and master each character until you become the havoc you feared upon your first crash landing.", - ); - }); - }); - }); - describe(".getSteamDbDevelopers.", function () { describe("When we provide a html page that contains two developers,", function () { beforeAll(function () { diff --git a/backend/src/main.js b/backend/src/main.js index 383609de..b924b6aa 100644 --- a/backend/src/main.js +++ b/backend/src/main.js @@ -15,6 +15,7 @@ import { PlayerHistoryRepository } from "./infrastructure/database/repositories/ import { HistoryChecksRepository } from "./infrastructure/database/repositories/history.checks.repository.js"; import { config } from "./utils/config.loader.js"; import { Logger } from "./utils/logger.js"; +import { ValidDataSources } from "./models/valid.data.sources.js"; // our entry point = main async function main() { @@ -65,11 +66,15 @@ async function main() { const webServer = new WebServer(gameQueriesRouter, logger); await webServer.start(); + const steamWeb = ValidDataSources.validDataSources.steamWeb; + const steamcharts = ValidDataSources.validDataSources.steamcharts; + const runnables = [ { func: steamAppsAggregator.collectSteamApps }, - { func: gameIdentifier.tryViaSteamWeb }, - { func: gameIdentifier.tryViaSteamchartsWeb }, + { func: () => gameIdentifier.tryIfGameViaSource(steamWeb) }, + { func: () => gameIdentifier.tryIfGameViaSource(steamcharts) }, { func: gameIdentifier.updateGamesWithoutDetails }, + { func: gameIdentifier.updateGamesWithoutReleaseDates }, { func: playerHistoryAggregator.addPlayerHistoryFromSteamcharts }, { func: playerHistoryAggregator.addCurrentPlayers }, ]; diff --git a/backend/src/models/steam.app.js b/backend/src/models/steam.app.js index e5526cf1..c5dab314 100644 --- a/backend/src/models/steam.app.js +++ b/backend/src/models/steam.app.js @@ -1,5 +1,3 @@ -import { ValidDataSources } from "../models/valid.data.sources.js"; - export class SteamApp { appid; name; @@ -31,30 +29,6 @@ export class SteamApp { this.failedVia.push(source); } - triedViaSteamWeb() { - this.triedVia.push(ValidDataSources.validDataSources.steamWeb); - } - - triedViaSteamchartsWeb() { - this.triedVia.push(ValidDataSources.validDataSources.steamcharts); - } - - triedViaSteamDb() { - this.triedVia.push(ValidDataSources.validDataSources.steamDb); - } - - failedViaSteamWeb() { - this.failedVia.push(ValidDataSources.validDataSources.steamWeb); - } - - failedViaSteamchartsWeb() { - this.failedVia.push(ValidDataSources.validDataSources.steamcharts); - } - - failedViaSteamDb() { - this.failedVia.push(ValidDataSources.validDataSources.steamDb); - } - isGame() { return this.type === SteamApp.validTypes.game; } diff --git a/backend/src/models/steam.app.spec.js b/backend/src/models/steam.app.spec.js index 65ccf805..cea9c252 100644 --- a/backend/src/models/steam.app.spec.js +++ b/backend/src/models/steam.app.spec.js @@ -2,6 +2,7 @@ import { gamesMock } from "../../assets/small.data.set.js"; import { smallestGamesMock } from "../../assets/smallest.data.set.js"; import { ValidDataSources } from "../models/valid.data.sources.js"; import { SteamApp } from "./steam.app.js"; +import { getXSampleSteamApps } from "./steam.app.mocks.js"; describe("SteamApp", function () { describe(".copy", function () { @@ -35,6 +36,66 @@ describe("SteamApp", function () { }); }); + describe(".triedIfGameViaSource", function () { + describe("via steamWeb", function () { + beforeAll(function () { + this.source = ValidDataSources.validDataSources.steamWeb; + + this.steamApp = getXSampleSteamApps(1)[0]; + + this.steamApp.triedIfGameViaSource(this.source); + }); + + it("the steam app is tried via steam web", function () { + expect(this.steamApp.triedVia).toEqual([this.source]); + }); + }); + + describe("via steamcharts", function () { + beforeAll(function () { + this.source = ValidDataSources.validDataSources.steamcharts; + + this.steamApp = getXSampleSteamApps(1)[0]; + + this.steamApp.triedIfGameViaSource(this.source); + }); + + it("the steam app is tried via steam web", function () { + expect(this.steamApp.triedVia).toEqual([this.source]); + }); + }); + }); + + describe(".htmlPageFailedViaSource", function () { + describe("via steamWeb", function () { + beforeAll(function () { + this.source = ValidDataSources.validDataSources.steamWeb; + + this.steamApp = getXSampleSteamApps(1)[0]; + + this.steamApp.htmlPageFailedViaSource(this.source); + }); + + it("the steam app is tried via steam web", function () { + expect(this.steamApp.failedVia).toEqual([this.source]); + }); + }); + + describe("via steamcharts", function () { + beforeAll(function () { + this.source = ValidDataSources.validDataSources.steamcharts; + + this.steamApp = getXSampleSteamApps(1)[0]; + + this.steamApp.htmlPageFailedViaSource(this.source); + }); + + it("the steam app is tried via steam web", function () { + expect(this.steamApp.failedVia).toEqual([this.source]); + }); + }); + }); + describe(".isGame", function () { describe("checks if the type property of the class instance equals 'games'. So, ", function () { describe("if an app's type property equals 'game'", function () {