testeranto 0.200.0 → 0.202.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.
- package/README.md +26 -1
- package/bundle.js +3 -2
- package/design-editor/DesignEditor.tsx +40 -241
- package/dist/common/design-editor/DesignEditor.js +33 -198
- package/dist/common/src/App.js +158 -16
- package/dist/common/src/PM/PM_WithBuild.js +135 -0
- package/dist/common/src/PM/PM_WithEslintAndTsc.js +79 -67
- package/dist/common/src/PM/PM_WithGit.js +517 -0
- package/dist/common/src/PM/PM_WithProcesses.js +519 -0
- package/dist/common/src/PM/PM_WithWebSocket.js +535 -0
- package/dist/common/src/PM/base.js +62 -0
- package/dist/common/src/PM/main.js +533 -1676
- package/dist/common/src/PM/metafileOutputs.js +78 -0
- package/dist/common/src/PM/node.js +0 -6
- package/dist/common/src/PM/pure.js +0 -8
- package/dist/common/src/PM/types.js +1 -0
- package/dist/common/src/PM/utils.js +210 -0
- package/dist/common/src/PM/web.js +0 -6
- package/dist/common/src/ReportServer.js +0 -10
- package/dist/common/src/ReportServerLib.js +0 -140
- package/dist/common/src/components/pure/AppFrame.js +68 -56
- package/dist/common/src/components/pure/ArtifactTree.js +80 -0
- package/dist/common/src/components/pure/BuildLogViewer.js +106 -0
- package/dist/common/src/components/pure/DebugEnv.js +30 -0
- package/dist/common/src/components/pure/FileTree.js +34 -0
- package/dist/common/src/components/pure/FileTreeItem.js +29 -0
- package/dist/common/src/components/pure/GitHubLoginButton.js +18 -0
- package/dist/common/src/components/pure/GitIntegrationView.js +342 -0
- package/dist/common/src/components/pure/ProcessManager.js +1 -0
- package/dist/common/src/components/pure/ProcessManagerView.js +73 -74
- package/dist/common/src/components/pure/ProjectPageView.js +4 -117
- package/dist/common/src/components/pure/Settings.js +121 -0
- package/dist/common/src/components/pure/Settings.test.js +34 -0
- package/dist/common/src/components/pure/SignIn.js +22 -0
- package/dist/common/src/components/pure/SingleProcessView.js +166 -213
- package/dist/common/src/components/pure/TestPageView.js +113 -368
- package/dist/common/src/components/pure/TestPageView_utils.js +117 -0
- package/dist/common/src/components/pure/TestTable.js +33 -0
- package/dist/common/src/components/pure/ToastNotification.js +14 -0
- package/dist/common/src/components/pure/UserProfile.js +27 -0
- package/dist/common/src/components/stateful/AuthCallbackPage.js +51 -0
- package/dist/common/src/components/stateful/FeaturesReporter.js +2 -1
- package/dist/common/src/components/stateful/FileTree.js +58 -39
- package/dist/common/src/components/stateful/GitIntegrationPage.js +12 -0
- package/dist/common/src/components/stateful/ProcessManagerPage.js +13 -15
- package/dist/common/src/components/stateful/ProjectPage.js +6 -5
- package/dist/common/src/components/stateful/ProjectsPage.js +17 -19
- package/dist/common/src/components/stateful/SingleProcessPage.js +16 -26
- package/dist/common/src/components/stateful/TestPage.js +7 -5
- package/dist/common/src/hooks/useGitMode.js +21 -0
- package/dist/common/src/lib/BaseSuite.test/mock.js +15 -8
- package/dist/common/src/lib/BaseSuite.test/test.js +56 -80
- package/dist/common/src/lib/Tiposkripto.js +24 -0
- package/dist/common/src/lib/Tiposkripto.test/MockTiposkripto.js +154 -10
- package/dist/common/src/lib/Tiposkripto.test/Tiposkripto.adapter.js +6 -12
- package/dist/common/src/lib/Tiposkripto.test/Tiposkripto.implementation.js +63 -23
- package/dist/common/src/lib/Tiposkripto.test/Tiposkripto.specification.js +14 -6
- package/dist/common/src/lib/pmProxy.test/specification.js +167 -52
- package/dist/common/src/services/FileService.js +505 -0
- package/dist/common/src/services/GitHubAuthService.js +184 -0
- package/dist/common/src/testeranto.js +38 -97
- package/dist/common/src/utils/api.js +12 -8
- package/dist/common/src/utils/gitTest.js +27 -0
- package/dist/common/src/utils.js +23 -13
- package/dist/common/testeranto.config.js +21 -17
- package/dist/common/tsconfig.common.tsbuildinfo +1 -1
- package/dist/module/design-editor/DesignEditor.js +33 -199
- package/dist/module/src/App.js +121 -15
- package/dist/module/src/PM/PM_WithBuild.js +128 -0
- package/dist/module/src/PM/PM_WithEslintAndTsc.js +79 -67
- package/dist/module/src/PM/PM_WithGit.js +477 -0
- package/dist/module/src/PM/PM_WithProcesses.js +479 -0
- package/dist/module/src/PM/PM_WithWebSocket.js +528 -0
- package/dist/module/src/PM/base.js +62 -0
- package/dist/module/src/PM/main.js +533 -1676
- package/dist/module/src/PM/metafileOutputs.js +78 -0
- package/dist/module/src/PM/node.js +0 -6
- package/dist/module/src/PM/pure.js +0 -8
- package/dist/module/src/PM/types.js +1 -1
- package/dist/module/src/PM/utils.js +196 -0
- package/dist/module/src/PM/web.js +0 -6
- package/dist/module/src/ReportServer.js +1 -9
- package/dist/module/src/ReportServerLib.js +1 -134
- package/dist/module/src/components/pure/AppFrame.js +66 -24
- package/dist/module/src/components/pure/ArtifactTree.js +80 -0
- package/dist/module/src/components/pure/BuildLogViewer.js +99 -0
- package/dist/module/src/components/pure/DebugEnv.js +23 -0
- package/dist/module/src/components/pure/FileTree.js +27 -0
- package/dist/module/src/components/pure/FileTreeItem.js +22 -0
- package/dist/module/src/components/pure/GitHubLoginButton.js +11 -0
- package/dist/module/src/components/pure/GitIntegrationView.js +305 -0
- package/dist/module/src/components/pure/ProcessManager.js +1 -0
- package/dist/module/src/components/pure/ProcessManagerView.js +74 -75
- package/dist/module/src/components/pure/ProjectPageView.js +5 -118
- package/dist/module/src/components/pure/Settings.js +84 -0
- package/dist/module/src/components/pure/Settings.test.js +29 -0
- package/dist/module/src/components/pure/SignIn.js +15 -0
- package/dist/module/src/components/pure/SingleProcessView.js +130 -214
- package/dist/module/src/components/pure/TestPageView.js +97 -352
- package/dist/module/src/components/pure/TestPageView_utils.js +109 -0
- package/dist/module/src/components/pure/TestTable.js +26 -0
- package/dist/module/src/components/pure/ToastNotification.js +7 -0
- package/dist/module/src/components/pure/UserProfile.js +20 -0
- package/dist/module/src/components/stateful/AuthCallbackPage.js +14 -0
- package/dist/module/src/components/stateful/FeaturesReporter.js +2 -1
- package/dist/module/src/components/stateful/FileTree.js +59 -33
- package/dist/module/src/components/stateful/GitIntegrationPage.js +5 -0
- package/dist/module/src/components/stateful/ProcessManagerPage.js +13 -15
- package/dist/module/src/components/stateful/ProjectPage.js +6 -5
- package/dist/module/src/components/stateful/ProjectsPage.js +16 -18
- package/dist/module/src/components/stateful/SingleProcessPage.js +16 -26
- package/dist/module/src/components/stateful/TestPage.js +8 -6
- package/dist/module/src/hooks/useGitMode.js +17 -0
- package/dist/module/src/lib/BaseSuite.test/mock.js +15 -8
- package/dist/module/src/lib/BaseSuite.test/test.js +56 -80
- package/dist/module/src/lib/Tiposkripto.js +24 -0
- package/dist/module/src/lib/Tiposkripto.test/MockTiposkripto.js +154 -10
- package/dist/module/src/lib/Tiposkripto.test/Tiposkripto.adapter.js +6 -12
- package/dist/module/src/lib/Tiposkripto.test/Tiposkripto.implementation.js +63 -23
- package/dist/module/src/lib/Tiposkripto.test/Tiposkripto.specification.js +14 -6
- package/dist/module/src/lib/pmProxy.test/specification.js +167 -52
- package/dist/module/src/services/FileService.js +468 -0
- package/dist/module/src/services/GitHubAuthService.js +180 -0
- package/dist/module/src/testeranto.js +38 -97
- package/dist/module/src/utils/api.js +10 -7
- package/dist/module/src/utils/gitTest.js +23 -0
- package/dist/module/src/utils.js +21 -12
- package/dist/module/testeranto.config.js +21 -17
- package/dist/module/tsconfig.module.tsbuildinfo +1 -1
- package/dist/prebuild/App.css +94 -121
- package/dist/prebuild/App.js +44601 -11225
- package/dist/prebuild/testeranto.mjs +4106 -0
- package/dist/types/design-editor/DesignEditor.d.ts +1 -18
- package/dist/types/src/App.d.ts +18 -0
- package/dist/types/src/PM/PM_WithBuild.d.ts +13 -0
- package/dist/types/src/PM/PM_WithEslintAndTsc.d.ts +2 -4
- package/dist/types/src/PM/PM_WithGit.d.ts +27 -0
- package/dist/types/src/PM/PM_WithProcesses.d.ts +29 -0
- package/dist/types/src/PM/PM_WithWebSocket.d.ts +108 -0
- package/dist/types/src/PM/base.d.ts +1 -1
- package/dist/types/src/PM/index.d.ts +0 -2
- package/dist/types/src/PM/main.d.ts +6 -77
- package/dist/types/src/PM/metafileOutputs.d.ts +0 -0
- package/dist/types/src/PM/node.d.ts +0 -2
- package/dist/types/src/PM/pure.d.ts +0 -2
- package/dist/types/src/PM/types.d.ts +118 -0
- package/dist/types/src/PM/utils.d.ts +35 -0
- package/dist/types/src/PM/web.d.ts +0 -2
- package/dist/types/src/Pure.d.ts +6 -1
- package/dist/types/src/ReportServer.d.ts +0 -1
- package/dist/types/src/ReportServerLib.d.ts +0 -1
- package/dist/types/src/Types.d.ts +1 -0
- package/dist/types/src/components/pure/ArtifactTree.d.ts +0 -0
- package/dist/types/src/components/pure/BuildLogViewer.d.ts +7 -0
- package/dist/types/src/components/pure/DebugEnv.d.ts +2 -0
- package/dist/types/src/components/pure/FileTree.d.ts +6 -0
- package/dist/types/src/components/pure/FileTreeItem.d.ts +8 -0
- package/dist/types/src/components/pure/GitHubLoginButton.d.ts +8 -0
- package/dist/types/src/components/pure/GitIntegrationView.d.ts +1 -0
- package/dist/types/src/components/pure/Settings.d.ts +1 -0
- package/dist/types/src/components/pure/Settings.test.d.ts +1 -0
- package/dist/types/src/components/pure/SignIn.d.ts +1 -0
- package/dist/types/src/components/pure/SingleProcessView.d.ts +10 -0
- package/dist/types/src/components/pure/TestPageView.d.ts +2 -1
- package/dist/types/src/components/pure/TestPageView_utils.d.ts +23 -0
- package/dist/types/src/components/pure/TestTable.d.ts +16 -0
- package/dist/types/src/components/pure/ToastNotification.d.ts +6 -0
- package/dist/types/src/components/pure/UserProfile.d.ts +2 -0
- package/dist/types/src/components/stateful/AuthCallbackPage.d.ts +2 -0
- package/dist/types/src/components/stateful/FileTree.d.ts +0 -8
- package/dist/types/src/components/stateful/GitIntegrationPage.d.ts +1 -0
- package/dist/types/src/hooks/useGitMode.d.ts +7 -0
- package/dist/types/src/lib/BaseSuite.test/mock.d.ts +2 -2
- package/dist/types/src/lib/BaseSuite.test/test.d.ts +4 -3
- package/dist/types/src/lib/Tiposkripto.d.ts +2 -0
- package/dist/types/src/lib/Tiposkripto.test/MockTiposkripto.d.ts +3 -0
- package/dist/types/src/lib/Tiposkripto.test/Tiposkripto.types.d.ts +5 -0
- package/dist/types/src/lib/index.d.ts +6 -0
- package/dist/types/src/services/FileService.d.ts +34 -0
- package/dist/types/src/services/GitHubAuthService.d.ts +32 -0
- package/dist/types/src/utils/api.d.ts +1 -0
- package/dist/types/src/utils/gitTest.d.ts +11 -0
- package/dist/types/src/utils.d.ts +3 -3
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/example/__pycache__/Calculator.cpython-313.pyc +0 -0
- package/example/vendor/github.com/adamwong246/testeranto/src/golingvu/README.md +187 -0
- package/example/vendor/github.com/adamwong246/testeranto/src/golingvu/base_given.go +163 -0
- package/example/vendor/github.com/adamwong246/testeranto/src/golingvu/base_suite.go +85 -0
- package/example/vendor/github.com/adamwong246/testeranto/src/golingvu/base_then.go +21 -0
- package/example/vendor/github.com/adamwong246/testeranto/src/golingvu/base_when.go +21 -0
- package/example/vendor/github.com/adamwong246/testeranto/src/golingvu/golingvu.go +554 -0
- package/example/vendor/github.com/adamwong246/testeranto/src/golingvu/test_adapter.go +33 -0
- package/example/vendor/github.com/adamwong246/testeranto/src/golingvu/types.go +72 -0
- package/example/vendor/modules.txt +5 -0
- package/git-integration-plan.md +395 -0
- package/package.json +26 -14
- package/src/App.tsx +169 -18
- package/src/PM/PM_WithBuild.ts +171 -0
- package/src/PM/PM_WithEslintAndTsc.ts +109 -86
- package/src/PM/PM_WithGit.ts +585 -0
- package/src/PM/PM_WithProcesses.ts +639 -0
- package/src/PM/PM_WithWebSocket.ts +631 -0
- package/src/PM/base.ts +63 -1
- package/src/PM/index.ts +8 -5
- package/src/PM/main.ts +672 -2050
- package/src/PM/metafileOutputs.ts +90 -0
- package/src/PM/node.ts +18 -18
- package/src/PM/pure.ts +5 -13
- package/src/PM/types.ts +145 -0
- package/src/PM/utils.ts +256 -0
- package/src/PM/web.ts +8 -8
- package/src/README.md +122 -0
- package/src/ReportServer.ts +0 -12
- package/src/ReportServerLib.ts +0 -147
- package/src/Types.ts +1 -0
- package/src/app.scss +14 -164
- package/src/components/pure/AppFrame.tsx +237 -71
- package/src/components/pure/ArtifactTree.tsx +82 -0
- package/src/components/pure/BuildLogViewer.tsx +168 -0
- package/src/components/pure/DebugEnv.tsx +30 -0
- package/src/components/pure/FileTree.tsx +58 -0
- package/src/components/pure/FileTreeItem.tsx +49 -0
- package/src/components/pure/GitHubLoginButton.tsx +31 -0
- package/src/components/pure/GitIntegrationView.tsx +443 -0
- package/src/components/pure/ProcessManager.tsx +6 -5
- package/src/components/pure/ProcessManagerView.tsx +162 -166
- package/src/components/pure/ProjectPageView.tsx +6 -224
- package/src/components/pure/Settings.test.tsx +34 -0
- package/src/components/pure/Settings.tsx +163 -0
- package/src/components/pure/SignIn.tsx +33 -0
- package/src/components/pure/SingleProcessView.tsx +231 -235
- package/src/components/pure/TestPageView.test/specification.ts +1 -0
- package/src/components/pure/TestPageView.tsx +317 -826
- package/src/components/pure/TestPageView_utils.tsx +285 -0
- package/src/components/pure/TestTable.tsx +88 -0
- package/src/components/pure/ToastNotification.tsx +19 -0
- package/src/components/pure/UserProfile.tsx +44 -0
- package/src/components/stateful/AuthCallbackPage.tsx +21 -0
- package/src/components/stateful/FeaturesReporter.tsx +3 -1
- package/src/components/stateful/FileTree.tsx +58 -58
- package/src/components/stateful/GitIntegrationPage.tsx +8 -0
- package/src/components/stateful/ProcessManagerPage.tsx +13 -17
- package/src/components/stateful/ProjectPage.tsx +6 -5
- package/src/components/stateful/ProjectsPage.tsx +17 -19
- package/src/components/stateful/SVGEditor/CircleForm.tsx +68 -0
- package/src/components/stateful/SVGEditor/GroupForm.tsx +56 -0
- package/src/components/stateful/SVGEditor/RectForm.tsx +74 -0
- package/src/components/stateful/SVGEditor/SVGAttributeField.tsx +29 -0
- package/src/components/stateful/SVGEditor/SVGAttributesEditor.tsx +73 -0
- package/src/components/stateful/SVGEditor/SVGEditorControls.tsx +45 -0
- package/src/components/stateful/SVGEditor/SVGElementForm.tsx +45 -0
- package/src/components/stateful/SVGEditor/SVGPreview.tsx +225 -0
- package/src/components/stateful/SVGEditor/SVGTextEditor.tsx +166 -0
- package/src/components/stateful/SVGEditor/SVGTree.tsx +159 -0
- package/src/components/stateful/SVGEditor/SVGTypes.ts +36 -0
- package/src/components/stateful/SVGEditor/svg.xsd.xml +3038 -0
- package/src/components/stateful/SVGEditorPage.tsx +503 -0
- package/src/components/stateful/SingleProcessPage.tsx +18 -31
- package/src/components/stateful/TestPage.tsx +25 -22
- package/src/golingvu/golingvu.go +38 -2
- package/src/hooks/useGitMode.ts +20 -0
- package/src/lib/BaseSuite.test/mock.ts +16 -10
- package/src/lib/BaseSuite.test/test.ts +144 -103
- package/src/lib/Tiposkripto.test/MockTiposkripto.ts +178 -14
- package/src/lib/Tiposkripto.test/Tiposkripto.adapter.ts +9 -14
- package/src/lib/Tiposkripto.test/Tiposkripto.implementation.ts +78 -38
- package/src/lib/Tiposkripto.test/Tiposkripto.specification.ts +51 -9
- package/src/lib/Tiposkripto.test/Tiposkripto.types.ts +5 -0
- package/src/lib/Tiposkripto.ts +27 -0
- package/src/lib/index.ts +7 -0
- package/src/lib/pmProxy.test/specification.ts +168 -166
- package/src/pitono/PM/__pycache__/python.cpython-313.pyc +0 -0
- package/src/pitono/__pycache__/Pitono.cpython-313.pyc +0 -0
- package/src/pitono/__pycache__/__init__.cpython-313.pyc +0 -0
- package/src/pitono/__pycache__/base_given.cpython-313.pyc +0 -0
- package/src/pitono/__pycache__/base_suite.cpython-313.pyc +0 -0
- package/src/pitono/__pycache__/base_then.cpython-313.pyc +0 -0
- package/src/pitono/__pycache__/base_when.cpython-313.pyc +0 -0
- package/src/pitono/__pycache__/core_generator.cpython-313.pyc +0 -0
- package/src/pitono/__pycache__/simple_adapter.cpython-313.pyc +0 -0
- package/src/pitono/__pycache__/types.cpython-313.pyc +0 -0
- package/src/services/FileService.ts +542 -0
- package/src/services/GitHubAuthService.ts +240 -0
- package/src/testeranto.ts +62 -140
- package/src/utils/api.ts +15 -13
- package/src/utils/gitTest.ts +29 -0
- package/src/utils.ts +21 -12
- package/testeranto/App.css +94 -121
- package/testeranto/App.js +44601 -11225
- package/testeranto/bundles/golang/core/Calculator.golingvu.go +53 -0
- package/testeranto/bundles/golang/core/Calculator.golingvu.golingvu.go +53 -0
- package/testeranto/bundles/node/core/chunk-RIM6RECA.mjs +1170 -0
- package/testeranto/bundles/node/core/chunk-VXVF7WFO.mjs +4321 -0
- package/testeranto/bundles/node/core/example/Calculator.test.mjs +503 -0
- package/testeranto/bundles/node/core/src/lib/BaseSuite.test/node.test.mjs +94 -1231
- package/testeranto/bundles/node/core/src/lib/TipoSkripto.test/TipoSkripto.mjs +574 -0
- package/testeranto/bundles/node/core/src/lib/pmProxy.test/index.mjs +482 -0
- package/testeranto/bundles/pure/core/chunk-XYOCRDEQ.mjs +1080 -0
- package/testeranto/bundles/pure/core/src/Pure.test.mjs +410 -0
- package/testeranto/bundles/pure/core/src/lib/BaseSuite.test/pure.test.mjs +93 -1146
- package/testeranto/bundles/python/core/Calculator.pitono.test.py +24 -0
- package/testeranto/bundles/python/core/test_example.py +24 -0
- package/testeranto/bundles/web/core/MPLUSRounded1c-Black-O75GP5JI.ttf +0 -0
- package/testeranto/bundles/web/core/MPLUSRounded1c-Bold-R524Q5BH.ttf +0 -0
- package/testeranto/bundles/web/core/MPLUSRounded1c-ExtraBold-C6GRMYVT.ttf +0 -0
- package/testeranto/bundles/web/core/MPLUSRounded1c-Light-WKN65Y2C.ttf +0 -0
- package/testeranto/bundles/web/core/MPLUSRounded1c-Medium-ZC4DWL7C.ttf +0 -0
- package/testeranto/bundles/web/core/MPLUSRounded1c-Regular-DT6EKZ3S.ttf +0 -0
- package/testeranto/bundles/web/core/MPLUSRounded1c-Thin-YWDNVG6M.ttf +0 -0
- package/testeranto/bundles/web/core/chunk-DFRN4SYZ.mjs +2297 -0
- package/testeranto/bundles/web/core/chunk-JMDLMADH.mjs +27996 -0
- package/testeranto/bundles/web/core/chunk-LQMU5NCG.mjs +3082 -0
- package/testeranto/bundles/web/core/chunk-Q5TONB2Z.mjs +6874 -0
- package/testeranto/bundles/web/core/src/components/pure/FeaturesReporterView.test/index.mjs +164 -0
- package/testeranto/bundles/web/core/src/components/pure/ModalContent.test/index.css +11697 -0
- package/testeranto/bundles/web/core/src/components/pure/ModalContent.test/index.mjs +336 -0
- package/testeranto/bundles/web/core/src/components/pure/ProjectPageView.test/index.css +11697 -0
- package/testeranto/bundles/web/core/src/components/pure/ProjectPageView.test/index.mjs +517 -0
- package/testeranto/bundles/web/core/src/lib/BaseSuite.test/web.test.mjs +107 -1134
- package/testeranto/metafiles/golang/core.json +3 -3
- package/testeranto/metafiles/node/core.json +474 -31
- package/testeranto/metafiles/pure/core.json +144 -28
- package/testeranto/metafiles/python/core.json +11 -0
- package/testeranto/metafiles/web/core.json +15829 -45
- package/testeranto/reports/core/config.json +40 -0
- package/testeranto/reports/core/src/Pure.test/pure/exit.log +0 -0
- package/testeranto/reports/core/src/Pure.test/pure/lint_errors.txt +0 -0
- package/testeranto/reports/core/src/Pure.test/pure/prompt.txt +14 -0
- package/testeranto/reports/core/src/Pure.test/pure/type_errors.txt +73 -0
- package/testeranto/reports/core/src/components/pure/FeaturesReporterView.test/index/web/debug.log +0 -0
- package/testeranto/reports/core/src/components/pure/FeaturesReporterView.test/index/web/error.log +91 -0
- package/testeranto/reports/core/src/components/pure/FeaturesReporterView.test/index/web/exit.log +1 -0
- package/testeranto/reports/core/src/components/pure/FeaturesReporterView.test/index/web/info.log +2 -0
- package/testeranto/reports/core/src/components/pure/FeaturesReporterView.test/index/web/tests.json +68 -0
- package/testeranto/reports/core/src/components/pure/FeaturesReporterView.test/index/web/warn.log +0 -0
- package/testeranto/reports/core/src/components/pure/ProjectPageView.test/index/web/debug.log +0 -0
- package/testeranto/reports/core/src/components/pure/ProjectPageView.test/index/web/error.log +30 -0
- package/testeranto/reports/core/src/components/pure/ProjectPageView.test/index/web/exit.log +1 -0
- package/testeranto/reports/core/src/components/pure/ProjectPageView.test/index/web/info.log +2 -0
- package/testeranto/reports/core/src/components/pure/ProjectPageView.test/index/web/tests.json +88 -0
- package/testeranto/reports/core/src/components/pure/ProjectPageView.test/index/web/warn.log +0 -0
- package/testeranto/reports/core/src/lib/BaseSuite.test/node.test/node/lint_errors.txt +0 -6
- package/testeranto/reports/core/src/lib/BaseSuite.test/node.test/node/prompt.txt +0 -11
- package/testeranto/reports/core/src/lib/BaseSuite.test/node.test/node/stdout.log +1 -0
- package/testeranto/reports/core/src/lib/BaseSuite.test/node.test/node/tests.json +1 -1
- package/testeranto/reports/core/src/lib/BaseSuite.test/node.test/node/type_errors.txt +35 -38
- package/testeranto/reports/core/src/lib/BaseSuite.test/pure.test/pure/lint_errors.txt +0 -2
- package/testeranto/reports/core/src/lib/BaseSuite.test/pure.test/pure/prompt.txt +0 -10
- package/testeranto/reports/core/src/lib/BaseSuite.test/pure.test/pure/type_errors.txt +40 -38
- package/testeranto/reports/core/src/lib/BaseSuite.test/web.test/web/tests.json +1 -1
- package/testeranto/reports/core/src/lib/TipoSkripto.test/TipoSkripto/node/exit.log +1 -0
- package/testeranto/reports/core/src/lib/TipoSkripto.test/TipoSkripto/node/lint_errors.txt +0 -0
- package/testeranto/reports/core/src/lib/TipoSkripto.test/TipoSkripto/node/message.txt +17 -0
- package/testeranto/reports/core/src/lib/TipoSkripto.test/TipoSkripto/node/prompt.txt +17 -0
- package/testeranto/reports/core/src/lib/TipoSkripto.test/TipoSkripto/node/stderr.log +55 -0
- package/testeranto/reports/core/src/lib/TipoSkripto.test/TipoSkripto/node/stdout.log +191 -0
- package/testeranto/reports/core/src/lib/TipoSkripto.test/TipoSkripto/node/type_errors.txt +71 -0
- package/testeranto/reports/core/src/lib/pmProxy.test/index/node/exit.log +1 -0
- package/testeranto/reports/core/src/lib/pmProxy.test/index/node/lint_errors.txt +15 -0
- package/testeranto/reports/core/src/lib/pmProxy.test/index/node/message.txt +17 -0
- package/testeranto/reports/core/src/lib/pmProxy.test/index/node/prompt.txt +17 -0
- package/testeranto/reports/core/src/lib/pmProxy.test/index/node/stderr.log +20 -0
- package/testeranto/reports/core/src/lib/pmProxy.test/index/node/stdout.log +4 -0
- package/testeranto/reports/core/src/lib/pmProxy.test/index/node/type_errors.txt +49 -0
- package/testeranto/reports/core/summary.json +34 -6
- package/testeranto.config.ts +26 -20
- package/tsc.log +141 -91
- package/tsconfig.json +6 -2
- package/dist/prebuild/ReportServer.mjs +0 -227
- package/dist/prebuild/mothership/index.mjs +0 -22
- package/dist/types/design-editor/server.d.ts +0 -1
- package/testeranto/bundles/web/core/src/lib/BaseSuite.test/web.test.html +0 -15
- package/testeranto/reports/core/src/lib/BaseSuite.test/web.test/web/lint_errors.txt +0 -2
- package/testeranto/reports/core/src/lib/BaseSuite.test/web.test/web/prompt.txt +0 -25
- package/testeranto/reports/core/src/lib/BaseSuite.test/web.test/web/type_errors.txt +0 -56
- /package/testeranto/reports/core/src/{lib/BaseSuite.test/web.test/web → Pure.test/pure}/message.txt +0 -0
|
@@ -5,1771 +5,628 @@
|
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
6
|
import ansiColors from "ansi-colors";
|
|
7
7
|
import net from "net";
|
|
8
|
-
import fs
|
|
9
|
-
import path from "path";
|
|
10
|
-
import puppeteer from "puppeteer-core";
|
|
8
|
+
import fs from "fs";
|
|
11
9
|
import ansiC from "ansi-colors";
|
|
12
|
-
import
|
|
13
|
-
import { WebSocketServer } from "ws";
|
|
14
|
-
import http from "http";
|
|
15
|
-
import url from "url";
|
|
16
|
-
import mime from "mime-types";
|
|
17
|
-
import { getRunnables } from "../utils";
|
|
10
|
+
import { webEvaluator } from "../utils";
|
|
18
11
|
import { Queue } from "../utils/queue.js";
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
const fileHashes = {};
|
|
12
|
+
import { createLogStreams, statusMessagePretty } from "./utils.js";
|
|
13
|
+
import { PM_WithProcesses } from "./PM_WithProcesses.js";
|
|
22
14
|
const files = {};
|
|
23
15
|
const screenshots = {};
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (!fs.existsSync(safeDest)) {
|
|
28
|
-
fs.mkdirSync(safeDest, { recursive: true });
|
|
29
|
-
}
|
|
30
|
-
if (runtime === "node") {
|
|
31
|
-
return {
|
|
32
|
-
stdout: fs.createWriteStream(`${safeDest}/stdout.log`),
|
|
33
|
-
stderr: fs.createWriteStream(`${safeDest}/stderr.log`),
|
|
34
|
-
exit: fs.createWriteStream(`${safeDest}/exit.log`),
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
else if (runtime === "web") {
|
|
38
|
-
return {
|
|
39
|
-
info: fs.createWriteStream(`${safeDest}/info.log`),
|
|
40
|
-
warn: fs.createWriteStream(`${safeDest}/warn.log`),
|
|
41
|
-
error: fs.createWriteStream(`${safeDest}/error.log`),
|
|
42
|
-
debug: fs.createWriteStream(`${safeDest}/debug.log`),
|
|
43
|
-
exit: fs.createWriteStream(`${safeDest}/exit.log`),
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
else if (runtime === "pure") {
|
|
47
|
-
return {
|
|
48
|
-
exit: fs.createWriteStream(`${safeDest}/exit.log`),
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
else if (runtime === "pitono") {
|
|
52
|
-
return {
|
|
53
|
-
stdout: fs.createWriteStream(`${safeDest}/stdout.log`),
|
|
54
|
-
stderr: fs.createWriteStream(`${safeDest}/stderr.log`),
|
|
55
|
-
exit: fs.createWriteStream(`${safeDest}/exit.log`),
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
throw `unknown runtime: ${runtime}`;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
catch (e) {
|
|
63
|
-
console.error(`Failed to create log streams in ${safeDest}:`, e);
|
|
64
|
-
throw e;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
function createLogStreams(reportDest, runtime) {
|
|
68
|
-
// Create directory if it doesn't exist
|
|
69
|
-
if (!fs.existsSync(reportDest)) {
|
|
70
|
-
fs.mkdirSync(reportDest, { recursive: true });
|
|
71
|
-
}
|
|
72
|
-
const streams = runtimeLogs(runtime, reportDest);
|
|
73
|
-
// const streams = {
|
|
74
|
-
// exit: fs.createWriteStream(`${reportDest}/exit.log`),
|
|
75
|
-
const safeDest = reportDest || `testeranto/reports/default_${Date.now()}`;
|
|
76
|
-
try {
|
|
77
|
-
if (!fs.existsSync(safeDest)) {
|
|
78
|
-
fs.mkdirSync(safeDest, { recursive: true });
|
|
79
|
-
}
|
|
80
|
-
const streams = runtimeLogs(runtime, safeDest);
|
|
81
|
-
// const streams = {
|
|
82
|
-
// exit: fs.createWriteStream(`${safeDest}/exit.log`),
|
|
83
|
-
// ...(runtime === "node" || runtime === "pure"
|
|
84
|
-
// ? {
|
|
85
|
-
// stdout: fs.createWriteStream(`${safeDest}/stdout.log`),
|
|
86
|
-
// stderr: fs.createWriteStream(`${safeDest}/stderr.log`),
|
|
87
|
-
// }
|
|
88
|
-
// : {
|
|
89
|
-
// info: fs.createWriteStream(`${safeDest}/info.log`),
|
|
90
|
-
// warn: fs.createWriteStream(`${safeDest}/warn.log`),
|
|
91
|
-
// error: fs.createWriteStream(`${safeDest}/error.log`),
|
|
92
|
-
// debug: fs.createWriteStream(`${safeDest}/debug.log`),
|
|
93
|
-
// }),
|
|
94
|
-
// };
|
|
95
|
-
return Object.assign(Object.assign({}, streams), { closeAll: () => {
|
|
96
|
-
Object.values(streams).forEach((stream) => !stream.closed && stream.close());
|
|
97
|
-
}, writeExitCode: (code, error) => {
|
|
98
|
-
if (error) {
|
|
99
|
-
streams.exit.write(`Error: ${error.message}\n`);
|
|
100
|
-
if (error.stack) {
|
|
101
|
-
streams.exit.write(`Stack Trace:\n${error.stack}\n`);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
streams.exit.write(`${code}\n`);
|
|
105
|
-
}, exit: streams.exit });
|
|
106
|
-
}
|
|
107
|
-
catch (e) {
|
|
108
|
-
console.error(`Failed to create log streams in ${safeDest}:`, e);
|
|
109
|
-
throw e;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
async function fileHash(filePath, algorithm = "md5") {
|
|
113
|
-
return new Promise((resolve, reject) => {
|
|
114
|
-
const hash = crypto.createHash(algorithm);
|
|
115
|
-
const fileStream = fs.createReadStream(filePath);
|
|
116
|
-
fileStream.on("data", (data) => {
|
|
117
|
-
hash.update(data);
|
|
118
|
-
});
|
|
119
|
-
fileStream.on("end", () => {
|
|
120
|
-
const fileHash = hash.digest("hex");
|
|
121
|
-
resolve(fileHash);
|
|
122
|
-
});
|
|
123
|
-
fileStream.on("error", (error) => {
|
|
124
|
-
reject(`Error reading file: ${error.message}`);
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
const statusMessagePretty = (failures, test, runtime) => {
|
|
129
|
-
if (failures === 0) {
|
|
130
|
-
console.log(ansiC.green(ansiC.inverse(`${runtime} > ${test}`)));
|
|
131
|
-
}
|
|
132
|
-
else if (failures > 0) {
|
|
133
|
-
console.log(ansiC.red(ansiC.inverse(`${runtime} > ${test} failed ${failures} times (exit code: ${failures})`)));
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
console.log(ansiC.red(ansiC.inverse(`${runtime} > ${test} crashed (exit code: -1)`)));
|
|
137
|
-
}
|
|
138
|
-
};
|
|
139
|
-
async function writeFileAndCreateDir(filePath, data) {
|
|
140
|
-
const dirPath = path.dirname(filePath);
|
|
141
|
-
try {
|
|
142
|
-
await fs.promises.mkdir(dirPath, { recursive: true });
|
|
143
|
-
await fs.writeFileSync(filePath, data);
|
|
144
|
-
}
|
|
145
|
-
catch (error) {
|
|
146
|
-
console.error(`Error writing file: ${error}`);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
const filesHash = async (files, algorithm = "md5") => {
|
|
150
|
-
return new Promise((resolve, reject) => {
|
|
151
|
-
resolve(files.reduce(async (mm, f) => {
|
|
152
|
-
return (await mm) + (await fileHash(f));
|
|
153
|
-
}, Promise.resolve("")));
|
|
154
|
-
});
|
|
155
|
-
};
|
|
156
|
-
function isValidUrl(string) {
|
|
157
|
-
try {
|
|
158
|
-
new URL(string);
|
|
159
|
-
return true;
|
|
160
|
-
}
|
|
161
|
-
catch (err) {
|
|
162
|
-
return false;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
// Wait for file to exist, checks every 2 seconds by default
|
|
166
|
-
async function pollForFile(path, timeout = 2000) {
|
|
167
|
-
const intervalObj = setInterval(function () {
|
|
168
|
-
const file = path;
|
|
169
|
-
const fileExists = fs.existsSync(file);
|
|
170
|
-
if (fileExists) {
|
|
171
|
-
clearInterval(intervalObj);
|
|
172
|
-
}
|
|
173
|
-
}, timeout);
|
|
174
|
-
}
|
|
175
|
-
export class PM_Main extends PM_WithEslintAndTsc {
|
|
176
|
-
constructor(configs, name, mode) {
|
|
177
|
-
super(configs, name, mode);
|
|
178
|
-
this.logStreams = {};
|
|
179
|
-
this.sidecars = {};
|
|
180
|
-
this.clients = new Set();
|
|
181
|
-
this.runningProcesses = new Map();
|
|
182
|
-
this.allProcesses = new Map();
|
|
183
|
-
this.processLogs = new Map();
|
|
184
|
-
this.getRunnables = (tests, testName, payload = {
|
|
185
|
-
nodeEntryPoints: {},
|
|
186
|
-
nodeEntryPointSidecars: {},
|
|
187
|
-
webEntryPoints: {},
|
|
188
|
-
webEntryPointSidecars: {},
|
|
189
|
-
pureEntryPoints: {},
|
|
190
|
-
pureEntryPointSidecars: {},
|
|
191
|
-
}) => {
|
|
192
|
-
return getRunnables(tests, testName, payload);
|
|
193
|
-
};
|
|
16
|
+
export class PM_Main extends PM_WithProcesses {
|
|
17
|
+
constructor() {
|
|
18
|
+
super(...arguments);
|
|
194
19
|
this.launchPure = async (src, dest) => {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
.
|
|
200
|
-
.
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
process.exit(-1);
|
|
212
|
-
}
|
|
213
|
-
const testConfigResource = testConfig[2];
|
|
214
|
-
const portsToUse = [];
|
|
215
|
-
if (testConfigResource.ports === 0) {
|
|
216
|
-
argz = JSON.stringify({
|
|
217
|
-
scheduled: true,
|
|
218
|
-
name: src,
|
|
219
|
-
ports: portsToUse,
|
|
220
|
-
fs: reportDest,
|
|
221
|
-
browserWSEndpoint: this.browser.wsEndpoint(),
|
|
20
|
+
const processId = `pure-${src}-${Date.now()}`;
|
|
21
|
+
const command = `pure test: ${src}`;
|
|
22
|
+
// Create the promise
|
|
23
|
+
const purePromise = (async () => {
|
|
24
|
+
this.bddTestIsRunning(src);
|
|
25
|
+
const reportDest = `testeranto/reports/${this.name}/${src
|
|
26
|
+
.split(".")
|
|
27
|
+
.slice(0, -1)
|
|
28
|
+
.join(".")}/pure`;
|
|
29
|
+
if (!fs.existsSync(reportDest)) {
|
|
30
|
+
fs.mkdirSync(reportDest, { recursive: true });
|
|
31
|
+
}
|
|
32
|
+
const destFolder = dest.replace(".mjs", "");
|
|
33
|
+
let argz = "";
|
|
34
|
+
const testConfig = this.configs.tests.find((t) => {
|
|
35
|
+
return t[0] === src;
|
|
222
36
|
});
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
}
|
|
37
|
+
if (!testConfig) {
|
|
38
|
+
console.log(ansiC.inverse("missing test config! Exiting ungracefully!"));
|
|
39
|
+
process.exit(-1);
|
|
40
|
+
}
|
|
41
|
+
const testConfigResource = testConfig[2];
|
|
42
|
+
const portsToUse = [];
|
|
43
|
+
if (testConfigResource.ports === 0) {
|
|
231
44
|
argz = JSON.stringify({
|
|
232
45
|
scheduled: true,
|
|
233
46
|
name: src,
|
|
234
47
|
ports: portsToUse,
|
|
235
|
-
fs:
|
|
48
|
+
fs: reportDest,
|
|
236
49
|
browserWSEndpoint: this.browser.wsEndpoint(),
|
|
237
50
|
});
|
|
238
51
|
}
|
|
52
|
+
else if (testConfigResource.ports > 0) {
|
|
53
|
+
const openPorts = Object.entries(this.ports).filter(([portnumber, status]) => status === "");
|
|
54
|
+
if (openPorts.length >= testConfigResource.ports) {
|
|
55
|
+
for (let i = 0; i < testConfigResource.ports; i++) {
|
|
56
|
+
portsToUse.push(openPorts[i][0]);
|
|
57
|
+
this.ports[openPorts[i][0]] = src; // port is now claimed
|
|
58
|
+
}
|
|
59
|
+
argz = JSON.stringify({
|
|
60
|
+
scheduled: true,
|
|
61
|
+
name: src,
|
|
62
|
+
ports: portsToUse,
|
|
63
|
+
fs: destFolder,
|
|
64
|
+
browserWSEndpoint: this.browser.wsEndpoint(),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
this.queue.push(src);
|
|
69
|
+
return [Math.random(), argz];
|
|
70
|
+
}
|
|
71
|
+
}
|
|
239
72
|
else {
|
|
240
|
-
|
|
241
|
-
|
|
73
|
+
console.error("negative port makes no sense", src);
|
|
74
|
+
process.exit(-1);
|
|
242
75
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
// if (sidecar[1] === "web") {
|
|
257
|
-
// const s = await this.launchWebSideCar(
|
|
258
|
-
// sidecar[0],
|
|
259
|
-
// destinationOfRuntime(sidecar[0], "web", this.configs),
|
|
260
|
-
// sidecar
|
|
261
|
-
// );
|
|
262
|
-
// webSideCares.push(s);
|
|
263
|
-
// return s;
|
|
264
|
-
// }
|
|
265
|
-
// if (sidecar[1] === "node") {
|
|
266
|
-
// return this.launchNodeSideCar(
|
|
267
|
-
// sidecar[0],
|
|
268
|
-
// destinationOfRuntime(sidecar[0], "node", this.configs),
|
|
269
|
-
// sidecar
|
|
270
|
-
// );
|
|
271
|
-
// }
|
|
272
|
-
// })
|
|
273
|
-
// );
|
|
274
|
-
const logs = createLogStreams(reportDest, "pure");
|
|
275
|
-
try {
|
|
276
|
-
await import(`${builtfile}?cacheBust=${Date.now()}`).then((module) => {
|
|
277
|
-
// Override console methods to redirect logs
|
|
278
|
-
// Only override stdout/stderr methods for pure runtime
|
|
279
|
-
const originalConsole = Object.assign({}, console);
|
|
280
|
-
// console.log = (...args) => {
|
|
281
|
-
// logs.stdout.write(args.join(" ") + "\n");
|
|
282
|
-
// originalConsole.log(...args);
|
|
283
|
-
// };
|
|
284
|
-
// console.error = (...args) => {
|
|
285
|
-
// logs.stderr.write(args.join(" ") + "\n");
|
|
286
|
-
// originalConsole.error(...args);
|
|
287
|
-
// };
|
|
288
|
-
return module.default
|
|
289
|
-
.then((defaultModule) => {
|
|
290
|
-
defaultModule
|
|
291
|
-
.receiveTestResourceConfig(argz)
|
|
292
|
-
.then(async (results) => {
|
|
293
|
-
// this.receiveFeatures(results.features, destFolder, src, "pure");
|
|
294
|
-
// this.receiveFeaturesV2(reportDest, src, "pure");
|
|
295
|
-
statusMessagePretty(results.fails, src, "pure");
|
|
296
|
-
this.bddTestIsNowDone(src, results.fails);
|
|
76
|
+
const builtfile = dest;
|
|
77
|
+
const logs = createLogStreams(reportDest, "pure");
|
|
78
|
+
try {
|
|
79
|
+
await import(`${builtfile}?cacheBust=${Date.now()}`).then((module) => {
|
|
80
|
+
return module.default
|
|
81
|
+
.then((defaultModule) => {
|
|
82
|
+
return defaultModule
|
|
83
|
+
.receiveTestResourceConfig(argz)
|
|
84
|
+
.then(async (results) => {
|
|
85
|
+
statusMessagePretty(results.fails, src, "pure");
|
|
86
|
+
this.bddTestIsNowDone(src, results.fails);
|
|
87
|
+
return results.fails;
|
|
88
|
+
});
|
|
297
89
|
})
|
|
298
|
-
.catch((
|
|
299
|
-
console.log(
|
|
90
|
+
.catch((e2) => {
|
|
91
|
+
console.log(ansiColors.red(`pure ! ${src} failed to execute. No "tests.json" file was generated. Check the logs for more info`));
|
|
92
|
+
logs.exit.write(e2.stack);
|
|
93
|
+
logs.exit.write(-1);
|
|
300
94
|
this.bddTestIsNowDone(src, -1);
|
|
301
95
|
statusMessagePretty(-1, src, "pure");
|
|
96
|
+
throw e2;
|
|
302
97
|
});
|
|
303
|
-
// .finally(() => {
|
|
304
|
-
// // webSideCares.forEach((webSideCar) => webSideCar.close());
|
|
305
|
-
// });
|
|
306
|
-
})
|
|
307
|
-
.catch((e2) => {
|
|
308
|
-
console.log(ansiColors.red(`pure ! ${src} failed to execute. No "tests.json" file was generated. Check the logs for more info`));
|
|
309
|
-
logs.exit.write(e2.stack);
|
|
310
|
-
logs.exit.write(-1);
|
|
311
|
-
this.bddTestIsNowDone(src, -1);
|
|
312
|
-
statusMessagePretty(-1, src, "pure");
|
|
313
|
-
// console.error(e);
|
|
314
|
-
})
|
|
315
|
-
.finally((x) => {
|
|
316
|
-
// const fileSet = files[src] || new Set();
|
|
317
|
-
// fs.writeFileSync(
|
|
318
|
-
// reportDest + "/manifest.json",
|
|
319
|
-
// JSON.stringify(Array.from(fileSet))
|
|
320
|
-
// );
|
|
321
98
|
});
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
catch (e3) {
|
|
325
|
-
logs.writeExitCode(-1, e3);
|
|
326
|
-
console.log(ansiC.red(ansiC.inverse(`${src} 1 errored with: ${e3}. Check logs for more info`)));
|
|
327
|
-
logs.exit.write(e3.stack);
|
|
328
|
-
logs.exit.write("-1");
|
|
329
|
-
this.bddTestIsNowDone(src, -1);
|
|
330
|
-
statusMessagePretty(-1, src, "pure");
|
|
331
|
-
}
|
|
332
|
-
for (let i = 0; i <= portsToUse.length; i++) {
|
|
333
|
-
if (portsToUse[i]) {
|
|
334
|
-
this.ports[portsToUse[i]] = ""; //port is open again
|
|
335
99
|
}
|
|
336
|
-
|
|
100
|
+
catch (e3) {
|
|
101
|
+
logs.writeExitCode(-1, e3);
|
|
102
|
+
console.log(ansiC.red(ansiC.inverse(`${src} 1 errored with: ${e3}. Check logs for more info`)));
|
|
103
|
+
logs.exit.write(e3.stack);
|
|
104
|
+
logs.exit.write("-1");
|
|
105
|
+
this.bddTestIsNowDone(src, -1);
|
|
106
|
+
statusMessagePretty(-1, src, "pure");
|
|
107
|
+
throw e3;
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
for (let i = 0; i <= portsToUse.length; i++) {
|
|
111
|
+
if (portsToUse[i]) {
|
|
112
|
+
this.ports[portsToUse[i]] = ""; // port is open again
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
})();
|
|
117
|
+
// Add to process manager
|
|
118
|
+
this.addPromiseProcess(processId, purePromise, command, "bdd-test", src, "pure");
|
|
337
119
|
};
|
|
338
120
|
this.launchNode = async (src, dest) => {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
.
|
|
344
|
-
.
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
const
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
ports: [],
|
|
364
|
-
fs: reportDest,
|
|
365
|
-
browserWSEndpoint: this.browser.wsEndpoint(),
|
|
366
|
-
};
|
|
367
|
-
testResources = JSON.stringify(t);
|
|
368
|
-
}
|
|
369
|
-
else if (testConfigResource.ports > 0) {
|
|
370
|
-
const openPorts = Object.entries(this.ports).filter(([portnumber, portopen]) => portopen === "");
|
|
371
|
-
if (openPorts.length >= testConfigResource.ports) {
|
|
372
|
-
for (let i = 0; i < testConfigResource.ports; i++) {
|
|
373
|
-
portsToUse.push(openPorts[i][0]); // Convert string port to number
|
|
374
|
-
this.ports[openPorts[i][0]] = src; // port is now claimed
|
|
375
|
-
}
|
|
376
|
-
testResources = JSON.stringify({
|
|
377
|
-
scheduled: true,
|
|
121
|
+
const processId = `node-${src}-${Date.now()}`;
|
|
122
|
+
const command = `node test: ${src}`;
|
|
123
|
+
// Create the promise
|
|
124
|
+
const nodePromise = (async () => {
|
|
125
|
+
this.bddTestIsRunning(src);
|
|
126
|
+
const reportDest = `testeranto/reports/${this.name}/${src
|
|
127
|
+
.split(".")
|
|
128
|
+
.slice(0, -1)
|
|
129
|
+
.join(".")}/node`;
|
|
130
|
+
if (!fs.existsSync(reportDest)) {
|
|
131
|
+
fs.mkdirSync(reportDest, { recursive: true });
|
|
132
|
+
}
|
|
133
|
+
let testResources = "";
|
|
134
|
+
const testConfig = this.configs.tests.find((t) => {
|
|
135
|
+
return t[0] === src;
|
|
136
|
+
});
|
|
137
|
+
if (!testConfig) {
|
|
138
|
+
console.log(ansiC.inverse(`missing test config! Exiting ungracefully for '${src}'`));
|
|
139
|
+
process.exit(-1);
|
|
140
|
+
}
|
|
141
|
+
const testConfigResource = testConfig[2];
|
|
142
|
+
const portsToUse = [];
|
|
143
|
+
if (testConfigResource.ports === 0) {
|
|
144
|
+
const t = {
|
|
378
145
|
name: src,
|
|
379
|
-
ports:
|
|
146
|
+
ports: [],
|
|
380
147
|
fs: reportDest,
|
|
381
148
|
browserWSEndpoint: this.browser.wsEndpoint(),
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
else {
|
|
385
|
-
console.log(ansiC.red(`node: cannot run ${src} because there are no open ports ATM. This job will be enqueued and run again run a port is available`));
|
|
386
|
-
this.queue.push(src);
|
|
387
|
-
return [Math.random(), argz]; // Add this return
|
|
149
|
+
};
|
|
150
|
+
testResources = JSON.stringify(t);
|
|
388
151
|
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
let haltReturns = false;
|
|
396
|
-
const ipcfile = "/tmp/tpipe_" + Math.random();
|
|
397
|
-
const child = spawn("node",
|
|
398
|
-
// "node",
|
|
399
|
-
[
|
|
400
|
-
// "--inspect-brk",
|
|
401
|
-
builtfile,
|
|
402
|
-
testResources,
|
|
403
|
-
ipcfile,
|
|
404
|
-
], {
|
|
405
|
-
stdio: ["pipe", "pipe", "pipe", "ipc"],
|
|
406
|
-
});
|
|
407
|
-
let buffer = new Buffer("");
|
|
408
|
-
const server = net.createServer((socket) => {
|
|
409
|
-
const queue = new Queue();
|
|
410
|
-
socket.on("data", (data) => {
|
|
411
|
-
buffer = Buffer.concat([buffer, data]);
|
|
412
|
-
for (let b = 0; b < buffer.length + 1; b++) {
|
|
413
|
-
const c = buffer.slice(0, b);
|
|
414
|
-
let d;
|
|
415
|
-
try {
|
|
416
|
-
d = JSON.parse(c.toString());
|
|
417
|
-
queue.enqueue(d);
|
|
418
|
-
buffer = buffer.slice(b, buffer.length + 1);
|
|
419
|
-
b = 0;
|
|
420
|
-
}
|
|
421
|
-
catch (e) {
|
|
422
|
-
// b++;
|
|
152
|
+
else if (testConfigResource.ports > 0) {
|
|
153
|
+
const openPorts = Object.entries(this.ports).filter(([portnumber, portopen]) => portopen === "");
|
|
154
|
+
if (openPorts.length >= testConfigResource.ports) {
|
|
155
|
+
for (let i = 0; i < testConfigResource.ports; i++) {
|
|
156
|
+
portsToUse.push(openPorts[i][0]);
|
|
157
|
+
this.ports[openPorts[i][0]] = src; // port is now claimed
|
|
423
158
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
this.
|
|
430
|
-
|
|
431
|
-
const x = message.slice(1, -1);
|
|
432
|
-
const r = await this[command](...x);
|
|
433
|
-
if (!haltReturns) {
|
|
434
|
-
child.send(JSON.stringify({
|
|
435
|
-
payload: r,
|
|
436
|
-
key: message[message.length - 1],
|
|
437
|
-
}));
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
});
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
});
|
|
444
|
-
});
|
|
445
|
-
const logs = createLogStreams(reportDest, "node");
|
|
446
|
-
server.listen(ipcfile, () => {
|
|
447
|
-
var _a, _b;
|
|
448
|
-
// Only handle stdout/stderr for node runtime
|
|
449
|
-
(_a = child.stdout) === null || _a === void 0 ? void 0 : _a.on("data", (data) => {
|
|
450
|
-
var _a;
|
|
451
|
-
(_a = logs.stdout) === null || _a === void 0 ? void 0 : _a.write(data); // Add null check
|
|
452
|
-
});
|
|
453
|
-
(_b = child.stderr) === null || _b === void 0 ? void 0 : _b.on("data", (data) => {
|
|
454
|
-
var _a;
|
|
455
|
-
(_a = logs.stderr) === null || _a === void 0 ? void 0 : _a.write(data); // Add null check
|
|
456
|
-
});
|
|
457
|
-
child.on("error", (err) => { });
|
|
458
|
-
child.on("close", (code) => {
|
|
459
|
-
const exitCode = code === null ? -1 : code;
|
|
460
|
-
if (exitCode < 0) {
|
|
461
|
-
logs.writeExitCode(exitCode, new Error("Process crashed or was terminated"));
|
|
462
|
-
}
|
|
463
|
-
else {
|
|
464
|
-
logs.writeExitCode(exitCode);
|
|
465
|
-
}
|
|
466
|
-
logs.closeAll();
|
|
467
|
-
server.close();
|
|
468
|
-
if (!files[src]) {
|
|
469
|
-
files[src] = new Set();
|
|
470
|
-
}
|
|
471
|
-
if (exitCode === 255) {
|
|
472
|
-
console.log(ansiColors.red(`node ! ${src} failed to execute. No "tests.json" file was generated. Check ${reportDest}/stderr.log for more info`));
|
|
473
|
-
this.bddTestIsNowDone(src, -1);
|
|
474
|
-
statusMessagePretty(-1, src, "node");
|
|
475
|
-
return;
|
|
476
|
-
}
|
|
477
|
-
else if (exitCode === 0) {
|
|
478
|
-
this.bddTestIsNowDone(src, 0);
|
|
479
|
-
statusMessagePretty(0, src, "node");
|
|
159
|
+
testResources = JSON.stringify({
|
|
160
|
+
scheduled: true,
|
|
161
|
+
name: src,
|
|
162
|
+
ports: portsToUse,
|
|
163
|
+
fs: reportDest,
|
|
164
|
+
browserWSEndpoint: this.browser.wsEndpoint(),
|
|
165
|
+
});
|
|
480
166
|
}
|
|
481
167
|
else {
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
haltReturns = true;
|
|
486
|
-
});
|
|
487
|
-
child.on("exit", (code) => {
|
|
488
|
-
haltReturns = true;
|
|
489
|
-
for (let i = 0; i <= portsToUse.length; i++) {
|
|
490
|
-
if (portsToUse[i]) {
|
|
491
|
-
this.ports[portsToUse[i]] = ""; //port is open again
|
|
492
|
-
}
|
|
168
|
+
console.log(ansiC.red(`node: cannot run ${src} because there are no open ports ATM. This job will be enqueued and run again run a port is available`));
|
|
169
|
+
this.queue.push(src);
|
|
170
|
+
return [Math.random(), testResources];
|
|
493
171
|
}
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
console.error("negative port makes no sense", src);
|
|
175
|
+
process.exit(-1);
|
|
176
|
+
}
|
|
177
|
+
const builtfile = dest;
|
|
178
|
+
let haltReturns = false;
|
|
179
|
+
const ipcfile = "/tmp/tpipe_" + Math.random();
|
|
180
|
+
const child = spawn("node", [builtfile, testResources, ipcfile], {
|
|
181
|
+
stdio: ["pipe", "pipe", "pipe", "ipc"],
|
|
494
182
|
});
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
const destFolder = dest.replace(".mjs", "");
|
|
509
|
-
console.log(ansiC.green(ansiC.inverse(`launchWebSideCar ${src}`)));
|
|
510
|
-
// const fileStreams2: fs.WriteStream[] = [];
|
|
511
|
-
// const doneFileStream2: Promise<any>[] = [];
|
|
512
|
-
const logs = createLogStreams(dest, "web");
|
|
513
|
-
return new Promise((res, rej) => {
|
|
514
|
-
this.browser
|
|
515
|
-
.newPage()
|
|
516
|
-
.then(async (page) => {
|
|
517
|
-
this.mapping().forEach(async ([command, func]) => {
|
|
518
|
-
page.exposeFunction(command, func);
|
|
519
|
-
});
|
|
520
|
-
const close = () => {
|
|
521
|
-
if (!files[src]) {
|
|
522
|
-
files[src] = new Set();
|
|
523
|
-
}
|
|
524
|
-
// files[src].add(filepath);
|
|
525
|
-
// fs.writeFileSync(
|
|
526
|
-
// destFolder + "/manifest.json",
|
|
527
|
-
// JSON.stringify(Array.from(files[src]))
|
|
528
|
-
// );
|
|
529
|
-
delete files[src];
|
|
530
|
-
Promise.all(screenshots[src] || []).then(() => {
|
|
531
|
-
delete screenshots[src];
|
|
532
|
-
page.close();
|
|
533
|
-
});
|
|
534
|
-
};
|
|
535
|
-
page.on("pageerror", (err) => {
|
|
536
|
-
console.debug(`Error from ${src}: [${err.name}] `);
|
|
537
|
-
console.debug(`Error from ${src}: [${err.name}] `);
|
|
538
|
-
if (err.cause) {
|
|
539
|
-
console.debug(`Error from ${src} cause: [${err.cause}] `);
|
|
540
|
-
}
|
|
541
|
-
if (err.stack) {
|
|
542
|
-
console.debug(`Error from stack ${src}: [${err.stack}] `);
|
|
543
|
-
}
|
|
544
|
-
console.debug(`Error from message ${src}: [${err.message}] `);
|
|
545
|
-
this.bddTestIsNowDone(src, -1);
|
|
546
|
-
close();
|
|
547
|
-
});
|
|
548
|
-
page.on("console", (log) => {
|
|
549
|
-
var _a, _b, _c, _d;
|
|
550
|
-
const msg = `${log.text()}\n${JSON.stringify(log.location())}\n${JSON.stringify(log.stackTrace())}\n`;
|
|
551
|
-
switch (log.type()) {
|
|
552
|
-
case "info":
|
|
553
|
-
(_a = logs.info) === null || _a === void 0 ? void 0 : _a.write(msg);
|
|
554
|
-
break;
|
|
555
|
-
case "warn":
|
|
556
|
-
(_b = logs.warn) === null || _b === void 0 ? void 0 : _b.write(msg);
|
|
557
|
-
break;
|
|
558
|
-
case "error":
|
|
559
|
-
(_c = logs.error) === null || _c === void 0 ? void 0 : _c.write(msg);
|
|
560
|
-
break;
|
|
561
|
-
case "debug":
|
|
562
|
-
(_d = logs.debug) === null || _d === void 0 ? void 0 : _d.write(msg);
|
|
563
|
-
break;
|
|
564
|
-
default:
|
|
565
|
-
break;
|
|
566
|
-
}
|
|
567
|
-
});
|
|
568
|
-
await page.goto(`file://${`${destFolder}.html`}`, {});
|
|
569
|
-
const webArgz = JSON.stringify({
|
|
570
|
-
name: dest,
|
|
571
|
-
ports: [].toString(),
|
|
572
|
-
fs: dest,
|
|
573
|
-
browserWSEndpoint: this.browser.wsEndpoint(),
|
|
574
|
-
});
|
|
575
|
-
const d = `${dest}?cacheBust=${Date.now()}`;
|
|
576
|
-
const evaluation = `
|
|
577
|
-
import('${d}').then(async (x) => {
|
|
578
|
-
|
|
579
|
-
try {
|
|
580
|
-
return await (await x.default).receiveTestResourceConfig(${webArgz})
|
|
581
|
-
} catch (e) {
|
|
582
|
-
console.log("fail", e.toString())
|
|
583
|
-
}
|
|
584
|
-
})`;
|
|
585
|
-
await page
|
|
586
|
-
.evaluate(evaluation)
|
|
587
|
-
.then(async ({ fails, failed, features }) => {
|
|
588
|
-
// this.receiveFeatures(features, destFolder, src, "web");
|
|
589
|
-
// this.receiveFeaturesV2(reportDest, src, "web");
|
|
590
|
-
statusMessagePretty(fails, src, "web");
|
|
591
|
-
this.bddTestIsNowDone(src, fails);
|
|
592
|
-
})
|
|
593
|
-
.catch((e) => {
|
|
594
|
-
console.log(ansiC.red(ansiC.inverse(`launchWebSidecar - ${src} errored with: ${e}`)));
|
|
595
|
-
})
|
|
596
|
-
.finally(() => {
|
|
597
|
-
this.bddTestIsNowDone(src, -1);
|
|
598
|
-
close();
|
|
599
|
-
});
|
|
600
|
-
return page;
|
|
601
|
-
// return page;
|
|
602
|
-
})
|
|
603
|
-
.then(async (page) => {
|
|
604
|
-
await page.goto(`file://${`${dest}.html`}`, {});
|
|
605
|
-
res([Math.random(), page]);
|
|
606
|
-
});
|
|
607
|
-
});
|
|
608
|
-
};
|
|
609
|
-
this.launchNodeSideCar = async (sidecar) => {
|
|
610
|
-
const src = sidecar[0];
|
|
611
|
-
const dest = process.cwd() + `/testeranto/bundles/node/${this.name}/${sidecar[0]}`;
|
|
612
|
-
const d = dest + ".mjs";
|
|
613
|
-
console.log(ansiC.green(ansiC.inverse(`launchNodeSideCar ${sidecar[0]}`)));
|
|
614
|
-
const destFolder = dest.replace(".ts", "");
|
|
615
|
-
const reportDest = `testeranto/reports/${this.name}/${src
|
|
616
|
-
.split(".")
|
|
617
|
-
.slice(0, -1)
|
|
618
|
-
.join(".")}/node`;
|
|
619
|
-
const argz = {
|
|
620
|
-
name: sidecar[0],
|
|
621
|
-
ports: [],
|
|
622
|
-
fs: destFolder,
|
|
623
|
-
browserWSEndpoint: this.browser.wsEndpoint(),
|
|
624
|
-
};
|
|
625
|
-
const testReq = sidecar[2];
|
|
626
|
-
const logs = createLogStreams(dest, "node");
|
|
627
|
-
const portsToUse = [];
|
|
628
|
-
if (testReq.ports === 0) {
|
|
629
|
-
// argz = {
|
|
630
|
-
// name: sidecar[0],
|
|
631
|
-
// ports: portsToUse,
|
|
632
|
-
// fs: destFolder,
|
|
633
|
-
// browserWSEndpoint: this.browser.wsEndpoint(),
|
|
634
|
-
// };
|
|
635
|
-
}
|
|
636
|
-
else if (testReq.ports > 0) {
|
|
637
|
-
const openPorts = Object.entries(this.ports).filter(([portnumber, portopen]) => portopen === "");
|
|
638
|
-
if (openPorts.length >= testReq.ports) {
|
|
639
|
-
for (let i = 0; i < testReq.ports; i++) {
|
|
640
|
-
portsToUse.push(Number(openPorts[i][0])); // Convert string port to number
|
|
641
|
-
this.ports[openPorts[i][0]] = src; // port is now closed
|
|
642
|
-
}
|
|
643
|
-
argz.ports = portsToUse;
|
|
644
|
-
const builtfile = destFolder + ".mjs";
|
|
645
|
-
let haltReturns = false;
|
|
646
|
-
let buffer = new Buffer("");
|
|
647
|
-
const server = net.createServer((socket) => {
|
|
648
|
-
socket.on("data", (data) => {
|
|
649
|
-
buffer = Buffer.concat([buffer, data]);
|
|
650
|
-
const messages = [];
|
|
651
|
-
for (let b = 0; b < buffer.length + 1; b++) {
|
|
652
|
-
const c = buffer.slice(0, b);
|
|
653
|
-
let d;
|
|
654
|
-
try {
|
|
655
|
-
d = JSON.parse(c.toString());
|
|
656
|
-
messages.push(d);
|
|
657
|
-
buffer = buffer.slice(b, buffer.length + 1);
|
|
658
|
-
b = 0;
|
|
659
|
-
}
|
|
660
|
-
catch (e) {
|
|
661
|
-
// b++;
|
|
662
|
-
}
|
|
183
|
+
let buffer = new Buffer("");
|
|
184
|
+
const server = net.createServer((socket) => {
|
|
185
|
+
const queue = new Queue();
|
|
186
|
+
socket.on("data", (data) => {
|
|
187
|
+
buffer = Buffer.concat([buffer, data]);
|
|
188
|
+
for (let b = 0; b < buffer.length + 1; b++) {
|
|
189
|
+
const c = buffer.slice(0, b);
|
|
190
|
+
let d;
|
|
191
|
+
try {
|
|
192
|
+
d = JSON.parse(c.toString());
|
|
193
|
+
queue.enqueue(d);
|
|
194
|
+
buffer = buffer.slice(b, buffer.length + 1);
|
|
195
|
+
b = 0;
|
|
663
196
|
}
|
|
664
|
-
|
|
197
|
+
catch (e) {
|
|
198
|
+
// b++;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
while (queue.size() > 0) {
|
|
202
|
+
const message = queue.dequeue();
|
|
203
|
+
if (message) {
|
|
204
|
+
// set up the "node" listeners
|
|
665
205
|
this.mapping().forEach(async ([command, func]) => {
|
|
666
|
-
if (
|
|
667
|
-
const x =
|
|
206
|
+
if (message[0] === command) {
|
|
207
|
+
const x = message.slice(1, -1);
|
|
668
208
|
const r = await this[command](...x);
|
|
669
209
|
if (!haltReturns) {
|
|
670
210
|
child.send(JSON.stringify({
|
|
671
211
|
payload: r,
|
|
672
|
-
key:
|
|
212
|
+
key: message[message.length - 1],
|
|
673
213
|
}));
|
|
674
214
|
}
|
|
675
215
|
}
|
|
676
216
|
});
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
});
|
|
680
|
-
const child = spawn("node", [builtfile, JSON.stringify(argz)], {
|
|
681
|
-
stdio: ["pipe", "pipe", "pipe", "ipc"],
|
|
682
|
-
// silent: true
|
|
217
|
+
}
|
|
218
|
+
}
|
|
683
219
|
});
|
|
684
|
-
|
|
685
|
-
|
|
220
|
+
});
|
|
221
|
+
const logs = createLogStreams(reportDest, "node");
|
|
222
|
+
return new Promise((resolve, reject) => {
|
|
223
|
+
server.listen(ipcfile, () => {
|
|
224
|
+
var _a, _b;
|
|
225
|
+
(_a = child.stdout) === null || _a === void 0 ? void 0 : _a.on("data", (data) => {
|
|
226
|
+
var _a;
|
|
227
|
+
(_a = logs.stdout) === null || _a === void 0 ? void 0 : _a.write(data);
|
|
228
|
+
});
|
|
229
|
+
(_b = child.stderr) === null || _b === void 0 ? void 0 : _b.on("data", (data) => {
|
|
230
|
+
var _a;
|
|
231
|
+
(_a = logs.stderr) === null || _a === void 0 ? void 0 : _a.write(data);
|
|
232
|
+
});
|
|
686
233
|
child.on("close", (code) => {
|
|
234
|
+
const exitCode = code === null ? -1 : code;
|
|
235
|
+
if (exitCode < 0) {
|
|
236
|
+
logs.writeExitCode(exitCode, new Error("Process crashed or was terminated"));
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
logs.writeExitCode(exitCode);
|
|
240
|
+
}
|
|
241
|
+
logs.closeAll();
|
|
687
242
|
server.close();
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
243
|
+
if (exitCode === 255) {
|
|
244
|
+
console.log(ansiColors.red(`node ! ${src} failed to execute. No "tests.json" file was generated. Check ${reportDest}/stderr.log for more info`));
|
|
245
|
+
this.bddTestIsNowDone(src, -1);
|
|
246
|
+
statusMessagePretty(-1, src, "node");
|
|
247
|
+
reject(new Error(`Process exited with code ${exitCode}`));
|
|
248
|
+
}
|
|
249
|
+
else if (exitCode === 0) {
|
|
250
|
+
this.bddTestIsNowDone(src, 0);
|
|
251
|
+
statusMessagePretty(0, src, "node");
|
|
252
|
+
resolve();
|
|
696
253
|
}
|
|
254
|
+
else {
|
|
255
|
+
this.bddTestIsNowDone(src, exitCode);
|
|
256
|
+
statusMessagePretty(exitCode, src, "node");
|
|
257
|
+
reject(new Error(`Process exited with code ${exitCode}`));
|
|
258
|
+
}
|
|
259
|
+
haltReturns = true;
|
|
697
260
|
});
|
|
698
261
|
child.on("error", (e) => {
|
|
699
|
-
|
|
700
|
-
if (fs.existsSync(p)) {
|
|
701
|
-
fs.rmSync(p);
|
|
702
|
-
}
|
|
262
|
+
console.log("error");
|
|
703
263
|
haltReturns = true;
|
|
704
|
-
console.log(ansiC.red(ansiC.inverse(
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
264
|
+
console.log(ansiC.red(ansiC.inverse(`${src} errored with: ${e.name}. Check error logs for more info`)));
|
|
265
|
+
this.bddTestIsNowDone(src, -1);
|
|
266
|
+
statusMessagePretty(-1, src, "node");
|
|
267
|
+
reject(e);
|
|
708
268
|
});
|
|
709
269
|
});
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
else {
|
|
716
|
-
console.log(ansiC.red(`cannot ${src} because there are no open ports. the job will be unqueued`));
|
|
717
|
-
this.queue.push(sidecar[0]);
|
|
718
|
-
return [Math.random(), argz];
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
else {
|
|
722
|
-
console.error("negative port makes no sense", sidecar[0]);
|
|
723
|
-
process.exit(-1);
|
|
724
|
-
}
|
|
725
|
-
};
|
|
726
|
-
this.stopPureSideCar = async (uid) => {
|
|
727
|
-
console.log(ansiC.green(ansiC.inverse(`stopPureSideCar ${uid}`)));
|
|
728
|
-
await this.sidecars[uid].shutdown();
|
|
729
|
-
return;
|
|
730
|
-
};
|
|
731
|
-
this.launchPureSideCar = async (sidecar) => {
|
|
732
|
-
console.log(ansiC.green(ansiC.inverse(`launchPureSideCar ${sidecar[0]}`)));
|
|
733
|
-
const r = Math.random();
|
|
734
|
-
const dest = process.cwd() + `/testeranto/bundles/pure/${this.name}/${sidecar[0]}`;
|
|
735
|
-
const builtfile = dest.split(".").slice(0, -1).concat("mjs").join(".");
|
|
736
|
-
const destFolder = dest.replace(".mjs", "");
|
|
737
|
-
let argz;
|
|
738
|
-
const z = sidecar[2];
|
|
739
|
-
const testConfigResource = sidecar[2];
|
|
740
|
-
const src = sidecar[0];
|
|
741
|
-
const portsToUse = [];
|
|
742
|
-
if (testConfigResource.ports === 0) {
|
|
743
|
-
argz = {
|
|
744
|
-
// scheduled: true,
|
|
745
|
-
name: src,
|
|
746
|
-
ports: portsToUse,
|
|
747
|
-
fs: destFolder,
|
|
748
|
-
browserWSEndpoint: this.browser.wsEndpoint(),
|
|
749
|
-
};
|
|
750
|
-
}
|
|
751
|
-
else if (testConfigResource.ports > 0) {
|
|
752
|
-
const openPorts = Object.entries(this.ports).filter(([portnumber, portopen]) => portopen === "");
|
|
753
|
-
if (openPorts.length >= testConfigResource.ports) {
|
|
754
|
-
for (let i = 0; i < testConfigResource.ports; i++) {
|
|
755
|
-
portsToUse.push(Number(openPorts[i][0]));
|
|
756
|
-
this.ports[openPorts[i][0]] = src; // port is now claimed
|
|
270
|
+
}).finally(() => {
|
|
271
|
+
for (let i = 0; i <= portsToUse.length; i++) {
|
|
272
|
+
if (portsToUse[i]) {
|
|
273
|
+
this.ports[portsToUse[i]] = ""; //port is open again
|
|
274
|
+
}
|
|
757
275
|
}
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
ports: portsToUse,
|
|
763
|
-
fs: ".",
|
|
764
|
-
browserWSEndpoint: this.browser.wsEndpoint(),
|
|
765
|
-
};
|
|
766
|
-
}
|
|
767
|
-
else {
|
|
768
|
-
this.queue.push(src);
|
|
769
|
-
// return;
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
else {
|
|
773
|
-
console.error("negative port makes no sense", src);
|
|
774
|
-
process.exit(-1);
|
|
775
|
-
}
|
|
776
|
-
// const builtfile = dest + ".mjs";
|
|
777
|
-
await import(`${builtfile}?cacheBust=${Date.now()}`).then((module) => {
|
|
778
|
-
if (!this.pureSidecars)
|
|
779
|
-
this.pureSidecars = {};
|
|
780
|
-
this.pureSidecars[r] = module.default;
|
|
781
|
-
this.pureSidecars[r].start(argz);
|
|
782
|
-
});
|
|
783
|
-
return [r, argz];
|
|
784
|
-
// for (let i = 0; i <= portsToUse.length; i++) {
|
|
785
|
-
// if (portsToUse[i]) {
|
|
786
|
-
// this.ports[portsToUse[i]] = "true"; //port is open again
|
|
787
|
-
// }
|
|
788
|
-
// }
|
|
789
|
-
};
|
|
790
|
-
this.launchPitono = async (src, dest) => {
|
|
791
|
-
console.log(ansiC.green(ansiC.inverse(`pitono < ${src}`)));
|
|
792
|
-
this.bddTestIsRunning(src);
|
|
793
|
-
const reportDest = `testeranto/reports/${this.name}/${src
|
|
794
|
-
.split(".")
|
|
795
|
-
.slice(0, -1)
|
|
796
|
-
.join(".")}/pitono`;
|
|
797
|
-
if (!fs.existsSync(reportDest)) {
|
|
798
|
-
fs.mkdirSync(reportDest, { recursive: true });
|
|
799
|
-
}
|
|
800
|
-
const logs = createLogStreams(reportDest, "node"); // Use node-style logs for pitono
|
|
801
|
-
try {
|
|
802
|
-
// Execute the Python test using the pitono runner
|
|
803
|
-
const { PitonoRunner } = await import('./pitonoRunner');
|
|
804
|
-
const runner = new PitonoRunner(this.configs, this.name);
|
|
805
|
-
await runner.run();
|
|
806
|
-
this.bddTestIsNowDone(src, 0);
|
|
807
|
-
statusMessagePretty(0, src, "pitono");
|
|
808
|
-
}
|
|
809
|
-
catch (error) {
|
|
810
|
-
logs.writeExitCode(-1, error);
|
|
811
|
-
console.log(ansiC.red(ansiC.inverse(`${src} errored with: ${error}. Check logs for more info`)));
|
|
812
|
-
this.bddTestIsNowDone(src, -1);
|
|
813
|
-
statusMessagePretty(-1, src, "pitono");
|
|
814
|
-
}
|
|
276
|
+
});
|
|
277
|
+
})();
|
|
278
|
+
// Add to process manager
|
|
279
|
+
this.addPromiseProcess(processId, nodePromise, command, "bdd-test", src, "node");
|
|
815
280
|
};
|
|
816
281
|
this.launchWeb = async (src, dest) => {
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
.
|
|
822
|
-
.
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
this.browser
|
|
836
|
-
.newPage()
|
|
837
|
-
.then((page) => {
|
|
838
|
-
page.on("console", (log) => {
|
|
839
|
-
var _a, _b, _c, _d;
|
|
840
|
-
const msg = `${log.text()}\n`;
|
|
841
|
-
switch (log.type()) {
|
|
842
|
-
case "info":
|
|
843
|
-
(_a = logs.info) === null || _a === void 0 ? void 0 : _a.write(msg);
|
|
844
|
-
break;
|
|
845
|
-
case "warn":
|
|
846
|
-
(_b = logs.warn) === null || _b === void 0 ? void 0 : _b.write(msg);
|
|
847
|
-
break;
|
|
848
|
-
case "error":
|
|
849
|
-
(_c = logs.error) === null || _c === void 0 ? void 0 : _c.write(msg);
|
|
850
|
-
break;
|
|
851
|
-
case "debug":
|
|
852
|
-
(_d = logs.debug) === null || _d === void 0 ? void 0 : _d.write(msg);
|
|
853
|
-
break;
|
|
854
|
-
default:
|
|
855
|
-
break;
|
|
856
|
-
}
|
|
857
|
-
});
|
|
858
|
-
page.on("close", () => {
|
|
859
|
-
logs.writeExitCode(0); // Web tests exit with 0 unless there's an error
|
|
860
|
-
logs.closeAll();
|
|
861
|
-
logs.closeAll();
|
|
282
|
+
const processId = `web-${src}-${Date.now()}`;
|
|
283
|
+
const command = `web test: ${src}`;
|
|
284
|
+
// Create the promise
|
|
285
|
+
const webPromise = (async () => {
|
|
286
|
+
this.bddTestIsRunning(src);
|
|
287
|
+
const reportDest = `testeranto/reports/${this.name}/${src
|
|
288
|
+
.split(".")
|
|
289
|
+
.slice(0, -1)
|
|
290
|
+
.join(".")}/web`;
|
|
291
|
+
if (!fs.existsSync(reportDest)) {
|
|
292
|
+
fs.mkdirSync(reportDest, { recursive: true });
|
|
293
|
+
}
|
|
294
|
+
const destFolder = dest.replace(".mjs", "");
|
|
295
|
+
const webArgz = JSON.stringify({
|
|
296
|
+
name: src,
|
|
297
|
+
ports: [].toString(),
|
|
298
|
+
fs: reportDest,
|
|
299
|
+
browserWSEndpoint: this.browser.wsEndpoint(),
|
|
862
300
|
});
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
301
|
+
const d = `${dest}?cacheBust=${Date.now()}`;
|
|
302
|
+
const logs = createLogStreams(reportDest, "web");
|
|
303
|
+
return new Promise((resolve, reject) => {
|
|
304
|
+
this.browser
|
|
305
|
+
.newPage()
|
|
306
|
+
.then((page) => {
|
|
307
|
+
page.on("console", (log) => {
|
|
308
|
+
var _a, _b, _c, _d;
|
|
309
|
+
const msg = `${log.text()}\n`;
|
|
310
|
+
switch (log.type()) {
|
|
311
|
+
case "info":
|
|
312
|
+
(_a = logs.info) === null || _a === void 0 ? void 0 : _a.write(msg);
|
|
313
|
+
break;
|
|
314
|
+
case "warn":
|
|
315
|
+
(_b = logs.warn) === null || _b === void 0 ? void 0 : _b.write(msg);
|
|
316
|
+
break;
|
|
317
|
+
case "error":
|
|
318
|
+
(_c = logs.error) === null || _c === void 0 ? void 0 : _c.write(msg);
|
|
319
|
+
break;
|
|
320
|
+
case "debug":
|
|
321
|
+
(_d = logs.debug) === null || _d === void 0 ? void 0 : _d.write(msg);
|
|
322
|
+
break;
|
|
323
|
+
default:
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
page.on("close", () => {
|
|
328
|
+
logs.writeExitCode(0);
|
|
329
|
+
logs.closeAll();
|
|
330
|
+
});
|
|
331
|
+
this.mapping().forEach(async ([command, func]) => {
|
|
332
|
+
if (command === "page") {
|
|
333
|
+
page.exposeFunction(command, (x) => {
|
|
334
|
+
if (x) {
|
|
335
|
+
return func(x);
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
return func(page.mainFrame()._id);
|
|
339
|
+
}
|
|
340
|
+
});
|
|
868
341
|
}
|
|
869
342
|
else {
|
|
870
|
-
return
|
|
343
|
+
return page.exposeFunction(command, func);
|
|
871
344
|
}
|
|
872
345
|
});
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
page.
|
|
346
|
+
return page;
|
|
347
|
+
})
|
|
348
|
+
.then(async (page) => {
|
|
349
|
+
const close = () => {
|
|
350
|
+
if (!files[src]) {
|
|
351
|
+
files[src] = new Set();
|
|
352
|
+
}
|
|
353
|
+
delete files[src];
|
|
354
|
+
Promise.all(screenshots[src] || []).then(() => {
|
|
355
|
+
delete screenshots[src];
|
|
356
|
+
page.close();
|
|
357
|
+
});
|
|
358
|
+
};
|
|
359
|
+
page.on("pageerror", (err) => {
|
|
360
|
+
logs.writeExitCode(-1, err);
|
|
361
|
+
console.log(ansiColors.red(`web ! ${src} failed to execute No "tests.json" file was generated. Check ${reportDest}/error.log for more info`));
|
|
362
|
+
this.bddTestIsNowDone(src, -1);
|
|
363
|
+
close();
|
|
364
|
+
reject(err);
|
|
365
|
+
});
|
|
366
|
+
await page.goto(`file://${`${destFolder}.html`}`, {});
|
|
367
|
+
await page
|
|
368
|
+
.evaluate(webEvaluator(d, webArgz))
|
|
369
|
+
.then(async ({ fails, failed, features }) => {
|
|
370
|
+
statusMessagePretty(fails, src, "web");
|
|
371
|
+
this.bddTestIsNowDone(src, fails);
|
|
372
|
+
resolve();
|
|
373
|
+
})
|
|
374
|
+
.catch((e) => {
|
|
375
|
+
console.log(ansiC.red(ansiC.inverse(e.stack)));
|
|
376
|
+
console.log(ansiC.red(ansiC.inverse(`web ! ${src} failed to execute. No "tests.json" file was generated. Check logs for more info`)));
|
|
377
|
+
this.bddTestIsNowDone(src, -1);
|
|
378
|
+
reject(e);
|
|
379
|
+
})
|
|
380
|
+
.finally(() => {
|
|
381
|
+
close();
|
|
382
|
+
});
|
|
383
|
+
})
|
|
384
|
+
.catch((error) => {
|
|
385
|
+
reject(error);
|
|
894
386
|
});
|
|
895
|
-
return;
|
|
896
|
-
};
|
|
897
|
-
page.on("pageerror", (err) => {
|
|
898
|
-
logs.writeExitCode(-1, err);
|
|
899
|
-
console.log(ansiColors.red(`web ! ${src} failed to execute No "tests.json" file was generated. Check ${reportDest}/error.log for more info`));
|
|
900
|
-
this.bddTestIsNowDone(src, -1);
|
|
901
|
-
close();
|
|
902
|
-
});
|
|
903
|
-
// page.on("console", (log: ConsoleMessage) => {});
|
|
904
|
-
await page.goto(`file://${`${destFolder}.html`}`, {});
|
|
905
|
-
await page
|
|
906
|
-
.evaluate(`
|
|
907
|
-
import('${d}').then(async (x) => {
|
|
908
|
-
try {
|
|
909
|
-
return await (await x.default).receiveTestResourceConfig(${webArgz})
|
|
910
|
-
} catch (e) {
|
|
911
|
-
console.log("web run failure", e.toString())
|
|
912
|
-
}
|
|
913
|
-
})
|
|
914
|
-
`)
|
|
915
|
-
.then(async ({ fails, failed, features }) => {
|
|
916
|
-
statusMessagePretty(fails, src, "web");
|
|
917
|
-
this.bddTestIsNowDone(src, fails);
|
|
918
|
-
// close();
|
|
919
|
-
})
|
|
920
|
-
.catch((e) => {
|
|
921
|
-
console.log(ansiC.red(ansiC.inverse(e.stack)));
|
|
922
|
-
console.log(ansiC.red(ansiC.inverse(`web ! ${src} failed to execute. No "tests.json" file was generated. Check logs for more info`)));
|
|
923
|
-
this.bddTestIsNowDone(src, -1);
|
|
924
|
-
})
|
|
925
|
-
.finally(() => {
|
|
926
|
-
// process.exit(-1);
|
|
927
|
-
close();
|
|
928
387
|
});
|
|
929
|
-
|
|
930
|
-
|
|
388
|
+
})();
|
|
389
|
+
// Add to process manager
|
|
390
|
+
this.addPromiseProcess(processId, webPromise, command, "bdd-test", src, "web");
|
|
931
391
|
};
|
|
932
|
-
this.
|
|
933
|
-
const
|
|
934
|
-
|
|
935
|
-
const
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
return;
|
|
939
|
-
}
|
|
940
|
-
const testReport = JSON.parse(fs.readFileSync(testReportPath, "utf8"));
|
|
941
|
-
// Add full path information to each test
|
|
942
|
-
if (testReport.tests) {
|
|
943
|
-
testReport.tests.forEach((test) => {
|
|
944
|
-
// Add the full path to each test
|
|
945
|
-
test.fullPath = path.resolve(process.cwd(), srcTest);
|
|
946
|
-
});
|
|
947
|
-
}
|
|
948
|
-
// Add full path to the report itself
|
|
949
|
-
testReport.fullPath = path.resolve(process.cwd(), srcTest);
|
|
950
|
-
// Write the modified report back
|
|
951
|
-
fs.writeFileSync(testReportPath, JSON.stringify(testReport, null, 2));
|
|
952
|
-
testReport.features
|
|
953
|
-
.reduce(async (mm, featureStringKey) => {
|
|
954
|
-
const accum = await mm;
|
|
955
|
-
const isUrl = isValidUrl(featureStringKey);
|
|
956
|
-
if (isUrl) {
|
|
957
|
-
const u = new URL(featureStringKey);
|
|
958
|
-
if (u.protocol === "file:") {
|
|
959
|
-
const newPath = `${process.cwd()}/testeranto/features/internal/${path.relative(process.cwd(), u.pathname)}`;
|
|
960
|
-
// await fs.promises.mkdir(path.dirname(newPath), { recursive: true });
|
|
961
|
-
// try {
|
|
962
|
-
// await fs.unlinkSync(newPath);
|
|
963
|
-
// // console.log(`Removed existing link at ${newPath}`);
|
|
964
|
-
// } catch (error) {
|
|
965
|
-
// if (error.code !== "ENOENT") {
|
|
966
|
-
// // throw error;
|
|
967
|
-
// }
|
|
968
|
-
// }
|
|
969
|
-
// fs.symlink(u.pathname, newPath, (err) => {
|
|
970
|
-
// if (err) {
|
|
971
|
-
// // console.error("Error creating symlink:", err);
|
|
972
|
-
// } else {
|
|
973
|
-
// // console.log("Symlink created successfully");
|
|
974
|
-
// }
|
|
975
|
-
// });
|
|
976
|
-
accum.files.push(u.pathname);
|
|
977
|
-
}
|
|
978
|
-
else if (u.protocol === "http:" || u.protocol === "https:") {
|
|
979
|
-
const newPath = `${process.cwd()}/testeranto/features/external/${u.hostname}${u.pathname}`;
|
|
980
|
-
const body = await this.configs.featureIngestor(featureStringKey);
|
|
981
|
-
writeFileAndCreateDir(newPath, body);
|
|
982
|
-
accum.files.push(newPath);
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
else {
|
|
986
|
-
await fs.promises.mkdir(path.dirname(featureDestination), {
|
|
987
|
-
recursive: true,
|
|
988
|
-
});
|
|
989
|
-
accum.strings.push(featureStringKey);
|
|
990
|
-
}
|
|
991
|
-
return accum;
|
|
992
|
-
}, Promise.resolve({ files: [], strings: [] }))
|
|
993
|
-
.then(({ files, strings }) => {
|
|
994
|
-
// Markdown files must be referenced in the prompt but string style features are already present in the tests.json file
|
|
995
|
-
fs.writeFileSync(`testeranto/reports/${this.name}/${srcTest
|
|
392
|
+
this.launchPython = async (src, dest) => {
|
|
393
|
+
const processId = `python-${src}-${Date.now()}`;
|
|
394
|
+
const command = `python test: ${src}`;
|
|
395
|
+
const pythonPromise = (async () => {
|
|
396
|
+
this.bddTestIsRunning(src);
|
|
397
|
+
const reportDest = `testeranto/reports/${this.name}/${src
|
|
996
398
|
.split(".")
|
|
997
399
|
.slice(0, -1)
|
|
998
|
-
.join(".")}
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
})
|
|
1002
|
-
.join("\n"));
|
|
1003
|
-
});
|
|
1004
|
-
// const f: Record<string, string> = {};
|
|
1005
|
-
testReport.givens.forEach((g) => {
|
|
1006
|
-
if (g.failed === true) {
|
|
1007
|
-
this.summary[srcTest].failingFeatures[g.key] = g.features;
|
|
1008
|
-
}
|
|
1009
|
-
});
|
|
1010
|
-
// this.summary[srcTest].failingFeatures = f;
|
|
1011
|
-
this.writeBigBoard();
|
|
1012
|
-
};
|
|
1013
|
-
this.checkForShutdown = () => {
|
|
1014
|
-
// console.log(ansiC.inverse(JSON.stringify(this.summary, null, 2)));
|
|
1015
|
-
this.checkQueue();
|
|
1016
|
-
console.log(ansiC.inverse(`The following jobs are awaiting resources: ${JSON.stringify(this.queue)}`));
|
|
1017
|
-
console.log(ansiC.inverse(`The status of ports: ${JSON.stringify(this.ports)}`));
|
|
1018
|
-
this.writeBigBoard();
|
|
1019
|
-
if (this.mode === "dev")
|
|
1020
|
-
return;
|
|
1021
|
-
let inflight = false;
|
|
1022
|
-
Object.keys(this.summary).forEach((k) => {
|
|
1023
|
-
if (this.summary[k].prompt === "?") {
|
|
1024
|
-
console.log(ansiC.blue(ansiC.inverse(`🕕 prompt ${k}`)));
|
|
1025
|
-
inflight = true;
|
|
400
|
+
.join(".")}/python`;
|
|
401
|
+
if (!fs.existsSync(reportDest)) {
|
|
402
|
+
fs.mkdirSync(reportDest, { recursive: true });
|
|
1026
403
|
}
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
if (
|
|
1030
|
-
console.log(
|
|
1031
|
-
|
|
404
|
+
let testResources = "";
|
|
405
|
+
const testConfig = this.configs.tests.find((t) => t[0] === src);
|
|
406
|
+
if (!testConfig) {
|
|
407
|
+
console.log(ansiColors.inverse(`missing test config! Exiting ungracefully for '${src}'`));
|
|
408
|
+
process.exit(-1);
|
|
1032
409
|
}
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
if (
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
inflight = true;
|
|
1044
|
-
}
|
|
1045
|
-
});
|
|
1046
|
-
this.writeBigBoard();
|
|
1047
|
-
if (!inflight) {
|
|
1048
|
-
if (this.browser) {
|
|
1049
|
-
if (this.browser) {
|
|
1050
|
-
this.browser.disconnect().then(() => {
|
|
1051
|
-
console.log(ansiC.inverse(`${this.name} has been tested. Goodbye.`));
|
|
1052
|
-
process.exit();
|
|
1053
|
-
});
|
|
1054
|
-
}
|
|
410
|
+
const testConfigResource = testConfig[2];
|
|
411
|
+
const portsToUse = [];
|
|
412
|
+
if (testConfigResource.ports === 0) {
|
|
413
|
+
testResources = JSON.stringify({
|
|
414
|
+
scheduled: true,
|
|
415
|
+
name: src,
|
|
416
|
+
ports: portsToUse,
|
|
417
|
+
fs: reportDest,
|
|
418
|
+
browserWSEndpoint: this.browser.wsEndpoint(),
|
|
419
|
+
});
|
|
1055
420
|
}
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
this.webSidecars = {};
|
|
1063
|
-
this.pureSidecars = {};
|
|
1064
|
-
this.configs.ports.forEach((element) => {
|
|
1065
|
-
this.ports[element] = ""; // set ports as open
|
|
1066
|
-
});
|
|
1067
|
-
// Create HTTP server
|
|
1068
|
-
this.httpServer = http.createServer(this.requestHandler.bind(this));
|
|
1069
|
-
// Start WebSocket server attached to the HTTP server
|
|
1070
|
-
this.wss = new WebSocketServer({ server: this.httpServer });
|
|
1071
|
-
this.wss.on("connection", (ws) => {
|
|
1072
|
-
this.clients.add(ws);
|
|
1073
|
-
console.log("Client connected");
|
|
1074
|
-
ws.on("message", (data) => {
|
|
1075
|
-
var _a, _b;
|
|
1076
|
-
try {
|
|
1077
|
-
const message = JSON.parse(data.toString());
|
|
1078
|
-
if (message.type === "executeCommand") {
|
|
1079
|
-
// Validate the command starts with 'aider'
|
|
1080
|
-
if (message.command && message.command.trim().startsWith("aider")) {
|
|
1081
|
-
console.log(`Executing command: ${message.command}`);
|
|
1082
|
-
// Execute the command
|
|
1083
|
-
const processId = Date.now().toString();
|
|
1084
|
-
const child = spawn(message.command, {
|
|
1085
|
-
shell: true,
|
|
1086
|
-
cwd: process.cwd(),
|
|
1087
|
-
});
|
|
1088
|
-
// Track the process in both maps
|
|
1089
|
-
this.runningProcesses.set(processId, child);
|
|
1090
|
-
this.allProcesses.set(processId, {
|
|
1091
|
-
child,
|
|
1092
|
-
status: "running",
|
|
1093
|
-
command: message.command,
|
|
1094
|
-
pid: child.pid,
|
|
1095
|
-
timestamp: new Date().toISOString(),
|
|
1096
|
-
});
|
|
1097
|
-
// Initialize logs for this process
|
|
1098
|
-
this.processLogs.set(processId, []);
|
|
1099
|
-
// Broadcast process started
|
|
1100
|
-
this.broadcast({
|
|
1101
|
-
type: "processStarted",
|
|
1102
|
-
processId,
|
|
1103
|
-
command: message.command,
|
|
1104
|
-
timestamp: new Date().toISOString(),
|
|
1105
|
-
logs: [],
|
|
1106
|
-
});
|
|
1107
|
-
// Capture stdout and stderr
|
|
1108
|
-
(_a = child.stdout) === null || _a === void 0 ? void 0 : _a.on("data", (data) => {
|
|
1109
|
-
const logData = data.toString();
|
|
1110
|
-
// Add to stored logs
|
|
1111
|
-
const logs = this.processLogs.get(processId) || [];
|
|
1112
|
-
logs.push(logData);
|
|
1113
|
-
this.processLogs.set(processId, logs);
|
|
1114
|
-
this.broadcast({
|
|
1115
|
-
type: "processStdout",
|
|
1116
|
-
processId,
|
|
1117
|
-
data: logData,
|
|
1118
|
-
timestamp: new Date().toISOString(),
|
|
1119
|
-
});
|
|
1120
|
-
});
|
|
1121
|
-
(_b = child.stderr) === null || _b === void 0 ? void 0 : _b.on("data", (data) => {
|
|
1122
|
-
const logData = data.toString();
|
|
1123
|
-
// Add to stored logs
|
|
1124
|
-
const logs = this.processLogs.get(processId) || [];
|
|
1125
|
-
logs.push(logData);
|
|
1126
|
-
this.processLogs.set(processId, logs);
|
|
1127
|
-
this.broadcast({
|
|
1128
|
-
type: "processStderr",
|
|
1129
|
-
processId,
|
|
1130
|
-
data: logData,
|
|
1131
|
-
timestamp: new Date().toISOString(),
|
|
1132
|
-
});
|
|
1133
|
-
});
|
|
1134
|
-
child.on("error", (error) => {
|
|
1135
|
-
console.error(`Failed to execute command: ${error}`);
|
|
1136
|
-
this.runningProcesses.delete(processId);
|
|
1137
|
-
// Update the process status to error
|
|
1138
|
-
const processInfo = this.allProcesses.get(processId);
|
|
1139
|
-
if (processInfo) {
|
|
1140
|
-
this.allProcesses.set(processId, Object.assign(Object.assign({}, processInfo), { status: "error", error: error.message }));
|
|
1141
|
-
}
|
|
1142
|
-
this.broadcast({
|
|
1143
|
-
type: "processError",
|
|
1144
|
-
processId,
|
|
1145
|
-
error: error.message,
|
|
1146
|
-
timestamp: new Date().toISOString(),
|
|
1147
|
-
});
|
|
1148
|
-
});
|
|
1149
|
-
child.on("exit", (code) => {
|
|
1150
|
-
console.log(`Command exited with code ${code}`);
|
|
1151
|
-
// Remove from running processes but keep in allProcesses
|
|
1152
|
-
this.runningProcesses.delete(processId);
|
|
1153
|
-
// Update the process status to exited
|
|
1154
|
-
const processInfo = this.allProcesses.get(processId);
|
|
1155
|
-
if (processInfo) {
|
|
1156
|
-
this.allProcesses.set(processId, Object.assign(Object.assign({}, processInfo), { status: "exited", exitCode: code }));
|
|
1157
|
-
}
|
|
1158
|
-
this.broadcast({
|
|
1159
|
-
type: "processExited",
|
|
1160
|
-
processId,
|
|
1161
|
-
exitCode: code,
|
|
1162
|
-
timestamp: new Date().toISOString(),
|
|
1163
|
-
});
|
|
1164
|
-
});
|
|
421
|
+
else if (testConfigResource.ports > 0) {
|
|
422
|
+
const openPorts = Object.entries(this.ports).filter(([, status]) => status === "");
|
|
423
|
+
if (openPorts.length >= testConfigResource.ports) {
|
|
424
|
+
for (let i = 0; i < testConfigResource.ports; i++) {
|
|
425
|
+
portsToUse.push(openPorts[i][0]);
|
|
426
|
+
this.ports[openPorts[i][0]] = src;
|
|
1165
427
|
}
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
processId: id,
|
|
1174
|
-
command: procInfo.command,
|
|
1175
|
-
pid: procInfo.pid,
|
|
1176
|
-
status: procInfo.status,
|
|
1177
|
-
exitCode: procInfo.exitCode,
|
|
1178
|
-
error: procInfo.error,
|
|
1179
|
-
timestamp: procInfo.timestamp,
|
|
1180
|
-
logs: this.processLogs.get(id) || [],
|
|
1181
|
-
}));
|
|
1182
|
-
ws.send(JSON.stringify({
|
|
1183
|
-
type: "runningProcesses",
|
|
1184
|
-
processes,
|
|
1185
|
-
}));
|
|
428
|
+
testResources = JSON.stringify({
|
|
429
|
+
scheduled: true,
|
|
430
|
+
name: src,
|
|
431
|
+
ports: portsToUse,
|
|
432
|
+
fs: reportDest,
|
|
433
|
+
browserWSEndpoint: this.browser.wsEndpoint(),
|
|
434
|
+
});
|
|
1186
435
|
}
|
|
1187
|
-
else
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
if (procInfo) {
|
|
1192
|
-
ws.send(JSON.stringify({
|
|
1193
|
-
type: "processData",
|
|
1194
|
-
processId,
|
|
1195
|
-
command: procInfo.command,
|
|
1196
|
-
pid: procInfo.pid,
|
|
1197
|
-
status: procInfo.status,
|
|
1198
|
-
exitCode: procInfo.exitCode,
|
|
1199
|
-
error: procInfo.error,
|
|
1200
|
-
timestamp: procInfo.timestamp,
|
|
1201
|
-
logs: this.processLogs.get(processId) || [],
|
|
1202
|
-
}));
|
|
1203
|
-
}
|
|
436
|
+
else {
|
|
437
|
+
console.log(ansiColors.red(`python: cannot run ${src} because there are no open ports ATM. This job will be enqueued and run again when a port is available`));
|
|
438
|
+
this.queue.push(src);
|
|
439
|
+
return;
|
|
1204
440
|
}
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
console.error("negative port makes no sense", src);
|
|
444
|
+
process.exit(-1);
|
|
445
|
+
}
|
|
446
|
+
const logs = createLogStreams(reportDest, "python");
|
|
447
|
+
// For Python, we'll just run the script directly and pass test resources as an argument
|
|
448
|
+
// Python tests need to handle their own IPC if needed
|
|
449
|
+
const child = spawn("python3", [src, testResources], {
|
|
450
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
451
|
+
});
|
|
452
|
+
return new Promise((resolve, reject) => {
|
|
453
|
+
var _a, _b;
|
|
454
|
+
(_a = child.stdout) === null || _a === void 0 ? void 0 : _a.on("data", (data) => {
|
|
455
|
+
var _a;
|
|
456
|
+
(_a = logs.stdout) === null || _a === void 0 ? void 0 : _a.write(data);
|
|
457
|
+
});
|
|
458
|
+
(_b = child.stderr) === null || _b === void 0 ? void 0 : _b.on("data", (data) => {
|
|
459
|
+
var _a;
|
|
460
|
+
(_a = logs.stderr) === null || _a === void 0 ? void 0 : _a.write(data);
|
|
461
|
+
});
|
|
462
|
+
child.on("close", (code) => {
|
|
463
|
+
const exitCode = code === null ? -1 : code;
|
|
464
|
+
if (exitCode < 0) {
|
|
465
|
+
logs.writeExitCode(exitCode, new Error("Process crashed or was terminated"));
|
|
1214
466
|
}
|
|
1215
467
|
else {
|
|
1216
|
-
|
|
1217
|
-
processExists: !!childProcess,
|
|
1218
|
-
stdinExists: (childProcess === null || childProcess === void 0 ? void 0 : childProcess.stdin) ? true : false,
|
|
1219
|
-
});
|
|
468
|
+
logs.writeExitCode(exitCode);
|
|
1220
469
|
}
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
const childProcess = this.runningProcesses.get(processId);
|
|
1227
|
-
if (childProcess) {
|
|
1228
|
-
console.log("Killing process");
|
|
1229
|
-
childProcess.kill("SIGTERM");
|
|
1230
|
-
// The process exit handler will update the status and broadcast the change
|
|
470
|
+
logs.closeAll();
|
|
471
|
+
if (exitCode === 0) {
|
|
472
|
+
this.bddTestIsNowDone(src, 0);
|
|
473
|
+
statusMessagePretty(0, src, "python");
|
|
474
|
+
resolve();
|
|
1231
475
|
}
|
|
1232
476
|
else {
|
|
1233
|
-
console.log(
|
|
1234
|
-
|
|
1235
|
-
|
|
477
|
+
console.log(ansiColors.red(`python ! ${src} failed to execute. Check ${reportDest}/stderr.log for more info`));
|
|
478
|
+
this.bddTestIsNowDone(src, exitCode);
|
|
479
|
+
statusMessagePretty(exitCode, src, "python");
|
|
480
|
+
reject(new Error(`Process exited with code ${exitCode}`));
|
|
1236
481
|
}
|
|
1237
|
-
}
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
console.error("WebSocket error:", error);
|
|
1249
|
-
this.clients.delete(ws);
|
|
1250
|
-
});
|
|
1251
|
-
});
|
|
1252
|
-
// Start HTTP server
|
|
1253
|
-
const httpPort = Number(process.env.HTTP_PORT) || 3000;
|
|
1254
|
-
this.httpServer.listen(httpPort, () => {
|
|
1255
|
-
console.log(`HTTP server running on http://localhost:${httpPort}`);
|
|
1256
|
-
});
|
|
1257
|
-
}
|
|
1258
|
-
async stopSideCar(uid) {
|
|
1259
|
-
console.log(ansiC.green(ansiC.inverse(`stopSideCar ${uid}`)));
|
|
1260
|
-
Object.entries(this.pureSidecars).forEach(async ([k, v]) => {
|
|
1261
|
-
if (Number(k) === uid) {
|
|
1262
|
-
await this.pureSidecars[Number(k)].stop();
|
|
1263
|
-
delete this.pureSidecars[Number(k)];
|
|
1264
|
-
}
|
|
1265
|
-
});
|
|
1266
|
-
Object.entries(this.nodeSidecars).forEach(async ([k, v]) => {
|
|
1267
|
-
if (Number(k) === uid) {
|
|
1268
|
-
await this.nodeSidecars[Number(k)].send("stop");
|
|
1269
|
-
delete this.nodeSidecars[Number(k)];
|
|
1270
|
-
}
|
|
1271
|
-
});
|
|
1272
|
-
Object.entries(this.webSidecars).forEach(async ([k, v]) => {
|
|
1273
|
-
if (Number(k) === uid) {
|
|
1274
|
-
(await this.browser.pages()).forEach(async (p) => {
|
|
1275
|
-
if (p.mainFrame()._id === k) {
|
|
1276
|
-
await this.webSidecars[Number(k)].close();
|
|
1277
|
-
delete this.webSidecars[Number(k)];
|
|
1278
|
-
}
|
|
482
|
+
});
|
|
483
|
+
child.on("error", (e) => {
|
|
484
|
+
console.log(ansiColors.red(ansiColors.inverse(`python: ${src} errored with: ${e.name}. Check error logs for more info`)));
|
|
485
|
+
this.bddTestIsNowDone(src, -1);
|
|
486
|
+
statusMessagePretty(-1, src, "python");
|
|
487
|
+
reject(e);
|
|
488
|
+
});
|
|
489
|
+
}).finally(() => {
|
|
490
|
+
portsToUse.forEach(port => {
|
|
491
|
+
this.ports[port] = "";
|
|
492
|
+
});
|
|
1279
493
|
});
|
|
1280
|
-
}
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
return this.launchWebSideCar(s);
|
|
1295
|
-
}
|
|
1296
|
-
else if (r === "pure") {
|
|
1297
|
-
return this.launchPureSideCar(s);
|
|
1298
|
-
}
|
|
1299
|
-
else {
|
|
1300
|
-
throw `unknown runtime ${r}`;
|
|
1301
|
-
}
|
|
1302
|
-
}
|
|
1303
|
-
mapping() {
|
|
1304
|
-
return [
|
|
1305
|
-
["$", this.$],
|
|
1306
|
-
["click", this.click],
|
|
1307
|
-
["closePage", this.closePage],
|
|
1308
|
-
["createWriteStream", this.createWriteStream],
|
|
1309
|
-
["customclose", this.customclose],
|
|
1310
|
-
["customScreenShot", this.customScreenShot.bind(this)],
|
|
1311
|
-
["end", this.end],
|
|
1312
|
-
["existsSync", this.existsSync],
|
|
1313
|
-
["focusOn", this.focusOn],
|
|
1314
|
-
["getAttribute", this.getAttribute],
|
|
1315
|
-
["getInnerHtml", this.getInnerHtml],
|
|
1316
|
-
// ["setValue", this.setValue],
|
|
1317
|
-
["goto", this.goto.bind(this)],
|
|
1318
|
-
["isDisabled", this.isDisabled],
|
|
1319
|
-
["launchSideCar", this.launchSideCar.bind(this)],
|
|
1320
|
-
["mkdirSync", this.mkdirSync],
|
|
1321
|
-
["newPage", this.newPage],
|
|
1322
|
-
["page", this.page],
|
|
1323
|
-
["pages", this.pages],
|
|
1324
|
-
["screencast", this.screencast],
|
|
1325
|
-
["screencastStop", this.screencastStop],
|
|
1326
|
-
["stopSideCar", this.stopSideCar.bind(this)],
|
|
1327
|
-
["typeInto", this.typeInto],
|
|
1328
|
-
["waitForSelector", this.waitForSelector],
|
|
1329
|
-
["write", this.write],
|
|
1330
|
-
["writeFileSync", this.writeFileSync],
|
|
1331
|
-
];
|
|
1332
|
-
}
|
|
1333
|
-
async start() {
|
|
1334
|
-
// set up the "pure" listeners
|
|
1335
|
-
this.mapping().forEach(async ([command, func]) => {
|
|
1336
|
-
globalThis[command] = func;
|
|
1337
|
-
});
|
|
1338
|
-
if (!fs.existsSync(`testeranto/reports/${this.name}`)) {
|
|
1339
|
-
fs.mkdirSync(`testeranto/reports/${this.name}`);
|
|
1340
|
-
}
|
|
1341
|
-
const executablePath = "/opt/homebrew/bin/chromium";
|
|
1342
|
-
try {
|
|
1343
|
-
this.browser = await puppeteer.launch({
|
|
1344
|
-
slowMo: 1,
|
|
1345
|
-
waitForInitialPage: false,
|
|
1346
|
-
executablePath,
|
|
1347
|
-
headless: true,
|
|
1348
|
-
defaultViewport: null, // Disable default 800x600 viewport
|
|
1349
|
-
dumpio: false,
|
|
1350
|
-
devtools: false,
|
|
1351
|
-
args: [
|
|
1352
|
-
"--allow-file-access-from-files",
|
|
1353
|
-
"--allow-insecure-localhost",
|
|
1354
|
-
"--allow-running-insecure-content",
|
|
1355
|
-
"--auto-open-devtools-for-tabs",
|
|
1356
|
-
"--disable-dev-shm-usage",
|
|
1357
|
-
"--disable-extensions",
|
|
1358
|
-
"--disable-features=site-per-process",
|
|
1359
|
-
"--disable-gpu",
|
|
1360
|
-
"--disable-setuid-sandbox",
|
|
1361
|
-
"--disable-site-isolation-trials",
|
|
1362
|
-
"--disable-web-security",
|
|
1363
|
-
"--no-first-run",
|
|
1364
|
-
"--no-sandbox",
|
|
1365
|
-
"--no-startup-window",
|
|
1366
|
-
"--reduce-security-for-testing",
|
|
1367
|
-
"--remote-allow-origins=*",
|
|
1368
|
-
"--start-maximized",
|
|
1369
|
-
"--unsafely-treat-insecure-origin-as-secure=*",
|
|
1370
|
-
`--remote-debugging-port=3234`,
|
|
1371
|
-
// "--disable-features=IsolateOrigins,site-per-process",
|
|
1372
|
-
// "--disable-features=IsolateOrigins",
|
|
1373
|
-
// "--disk-cache-dir=/dev/null",
|
|
1374
|
-
// "--disk-cache-size=1",
|
|
1375
|
-
// "--no-zygote",
|
|
1376
|
-
// "--remote-allow-origins=ws://localhost:3234",
|
|
1377
|
-
// "--single-process",
|
|
1378
|
-
// "--start-maximized",
|
|
1379
|
-
// "--unsafely-treat-insecure-origin-as-secure",
|
|
1380
|
-
// "--unsafely-treat-insecure-origin-as-secure=ws://192.168.0.101:3234",
|
|
1381
|
-
],
|
|
1382
|
-
});
|
|
1383
|
-
}
|
|
1384
|
-
catch (e) {
|
|
1385
|
-
console.error(e);
|
|
1386
|
-
console.error("could not start chrome via puppeter. Check this path: ", executablePath);
|
|
1387
|
-
}
|
|
1388
|
-
const { nodeEntryPoints, webEntryPoints, pureEntryPoints, pitonoEntryPoints } = this.getRunnables(this.configs.tests, this.name);
|
|
1389
|
-
[
|
|
1390
|
-
[
|
|
1391
|
-
nodeEntryPoints,
|
|
1392
|
-
this.launchNode,
|
|
1393
|
-
"node",
|
|
1394
|
-
(w) => {
|
|
1395
|
-
this.nodeMetafileWatcher = w;
|
|
1396
|
-
},
|
|
1397
|
-
],
|
|
1398
|
-
[
|
|
1399
|
-
webEntryPoints,
|
|
1400
|
-
this.launchWeb,
|
|
1401
|
-
"web",
|
|
1402
|
-
(w) => {
|
|
1403
|
-
this.webMetafileWatcher = w;
|
|
1404
|
-
},
|
|
1405
|
-
],
|
|
1406
|
-
[
|
|
1407
|
-
pureEntryPoints,
|
|
1408
|
-
this.launchPure,
|
|
1409
|
-
"pure",
|
|
1410
|
-
(w) => {
|
|
1411
|
-
this.importMetafileWatcher = w;
|
|
1412
|
-
},
|
|
1413
|
-
],
|
|
1414
|
-
[
|
|
1415
|
-
pitonoEntryPoints,
|
|
1416
|
-
this.launchPitono,
|
|
1417
|
-
"pitono",
|
|
1418
|
-
(w) => {
|
|
1419
|
-
this.pitonoMetafileWatcher = w;
|
|
1420
|
-
},
|
|
1421
|
-
],
|
|
1422
|
-
].forEach(async ([eps, launcher, runtime, watcher]) => {
|
|
1423
|
-
let metafile;
|
|
1424
|
-
if (runtime === "pitono") {
|
|
1425
|
-
metafile = `./testeranto/metafiles/python/core.json`;
|
|
1426
|
-
// Ensure the directory exists before trying to watch
|
|
1427
|
-
const metafileDir = path.dirname(metafile);
|
|
1428
|
-
if (!fs.existsSync(metafileDir)) {
|
|
1429
|
-
fs.mkdirSync(metafileDir, { recursive: true });
|
|
494
|
+
})();
|
|
495
|
+
this.addPromiseProcess(processId, pythonPromise, command, "bdd-test", src, "python");
|
|
496
|
+
};
|
|
497
|
+
this.launchGolang = async (src, dest) => {
|
|
498
|
+
const processId = `golang-${src}-${Date.now()}`;
|
|
499
|
+
const command = `golang test: ${src}`;
|
|
500
|
+
const golangPromise = (async () => {
|
|
501
|
+
this.bddTestIsRunning(src);
|
|
502
|
+
const reportDest = `testeranto/reports/${this.name}/${src
|
|
503
|
+
.split(".")
|
|
504
|
+
.slice(0, -1)
|
|
505
|
+
.join(".")}/golang`;
|
|
506
|
+
if (!fs.existsSync(reportDest)) {
|
|
507
|
+
fs.mkdirSync(reportDest, { recursive: true });
|
|
1430
508
|
}
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
if (runtime !== "pitono") {
|
|
1437
|
-
await pollForFile(metafile);
|
|
1438
|
-
}
|
|
1439
|
-
Object.entries(eps).forEach(async ([inputFile, outputFile]) => {
|
|
1440
|
-
// await pollForFile(outputFile);\
|
|
1441
|
-
this.launchers[inputFile] = () => launcher(inputFile, outputFile);
|
|
1442
|
-
this.launchers[inputFile]();
|
|
1443
|
-
try {
|
|
1444
|
-
watch(outputFile, async (e, filename) => {
|
|
1445
|
-
const hash = await fileHash(outputFile);
|
|
1446
|
-
if (fileHashes[inputFile] !== hash) {
|
|
1447
|
-
fileHashes[inputFile] = hash;
|
|
1448
|
-
console.log(ansiC.yellow(ansiC.inverse(`< ${e} ${filename}`)));
|
|
1449
|
-
// launcher(inputFile, outputFile);
|
|
1450
|
-
this.launchers[inputFile]();
|
|
1451
|
-
}
|
|
1452
|
-
});
|
|
509
|
+
let testResources = "";
|
|
510
|
+
const testConfig = this.configs.tests.find((t) => t[0] === src);
|
|
511
|
+
if (!testConfig) {
|
|
512
|
+
console.log(ansiColors.inverse(`golang: missing test config! Exiting ungracefully for '${src}'`));
|
|
513
|
+
process.exit(-1);
|
|
1453
514
|
}
|
|
1454
|
-
|
|
1455
|
-
|
|
515
|
+
const testConfigResource = testConfig[2];
|
|
516
|
+
const portsToUse = [];
|
|
517
|
+
if (testConfigResource.ports === 0) {
|
|
518
|
+
testResources = JSON.stringify({
|
|
519
|
+
scheduled: true,
|
|
520
|
+
name: src,
|
|
521
|
+
ports: portsToUse,
|
|
522
|
+
fs: reportDest,
|
|
523
|
+
browserWSEndpoint: this.browser.wsEndpoint(),
|
|
524
|
+
});
|
|
1456
525
|
}
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
this.metafileOutputs(runtime);
|
|
526
|
+
else if (testConfigResource.ports > 0) {
|
|
527
|
+
const openPorts = Object.entries(this.ports).filter(([, status]) => status === "");
|
|
528
|
+
if (openPorts.length >= testConfigResource.ports) {
|
|
529
|
+
for (let i = 0; i < testConfigResource.ports; i++) {
|
|
530
|
+
portsToUse.push(openPorts[i][0]);
|
|
531
|
+
this.ports[openPorts[i][0]] = src;
|
|
532
|
+
}
|
|
533
|
+
testResources = JSON.stringify({
|
|
534
|
+
scheduled: true,
|
|
535
|
+
name: src,
|
|
536
|
+
ports: portsToUse,
|
|
537
|
+
fs: reportDest,
|
|
538
|
+
browserWSEndpoint: this.browser.wsEndpoint(),
|
|
539
|
+
});
|
|
1472
540
|
}
|
|
1473
541
|
else {
|
|
1474
|
-
|
|
1475
|
-
|
|
542
|
+
console.log(ansiColors.red(`golang: cannot run ${src} because there are no open ports ATM. This job will be enqueued and run again when a port is available`));
|
|
543
|
+
this.queue.push(src);
|
|
544
|
+
return;
|
|
1476
545
|
}
|
|
1477
|
-
};
|
|
1478
|
-
// Start checking for the file
|
|
1479
|
-
checkFileExists();
|
|
1480
|
-
}
|
|
1481
|
-
else {
|
|
1482
|
-
// For other runtimes, only set up watcher if the file exists
|
|
1483
|
-
if (fs.existsSync(metafile)) {
|
|
1484
|
-
watcher(watch(metafile, async (e, filename) => {
|
|
1485
|
-
console.log(ansiC.yellow(ansiC.inverse(`< ${e} ${filename} (${runtime})`)));
|
|
1486
|
-
this.metafileOutputs(runtime);
|
|
1487
|
-
}));
|
|
1488
|
-
}
|
|
1489
|
-
}
|
|
1490
|
-
});
|
|
1491
|
-
// Object.keys(this.configs.externalTests).forEach((et) => {
|
|
1492
|
-
// this.launchExternalTest(et, this.configs.externalTests[et]);
|
|
1493
|
-
// });
|
|
1494
|
-
}
|
|
1495
|
-
// async launchExternalTest(
|
|
1496
|
-
// externalTestName: string,
|
|
1497
|
-
// externalTest: {
|
|
1498
|
-
// watch: string[];
|
|
1499
|
-
// exec: string;
|
|
1500
|
-
// }
|
|
1501
|
-
// ) {
|
|
1502
|
-
// // fs.mkdirSync(`testeranto/externalTests/${externalTestName}`);
|
|
1503
|
-
// // exec(externalTest.exec, (error, stdout, stderr) => {
|
|
1504
|
-
// // if (error) {
|
|
1505
|
-
// // fs.writeFileSync(
|
|
1506
|
-
// // `testeranto/externalTests/${externalTestName}/exitcode.txt`,
|
|
1507
|
-
// // `${error.name}\n${error.message}\n${error.code}\n`
|
|
1508
|
-
// // );
|
|
1509
|
-
// // } else {
|
|
1510
|
-
// // fs.writeFileSync(
|
|
1511
|
-
// // `testeranto/externalTests/${externalTestName}/exitcode.txt`,
|
|
1512
|
-
// // `0`
|
|
1513
|
-
// // );
|
|
1514
|
-
// // }
|
|
1515
|
-
// // fs.writeFileSync(
|
|
1516
|
-
// // `testeranto/externalTests/${externalTestName}/stdout.txt`,
|
|
1517
|
-
// // stdout
|
|
1518
|
-
// // );
|
|
1519
|
-
// // fs.writeFileSync(
|
|
1520
|
-
// // `testeranto/externalTests/${externalTestName}/stderr.txt`,
|
|
1521
|
-
// // stderr
|
|
1522
|
-
// // );
|
|
1523
|
-
// // });
|
|
1524
|
-
// }
|
|
1525
|
-
async stop() {
|
|
1526
|
-
console.log(ansiC.inverse("Testeranto-Run is shutting down gracefully..."));
|
|
1527
|
-
this.mode = "once";
|
|
1528
|
-
this.nodeMetafileWatcher.close();
|
|
1529
|
-
this.webMetafileWatcher.close();
|
|
1530
|
-
this.importMetafileWatcher.close();
|
|
1531
|
-
if (this.pitonoMetafileWatcher) {
|
|
1532
|
-
this.pitonoMetafileWatcher.close();
|
|
1533
|
-
}
|
|
1534
|
-
// Close any remaining log streams
|
|
1535
|
-
Object.values(this.logStreams || {}).forEach((logs) => logs.closeAll());
|
|
1536
|
-
// Close WebSocket server
|
|
1537
|
-
this.wss.close(() => {
|
|
1538
|
-
console.log("WebSocket server closed");
|
|
1539
|
-
});
|
|
1540
|
-
// Close all client connections
|
|
1541
|
-
this.clients.forEach((client) => {
|
|
1542
|
-
client.terminate();
|
|
1543
|
-
});
|
|
1544
|
-
this.clients.clear();
|
|
1545
|
-
// Close HTTP server
|
|
1546
|
-
this.httpServer.close(() => {
|
|
1547
|
-
console.log("HTTP server closed");
|
|
1548
|
-
});
|
|
1549
|
-
this.checkForShutdown();
|
|
1550
|
-
}
|
|
1551
|
-
async metafileOutputs(platform) {
|
|
1552
|
-
let metafilePath;
|
|
1553
|
-
if (platform === "pitono") {
|
|
1554
|
-
metafilePath = `./testeranto/metafiles/python/core.json`;
|
|
1555
|
-
}
|
|
1556
|
-
else {
|
|
1557
|
-
metafilePath = `./testeranto/metafiles/${platform}/${this.name}.json`;
|
|
1558
|
-
}
|
|
1559
|
-
// Check if the file exists
|
|
1560
|
-
if (!fs.existsSync(metafilePath)) {
|
|
1561
|
-
if (platform === "pitono") {
|
|
1562
|
-
console.log(ansiC.yellow(ansiC.inverse(`Pitono metafile not found yet: ${metafilePath}`)));
|
|
1563
|
-
}
|
|
1564
|
-
return;
|
|
1565
|
-
}
|
|
1566
|
-
let metafile;
|
|
1567
|
-
try {
|
|
1568
|
-
const fileContent = fs.readFileSync(metafilePath).toString();
|
|
1569
|
-
const parsedData = JSON.parse(fileContent);
|
|
1570
|
-
// Handle different metafile structures
|
|
1571
|
-
if (platform === "pitono") {
|
|
1572
|
-
// Pitono metafile might be the entire content or have a different structure
|
|
1573
|
-
metafile = parsedData.metafile || parsedData;
|
|
1574
|
-
}
|
|
1575
|
-
else {
|
|
1576
|
-
metafile = parsedData.metafile;
|
|
1577
|
-
}
|
|
1578
|
-
if (!metafile) {
|
|
1579
|
-
console.log(ansiC.yellow(ansiC.inverse(`No metafile found in ${metafilePath}`)));
|
|
1580
|
-
return;
|
|
1581
|
-
}
|
|
1582
|
-
}
|
|
1583
|
-
catch (error) {
|
|
1584
|
-
console.error(`Error reading metafile at ${metafilePath}:`, error);
|
|
1585
|
-
return;
|
|
1586
|
-
}
|
|
1587
|
-
const outputs = metafile.outputs;
|
|
1588
|
-
Object.keys(outputs).forEach(async (k) => {
|
|
1589
|
-
const pattern = `testeranto/bundles/${platform}/${this.name}/${this.configs.src}`;
|
|
1590
|
-
if (!k.startsWith(pattern)) {
|
|
1591
|
-
return false;
|
|
1592
|
-
}
|
|
1593
|
-
const addableFiles = Object.keys(outputs[k].inputs).filter((i) => {
|
|
1594
|
-
if (!fs.existsSync(i))
|
|
1595
|
-
return false;
|
|
1596
|
-
if (i.startsWith("node_modules"))
|
|
1597
|
-
return false;
|
|
1598
|
-
if (i.startsWith("./node_modules"))
|
|
1599
|
-
return false;
|
|
1600
|
-
return true;
|
|
1601
|
-
});
|
|
1602
|
-
const f = `${k.split(".").slice(0, -1).join(".")}/`;
|
|
1603
|
-
if (!fs.existsSync(f)) {
|
|
1604
|
-
fs.mkdirSync(f);
|
|
1605
|
-
}
|
|
1606
|
-
const entrypoint = outputs[k].entryPoint;
|
|
1607
|
-
if (entrypoint) {
|
|
1608
|
-
const changeDigest = await filesHash(addableFiles);
|
|
1609
|
-
if (changeDigest === changes[entrypoint]) {
|
|
1610
|
-
// skip
|
|
1611
546
|
}
|
|
1612
547
|
else {
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
platform,
|
|
1616
|
-
addableFiles,
|
|
1617
|
-
entrypoint: entrypoint,
|
|
1618
|
-
});
|
|
1619
|
-
this.eslintCheck(entrypoint, platform, addableFiles);
|
|
1620
|
-
this.makePrompt(entrypoint, addableFiles, platform);
|
|
548
|
+
console.error("negative port makes no sense", src);
|
|
549
|
+
process.exit(-1);
|
|
1621
550
|
}
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
filePath = `testeranto/${filePath}`;
|
|
1647
|
-
}
|
|
1648
|
-
else {
|
|
1649
|
-
// For frontend assets, try multiple possible locations
|
|
1650
|
-
// First, try the dist directory
|
|
1651
|
-
const possiblePaths = [
|
|
1652
|
-
`dist/${filePath}`,
|
|
1653
|
-
`testeranto/dist/${filePath}`,
|
|
1654
|
-
`../dist/${filePath}`,
|
|
1655
|
-
`./${filePath}`,
|
|
1656
|
-
];
|
|
1657
|
-
// Find the first existing file
|
|
1658
|
-
let foundPath = null;
|
|
1659
|
-
for (const possiblePath of possiblePaths) {
|
|
1660
|
-
if (fs.existsSync(possiblePath)) {
|
|
1661
|
-
foundPath = possiblePath;
|
|
1662
|
-
break;
|
|
1663
|
-
}
|
|
1664
|
-
}
|
|
1665
|
-
if (foundPath) {
|
|
1666
|
-
filePath = foundPath;
|
|
1667
|
-
}
|
|
1668
|
-
else {
|
|
1669
|
-
// If no file found, serve index.html for SPA routing
|
|
1670
|
-
const indexPath = this.findIndexHtml();
|
|
1671
|
-
if (indexPath) {
|
|
1672
|
-
fs.readFile(indexPath, (err, data) => {
|
|
1673
|
-
if (err) {
|
|
1674
|
-
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
1675
|
-
res.end("404 Not Found");
|
|
551
|
+
// Compile the Go test first
|
|
552
|
+
const buildDir = path.dirname(dest);
|
|
553
|
+
const binaryName = path.basename(dest, '.go');
|
|
554
|
+
const binaryPath = path.join(buildDir, binaryName);
|
|
555
|
+
const logs = createLogStreams(reportDest, "golang");
|
|
556
|
+
// First, compile the Go program
|
|
557
|
+
const compileProcess = spawn("go", ["build", "-o", binaryPath, dest]);
|
|
558
|
+
return new Promise((resolve, reject) => {
|
|
559
|
+
var _a, _b;
|
|
560
|
+
(_a = compileProcess.stdout) === null || _a === void 0 ? void 0 : _a.on("data", (data) => {
|
|
561
|
+
var _a;
|
|
562
|
+
(_a = logs.stdout) === null || _a === void 0 ? void 0 : _a.write(data);
|
|
563
|
+
});
|
|
564
|
+
(_b = compileProcess.stderr) === null || _b === void 0 ? void 0 : _b.on("data", (data) => {
|
|
565
|
+
var _a;
|
|
566
|
+
(_a = logs.stderr) === null || _a === void 0 ? void 0 : _a.write(data);
|
|
567
|
+
});
|
|
568
|
+
compileProcess.on("close", (compileCode) => {
|
|
569
|
+
var _a, _b;
|
|
570
|
+
if (compileCode !== 0) {
|
|
571
|
+
console.log(ansiColors.red(`golang ! ${src} failed to compile. Check ${reportDest}/stderr.log for more info`));
|
|
572
|
+
this.bddTestIsNowDone(src, compileCode || -1);
|
|
573
|
+
statusMessagePretty(compileCode || -1, src, "golang");
|
|
574
|
+
reject(new Error(`Compilation failed with code ${compileCode}`));
|
|
1676
575
|
return;
|
|
1677
576
|
}
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
577
|
+
// Now run the compiled binary
|
|
578
|
+
const child = spawn(binaryPath, [testResources], {
|
|
579
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
580
|
+
});
|
|
581
|
+
(_a = child.stdout) === null || _a === void 0 ? void 0 : _a.on("data", (data) => {
|
|
582
|
+
var _a;
|
|
583
|
+
(_a = logs.stdout) === null || _a === void 0 ? void 0 : _a.write(data);
|
|
584
|
+
});
|
|
585
|
+
(_b = child.stderr) === null || _b === void 0 ? void 0 : _b.on("data", (data) => {
|
|
586
|
+
var _a;
|
|
587
|
+
(_a = logs.stderr) === null || _a === void 0 ? void 0 : _a.write(data);
|
|
588
|
+
});
|
|
589
|
+
child.on("close", (code) => {
|
|
590
|
+
const exitCode = code === null ? -1 : code;
|
|
591
|
+
if (exitCode < 0) {
|
|
592
|
+
logs.writeExitCode(exitCode, new Error("Process crashed or was terminated"));
|
|
593
|
+
}
|
|
594
|
+
else {
|
|
595
|
+
logs.writeExitCode(exitCode);
|
|
596
|
+
}
|
|
597
|
+
logs.closeAll();
|
|
598
|
+
if (exitCode === 0) {
|
|
599
|
+
this.bddTestIsNowDone(src, 0);
|
|
600
|
+
statusMessagePretty(0, src, "golang");
|
|
601
|
+
resolve();
|
|
602
|
+
}
|
|
603
|
+
else {
|
|
604
|
+
console.log(ansiColors.red(`golang ! ${src} failed to execute. Check ${reportDest}/stderr.log for more info`));
|
|
605
|
+
this.bddTestIsNowDone(src, exitCode);
|
|
606
|
+
statusMessagePretty(exitCode, src, "golang");
|
|
607
|
+
reject(new Error(`Process exited with code ${exitCode}`));
|
|
1702
608
|
}
|
|
1703
|
-
res.writeHead(200, { "Content-Type": "text/html" });
|
|
1704
|
-
res.end(data);
|
|
1705
609
|
});
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
fs.readFile(filePath, (err, data) => {
|
|
1728
|
-
if (err) {
|
|
1729
|
-
res.writeHead(500, { "Content-Type": "text/plain" });
|
|
1730
|
-
res.end("500 Internal Server Error");
|
|
1731
|
-
return;
|
|
1732
|
-
}
|
|
1733
|
-
// Get MIME type
|
|
1734
|
-
const mimeType = mime.lookup(filePath) || "application/octet-stream";
|
|
1735
|
-
res.writeHead(200, { "Content-Type": mimeType });
|
|
1736
|
-
res.end(data);
|
|
1737
|
-
});
|
|
1738
|
-
});
|
|
1739
|
-
}
|
|
1740
|
-
findIndexHtml() {
|
|
1741
|
-
const possiblePaths = [
|
|
1742
|
-
"dist/index.html",
|
|
1743
|
-
"testeranto/dist/index.html",
|
|
1744
|
-
"../dist/index.html",
|
|
1745
|
-
"./index.html",
|
|
1746
|
-
];
|
|
1747
|
-
for (const path of possiblePaths) {
|
|
1748
|
-
if (fs.existsSync(path)) {
|
|
1749
|
-
return path;
|
|
1750
|
-
}
|
|
1751
|
-
}
|
|
1752
|
-
return null;
|
|
1753
|
-
}
|
|
1754
|
-
broadcast(message) {
|
|
1755
|
-
const data = typeof message === "string" ? message : JSON.stringify(message);
|
|
1756
|
-
this.clients.forEach((client) => {
|
|
1757
|
-
if (client.readyState === 1) {
|
|
1758
|
-
// WebSocket.OPEN
|
|
1759
|
-
client.send(data);
|
|
1760
|
-
}
|
|
1761
|
-
});
|
|
1762
|
-
}
|
|
1763
|
-
checkQueue() {
|
|
1764
|
-
const x = this.queue.pop();
|
|
1765
|
-
if (!x) {
|
|
1766
|
-
ansiC.inverse(`The following queue is empty`);
|
|
1767
|
-
return;
|
|
1768
|
-
}
|
|
1769
|
-
const test = this.configs.tests.find((t) => t[0] === x);
|
|
1770
|
-
if (!test)
|
|
1771
|
-
throw `test is undefined ${x}`;
|
|
1772
|
-
// const [src, runtime, ...xx]: [string, IRunTime, ...any] = test;
|
|
1773
|
-
this.launchers[test[0]]();
|
|
610
|
+
child.on("error", (e) => {
|
|
611
|
+
console.log(ansiColors.red(ansiColors.inverse(`golang: ${src} errored with: ${e.name}. Check error logs for more info`)));
|
|
612
|
+
this.bddTestIsNowDone(src, -1);
|
|
613
|
+
statusMessagePretty(-1, src, "golang");
|
|
614
|
+
reject(e);
|
|
615
|
+
});
|
|
616
|
+
});
|
|
617
|
+
compileProcess.on("error", (e) => {
|
|
618
|
+
console.log(ansiColors.red(ansiColors.inverse(`golang: ${src} compilation errored with: ${e.name}. Check error logs for more info`)));
|
|
619
|
+
this.bddTestIsNowDone(src, -1);
|
|
620
|
+
statusMessagePretty(-1, src, "golang");
|
|
621
|
+
reject(e);
|
|
622
|
+
});
|
|
623
|
+
}).finally(() => {
|
|
624
|
+
portsToUse.forEach(port => {
|
|
625
|
+
this.ports[port] = "";
|
|
626
|
+
});
|
|
627
|
+
});
|
|
628
|
+
})();
|
|
629
|
+
this.addPromiseProcess(processId, golangPromise, command, "bdd-test", src, "golang");
|
|
630
|
+
};
|
|
1774
631
|
}
|
|
1775
632
|
}
|