Repository: beeware/briefcase
Pull request #1988 (2024-09-08 17:57:55)

Ensure app bootstrap `AppContext` is correct
## Changes
- Noticed `AppContext` didn't actually match reality; this helps avoid that going forward

## PR Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
- [x] All new features have been tested
- [x] All new features have been documented
- [X] I have read the **CONTRIBUTING.md** file
- [X] I will abide by the code of conduct


Patch:
diff --git a/changes/1988.bugfix.rst b/changes/1988.bugfix.rst
new file mode 100644
index 00000000..c3ae5939
--- /dev/null
+++ b/changes/1988.bugfix.rst
@@ -0,0 +1,1 @@
+The typings for ``AppContext`` passed to GUI Toolkit bootstraps for creating new projects is now correct.
diff --git a/src/briefcase/bootstraps/base.py b/src/briefcase/bootstraps/base.py
index 6c15362e..2410798d 100644
--- a/src/briefcase/bootstraps/base.py
+++ b/src/briefcase/bootstraps/base.py
@@ -9,6 +9,8 @@ class AppContext(TypedDict):
     app_name: str
     class_name: str
     module_name: str
+    source_dir: str
+    test_source_dir: str
     project_name: str
     description: str
     author: str
@@ -16,9 +18,6 @@ class AppContext(TypedDict):
     bundle: str
     url: str
     license: str
-    briefcase_version: str
-    template_source: str
-    template_branch: str
 
 
 class BaseGuiBootstrap(ABC):


Test patch:
diff --git a/tests/commands/new/test_build_context.py b/tests/commands/new/test_build_context.py
index c37ff261..4a18d93b 100644
--- a/tests/commands/new/test_build_context.py
+++ b/tests/commands/new/test_build_context.py
@@ -9,6 +9,7 @@ from briefcase.bootstraps import (
     PySide6GuiBootstrap,
     TogaGuiBootstrap,
 )
+from briefcase.bootstraps.base import AppContext
 
 
 @pytest.fixture
@@ -21,6 +22,68 @@ def mock_builtin_bootstraps():
     }
 
 
+def test_question_sequence_bootstrap_context(
+    new_command,
+    mock_builtin_bootstraps,
+    monkeypatch,
+):
+    """The context passed to GUI Toolkits is correct."""
+
+    passed_context = {}
+
+    class GuiBootstrap:
+        fields = []
+
+        def __init__(self, context):
+            nonlocal passed_context
+            passed_context = context.copy()
+
+    monkeypatch.setattr(
+        briefcase.commands.new,
+        "get_gui_bootstraps",
+        MagicMock(
+            return_value=dict(
+                **mock_builtin_bootstraps,
+                **{"Custom GUI": GuiBootstrap},
+            ),
+        ),
+    )
+
+    new_command.input.enabled = False
+
+    new_command.build_context(
+        project_overrides=dict(
+            formal_name="My Override App",
+            app_name="myoverrideapp",
+            bundle="net.example",
+            project_name="My Override Project",
+            description="My override description",
+            author="override, author",
+            author_email="author@override.tld",
+            url="https://override.example.com",
+            license="MIT license",
+            bootstrap="Custom GUI",
+        ),
+    )
+
+    assert passed_context == {
+        "app_name": "myoverrideapp",
+        "author": "override, author",
+        "author_email": "author@override.tld",
+        "bundle": "net.example",
+        "class_name": "MyOverrideApp",
+        "description": "My override description",
+        "formal_name": "My Override App",
+        "license": "MIT license",
+        "module_name": "myoverrideapp",
+        "project_name": "My Override Project",
+        "source_dir": "src/myoverrideapp",
+        "test_source_dir": "tests",
+        "url": "https://override.example.com",
+    }
+    assert sorted(passed_context.keys()) == sorted(AppContext.__annotations__.keys())
+
+
 def test_question_sequence_toga(new_command):
     """Questions are asked, a context is constructed."""