refactor and add more tests