jac-client 0.2.3__py3-none-any.whl → 0.2.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. jac_client/examples/all-in-one/assets/workers/worker.py +5 -0
  2. jac_client/examples/all-in-one/src/app.jac +841 -0
  3. jac_client/examples/all-in-one/{button.jac → src/button.jac} +1 -1
  4. jac_client/examples/all-in-one/{components → src/components}/button.jac +1 -1
  5. jac_client/examples/asset-serving/css-with-image/{app.jac → src/app.jac} +2 -2
  6. jac_client/examples/asset-serving/image-asset/{app.jac → src/app.jac} +2 -2
  7. jac_client/examples/asset-serving/import-alias/{app.jac → src/app.jac} +3 -3
  8. jac_client/examples/basic/{app.jac → src/app.jac} +2 -2
  9. jac_client/examples/basic-auth/src/app.jac +377 -0
  10. jac_client/examples/basic-auth-with-router/{app.jac → src/app.jac} +18 -18
  11. jac_client/examples/basic-full-stack/{app.jac → src/app.jac} +175 -130
  12. jac_client/examples/css-styling/js-styling/{app.jac → src/app.jac} +6 -6
  13. jac_client/examples/css-styling/material-ui/{app.jac → src/app.jac} +5 -5
  14. jac_client/examples/css-styling/pure-css/{app.jac → src/app.jac} +6 -6
  15. jac_client/examples/css-styling/sass-example/{app.jac → src/app.jac} +6 -6
  16. jac_client/examples/css-styling/styled-components/{app.jac → src/app.jac} +5 -5
  17. jac_client/examples/css-styling/tailwind-example/{app.jac → src/app.jac} +6 -6
  18. jac_client/examples/full-stack-with-auth/{app.jac → src/app.jac} +37 -37
  19. jac_client/examples/little-x/{app.jac → src/app.jac} +27 -32
  20. jac_client/examples/little-x/src/submit-button.jac +16 -0
  21. jac_client/examples/nested-folders/nested-advance/{ButtonRoot.jac → src/ButtonRoot.jac} +1 -1
  22. jac_client/examples/nested-folders/nested-advance/{app.jac → src/app.jac} +1 -1
  23. jac_client/examples/nested-folders/nested-advance/{level1 → src/level1}/ButtonSecondL.jac +1 -1
  24. jac_client/examples/nested-folders/nested-advance/{level1 → src/level1}/Card.jac +1 -1
  25. jac_client/examples/nested-folders/nested-advance/{level1 → src/level1}/level2/ButtonThirdL.jac +1 -1
  26. jac_client/examples/nested-folders/nested-basic/{app.jac → src/app.jac} +2 -2
  27. jac_client/examples/nested-folders/nested-basic/{button.jac → src/button.jac} +1 -1
  28. jac_client/examples/nested-folders/nested-basic/{components → src/components}/button.jac +1 -1
  29. jac_client/examples/ts-support/src/app.jac +35 -0
  30. jac_client/examples/with-router/{app.jac → src/app.jac} +11 -11
  31. jac_client/plugin/cli.jac +547 -0
  32. jac_client/plugin/client.jac +52 -0
  33. jac_client/plugin/client_runtime.cl.jac +38 -0
  34. jac_client/plugin/impl/client.impl.jac +134 -0
  35. jac_client/plugin/impl/client_runtime.impl.jac +177 -0
  36. jac_client/plugin/impl/vite_client_bundle.impl.jac +72 -0
  37. jac_client/plugin/plugin_config.jac +195 -0
  38. jac_client/plugin/src/__init__.jac +20 -0
  39. jac_client/plugin/src/asset_processor.jac +33 -0
  40. jac_client/plugin/src/babel_processor.jac +18 -0
  41. jac_client/plugin/src/compiler.jac +66 -0
  42. jac_client/plugin/src/config_loader.jac +32 -0
  43. jac_client/plugin/src/impl/asset_processor.impl.jac +127 -0
  44. jac_client/plugin/src/impl/babel_processor.impl.jac +84 -0
  45. jac_client/plugin/src/impl/compiler.impl.jac +251 -0
  46. jac_client/plugin/src/impl/config_loader.impl.jac +119 -0
  47. jac_client/plugin/src/impl/import_processor.impl.jac +33 -0
  48. jac_client/plugin/src/impl/jac_to_js.impl.jac +41 -0
  49. jac_client/plugin/src/impl/package_installer.impl.jac +105 -0
  50. jac_client/plugin/src/impl/vite_bundler.impl.jac +513 -0
  51. jac_client/plugin/src/import_processor.jac +19 -0
  52. jac_client/plugin/src/jac_to_js.jac +35 -0
  53. jac_client/plugin/src/package_installer.jac +26 -0
  54. jac_client/plugin/src/vite_bundler.jac +36 -0
  55. jac_client/plugin/vite_client_bundle.jac +31 -0
  56. jac_client/tests/conftest.py +281 -0
  57. jac_client/tests/fixtures/basic-app/app.jac +2 -2
  58. jac_client/tests/fixtures/cl_file/app.cl.jac +2 -2
  59. jac_client/tests/fixtures/client_app_with_antd/app.jac +1 -1
  60. jac_client/tests/fixtures/js_import/app.jac +5 -5
  61. jac_client/tests/fixtures/spawn_test/app.jac +7 -7
  62. jac_client/tests/fixtures/with-ts/app.jac +35 -0
  63. jac_client/tests/test_cli.py +755 -0
  64. jac_client/tests/test_it.py +347 -67
  65. {jac_client-0.2.3.dist-info → jac_client-0.2.5.dist-info}/METADATA +28 -30
  66. jac_client-0.2.5.dist-info/RECORD +74 -0
  67. {jac_client-0.2.3.dist-info → jac_client-0.2.5.dist-info}/WHEEL +2 -1
  68. jac_client-0.2.5.dist-info/entry_points.txt +4 -0
  69. jac_client-0.2.5.dist-info/top_level.txt +1 -0
  70. jac_client/docs/README.md +0 -689
  71. jac_client/docs/advanced-state.md +0 -1265
  72. jac_client/docs/asset-serving/intro.md +0 -209
  73. jac_client/docs/assets/pipe_line-v2.svg +0 -32
  74. jac_client/docs/assets/pipe_line.png +0 -0
  75. jac_client/docs/file-system/app.jac.md +0 -121
  76. jac_client/docs/file-system/backend-frontend.md +0 -217
  77. jac_client/docs/file-system/intro.md +0 -72
  78. jac_client/docs/file-system/nested-imports.md +0 -348
  79. jac_client/docs/guide-example/intro.md +0 -115
  80. jac_client/docs/guide-example/step-01-setup.md +0 -270
  81. jac_client/docs/guide-example/step-02-components.md +0 -416
  82. jac_client/docs/guide-example/step-03-styling.md +0 -478
  83. jac_client/docs/guide-example/step-04-todo-ui.md +0 -477
  84. jac_client/docs/guide-example/step-05-local-state.md +0 -530
  85. jac_client/docs/guide-example/step-06-events.md +0 -749
  86. jac_client/docs/guide-example/step-07-effects.md +0 -468
  87. jac_client/docs/guide-example/step-08-walkers.md +0 -534
  88. jac_client/docs/guide-example/step-09-authentication.md +0 -586
  89. jac_client/docs/guide-example/step-10-routing.md +0 -539
  90. jac_client/docs/guide-example/step-11-final.md +0 -963
  91. jac_client/docs/imports.md +0 -1141
  92. jac_client/docs/lifecycle-hooks.md +0 -773
  93. jac_client/docs/routing.md +0 -659
  94. jac_client/docs/styling/intro.md +0 -249
  95. jac_client/docs/styling/js-styling.md +0 -367
  96. jac_client/docs/styling/material-ui.md +0 -341
  97. jac_client/docs/styling/pure-css.md +0 -299
  98. jac_client/docs/styling/sass.md +0 -403
  99. jac_client/docs/styling/styled-components.md +0 -395
  100. jac_client/docs/styling/tailwind.md +0 -298
  101. jac_client/examples/all-in-one/.babelrc +0 -9
  102. jac_client/examples/all-in-one/README.md +0 -16
  103. jac_client/examples/all-in-one/app.jac +0 -426
  104. jac_client/examples/all-in-one/assets/burger.png +0 -0
  105. jac_client/examples/all-in-one/package.json +0 -29
  106. jac_client/examples/all-in-one/styles.css +0 -26
  107. jac_client/examples/all-in-one/vite.config.js +0 -28
  108. jac_client/examples/asset-serving/css-with-image/.babelrc +0 -9
  109. jac_client/examples/asset-serving/css-with-image/README.md +0 -91
  110. jac_client/examples/asset-serving/css-with-image/assets/burger.png +0 -0
  111. jac_client/examples/asset-serving/css-with-image/package.json +0 -28
  112. jac_client/examples/asset-serving/css-with-image/styles.css +0 -26
  113. jac_client/examples/asset-serving/css-with-image/vite.config.js +0 -28
  114. jac_client/examples/asset-serving/image-asset/.babelrc +0 -9
  115. jac_client/examples/asset-serving/image-asset/README.md +0 -119
  116. jac_client/examples/asset-serving/image-asset/assets/burger.png +0 -0
  117. jac_client/examples/asset-serving/image-asset/package.json +0 -28
  118. jac_client/examples/asset-serving/image-asset/styles.css +0 -26
  119. jac_client/examples/asset-serving/image-asset/vite.config.js +0 -28
  120. jac_client/examples/asset-serving/import-alias/.babelrc +0 -9
  121. jac_client/examples/asset-serving/import-alias/README.md +0 -83
  122. jac_client/examples/asset-serving/import-alias/assets/burger.png +0 -0
  123. jac_client/examples/asset-serving/import-alias/package.json +0 -28
  124. jac_client/examples/asset-serving/import-alias/vite.config.js +0 -28
  125. jac_client/examples/basic/.babelrc +0 -9
  126. jac_client/examples/basic/README.md +0 -16
  127. jac_client/examples/basic/package.json +0 -27
  128. jac_client/examples/basic/vite.config.js +0 -27
  129. jac_client/examples/basic-auth/.babelrc +0 -9
  130. jac_client/examples/basic-auth/README.md +0 -16
  131. jac_client/examples/basic-auth/app.jac +0 -308
  132. jac_client/examples/basic-auth/package.json +0 -27
  133. jac_client/examples/basic-auth/vite.config.js +0 -27
  134. jac_client/examples/basic-auth-with-router/.babelrc +0 -9
  135. jac_client/examples/basic-auth-with-router/README.md +0 -60
  136. jac_client/examples/basic-auth-with-router/package.json +0 -28
  137. jac_client/examples/basic-auth-with-router/vite.config.js +0 -27
  138. jac_client/examples/basic-full-stack/.babelrc +0 -9
  139. jac_client/examples/basic-full-stack/README.md +0 -18
  140. jac_client/examples/basic-full-stack/package.json +0 -28
  141. jac_client/examples/basic-full-stack/vite.config.js +0 -27
  142. jac_client/examples/css-styling/js-styling/.babelrc +0 -9
  143. jac_client/examples/css-styling/js-styling/README.md +0 -183
  144. jac_client/examples/css-styling/js-styling/package.json +0 -28
  145. jac_client/examples/css-styling/js-styling/styles.js +0 -100
  146. jac_client/examples/css-styling/js-styling/vite.config.js +0 -27
  147. jac_client/examples/css-styling/material-ui/.babelrc +0 -9
  148. jac_client/examples/css-styling/material-ui/README.md +0 -16
  149. jac_client/examples/css-styling/material-ui/package.json +0 -32
  150. jac_client/examples/css-styling/material-ui/vite.config.js +0 -27
  151. jac_client/examples/css-styling/pure-css/.babelrc +0 -9
  152. jac_client/examples/css-styling/pure-css/README.md +0 -16
  153. jac_client/examples/css-styling/pure-css/package.json +0 -28
  154. jac_client/examples/css-styling/pure-css/styles.css +0 -111
  155. jac_client/examples/css-styling/pure-css/vite.config.js +0 -27
  156. jac_client/examples/css-styling/sass-example/.babelrc +0 -9
  157. jac_client/examples/css-styling/sass-example/README.md +0 -16
  158. jac_client/examples/css-styling/sass-example/package.json +0 -29
  159. jac_client/examples/css-styling/sass-example/styles.scss +0 -153
  160. jac_client/examples/css-styling/sass-example/vite.config.js +0 -27
  161. jac_client/examples/css-styling/styled-components/.babelrc +0 -9
  162. jac_client/examples/css-styling/styled-components/README.md +0 -16
  163. jac_client/examples/css-styling/styled-components/package.json +0 -29
  164. jac_client/examples/css-styling/styled-components/styled.js +0 -90
  165. jac_client/examples/css-styling/styled-components/vite.config.js +0 -27
  166. jac_client/examples/css-styling/tailwind-example/.babelrc +0 -9
  167. jac_client/examples/css-styling/tailwind-example/README.md +0 -16
  168. jac_client/examples/css-styling/tailwind-example/global.css +0 -1
  169. jac_client/examples/css-styling/tailwind-example/package.json +0 -30
  170. jac_client/examples/css-styling/tailwind-example/vite.config.js +0 -29
  171. jac_client/examples/full-stack-with-auth/.babelrc +0 -9
  172. jac_client/examples/full-stack-with-auth/README.md +0 -16
  173. jac_client/examples/full-stack-with-auth/package.json +0 -28
  174. jac_client/examples/full-stack-with-auth/vite.config.js +0 -29
  175. jac_client/examples/little-x/package.json +0 -23
  176. jac_client/examples/little-x/submit-button.jac +0 -8
  177. jac_client/examples/nested-folders/nested-advance/.babelrc +0 -9
  178. jac_client/examples/nested-folders/nested-advance/README.md +0 -77
  179. jac_client/examples/nested-folders/nested-advance/package.json +0 -29
  180. jac_client/examples/nested-folders/nested-advance/vite.config.js +0 -28
  181. jac_client/examples/nested-folders/nested-basic/.babelrc +0 -9
  182. jac_client/examples/nested-folders/nested-basic/README.md +0 -183
  183. jac_client/examples/nested-folders/nested-basic/app.js +0 -7
  184. jac_client/examples/nested-folders/nested-basic/package.json +0 -28
  185. jac_client/examples/nested-folders/nested-basic/vite.config.js +0 -27
  186. jac_client/examples/with-router/.babelrc +0 -9
  187. jac_client/examples/with-router/README.md +0 -17
  188. jac_client/examples/with-router/package.json +0 -28
  189. jac_client/examples/with-router/vite.config.js +0 -27
  190. jac_client/plugin/cli.py +0 -244
  191. jac_client/plugin/client.py +0 -152
  192. jac_client/plugin/client_runtime.jac +0 -234
  193. jac_client/plugin/vite_client_bundle.py +0 -503
  194. jac_client/tests/fixtures/js_import/utils.js +0 -21
  195. jac_client/tests/fixtures/package-lock.json +0 -329
  196. jac_client/tests/fixtures/package.json +0 -11
  197. jac_client/tests/test_asset_examples.py +0 -322
  198. jac_client/tests/test_cl.py +0 -530
  199. jac_client/tests/test_create_jac_app.py +0 -131
  200. jac_client/tests/test_nested_file.py +0 -374
  201. jac_client-0.2.3.dist-info/RECORD +0 -171
  202. jac_client-0.2.3.dist-info/entry_points.txt +0 -4
@@ -0,0 +1,281 @@
1
+ """Pytest configuration and shared fixtures for jac-client tests.
2
+
3
+ This module provides session-scoped fixtures to optimize test execution by:
4
+ 1. Running npm install once per session and caching node_modules
5
+ 2. Providing shared Vite build infrastructure
6
+ 3. Mocking npm install for tests that only need jac.toml manipulation
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import contextlib
12
+ import os
13
+ import shutil
14
+ import subprocess
15
+ import sys
16
+ import tempfile
17
+ from collections.abc import Generator
18
+ from pathlib import Path
19
+ from unittest.mock import patch
20
+
21
+ import pytest
22
+
23
+ from jaclang.pycore.runtime import JacRuntime as Jac
24
+ from jaclang.pycore.runtime import JacRuntimeImpl, plugin_manager
25
+
26
+ # Store unregistered plugins globally for session-level management
27
+ _external_plugins: list = []
28
+
29
+
30
+ def pytest_configure(config: pytest.Config) -> None:
31
+ """Disable jac-scale plugin at the start of the test session.
32
+
33
+ jac-scale plugin is disabled during tests to avoid MongoDB connections
34
+ and other jac-scale specific dependencies. jac-client plugin is kept
35
+ enabled since we're testing it.
36
+ """
37
+ global _external_plugins
38
+ for name, plugin in list(plugin_manager.list_name_plugin()):
39
+ # Keep core runtime and jac-client plugins
40
+ if plugin is JacRuntimeImpl or name == "JacRuntimeImpl":
41
+ continue
42
+ if "client" in name.lower() or "JacClient" in str(type(plugin)):
43
+ continue
44
+ # Disable jac-scale and other external plugins
45
+ _external_plugins.append((name, plugin))
46
+ plugin_manager.unregister(plugin=plugin, name=name)
47
+
48
+
49
+ def pytest_unconfigure(config: pytest.Config) -> None:
50
+ """Re-register external plugins at the end of the test session."""
51
+ global _external_plugins
52
+ for name, plugin in _external_plugins:
53
+ with contextlib.suppress(ValueError):
54
+ plugin_manager.register(plugin, name=name)
55
+ _external_plugins.clear()
56
+
57
+
58
+ def _get_jac_command() -> list[str]:
59
+ """Get the jac command with proper path handling."""
60
+ # Try to find jac in PATH or use python -m jaclang
61
+ jac_path = shutil.which("jac")
62
+ if jac_path:
63
+ return [jac_path]
64
+ # Fall back to running via python module
65
+ return [sys.executable, "-m", "jaclang"]
66
+
67
+
68
+ def _get_env_with_npm() -> dict[str, str]:
69
+ """Get environment dict with npm in PATH."""
70
+ env = os.environ.copy()
71
+ # npm might be installed via nvm, ensure PATH includes common locations
72
+ npm_path = shutil.which("npm")
73
+ if npm_path:
74
+ npm_dir = str(Path(npm_path).parent)
75
+ current_path = env.get("PATH", "")
76
+ if npm_dir not in current_path:
77
+ env["PATH"] = f"{npm_dir}:{current_path}"
78
+ return env
79
+
80
+
81
+ @pytest.fixture(autouse=True)
82
+ def reset_jac_machine() -> Generator[None, None, None]:
83
+ """Reset Jac machine before and after each test."""
84
+ Jac.reset_machine()
85
+ yield
86
+ Jac.reset_machine()
87
+
88
+
89
+ # Session-scoped cache for npm installation
90
+ _npm_cache_dir: Path | None = None
91
+
92
+
93
+ def _get_minimal_jac_toml() -> str:
94
+ """Get minimal jac.toml content for npm cache setup."""
95
+ return """[project]
96
+ name = "npm-cache"
97
+ version = "0.0.1"
98
+ description = "Cached npm modules"
99
+ entry-point = "app.jac"
100
+
101
+ [plugins.client.vite.build]
102
+ minify = false
103
+ """
104
+
105
+
106
+ @pytest.fixture(scope="session")
107
+ def npm_cache_dir() -> Generator[Path, None, None]:
108
+ """Session-scoped fixture that provides a directory with npm packages installed.
109
+
110
+ This runs npm install once per test session and provides the path to the
111
+ .jac-client.configs directory containing node_modules.
112
+ """
113
+ global _npm_cache_dir
114
+
115
+ if _npm_cache_dir is not None and _npm_cache_dir.exists():
116
+ yield _npm_cache_dir
117
+ return
118
+
119
+ # Create a persistent temp directory for the session
120
+ cache_dir = Path(tempfile.mkdtemp(prefix="jac_npm_cache_"))
121
+
122
+ # Create jac.toml
123
+ jac_toml = cache_dir / "jac.toml"
124
+ jac_toml.write_text(_get_minimal_jac_toml())
125
+
126
+ # Run jac add --cl to install packages
127
+ jac_cmd = _get_jac_command()
128
+ env = _get_env_with_npm()
129
+ result = subprocess.run(
130
+ [*jac_cmd, "add", "--cl"],
131
+ cwd=cache_dir,
132
+ capture_output=True,
133
+ text=True,
134
+ env=env,
135
+ )
136
+
137
+ if result.returncode != 0:
138
+ # Clean up on failure
139
+ shutil.rmtree(cache_dir, ignore_errors=True)
140
+ pytest.skip(f"Failed to set up npm cache: {result.stderr}")
141
+
142
+ _npm_cache_dir = cache_dir
143
+ yield cache_dir
144
+
145
+ # Cleanup after all tests complete
146
+ shutil.rmtree(cache_dir, ignore_errors=True)
147
+
148
+
149
+ @pytest.fixture
150
+ def vite_project_dir(npm_cache_dir: Path, tmp_path: Path) -> Path:
151
+ """Fixture that provides a project directory with pre-installed node_modules.
152
+
153
+ This copies node_modules from the session cache instead of running npm install.
154
+ """
155
+ # Create jac.toml in the temp directory
156
+ jac_toml = tmp_path / "jac.toml"
157
+ jac_toml.write_text(_get_minimal_jac_toml())
158
+
159
+ # Copy .jac-client.configs directory (contains package.json)
160
+ source_configs = npm_cache_dir / ".jac-client.configs"
161
+ dest_configs = tmp_path / ".jac-client.configs"
162
+ if source_configs.exists():
163
+ shutil.copytree(source_configs, dest_configs, symlinks=True)
164
+
165
+ # Copy node_modules from project root (npm installs there, not in .jac-client.configs)
166
+ source_node_modules = npm_cache_dir / "node_modules"
167
+ dest_node_modules = tmp_path / "node_modules"
168
+ if source_node_modules.exists():
169
+ shutil.copytree(source_node_modules, dest_node_modules, symlinks=True)
170
+
171
+ # Create required directories
172
+ (tmp_path / "dist").mkdir(exist_ok=True)
173
+ (tmp_path / "compiled").mkdir(exist_ok=True)
174
+ (tmp_path / "build").mkdir(exist_ok=True)
175
+
176
+ return tmp_path
177
+
178
+
179
+ @pytest.fixture
180
+ def vite_project_with_antd(npm_cache_dir: Path, tmp_path: Path) -> Path:
181
+ """Fixture that provides a project directory with antd pre-installed."""
182
+ # Create jac.toml with antd dependency
183
+ jac_toml_content = """[project]
184
+ name = "antd-test"
185
+ version = "0.0.1"
186
+ description = "Test project with antd"
187
+ entry-point = "app.jac"
188
+
189
+ [plugins.client.vite.build]
190
+ minify = false
191
+
192
+ [dependencies.npm]
193
+ antd = "^6.0.0"
194
+ """
195
+ jac_toml = tmp_path / "jac.toml"
196
+ jac_toml.write_text(jac_toml_content)
197
+
198
+ # Copy base .jac-client.configs first for faster install
199
+ source_configs = npm_cache_dir / ".jac-client.configs"
200
+ dest_configs = tmp_path / ".jac-client.configs"
201
+ if source_configs.exists():
202
+ shutil.copytree(source_configs, dest_configs, symlinks=True)
203
+
204
+ # Copy base node_modules for faster install (npm will add antd on top)
205
+ source_node_modules = npm_cache_dir / "node_modules"
206
+ dest_node_modules = tmp_path / "node_modules"
207
+ if source_node_modules.exists():
208
+ shutil.copytree(source_node_modules, dest_node_modules, symlinks=True)
209
+
210
+ # Install antd on top (uses cached node_modules as base)
211
+ jac_cmd = _get_jac_command()
212
+ env = _get_env_with_npm()
213
+ result = subprocess.run(
214
+ [*jac_cmd, "add", "--cl"],
215
+ cwd=tmp_path,
216
+ capture_output=True,
217
+ text=True,
218
+ env=env,
219
+ )
220
+ if result.returncode != 0:
221
+ pytest.skip(f"Failed to install antd: {result.stderr}")
222
+
223
+ # Create required directories
224
+ (tmp_path / "dist").mkdir(exist_ok=True)
225
+ (tmp_path / "compiled").mkdir(exist_ok=True)
226
+ (tmp_path / "build").mkdir(exist_ok=True)
227
+
228
+ return tmp_path
229
+
230
+
231
+ @pytest.fixture
232
+ def mock_npm_install():
233
+ """Fixture that mocks npm install for tests that only test jac.toml manipulation.
234
+
235
+ Use this for CLI tests (add/remove commands) that don't need actual npm packages.
236
+ """
237
+ with patch(
238
+ "jac_client.plugin.src.package_installer.PackageInstaller._regenerate_and_install"
239
+ ) as mock:
240
+ yield mock
241
+
242
+
243
+ @pytest.fixture
244
+ def cli_test_dir(tmp_path: Path) -> Path:
245
+ """Fixture that provides a minimal test directory for CLI tests."""
246
+ return tmp_path
247
+
248
+
249
+ def create_test_jac_toml(
250
+ path: Path,
251
+ deps: str = "",
252
+ dev_deps: str = "",
253
+ name: str = "test-project",
254
+ ) -> Path:
255
+ """Helper to create a jac.toml file for testing.
256
+
257
+ Args:
258
+ path: Directory to create jac.toml in
259
+ deps: Dependencies to add (TOML format, e.g., 'lodash = "^4.17.21"')
260
+ dev_deps: Dev dependencies to add (TOML format)
261
+ name: Project name
262
+
263
+ Returns:
264
+ Path to the created jac.toml file
265
+ """
266
+ deps_section = f"\n{deps}" if deps else ""
267
+ dev_deps_section = f"\n{dev_deps}" if dev_deps else ""
268
+
269
+ content = f"""[project]
270
+ name = "{name}"
271
+ version = "1.0.0"
272
+ description = "Test project"
273
+ entry-point = "app.jac"
274
+
275
+ [dependencies.npm]{deps_section}
276
+
277
+ [dev-dependencies.npm]{dev_deps_section}
278
+ """
279
+ config_path = path / "jac.toml"
280
+ config_path.write_text(content)
281
+ return config_path
@@ -1,6 +1,6 @@
1
1
  """Sample Jac module containing client-side declarations."""
2
2
 
3
- cl let API_LABEL: str = "Runtime Test";
3
+ cl glob API_LABEL: str = "Runtime Test";
4
4
 
5
5
  cl obj ButtonProps {
6
6
  has label: str = "Tap Me";
@@ -8,7 +8,7 @@ cl obj ButtonProps {
8
8
  }
9
9
 
10
10
  cl def app() {
11
- let props = ButtonProps(label="Tap Me", color="primary");
11
+ props = ButtonProps(label="Tap Me", color="primary");
12
12
  return <div class="app">
13
13
  <h1>
14
14
  {API_LABEL}
@@ -1,8 +1,8 @@
1
1
  import from react { useState }
2
2
 
3
3
  def app() -> any {
4
- let [todos, setTodos] = useState([]);
5
- let [input, setInput] = useState("");
4
+ [todos, setTodos] = useState([]);
5
+ [input, setInput] = useState("");
6
6
 
7
7
  # Event Handler
8
8
  async def addTodo() -> None {
@@ -2,7 +2,7 @@
2
2
 
3
3
  cl import from antd { Button }
4
4
 
5
- cl let APP_NAME: str = "Ant Design Test";
5
+ cl glob APP_NAME: str = "Ant Design Test";
6
6
 
7
7
  cl def ButtonTest() {
8
8
  return <div>
@@ -2,13 +2,13 @@
2
2
 
3
3
  cl import from .utils { formatMessage, calculateSum, JS_CONSTANT, MessageFormatter }
4
4
 
5
- cl let JS_IMPORT_LABEL: str = "JavaScript Import Test";
5
+ cl glob JS_IMPORT_LABEL: str = "JavaScript Import Test";
6
6
 
7
7
  cl def JsImportTest() -> any {
8
- let greeting = formatMessage("Jac");
9
- let sum = calculateSum(5, 3);
10
- let formatter = MessageFormatter("JS");
11
- let formatted = formatter.format("Hello from JS class");
8
+ greeting = formatMessage("Jac");
9
+ sum = calculateSum(5, 3);
10
+ formatter = MessageFormatter("JS");
11
+ formatted = formatter.format("Hello from JS class");
12
12
 
13
13
  return <div class="js-import-test">
14
14
  <h1>
@@ -39,13 +39,13 @@ cl import from react {
39
39
 
40
40
  cl {
41
41
  def app() -> any {
42
- let [standardResult, setStandardResult] = useState(None);
43
- let [standardComputed, setStandardComputed] = useState(None);
44
- let [reverseResult, setReverseResult] = useState(None);
45
- let [uuidResult, setUuidResult] = useState(None);
46
- let [reverseUuidResult, setReverseUuidResult] = useState(None);
47
- let [positionalResult, setPositionalResult] = useState(None);
48
- let [spreadResult, setSpreadResult] = useState(None);
42
+ [standardResult, setStandardResult] = useState(None);
43
+ [standardComputed, setStandardComputed] = useState(None);
44
+ [reverseResult, setReverseResult] = useState(None);
45
+ [uuidResult, setUuidResult] = useState(None);
46
+ [reverseUuidResult, setReverseUuidResult] = useState(None);
47
+ [positionalResult, setPositionalResult] = useState(None);
48
+ [spreadResult, setSpreadResult] = useState(None);
49
49
 
50
50
  async def loadData() -> None {
51
51
  # Test standard spawn order: node spawn walker()
@@ -0,0 +1,35 @@
1
+
2
+ # Pages
3
+ cl import from react { useState, useEffect }
4
+ cl import from ".components/Button.tsx" { Button }
5
+
6
+ cl {
7
+ def app() -> any {
8
+ [count, setCount] = useState(0);
9
+ useEffect(lambda -> None{ console.log("Count: ", count);} , [count]);
10
+ return <div
11
+ style={{padding: "2rem", fontFamily: "Arial, sans-serif"}}
12
+ >
13
+ <h1>
14
+ Hello, World!
15
+ </h1>
16
+ <p>
17
+ Count: {count}
18
+ </p>
19
+ <div
20
+ style={{display: "flex", gap: "1rem", marginTop: "1rem"}}
21
+ >
22
+ <Button
23
+ label="Increment"
24
+ onClick={lambda -> None{ setCount(count + 1);} }
25
+ variant="primary"
26
+ />
27
+ <Button
28
+ label="Reset"
29
+ onClick={lambda -> None{ setCount(0);} }
30
+ variant="secondary"
31
+ />
32
+ </div>
33
+ </div>;
34
+ }
35
+ }