use std::path::PathBuf;
use wolfxl_core::{infer_sheet_schema, CellValue, InferredType, SourceFormat, Workbook};
fn fixture(name: &str) -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("tests")
.join("fixtures")
.join(name)
}
#[test]
fn opens_csv_as_single_synthetic_sheet() {
let path = fixture("sample-minimal.csv");
assert!(path.exists(), "csv fixture missing at {}", path.display());
let mut wb = Workbook::open(&path).expect("open csv");
assert_eq!(wb.format(), SourceFormat::Csv);
let names = wb.sheet_names().to_vec();
assert_eq!(
names.len(),
1,
"csv should expose exactly one synthetic sheet, got {names:?}"
);
assert_eq!(names[0], "sample-minimal");
let sheet = wb.first_sheet().expect("read csv sheet");
let (rows, cols) = sheet.dimensions();
assert_eq!(rows, 4, "got {rows} rows");
assert_eq!(cols, 5, "got {cols} cols");
let headers = sheet.headers();
assert_eq!(
headers,
vec!["Account", "Jan", "Feb", "Mar", "Q1"],
"csv header row"
);
for row in sheet.rows().iter().skip(1) {
for cell in row.iter().skip(1) {
match &cell.value {
CellValue::String(_) => {}
CellValue::Empty => {}
other => panic!("expected string-valued CSV cell, got {other:?}"),
}
}
}
let schema = infer_sheet_schema(&sheet);
assert_eq!(schema.columns.len(), 5);
assert_eq!(schema.columns[0].inferred_type, InferredType::String);
for col in &schema.columns[1..] {
assert_eq!(
col.inferred_type,
InferredType::Int,
"column {:?} should infer Int, got {:?}",
col.name,
col.inferred_type
);
}
}
#[test]
fn opens_xls_with_calamine_backend() {
let path = fixture("sample-minimal.xls");
assert!(path.exists(), "xls fixture missing at {}", path.display());
let mut wb = Workbook::open(&path).expect("open xls");
assert_eq!(wb.format(), SourceFormat::Xls);
let names = wb.sheet_names().to_vec();
assert!(!names.is_empty(), "xls should have at least one sheet");
assert_eq!(names[0], "P&L");
let sheet = wb.first_sheet().expect("read xls sheet");
let (rows, cols) = sheet.dimensions();
assert!(
rows >= 4 && cols >= 5,
"dims should be >= 4x5, got {rows}x{cols}"
);
let headers = sheet.headers();
assert_eq!(headers[0], "Account");
assert_eq!(headers[1], "Jan");
let schema = infer_sheet_schema(&sheet);
assert_eq!(schema.columns[0].inferred_type, InferredType::String);
assert_eq!(
schema.columns[1].inferred_type,
InferredType::Int,
"Jan column should infer Int, got {:?}",
schema.columns[1].inferred_type
);
}
#[test]
fn opens_xlsb_with_calamine_backend() {
let path = fixture("sample-date.xlsb");
assert!(path.exists(), "xlsb fixture missing at {}", path.display());
let mut wb = Workbook::open(&path).expect("open xlsb");
assert_eq!(wb.format(), SourceFormat::Xlsb);
let names = wb.sheet_names().to_vec();
assert_eq!(names, vec!["Sheet1"]);
let sheet = wb.first_sheet().expect("read xlsb sheet");
let (rows, cols) = sheet.dimensions();
assert_eq!((rows, cols), (3, 2));
let headers = sheet.headers();
assert_eq!(headers[0], "2021-01-01");
assert_eq!(headers[1], "15");
let schema = infer_sheet_schema(&sheet);
assert_eq!(schema.columns.len(), 2);
assert_eq!(schema.columns[1].inferred_type, InferredType::Int);
}
#[test]
fn opens_ods_with_calamine_backend() {
let path = fixture("sample-minimal.ods");
assert!(path.exists(), "ods fixture missing at {}", path.display());
let mut wb = Workbook::open(&path).expect("open ods");
assert_eq!(wb.format(), SourceFormat::Ods);
let names = wb.sheet_names().to_vec();
assert!(!names.is_empty(), "ods should have at least one sheet");
let sheet = wb.first_sheet().expect("read ods sheet");
let (rows, cols) = sheet.dimensions();
assert!(
rows >= 4 && cols >= 5,
"dims should be >= 4x5, got {rows}x{cols}"
);
let headers = sheet.headers();
assert_eq!(headers[0], "Account");
let schema = infer_sheet_schema(&sheet);
assert_eq!(
schema.columns[1].inferred_type,
InferredType::Int,
"Jan column on ods should infer Int, got {:?}",
schema.columns[1].inferred_type
);
}
#[test]
fn rejects_unsupported_extension() {
let bad_path = fixture("sample-minimal.csv").with_extension("unknown-ext");
match Workbook::open(&bad_path) {
Ok(_) => panic!("should reject .unknown-ext"),
Err(e) => {
let msg = format!("{e}");
assert!(
msg.contains("unsupported file extension"),
"error should name the bad extension, got {msg:?}"
);
}
}
}
#[test]
fn rejects_missing_extension() {
let bare = fixture("sample-minimal").with_file_name("no-extension-here");
match Workbook::open(&bare) {
Ok(_) => panic!("should reject path with no extension"),
Err(e) => assert!(format!("{e}").contains("cannot detect format"), "got {e}"),
}
}
#[test]
fn styles_accessor_errors_for_non_xlsx_formats() {
let mut wb = Workbook::open(fixture("sample-minimal.csv")).expect("open csv");
match wb.styles() {
Ok(_) => panic!("styles walker should error on non-xlsx"),
Err(e) => assert!(format!("{e}").contains("only supports xlsx"), "got {e}"),
}
}