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
155 changes: 155 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# pipenv
Pipfile.lock

# Poetry
# poetry.lock is deliberately not ignored - it should be committed

# PEP 582
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# IDE files
.vscode/
.idea/
*.swp
*.swo
*~
.DS_Store

# Claude settings
.claude/*

# Sublime Text
*.sublime-project
*.sublime-workspace

# Testing artifacts
.pytest_cache/
.coverage
htmlcov/
coverage.xml
*.cover
.hypothesis/

# Virtual environments
venv/
.venv/
env/
.env/
282 changes: 282 additions & 0 deletions poetry.lock

Large diffs are not rendered by default.

78 changes: 78 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
[tool.poetry]
name = "all-autocomplete"
version = "0.1.0"
description = "Extends the default autocomplete to find matches in all open files"
authors = ["Your Name <[email protected]>"]
license = "WTFPL"
readme = "README.md"
packages = [{include = "all_views_completions.py"}]

[tool.poetry.dependencies]
python = "^3.8"

[tool.poetry.group.dev.dependencies]
pytest = "^8.0.0"
pytest-cov = "^5.0.0"
pytest-mock = "^3.14.0"

[tool.poetry.scripts]
test = "pytest:main"
tests = "pytest:main"

[tool.pytest.ini_options]
minversion = "8.0"
testpaths = ["tests"]
python_files = ["test_*.py", "*_test.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
"-ra",
"--strict-markers",
"--strict-config",
"--cov=all_views_completions",
"--cov-branch",
"--cov-report=term-missing:skip-covered",
"--cov-report=html:htmlcov",
"--cov-report=xml:coverage.xml",
"--cov-fail-under=80",
]
markers = [
"unit: Unit tests",
"integration: Integration tests",
"slow: Slow running tests",
]

[tool.coverage.run]
source = ["all_views_completions"]
branch = true
omit = [
"*/tests/*",
"*/__pycache__/*",
"*/venv/*",
"*/.venv/*",
]

[tool.coverage.report]
precision = 2
show_missing = true
skip_covered = false
exclude_lines = [
"pragma: no cover",
"def __repr__",
"raise AssertionError",
"raise NotImplementedError",
"if __name__ == .__main__.:",
"if TYPE_CHECKING:",
"class .*\\bProtocol\\):",
"@(abc\\.)?abstractmethod",
]

[tool.coverage.html]
directory = "htmlcov"

[tool.coverage.xml]
output = "coverage.xml"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
Empty file added tests/__init__.py
Empty file.
148 changes: 148 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
"""
Shared pytest fixtures for testing the All Autocomplete Sublime Text plugin.
"""
import json
import os
import sys
import tempfile
from pathlib import Path
from unittest.mock import MagicMock, Mock

import pytest


sys.modules['sublime'] = MagicMock()
sys.modules['sublime_plugin'] = MagicMock()


@pytest.fixture
def mock_sublime():
"""Mock the sublime module with common functionality."""
sublime_mock = MagicMock()

sublime_mock.HOVER_TEXT = 1
sublime_mock.HOVER_GUTTER = 2
sublime_mock.HOVER_MARGIN = 3

sublime_mock.load_settings.return_value = MagicMock()

sys.modules['sublime'] = sublime_mock
return sublime_mock


@pytest.fixture
def mock_sublime_plugin():
"""Mock the sublime_plugin module."""
plugin_mock = MagicMock()

class MockEventListener:
pass

plugin_mock.EventListener = MockEventListener

sys.modules['sublime_plugin'] = plugin_mock
return plugin_mock


@pytest.fixture
def temp_dir():
"""Create a temporary directory for test files."""
with tempfile.TemporaryDirectory() as tmpdir:
yield Path(tmpdir)


@pytest.fixture
def mock_settings():
"""Mock Sublime Text settings object."""
settings = MagicMock()
settings.get.side_effect = lambda key, default=None: {
'min_word_size': 3,
'max_word_size': 50,
'exclude_from_completion': [],
'exclude_sources': [],
'disabled_by_default': False,
'maximum_words_per_view': 100,
'maximum_views': 20,
}.get(key, default)
return settings


@pytest.fixture
def mock_view():
"""Mock a Sublime Text view object."""
view = MagicMock()
view.id.return_value = 1234
view.size.return_value = 1000
view.settings.return_value = MagicMock()
view.window.return_value = MagicMock()

region_mock = MagicMock()
region_mock.a = 0
region_mock.b = 100

view.sel.return_value = [region_mock]
view.substr.return_value = "sample text content"
view.file_name.return_value = "/path/to/file.py"

return view


@pytest.fixture
def mock_window():
"""Mock a Sublime Text window object."""
window = MagicMock()
window.id.return_value = 5678
window.views.return_value = []
return window


@pytest.fixture
def sample_completions():
"""Sample completion data for testing."""
return [
("function", "function"),
("variable", "variable"),
("constant", "constant"),
("TestClass", "TestClass"),
("test_method", "test_method"),
]


@pytest.fixture
def plugin_settings_file(temp_dir):
"""Create a temporary plugin settings file."""
settings_content = {
"min_word_size": 3,
"max_word_size": 50,
"exclude_from_completion": [
"css",
"html"
],
"exclude_sources": [],
"disabled_by_default": False
}

settings_path = temp_dir / "All Autocomplete.sublime-settings"
settings_path.write_text(json.dumps(settings_content, indent=4))
return settings_path


@pytest.fixture
def mock_region():
"""Mock a Sublime Text Region object."""
def _region(a, b):
region = MagicMock()
region.a = a
region.b = b
return region
return _region


@pytest.fixture(autouse=True)
def reset_modules():
"""Reset mocked modules after each test."""
yield
if 'sublime' in sys.modules:
sys.modules['sublime'] = MagicMock()
if 'sublime_plugin' in sys.modules:
sys.modules['sublime_plugin'] = MagicMock()
Empty file added tests/integration/__init__.py
Empty file.
Loading