Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
*.pyc
.DS_Store
36 changes: 36 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
}
```
94 changes: 87 additions & 7 deletions sublime-phpunit.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,19 +84,51 @@ 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('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):
Expand All @@ -106,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):

Expand All @@ -123,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):

Expand All @@ -132,21 +175,58 @@ 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):

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)

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):
Expand Down
3 changes: 2 additions & 1 deletion sublime-phpunit.sublime-commands
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
]