twoken 0.4.0

Generate One-Time Passwords from stored token secrets.
Documentation
use std::fs;

use assert_cmd::Command;
use tempfile::NamedTempFile;
use twoken::{otp::TOTP, store::Store, yubikey::Yubikey};

#[derive(Debug)]
struct TestContext {
    file: NamedTempFile,
}

impl Drop for TestContext {
    fn drop(&mut self) {
        println!("teardown");
        //fs::remove_file("testtoken");
    }
}

fn setup(token_type: &str) -> TestContext {
    let file = NamedTempFile::new().unwrap();
    let mut cmd = Command::cargo_bin("twoken").unwrap();
    cmd.arg("--new")
        .arg("--token")
        .arg(token_type)
        .arg("--store")
        .arg("file")
        .arg(file.path());
    cmd.assert().success();
    TestContext { file }
}

#[test]
fn create_token() {
    let context = setup("yubikey");
    let store = twoken::store::GenericStore::File;
    assert!(store
        .get::<Yubikey>(context.file.path().to_str().unwrap())
        .is_ok());
    println!("{:?}", context);
}

#[test]
fn use_token() {
    let context = setup("yubikey");
    let mut cmd = Command::cargo_bin("twoken").unwrap();
    cmd.arg("--print")
        .arg("--store")
        .arg("file")
        .arg(context.file.path());
    cmd.assert()
        .success()
        .stdout(predicates::str::is_match(r"[b-v]{42}.").unwrap());
    println!("{:?}", context);
}

#[test]
fn create_totp_token() {
    let context = setup("totp");
    let store = twoken::store::GenericStore::File;
    assert!(store
        .get::<TOTP>(context.file.path().to_str().unwrap())
        .is_ok());
    println!("{:?}", context);
}

#[test]
fn use_totp_token() {
    let context = setup("totp");
    let mut cmd = Command::cargo_bin("twoken").unwrap();
    cmd.arg("--print")
        .arg("--token")
        .arg("totp")
        .arg("--store")
        .arg("file")
        .arg(context.file.path());
    cmd.assert()
        .success()
        .stdout(predicates::str::is_match(r"[0-9]{6}").unwrap());
    println!("{:?}", context);
}