add tests; refactor