add tests, add docs, some refactor