tui-piechart 0.3.3

A customizable pie chart widget for Ratatui TUI applications
Documentation
#!/usr/bin/env nu
# Tests for scripts/bump_version.nu
#
# Run with: nu scripts/tests/test_bump_version.nu

use std/assert
use runner.nu *

# ── Helpers ───────────────────────────────────────────────────────────────────

# Write a minimal single-crate Cargo.toml at the given version into a temp dir.
# Returns the dir path.
def make_package_cargo [version: string] {
    let tmp = (mktemp -d)
    let content = $'[package]
name = "tui-piechart"
version = "($version)"
authors = ["Test Author <test@example.com>"]
edition = "2021"
license = "MIT"
description = "A customizable pie chart widget for Ratatui"

[dependencies]
ratatui = { version = "0.30", default-features = false }

[dev-dependencies]
color-eyre = "0.6"
'
    $content | save --force ($tmp | path join "Cargo.toml")
    $tmp
}

# Read back the [package] version from a Cargo.toml string.
def read_package_version [content: string] {
    $content
    | lines
    | reduce --fold { in_pkg: false, version: "" } { |line, acc|
        let new_in_pkg = if ($line =~ '^\[package\]') {
            true
        } else if ($acc.in_pkg and ($line =~ '^\[')) {
            false
        } else {
            $acc.in_pkg
        }

        let new_version = if ($acc.in_pkg and ($line =~ '^version\s*=\s*"[^"]*"')) {
            $line
            | parse --regex 'version\s*=\s*"(?P<v>[^"]+)"'
            | get v
            | first
        } else {
            $acc.version
        }

        { in_pkg: $new_in_pkg, version: $new_version }
    }
    | get version
}

# Apply the same [package] version update logic that bump_version.nu uses.
def apply_package_version_update [dir: string, new_version: string] {
    let cargo_path = ($dir | path join "Cargo.toml")
    let lines = open --raw $cargo_path | lines

    let result = $lines | reduce --fold { in_pkg: false, lines: [] } { |line, acc|
        let new_in_pkg = if ($line =~ '^\[package\]') {
            true
        } else if ($acc.in_pkg and ($line =~ '^\[')) {
            false
        } else {
            $acc.in_pkg
        }
        let new_line = if ($acc.in_pkg and ($line =~ '^version\s*=\s*"[^"]*"')) {
            $'version = "($new_version)"'
        } else {
            $line
        }
        { in_pkg: $new_in_pkg, lines: ($acc.lines | append $new_line) }
    }
    $result.lines | str join "\n" | save --force $cargo_path
}

# ── Version format validation tests ───────────────────────────────────────────

def "test valid version x.y.z is accepted" [] {
    assert ("1.2.3" =~ '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$')
}

def "test valid version 0.0.0 is accepted" [] {
    assert ("0.0.0" =~ '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$')
}

def "test valid version with pre-release suffix is accepted" [] {
    assert ("1.0.0-beta.1" =~ '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$')
}

def "test valid version with alpha suffix is accepted" [] {
    assert ("2.3.4-alpha" =~ '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$')
}

def "test invalid version missing patch is rejected" [] {
    assert not ("1.2" =~ '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$')
}

def "test invalid version with v prefix is rejected" [] {
    assert not ("v1.2.3" =~ '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$')
}

def "test invalid version empty string is rejected" [] {
    assert not ("" =~ '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$')
}

def "test invalid version with spaces is rejected" [] {
    assert not ("1.2.3 " =~ '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$')
}

def "test invalid version with only two parts is rejected" [] {
    assert not ("0.8" =~ '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$')
}

# ── [package] version reading tests ───────────────────────────────────────────

def "test read package version from simple cargo toml" [] {
    let tmp = make_package_cargo "0.3.1"
    let content = open --raw ($tmp | path join "Cargo.toml")
    let got = read_package_version $content
    rm -rf $tmp
    assert equal $got "0.3.1"
}

def "test read package version with padded assignment" [] {
    let tmp = (mktemp -d)
    let content = '[package]
name = "tui-piechart"
version      = "1.2.3"
edition      = "2021"
'
    $content | save --force ($tmp | path join "Cargo.toml")
    let got = read_package_version (open --raw ($tmp | path join "Cargo.toml"))
    rm -rf $tmp
    assert equal $got "1.2.3"
}

def "test read package version ignores dependency version lines" [] {
    let tmp = make_package_cargo "2.0.0"
    let content = open --raw ($tmp | path join "Cargo.toml")
    let got = read_package_version $content
    rm -rf $tmp
    assert equal $got "2.0.0"
}

def "test read package version ignores dep inline version" [] {
    let tmp = (mktemp -d)
    let content = '[package]
name = "tui-piechart"
version = "3.1.4"
edition = "2021"

[dependencies]
ratatui = { version = "0.30", default-features = false }
'
    $content | save --force ($tmp | path join "Cargo.toml")
    let got = read_package_version (open --raw ($tmp | path join "Cargo.toml"))
    rm -rf $tmp
    assert equal $got "3.1.4"
}

# ── [package] version update tests ────────────────────────────────────────────

def "test package version is updated" [] {
    let tmp = make_package_cargo "0.3.1"
    apply_package_version_update $tmp "0.4.0"
    let content = open --raw ($tmp | path join "Cargo.toml")
    let got = read_package_version $content
    rm -rf $tmp
    assert equal $got "0.4.0"
}

def "test package version patch bump is correct" [] {
    let tmp = make_package_cargo "0.3.1"
    apply_package_version_update $tmp "0.3.2"
    let content = open --raw ($tmp | path join "Cargo.toml")
    let got = read_package_version $content
    rm -rf $tmp
    assert equal $got "0.3.2"
}

def "test package version minor bump is correct" [] {
    let tmp = make_package_cargo "0.3.1"
    apply_package_version_update $tmp "0.4.0"
    let content = open --raw ($tmp | path join "Cargo.toml")
    let got = read_package_version $content
    rm -rf $tmp
    assert equal $got "0.4.0"
}

def "test package version major bump is correct" [] {
    let tmp = make_package_cargo "0.9.9"
    apply_package_version_update $tmp "1.0.0"
    let content = open --raw ($tmp | path join "Cargo.toml")
    let got = read_package_version $content
    rm -rf $tmp
    assert equal $got "1.0.0"
}

def "test package version update leaves other lines intact" [] {
    let tmp = make_package_cargo "0.3.1"
    apply_package_version_update $tmp "0.4.0"
    let content = open --raw ($tmp | path join "Cargo.toml")
    rm -rf $tmp
    assert str contains $content "[package]"
    assert str contains $content "edition"
    assert str contains $content "ratatui"
}

def "test package version update does not change dep versions" [] {
    let tmp = make_package_cargo "1.0.0"
    apply_package_version_update $tmp "1.1.0"
    let content = open --raw ($tmp | path join "Cargo.toml")
    rm -rf $tmp
    # ratatui dep must remain at 0.30
    assert str contains $content 'version = "0.30"'
}

def "test package version update is idempotent" [] {
    let tmp = make_package_cargo "1.0.0"
    apply_package_version_update $tmp "1.0.0"
    let content = open --raw ($tmp | path join "Cargo.toml")
    let got = read_package_version $content
    rm -rf $tmp
    assert equal $got "1.0.0"
}

# ── Same-version guard tests ──────────────────────────────────────────────────

def "test same version is detected" [] {
    let current = "0.3.1"
    let new     = "0.3.1"
    assert equal $current $new "same version guard should trigger"
}

def "test different version is not blocked" [] {
    let current = "0.3.1"
    let new     = "0.4.0"
    assert not equal $current $new
}

# ── Tag existence guard tests ─────────────────────────────────────────────────

def "test tag check detects existing tag" [] {
    let existing  = ["v0.3.0" "v0.3.1"]
    let candidate = "v0.3.1"
    assert ($existing | any { |t| $t == $candidate }) "existing tag should be detected"
}

def "test tag check allows new tag" [] {
    let existing  = ["v0.3.0" "v0.3.1"]
    let candidate = "v0.4.0"
    assert not ($existing | any { |t| $t == $candidate }) "new tag should not be blocked"
}

def "test tag name is prefixed with v" [] {
    let version = "0.4.0"
    let tag = $"v($version)"
    assert str contains $tag "v"
    assert equal $tag "v0.4.0"
}

# ── Version via native TOML read ──────────────────────────────────────────────

def "test native toml read matches text parse" [] {
    let tmp = make_package_cargo "1.7.3"
    let path = ($tmp | path join "Cargo.toml")
    let via_toml = (open $path | get package.version)
    let via_text = (read_package_version (open --raw $path))
    rm -rf $tmp
    assert equal $via_toml $via_text
}

# ── Runner ────────────────────────────────────────────────────────────────────

def main [] {
    print $"(ansi cyan)═══ test_bump_version.nu ═══(ansi reset)"
    run-tests
}