@nutin/cli 1.3.1 → 2.0.0

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 (287) hide show
  1. package/CHANGELOG.md +89 -9
  2. package/README.md +20 -35
  3. package/bin/add-feature.mjs +9 -0
  4. package/bin/cli.mjs +8 -0
  5. package/bin/create-app.mjs +5 -4
  6. package/bin/update-app.mjs +9 -0
  7. package/lib/index.mjs +76 -25
  8. package/lib/src/add-feature/feature-adder.mjs +83 -0
  9. package/lib/src/add-feature/feature-context-builder.mjs +25 -0
  10. package/lib/src/add-feature/nutin-config-updater.mjs +29 -0
  11. package/lib/src/add-feature/package-json-updater.mjs +49 -0
  12. package/lib/src/common/feature-registry.mjs +11 -0
  13. package/lib/src/common/file-generator.mjs +159 -0
  14. package/lib/src/common/meta-bootstrap-prompt.mjs +33 -0
  15. package/lib/src/common/package-data.mjs +10 -0
  16. package/lib/src/common/package-json-helper.mjs +103 -0
  17. package/lib/src/common/project-meta.mjs +54 -0
  18. package/lib/src/create-app/context-builder.mjs +21 -0
  19. package/lib/src/{git-manager.mjs → create-app/git-manager.mjs} +2 -2
  20. package/lib/src/create-app/json-manager.mjs +73 -0
  21. package/lib/src/{prompts.mjs → create-app/new-app-prompt.mjs} +6 -6
  22. package/lib/src/{project-generator.mjs → create-app/project-generator.mjs} +10 -8
  23. package/lib/src/create-app/success-message.mjs +14 -0
  24. package/lib/src/update-app/conflict-report-writer.mjs +31 -0
  25. package/lib/src/update-app/fetch-old-templates.mjs +61 -0
  26. package/lib/src/update-app/project-updater.mjs +136 -0
  27. package/lib/src/update-app/template-differ.mjs +124 -0
  28. package/lib/src/update-app/update-context-builder.mjs +25 -0
  29. package/lib/src/update-app/update-summary-printer.mjs +22 -0
  30. package/lib/src/update-app/version-compare.mjs +12 -0
  31. package/lib/src/utils/print.mjs +36 -0
  32. package/lib/src/utils/promise-exec-alias.mjs +4 -0
  33. package/package.json +17 -12
  34. package/templates/base/.gitignore.hbs +6 -1
  35. package/templates/base/AGENTS.md.hbs +169 -0
  36. package/templates/base/GETTING_STARTED.md.hbs +227 -0
  37. package/templates/base/README.md.hbs +8 -17
  38. package/templates/base/config/languages.json.hbs +6 -0
  39. package/templates/base/config/seo.json.hbs +12 -0
  40. package/templates/base/nutin.config.js.hbs +51 -0
  41. package/templates/base/src/app/components/index.ts.hbs +1 -2
  42. package/templates/base/src/app/globals.d.ts.hbs +3 -19
  43. package/templates/base/src/{libs/guards → app}/guards.ts.hbs +1 -5
  44. package/templates/base/src/app/main.ts.hbs +7 -26
  45. package/templates/base/src/app/services/index.ts.hbs +1 -1
  46. package/templates/base/src/app/views/home/home.view.html.hbs +7 -0
  47. package/templates/base/src/app/views/home/home.view.ts.hbs +1 -56
  48. package/templates/base/src/app/views/index.ts.hbs +1 -0
  49. package/templates/base/src/app/views/not-found/not-found.view.html.hbs +8 -0
  50. package/templates/base/src/app/views/not-found/not-found.view.ts.hbs +4 -37
  51. package/templates/base/src/core/base-classes/base-component/base-component.test.js.hbs +158 -0
  52. package/templates/base/src/core/base-classes/base-component/base-component.ts.hbs +68 -35
  53. package/templates/base/src/core/base-classes/base-component/helpers/catalog.helper.test.js.hbs +124 -0
  54. package/templates/base/src/core/base-classes/base-component/helpers/catalog.helper.ts.hbs +9 -8
  55. package/templates/base/src/core/base-classes/base-component/helpers/children.helper.test.js.hbs +74 -0
  56. package/templates/base/src/core/base-classes/base-component/helpers/children.helper.ts.hbs +1 -1
  57. package/templates/base/src/core/base-classes/base-component/helpers/dom.helper.test.js.hbs +145 -0
  58. package/templates/base/src/core/base-classes/base-component/helpers/dom.helper.ts.hbs +7 -1
  59. package/templates/base/src/core/base-classes/base-component/helpers/event.helper.test.js.hbs +88 -0
  60. package/templates/base/src/core/base-classes/base-component/helpers/event.helper.ts.hbs +2 -2
  61. package/templates/base/src/core/base-classes/base-component/helpers/i18n.helper.test.js.hbs +62 -0
  62. package/templates/base/src/core/base-classes/base-component/helpers/pipe.helper.test.js.hbs +82 -0
  63. package/templates/base/src/core/base-classes/base-component/helpers/security.helper.test.js.hbs +142 -0
  64. package/templates/base/src/core/base-classes/base-component/helpers/security.helper.ts.hbs +67 -22
  65. package/templates/base/src/core/base-classes/base-component/helpers/token.helper.test.js.hbs +183 -0
  66. package/templates/base/src/core/base-classes/component/component.test.js.hbs +85 -0
  67. package/templates/base/src/core/base-classes/component/component.ts.hbs +24 -33
  68. package/templates/base/src/core/base-classes/component/helpers/config.helper.test.js.hbs +58 -0
  69. package/templates/base/src/core/base-classes/component/helpers/data-binding.helper.test.js.hbs +75 -0
  70. package/templates/base/src/core/base-classes/service/service.test.js.hbs +150 -0
  71. package/templates/base/src/core/base-classes/service/service.ts.hbs +26 -20
  72. package/templates/base/src/core/base-classes/view/view.test.js.hbs +74 -0
  73. package/templates/base/src/core/base-classes/view/view.ts.hbs +17 -41
  74. package/templates/base/src/core/config.ts.hbs +7 -0
  75. package/templates/base/src/core/index.ts.hbs +0 -3
  76. package/templates/base/src/core/internals.d.ts.hbs +27 -0
  77. package/templates/base/src/core/nutin-config.d.ts.hbs +4 -0
  78. package/templates/base/src/core/services/event-bus/event-bus.test.js.hbs +67 -3
  79. package/templates/base/src/core/services/event-bus/event-bus.ts.hbs +9 -4
  80. package/templates/base/src/core/services/event-bus/index.ts.hbs +3 -0
  81. package/templates/base/src/core/services/event-bus/lifecycle.facade.test.js.hbs +123 -0
  82. package/templates/base/src/core/services/event-bus/lifecycle.facade.ts.hbs +61 -0
  83. package/templates/base/src/core/services/event-bus/navigation.facade.test.js.hbs +46 -0
  84. package/templates/base/src/core/services/event-bus/navigation.facade.ts.hbs +25 -0
  85. package/templates/base/src/core/services/globals/globals.test.js.hbs +149 -0
  86. package/templates/base/src/core/services/globals/globals.ts.hbs +95 -0
  87. package/templates/base/src/core/services/http-client/helpers/http-builder.helper.test.js.hbs +25 -0
  88. package/templates/base/src/core/services/http-client/helpers/http-manager.helper.test.js.hbs +20 -0
  89. package/templates/base/src/core/services/http-client/http-client.test.js.hbs +43 -0
  90. package/templates/base/src/core/services/i18n/i18n.test.js.hbs +270 -0
  91. package/templates/{features/i18n → base}/src/core/services/i18n/i18n.ts.hbs +22 -4
  92. package/templates/base/src/core/services/index.ts.hbs +5 -6
  93. package/templates/base/src/core/services/pipe-registry/pipe-registry.test.js.hbs +60 -1
  94. package/templates/base/src/core/services/pipe-registry/pipe-registry.ts.hbs +1 -1
  95. package/templates/base/src/core/services/pipe-registry/pipes.test.js.hbs +128 -0
  96. package/templates/base/src/{libs/pipes → core/services/pipe-registry}/pipes.ts.hbs +8 -5
  97. package/templates/base/src/core/services/router/helpers/navigation-manager.helper.test.js.hbs +149 -6
  98. package/templates/base/src/core/services/router/helpers/navigation-manager.helper.ts.hbs +40 -29
  99. package/templates/base/src/core/services/router/helpers/route-guard-manager.helper.test.js.hbs +27 -0
  100. package/templates/base/src/core/services/router/helpers/view-render-manager.helper.test.js.hbs +83 -17
  101. package/templates/base/src/core/services/router/helpers/view-render-manager.helper.ts.hbs +14 -38
  102. package/templates/base/src/core/services/router/router.test.js.hbs +226 -2
  103. package/templates/base/src/core/services/router/router.ts.hbs +40 -8
  104. package/templates/base/src/index.html.hbs +2 -6
  105. package/templates/base/src/styles/_styles.scss.hbs +102 -43
  106. package/templates/base/src/styles/base/_variables.scss.hbs +1 -86
  107. package/templates/base/src/styles/main.scss.hbs +1 -18
  108. package/templates/base/src/styles/tailwind.css.hbs +2 -0
  109. package/templates/base/tools/builder/builder.config.js.hbs +40 -0
  110. package/templates/base/tools/builder/builder.js.hbs +24 -26
  111. package/templates/base/tools/builder/core/app/binary-extensions.test.js.hbs +16 -0
  112. package/templates/base/tools/builder/core/app/compile-ts.js.hbs +16 -0
  113. package/templates/base/tools/builder/core/{copy-static.js.hbs → app/copy-static.js.hbs} +27 -34
  114. package/templates/base/tools/builder/core/app/validate-routes.js.hbs +77 -0
  115. package/templates/base/tools/builder/core/finalize-build.js.hbs +16 -7
  116. package/templates/base/tools/builder/core/{add-tags.js.hbs → html-index/add-tags.js.hbs} +2 -2
  117. package/templates/base/tools/builder/core/html-index/add-tags.test.js.hbs +56 -0
  118. package/templates/base/tools/builder/core/{validate-html.js.hbs → html-index/validate-html.js.hbs} +5 -11
  119. package/templates/base/tools/builder/core/html-templates/merge-templates.js.hbs +152 -0
  120. package/templates/base/tools/builder/core/html-templates/minify-html.js.hbs +15 -0
  121. package/templates/base/tools/builder/core/html-templates/process-html-templates.js.hbs +8 -0
  122. package/templates/{features/i18n/tools/builder/core → base/tools/builder/core/i18n}/build-i18n.js.hbs +6 -17
  123. package/templates/base/tools/builder/core/prod-bundle/compress-files.js.hbs +37 -0
  124. package/templates/base/tools/builder/core/prod-bundle/esbuild.js.hbs +30 -0
  125. package/templates/base/tools/builder/core/{hash-files.js.hbs → prod-bundle/hash-files.js.hbs} +14 -11
  126. package/templates/base/tools/builder/core/seo/generate-robots-txt.js.hbs +51 -0
  127. package/templates/base/tools/builder/core/seo/generate-seo-files.js.hbs +16 -0
  128. package/templates/base/tools/builder/core/seo/generate-seo-html.js.hbs +128 -0
  129. package/templates/base/tools/builder/core/seo/generate-sitemap-xml.js.hbs +43 -0
  130. package/templates/base/tools/builder/core/seo/html-substitutions.js.hbs +99 -0
  131. package/templates/base/tools/builder/core/seo/i18n-resolution.js.hbs +66 -0
  132. package/templates/base/tools/builder/core/seo/route-output.js.hbs +64 -0
  133. package/templates/base/tools/builder/core/seo/ssr/ssr-bundle.js.hbs +54 -0
  134. package/templates/base/tools/builder/core/seo/ssr/ssr-polyfills.js.hbs +132 -0
  135. package/templates/base/tools/builder/core/seo/ssr/ssr-render.js.hbs +95 -0
  136. package/templates/base/tools/builder/core/styles/sass.js.hbs +40 -0
  137. package/templates/base/tools/builder/core/styles/tailwind.js.hbs +84 -0
  138. package/templates/base/tools/dev/dev-serve.js.hbs +26 -18
  139. package/templates/base/tools/dev/serve.js.hbs +11 -1
  140. package/templates/base/tools/dev/watcher.js.hbs +14 -6
  141. package/templates/base/tools/generator/generator.js.hbs +64 -47
  142. package/templates/base/tools/generator/handle-file.js.hbs +17 -44
  143. package/templates/base/tools/generator/handle-file.test.js.hbs +72 -0
  144. package/templates/base/tools/generator/templates/{component.template.js.hbs → component/component.template.js.hbs} +3 -2
  145. package/templates/base/tools/generator/templates/component/component.template.test.js.hbs +23 -0
  146. package/templates/base/tools/generator/templates/html/html.template.js.hbs +2 -0
  147. package/templates/base/tools/generator/templates/html/html.template.test.js.hbs +7 -0
  148. package/templates/base/tools/generator/templates/index.js.hbs +7 -12
  149. package/templates/base/tools/generator/templates/locale/locale.template.js.hbs +4 -0
  150. package/templates/base/tools/generator/templates/locale/locale.template.test.js.hbs +7 -0
  151. package/templates/base/tools/generator/templates/scss/scss.template.js.hbs +1 -0
  152. package/templates/base/tools/generator/templates/scss/scss.template.test.js.hbs +7 -0
  153. package/templates/base/tools/generator/templates/service/service.template.js.hbs +17 -0
  154. package/templates/base/tools/generator/templates/service/service.template.test.js.hbs +22 -0
  155. package/templates/base/tools/generator/templates/test/test.template.js.hbs +10 -0
  156. package/templates/base/tools/generator/templates/test/test.template.test.js.hbs +27 -0
  157. package/templates/base/tools/generator/templates/{view.template.js.hbs → view/view.template.js.hbs} +3 -2
  158. package/templates/base/tools/generator/templates/view/view.template.test.js.hbs +24 -0
  159. package/templates/base/tools/testin-nutin/core/coverage/collect-coverage.js.hbs +39 -0
  160. package/templates/base/tools/testin-nutin/core/coverage/compute-coverage.js.hbs +115 -0
  161. package/templates/base/tools/testin-nutin/core/coverage/compute-coverage.test.js.hbs +74 -0
  162. package/templates/base/tools/testin-nutin/core/coverage/write-summary-report.js.hbs +54 -0
  163. package/templates/base/tools/testin-nutin/core/coverage/write-uncovered-report.js.hbs +44 -0
  164. package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/assertion-lib.js.hbs +62 -24
  165. package/templates/base/tools/testin-nutin/core/globals/clock.js.hbs +206 -0
  166. package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/jsdom-setup.js.hbs +19 -6
  167. package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/register-test-globals.js.hbs +13 -4
  168. package/templates/base/tools/testin-nutin/core/globals/silence-console.js.hbs +23 -0
  169. package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/spyon.js.hbs +2 -0
  170. package/templates/base/tools/testin-nutin/core/index.js.hbs +9 -0
  171. package/templates/base/tools/testin-nutin/core/printer.js.hbs +85 -0
  172. package/templates/base/tools/testin-nutin/core/queue/queue.test.js.hbs +46 -0
  173. package/templates/base/tools/testin-nutin/core/queue/test-discovery.test.js.hbs +46 -0
  174. package/templates/base/tools/testin-nutin/core/queue/test-queue.js.hbs +154 -0
  175. package/templates/{features/testinNutin → base/tools}/testin-nutin/core/tests/assertions.test.js.hbs +27 -0
  176. package/templates/base/tools/testin-nutin/core/tests/clock.test.js.hbs +118 -0
  177. package/templates/base/tools/testin-nutin/core/tests/globals-each-all.test.js.hbs +28 -0
  178. package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/create-mock-method.js.hbs +2 -1
  179. package/templates/base/tools/testin-nutin/mocks/create-mock-method.test.js.hbs +64 -0
  180. package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-event-bus.js.hbs +3 -2
  181. package/templates/base/tools/testin-nutin/mocks/mock-event-bus.test.js.hbs +66 -0
  182. package/templates/base/tools/testin-nutin/mocks/mock-http-client.test.js.hbs +26 -0
  183. package/templates/base/tools/testin-nutin/mocks/mock-i18n.test.js.hbs +61 -0
  184. package/templates/base/tools/testin-nutin/mocks/mock-router.test.js.hbs +29 -0
  185. package/templates/base/tools/testin-nutin/runner.js.hbs +100 -0
  186. package/templates/base/tools/testin-nutin/watch-tests.js.hbs +37 -0
  187. package/templates/base/tools/utils/error-exit.js.hbs +8 -0
  188. package/templates/base/tools/utils/format.js.hbs +10 -10
  189. package/templates/base/tools/utils/format.test.js.hbs +45 -0
  190. package/templates/base/tools/utils/get-files-recursive.js.hbs +6 -1
  191. package/templates/base/tools/utils/get-files-recursive.test.js.hbs +49 -0
  192. package/templates/base/tools/utils/get-rel-to-core.test.js.hbs +18 -0
  193. package/templates/base/tools/utils/index.js.hbs +1 -3
  194. package/templates/base/tools/utils/languages.js.hbs +15 -0
  195. package/templates/base/tools/utils/languages.test.js.hbs +16 -0
  196. package/templates/base/tools/utils/print.js.hbs +19 -13
  197. package/templates/base/tools/utils/print.test.js.hbs +60 -0
  198. package/templates/base/tools/utils/prompt-boolean.js.hbs +7 -0
  199. package/templates/base/tools/utils/prompt-boolean.test.js.hbs +54 -0
  200. package/templates/base/tools/utils/run-command.js.hbs +4 -2
  201. package/templates/base/tools/utils/run-command.test.js.hbs +19 -0
  202. package/templates/base/tools/utils/run-script.js.hbs +14 -3
  203. package/templates/base/tools/utils/run-script.test.js.hbs +40 -0
  204. package/templates/features/{deployHelper → docker}/.dockerignore.hbs +4 -4
  205. package/templates/features/docker/tools/docker/Dockerfile.template.hbs +51 -0
  206. package/templates/features/{deployHelper/tools/deployment/nginx.conf.hbs → docker/tools/docker/nginx.conf.template} +4 -2
  207. package/templates/features/docker/tools/docker/scripts/docker-build.js.hbs +20 -0
  208. package/templates/features/docker/tools/docker/scripts/docker-ports.js.hbs +48 -0
  209. package/templates/features/docker/tools/docker/scripts/docker-ports.test.js.hbs +52 -0
  210. package/templates/features/docker/tools/docker/scripts/docker-run.js.hbs +28 -0
  211. package/templates/features/docker/tools/docker/scripts/render-docker-template.js.hbs +23 -0
  212. package/templates/features/docker/tools/docker/scripts/render-docker-template.test.js.hbs +60 -0
  213. package/templates/features/docker/tools/docker/scripts/validate-docker.js.hbs +30 -0
  214. package/lib/src/context-builder.mjs +0 -40
  215. package/lib/src/file-generator.mjs +0 -109
  216. package/lib/src/json-generator.mjs +0 -31
  217. package/lib/src/package-manager.mjs +0 -139
  218. package/lib/src/print.mjs +0 -32
  219. package/lib/src/utils.mjs +0 -18
  220. package/lib/src/version.mjs +0 -1
  221. package/templates/base/builder.config.js.hbs +0 -36
  222. package/templates/base/src/app/components/common/anchor/anchor.component.ts.hbs +0 -32
  223. package/templates/base/src/app/components/common/button/button.component.ts.hbs +0 -40
  224. package/templates/base/src/app/dom.test.js.hbs +0 -13
  225. package/templates/base/src/app/services/example/example.service.ts.hbs +0 -18
  226. package/templates/base/src/app/views/home/home.view.test.js.hbs +0 -26
  227. package/templates/base/src/core/services/store/store.test.js.hbs +0 -8
  228. package/templates/base/src/core/services/store/store.ts.hbs +0 -39
  229. package/templates/base/src/core/utils/anchor-manager/anchor-manager.utils.test.js.hbs +0 -0
  230. package/templates/base/src/core/utils/anchor-manager/anchor-manager.utils.ts.hbs +0 -113
  231. package/templates/base/src/core/utils/button-manager/button-manager.utils.test.js.hbs +0 -249
  232. package/templates/base/src/core/utils/button-manager/button-manager.utils.ts.hbs +0 -131
  233. package/templates/base/src/core/utils/helpers/attributes.helper.ts.hbs +0 -50
  234. package/templates/base/src/core/utils/index.ts.hbs +0 -2
  235. package/templates/base/src/libs/index.ts.hbs +0 -4
  236. package/templates/base/src/libs/popover/helpers/focus-trap.helper.ts.hbs +0 -197
  237. package/templates/base/src/libs/popover/helpers/popover-dom.helper.ts.hbs +0 -75
  238. package/templates/base/src/libs/popover/popover.ts.hbs +0 -138
  239. package/templates/base/src/libs/snackbar/snackbar.ts.hbs +0 -75
  240. package/templates/base/src/styles/base/_functions.scss.hbs +0 -9
  241. package/templates/base/src/styles/core/_anchors.scss.hbs +0 -10
  242. package/templates/base/src/styles/core/_index.scss.hbs +0 -6
  243. package/templates/base/src/styles/core/_popover.scss.hbs +0 -96
  244. package/templates/base/src/styles/core/_snackbar.scss.hbs +0 -50
  245. package/templates/base/tools/builder/core/esbuild.js.hbs +0 -25
  246. package/templates/base/tools/builder/core/minify-html.js.hbs +0 -60
  247. package/templates/base/tools/builder/core/sass.js.hbs +0 -22
  248. package/templates/base/tools/builder/core/tsc.js.hbs +0 -12
  249. package/templates/base/tools/generator/templates/service.template.js.hbs +0 -17
  250. package/templates/base/tools/utils/export-flags.js.hbs +0 -6
  251. package/templates/features/deployHelper/tools/builder/core/compress-files.js.hbs +0 -56
  252. package/templates/features/deployHelper/tools/deployment/Dockerfile.hbs +0 -30
  253. package/templates/features/i18n/src/app/views/home/locales/en.json.hbs +0 -9
  254. package/templates/features/i18n/src/app/views/not-found/locales/en.json +0 -8
  255. package/templates/features/i18n/src/app/views/not-found/locales/fr.json +0 -8
  256. package/templates/features/i18n/src/core/config.ts.hbs +0 -3
  257. package/templates/features/i18n/src/core/services/i18n/i18n.test.js.hbs +0 -125
  258. package/templates/features/i18n/tools/generator/templates/json.template.js.hbs +0 -8
  259. package/templates/features/i18n/tools/utils/languages.js.hbs +0 -7
  260. package/templates/features/stylinNutin/src/styles/_custom-classes.scss.hbs +0 -9
  261. package/templates/features/stylinNutin/src/styles/base/_mixins.scss.hbs +0 -372
  262. package/templates/features/stylinNutin/src/styles/components/_index.scss.hbs +0 -3
  263. package/templates/features/stylinNutin/src/styles/core/_utilities.scss.hbs +0 -254
  264. package/templates/features/stylinNutin/src/styles/views/_index.scss.hbs +0 -0
  265. package/templates/features/stylinNutin/tools/generator/templates/scss.template.js.hbs +0 -4
  266. package/templates/features/template/src/app/views/home/home.view.html.hbs +0 -56
  267. package/templates/features/template/src/app/views/not-found/not-found.view.html.hbs +0 -19
  268. package/templates/features/template/tools/builder/core/merge-templates.js.hbs +0 -49
  269. package/templates/features/template/tools/generator/templates/html.template.js.hbs +0 -2
  270. package/templates/features/testinNutin/testin-nutin/core/index.js.hbs +0 -5
  271. package/templates/features/testinNutin/testin-nutin/core/src/utils/print.js.hbs +0 -64
  272. package/templates/features/testinNutin/testin-nutin/core/src/utils/test-queue.js.hbs +0 -64
  273. package/templates/features/testinNutin/testin-nutin/core/tests/globals-each-all.test.js.hbs +0 -28
  274. package/templates/features/testinNutin/testin-nutin/mocks/mock-store.js.hbs +0 -38
  275. package/templates/features/testinNutin/testin-nutin/runner.js.hbs +0 -36
  276. package/templates/features/testinNutin/testin-nutin/watch-tests.js.hbs +0 -21
  277. package/templates/features/testinNutin/testin-nutin.config.js.hbs +0 -14
  278. /package/lib/src/{template-compiler.mjs → common/template-compiler.mjs} +0 -0
  279. /package/templates/{features/i18n → base}/src/core/base-classes/base-component/helpers/i18n.helper.ts.hbs +0 -0
  280. /package/templates/{features/i18n → base}/src/core/services/i18n/languages.ts.hbs +0 -0
  281. /package/templates/base/tools/builder/{variables → core/app}/binary-extensions.js.hbs +0 -0
  282. /package/templates/base/tools/builder/core/{paths.js.hbs → app/paths.js.hbs} +0 -0
  283. /package/templates/{features/testinNutin/testin-nutin/core/src/utils → base/tools/testin-nutin/core/queue}/queue.js.hbs +0 -0
  284. /package/templates/{features/testinNutin/testin-nutin/core/src/utils → base/tools/testin-nutin/core/queue}/test-discovery.js.hbs +0 -0
  285. /package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-http-client.js.hbs +0 -0
  286. /package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-i18n.js.hbs +0 -0
  287. /package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-router.js.hbs +0 -0
@@ -0,0 +1,154 @@
1
+ import path from 'path';
2
+ import Queue from './queue.js';
3
+ import { printStart, printSummary, printResults } from '../index.js';
4
+ import { setupJsdom, teardownJsdom } from '../globals/jsdom-setup.js';
5
+
6
+ const testQueue = new Queue();
7
+ let todo = 0;
8
+ let passed = 0;
9
+ let failed = 0;
10
+ let elapsedTime;
11
+ let currentTestFile = '';
12
+
13
+ export function setCurrentTestFile(file) {
14
+ currentTestFile = file ? path.relative(process.cwd(), file) : '';
15
+ }
16
+
17
+ export function addTest(test) {
18
+ testQueue.enqueue({ ...test, file: currentTestFile });
19
+ }
20
+
21
+ export async function runQueuedTests() {
22
+ printStart();
23
+ const startTime = performance.now();
24
+ const testAmount = testQueue.length;
25
+ const results = [];
26
+ let previousSuiteKey = null;
27
+ let previousSuite = null;
28
+ let previousSuiteAfterAll = null;
29
+ let test;
30
+
31
+ const runAfterAll = async (suiteName, afterAllFn) => {
32
+ if (!afterAllFn) return;
33
+ try {
34
+ await afterAllFn();
35
+ } catch (err) {
36
+ failed++;
37
+ results.push({
38
+ suiteName,
39
+ status: 'failed',
40
+ name: 'afterAll',
41
+ error: err.stack
42
+ });
43
+ }
44
+ };
45
+
46
+ const suiteKey = (t) => `${t.file}::${t.suiteName}`;
47
+
48
+ for (let i = 0; i < testAmount; i++) {
49
+ test = testQueue.deque();
50
+
51
+ if (suiteKey(test) !== previousSuiteKey) {
52
+ await runAfterAll(previousSuite, previousSuiteAfterAll);
53
+ if (previousSuiteKey !== null) teardownJsdom();
54
+
55
+ try {
56
+ setupJsdom();
57
+ } catch (err) {
58
+ failed++;
59
+ results.push({
60
+ suiteName: test.suiteName,
61
+ status: 'failed',
62
+ name: 'setupJsdom',
63
+ error: err.stack
64
+ });
65
+ previousSuiteKey = suiteKey(test);
66
+ previousSuite = test.suiteName;
67
+ previousSuiteAfterAll = null;
68
+ continue;
69
+ }
70
+
71
+ previousSuiteKey = suiteKey(test);
72
+ previousSuite = test.suiteName;
73
+ previousSuiteAfterAll = test.afterAll;
74
+ if (test.beforeAll) {
75
+ try {
76
+ await test.beforeAll();
77
+ } catch (err) {
78
+ failed++;
79
+ results.push({
80
+ suiteName: test.suiteName,
81
+ status: 'failed',
82
+ name: 'beforeAll',
83
+ error: err.stack
84
+ });
85
+ }
86
+ }
87
+ }
88
+
89
+ if (test.isTodo) {
90
+ todo++;
91
+ results.push({
92
+ suiteName: test.suiteName,
93
+ status: 'todo',
94
+ name: test.testName,
95
+ file: test.file
96
+ });
97
+ continue;
98
+ }
99
+
100
+ let testError = null;
101
+ try {
102
+ if (test.beforeEach) await test.beforeEach();
103
+ await test.testFn();
104
+ } catch (err) {
105
+ testError = err;
106
+ }
107
+
108
+ let afterEachError = null;
109
+ try {
110
+ if (test.afterEach) await test.afterEach();
111
+ } catch (err) {
112
+ afterEachError = err;
113
+ }
114
+
115
+ if (testError) {
116
+ failed++;
117
+ results.push({
118
+ suiteName: test.suiteName,
119
+ status: 'failed',
120
+ name: test.testName,
121
+ error: testError.stack
122
+ });
123
+ } else {
124
+ passed++;
125
+ results.push({
126
+ suiteName: test.suiteName,
127
+ status: 'passed',
128
+ name: test.testName
129
+ });
130
+ }
131
+
132
+ if (afterEachError) {
133
+ failed++;
134
+ results.push({
135
+ suiteName: test.suiteName,
136
+ status: 'failed',
137
+ name: `${test.testName} (afterEach)`,
138
+ error: afterEachError.stack
139
+ });
140
+ }
141
+ }
142
+
143
+ if (previousSuiteKey !== null) {
144
+ await runAfterAll(previousSuite, previousSuiteAfterAll);
145
+ teardownJsdom();
146
+ }
147
+
148
+ const endTime = performance.now();
149
+ elapsedTime = (endTime - startTime);
150
+ printResults(results);
151
+ printSummary(todo, passed, failed, elapsedTime);
152
+
153
+ return { todo, passed, failed, elapsedTime };
154
+ }
@@ -67,4 +67,31 @@ describe('assertions', () => {
67
67
  expect(notErr).not.toThrow();
68
68
  expect(notErr).not.toThrow('messsage');
69
69
  });
70
+ it('should support toThrow with an async function that rejects', async () => {
71
+ const rejects = async () => { throw new Error('async failure'); };
72
+ const resolves = async () => 'ok';
73
+ await expect(rejects).toThrow();
74
+ await expect(rejects).toThrow('async failure');
75
+ await expect(resolves).not.toThrow();
76
+ });
77
+ it('should throw a distinguishable AssertionError on failure', () => {
78
+ let caught;
79
+ try {
80
+ expect(1).toBe(2);
81
+ } catch (err) {
82
+ caught = err;
83
+ }
84
+ expect(caught).toBeInstanceOf(AssertionError);
85
+ });
86
+ it('.not should not swallow an unrelated runtime error from the matcher itself', () => {
87
+ // `x instanceof undefined` throws a TypeError — a bug in the test, not a
88
+ // legitimate assertion mismatch, so it must not be reported as a pass.
89
+ let caught;
90
+ try {
91
+ expect({}).not.toBeInstanceOf(undefined);
92
+ } catch (err) {
93
+ caught = err;
94
+ }
95
+ expect(caught).toBeInstanceOf(TypeError);
96
+ });
70
97
  });
@@ -0,0 +1,118 @@
1
+ describe('clock (fake timers)', () => {
2
+ afterEach(() => {
3
+ useRealTimers();
4
+ });
5
+
6
+ it('should fake setTimeout and fire it on advanceTimersByTime', () => {
7
+ useFakeTimers();
8
+ let called = false;
9
+ setTimeout(() => { called = true; }, 1000);
10
+
11
+ expect(called).toBeFalsy();
12
+ advanceTimersByTime(999);
13
+ expect(called).toBeFalsy();
14
+ advanceTimersByTime(1);
15
+ expect(called).toBeTruthy();
16
+ });
17
+
18
+ it('should fire multiple timers in deadline order', () => {
19
+ useFakeTimers();
20
+ const order = [];
21
+ setTimeout(() => order.push('b'), 200);
22
+ setTimeout(() => order.push('a'), 100);
23
+ setTimeout(() => order.push('c'), 300);
24
+
25
+ advanceTimersByTime(300);
26
+ expect(order).toEqual(['a', 'b', 'c']);
27
+ });
28
+
29
+ it('should fire setInterval repeatedly on a single advance', () => {
30
+ useFakeTimers();
31
+ let count = 0;
32
+ const id = setInterval(() => { count++; }, 10);
33
+
34
+ advanceTimersByTime(105);
35
+ expect(count).toEqual(10);
36
+ clearInterval(id);
37
+ });
38
+
39
+ it('should chase timers scheduled from within a firing timer via runAllTimers', () => {
40
+ useFakeTimers();
41
+ const order = [];
42
+ setTimeout(() => {
43
+ order.push('first');
44
+ setTimeout(() => order.push('nested'), 10);
45
+ }, 10);
46
+
47
+ runAllTimers();
48
+ expect(order).toEqual(['first', 'nested']);
49
+ expect(getTimerCount()).toEqual(0);
50
+ });
51
+
52
+ it('should bail out of an infinite setInterval loop in runAllTimers', () => {
53
+ useFakeTimers();
54
+ setInterval(() => {}, 0);
55
+ const throwing = () => runAllTimers();
56
+
57
+ expect(throwing).toThrow();
58
+ });
59
+
60
+ it('should only fire snapshot-pending timers with runOnlyPendingTimers', () => {
61
+ useFakeTimers();
62
+ let outer = 0;
63
+ let inner = 0;
64
+ setTimeout(() => {
65
+ outer++;
66
+ setTimeout(() => { inner++; }, 0);
67
+ }, 0);
68
+
69
+ runOnlyPendingTimers();
70
+ expect(outer).toEqual(1);
71
+ expect(inner).toEqual(0);
72
+ });
73
+
74
+ it('should clear all pending timers without firing them', () => {
75
+ useFakeTimers();
76
+ let called = false;
77
+ setTimeout(() => { called = true; }, 10);
78
+
79
+ expect(getTimerCount()).toEqual(1);
80
+ clearAllTimers();
81
+ expect(getTimerCount()).toEqual(0);
82
+ advanceTimersByTime(1000);
83
+ expect(called).toBeFalsy();
84
+ });
85
+
86
+ it('should reflect fake time in Date.now() and new Date()', () => {
87
+ useFakeTimers();
88
+ setSystemTime(1000000);
89
+
90
+ expect(Date.now()).toEqual(1000000);
91
+ expect(new Date().getTime()).toEqual(1000000);
92
+ advanceTimersByTime(500);
93
+ expect(Date.now()).toEqual(1000500);
94
+ });
95
+
96
+ it('should still construct explicit Date args normally under fake time', () => {
97
+ useFakeTimers();
98
+ setSystemTime(1000000);
99
+ const explicit = new Date(2020, 0, 1);
100
+
101
+ expect(explicit.getFullYear()).toEqual(2020);
102
+ });
103
+
104
+ it('should restore real timers after useRealTimers()', async () => {
105
+ useFakeTimers();
106
+ useRealTimers();
107
+
108
+ await new Promise(resolve => {
109
+ setTimeout(resolve, 5);
110
+ });
111
+ expect(true).toBeTruthy();
112
+ });
113
+
114
+ it('should throw a clear error when used without useFakeTimers()', () => {
115
+ const throwing = () => advanceTimersByTime(100);
116
+ expect(throwing).toThrow('useFakeTimers');
117
+ });
118
+ });
@@ -0,0 +1,28 @@
1
+ describe('globals beforeEach/All and afterEach/All', () => {
2
+ let beforeEachCount = 0;
3
+ let beforeAllCount = 0;
4
+ let afterEachCount = 0;
5
+
6
+ beforeAll(() => {
7
+ beforeAllCount++;
8
+ });
9
+ beforeEach(() => {
10
+ beforeEachCount++;
11
+ });
12
+ afterEach(() => {
13
+ afterEachCount++;
14
+ });
15
+ afterAll(() => {
16
+ // console.debug('afterAll called.');
17
+ });
18
+ it('should be called once for all and once for each', () => {
19
+ expect(beforeAllCount).toEqual(1);
20
+ expect(beforeEachCount).toEqual(1);
21
+ expect(afterEachCount).toEqual(0);
22
+ });
23
+ it('should be called once for all and twice for each', () => {
24
+ expect(beforeAllCount).toEqual(1);
25
+ expect(beforeEachCount).toEqual(2);
26
+ expect(afterEachCount).toEqual(1);
27
+ });
28
+ })
@@ -1,9 +1,10 @@
1
- export function createMockMethod() {
1
+ export function createMockMethod(defaultImpl) {
2
2
  const calls = [];
3
3
  const fn = (...args) => {
4
4
  calls.push(args);
5
5
  if (fn.__mockReturn !== undefined) return fn.__mockReturn;
6
6
  if (fn.__mockReturnFn) return fn.__mockReturnFn(...args);
7
+ if (defaultImpl) return defaultImpl(...args);
7
8
  };
8
9
  fn.calls = calls;
9
10
  fn.mockReturnValue = (value) => { fn.__mockReturn = value; };
@@ -0,0 +1,64 @@
1
+ import { createMockMethod } from './create-mock-method.js';
2
+
3
+ describe('createMockMethod', () => {
4
+ it('records every call', () => {
5
+ const fn = createMockMethod();
6
+ fn(1, 2);
7
+ fn('a');
8
+
9
+ expect(fn.calls).toEqual([[1, 2], ['a']]);
10
+ });
11
+
12
+ it('returns undefined by default', () => {
13
+ const fn = createMockMethod();
14
+ expect(fn()).toBe(undefined);
15
+ });
16
+
17
+ it('mockReturnValue makes every call return a fixed value', () => {
18
+ const fn = createMockMethod();
19
+ fn.mockReturnValue(42);
20
+
21
+ expect(fn()).toBe(42);
22
+ expect(fn('ignored arg')).toBe(42);
23
+ });
24
+
25
+ it('mockImplementation delegates to the given function', () => {
26
+ const fn = createMockMethod();
27
+ fn.mockImplementation((a, b) => a + b);
28
+
29
+ expect(fn(2, 3)).toBe(5);
30
+ });
31
+
32
+ it('mockReset clears recorded calls and configured behavior', () => {
33
+ const fn = createMockMethod();
34
+ fn.mockReturnValue(42);
35
+ fn(1);
36
+
37
+ fn.mockReset();
38
+
39
+ expect(fn.calls).toEqual([]);
40
+ expect(fn()).toBe(undefined);
41
+ });
42
+
43
+ it('falls back to the given default implementation', () => {
44
+ const fn = createMockMethod((a, b) => a + b);
45
+
46
+ expect(fn(2, 3)).toBe(5);
47
+ });
48
+
49
+ it('mockImplementation overrides the default implementation', () => {
50
+ const fn = createMockMethod(() => 'default');
51
+ fn.mockImplementation(() => 'overridden');
52
+
53
+ expect(fn()).toBe('overridden');
54
+ });
55
+
56
+ it('mockReset restores the default implementation', () => {
57
+ const fn = createMockMethod(() => 'default');
58
+ fn.mockImplementation(() => 'overridden');
59
+
60
+ fn.mockReset();
61
+
62
+ expect(fn()).toBe('default');
63
+ });
64
+ });
@@ -24,10 +24,10 @@ export class MockEventBus {
24
24
  this.off.calls = [];
25
25
  this.off.mockReset = () => { this.off.calls = []; };
26
26
 
27
- this.on = (event, callback) => {
27
+ this.on = createMockMethod((event, callback) => {
28
28
  if (!this.handlers[event]) this.handlers[event] = [];
29
29
  this.handlers[event].push(callback);
30
- };
30
+ });
31
31
 
32
32
  this.onDestroy = createMockMethod();
33
33
  this.reset = this.reset.bind(this);
@@ -37,6 +37,7 @@ export class MockEventBus {
37
37
  this.subscribe.mockReset();
38
38
  this.emit.mockReset();
39
39
  this.off.mockReset();
40
+ this.on.mockReset();
40
41
  this.onDestroy.mockReset();
41
42
  this.handlers = {};
42
43
  }
@@ -0,0 +1,66 @@
1
+ import { MockEventBus } from './mock-event-bus.js';
2
+
3
+ describe('MockEventBus', () => {
4
+ it('on() + emit() dispatches the event data to the registered handler', () => {
5
+ const bus = new MockEventBus();
6
+ let received;
7
+ bus.on('greet', (data) => { received = data; });
8
+
9
+ bus.emit('greet', 'hello');
10
+
11
+ expect(received).toBe('hello');
12
+ expect(bus.emit.calls).toEqual([['greet', 'hello']]);
13
+ });
14
+
15
+ it('on() is a trackable mock', () => {
16
+ const bus = new MockEventBus();
17
+ const handler = () => {};
18
+ bus.on('greet', handler);
19
+
20
+ expect(bus.on).toHaveBeenCalled();
21
+ expect(bus.on).toHaveBeenCalledWith('greet', handler);
22
+ });
23
+
24
+ it('off() removes a previously registered handler', () => {
25
+ const bus = new MockEventBus();
26
+ let callCount = 0;
27
+ const handler = () => { callCount++; };
28
+ bus.on('greet', handler);
29
+ bus.off('greet', handler);
30
+
31
+ bus.emit('greet', 'hello');
32
+
33
+ expect(callCount).toBe(0);
34
+ });
35
+
36
+ it('subscribe() is a bare mock and does not actually register a handler', () => {
37
+ const bus = new MockEventBus();
38
+ let called = false;
39
+ const handler = () => { called = true; };
40
+ bus.subscribe('greet', handler);
41
+
42
+ bus.emit('greet', 'hello');
43
+
44
+ expect(called).toBeFalsy();
45
+ expect(bus.subscribe.calls.length).toBe(1);
46
+ expect(bus.subscribe.calls[0][0]).toBe('greet');
47
+ expect(bus.subscribe.calls[0][1]).toBe(handler);
48
+ });
49
+
50
+ it('reset() clears handlers and call logs', () => {
51
+ const bus = new MockEventBus();
52
+ let callCount = 0;
53
+ bus.on('greet', () => { callCount++; });
54
+ bus.emit('greet', 'x');
55
+ bus.subscribe('greet', () => {});
56
+
57
+ bus.reset();
58
+
59
+ expect(bus.emit.calls).toEqual([]);
60
+ expect(bus.subscribe.calls).toEqual([]);
61
+ expect(bus.on.calls).toEqual([]);
62
+
63
+ bus.emit('greet', 'y');
64
+ expect(callCount).toBe(1); // only the pre-reset emit reached the handler
65
+ });
66
+ });
@@ -0,0 +1,26 @@
1
+ import { MockHttpClient } from './mock-http-client.js';
2
+
3
+ describe('MockHttpClient', () => {
4
+ it('exposes get/post/put/patch/delete as independent bare mocks', () => {
5
+ const client = new MockHttpClient();
6
+ client.get.mockReturnValue('get-result');
7
+ client.post('/widgets', { name: 'a' });
8
+
9
+ expect(client.get()).toBe('get-result');
10
+ expect(client.post.calls).toEqual([['/widgets', { name: 'a' }]]);
11
+ expect(client.put.calls).toEqual([]);
12
+ });
13
+
14
+ it('reset() clears calls and configured return values on every method', () => {
15
+ const client = new MockHttpClient();
16
+ client.get.mockReturnValue('cached');
17
+ client.get();
18
+ client.delete('/widgets/1');
19
+
20
+ client.reset();
21
+
22
+ expect(client.get.calls).toEqual([]);
23
+ expect(client.delete.calls).toEqual([]);
24
+ expect(client.get()).toBe(undefined);
25
+ });
26
+ });
@@ -0,0 +1,61 @@
1
+ import { MockI18n } from './mock-i18n.js';
2
+
3
+ describe('MockI18n', () => {
4
+ it('exposes the constructor defaults via currentLanguage', () => {
5
+ const i18n = new MockI18n('fr', ['en', 'fr']);
6
+ expect(i18n.currentLanguage).toBe('fr');
7
+ });
8
+
9
+ it('translate/getBrowserLanguage run their built-in default implementation without needing .mockImplementation', () => {
10
+ const i18n = new MockI18n();
11
+
12
+ // No translations set — translate() falls back to returning the key itself.
13
+ expect(i18n.translate('some.key')).toBe('some.key');
14
+ expect(i18n.getBrowserLanguage()).toBe('en');
15
+ });
16
+
17
+ it('loadTranslations/initTranslations run their default implementation and update currentLanguage', async () => {
18
+ const i18n = new MockI18n('en', ['en', 'fr']);
19
+
20
+ await i18n.loadTranslations('fr');
21
+ expect(i18n.currentLanguage).toBe('fr');
22
+ });
23
+
24
+ it('translate is still trackable as a mock alongside its default implementation', () => {
25
+ const i18n = new MockI18n();
26
+ i18n.translate('some.key');
27
+
28
+ expect(i18n.translate).toHaveBeenCalledWith('some.key');
29
+ });
30
+
31
+ it('translate can be given real interpolation behavior via .mockImplementation', () => {
32
+ const i18n = new MockI18n();
33
+ i18n.setTranslations({ greeting: 'Hello {name}' });
34
+ i18n.translate.mockImplementation((key, params) => {
35
+ const value = i18n._translations[key] || key;
36
+ if (!params) return value;
37
+ return Object.entries(params).reduce((acc, [k, v]) => acc.replace(`{${k}}`, v), value);
38
+ });
39
+
40
+ expect(i18n.translate('greeting', { name: 'Ada' })).toBe('Hello Ada');
41
+ });
42
+
43
+ it('setTranslations/setDefaultTranslations seed real, readable state', () => {
44
+ const i18n = new MockI18n();
45
+ i18n.setTranslations({ a: '1' });
46
+ i18n.setDefaultTranslations({ b: '2' });
47
+
48
+ expect(i18n._translations).toEqual({ a: '1' });
49
+ expect(i18n._defaultTranslations).toEqual({ b: '2' });
50
+ });
51
+
52
+ it('reset() restores the constructor default language and clears translations', () => {
53
+ const i18n = new MockI18n('en');
54
+ i18n.setTranslations({ a: '1' });
55
+
56
+ i18n.reset();
57
+
58
+ expect(i18n._translations).toEqual({});
59
+ expect(i18n.currentLanguage).toBe('en');
60
+ });
61
+ });
@@ -0,0 +1,29 @@
1
+ import { MockRouter } from './mock-router.js';
2
+
3
+ describe('MockRouter', () => {
4
+ it('stores the routes passed to the constructor', () => {
5
+ const routes = { '/home': {} };
6
+ const router = new MockRouter(routes);
7
+
8
+ expect(router.routes).toBe(routes);
9
+ });
10
+
11
+ it('navigate/handlePopState/handleNotFound/handleGuards/initializeEventListeners are independent bare mocks', () => {
12
+ const router = new MockRouter();
13
+ router.navigate('/about');
14
+
15
+ expect(router.navigate.calls).toEqual([['/about']]);
16
+ expect(router.handlePopState.calls).toEqual([]);
17
+ });
18
+
19
+ it('reset() clears every mock method and _currentView', () => {
20
+ const router = new MockRouter();
21
+ router.navigate('/about');
22
+ router._currentView = 'about-view';
23
+
24
+ router.reset();
25
+
26
+ expect(router.navigate.calls).toEqual([]);
27
+ expect(router._currentView).toBe(null);
28
+ });
29
+ });