Skip to content

Commit a8e71e7

Browse files
committed
Merge branch 'feature/action-tests' into devel
2 parents dce866a + 721db19 commit a8e71e7

13 files changed

+436
-33
lines changed

contextshell/backends/filesystem.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ def list_action(self, target: NodePath) -> List[NodePath]:
4545
return []
4646
return list(sorted([NodePath(f.name) for f in dir_path.iterdir()]))
4747

48-
def list_actions_action(self, _: NodePath) -> List[NodePath]:
48+
def list_actions_action(self, _: NodePath, prefix_: NodePath = None) -> List[NodePath]:
4949
# TODO: list actions depending on target type (might require issue #14)
50-
return list(map(lambda a: a.name, self.list_builtin_actions()))
50+
prefix = NodePath(prefix_)
51+
all_actions = self.list_builtin_actions()
52+
action_names = map(lambda a: NodePath(a.name[: len(prefix) + 1]), all_actions)
53+
names_matching_prefix = filter(prefix.is_parent_of, action_names)
54+
return list(names_matching_prefix)

contextshell/backends/node.py

+16-12
Original file line numberDiff line numberDiff line change
@@ -92,40 +92,44 @@ def __init__(self):
9292
self.root = Node(None)
9393
self.install_default_actions()
9494

95-
def create_action(self, target: NodePath, path: str, value=None): # NOCOVER
95+
def create_action(self, target: NodePath, path: str, value=None):
9696
self.create(NodePath.join(target, path), value)
9797

98-
def contains_action(self, target: NodePath, path: str) -> bool: # NOCOVER
98+
def contains_action(self, target: NodePath, path: str) -> bool:
9999
return self.contains(NodePath.join(target, path))
100100

101-
def get_action(self, target: NodePath): # NOCOVER
101+
def get_action(self, target: NodePath):
102102
return self.get(target)
103103

104-
def set_action(self, target: NodePath, new_value): # NOCOVER
104+
def set_action(self, target: NodePath, new_value):
105105
return self.set(target, new_value)
106106

107-
def list_action(self, target: NodePath): # NOCOVER
107+
def list_action(self, target: NodePath):
108108
all_list = self.list(target)
109109
return list(filter(lambda p: not NodePath(p).is_attribute, all_list))
110110

111-
def list_all_action(self, target: NodePath): # NOCOVER
111+
def list_all_action(self, target: NodePath):
112112
return self.list(target)
113113

114-
def list_attributes_action(self, target: NodePath): # NOCOVER
114+
def list_attributes_action(self, target: NodePath):
115115
all_list = self.list(target)
116116
return list(filter(lambda p: NodePath(p).is_attribute, all_list))
117117

118-
def list_actions_action(self, target: NodePath): # NOCOVER
118+
def list_actions_action(self, target: NodePath):
119119
# FIXME: use the same mechanism as in self.find_action
120120
# CHECK: consider using find.all.actions action
121121
actions_branch = NodePath.join(target, "@actions")
122122
return self.list(actions_branch)
123123

124-
def remove_action(self, target: NodePath): # NOCOVER
125-
# CHECK: use 'path' argument?
126-
return self.remove(target)
124+
def remove_action(self, target: NodePath, path: NodePath = None):
125+
if path is None:
126+
return self.remove(target)
127+
path_to_remove = NodePath.join(target, path)
128+
if not self.contains(path_to_remove):
129+
return None
130+
return self.remove(path_to_remove)
127131

128-
def find_type_action(self, target: NodePath, type_name: str): # NOCOVER
132+
def find_type_action(self, target: NodePath, type_name: str):
129133
return self.find_type(target, NodePath(type_name))
130134

131135
def install_default_actions(self):

functional_tests.sh

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ coverage run \
88
-m unittest \
99
discover \
1010
--pattern '*Tests.py' \
11-
--start-directory ./ \
12-
./tests/functional
11+
--top-level-directory ./ \
12+
--start-directory ./tests/functional/ \
13+
./tests/functional/
1314
TESTS_PASSED=$?
1415

1516
if [[ $TESTS_PASSED -eq 0 ]];

tests/unit/ActionExecutorTests.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from typing import Optional
44

55
from contextshell.action import Action, ActionExecutor, pack_argument_tree
6-
from tests.unit.Fakes import FakeAction
6+
from tests.unit.fakes import FakeAction
77

88
from contextshell.path import NodePath, NodePath as np # isort:skip
99

tests/unit/BuiltinExecutorTests.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from contextshell.action import BuiltinExecutor
44
from contextshell.path import NodePath
5-
from tests.unit.Fakes import FakeAction
5+
from tests.unit.fakes import FakeAction
66

77

88
class RegisterAction(unittest.TestCase):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
import tempfile
2+
import unittest
3+
from pathlib import Path
4+
5+
from .bases import ActionTestsBase
6+
7+
8+
def create_filesystem_tree(*args, **kwargs):
9+
from contextshell.backends.filesystem import FilesystemTree
10+
return FilesystemTree(*args, **kwargs)
11+
12+
13+
class FilesystemActionsTestsBase(ActionTestsBase):
14+
"""Test base for tests wishing to use actual filesystem directory"""
15+
def _make_test_path(self, relative_path):
16+
return Path(self.test_directory.name).joinpath(relative_path)
17+
18+
def create_file(self, path: str, contents: str=None):
19+
full_path = self._make_test_path(path)
20+
full_path.parent.mkdir(parents=True, exist_ok=True)
21+
with open(full_path, 'w') as file:
22+
file.write(contents if contents else '')
23+
24+
def create_directory(self, path):
25+
full_path = self._make_test_path(path)
26+
full_path.mkdir(parents=True)
27+
28+
def create_backend(self):
29+
return create_filesystem_tree(self.test_directory.name)
30+
31+
def setUp(self):
32+
temp_dir_suffix = type(self).__name__
33+
self.test_directory = tempfile.TemporaryDirectory(temp_dir_suffix)
34+
35+
super().setUp()
36+
37+
def tearDown(self):
38+
self.test_directory.cleanup()
39+
super().tearDown()
40+
41+
42+
class ContainsActionTests(FilesystemActionsTestsBase):
43+
def test_existing_file(self):
44+
self.create_file('file')
45+
46+
exists = self.execute(".", "contains", 'file')
47+
48+
self.assertTrue(exists)
49+
50+
def test_existing_file_nested(self):
51+
self.create_file('parent/file')
52+
53+
exists = self.execute(".", "contains", 'parent.file')
54+
55+
self.assertTrue(exists)
56+
57+
def test_existing_directory(self):
58+
self.create_directory('dir')
59+
60+
exists = self.execute(".", "contains", 'dir')
61+
62+
self.assertTrue(exists)
63+
64+
def test_nonexistent(self):
65+
exists = self.execute(".", "contains", 'nonexistent')
66+
67+
self.assertFalse(exists)
68+
69+
def test_nonexistent_nested(self):
70+
self.create_directory('parent')
71+
72+
exists = self.execute(".", "contains", 'parent.path')
73+
74+
self.assertFalse(exists)
75+
76+
77+
class GetActionTests(FilesystemActionsTestsBase):
78+
def test_empty_file(self):
79+
self.create_file('file')
80+
81+
file_value = self.execute(".file", "get")
82+
83+
self.assertEqual(file_value, '')
84+
85+
def test_file(self):
86+
self.create_file('file', 'DATA')
87+
88+
file_value = self.execute(".file", "get")
89+
90+
self.assertEqual(file_value, 'DATA')
91+
92+
def test_directory(self):
93+
self.create_directory('dir')
94+
95+
dir_value = self.execute(".dir", "get")
96+
97+
self.assertEqual(dir_value, None)
98+
99+
100+
class IsActionTests(FilesystemActionsTestsBase):
101+
def test_directory_is_file(self):
102+
self.create_directory('dir')
103+
104+
is_file = self.execute(".dir", "is.file")
105+
106+
self.assertFalse(is_file)
107+
108+
def test_file_is_file(self):
109+
self.create_file('file')
110+
111+
is_file = self.execute(".file", "is.file")
112+
113+
self.assertTrue(is_file)
114+
115+
def test_directory_is_directory(self):
116+
self.create_directory('dir')
117+
118+
is_dir = self.execute(".dir", "is.directory")
119+
120+
self.assertTrue(is_dir)
121+
122+
def test_file_is_directory(self):
123+
self.create_file('file')
124+
125+
is_dir = self.execute(".file", "is.directory")
126+
127+
self.assertFalse(is_dir)
128+
129+
130+
class ListActionTests(FilesystemActionsTestsBase):
131+
def test_list_file(self):
132+
self.create_file('file')
133+
134+
file_list = self.execute(".file", "list")
135+
136+
self.assertEqual(file_list, [])
137+
138+
def test_list_empty_directory(self):
139+
self.create_directory('dir')
140+
141+
file_list = self.execute(".dir", "list")
142+
143+
self.assertEqual(file_list, [])
144+
145+
def test_list_directory_with_file_and_dirs(self):
146+
self.create_directory('parent/dir')
147+
self.create_file('parent/file')
148+
149+
file_list = self.execute(".parent", "list")
150+
151+
self.assertIn('dir', file_list)
152+
self.assertIn('file', file_list)
153+
154+
@unittest.skip("Re-enable when path uses '/' as separator")
155+
def test_list_hidden(self):
156+
self.create_directory('parent/.dir')
157+
self.create_file('parent/.file')
158+
159+
file_list = self.execute(".parent", "list")
160+
161+
self.assertListEqual(file_list, [])
162+
163+
@unittest.skip("Re-enable when path uses '/' as separator")
164+
def test_list_all(self):
165+
self.create_directory('parent/.dir')
166+
self.create_file('parent/.file')
167+
168+
file_list = self.execute(".parent", "list.all")
169+
170+
self.assertIn('@dir', file_list)
171+
self.assertIn('@file', file_list)
172+
173+
174+
class ListActionsActionTests(FilesystemActionsTestsBase):
175+
def test_list_all(self):
176+
action_list = self.execute(".", "list.actions")
177+
178+
self.assertSetEqual({'contains', 'get', 'is', 'list'}, set(action_list))
179+
180+
def test_list_nested(self):
181+
action_list = self.execute(".", "list.actions", "is")
182+
183+
self.assertSetEqual({'is.file', 'is.directory'}, set(action_list))

tests/unit/backends/FilesystemTreeTests.py

-8
This file was deleted.

0 commit comments

Comments
 (0)