Skip to content

fanganga/CardTrackerWeb

Repository files navigation

CardTrackerWeb

A full-stack ASP.NET Core web application for managing and importing card game decks with a layered architecture, unit tests, and CI/CD pipeline. Created with the initial motivation of inspiring deck-building creativity by enabling me to see which cards I have yet to include in decks.

.NET Tests

Tech Stack

Layer Technology
Framework ASP.NET Core 8+ MVC
ORM Entity Framework Core
Database SQLite
Testing xUnit, Moq
Frontend Razor Views, HTML5, CSS3
CI/CD GitHub Actions

Project Architecture

CardTrackerWeb/
├── CardTrackerWebMainProj/
│   ├── Controllers/              # HTTP request handlers
│   ├── BLL/ (Business Logic Layer)
│   │   ├── Interfaces/
│   │   └── Services/
│   ├── DAL/ (Data Access Layer)
│   │   ├── Interfaces/
│   │   └── Repositories/
│   ├── Models/                   # Domain entities
│   ├── Data/                     # EF Core DbContext
│   ├── Views/                    # Razor templates
│   └── Program.cs                # DI configuration & app setup
│
└── CardTrackerWeb.Tests/         # Unit test project

Design Patterns & Principles

Layered Architecture

  • Presentation Layer: Controllers + Razor Views handle HTTP requests/responses
  • Business Logic Layer: Services encapsulate business rules and workflows
  • Data Access Layer: Repositories abstract database operations via EF Core

Dependency Injection

All services registered in Program.cs using ASP.NET Core's built-in DI container:

builder.Services.AddScoped<ICardService, CardService>();
builder.Services.AddScoped<IDeckService, DeckService>();
builder.Services.AddSingleton<ICardListParser, ThronesDbJsonCardListParser>();

Key Interfaces (Abstraction)

  • ICardListParser - Parses card data from external JSON sources
  • IDeckImporter - Imports deck lists from user-provided text format
  • ICardService / IDeckService - Business logic for cards and decks
  • ICardRepo / IDeckRepo - Database persistence abstraction

Features

Deck Management

  • ✅ Create, read, update, and delete decks
  • ✅ Full deck composition visibility with card details
  • ✅ Persistent storage with SQLite

Deck Import

  • ✅ Parse ThronesDB .txt deck format
  • ✅ Validate and normalize imported card data
  • ✅ Handle import errors with meaningful feedback

Card Database

  • ✅ Load card metadata from ThronesDB JSON API
  • ✅ Card search and filtering by faction

Getting Started

Prerequisites

  • .NET 8 SDK or later
  • SQLite

Installation

  1. Clone the repository

    git clone {this repository}
    cd CardTrackerWeb
  2. Restore dependencies

    dotnet restore
  3. Run the application

    cd CardTrackerWebMainProj
    dotnet run

    The app will automatically seed the database on first run.

  4. Open in browser

    https://localhost:5001
    

Running Tests

# Run all tests
dotnet test

# Run with verbose output
dotnet test --verbosity detailed

# Run specific test class
dotnet test --filter "ClassName=DeckServiceTests"

Usage Examples

Importing a Deck

  1. Navigate to DecksImport
  2. Paste a ThronesDB deck list (.txt format)
  3. Application validates format and imports cards
  4. View imported deck in Decks list with full composition

Managing Decks

  • View: Click a deck to see all cards, constraints, and metadata
  • Edit: Update deck name and description
  • Delete: Permanently remove a deck

Testing Strategy

Unit Tests (DeckServiceTests.cs)

  • Service isolation: Mocked repositories and dependencies using Moq
  • Happy path: Successful deck import with valid data
  • Error cases: Unknown faction, missing cards, validation failures
  • Verification: Assert that repositories receive correct data

Example:

[Test]
public async Task ImportDeck_WhenImporterParsesDeckString_ShouldReturnSuccessWithId()
{
    // Arrange
    var mockRepo = new Mock<IDeckRepo>();
    var deckService = new DeckService(mockRepo.Object, ...);

    // Act
    var result = await deckService.ImportDeckFromString("deck string", "owner", "name");

    // Assert
    Assert.That(result.Status, Is.EqualTo(DeckImportStatus.Success));
    mockRepo.Verify(r => r.InsertDeck(It.IsAny<Deck>()), Times.Once);
}

Parser Tests (ThronesdbJsonParserTest.cs)

  • Nullable field handling (cost, strength, etc.)
  • Complete card property coverage

Test Coverage

  • Service layer: Business logic and workflows
  • Parser layer: JSON deserialization and validation
  • Edge cases: Null values, invalid data, missing resources

Configuration

Update appsettings.json for database and API settings:

{
  "ConnectionStrings": {
    "LocalSQLiteCardTrackerDb": "Data Source=cardtracker.db"
  }
}

SQLite database file will be created automatically on first run.

CI/CD Pipeline

GitHub Actions automatically:

  • ✅ Builds the solution
  • ✅ Runs all unit tests
  • ✅ Reports test coverage
  • ✅ Validates code style

View workflow: .github/workflows/dotnet.yml

Development Notes

External Dependencies

  • ThronesDB API - Card data fetched on application startup (requires internet)
  • SQLite - Local database stored in project directory

Database

  • Schema created model-first by EF Core. Migrations can be found in CardTrackerWebMainProj/Migrations
  • Seeding happens during application initialization

About

ASP.NET web application built to identify underused cards in my Game of Thrones LCG collection

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages