Complete first version with full tests