def test_taskchain_completion_child_and_parent_complete(self): task = astnode.Node( _id=None, ntype='task', name='kitchen', data={ 'status': 'done', 'created': None, 'finished': None, 'modified': None, }, children=[ astnode.Node( _id=None, ntype='task', name='kitchen', data={ 'status': 'skip', 'created': None, 'finished': None, 'modified': None, }, children=None, ) ], ) assert task.is_complete() is True
def test_update_add_child(self): old_node = astnode.Node( _id='233662903DE54C4E9FC71EF7DA2920A8', ntype='task', name='task A', data={ 'status': 'todo', 'created': None, 'finished': None, 'modified': None, }, children=[ astnode.Node( _id='A58ACFFF058849B291D65DFBBC146BB8', ntype='task', name='subtask B', data={ 'status': 'todo', 'created': None, 'finished': None, 'modified': None, }, ) ] ) new_node = astnode.Node( _id='233662903DE54C4E9FC71EF7DA2920A8', ntype='task', name='task A', data={ 'status': 'todo', 'created': None, 'finished': None, 'modified': None, }, children=[ astnode.Node( _id='AE0CC1B973694FB4B76F191B28C642FA', ntype='task', name='subtask A', data={ 'status': 'todo', 'created': None, 'finished': None, 'modified': None, }, ), astnode.Node( _id='A58ACFFF058849B291D65DFBBC146BB8', ntype='task', name='subtask B', data={ 'status': 'todo', 'created': None, 'finished': None, 'modified': None, }, ) ] ) old_node.update(new_node) assert len(old_node.children) == 2 assert old_node.children[1].id == 'A58ACFFF058849B291D65DFBBC146BB8'
def test_inequality(self): dt = datetime.datetime(1970, 1, 1, 0, 0, 0, tzinfo=timezone.UTC()) task_A = astnode.Node( _id=None, ntype='task', name='task A', data={ 'status': 'todo', 'created': dt, 'finished': False, 'modified': dt, }, children=None, ) task_B = astnode.Node( _id=None, ntype='task', name='task B', data={ 'status': 'todo', 'created': dt, 'finished': False, 'modified': dt, }, children=None, ) assert task_A != task_B
def test_node_with_parent_returns_id(self): parent_node = astnode.Node( _id='393444843C3A4BB08839D9949F04F715', ntype='task', name='task A', data={ 'status': 'todo', 'created': None, 'finished': False, 'modified': None, }, ) node = astnode.Node( _id='212BA0B5FA144F71BCF73B07F9DEBABD', ntype='task', name='task A', data={ 'status': 'todo', 'created': None, 'finished': False, 'modified': None, }, parent=parent_node ) assert node.parentid == '393444843C3A4BB08839D9949F04F715'
def test_subtask(self): parsed = self.parser([ { '_id': '6ed88ae2e7d94d2c88249a954782fc46', 'type': 'task', 'name': 'taskA', 'indent': 0, 'parent': None, 'data': { 'status': 'todo', 'created': None, 'finished': False, 'modified': None }, }, { '_id': '032012b832f546d7bdc13a08ade41ba0', 'type': 'task', 'name': 'subtaskA', 'indent': 4, 'parent': '6ed88ae2e7d94d2c88249a954782fc46', 'data': { 'status': 'todo', 'created': None, 'finished': False, 'modified': None }, }, ]) expected = [ astnode.Node(_id='6ed88ae2e7d94d2c88249a954782fc46', ntype='task', name='taskA', data={ 'status': 'todo', 'created': None, 'finished': False, 'modified': None }, children=[ astnode.Node( _id='032012b832f546d7bdc13a08ade41ba0', ntype='task', name='subtaskA', data={ 'status': 'todo', 'created': None, 'finished': False, 'modified': None }, children=None, ), ]) ] assert parsed == expected
def test_subsection_with_task_subtasks(self): render = self.render([ astnode.Node(_id=None, ntype='section', name='cleanup', data={}, children=[ astnode.Node(_id=None, ntype='section', name='kitchen', data={}, children=[ astnode.Node( _id=None, ntype='task', name='oven', data={ 'status': 'todo', 'created': None, 'finished': False, 'modified': None, }, children=[ astnode.Node( _id=None, ntype='task', name='elements', data={ 'status': 'todo', 'created': None, 'finished': False, 'modified': None, }, children=None, ), ]), ]) ]) ]) print(render) assert render == [ '', 'cleanup', '=======', '', '', 'kitchen', '-------', '', '* oven', ' * elements', ]
def test_produces_ast(self): # input data = [ { '_id': 'C5ED1030425A436DABE94E0FCCCE76D6', 'type': 'section', 'name': 'home', 'indent': 0, 'parent': None, 'data': {}, }, ] fd = get_iostream(json.dumps(data)) AST = parsers.parse(fd, lexers.LexerTypes.mtask) # expects expected_AST = asttree.AbstractSyntaxTree([ astnode.Node( _id='C5ED1030425A436DABE94E0FCCCE76D6', ntype=astnode.NodeType.section, name='home', ), ]) assert AST == expected_AST
def test_task(self): render = self.render([ astnode.Node( _id=None, ntype='task', name='task A', data={ 'status': 'todo', 'created': None, 'finished': False, 'modified': None, }, children=None, ) ]) assert render == [{ '_id': None, 'type': 'task', 'name': 'task A', 'indent': 0, 'data': { 'status': 'todo', 'created': None, 'finished': False, 'modified': None, }, 'parent': None, }]
def test_status_done(self): render = self.render([ astnode.Node( _id=None, ntype='task', name='task A', data={ 'status': 'done', 'created': None, 'finished': datetime.datetime(2018, 1, 1, 0, 0, 0, tzinfo=timezone.UTC()), 'modified': None, }, children=None, ) ]) assert render == ['x task A']
def test_task_finished_converted_to_iso8601(self): render = self.render([ astnode.Node( _id=None, ntype='task', name='task A', data={ 'status': 'todo', 'created': None, 'finished': datetime.datetime(2018, 1, 1, 0, 0, 0, tzinfo=timezone.UTC()), 'modified': None, }, children=None, ) ]) assert render[0]['data']['finished'] == '2018-01-01T00:00:00+00:00'
def test_task(self): parsed = self.parser([{ # an empty, but syntactically correct task '_id': '6ed88ae2e7d94d2c88249a954782fc46', 'type': 'task', 'name': 'taskA', 'indent': 0, 'parent': None, 'data': { 'status': 'todo', 'created': None, 'finished': False, 'modified': None }, }]) assert parsed == [ astnode.Node( _id='6ed88ae2e7d94d2c88249a954782fc46', ntype='task', name='taskA', data={ 'status': 'todo', 'created': None, 'finished': False, 'modified': None }, children=None, ) ]
def test_file_nodetype(self): task = astnode.Node( _id=None, ntype='file', name='path/to/file.mtask', ) assert task.type == 'file' assert task.name == 'path/to/file.mtask'
def test_section_nodetype(self): task = astnode.Node( _id=None, ntype='section', name='My Section', ) assert task.type == 'section' assert task.name == 'My Section'
def test_update_name_also_updates_modified(self): params = dict( _id=None, ntype='task', data={ 'status': 'todo', 'created': None, 'finished': None, 'modified': None, }, children=None, ) node_A = astnode.Node(name='task A', **params) node_B = astnode.Node(name='task B', **params) node_A.update(node_B) assert node_A.data.modified != node_B.data.modified
def test_raises_typeerror_if_data_not_iterable(self): node = astnode.Node( _id=None, name='abc', ntype=astnode.NodeType.section, ) with pytest.raises(TypeError): asttree.AbstractSyntaxTree(node)
def test_update_receives_type(self): params = dict( _id=None, ntype='task', data={ 'status': 'todo', 'created': None, 'finished': None, 'modified': None, }, children=None, ) node_A = astnode.Node(name='task A', **params) node_B = astnode.Node(name='task B', **params) # NOTE: actual value is enum, `type` returns the enum's value node_A.update(node_B) assert node_A.type == 'task'
def test_get_by_index(self): node = astnode.Node( _id=None, ntype='section', name='Section 1', children=[ astnode.Node( _id=None, ntype='section', name='Section 1a', ), astnode.Node( _id=None, ntype='section', name='Section 1b', ), ] ) assert node[1].name == 'Section 1b'
def test_get_by_id(self): node = astnode.Node( _id='E22275B921714E99A5579056601EAF1F', ntype='section', name='Section 1', children=[ astnode.Node( _id='2676AF58D79C47A38F1A976A9C99ED7C', ntype='section', name='Section 1a', ), astnode.Node( _id='E4CF0C3DC7264F29968D2C81D386F7A7', ntype='section', name='Section 1b', ), ] ) assert node['2676AF58D79C47A38F1A976A9C99ED7C'].name == 'Section 1a'
def test_update_type_works(self): params = dict( _id='206BC92CC45D454792CEE22EF2E33CD6', data={}, children=None, ) node_A = astnode.Node( ntype='section', name='Section', **params ) node_B = astnode.Node( ntype='file', name='/path/to/file.mtask', **params ) node_A.update(node_B) assert node_A.type == 'file'
def test_section_with_tasks(self): render = self.render([ astnode.Node(_id=None, ntype='section', name='cleanup', data={}, children=[ astnode.Node( _id=None, ntype='task', name='subtask A', data={ 'status': 'todo', 'created': None, 'finished': False, 'modified': None, }, children=None, ), astnode.Node( _id=None, ntype='task', name='subtask B', data={ 'status': 'todo', 'created': None, 'finished': False, 'modified': None, }, children=None, ), ]) ]) assert render == [ '', 'cleanup', '=======', '', '* subtask A', '* subtask B', ]
def test_invalid_nodetype(self): # enum astnode.NodeType raises ValueError when nodetype is invalid. with pytest.raises(ValueError): self.render([ astnode.Node( _id=None, ntype='invalid-ntype', name='name', data={}, ) ])
def test_get_by_id_fails_with_keyerror(self): with pytest.raises(KeyError): node = astnode.Node( _id='E22275B921714E99A5579056601EAF1F', ntype='section', name='Section 1', children=[ astnode.Node( _id='2676AF58D79C47A38F1A976A9C99ED7C', ntype='section', name='Section 1a', ), astnode.Node( _id='E4CF0C3DC7264F29968D2C81D386F7A7', ntype='section', name='Section 1b', ), ] ) node['invalid-id'].name
def test_taskchain_completion_empty_section(self): """ empty sections resolve as false, they are likely there as markers for what is to come next. """ task = astnode.Node( _id=None, ntype='section', name='kitchen', data={}, children=None, ) assert task.is_complete() is False
def test_taskchain_completion_file(self): """ files must resolve as false, at least until I figure out a mechanism for archiving an entire taskfile, and if that is even desirable. """ task = astnode.Node( _id=None, ntype='file', name='home/todo.mtask', data={}, children=None, ) assert task.is_complete() is False
def test_node_without_parent_returns_none(self): node = astnode.Node( _id='99805A4613714AB1859CB57DFF0F85CA', ntype='task', name='task A', data={ 'status': 'todo', 'created': None, 'finished': False, 'modified': None, }, ) assert node.parentid is None
def test_update_with_nonmatching_id(self): params = dict( ntype='task', name='task A', data={ 'status': 'todo', 'created': None, 'finished': None, 'modified': None, }, children=None, ) node_A = astnode.Node( _id='24B7213E055B43C2A182FB2CEDC9D36F', **params ) node_B = astnode.Node( _id='7B28520767FD4EA2961A42E414022B3F', **params ) with pytest.raises(RuntimeError): node_A.update(node_B)
def test_taskchain_completion_top_task_incomplete(self): task = astnode.Node( _id=None, ntype='task', name='kitchen', data={ 'status': 'todo', 'created': None, 'finished': None, 'modified': None, }, children=None, ) assert task.is_complete() is False
def test_update_operates_on_data(self): params = dict( _id=None, name='task A', ntype='task', data={ 'status': 'todo', 'created': None, 'finished': None, 'modified': None, }, children=None, ) with mock.patch('{}.isinstance'.format(ns), return_value=True): mock_data = mock.Mock(spec='{}.TaskData'.format(nodedata.__name__)) mock_data.update = mock.Mock() node_A = astnode.Node(**params) node_A._data = mock_data node_B = astnode.Node(**params) node_A.update(node_B) assert mock_data.update.called_with(node_B)
def test_with_parent(self): dt = datetime.datetime(1970, 1, 1, 0, 0, 0, tzinfo=timezone.UTC()) parent = astnode.Node( _id='6FE476CAD8774F8A874D1B5305867F4F', ntype='section', name='Section', ) task = astnode.Node( _id='A910AC72BFF74C7185F3A9DACDE5B50B', ntype='task', name='task A', data={ 'status': 'todo', 'created': dt, 'finished': False, 'modified': dt, }, children=None, parent=parent, ) taskrepr = repr(task) expects = 'Node(type=task, name=task A, id=A910AC72BFF74C7185F3A9DACDE5B50B, parentid=6FE476CAD8774F8A874D1B5305867F4F)' assert expects == taskrepr
def test_taskchain_completion_section_with_children(self): """ entirely completed sections resolve as true. """ task = astnode.Node( _id=None, ntype='section', name='kitchen', data={}, children=[ astnode.Node( _id=None, ntype='task', name='kitchen', data={ 'status': 'done', 'created': None, 'finished': None, 'modified': None, }, children=None, ) ], ) assert task.is_complete() is True