add tests and refactor