angular-switcher 0.1.0

Switch between Angular component files (.ts, .html, styles, .spec.ts) from the Zed editor with a customizable keybinding.
Documentation
use assert_cmd::Command;
use predicates::prelude::*;
use std::path::PathBuf;

fn fixtures() -> PathBuf {
    PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures")
}

fn cmd() -> Command {
    Command::cargo_bin("angular-switcher").unwrap()
}

#[test]
fn cycle_prints_html_sibling() {
    let ts = fixtures().join("standard/foo.component.ts");
    cmd()
        .args(["--cycle", "--print"])
        .arg(&ts)
        .assert()
        .success()
        .stdout(predicate::str::contains("foo.component.html"));
}

#[test]
fn direct_to_spec_prints_spec_path() {
    let html = fixtures().join("standard/foo.component.html");
    cmd()
        .args(["--to", "spec", "--print"])
        .arg(&html)
        .assert()
        .success()
        .stdout(predicate::str::contains("foo.component.spec.ts"));
}

#[test]
fn direct_to_style_prefers_scss_over_css_in_multi_style() {
    let ts = fixtures().join("multi-style/baz.component.ts");
    cmd()
        .args(["--to", "style", "--print"])
        .arg(&ts)
        .assert()
        .success()
        .stdout(predicate::str::contains("baz.component.scss"));
}

#[test]
fn css_only_fixture_resolves_style_to_css() {
    let ts = fixtures().join("css-only/bar.component.ts");
    cmd()
        .args(["--to", "style", "--print"])
        .arg(&ts)
        .assert()
        .success()
        .stdout(predicate::str::contains("bar.component.css"));
}

#[test]
fn no_sibling_exits_with_code_two() {
    let lonely = fixtures().join("non-angular/util.ts");
    cmd()
        .args(["--cycle", "--print"])
        .arg(&lonely)
        .assert()
        .failure()
        .code(2)
        .stderr(predicate::str::contains("no sibling"));
}

#[test]
fn unknown_target_exits_with_code_one() {
    let ts = fixtures().join("standard/foo.component.ts");
    cmd()
        .args(["--to", "bogus", "--print"])
        .arg(&ts)
        .assert()
        .failure()
        .code(1)
        .stderr(predicate::str::contains("unknown target"));
}

#[test]
fn picks_up_zed_file_env_var() {
    let ts = fixtures().join("standard/foo.component.ts");
    cmd()
        .env("ZED_FILE", &ts)
        .args(["--cycle", "--print"])
        .assert()
        .success()
        .stdout(predicate::str::contains("foo.component.html"));
}

#[test]
fn missing_input_emits_input_error() {
    cmd()
        .env_remove("ZED_FILE")
        .args(["--cycle", "--print"])
        .assert()
        .failure()
        .code(1)
        .stderr(predicate::str::contains("missing input file"));
}

#[test]
fn cycle_from_spec_wraps_back_to_ts() {
    let spec = fixtures().join("standard/foo.component.spec.ts");
    cmd()
        .args(["--cycle", "--print"])
        .arg(&spec)
        .assert()
        .success()
        .stdout(predicate::str::contains("foo.component.ts"))
        // make sure we got the TS file, not the SPEC file
        .stdout(predicate::str::contains(".spec.ts").not());
}

#[test]
fn reverse_cycle_from_ts_goes_to_spec() {
    let ts = fixtures().join("standard/foo.component.ts");
    cmd()
        .args(["--cycle", "--reverse", "--print"])
        .arg(&ts)
        .assert()
        .success()
        .stdout(predicate::str::contains("foo.component.spec.ts"));
}