refactor; add tests