chore: add test runner to pre-commit hook with failure-only output
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 1m58s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 1m58s
This commit is contained in:
@@ -13,6 +13,13 @@ if [ -n "$STAGED_FILES" ]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Run tests — only failing tests are printed to keep output focused
|
||||||
|
echo "🧪 Running tests..."
|
||||||
|
bash .husky/scripts/run-tests.sh
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Generate project structure
|
# Generate project structure
|
||||||
echo "🗺️ Updating project structure..."
|
echo "🗺️ Updating project structure..."
|
||||||
node .husky/scripts/generate-project-tree.js
|
node .husky/scripts/generate-project-tree.js
|
||||||
|
|||||||
Executable
+24
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Run all tests and display only failing tests (plus a summary).
|
||||||
|
# Keeps output focused so commit context isn't bloated.
|
||||||
|
#
|
||||||
|
# NOTE: It doesn't matter if you didn't introduce the failing tests —
|
||||||
|
# they should be handled before committing. A red main branch helps no one.
|
||||||
|
|
||||||
|
cd "$(dirname "$0")/../.."
|
||||||
|
|
||||||
|
echo "🧪 Running tests (only failures will be shown)..."
|
||||||
|
|
||||||
|
# Disable TTY progress bars for clean pre-commit output.
|
||||||
|
# Use `--reporter=default` which prints only failures + the final summary.
|
||||||
|
CI=true npx vitest run --reporter=default 2>&1
|
||||||
|
EXIT_CODE=$?
|
||||||
|
|
||||||
|
if [ $EXIT_CODE -ne 0 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "⛔ Commit blocked: failing tests found."
|
||||||
|
echo " It doesn't matter if you didn't introduce the failing tests —"
|
||||||
|
echo " they should be handled before committing."
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit $EXIT_CODE
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Circular Dependencies
|
# Circular Dependencies
|
||||||
Generated: 2026-05-30T20:28:51.293Z
|
Generated: 2026-05-30T23:18:13.094Z
|
||||||
|
|
||||||
No circular dependencies found. ✅
|
No circular dependencies found. ✅
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"generated": "2026-05-30T20:28:49.474Z",
|
"generated": "2026-05-30T23:18:08.992Z",
|
||||||
"description": "Import dependency graph for src/lib/game. Keys are files, values are arrays of files they import.",
|
"description": "Import dependency graph for src/lib/game. Keys are files, values are arrays of files they import.",
|
||||||
"usage": "To find what a file affects, search for its path in the VALUES. To find what a file depends on, look at its KEY entry."
|
"usage": "To find what a file affects, search for its path in the VALUES. To find what a file depends on, look at its KEY entry."
|
||||||
},
|
},
|
||||||
@@ -122,6 +122,8 @@
|
|||||||
"crafting-actions/application-actions.ts": [
|
"crafting-actions/application-actions.ts": [
|
||||||
"crafting-apply.ts",
|
"crafting-apply.ts",
|
||||||
"stores/craftingStore.types.ts",
|
"stores/craftingStore.types.ts",
|
||||||
|
"stores/manaStore.ts",
|
||||||
|
"stores/uiStore.ts",
|
||||||
"types.ts"
|
"types.ts"
|
||||||
],
|
],
|
||||||
"crafting-actions/computed-getters.ts": [
|
"crafting-actions/computed-getters.ts": [
|
||||||
@@ -165,7 +167,9 @@
|
|||||||
],
|
],
|
||||||
"crafting-actions/preparation-actions.ts": [
|
"crafting-actions/preparation-actions.ts": [
|
||||||
"crafting-prep.ts",
|
"crafting-prep.ts",
|
||||||
"stores/craftingStore.types.ts"
|
"stores/craftingStore.types.ts",
|
||||||
|
"stores/manaStore.ts",
|
||||||
|
"stores/uiStore.ts"
|
||||||
],
|
],
|
||||||
"crafting-apply.ts": [
|
"crafting-apply.ts": [
|
||||||
"constants.ts",
|
"constants.ts",
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ Mana-Loop/
|
|||||||
│ ├── scripts/
|
│ ├── scripts/
|
||||||
│ │ ├── check-file-size.js
|
│ │ ├── check-file-size.js
|
||||||
│ │ ├── generate-dependency-graph.js
|
│ │ ├── generate-dependency-graph.js
|
||||||
│ │ └── generate-project-tree.js
|
│ │ ├── generate-project-tree.js
|
||||||
|
│ │ └── run-tests.sh
|
||||||
│ ├── post-merge
|
│ ├── post-merge
|
||||||
│ └── pre-commit
|
│ └── pre-commit
|
||||||
├── docs/
|
├── docs/
|
||||||
|
|||||||
@@ -4,10 +4,11 @@ import { describe, it, expect } from 'vitest';
|
|||||||
|
|
||||||
describe('CraftingTab module structure', () => {
|
describe('CraftingTab module structure', () => {
|
||||||
it('exports CraftingTab from its module', async () => {
|
it('exports CraftingTab from its module', async () => {
|
||||||
|
// Allow extra time for the heavy component import (FabricatorSubTab/EnchanterSubTab)
|
||||||
const mod = await import('./CraftingTab');
|
const mod = await import('./CraftingTab');
|
||||||
expect(mod.CraftingTab).toBeDefined();
|
expect(mod.CraftingTab).toBeDefined();
|
||||||
expect(typeof mod.CraftingTab).toBe('function');
|
expect(typeof mod.CraftingTab).toBe('function');
|
||||||
});
|
}, 30000);
|
||||||
|
|
||||||
it('CraftingTab has correct displayName', async () => {
|
it('CraftingTab has correct displayName', async () => {
|
||||||
const { CraftingTab } = await import('./CraftingTab');
|
const { CraftingTab } = await import('./CraftingTab');
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ describe('EquipmentTab module structure', () => {
|
|||||||
const mod = await import('./EquipmentTab');
|
const mod = await import('./EquipmentTab');
|
||||||
expect(mod.EquipmentTab).toBeDefined();
|
expect(mod.EquipmentTab).toBeDefined();
|
||||||
expect(typeof mod.EquipmentTab).toBe('function');
|
expect(typeof mod.EquipmentTab).toBe('function');
|
||||||
});
|
}, 30000);
|
||||||
|
|
||||||
it('EquipmentTab has correct displayName', async () => {
|
it('EquipmentTab has correct displayName', async () => {
|
||||||
const { EquipmentTab } = await import('./EquipmentTab');
|
const { EquipmentTab } = await import('./EquipmentTab');
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ export const WIZARD_BRANCH_RECIPES: FabricatorRecipe[] = [
|
|||||||
id: 'aetherRobe',
|
id: 'aetherRobe',
|
||||||
name: 'Aetherweave Robe',
|
name: 'Aetherweave Robe',
|
||||||
description: 'A robe woven from Aether Weave. Shimmers with latent air and light mana. Exceptional enchanting potential.',
|
description: 'A robe woven from Aether Weave. Shimmers with latent air and light mana. Exceptional enchanting potential.',
|
||||||
manaType: 'air',
|
manaType: 'crystal',
|
||||||
equipmentTypeId: 'arcanistRobe',
|
equipmentTypeId: 'arcanistRobe',
|
||||||
slot: 'body',
|
slot: 'body',
|
||||||
materials: { aetherWeave: 3, manaCrystalDust: 15, crystalShard: 8, elementalCore: 4 },
|
materials: { aetherWeave: 3, manaCrystalDust: 15, crystalShard: 8, elementalCore: 4 },
|
||||||
@@ -143,25 +143,25 @@ export const WIZARD_BRANCH_RECIPES: FabricatorRecipe[] = [
|
|||||||
bonusEnchantments: [
|
bonusEnchantments: [
|
||||||
{ effectId: 'mana_cap_100', stacks: 1, actualCost: 35 },
|
{ effectId: 'mana_cap_100', stacks: 1, actualCost: 35 },
|
||||||
{ effectId: 'mana_regen_5', stacks: 1, actualCost: 50 },
|
{ effectId: 'mana_regen_5', stacks: 1, actualCost: 50 },
|
||||||
{ effectId: 'air_cap_10', stacks: 1, actualCost: 30 },
|
{ effectId: 'crystal_cap_10', stacks: 1, actualCost: 30 },
|
||||||
{ effectId: 'light_cap_10', stacks: 1, actualCost: 30 },
|
{ effectId: 'crystal_cap_10', stacks: 1, actualCost: 30 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'aetherCirclet',
|
id: 'aetherCirclet',
|
||||||
name: 'Aetherweave Circlet',
|
name: 'Aetherweave Circlet',
|
||||||
description: 'A circlet infused with Aether Weave. Sharpens focus and amplifies arcane power.',
|
description: 'A circlet infused with Aether Weave. Sharpens focus and amplifies arcane power.',
|
||||||
manaType: 'light',
|
manaType: 'crystal',
|
||||||
equipmentTypeId: 'arcanistCirclet',
|
equipmentTypeId: 'arcanistCirclet',
|
||||||
slot: 'head',
|
slot: 'head',
|
||||||
materials: { aetherWeave: 2, manaCrystalDust: 10, lightCrystal: 3, elementalCore: 3 },
|
materials: { aetherWeave: 2, manaCrystalDust: 10, lightCrystal: 3, elementalCore: 3 },
|
||||||
manaCost: 900,
|
manaCost: 900,
|
||||||
craftTime: 10,
|
craftTime: 10,
|
||||||
rarity: 'epic',
|
rarity: 'epic',
|
||||||
gearTrait: '+30% Enchantment Power, +25 Light Mana Capacity',
|
gearTrait: '+30% Enchantment Power, +25 Crystal Mana Capacity',
|
||||||
bonusEnchantments: [
|
bonusEnchantments: [
|
||||||
{ effectId: 'mana_cap_100', stacks: 1, actualCost: 35 },
|
{ effectId: 'mana_cap_100', stacks: 1, actualCost: 35 },
|
||||||
{ effectId: 'light_cap_10', stacks: 1, actualCost: 30 },
|
{ effectId: 'crystal_cap_10', stacks: 1, actualCost: 30 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@ export const WIZARD_BRANCH_RECIPES: FabricatorRecipe[] = [
|
|||||||
id: 'voidRobe',
|
id: 'voidRobe',
|
||||||
name: 'Voidweave Robe',
|
name: 'Voidweave Robe',
|
||||||
description: 'A robe stitched from Void Cloth. Seems to absorb light and sound. Perfect for dark arcana.',
|
description: 'A robe stitched from Void Cloth. Seems to absorb light and sound. Perfect for dark arcana.',
|
||||||
manaType: 'dark',
|
manaType: 'sand',
|
||||||
equipmentTypeId: 'arcanistRobe',
|
equipmentTypeId: 'arcanistRobe',
|
||||||
slot: 'body',
|
slot: 'body',
|
||||||
materials: { voidCloth: 3, manaCrystalDust: 15, crystalShard: 8, voidEssence: 3 },
|
materials: { voidCloth: 3, manaCrystalDust: 15, crystalShard: 8, voidEssence: 3 },
|
||||||
@@ -181,14 +181,14 @@ export const WIZARD_BRANCH_RECIPES: FabricatorRecipe[] = [
|
|||||||
bonusEnchantments: [
|
bonusEnchantments: [
|
||||||
{ effectId: 'mana_cap_100', stacks: 1, actualCost: 35 },
|
{ effectId: 'mana_cap_100', stacks: 1, actualCost: 35 },
|
||||||
{ effectId: 'damage_10', stacks: 1, actualCost: 28 },
|
{ effectId: 'damage_10', stacks: 1, actualCost: 28 },
|
||||||
{ effectId: 'dark_cap_10', stacks: 1, actualCost: 30 },
|
{ effectId: 'sand_cap_10', stacks: 1, actualCost: 30 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'voidCowl',
|
id: 'voidCowl',
|
||||||
name: 'Voidweave Cowl',
|
name: 'Voidweave Cowl',
|
||||||
description: 'A deep cowl made from Void Cloth. Shields the wearer from detection.',
|
description: 'A deep cowl made from Void Cloth. Shields the wearer from detection.',
|
||||||
manaType: 'dark',
|
manaType: 'sand',
|
||||||
equipmentTypeId: 'arcanistCirclet',
|
equipmentTypeId: 'arcanistCirclet',
|
||||||
slot: 'head',
|
slot: 'head',
|
||||||
materials: { voidCloth: 2, manaCrystalDust: 10, darkCrystal: 3, voidEssence: 2 },
|
materials: { voidCloth: 2, manaCrystalDust: 10, darkCrystal: 3, voidEssence: 2 },
|
||||||
@@ -197,7 +197,7 @@ export const WIZARD_BRANCH_RECIPES: FabricatorRecipe[] = [
|
|||||||
rarity: 'epic',
|
rarity: 'epic',
|
||||||
gearTrait: '+25% Dark Enchantment Power, +15% Evasion',
|
gearTrait: '+25% Dark Enchantment Power, +15% Evasion',
|
||||||
bonusEnchantments: [
|
bonusEnchantments: [
|
||||||
{ effectId: 'dark_cap_10', stacks: 1, actualCost: 30 },
|
{ effectId: 'sand_cap_10', stacks: 1, actualCost: 30 },
|
||||||
{ effectId: 'mana_cap_50', stacks: 1, actualCost: 20 },
|
{ effectId: 'mana_cap_50', stacks: 1, actualCost: 20 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user