tenseleyflow/shtick / f6cee13

Browse files

test scripts. bash one broken

Authored by espadonne
SHA
f6cee136d784d09289adc041a5faf13880698b30
Parents
d2b96fe
Tree
6806a65

2 changed files

StatusFile+-
A test_shtick.py 461 0
A test_shtick.sh 236 0
test_shtick.pyadded
@@ -0,0 +1,461 @@
1
+#!/usr/bin/env python3
2
+"""
3
+test_shtick_fixed.py - Comprehensive test suite for shtick commands
4
+Fixed to handle interactive prompts
5
+"""
6
+
7
+import subprocess
8
+import tempfile
9
+import shutil
10
+import os
11
+import sys
12
+from pathlib import Path
13
+
14
+# ANSI color codes
15
+RED = "\033[0;31m"
16
+GREEN = "\033[0;32m"
17
+YELLOW = "\033[1;33m"
18
+NC = "\033[0m"  # No Color
19
+
20
+
21
+class ShtickTester:
22
+    def __init__(self):
23
+        self.tests_run = 0
24
+        self.tests_passed = 0
25
+        self.tests_failed = 0
26
+        self.test_dir = None
27
+        self.original_home = os.environ.get("HOME")
28
+        self.shtick_cmd = self._find_shtick_command()
29
+
30
+    def _find_shtick_command(self):
31
+        """Find the shtick command to use"""
32
+        # Method 1: Check if shtick is in PATH
33
+        if shutil.which("shtick"):
34
+            print(f"Found shtick in PATH: {shutil.which('shtick')}")
35
+            return ["shtick"]
36
+
37
+        # Method 2: Try running as module from current directory
38
+        if Path("shtick/cli.py").exists():
39
+            print("Found shtick module in current directory")
40
+            return [sys.executable, "-m", "shtick.cli"]
41
+
42
+        # Method 3: Try parent directory
43
+        if Path("../shtick/cli.py").exists():
44
+            print("Found shtick module in parent directory")
45
+            os.chdir("..")
46
+            return [sys.executable, "-m", "shtick.cli"]
47
+
48
+        # Method 4: Direct cli.py execution
49
+        if Path("cli.py").exists():
50
+            print("Found cli.py in current directory")
51
+            return [sys.executable, "cli.py"]
52
+
53
+        raise RuntimeError(
54
+            "Cannot find shtick command! Please ensure shtick is installed or run from source directory."
55
+        )
56
+
57
+    def setup(self):
58
+        """Set up test environment"""
59
+        self.test_dir = tempfile.mkdtemp(prefix="shtick_test_")
60
+        os.environ["HOME"] = self.test_dir
61
+        os.makedirs(os.path.join(self.test_dir, ".config", "shtick"), exist_ok=True)
62
+
63
+        # Create a settings file that disables auto_source_prompt to avoid timeouts
64
+        settings_path = os.path.join(
65
+            self.test_dir, ".config", "shtick", "settings.toml"
66
+        )
67
+        with open(settings_path, "w") as f:
68
+            f.write(
69
+                """# Test settings
70
+[behavior]
71
+auto_source_prompt = false
72
+check_conflicts = true
73
+backup_on_save = false
74
+interactive_mode = false
75
+"""
76
+            )
77
+
78
+        print(f"Test directory: {self.test_dir}")
79
+        print(f"Created settings to disable interactive prompts")
80
+
81
+    def cleanup(self):
82
+        """Clean up test environment"""
83
+        if self.test_dir and os.path.exists(self.test_dir):
84
+            shutil.rmtree(self.test_dir)
85
+        if self.original_home:
86
+            os.environ["HOME"] = self.original_home
87
+        else:
88
+            os.environ.pop("HOME", None)
89
+
90
+    def run_command(self, args, input_text=None, env_override=None):
91
+        """Run a shtick command and return (output, return_code)"""
92
+        cmd = self.shtick_cmd + args
93
+
94
+        env = os.environ.copy()
95
+        if env_override:
96
+            env.update(env_override)
97
+
98
+        # Always ensure we're using our test HOME
99
+        env["HOME"] = self.test_dir
100
+
101
+        try:
102
+            # For commands that might prompt, always provide 'n' as input
103
+            # to avoid hanging on interactive prompts
104
+            if input_text is None and any(
105
+                x in args for x in ["alias", "env", "function", "add", "remove"]
106
+            ):
107
+                input_text = "n\n"
108
+
109
+            result = subprocess.run(
110
+                cmd,
111
+                capture_output=True,
112
+                text=True,
113
+                input=input_text,
114
+                env=env,
115
+                timeout=5,  # Reduced timeout since we're handling prompts
116
+            )
117
+            return result.stdout + result.stderr, result.returncode
118
+        except subprocess.TimeoutExpired:
119
+            return "Command timed out", -1
120
+        except Exception as e:
121
+            return f"Error running command: {e}", -1
122
+
123
+    def test_command(
124
+        self,
125
+        test_name,
126
+        args,
127
+        expected_status,
128
+        description,
129
+        input_text=None,
130
+        env_override=None,
131
+    ):
132
+        """Run a test and check the result"""
133
+        self.tests_run += 1
134
+
135
+        print(f"[{self.tests_run}] {test_name}: {description} ... ", end="", flush=True)
136
+
137
+        output, actual_status = self.run_command(args, input_text, env_override)
138
+
139
+        if actual_status == expected_status:
140
+            print(f"{GREEN}PASS{NC}")
141
+            self.tests_passed += 1
142
+        else:
143
+            print(f"{RED}FAIL{NC}")
144
+            print(f"  Expected status: {expected_status}, Got: {actual_status}")
145
+            print(f"  Command: {' '.join(self.shtick_cmd + args)}")
146
+            print(f"  Output: {output[:500]}...")  # Truncate long output
147
+            self.tests_failed += 1
148
+
149
+    def verify_shtick(self):
150
+        """Verify shtick command is working"""
151
+        print("Verifying shtick command...")
152
+        output, status = self.run_command(["--help"])
153
+
154
+        if status != 0:
155
+            print(f"{RED}ERROR: shtick command not working!{NC}")
156
+            print(f"Status: {status}")
157
+            print(f"Output: {output}")
158
+            sys.exit(1)
159
+
160
+        print(f"{GREEN}✓ shtick command verified{NC}\n")
161
+
162
+    def run_all_tests(self):
163
+        """Run all tests"""
164
+        print("===================================")
165
+        print("Shtick Command Test Suite (Python)")
166
+        print("===================================\n")
167
+
168
+        self.setup()
169
+        self.verify_shtick()
170
+
171
+        try:
172
+            # Test 1: Basic commands without config
173
+            print(f"{YELLOW}Testing basic commands without config:{NC}")
174
+            self.test_command(
175
+                "status-no-config", ["status"], 0, "Status should work without config"
176
+            )
177
+            self.test_command(
178
+                "list-no-config", ["list"], 0, "List should work without config"
179
+            )
180
+            self.test_command(
181
+                "shells", ["shells"], 0, "Shells command should always work"
182
+            )
183
+
184
+            # Test 2: Adding items - use proper quoting
185
+            print(f"\n{YELLOW}Testing add commands:{NC}")
186
+            self.test_command(
187
+                "add-alias", ["alias", "ll=ls -la"], 0, "Add persistent alias"
188
+            )
189
+            self.test_command(
190
+                "add-env", ["env", "DEBUG=1"], 0, "Add persistent env var"
191
+            )
192
+            self.test_command(
193
+                "add-function",
194
+                ["function", "greet=echo Hello"],
195
+                0,
196
+                "Add persistent function",
197
+            )
198
+
199
+            # Test 3: Invalid add commands
200
+            print(f"\n{YELLOW}Testing invalid add commands:{NC}")
201
+            self.test_command(
202
+                "add-invalid-key",
203
+                ["alias", "123bad=value"],
204
+                1,
205
+                "Invalid key should fail",
206
+            )
207
+            self.test_command(
208
+                "add-no-equals", ["alias", "no_equals_sign"], 1, "Missing = should fail"
209
+            )
210
+            self.test_command(
211
+                "add-empty-key", ["alias", "=value"], 1, "Empty key should fail"
212
+            )
213
+            self.test_command(
214
+                "add-empty-value", ["alias", "key="], 1, "Empty value should fail"
215
+            )
216
+
217
+            # Test 4: Group operations
218
+            print(f"\n{YELLOW}Testing group operations:{NC}")
219
+            self.test_command(
220
+                "add-to-group",
221
+                ["add", "alias", "work", "ll=ls -la"],
222
+                0,
223
+                "Add to specific group",
224
+            )
225
+            self.test_command(
226
+                "activate-group", ["activate", "work"], 0, "Activate existing group"
227
+            )
228
+            self.test_command(
229
+                "activate-nonexistent",
230
+                ["activate", "nonexistent"],
231
+                1,
232
+                "Activate non-existent group should fail",
233
+            )
234
+            self.test_command(
235
+                "deactivate-group", ["deactivate", "work"], 0, "Deactivate active group"
236
+            )
237
+            self.test_command(
238
+                "deactivate-inactive",
239
+                ["deactivate", "work"],
240
+                0,
241
+                "Deactivate already inactive group",
242
+            )
243
+
244
+            # Test 5: Remove operations - provide input for selection
245
+            print(f"\n{YELLOW}Testing remove operations:{NC}")
246
+            self.test_command(
247
+                "remove-existing",
248
+                ["remove-persistent", "alias", "ll"],
249
+                0,
250
+                "Remove existing alias",
251
+                input_text="1\n",
252
+            )
253
+            self.test_command(
254
+                "remove-nonexistent",
255
+                ["remove-persistent", "alias", "nonexistent"],
256
+                0,
257
+                "Remove non-existent item",
258
+            )
259
+
260
+            # Re-add for next test
261
+            self.run_command(["add", "alias", "work", "ll=ls -la"])
262
+            self.test_command(
263
+                "remove-fuzzy",
264
+                ["remove", "alias", "work", "ll"],
265
+                0,
266
+                "Remove with fuzzy match",
267
+                input_text="1\n",
268
+            )
269
+
270
+            # Test 6: Generate command
271
+            print(f"\n{YELLOW}Testing generate command:{NC}")
272
+            self.test_command(
273
+                "generate-default",
274
+                ["generate", "--terse"],
275
+                0,
276
+                "Generate with default config",
277
+            )
278
+            config_path = os.path.join(
279
+                self.test_dir, ".config", "shtick", "config.toml"
280
+            )
281
+            self.test_command(
282
+                "generate-custom",
283
+                ["generate", config_path, "--terse"],
284
+                0,
285
+                "Generate with custom config path",
286
+            )
287
+            self.test_command(
288
+                "generate-nonexistent",
289
+                ["generate", "/tmp/nonexistent.toml"],
290
+                1,
291
+                "Generate with non-existent config should fail",
292
+            )
293
+
294
+            # Test 7: Source command
295
+            print(f"\n{YELLOW}Testing source command:{NC}")
296
+            self.test_command(
297
+                "source-bash",
298
+                ["source"],
299
+                0,
300
+                "Source command for bash",
301
+                env_override={"SHELL": "/bin/bash"},
302
+            )
303
+            self.test_command(
304
+                "source-no-shell",
305
+                ["source"],
306
+                1,
307
+                "Source without shell should fail",
308
+                env_override={"SHELL": ""},
309
+            )
310
+
311
+            # Test 8: Settings commands
312
+            print(f"\n{YELLOW}Testing settings commands:{NC}")
313
+            self.test_command("settings-show", ["settings", "show"], 0, "Show settings")
314
+            # Don't re-init since we already have settings
315
+            self.test_command(
316
+                "settings-set-bool",
317
+                ["settings", "set", "behavior.backup_on_save", "true"],
318
+                0,
319
+                "Set boolean setting",
320
+            )
321
+            self.test_command(
322
+                "settings-set-invalid",
323
+                ["settings", "set", "invalid.key", "value"],
324
+                1,
325
+                "Set invalid setting should fail",
326
+            )
327
+
328
+            # Test 9: Edge cases
329
+            print(f"\n{YELLOW}Testing edge cases:{NC}")
330
+            self.test_command(
331
+                "persistent-activate",
332
+                ["activate", "persistent"],
333
+                1,
334
+                "Cannot activate persistent group",
335
+            )
336
+            self.test_command(
337
+                "persistent-deactivate",
338
+                ["deactivate", "persistent"],
339
+                1,
340
+                "Cannot deactivate persistent group",
341
+            )
342
+            long_key = "a" * 65
343
+            self.test_command(
344
+                "very-long-key",
345
+                ["alias", f"{long_key}=value"],
346
+                1,
347
+                "Key over 64 chars should fail",
348
+            )
349
+
350
+            # Test 10: Special characters
351
+            print(f"\n{YELLOW}Testing special characters:{NC}")
352
+            self.test_command(
353
+                "alias-with-quotes",
354
+                ["alias", 'msg=echo "Hello World"'],
355
+                0,
356
+                "Alias with quotes",
357
+            )
358
+            self.test_command(
359
+                "alias-with-dollar",
360
+                ["alias", "home=cd $HOME"],
361
+                0,
362
+                "Alias with dollar sign",
363
+            )
364
+            self.test_command(
365
+                "multiline-function",
366
+                ["function", "hello=echo line1\necho line2"],
367
+                0,
368
+                "Multiline function",
369
+            )
370
+
371
+            # Test 11: List and status with content
372
+            print(f"\n{YELLOW}Testing list and status with content:{NC}")
373
+            self.test_command("list-with-content", ["list"], 0, "List with items")
374
+            self.test_command(
375
+                "list-long-format", ["list", "-l"], 0, "List in long format"
376
+            )
377
+            self.test_command(
378
+                "status-with-content", ["status"], 0, "Status with configuration"
379
+            )
380
+
381
+            # Test 12: Conflict handling
382
+            print(f"\n{YELLOW}Testing conflict handling:{NC}")
383
+            # First create an alias in persistent
384
+            self.run_command(["alias", "mytest=echo test1"])
385
+            # Then add conflicting alias to different group
386
+            self.test_command(
387
+                "add-conflict-alias",
388
+                ["add", "alias", "temp", "mytest=echo test2"],
389
+                0,
390
+                "Add conflicting alias to different group",
391
+            )
392
+
393
+            # Check if warning appears when adding duplicate
394
+            output, status = self.run_command(["alias", "mytest=echo test3"])
395
+            if "exists in groups" in output and status == 0:
396
+                print(
397
+                    f"[{self.tests_run + 1}] check-conflict-warning: Should warn about conflicts ... {GREEN}PASS{NC}"
398
+                )
399
+                self.tests_passed += 1
400
+            else:
401
+                print(
402
+                    f"[{self.tests_run + 1}] check-conflict-warning: Should warn about conflicts ... {RED}FAIL{NC}"
403
+                )
404
+                print(f"  Expected warning about existing item, but got: {output}")
405
+                print(f"  Status: {status}")
406
+                self.tests_failed += 1
407
+            self.tests_run += 1
408
+
409
+            # Test 13: Backup functionality
410
+            print(f"\n{YELLOW}Testing backup functionality:{NC}")
411
+            self.test_command("backup-create", ["backup", "create"], 0, "Create backup")
412
+            self.test_command("backup-list", ["backup", "list"], 0, "List backups")
413
+
414
+            # Test 14: Group management
415
+            print(f"\n{YELLOW}Testing group management:{NC}")
416
+            self.test_command(
417
+                "group-create", ["group", "create", "testgroup"], 0, "Create new group"
418
+            )
419
+            self.test_command(
420
+                "group-rename",
421
+                ["group", "rename", "testgroup", "newgroup"],
422
+                0,
423
+                "Rename group",
424
+            )
425
+            self.test_command(
426
+                "group-remove", ["group", "remove", "newgroup", "-f"], 0, "Remove group"
427
+            )
428
+
429
+        finally:
430
+            self.cleanup()
431
+
432
+        # Summary
433
+        print("\n===================================")
434
+        print("Test Summary")
435
+        print("===================================")
436
+        print(f"Tests run:    {self.tests_run}")
437
+        print(f"Tests passed: {GREEN}{self.tests_passed}{NC}")
438
+        print(f"Tests failed: {RED}{self.tests_failed}{NC}")
439
+
440
+        if self.tests_failed == 0:
441
+            print(f"\n{GREEN}All tests passed!{NC}")
442
+            return 0
443
+        else:
444
+            print(f"\n{RED}Some tests failed!{NC}")
445
+            return 1
446
+
447
+
448
+def main():
449
+    """Run the test suite"""
450
+    # Check if we should run in non-interactive mode
451
+    if len(sys.argv) > 1 and sys.argv[1] == "--help":
452
+        print("Usage: test_shtick_fixed.py")
453
+        print("Run comprehensive tests for shtick command line tool")
454
+        return 0
455
+
456
+    tester = ShtickTester()
457
+    return tester.run_all_tests()
458
+
459
+
460
+if __name__ == "__main__":
461
+    sys.exit(main())
test_shtick.shadded
@@ -0,0 +1,236 @@
1
+#!/bin/bash
2
+# test_shtick_fixed.sh - Test suite for shtick commands with proper PATH handling
3
+
4
+set -e  # Exit on error
5
+
6
+# Colors for output
7
+RED='\033[0;31m'
8
+GREEN='\033[0;32m'
9
+YELLOW='\033[1;33m'
10
+NC='\033[0m' # No Color
11
+
12
+# Test counters
13
+TESTS_RUN=0
14
+TESTS_PASSED=0
15
+TESTS_FAILED=0
16
+
17
+# Test config directory
18
+TEST_DIR="/tmp/shtick_test_$$"
19
+export HOME="$TEST_DIR"
20
+CONFIG_DIR="$TEST_DIR/.config/shtick"
21
+
22
+# Find shtick command - try multiple approaches
23
+find_shtick() {
24
+    # Method 1: Check if shtick is in PATH
25
+    if command -v shtick >/dev/null 2>&1; then
26
+        SHTICK_CMD="shtick"
27
+        echo "Found shtick in PATH: $(command -v shtick)"
28
+        return 0
29
+    fi
30
+    
31
+    # Method 2: Check if we're in development directory with cli.py
32
+    if [ -f "./shtick/cli.py" ]; then
33
+        SHTICK_CMD="python -m shtick.cli"
34
+        echo "Found shtick module in current directory, using: $SHTICK_CMD"
35
+        return 0
36
+    fi
37
+    
38
+    # Method 3: Check parent directory
39
+    if [ -f "../shtick/cli.py" ]; then
40
+        SHTICK_CMD="python -m shtick.cli"
41
+        echo "Found shtick module in parent directory"
42
+        cd ..
43
+        return 0
44
+    fi
45
+    
46
+    # Method 4: Try direct python execution
47
+    if [ -f "cli.py" ]; then
48
+        SHTICK_CMD="python cli.py"
49
+        echo "Found cli.py in current directory, using: $SHTICK_CMD"
50
+        return 0
51
+    fi
52
+    
53
+    echo "ERROR: Cannot find shtick command!"
54
+    echo "Please ensure either:"
55
+    echo "  1. shtick is installed and in your PATH"
56
+    echo "  2. You're running this from the shtick source directory"
57
+    echo "  3. The shtick package is properly installed with 'pip install -e .'"
58
+    exit 1
59
+}
60
+
61
+# Clean up function
62
+cleanup() {
63
+    rm -rf "$TEST_DIR"
64
+}
65
+trap cleanup EXIT
66
+
67
+# Setup test environment
68
+setup() {
69
+    rm -rf "$TEST_DIR"
70
+    mkdir -p "$CONFIG_DIR"
71
+    cd "$TEST_DIR"
72
+}
73
+
74
+# Test function
75
+test_command() {
76
+    local test_name="$1"
77
+    local command="$2"
78
+    local expected_status="$3"
79
+    local description="$4"
80
+    
81
+    TESTS_RUN=$((TESTS_RUN + 1))
82
+    
83
+    echo -n "[$TESTS_RUN] $test_name: $description ... "
84
+    
85
+    # Replace 'shtick' with actual command
86
+    command="${command//shtick/$SHTICK_CMD}"
87
+    
88
+    # Run command and capture status
89
+    set +e
90
+    output=$(eval "$command" 2>&1)
91
+    actual_status=$?
92
+    set -e
93
+    
94
+    if [ $actual_status -eq $expected_status ]; then
95
+        echo -e "${GREEN}PASS${NC}"
96
+        TESTS_PASSED=$((TESTS_PASSED + 1))
97
+    else
98
+        echo -e "${RED}FAIL${NC}"
99
+        echo "  Expected status: $expected_status, Got: $actual_status"
100
+        echo "  Command: $command"
101
+        echo "  Output: $output"
102
+        TESTS_FAILED=$((TESTS_FAILED + 1))
103
+    fi
104
+}
105
+
106
+# Verify shtick is working
107
+verify_shtick() {
108
+    echo "Verifying shtick command..."
109
+    set +e
110
+    output=$($SHTICK_CMD --help 2>&1)
111
+    status=$?
112
+    set -e
113
+    
114
+    if [ $status -ne 0 ]; then
115
+        echo -e "${RED}ERROR: shtick command not working!${NC}"
116
+        echo "Command: $SHTICK_CMD --help"
117
+        echo "Status: $status"
118
+        echo "Output: $output"
119
+        exit 1
120
+    fi
121
+    echo -e "${GREEN}✓ shtick command verified${NC}"
122
+    echo
123
+}
124
+
125
+# Header
126
+echo "==================================="
127
+echo "Shtick Command Test Suite"
128
+echo "==================================="
129
+echo
130
+
131
+# Find shtick command
132
+find_shtick
133
+
134
+# Setup
135
+setup
136
+
137
+# Verify shtick works
138
+verify_shtick
139
+
140
+# Save original directory to return to later
141
+ORIGINAL_DIR=$(pwd)
142
+
143
+# Test 1: Basic commands without config
144
+echo -e "${YELLOW}Testing basic commands without config:${NC}"
145
+test_command "status-no-config" "shtick status" 0 "Status should work without config"
146
+test_command "list-no-config" "shtick list" 0 "List should work without config"
147
+test_command "shells" "shtick shells" 0 "Shells command should always work"
148
+
149
+# Test 2: Adding items (creates config)
150
+echo -e "\n${YELLOW}Testing add commands:${NC}"
151
+test_command "add-alias" "shtick alias ll='ls -la'" 0 "Add persistent alias"
152
+test_command "add-env" "shtick env DEBUG=1" 0 "Add persistent env var"
153
+test_command "add-function" "shtick function greet='echo Hello'" 0 "Add persistent function"
154
+
155
+# Test 3: Invalid add commands
156
+echo -e "\n${YELLOW}Testing invalid add commands:${NC}"
157
+test_command "add-invalid-key" "shtick alias '123bad=value'" 1 "Invalid key should fail"
158
+test_command "add-no-equals" "shtick alias 'no_equals_sign'" 1 "Missing = should fail"
159
+test_command "add-empty-key" "shtick alias '=value'" 1 "Empty key should fail"
160
+test_command "add-empty-value" "shtick alias 'key='" 1 "Empty value should fail"
161
+
162
+# Test 4: Group operations
163
+echo -e "\n${YELLOW}Testing group operations:${NC}"
164
+test_command "add-to-group" "shtick add alias work ll='ls -la'" 0 "Add to specific group"
165
+test_command "activate-group" "shtick activate work" 0 "Activate existing group"
166
+test_command "activate-nonexistent" "shtick activate nonexistent" 1 "Activate non-existent group should fail"
167
+test_command "deactivate-group" "shtick deactivate work" 0 "Deactivate active group"
168
+test_command "deactivate-inactive" "shtick deactivate work" 0 "Deactivate already inactive group"
169
+
170
+# Test 5: Remove operations
171
+echo -e "\n${YELLOW}Testing remove operations:${NC}"
172
+test_command "remove-existing" "echo 1 | shtick remove-persistent alias ll" 0 "Remove existing alias"
173
+test_command "remove-nonexistent" "shtick remove-persistent alias nonexistent" 0 "Remove non-existent item"
174
+test_command "remove-fuzzy" "echo 1 | shtick remove alias work ll" 0 "Remove with fuzzy match"
175
+
176
+# Test 6: Generate command
177
+echo -e "\n${YELLOW}Testing generate command:${NC}"
178
+test_command "generate-default" "shtick generate --terse" 0 "Generate with default config"
179
+test_command "generate-custom" "shtick generate $CONFIG_DIR/config.toml --terse" 0 "Generate with custom config path"
180
+test_command "generate-nonexistent" "shtick generate /tmp/nonexistent.toml" 1 "Generate with non-existent config should fail"
181
+
182
+# Test 7: Source command
183
+echo -e "\n${YELLOW}Testing source command:${NC}"
184
+test_command "source-bash" "SHELL=/bin/bash shtick source" 0 "Source command for bash"
185
+test_command "source-no-shell" "SHELL= shtick source" 1 "Source without shell should fail"
186
+
187
+# Test 8: Settings commands
188
+echo -e "\n${YELLOW}Testing settings commands:${NC}"
189
+test_command "settings-show" "shtick settings show" 0 "Show settings"
190
+test_command "settings-init" "shtick settings init" 0 "Initialize settings"
191
+test_command "settings-set-bool" "shtick settings set behavior.auto_source_prompt false" 0 "Set boolean setting"
192
+test_command "settings-set-invalid" "shtick settings set invalid.key value" 1 "Set invalid setting should fail"
193
+
194
+# Test 9: Edge cases
195
+echo -e "\n${YELLOW}Testing edge cases:${NC}"
196
+test_command "persistent-activate" "shtick activate persistent" 1 "Cannot activate persistent group"
197
+test_command "persistent-deactivate" "shtick deactivate persistent" 1 "Cannot deactivate persistent group"
198
+test_command "very-long-key" "shtick alias $(printf 'a%.0s' {1..65})=value" 1 "Key over 64 chars should fail"
199
+
200
+# Test 10: Special characters and escaping
201
+echo -e "\n${YELLOW}Testing special characters:${NC}"
202
+test_command "alias-with-quotes" "shtick alias msg='echo \"Hello World\"'" 0 "Alias with quotes"
203
+test_command "alias-with-dollar" 'shtick alias home="cd \$HOME"' 0 "Alias with dollar sign"
204
+test_command "multiline-function" 'shtick function hello="echo line1
205
+echo line2"' 0 "Multiline function"
206
+
207
+# Test 11: List and status with content
208
+echo -e "\n${YELLOW}Testing list and status with content:${NC}"
209
+test_command "list-with-content" "shtick list" 0 "List with items"
210
+test_command "list-long-format" "shtick list -l" 0 "List in long format"
211
+test_command "status-with-content" "shtick status" 0 "Status with configuration"
212
+
213
+# Test 12: Conflict handling
214
+echo -e "\n${YELLOW}Testing conflict handling:${NC}"
215
+test_command "add-conflict-alias" "shtick add alias temp ll='ls -lah'" 0 "Add conflicting alias to different group"
216
+test_command "check-conflict-warning" "shtick alias ll='ls -la' 2>&1 | grep -q 'exists in groups'" 0 "Should warn about conflicts"
217
+
218
+# Return to original directory
219
+cd "$ORIGINAL_DIR"
220
+
221
+# Summary
222
+echo
223
+echo "==================================="
224
+echo "Test Summary"
225
+echo "==================================="
226
+echo "Tests run:    $TESTS_RUN"
227
+echo -e "Tests passed: ${GREEN}$TESTS_PASSED${NC}"
228
+echo -e "Tests failed: ${RED}$TESTS_FAILED${NC}"
229
+
230
+if [ $TESTS_FAILED -eq 0 ]; then
231
+    echo -e "\n${GREEN}All tests passed!${NC}"
232
+    exit 0
233
+else
234
+    echo -e "\n${RED}Some tests failed!${NC}"
235
+    exit 1
236
+fi