From 9c4c19b5fb1870911e420f692644374ed1c6fe97 Mon Sep 17 00:00:00 2001 From: MokaStitcher <54149968+MokaStitcher@users.noreply.github.com> Date: Tue, 10 Sep 2024 16:12:17 +0200 Subject: [PATCH 1/7] [UI Bug] Fix HA icon not always showing in egg summary screen (#4150) --- src/ui/egg-summary-ui-handler.ts | 104 +++++++++++++++++-------------- src/ui/pokemon-info-container.ts | 2 +- 2 files changed, 57 insertions(+), 49 deletions(-) diff --git a/src/ui/egg-summary-ui-handler.ts b/src/ui/egg-summary-ui-handler.ts index af82ab33438..1d18e75f530 100644 --- a/src/ui/egg-summary-ui-handler.ts +++ b/src/ui/egg-summary-ui-handler.ts @@ -29,8 +29,10 @@ export default class EggSummaryUiHandler extends MessageUiHandler { private summaryContainer: Phaser.GameObjects.Container; /** container for the mini pokemon sprites */ private pokemonIconSpritesContainer: Phaser.GameObjects.Container; - /** container for the icons displayed alongside the mini icons (e.g. shiny, HA capsule) */ + /** container for the icons displayed on top of the mini pokemon sprites (e.g. shiny, HA capsule) */ private pokemonIconsContainer: Phaser.GameObjects.Container; + /** container for the elements displayed behind the mini pokemon sprites (e.g. egg rarity bg) */ + private pokemonBackgroundContainer: Phaser.GameObjects.Container; /** hatch info container that displays the current pokemon / hatch (main element on left hand side) */ private infoContainer: PokemonHatchInfoContainer; /** handles jumping animations for the pokemon sprite icons */ @@ -71,15 +73,17 @@ export default class EggSummaryUiHandler extends MessageUiHandler { this.eggHatchBg.setOrigin(0, 0); this.eggHatchContainer.add(this.eggHatchBg); - this.pokemonIconsContainer = this.scene.add.container(iconContainerX, iconContainerY); - this.pokemonIconSpritesContainer = this.scene.add.container(iconContainerX, iconContainerY); - this.summaryContainer.add(this.pokemonIconsContainer); - this.summaryContainer.add(this.pokemonIconSpritesContainer); - this.cursorObj = this.scene.add.image(0, 0, "select_cursor"); this.cursorObj.setOrigin(0, 0); this.summaryContainer.add(this.cursorObj); + this.pokemonIconSpritesContainer = this.scene.add.container(iconContainerX, iconContainerY); + this.pokemonIconsContainer = this.scene.add.container(iconContainerX, iconContainerY); + this.pokemonBackgroundContainer = this.scene.add.container(iconContainerX, iconContainerY); + this.summaryContainer.add(this.pokemonBackgroundContainer); + this.summaryContainer.add(this.pokemonIconSpritesContainer); + this.summaryContainer.add(this.pokemonIconsContainer); + this.infoContainer = new PokemonHatchInfoContainer(this.scene, this.summaryContainer); this.infoContainer.setup(); this.infoContainer.changeToEggSummaryLayout(); @@ -95,6 +99,7 @@ export default class EggSummaryUiHandler extends MessageUiHandler { this.summaryContainer.setVisible(false); this.pokemonIconSpritesContainer.removeAll(true); this.pokemonIconsContainer.removeAll(true); + this.pokemonBackgroundContainer.removeAll(true); this.eggHatchBg.setVisible(false); this.getUi().hideTooltip(); // Note: Questions on garbage collection go to @frutescens @@ -164,25 +169,25 @@ export default class EggSummaryUiHandler extends MessageUiHandler { const offset = 2; const rightSideX = 12; - const bg = this.scene.add.image(x+2, y+5, "passive_bg"); - bg.setOrigin(0, 0); - bg.setScale(0.75); - bg.setVisible(true); - this.pokemonIconsContainer.add(bg); + const rarityBg = this.scene.add.image(x + 2, y + 5, "passive_bg"); + rarityBg.setOrigin(0, 0); + rarityBg.setScale(0.75); + rarityBg.setVisible(true); + this.pokemonBackgroundContainer.add(rarityBg); // set tint for passive bg switch (getEggTierForSpecies(displayPokemon.species)) { case EggTier.COMMON: - bg.setVisible(false); + rarityBg.setVisible(false); break; case EggTier.GREAT: - bg.setTint(0xabafff); + rarityBg.setTint(0xabafff); break; case EggTier.ULTRA: - bg.setTint(0xffffaa); + rarityBg.setTint(0xffffaa); break; case EggTier.MASTER: - bg.setTint(0xdfffaf); + rarityBg.setTint(0xdfffaf); break; } const species = displayPokemon.species; @@ -192,35 +197,31 @@ export default class EggSummaryUiHandler extends MessageUiHandler { const isShiny = displayPokemon.shiny; // set pokemon icon (and replace with base sprite if there is a mismatch) - const icon = this.scene.add.sprite(x - offset, y + offset, species.getIconAtlasKey(formIndex, isShiny, variant)); - icon.setScale(0.5); - icon.setOrigin(0, 0); - icon.setFrame(species.getIconId(female, formIndex, isShiny, variant)); + const pokemonIcon = this.scene.add.sprite(x - offset, y + offset, species.getIconAtlasKey(formIndex, isShiny, variant)); + pokemonIcon.setScale(0.5); + pokemonIcon.setOrigin(0, 0); + pokemonIcon.setFrame(species.getIconId(female, formIndex, isShiny, variant)); - if (icon.frame.name !== species.getIconId(female, formIndex, isShiny, variant)) { + if (pokemonIcon.frame.name !== species.getIconId(female, formIndex, isShiny, variant)) { console.log(`${species.name}'s variant icon does not exist. Replacing with default.`); - icon.setTexture(species.getIconAtlasKey(formIndex, false, variant)); - icon.setFrame(species.getIconId(female, formIndex, false, variant)); + pokemonIcon.setTexture(species.getIconAtlasKey(formIndex, false, variant)); + pokemonIcon.setFrame(species.getIconId(female, formIndex, false, variant)); } - this.pokemonIconSpritesContainer.add(icon); - this.iconAnimHandler.addOrUpdate(icon, PokemonIconAnimMode.NONE); + this.pokemonIconSpritesContainer.add(pokemonIcon); - const shiny = this.scene.add.image(x + rightSideX, y + offset * 2, "shiny_star_small"); - shiny.setScale(0.5); - shiny.setVisible(displayPokemon.shiny); - shiny.setTint(getVariantTint(displayPokemon.variant)); - this.pokemonIconsContainer.add(shiny); + const shinyIcon = this.scene.add.image(x + rightSideX, y + offset, "shiny_star_small"); + shinyIcon.setOrigin(0, 0); + shinyIcon.setScale(0.5); + shinyIcon.setVisible(displayPokemon.shiny); + shinyIcon.setTint(getVariantTint(displayPokemon.variant)); + this.pokemonIconsContainer.add(shinyIcon); - const ha = this.scene.add.image(x + rightSideX, y + 7, "ha_capsule"); - ha.setScale(0.5); - ha.setVisible((displayPokemon.hasAbility(displayPokemon.species.abilityHidden))); - this.pokemonIconsContainer.add(ha); + const haIcon = this.scene.add.image(x + rightSideX, y + offset * 4, "ha_capsule"); + haIcon.setOrigin(0, 0); + haIcon.setScale(0.5); + haIcon.setVisible(displayPokemon.abilityIndex === 2); + this.pokemonIconsContainer.add(haIcon); - const pb = this.scene.add.image(x + rightSideX, y + offset * 7, "icon_owned"); - pb.setOrigin(0, 0); - pb.setScale(0.5); - - // add animation for new unlocks (new catch or new shiny or new form) const dexEntry = value.dexEntryBeforeUpdate; const caughtAttr = dexEntry.caughtAttr; const newShiny = BigInt(1 << (displayPokemon.shiny ? 1 : 0)); @@ -228,17 +229,24 @@ export default class EggSummaryUiHandler extends MessageUiHandler { const newShinyOrVariant = ((newShiny & caughtAttr) === BigInt(0)) || ((newVariant & caughtAttr) === BigInt(0)); const newForm = (BigInt(1 << displayPokemon.formIndex) * DexAttr.DEFAULT_FORM & caughtAttr) === BigInt(0); - pb.setVisible(!caughtAttr || newForm); - if (!caughtAttr || newShinyOrVariant || newForm) { - this.iconAnimHandler.addOrUpdate(icon, PokemonIconAnimMode.PASSIVE); - } - this.pokemonIconsContainer.add(pb); + const pokeballIcon = this.scene.add.image(x + rightSideX, y + offset * 7, "icon_owned"); + pokeballIcon.setOrigin(0, 0); + pokeballIcon.setScale(0.5); + pokeballIcon.setVisible(!caughtAttr || newForm); + this.pokemonIconsContainer.add(pokeballIcon); - const em = this.scene.add.image(x, y + offset, "icon_egg_move"); - em.setOrigin(0, 0); - em.setScale(0.5); - em.setVisible(value.eggMoveUnlocked); - this.pokemonIconsContainer.add(em); + const eggMoveIcon = this.scene.add.image(x, y + offset, "icon_egg_move"); + eggMoveIcon.setOrigin(0, 0); + eggMoveIcon.setScale(0.5); + eggMoveIcon.setVisible(value.eggMoveUnlocked); + this.pokemonIconsContainer.add(eggMoveIcon); + + // add animation to the Pokemon sprite for new unlocks (new catch, new shiny or new form) + if (!caughtAttr || newShinyOrVariant || newForm) { + this.iconAnimHandler.addOrUpdate(pokemonIcon, PokemonIconAnimMode.PASSIVE); + } else { + this.iconAnimHandler.addOrUpdate(pokemonIcon, PokemonIconAnimMode.NONE); + } }); this.setCursor(0); diff --git a/src/ui/pokemon-info-container.ts b/src/ui/pokemon-info-container.ts index 49bfd4d7293..3c54e529d43 100644 --- a/src/ui/pokemon-info-container.ts +++ b/src/ui/pokemon-info-container.ts @@ -262,7 +262,7 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container { this.pokemonFormText.disableInteractive(); } - const abilityTextStyle = pokemon.abilityIndex === (pokemon.species.ability2 ? 2 : 1) ? TextStyle.MONEY : TextStyle.WINDOW; + const abilityTextStyle = pokemon.abilityIndex === 2 ? TextStyle.MONEY : TextStyle.WINDOW; this.pokemonAbilityText.setText(pokemon.getAbility(true).name); this.pokemonAbilityText.setColor(getTextColor(abilityTextStyle, false, this.scene.uiTheme)); this.pokemonAbilityText.setShadowColor(getTextColor(abilityTextStyle, true, this.scene.uiTheme)); From 4b8083211ab114c94d7f194494a168bf353647b1 Mon Sep 17 00:00:00 2001 From: Madmadness65 <59298170+Madmadness65@users.noreply.github.com> Date: Tue, 10 Sep 2024 09:13:16 -0500 Subject: [PATCH 2/7] [P3 Bug] Fix Transform SFX not playing on quiet form changes (#4144) --- src/phases/quiet-form-change-phase.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/phases/quiet-form-change-phase.ts b/src/phases/quiet-form-change-phase.ts index 6a1d31d137d..dde500e156a 100644 --- a/src/phases/quiet-form-change-phase.ts +++ b/src/phases/quiet-form-change-phase.ts @@ -65,7 +65,7 @@ export class QuietFormChangePhase extends BattlePhase { pokemonFormTintSprite.setVisible(false); pokemonFormTintSprite.setTintFill(0xFFFFFF); - this.scene.playSound("PRSFX- Transform"); + this.scene.playSound("battle_anims/PRSFX- Transform"); this.scene.tweens.add({ targets: pokemonTintSprite, From 5bf21a4f7519d2a8850e6ea5b4c7e12b9d89909d Mon Sep 17 00:00:00 2001 From: PigeonBar <56974298+PigeonBar@users.noreply.github.com> Date: Tue, 10 Sep 2024 10:15:07 -0400 Subject: [PATCH 3/7] [Bug] Fix rare egg move and species rates for Manaphy eggs (#4125) --- src/data/egg.ts | 12 ++- src/test/eggs/manaphy-egg.test.ts | 118 ++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+), 3 deletions(-) create mode 100644 src/test/eggs/manaphy-egg.test.ts diff --git a/src/data/egg.ts b/src/data/egg.ts index ce27030ebef..1cd5c65fc18 100644 --- a/src/data/egg.ts +++ b/src/data/egg.ts @@ -222,7 +222,7 @@ export class Egg { let pokemonSpecies = getPokemonSpecies(this._species); // Special condition to have Phione eggs also have a chance of generating Manaphy - if (this._species === Species.PHIONE) { + if (this._species === Species.PHIONE && this._sourceType === EggSourceType.SAME_SPECIES_EGG) { pokemonSpecies = getPokemonSpecies(Utils.randSeedInt(MANAPHY_EGG_MANAPHY_RATE) ? Species.PHIONE : Species.MANAPHY); } @@ -326,7 +326,8 @@ export class Egg { break; } - return Utils.randSeedInt(baseChance * Math.pow(2, 3 - this.tier)) ? Utils.randSeedInt(3) : 3; + const tierMultiplier = this.isManaphyEgg() ? 2 : Math.pow(2, 3 - this.tier); + return Utils.randSeedInt(baseChance * tierMultiplier) ? Utils.randSeedInt(3) : 3; } private getEggTierDefaultHatchWaves(eggTier?: EggTier): number { @@ -361,7 +362,12 @@ export class Egg { * the species that was the legendary focus at the time */ if (this.isManaphyEgg()) { - const rand = Utils.randSeedInt(MANAPHY_EGG_MANAPHY_RATE); + /** + * Adding a technicality to make unit tests easier: By making this check pass + * when Utils.randSeedInt(8) = 1, and by making the generatePlayerPokemon() species + * check pass when Utils.randSeedInt(8) = 0, we can tell them apart during tests. + */ + const rand = (Utils.randSeedInt(MANAPHY_EGG_MANAPHY_RATE) !== 1); return rand ? Species.PHIONE : Species.MANAPHY; } else if (this.tier === EggTier.MASTER && this._sourceType === EggSourceType.GACHA_LEGENDARY) { diff --git a/src/test/eggs/manaphy-egg.test.ts b/src/test/eggs/manaphy-egg.test.ts new file mode 100644 index 00000000000..257bf330bb8 --- /dev/null +++ b/src/test/eggs/manaphy-egg.test.ts @@ -0,0 +1,118 @@ +import { Egg } from "#app/data/egg"; +import { EggSourceType } from "#app/enums/egg-source-types"; +import { EggTier } from "#app/enums/egg-type"; +import { Species } from "#enums/species"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; + +describe("Manaphy Eggs", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + const EGG_HATCH_COUNT: integer = 48; + let rngSweepProgress: number = 0; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + game = new GameManager(phaserGame); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + vi.restoreAllMocks(); + }); + + beforeEach(async () => { + await game.importData("src/test/utils/saves/everything.prsv"); + + /** + * In our tests, we will perform an "RNG sweep" by letting rngSweepProgress + * increase uniformly from 0 to 1 in order to get a uniform sample of the + * possible RNG outcomes. This will let us quickly and consistently find + * the probability of each RNG outcome. + */ + vi.spyOn(Phaser.Math.RND, "realInRange").mockImplementation((min: number, max: number) => { + return rngSweepProgress * (max - min) + min; + }); + }); + + it("should have correct Manaphy rates and Rare Egg Move rates, from the egg gacha", () => { + const scene = game.scene; + + let manaphyCount = 0; + let phioneCount = 0; + let rareEggMoveCount = 0; + for (let i = 0; i < EGG_HATCH_COUNT; i++) { + rngSweepProgress = (2 * i + 1) / (2 * EGG_HATCH_COUNT); + + const newEgg = new Egg({ scene, tier: EggTier.COMMON, sourceType: EggSourceType.GACHA_SHINY, id: 204 }); + const newHatch = newEgg.generatePlayerPokemon(scene); + if (newHatch.species.speciesId === Species.MANAPHY) { + manaphyCount++; + } else if (newHatch.species.speciesId === Species.PHIONE) { + phioneCount++; + } + if (newEgg.eggMoveIndex === 3) { + rareEggMoveCount++; + } + } + + expect(manaphyCount + phioneCount).toBe(EGG_HATCH_COUNT); + expect(manaphyCount).toBe(1/8 * EGG_HATCH_COUNT); + expect(rareEggMoveCount).toBe(1/12 * EGG_HATCH_COUNT); + }); + + it("should have correct Manaphy rates and Rare Egg Move rates, from Phione species eggs", () => { + const scene = game.scene; + + let manaphyCount = 0; + let phioneCount = 0; + let rareEggMoveCount = 0; + for (let i = 0; i < EGG_HATCH_COUNT; i++) { + rngSweepProgress = (2 * i + 1) / (2 * EGG_HATCH_COUNT); + + const newEgg = new Egg({ scene, species: Species.PHIONE, sourceType: EggSourceType.SAME_SPECIES_EGG }); + const newHatch = newEgg.generatePlayerPokemon(scene); + if (newHatch.species.speciesId === Species.MANAPHY) { + manaphyCount++; + } else if (newHatch.species.speciesId === Species.PHIONE) { + phioneCount++; + } + if (newEgg.eggMoveIndex === 3) { + rareEggMoveCount++; + } + } + + expect(manaphyCount + phioneCount).toBe(EGG_HATCH_COUNT); + expect(manaphyCount).toBe(1/8 * EGG_HATCH_COUNT); + expect(rareEggMoveCount).toBe(1/6 * EGG_HATCH_COUNT); + }); + + it("should have correct Manaphy rates and Rare Egg Move rates, from Manaphy species eggs", () => { + const scene = game.scene; + + let manaphyCount = 0; + let phioneCount = 0; + let rareEggMoveCount = 0; + for (let i = 0; i < EGG_HATCH_COUNT; i++) { + rngSweepProgress = (2 * i + 1) / (2 * EGG_HATCH_COUNT); + + const newEgg = new Egg({ scene, species: Species.MANAPHY, sourceType: EggSourceType.SAME_SPECIES_EGG }); + const newHatch = newEgg.generatePlayerPokemon(scene); + if (newHatch.species.speciesId === Species.MANAPHY) { + manaphyCount++; + } else if (newHatch.species.speciesId === Species.PHIONE) { + phioneCount++; + } + if (newEgg.eggMoveIndex === 3) { + rareEggMoveCount++; + } + } + + expect(phioneCount).toBe(0); + expect(manaphyCount).toBe(EGG_HATCH_COUNT); + expect(rareEggMoveCount).toBe(1/6 * EGG_HATCH_COUNT); + }); +}); From 150ab3d1b29a7191bfef6d2107e3ffe43a38aa54 Mon Sep 17 00:00:00 2001 From: AJ Fontaine <36677462+Fontbane@users.noreply.github.com> Date: Tue, 10 Sep 2024 11:54:23 -0400 Subject: [PATCH 4/7] [UI/UX] Make "CH-CHING!" sound when unlocking passive (#4151) * Make "CH-CHING!" sound when unlocking passive * Remove unused parameters in line above sound --- src/ui/starter-select-ui-handler.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index e1269499b10..89f1b87bcf4 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -1724,7 +1724,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } }); ui.setMode(Mode.STARTER_SELECT); - this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined, undefined); + this.setSpeciesDetails(this.lastSpecies); + this.scene.playSound("se/buy"); // if starterContainer exists, update the passive background if (starterContainer) { From d1b058fe3e4224343283a74e44d98589d6702a20 Mon Sep 17 00:00:00 2001 From: MokaStitcher <54149968+MokaStitcher@users.noreply.github.com> Date: Tue, 10 Sep 2024 20:00:50 +0200 Subject: [PATCH 5/7] [UI] fix candy upgrade icon not updating after purchasing eggs (#4153) --- src/ui/starter-select-ui-handler.ts | 53 +++++++++++++++++------------ 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index 89f1b87bcf4..0c3d8de61b0 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -1220,6 +1220,19 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } } + /** + * Update the display of candy upgrade icons or animations for the given StarterContainer + * @param starterContainer the container for the Pokemon to update + */ + updateCandyUpgradeDisplay(starterContainer: StarterContainer) { + if (this.isUpgradeIconEnabled() ) { + this.setUpgradeIcon(starterContainer); + } + if (this.isUpgradeAnimationEnabled()) { + this.setUpgradeAnimation(starterContainer.icon, this.lastSpecies, true); + } + } + /** * Processes an {@linkcode CandyUpgradeNotificationChangedEvent} sent when the corresponding setting changes * @param event {@linkcode Event} sent by the callback @@ -1624,7 +1637,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } }); } - const candyCount = starterData.candyCount; + const passiveAttr = starterData.passiveAttr; if (passiveAttr & PassiveAttr.UNLOCKED) { // this is for enabling and disabling the passive if (!(passiveAttr & PassiveAttr.ENABLED)) { @@ -1705,8 +1718,13 @@ export default class StarterSelectUiHandler extends MessageUiHandler { return true; } }); - const showUseCandies = () => { // this lets you use your candies + + // Purchases with Candy + const candyCount = starterData.candyCount; + const showUseCandies = () => { const options: any[] = []; // TODO: add proper type + + // Unlock passive option if (!(passiveAttr & PassiveAttr.UNLOCKED)) { const passiveCost = getPassiveCandyCount(speciesStarters[this.lastSpecies.speciesId]); options.push({ @@ -1727,16 +1745,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.setSpeciesDetails(this.lastSpecies); this.scene.playSound("se/buy"); - // if starterContainer exists, update the passive background + // update the passive background and icon/animation for available upgrade if (starterContainer) { - // Update the candy upgrade display - if (this.isUpgradeIconEnabled() ) { - this.setUpgradeIcon(starterContainer); - } - if (this.isUpgradeAnimationEnabled()) { - this.setUpgradeAnimation(starterContainer.icon, this.lastSpecies, true); - } - + this.updateCandyUpgradeDisplay(starterContainer); starterContainer.starterPassiveBgs.setVisible(!!this.scene.gameData.starterData[this.lastSpecies.speciesId].passiveAttr); } return true; @@ -1747,6 +1758,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler { itemArgs: starterColors[this.lastSpecies.speciesId] }); } + + // Reduce cost option const valueReduction = starterData.valueReduction; if (valueReduction < valueReductionMax) { const reductionCost = getValueReductionCandyCounts(speciesStarters[this.lastSpecies.speciesId])[valueReduction]; @@ -1768,19 +1781,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler { ui.setMode(Mode.STARTER_SELECT); this.scene.playSound("se/buy"); - // if starterContainer exists, update the value reduction background + // update the value label and icon/animation for available upgrade if (starterContainer) { this.updateStarterValueLabel(starterContainer); - - // If the notification setting is set to 'On', update the candy upgrade display - if (this.scene.candyUpgradeNotification === 2) { - if (this.isUpgradeIconEnabled() ) { - this.setUpgradeIcon(starterContainer); - } - if (this.isUpgradeAnimationEnabled()) { - this.setUpgradeAnimation(starterContainer.icon, this.lastSpecies, true); - } - } + this.updateCandyUpgradeDisplay(starterContainer); } return true; } @@ -1813,6 +1817,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler { ui.setMode(Mode.STARTER_SELECT); this.scene.playSound("se/buy"); + // update the icon/animation for available upgrade + if (starterContainer) { + this.updateCandyUpgradeDisplay(starterContainer); + } + return true; } return false; From 14ace406344b02151ad7e1bdedcc3c77a599d04d Mon Sep 17 00:00:00 2001 From: flx-sta <50131232+flx-sta@users.noreply.github.com> Date: Tue, 10 Sep 2024 13:34:50 -0700 Subject: [PATCH 6/7] [Misc] eslint rule to prevent `.js` imports (#4160) * add `eslint-plugin-import-x` module * add import eslint rules * remove .js extensions * rename account.spec to account.test * move fontFace.setup into `setupFiles` instead of importing it in `vitest.setup.ts` --- eslint.config.js | 7 +- package-lock.json | 200 ++++++++++++++++++ package.json | 1 + src/phases/weather-effect-phase.ts | 2 +- src/system/version-converter.ts | 2 +- src/test/{account.spec.ts => account.test.ts} | 0 .../double_battle_chance_booster.test.ts | 12 +- src/test/vitest.setup.ts | 1 - vitest.config.ts | 2 +- 9 files changed, 214 insertions(+), 13 deletions(-) rename src/test/{account.spec.ts => account.test.ts} (100%) diff --git a/eslint.config.js b/eslint.config.js index eeea38e3178..80e9e67b525 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,7 +1,7 @@ import tseslint from '@typescript-eslint/eslint-plugin'; import stylisticTs from '@stylistic/eslint-plugin-ts' import parser from '@typescript-eslint/parser'; -// import imports from 'eslint-plugin-import'; // Disabled due to not being compatible with eslint v9 +import importX from 'eslint-plugin-import-x'; export default [ { @@ -11,7 +11,7 @@ export default [ parser: parser }, plugins: { - // imports: imports.configs.recommended // Disabled due to not being compatible with eslint v9 + "import-x": importX, '@stylistic/ts': stylisticTs, '@typescript-eslint': tseslint }, @@ -39,7 +39,8 @@ export default [ }], "space-before-blocks": ["error", "always"], // Enforces a space before blocks "keyword-spacing": ["error", { "before": true, "after": true }], // Enforces spacing before and after keywords - "comma-spacing": ["error", { "before": false, "after": true }] // Enforces spacing after comma + "comma-spacing": ["error", { "before": false, "after": true }], // Enforces spacing after comma + "import-x/extensions": ["error", "never", { "json": "always" }], // Enforces no extension for imports unless json } } ] diff --git a/package-lock.json b/package-lock.json index 0605b299dab..4a447554819 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "@vitest/coverage-istanbul": "^2.0.4", "dependency-cruiser": "^16.3.10", "eslint": "^9.7.0", + "eslint-plugin-import-x": "^4.2.1", "jsdom": "^24.0.0", "lefthook": "^1.6.12", "phaser3spectorjs": "^0.0.8", @@ -2505,6 +2506,19 @@ "node": ">=8" } }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -2687,6 +2701,155 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import-x": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.2.1.tgz", + "integrity": "sha512-WWi2GedccIJa0zXxx3WDnTgouGQTtdYK1nhXMwywbqqAgB0Ov+p1pYBsWh3VaB0bvBOwLse6OfVII7jZD9xo5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.1.0", + "debug": "^4.3.4", + "doctrine": "^3.0.0", + "eslint-import-resolver-node": "^0.3.9", + "get-tsconfig": "^4.7.3", + "is-glob": "^4.0.3", + "minimatch": "^9.0.3", + "semver": "^7.6.3", + "stable-hash": "^0.0.4", + "tslib": "^2.6.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-import-x/node_modules/@typescript-eslint/scope-manager": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.5.0.tgz", + "integrity": "sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-import-x/node_modules/@typescript-eslint/types": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.5.0.tgz", + "integrity": "sha512-qjkormnQS5wF9pjSi6q60bKUHH44j2APxfh9TQRXK8wbYVeDYYdYJGIROL87LGZZ2gz3Rbmjc736qyL8deVtdw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-import-x/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.5.0.tgz", + "integrity": "sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-import-x/node_modules/@typescript-eslint/utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-6yyGYVL0e+VzGYp60wvkBHiqDWOpT63pdMV2CVG4LVDd5uR6q1qQN/7LafBZtAtNIn/mqXjsSeS5ggv/P0iECw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.5.0", + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/typescript-estree": "8.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-import-x/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.5.0.tgz", + "integrity": "sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.5.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/eslint-scope": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", @@ -3143,6 +3306,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-tsconfig": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.0.tgz", + "integrity": "sha512-Pgba6TExTZ0FJAn1qkJAjIeKoDJ3CsI2ChuLohJnZl/tTU8MVrq3b+2t5UOPfRa4RMsorClBjJALkJUMjG1PAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -4854,6 +5030,16 @@ "node": ">=4" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -5069,6 +5255,13 @@ "node": ">=0.10.0" } }, + "node_modules/stable-hash": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz", + "integrity": "sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==", + "dev": true, + "license": "MIT" + }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -5460,6 +5653,13 @@ "node": ">=6" } }, + "node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true, + "license": "0BSD" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index 83e82585d1e..dddf5aedebd 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@vitest/coverage-istanbul": "^2.0.4", "dependency-cruiser": "^16.3.10", "eslint": "^9.7.0", + "eslint-plugin-import-x": "^4.2.1", "jsdom": "^24.0.0", "lefthook": "^1.6.12", "phaser3spectorjs": "^0.0.8", diff --git a/src/phases/weather-effect-phase.ts b/src/phases/weather-effect-phase.ts index e85ef0326f6..73de44389d0 100644 --- a/src/phases/weather-effect-phase.ts +++ b/src/phases/weather-effect-phase.ts @@ -1,5 +1,5 @@ import BattleScene from "#app/battle-scene"; -import { applyPreWeatherEffectAbAttrs, SuppressWeatherEffectAbAttr, PreWeatherDamageAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPostWeatherLapseAbAttrs, PostWeatherLapseAbAttr } from "#app/data/ability.js"; +import { applyPreWeatherEffectAbAttrs, SuppressWeatherEffectAbAttr, PreWeatherDamageAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPostWeatherLapseAbAttrs, PostWeatherLapseAbAttr } from "#app/data/ability"; import { CommonAnim } from "#app/data/battle-anims"; import { Weather, getWeatherDamageMessage, getWeatherLapseMessage } from "#app/data/weather"; import { BattlerTagType } from "#app/enums/battler-tag-type"; diff --git a/src/system/version-converter.ts b/src/system/version-converter.ts index ed65fcd99b8..1a7c7b2026a 100644 --- a/src/system/version-converter.ts +++ b/src/system/version-converter.ts @@ -1,4 +1,4 @@ -import { allSpecies } from "#app/data/pokemon-species.js"; +import { allSpecies } from "#app/data/pokemon-species"; import { AbilityAttr, defaultStarterSpecies, DexAttr, SessionSaveData, SystemSaveData } from "./game-data"; import { SettingKeys } from "./settings/settings"; diff --git a/src/test/account.spec.ts b/src/test/account.test.ts similarity index 100% rename from src/test/account.spec.ts rename to src/test/account.test.ts diff --git a/src/test/items/double_battle_chance_booster.test.ts b/src/test/items/double_battle_chance_booster.test.ts index f581af7afc5..1d5051fa9e9 100644 --- a/src/test/items/double_battle_chance_booster.test.ts +++ b/src/test/items/double_battle_chance_booster.test.ts @@ -1,13 +1,13 @@ -import { Moves } from "#app/enums/moves.js"; -import { Species } from "#app/enums/species.js"; +import { Moves } from "#app/enums/moves"; +import { Species } from "#app/enums/species"; import { DoubleBattleChanceBoosterModifier } from "#app/modifier/modifier"; import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -import { ShopCursorTarget } from "#app/enums/shop-cursor-target.js"; -import { Mode } from "#app/ui/ui.js"; -import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler.js"; -import { Button } from "#app/enums/buttons.js"; +import { ShopCursorTarget } from "#app/enums/shop-cursor-target"; +import { Mode } from "#app/ui/ui"; +import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; +import { Button } from "#app/enums/buttons"; describe("Items - Double Battle Chance Boosters", () => { let phaserGame: Phaser.Game; diff --git a/src/test/vitest.setup.ts b/src/test/vitest.setup.ts index eaa987c1a66..bf806cd053a 100644 --- a/src/test/vitest.setup.ts +++ b/src/test/vitest.setup.ts @@ -1,4 +1,3 @@ -import "#test/fontFace.setup"; import "vitest-canvas-mock"; import { initLoggedInUser } from "#app/account"; diff --git a/vitest.config.ts b/vitest.config.ts index 9a765a89ae7..bfa380ec5fa 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -2,7 +2,7 @@ import { defineProject, UserWorkspaceConfig } from 'vitest/config'; import { defaultConfig } from './vite.config'; export const defaultProjectTestConfig: UserWorkspaceConfig["test"] = { - setupFiles: ['./src/test/vitest.setup.ts'], + setupFiles: ['./src/test/fontFace.setup.ts', './src/test/vitest.setup.ts'], server: { deps: { inline: ['vitest-canvas-mock'], From e17bf592c22a7e53d7a06e6e891d975dc0962ffe Mon Sep 17 00:00:00 2001 From: flx-sta <50131232+flx-sta@users.noreply.github.com> Date: Tue, 10 Sep 2024 14:13:42 -0700 Subject: [PATCH 7/7] [Bug] Use silent mode during tests (unless debugging!) + test workflow optimization (#4154) * add :silent to all tests but disable it if the runner is in debug mode! * fix: use `--silent` instead of `:silent` Cause the previous was npm scrpt specific (whops) * remove env and replace with logic in each call * reduce redundancy by checking out once * move pre-test into `needs` after `checkout` * use cache approach in pre-test * add node.js install step to `setup` job * WIP: setup -> pre-test -> all other tests with using cache * use matrix approach for tests * fix matrix approach for tests * fix wrong use of env var in `run-test-template.yml` * test: out-comment `run-tests` to see whats wrong * test: see if this works * let's try using matrix again... * make `node-version` input a string * remove `node-version` input for now * test: without a matrix fornow * change usage of reuseable workflow call * fix call of matrix.project * try using working-dir * try setup for pre-tests * remove `runs-on` from run-tests * fix some identations for run-tests * add pre-test as requirement for running tests * use `1` instead of `'1'` to check `runner.debug` * add `options` input. Possible fix for debug = not silent * try again... * not as an ENV but inside * move 2nd ${{ !runner.debug && '--silent' }} check into test-template * fix printing `false` instead of empty-string on runner-debug check * try a yml array approach * test running with file include path * make `project` always `main` for now * remove all extra vitest workspaces * adopt `shards` workflow in vitest * fix workflow reference in tests.yml * add missing `$` in test-shard-template.yml` * chore: fix vitest.config.ts after merge man.. cant trust these machines * make `project` a variable. try to use inputs on job names * adjust `test-shard-template` job name --- .github/workflows/test-shard-template.yml | 30 +++++++ .github/workflows/tests.yml | 98 +++++------------------ vitest.config.ts | 84 +++++++++---------- vitest.workspace.ts | 54 ------------- 4 files changed, 90 insertions(+), 176 deletions(-) create mode 100644 .github/workflows/test-shard-template.yml diff --git a/.github/workflows/test-shard-template.yml b/.github/workflows/test-shard-template.yml new file mode 100644 index 00000000000..ac89b503f0c --- /dev/null +++ b/.github/workflows/test-shard-template.yml @@ -0,0 +1,30 @@ +name: Test Template + +on: + workflow_call: + inputs: + project: + required: true + type: string + shard: + required: true + type: number + totalShards: + required: true + type: number + +jobs: + test: + name: Shard ${{ inputs.shard }} of ${{ inputs.totalShards }} + runs-on: ubuntu-latest + steps: + - name: Check out Git repository + uses: actions/checkout@v4 + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + - name: Install Node.js dependencies + run: npm ci + - name: Run tests + run: npx vitest --project ${{ inputs.project }} --shard=${{ inputs.shard }}/${{ inputs.totalShards }} ${{ !runner.debug && '--silent' || '' }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2a78ec252b8..66cc3ecc139 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -15,91 +15,33 @@ on: types: [checks_requested] jobs: - run-misc-tests: # Define a job named "run-tests" - name: Run misc tests # Human-readable name for the job - runs-on: ubuntu-latest # Specify the latest Ubuntu runner for the job - - steps: - - name: Check out Git repository # Step to check out the repository - uses: actions/checkout@v4 # Use the checkout action version 4 - - - name: Set up Node.js # Step to set up Node.js environment - uses: actions/setup-node@v4 # Use the setup-node action version 4 - with: - node-version: 20 # Specify Node.js version 20 - - - name: Install Node.js dependencies # Step to install Node.js dependencies - run: npm ci # Use 'npm ci' to install dependencies - - - name: pre-test # pre-test to check overrides - run: npx vitest run --project pre - - name: test misc - run: npx vitest --project misc - - run-abilities-tests: - name: Run abilities tests - runs-on: ubuntu-latest + pre-test: + name: Run Pre-test + runs-on: ubuntu-latest steps: - name: Check out Git repository uses: actions/checkout@v4 + with: + path: tests-action - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: 20 - name: Install Node.js dependencies + working-directory: tests-action run: npm ci - - name: pre-test - run: npx vitest run --project pre - - name: test abilities - run: npx vitest --project abilities + - name: Run Pre-test + working-directory: tests-action + run: npx vitest run --project pre ${{ !runner.debug && '--silent' || '' }} - run-items-tests: - name: Run items tests - runs-on: ubuntu-latest - steps: - - name: Check out Git repository - uses: actions/checkout@v4 - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 20 - - name: Install Node.js dependencies - run: npm ci - - name: pre-test - run: npx vitest run --project pre - - name: test items - run: npx vitest --project items - - run-moves-tests: - name: Run moves tests - runs-on: ubuntu-latest - steps: - - name: Check out Git repository - uses: actions/checkout@v4 - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 20 - - name: Install Node.js dependencies - run: npm ci - - name: pre-test - run: npx vitest run --project pre - - name: test moves - run: npx vitest --project moves - - run-battle-tests: - name: Run battle tests - runs-on: ubuntu-latest - steps: - - name: Check out Git repository - uses: actions/checkout@v4 - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 20 - - name: Install Node.js dependencies - run: npm ci - - name: pre-test - run: npx vitest run --project pre - - name: test battle - run: npx vitest --project battle \ No newline at end of file + run-tests: + name: Run Tests + needs: [pre-test] + strategy: + matrix: + shard: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + uses: ./.github/workflows/test-shard-template.yml + with: + project: main + shard: ${{ matrix.shard }} + totalShards: 10 \ No newline at end of file diff --git a/vitest.config.ts b/vitest.config.ts index bfa380ec5fa..54462675704 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -1,46 +1,42 @@ -import { defineProject, UserWorkspaceConfig } from 'vitest/config'; -import { defaultConfig } from './vite.config'; - -export const defaultProjectTestConfig: UserWorkspaceConfig["test"] = { - setupFiles: ['./src/test/fontFace.setup.ts', './src/test/vitest.setup.ts'], - server: { - deps: { - inline: ['vitest-canvas-mock'], - //@ts-ignore - optimizer: { - web: { - include: ['vitest-canvas-mock'], - } - } - } - }, - environment: 'jsdom' as const, - environmentOptions: { - jsdom: { - resources: 'usable', - }, - }, - threads: false, - trace: true, - restoreMocks: true, - watch: false, - coverage: { - provider: 'istanbul' as const, - reportsDirectory: 'coverage' as const, - reporters: ['text-summary', 'html'], - }, -} +import { defineProject } from "vitest/config"; +import { defaultConfig } from "./vite.config"; export default defineProject(({ mode }) => ({ - ...defaultConfig, - test: { - ...defaultProjectTestConfig, - name: "main", - include: ["./src/test/**/*.{test,spec}.ts"], - exclude: ["./src/test/pre.test.ts"], - }, - esbuild: { - pure: mode === 'production' ? [ 'console.log' ] : [], - keepNames: true, - }, -})) + ...defaultConfig, + test: { + setupFiles: ["./src/test/fontFace.setup.ts", "./src/test/vitest.setup.ts"], + server: { + deps: { + inline: ["vitest-canvas-mock"], + //@ts-ignore + optimizer: { + web: { + include: ["vitest-canvas-mock"], + }, + }, + }, + }, + environment: "jsdom" as const, + environmentOptions: { + jsdom: { + resources: "usable", + }, + }, + threads: false, + trace: true, + restoreMocks: true, + watch: false, + coverage: { + provider: "istanbul" as const, + reportsDirectory: "coverage" as const, + reporters: ["text-summary", "html"], + }, + name: "main", + include: ["./src/test/**/*.{test,spec}.ts"], + exclude: ["./src/test/pre.test.ts"], + }, + esbuild: { + pure: mode === "production" ? ["console.log"] : [], + keepNames: true, + }, +})); diff --git a/vitest.workspace.ts b/vitest.workspace.ts index a885b77dc9d..38121942004 100644 --- a/vitest.workspace.ts +++ b/vitest.workspace.ts @@ -1,6 +1,5 @@ import { defineWorkspace } from "vitest/config"; import { defaultConfig } from "./vite.config"; -import { defaultProjectTestConfig } from "./vitest.config"; export default defineWorkspace([ { @@ -11,58 +10,5 @@ export default defineWorkspace([ environment: "jsdom", }, }, - { - ...defaultConfig, - test: { - ...defaultProjectTestConfig, - name: "misc", - include: [ - "src/test/achievements/**/*.{test,spec}.ts", - "src/test/arena/**/*.{test,spec}.ts", - "src/test/battlerTags/**/*.{test,spec}.ts", - "src/test/eggs/**/*.{test,spec}.ts", - "src/test/field/**/*.{test,spec}.ts", - "src/test/inputs/**/*.{test,spec}.ts", - "src/test/localization/**/*.{test,spec}.ts", - "src/test/phases/**/*.{test,spec}.ts", - "src/test/settingMenu/**/*.{test,spec}.ts", - "src/test/sprites/**/*.{test,spec}.ts", - "src/test/ui/**/*.{test,spec}.ts", - "src/test/*.{test,spec}.ts", - ], - }, - }, - { - ...defaultConfig, - test: { - ...defaultProjectTestConfig, - name: "abilities", - include: ["src/test/abilities/**/*.{test,spec}.ts"], - }, - }, - { - ...defaultConfig, - test: { - ...defaultProjectTestConfig, - name: "battle", - include: ["src/test/battle/**/*.{test,spec}.ts"], - }, - }, - { - ...defaultConfig, - test: { - ...defaultProjectTestConfig, - name: "items", - include: ["src/test/items/**/*.{test,spec}.ts"], - }, - }, - { - ...defaultConfig, - test: { - ...defaultProjectTestConfig, - name: "moves", - include: ["src/test/moves/**/*.{test,spec}.ts"], - }, - }, "./vitest.config.ts", ]);