jac-client 0.2.2__py3-none-any.whl → 0.2.6__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} +7 -7
  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.2.dist-info → jac_client-0.2.6.dist-info}/METADATA +30 -24
  66. jac_client-0.2.6.dist-info/RECORD +74 -0
  67. {jac_client-0.2.2.dist-info → jac_client-0.2.6.dist-info}/WHEEL +2 -1
  68. jac_client-0.2.6.dist-info/entry_points.txt +4 -0
  69. jac_client-0.2.6.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.2.dist-info/RECORD +0 -171
  202. jac_client-0.2.2.dist-info/entry_points.txt +0 -4
@@ -1,530 +0,0 @@
1
- """Tests for Vite client bundle generation."""
2
-
3
- from __future__ import annotations
4
-
5
- import json
6
- import subprocess
7
- import tempfile
8
- from pathlib import Path
9
-
10
- import pytest
11
-
12
- from jac_client.plugin.vite_client_bundle import ViteClientBundleBuilder
13
- from jaclang.runtimelib.runtime import JacRuntime as Jac
14
-
15
-
16
- @pytest.fixture(autouse=True)
17
- def reset_jac_machine():
18
- """Reset Jac machine before and after each test."""
19
- Jac.reset_machine()
20
- yield
21
- Jac.reset_machine()
22
-
23
-
24
- def _create_test_project_with_vite(
25
- temp_path: Path, include_antd: bool = False
26
- ) -> tuple[Path, Path]:
27
- """Create a minimal test project with Vite installed.
28
-
29
- Args:
30
- temp_path: Path to the temporary directory
31
- include_antd: If True, includes antd in dependencies
32
- """
33
- # Create package.json with base dependencies
34
- dependencies = {
35
- "react": "^19.2.0",
36
- "react-dom": "^19.2.0",
37
- "react-router-dom": "^7.3.0",
38
- }
39
-
40
- # Add antd if requested
41
- if include_antd:
42
- dependencies["antd"] = "^5.0.0"
43
-
44
- # Create package.json structure
45
- package_data = {
46
- "name": "test-client",
47
- "version": "0.0.1",
48
- "type": "module",
49
- "scripts": {
50
- "build": "npm run compile && vite build",
51
- "dev": "vite dev",
52
- "preview": "vite preview",
53
- "compile": 'babel src --out-dir build --extensions ".jsx,.js" --out-file-extension .js',
54
- },
55
- "dependencies": dependencies,
56
- "devDependencies": {
57
- "vite": "^6.4.1",
58
- "@babel/cli": "^7.28.3",
59
- "@babel/core": "^7.28.5",
60
- "@babel/preset-env": "^7.28.5",
61
- "@babel/preset-react": "^7.28.5",
62
- },
63
- }
64
-
65
- package_json = temp_path / "package.json"
66
- with package_json.open("w", encoding="utf-8") as f:
67
- json.dump(package_data, f, indent=2)
68
-
69
- # Create .babelrc file
70
- babelrc = temp_path / ".babelrc"
71
- babelrc.write_text(
72
- """{
73
- "presets": [[
74
- "@babel/preset-env",
75
- {
76
- "modules": false
77
- }
78
- ], "@babel/preset-react"]
79
- }
80
- """,
81
- encoding="utf-8",
82
- )
83
-
84
- # Create vite.config.js file
85
- vite_config = temp_path / "vite.config.js"
86
- vite_config.write_text(
87
- """import { defineConfig } from "vite";
88
- import path from "path";
89
- import { fileURLToPath } from "url";
90
-
91
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
92
-
93
- export default defineConfig({
94
- root: ".",
95
- build: {
96
- rollupOptions: {
97
- input: "build/main.js",
98
- output: {
99
- entryFileNames: "client.[hash].js",
100
- assetFileNames: "[name].[ext]",
101
- },
102
- },
103
- outDir: "dist",
104
- emptyOutDir: true,
105
- minify: false,
106
- },
107
- publicDir: false,
108
- resolve: {
109
- alias: {
110
- "@jac-client/utils": path.resolve(__dirname, "src/client_runtime.js"),
111
- },
112
- },
113
- });
114
- """,
115
- encoding="utf-8",
116
- )
117
-
118
- # Install dependencies
119
- result = subprocess.run(
120
- ["npm", "install"],
121
- cwd=temp_path,
122
- check=False,
123
- capture_output=True,
124
- text=True,
125
- )
126
- if result.returncode != 0:
127
- error_msg = f"npm install failed with exit code {result.returncode}\n"
128
- error_msg += f"stdout: {result.stdout}\n"
129
- error_msg += f"stderr: {result.stderr}\n"
130
- raise RuntimeError(error_msg)
131
-
132
- # Create output directory
133
- output_dir = temp_path / "dist"
134
- output_dir.mkdir(parents=True, exist_ok=True)
135
-
136
- src_dir = temp_path / "src"
137
- src_dir.mkdir(parents=True, exist_ok=True)
138
-
139
- build_dir = temp_path / "build"
140
- build_dir.mkdir(parents=True, exist_ok=True)
141
-
142
- return package_json, output_dir
143
-
144
-
145
- def test_build_bundle_with_vite() -> None:
146
- """Test that Vite bundling produces optimized output with proper structure."""
147
- # Create a temporary directory for our test project
148
- with tempfile.TemporaryDirectory() as temp_dir:
149
- temp_path = Path(temp_dir)
150
-
151
- package_json, output_dir = _create_test_project_with_vite(temp_path)
152
- runtime_path = Path(__file__).parent.parent / "plugin" / "client_runtime.jac"
153
- # Initialize the Vite builder
154
- builder = ViteClientBundleBuilder(
155
- runtime_path=runtime_path,
156
- vite_package_json=package_json,
157
- vite_output_dir=output_dir,
158
- vite_minify=False, # Disable minification for easier inspection
159
- )
160
- # Import the test module
161
- fixtures_dir = Path(__file__).parent / "fixtures" / "basic-app"
162
- (module,) = Jac.jac_import("app", str(fixtures_dir))
163
- # Build the bundle
164
- bundle = builder.build(module, force=True)
165
-
166
- assert bundle is not None
167
- assert bundle.module_name == "app"
168
- assert "app" in bundle.client_functions
169
- assert "ButtonProps" in bundle.client_functions
170
- assert "API_LABEL" in bundle.client_globals
171
- assert len(bundle.hash) > 10
172
-
173
- # Verify bundle code contains expected content
174
- assert "function app()" in bundle.code
175
- assert 'API_LABEL = "Runtime Test";' in bundle.code
176
-
177
- # Verify bundle was written to output directory
178
- bundle_files = list(output_dir.glob("client.*.js"))
179
- assert len(bundle_files) > 0, "Expected at least one bundle file"
180
-
181
- # Verify cached bundle is identical
182
- cached = builder.build(module, force=False)
183
- assert bundle.hash == cached.hash
184
- assert bundle.code == cached.code
185
-
186
-
187
- def test_vite_bundle_without_package_json() -> None:
188
- """Test that missing package.json raises appropriate error."""
189
- fixtures_dir = Path(__file__).parent / "fixtures" / "basic-app"
190
- (module,) = Jac.jac_import("app", str(fixtures_dir))
191
-
192
- runtime_path = Path(__file__).parent.parent / "plugin" / "client_runtime.jac"
193
-
194
- # Create builder without package.json
195
- builder = ViteClientBundleBuilder(
196
- runtime_path=runtime_path,
197
- vite_package_json=Path("/nonexistent/package.json"),
198
- vite_output_dir=Path("/tmp/output"),
199
- )
200
-
201
- # Building should raise an error
202
- from jaclang.runtimelib.client_bundle import ClientBundleError
203
-
204
- with pytest.raises(ClientBundleError) as cm:
205
- builder.build(module, force=True)
206
-
207
- assert "Vite package.json not found" in str(cm.value)
208
-
209
-
210
- def test_build_bundle_with_antd() -> None:
211
- """Test that Vite bundling works with Ant Design components."""
212
- with tempfile.TemporaryDirectory() as temp_dir:
213
- temp_path = Path(temp_dir)
214
-
215
- # Create project with Vite and Ant Design installed
216
- package_json, output_dir = _create_test_project_with_vite(
217
- temp_path, include_antd=True
218
- )
219
- runtime_path = Path(__file__).parent.parent / "plugin" / "client_runtime.jac"
220
-
221
- # Initialize the Vite builder
222
- builder = ViteClientBundleBuilder(
223
- runtime_path=runtime_path,
224
- vite_package_json=package_json,
225
- vite_output_dir=output_dir,
226
- vite_minify=False,
227
- )
228
-
229
- # Import the test module with Ant Design
230
- fixtures_dir = Path(__file__).parent / "fixtures" / "client_app_with_antd"
231
- (module,) = Jac.jac_import("app", str(fixtures_dir))
232
-
233
- # Build the bundle
234
- bundle = builder.build(module, force=True)
235
-
236
- # Verify bundle structure
237
- assert bundle is not None
238
- assert bundle.module_name == "app"
239
- assert "ButtonTest" in bundle.client_functions
240
- assert "CardTest" in bundle.client_functions
241
- assert "APP_NAME" in bundle.client_globals
242
-
243
- # Verify bundle code contains expected content
244
- assert "function ButtonTest()" in bundle.code
245
- assert "function CardTest()" in bundle.code
246
- assert 'APP_NAME = "Ant Design Test";' in bundle.code
247
-
248
- # verify antd components are present
249
- assert "ButtonGroup" in bundle.code
250
-
251
- # Verify the Ant Design fixture content is present
252
- assert "Testing Ant Design integration" in bundle.code
253
-
254
- # Verify bundle was written to output directory
255
- bundle_files = list(output_dir.glob("client.*.js"))
256
- assert len(bundle_files) > 0, "Expected at least one bundle file"
257
-
258
- # Cleanup
259
- builder.cleanup_temp_dir()
260
-
261
-
262
- def test_relative_import() -> None:
263
- """Test that relative imports work correctly in Vite bundling."""
264
- with tempfile.TemporaryDirectory() as temp_dir:
265
- temp_path = Path(temp_dir)
266
-
267
- # Create project with Vite installed
268
- package_json, output_dir = _create_test_project_with_vite(
269
- temp_path, include_antd=True
270
- )
271
- runtime_path = Path(__file__).parent.parent / "plugin" / "client_runtime.jac"
272
-
273
- # Initialize the Vite builder
274
- builder = ViteClientBundleBuilder(
275
- runtime_path=runtime_path,
276
- vite_package_json=package_json,
277
- vite_output_dir=output_dir,
278
- vite_minify=False,
279
- )
280
-
281
- # Import the test module with relative import
282
- fixtures_dir = Path(__file__).parent / "fixtures" / "relative_import"
283
- (module,) = Jac.jac_import("app", str(fixtures_dir))
284
-
285
- # Build the bundle
286
- bundle = builder.build(module, force=True)
287
-
288
- # Verify bundle structure
289
- assert bundle is not None
290
- assert bundle.module_name == "app"
291
- assert "RelativeImport" in bundle.client_functions
292
- assert "app" in bundle.client_functions
293
- assert "CustomButton" in bundle.code
294
-
295
- # Verify bundle code contains expected content
296
- assert "function RelativeImport()" in bundle.code
297
- assert "function app()" in bundle.code
298
-
299
- # Verify that the relative import (Button from .button) is properly resolved
300
- assert "ButtonGroup" in bundle.code
301
-
302
- # Verify bundle was written to output directory
303
- bundle_files = list(output_dir.glob("client.*.js"))
304
- assert len(bundle_files) > 0, "Expected at least one bundle file"
305
-
306
- # Cleanup
307
- builder.cleanup_temp_dir()
308
-
309
-
310
- def test_js_import() -> None:
311
- """Test that JavaScript file imports work correctly in Vite bundling."""
312
- with tempfile.TemporaryDirectory() as temp_dir:
313
- temp_path = Path(temp_dir)
314
- # Create project with Vite installed
315
- package_json, output_dir = _create_test_project_with_vite(temp_path)
316
- runtime_path = Path(__file__).parent.parent / "plugin" / "client_runtime.jac"
317
- # Initialize the Vite builder
318
- builder = ViteClientBundleBuilder(
319
- runtime_path=runtime_path,
320
- vite_package_json=package_json,
321
- vite_output_dir=output_dir,
322
- vite_minify=False,
323
- )
324
-
325
- # Import the test module with JavaScript import
326
- fixtures_dir = Path(__file__).parent / "fixtures" / "js_import"
327
- (module,) = Jac.jac_import("app", str(fixtures_dir))
328
-
329
- # Build the bundle
330
- bundle = builder.build(module, force=True)
331
-
332
- # Verify bundle structure
333
- assert bundle is not None
334
- assert bundle.module_name == "app"
335
- assert "JsImportTest" in bundle.client_functions
336
- assert "app" in bundle.client_functions
337
- assert "JS_IMPORT_LABEL" in bundle.client_globals
338
-
339
- # Verify bundle code contains expected content
340
- assert "function JsImportTest()" in bundle.code
341
- assert "function app()" in bundle.code
342
- assert 'JS_IMPORT_LABEL = "JavaScript Import Test";' in bundle.code
343
-
344
- # Verify JavaScript imports are present in the bundle
345
- # The JavaScript functions should be available in the bundle
346
- assert "formatMessage" in bundle.code
347
- assert "calculateSum" in bundle.code
348
- assert "JS_CONSTANT" in bundle.code
349
- assert "MessageFormatter" in bundle.code
350
-
351
- # Verify the JavaScript utility code is included
352
- assert "Hello," in bundle.code # From formatMessage function
353
- assert "Imported from JavaScript" in bundle.code # From JS_CONSTANT
354
-
355
- # Verify bundle was written to output directory
356
- bundle_files = list(output_dir.glob("client.*.js"))
357
- assert len(bundle_files) > 0, "Expected at least one bundle file"
358
-
359
- # Cleanup
360
- builder.cleanup_temp_dir()
361
-
362
-
363
- def test_jsx_fragments_and_spread_props() -> None:
364
- """Test that JSX fragments and spread props work correctly."""
365
- with tempfile.TemporaryDirectory() as temp_dir:
366
- temp_path = Path(temp_dir)
367
-
368
- # Create project with Vite installed
369
- package_json, output_dir = _create_test_project_with_vite(temp_path)
370
- runtime_path = Path(__file__).parent.parent / "plugin" / "client_runtime.jac"
371
-
372
- # Initialize the Vite builder
373
- builder = ViteClientBundleBuilder(
374
- runtime_path=runtime_path,
375
- vite_package_json=package_json,
376
- vite_output_dir=output_dir,
377
- vite_minify=False,
378
- )
379
-
380
- # Import the test module with fragments and spread props
381
- fixtures_dir = Path(__file__).parent / "fixtures" / "test_fragments_spread"
382
- (module,) = Jac.jac_import("app", str(fixtures_dir))
383
-
384
- # Build the bundle
385
- bundle = builder.build(module, force=True)
386
-
387
- # Verify bundle structure
388
- assert bundle is not None
389
- assert bundle.module_name == "app"
390
- assert "FragmentTest" in bundle.client_functions
391
- assert "SpreadPropsTest" in bundle.client_functions
392
- assert "MixedTest" in bundle.client_functions
393
- assert "NestedFragments" in bundle.client_functions
394
-
395
- # Verify spread props handling (Object.assign is used by compiler)
396
- assert "Object.assign" in bundle.code
397
-
398
- # Verify fragment test function exists
399
- assert "function FragmentTest()" in bundle.code
400
-
401
- # Verify spread props test function exists
402
- assert "function SpreadPropsTest()" in bundle.code
403
-
404
- # Verify bundle was written to output directory
405
- bundle_files = list(output_dir.glob("client.*.js"))
406
- assert len(bundle_files) > 0, "Expected at least one bundle file"
407
-
408
- # Cleanup
409
- builder.cleanup_temp_dir()
410
-
411
-
412
- def test_spawn_operator() -> None:
413
- """Test that spawn operator generates correct __jacSpawn calls for both orderings and node types (root and UUID)."""
414
- with tempfile.TemporaryDirectory() as temp_dir:
415
- temp_path = Path(temp_dir)
416
-
417
- # Create project with Vite installed
418
- package_json, output_dir = _create_test_project_with_vite(temp_path)
419
- runtime_path = Path(__file__).parent.parent / "plugin" / "client_runtime.jac"
420
-
421
- # Initialize the Vite builder
422
- builder = ViteClientBundleBuilder(
423
- runtime_path=runtime_path,
424
- vite_package_json=package_json,
425
- vite_output_dir=output_dir,
426
- vite_minify=False,
427
- )
428
-
429
- # Import the test module with both spawn operator orderings
430
- fixtures_dir = Path(__file__).parent / "fixtures" / "spawn_test"
431
- (module,) = Jac.jac_import("app", str(fixtures_dir))
432
-
433
- # Build the bundle
434
- bundle = builder.build(module, force=True)
435
-
436
- # Verify bundle structure
437
- assert bundle is not None
438
- assert bundle.module_name == "app"
439
- assert "app" in bundle.client_functions
440
-
441
- # Verify complete __jacSpawn calls for root spawn scenarios
442
- # Standard order: root spawn test_walker()
443
- assert '__jacSpawn("test_walker", "", {})' in bundle.code
444
-
445
- # Standard order: root spawn parameterized_walker(value=42)
446
- assert '__jacSpawn("parameterized_walker", "", {' in bundle.code
447
- assert '"value": 42' in bundle.code
448
-
449
- # Reverse order: test_walker(message="Reverse spawn!") spawn root
450
- # Should generate: __jacSpawn("test_walker", "", {message: "Reverse spawn!"})
451
- import re
452
-
453
- assert re.search(
454
- r'__jacSpawn\("test_walker",\s*"",\s*\{[^}]*"message":\s*"Reverse spawn!"[^}]*\}\)',
455
- bundle.code,
456
- )
457
-
458
- # Verify UUID spawn scenarios with complete calls
459
- # Standard UUID spawn: node_id spawn test_walker()
460
- # Should generate: __jacSpawn("test_walker", node_id, {})
461
- assert '__jacSpawn("test_walker", node_id, {})' in bundle.code
462
- assert '"550e8400-e29b-41d4-a716-446655440000"' in bundle.code
463
-
464
- # Reverse UUID spawn: parameterized_walker(value=100) spawn another_node_id
465
- # Should generate: __jacSpawn("parameterized_walker", another_node_id, {value: 100})
466
- assert re.search(
467
- r'__jacSpawn\("parameterized_walker",\s*another_node_id,\s*\{[^}]*"value":\s*100[^}]*\}\)',
468
- bundle.code,
469
- )
470
- assert '"6ba7b810-9dad-11d1-80b4-00c04fd430c8"' in bundle.code
471
-
472
- # Verify positional argument mapping for walkers
473
- assert re.search(
474
- r'__jacSpawn\("positional_walker",\s*node_id,\s*\{[^}]*"label":\s*"Node positional"[^}]*"count":\s*2',
475
- bundle.code,
476
- )
477
- # Verify spread (**kwargs) handling when walker is on left-hand side
478
- assert re.search(
479
- r'__jacSpawn\("positional_walker",\s*"",\s*_objectSpread\(\{\s*"label":\s*"Spread order"[^}]*"count":\s*5\s*\},\s*extra_fields\)',
480
- bundle.code,
481
- )
482
-
483
- # Verify we have at least 7 __jacSpawn calls (previous cases + new positional/spread)
484
- assert bundle.code.count("__jacSpawn") >= 7, (
485
- "Expected at least 7 __jacSpawn calls in bundle"
486
- )
487
-
488
- # Verify bundle was written to output directory
489
- bundle_files = list(output_dir.glob("client.*.js"))
490
- assert len(bundle_files) > 0, "Expected at least one bundle file"
491
-
492
- # Cleanup
493
- builder.cleanup_temp_dir()
494
-
495
-
496
- def test_serve_cl_file() -> None:
497
- """Test that serving a .cl file works correctly."""
498
- with tempfile.TemporaryDirectory() as temp_dir:
499
- temp_path = Path(temp_dir)
500
-
501
- # Create project with Vite installed
502
- package_json, output_dir = _create_test_project_with_vite(temp_path)
503
- runtime_path = Path(__file__).parent.parent / "plugin" / "client_runtime.jac"
504
-
505
- # Initialize the Vite builder
506
- builder = ViteClientBundleBuilder(
507
- runtime_path=runtime_path,
508
- vite_package_json=package_json,
509
- vite_output_dir=output_dir,
510
- vite_minify=False,
511
- )
512
-
513
- # Import the test module with both spawn operator orderings
514
- fixtures_dir = Path(__file__).parent / "fixtures" / "cl_file"
515
- (module,) = Jac.jac_import("app", str(fixtures_dir))
516
-
517
- # Build the bundle
518
- bundle = builder.build(module, force=True)
519
- # Verify bundle structure
520
- assert bundle is not None
521
- assert bundle.module_name == "app"
522
- assert "app" in bundle.client_functions
523
-
524
- assert "function app()" in bundle.code
525
- assert '__jacJsx("div", {}, [__jacJsx("h2", {}, ["My Todos"])' in bundle.code
526
- assert "root.render(/* @__PURE__ */ React.c" in bundle.code
527
- assert "ar _useState = reactExports.useState([]), _useStat" in bundle.code
528
- assert 'turn __jacSpawn("create_todo", ' in bundle.code
529
- # Cleanup
530
- builder.cleanup_temp_dir()
@@ -1,131 +0,0 @@
1
- """Test create-jac-app command."""
2
-
3
- import json
4
- import os
5
- import tempfile
6
- from subprocess import run
7
-
8
-
9
- def test_create_jac_app() -> None:
10
- """Test create-jac-app command."""
11
- test_project_name = "test-jac-app"
12
-
13
- # Create a temporary directory for testing
14
- with tempfile.TemporaryDirectory() as temp_dir:
15
- original_cwd = os.getcwd()
16
- try:
17
- # Change to temp directory
18
- os.chdir(temp_dir)
19
-
20
- # Run create-jac-app command
21
- result = run(
22
- ["jac", "create_jac_app", test_project_name],
23
- capture_output=True,
24
- text=True,
25
- check=True,
26
- )
27
-
28
- # Check that command succeeded
29
- assert result.returncode == 0
30
- assert (
31
- f"Successfully created Jac application '{test_project_name}'!"
32
- in result.stdout
33
- )
34
-
35
- # Verify project directory was created
36
- project_path = os.path.join(temp_dir, test_project_name)
37
- assert os.path.exists(project_path)
38
- assert os.path.isdir(project_path)
39
-
40
- # Verify package.json was created and has correct content
41
- package_json_path = os.path.join(project_path, "package.json")
42
- assert os.path.exists(package_json_path)
43
-
44
- with open(package_json_path) as f:
45
- package_data = json.load(f)
46
-
47
- assert package_data["name"] == test_project_name
48
- assert package_data["type"] == "module"
49
- assert "vite" in package_data["devDependencies"]
50
- assert "build" in package_data["scripts"]
51
- assert "dev" in package_data["scripts"]
52
- assert "preview" in package_data["scripts"]
53
-
54
- # Verify app.jac file was created
55
- app_jac_path = os.path.join(project_path, "app.jac")
56
- assert os.path.exists(app_jac_path)
57
-
58
- with open(app_jac_path) as f:
59
- app_jac_content = f.read()
60
-
61
- assert "app()" in app_jac_content
62
-
63
- # Verify README.md was created
64
- readme_path = os.path.join(project_path, "README.md")
65
- assert os.path.exists(readme_path)
66
-
67
- with open(readme_path) as f:
68
- readme_content = f.read()
69
-
70
- assert f"# {test_project_name}" in readme_content
71
- assert "jac serve app.jac" in readme_content
72
-
73
- # Verify node_modules was created (npm install ran)
74
- node_modules_path = os.path.join(project_path, "node_modules")
75
- assert os.path.exists(node_modules_path)
76
-
77
- finally:
78
- # Return to original directory
79
- os.chdir(original_cwd)
80
-
81
-
82
- def test_create_jac_app_invalid_name() -> None:
83
- """Test create-jac-app command with invalid project name."""
84
- with tempfile.TemporaryDirectory() as temp_dir:
85
- original_cwd = os.getcwd()
86
- try:
87
- os.chdir(temp_dir)
88
-
89
- # Test with invalid name containing spaces
90
- result = run(
91
- ["jac", "create_jac_app", "invalid name with spaces"],
92
- capture_output=True,
93
- text=True,
94
- )
95
-
96
- # Should fail with non-zero exit code
97
- assert result.returncode != 0
98
- assert (
99
- "Project name must contain only letters, numbers, hyphens, and underscores"
100
- in result.stderr
101
- )
102
-
103
- finally:
104
- os.chdir(original_cwd)
105
-
106
-
107
- def test_create_jac_app_existing_directory() -> None:
108
- """Test create-jac-app command when directory already exists."""
109
- test_project_name = "existing-test-app"
110
-
111
- with tempfile.TemporaryDirectory() as temp_dir:
112
- original_cwd = os.getcwd()
113
- try:
114
- os.chdir(temp_dir)
115
-
116
- # Create the directory first
117
- os.makedirs(test_project_name)
118
-
119
- # Try to create app with same name
120
- result = run(
121
- ["jac", "create_jac_app", test_project_name],
122
- capture_output=True,
123
- text=True,
124
- )
125
-
126
- # Should fail with non-zero exit code
127
- assert result.returncode != 0
128
- assert f"Directory '{test_project_name}' already exists" in result.stderr
129
-
130
- finally:
131
- os.chdir(original_cwd)