From 6f19f6dc7e0771dd48d0ab5d96ff6e4d91f2efc1 Mon Sep 17 00:00:00 2001 From: andrew malinnikov Date: Thu, 25 Sep 2025 11:35:55 +0700 Subject: [PATCH 1/5] run pint command --- .DS_Store | Bin 0 -> 6148 bytes sublime-phpunit.py | 18 ++++++++++++++++++ sublime-phpunit.sublime-commands | 3 ++- 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..3c914a3aad05cb54b6afe564d5175f74e4a6dc0e GIT binary patch literal 6148 zcmeHKK~BR!475umBEg|Yj{5>o)ekIDctJmaN>M>-l^)=Va^pLQPw*|q_JR^c<;VfX zl6SJUC!5S6jzvV9=gmT7E+RGDP+o1Bn&r(WHYL3@qlqFxsD0^lY>G zERZV|paN9jTLJq%B)DNN*a!Nj1B;IUK>Lk%!?n*6z+?enF4zYm0@I)ZgQ{i3(4Zrp zN?k742L@f#PsV-9$yz29_0thgUM`vgxl#ctFjn9swsY(MH}E6#|Cq!b6`%rtN&&6f zRomc|N^hOKob}oSzlDDpYP}qbw_>2TVr;AxUkvJ!T_c|h_JK}E-04962$(K3D)1W$ Fd;(`jCl&wz literal 0 HcmV?d00001 diff --git a/sublime-phpunit.py b/sublime-phpunit.py index 259d76f..d63801c 100644 --- a/sublime-phpunit.py +++ b/sublime-phpunit.py @@ -149,6 +149,24 @@ def run(self, *args, **kwargs): self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + 'php artisan dusk ' + directory) +class RunPintOnCurrentFileCommand(PhpunitTestCommand): + + def find_pint_bin(self, directory): + binpath = os.path.realpath(directory + "/vendor/bin/pint") + + if os.path.isfile(binpath.replace("\\", "")): + return binpath + else: + return 'vendor/bin/pint' + + def run(self, *args, **kwargs): + file_name, phpunit_config_path, phpunit_bin, active_view, directory = self.get_paths() + + pint_bin = self.find_pint_bin(phpunit_config_path) + + self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + pint_bin + ' ' + file_name) + + class FindMatchingTestCommand(sublime_plugin.WindowCommand): def path_leaf(self, path): diff --git a/sublime-phpunit.sublime-commands b/sublime-phpunit.sublime-commands index 6a8f16d..b5190c6 100644 --- a/sublime-phpunit.sublime-commands +++ b/sublime-phpunit.sublime-commands @@ -7,5 +7,6 @@ { "caption": "Sublime PHPUnit: Run Dusk In This Directory", "command": "run_dusk_tests_in_dir" }, { "caption": "Sublime PHPUnit: Run Dusk On This File", "command": "run_dusk_test" }, { "caption": "Sublime PHPUnit: Run Dusk On This Method", "command": "run_single_dusk_test" }, - { "caption": "Sublime PHPUnit: Run All Dusk Tests", "command": "run_all_dusk_tests" } + { "caption": "Sublime PHPUnit: Run All Dusk Tests", "command": "run_all_dusk_tests" }, + { "caption": "Laravel Pint: Fix Current File", "command": "run_pint_on_current_file" } ] From 92fcde15f5c90e54aa92a834d26fef7a7b62ac37 Mon Sep 17 00:00:00 2001 From: andrew malinnikov Date: Thu, 4 Dec 2025 10:46:03 +0700 Subject: [PATCH 2/5] Stop tracking .DS_Store and ignore it --- .DS_Store | Bin 6148 -> 0 bytes .gitignore | 1 + 2 files changed, 1 insertion(+) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 3c914a3aad05cb54b6afe564d5175f74e4a6dc0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKK~BR!475umBEg|Yj{5>o)ekIDctJmaN>M>-l^)=Va^pLQPw*|q_JR^c<;VfX zl6SJUC!5S6jzvV9=gmT7E+RGDP+o1Bn&r(WHYL3@qlqFxsD0^lY>G zERZV|paN9jTLJq%B)DNN*a!Nj1B;IUK>Lk%!?n*6z+?enF4zYm0@I)ZgQ{i3(4Zrp zN?k742L@f#PsV-9$yz29_0thgUM`vgxl#ctFjn9swsY(MH}E6#|Cq!b6`%rtN&&6f zRomc|N^hOKob}oSzlDDpYP}qbw_>2TVr;AxUkvJ!T_c|h_JK}E-04962$(K3D)1W$ Fd;(`jCl&wz diff --git a/.gitignore b/.gitignore index 0d20b64..d0a113f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.pyc +.DS_Store \ No newline at end of file From 18b94066a2932925d6cb29db6755fd3068815b70 Mon Sep 17 00:00:00 2001 From: andrew malinnikov Date: Thu, 4 Dec 2025 10:47:08 +0700 Subject: [PATCH 3/5] Implment sublime auto-focus after the test is run via settings --- sublime-phpunit.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sublime-phpunit.py b/sublime-phpunit.py index d63801c..e18a597 100644 --- a/sublime-phpunit.py +++ b/sublime-phpunit.py @@ -84,6 +84,14 @@ def run_in_terminal(self, command): self.lastTestCommand = command os.system(osascript_command) + # Auto-focus Sublime Text if setting is enabled + if self.get_setting('sublime-text-autofocus', False): + self.focus_sublime_text() + + def focus_sublime_text(self): + focus_command = 'osascript -e "tell application \\"System Events\\" to keystroke tab using {command down}"' + os.system(focus_command) + class RunPhpunitTestCommand(PhpunitTestCommand): def run(self, *args, **kwargs): From 4cb318456751c648d665a11704732d2196261877 Mon Sep 17 00:00:00 2001 From: Andrew Malinnikov Date: Wed, 25 Feb 2026 12:54:46 +0700 Subject: [PATCH 4/5] Add Docker support and rename settings for consistency Wrap all test commands (PHPUnit, Dusk, Pint) with docker compose exec when phpunit-sublime-docker-service is set in project settings. Also rename sublime-text-autofocus to phpunit-sublime-autofocus-after-run. Co-Authored-By: Claude Opus 4.6 --- sublime-phpunit.py | 72 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/sublime-phpunit.py b/sublime-phpunit.py index e18a597..485137e 100644 --- a/sublime-phpunit.py +++ b/sublime-phpunit.py @@ -85,26 +85,50 @@ def run_in_terminal(self, command): os.system(osascript_command) # Auto-focus Sublime Text if setting is enabled - if self.get_setting('sublime-text-autofocus', False): + if self.get_setting('phpunit-sublime-autofocus-after-run', False): self.focus_sublime_text() def focus_sublime_text(self): focus_command = 'osascript -e "tell application \\"System Events\\" to keystroke tab using {command down}"' os.system(focus_command) + def get_docker_service(self): + view = self.window.active_view() + if view: + return view.settings().get('phpunit-sublime-docker-service') + return None + + def relative_path(self, path, base): + clean_path = path.replace('\\ ', ' ') + clean_base = base.replace('\\ ', ' ') + rel = os.path.relpath(clean_path, clean_base) + return rel.replace(' ', '\\ ') + + def docker_cmd(self, service): + return 'docker compose exec -e XDEBUG_MODE=off ' + service + class RunPhpunitTestCommand(PhpunitTestCommand): def run(self, *args, **kwargs): file_name, phpunit_config_path, phpunit_bin, active_view, directory = self.get_paths() - self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + phpunit_bin + ' ' + file_name) + docker_service = self.get_docker_service() + if docker_service: + rel_file = self.relative_path(file_name, phpunit_config_path) + self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + self.docker_cmd(docker_service) + ' php vendor/bin/phpunit ' + rel_file) + else: + self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + phpunit_bin + ' ' + file_name) class RunAllPhpunitTestsCommand(PhpunitTestCommand): def run(self, *args, **kwargs): file_name, phpunit_config_path, phpunit_bin, active_view, directory = self.get_paths() - self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + phpunit_bin) + docker_service = self.get_docker_service() + if docker_service: + self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + self.docker_cmd(docker_service) + ' php vendor/bin/phpunit') + else: + self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + phpunit_bin) class RunSinglePhpunitTestCommand(PhpunitTestCommand): @@ -114,7 +138,13 @@ def run(self, *args, **kwargs): current_function = self.get_current_function(active_view) - self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + phpunit_bin + ' ' + file_name + " --filter '/::" + current_function + "$/'") + docker_service = self.get_docker_service() + if docker_service: + rel_file = self.relative_path(file_name, phpunit_config_path) + self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + self.docker_cmd(docker_service) + ' php vendor/bin/phpunit ' + rel_file + " --filter '/::" + current_function + "$/'") + else: + self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + phpunit_bin + ' ' + file_name + " --filter '/::" + current_function + "$/'") + class RunLastPhpunitTestCommand(PhpunitTestCommand): @@ -131,7 +161,12 @@ class RunPhpunitTestsInDirCommand(PhpunitTestCommand): def run(self, *args, **kwargs): file_name, phpunit_config_path, phpunit_bin, active_view, directory = self.get_paths() - self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + phpunit_bin + ' ' + directory) + docker_service = self.get_docker_service() + if docker_service: + rel_dir = self.relative_path(directory, phpunit_config_path.replace('\\ ', ' ')) + self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + self.docker_cmd(docker_service) + ' php vendor/bin/phpunit ' + rel_dir) + else: + self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + phpunit_bin + ' ' + directory) class RunSingleDuskTestCommand(PhpunitTestCommand): @@ -140,21 +175,35 @@ def run(self, *args, **kwargs): current_function = self.get_current_function(active_view) - self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + 'php artisan dusk ' + file_name + ' --filter ' + current_function) + docker_service = self.get_docker_service() + if docker_service: + rel_file = self.relative_path(file_name, phpunit_config_path) + self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + self.docker_cmd(docker_service) + ' php artisan dusk ' + rel_file + ' --filter ' + current_function) + else: + self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + 'php artisan dusk ' + file_name + ' --filter ' + current_function) class RunAllDuskTestsCommand(PhpunitTestCommand): def run(self, *args, **kwargs): file_name, phpunit_config_path, active_view, directory = self.get_paths() - self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + 'php artisan dusk') + docker_service = self.get_docker_service() + if docker_service: + self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + self.docker_cmd(docker_service) + ' php artisan dusk') + else: + self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + 'php artisan dusk') class RunDuskTestsInDirCommand(PhpunitTestCommand): def run(self, *args, **kwargs): file_name, phpunit_config_path, active_view, directory = self.get_paths() - self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + 'php artisan dusk ' + directory) + docker_service = self.get_docker_service() + if docker_service: + rel_dir = self.relative_path(directory, phpunit_config_path.replace('\\ ', ' ')) + self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + self.docker_cmd(docker_service) + ' php artisan dusk ' + rel_dir) + else: + self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + 'php artisan dusk ' + directory) class RunPintOnCurrentFileCommand(PhpunitTestCommand): @@ -172,7 +221,12 @@ def run(self, *args, **kwargs): pint_bin = self.find_pint_bin(phpunit_config_path) - self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + pint_bin + ' ' + file_name) + docker_service = self.get_docker_service() + if docker_service: + rel_file = self.relative_path(file_name, phpunit_config_path) + self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + self.docker_cmd(docker_service) + ' php vendor/bin/pint ' + rel_file) + else: + self.run_in_terminal('cd ' + phpunit_config_path + self.get_cmd_connector() + pint_bin + ' ' + file_name) class FindMatchingTestCommand(sublime_plugin.WindowCommand): From 887adc22c7cdf74fa26034a430df41f944709c45 Mon Sep 17 00:00:00 2001 From: Andrew Malinnikov Date: Wed, 25 Feb 2026 14:02:54 +0700 Subject: [PATCH 5/5] Update readme with Docker support, autofocus setting, and missing commands Co-Authored-By: Claude Opus 4.6 --- readme.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/readme.md b/readme.md index 7cbce03..eb29b13 100644 --- a/readme.md +++ b/readme.md @@ -23,6 +23,10 @@ run_phpunit_tests_in_dir run_single_phpunit_test run_last_phpunit_test run_all_phpunit_tests +run_single_dusk_test +run_all_dusk_tests +run_dusk_tests_in_dir +run_pint_on_current_file ```` Here are some example keybindings: @@ -59,3 +63,35 @@ If you use [fish shell](https://fishshell.com/), specify this in your settings: ``` This will instruct Sublime PHPUnit to connect the commands using fish's `; and` instead of bash's `&&`. + +## Docker Support + +If your PHP project runs inside Docker, you can have all commands execute inside a container via `docker compose exec`. Add the `phpunit-sublime-docker-service` setting to your `.sublime-project` file: + +```json +{ + "settings": { + "phpunit-sublime-docker-service": "app" + } +} +``` + +Where `app` is the name of your Docker Compose service. When this setting is present, commands will be wrapped like: + +``` +cd /path/to/project && docker compose exec -e XDEBUG_MODE=off app php vendor/bin/phpunit tests/Feature/SomeTest.php +``` + +The `cd` runs on the host so `docker compose` can find your `docker-compose.yml`. File paths are automatically converted to project-relative paths for the container. + +When this setting is absent, all commands run locally as usual. + +## Auto-focus Sublime Text After Running Tests + +If you want Sublime Text to automatically regain focus after a test is triggered, enable the following setting: + +```json +{ + "phpunit-sublime-autofocus-after-run": true +} +```