ai-first-cli 1.3.1 → 1.3.5
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/.ai-dev/index.db +0 -0
- package/BETA_EVALUATION_REPORT.md +151 -0
- package/CHANGELOG.md +178 -0
- package/PHASE1_USER_SIMULATION.md +56 -0
- package/PHASE2_USER_SIMULATION.md +81 -0
- package/PHASE3_USER_SIMULATION.md +176 -0
- package/README.es.md +18 -0
- package/README.md +80 -1
- package/ai/graph/knowledge-graph.json +10 -0
- package/ai-context/ai_context.md +130 -0
- package/{test-projects/react-app/.ai-dev → ai-context}/ai_rules.md +10 -5
- package/ai-context/architecture.md +136 -0
- package/ai-context/context/features/src.json +69 -0
- package/ai-context/context/features/test-projects.json +69 -0
- package/ai-context/context/flows/App.json +17 -0
- package/ai-context/context/flows/DashboardPage.json +14 -0
- package/ai-context/context/flows/LoginPage.json +14 -0
- package/ai-context/context/flows/admin.json +10 -0
- package/ai-context/context/flows/ai-first.json +9 -0
- package/ai-context/context/flows/androidresources.json +11 -0
- package/ai-context/context/flows/auth.json +13 -0
- package/ai-context/context/flows/authController.json +14 -0
- package/ai-context/context/flows/doctor.json +9 -0
- package/ai-context/context/flows/entrypoints.json +9 -0
- package/ai-context/context/flows/explore.json +9 -0
- package/ai-context/context/flows/fastapiAdapter.json +14 -0
- package/ai-context/context/flows/fastapiadapter.json +11 -0
- package/ai-context/context/flows/index.json +19 -0
- package/ai-context/context/flows/indexer.json +9 -0
- package/ai-context/context/flows/indexstate.json +9 -0
- package/ai-context/context/flows/init.json +22 -0
- package/ai-context/context/flows/main.json +18 -0
- package/ai-context/context/flows/mainactivity.json +9 -0
- package/ai-context/context/flows/models.json +15 -0
- package/ai-context/context/flows/posts.json +15 -0
- package/ai-context/context/flows/repoMapper.json +20 -0
- package/ai-context/context/flows/repomapper.json +11 -0
- package/ai-context/context/flows/routes.json +15 -0
- package/ai-context/context/flows/serializers.json +10 -0
- package/ai-context/context/flows/user.json +23 -0
- package/ai-context/context/flows/views.json +12 -0
- package/{test-projects/react-app/.ai-dev → ai-context}/conventions.md +3 -2
- package/ai-context/dependencies.json +3360 -0
- package/ai-context/entrypoints.md +45 -0
- package/ai-context/index-state.json +196 -0
- package/ai-context/modules.json +901 -0
- package/ai-context/project.json +33 -0
- package/ai-context/repo_map.json +8857 -0
- package/ai-context/repo_map.md +2002 -0
- package/{test-projects/flask-app/.ai-dev → ai-context}/schema.json +1 -1
- package/ai-context/summary.md +46 -0
- package/ai-context/symbols.json +82467 -0
- package/{test-projects/react-app/.ai-dev → ai-context}/tech_stack.md +15 -7
- package/ai-context-evaluation-report-1774223059505.md +206 -0
- package/dist/analyzers/architecture.d.ts.map +1 -1
- package/dist/analyzers/architecture.js +6 -0
- package/dist/analyzers/architecture.js.map +1 -1
- package/dist/analyzers/entrypoints.d.ts.map +1 -1
- package/dist/analyzers/entrypoints.js +105 -0
- package/dist/analyzers/entrypoints.js.map +1 -1
- package/dist/analyzers/symbols.d.ts.map +1 -1
- package/dist/analyzers/symbols.js +72 -1
- package/dist/analyzers/symbols.js.map +1 -1
- package/dist/analyzers/techStack.d.ts +8 -0
- package/dist/analyzers/techStack.d.ts.map +1 -1
- package/dist/analyzers/techStack.js +75 -0
- package/dist/analyzers/techStack.js.map +1 -1
- package/dist/scripts/ai-context-evaluator.js +367 -0
- package/package.json +1 -1
- package/quick-evaluation-report-1774396002305.md +64 -0
- package/quick-evaluator.ts +200 -0
- package/scripts/ai-context-evaluator.ts +440 -0
- package/src/analyzers/architecture.ts +8 -0
- package/src/analyzers/entrypoints.ts +115 -0
- package/src/analyzers/symbols.ts +77 -1
- package/src/analyzers/techStack.ts +93 -0
- package/tests/apex-parser.test.ts +193 -0
- package/tests/cli-commands-batch1.test.ts +808 -0
- package/tests/cli-commands-batch2.test.ts +1113 -0
- package/tests/cli-commands-batch3.test.ts +1128 -0
- package/tests/cli-index.test.ts +1007 -0
- package/tests/cli-init.test.ts +761 -0
- package/tests/salesforce-apex-classes.test.ts +713 -0
- package/tests/salesforce-apex-triggers.test.ts +871 -0
- package/tests/salesforce-custom-objects.test.ts +918 -0
- package/tests/salesforce-flows.test.ts +710 -0
- package/tests/salesforce-lwc.test.ts +963 -0
- package/tests/salesforce-sfdx-integration.test.ts +1125 -0
- package/ANALISIS_COMPLETO.md +0 -424
- package/ANALISIS_MEJORAS.md +0 -327
- package/CONTRIBUTING.md +0 -89
- package/FLOW.md +0 -129
- package/TEST_RESULTS.md +0 -198
- package/TEST_RESULTS_COMPARATIVE.md +0 -159
- package/TEST_RESULTS_COMPLETE.md +0 -127
- package/TEST_RESULTS_COMPREHENSIVE.md +0 -208
- package/install.sh +0 -188
- package/run-all-tests.sh +0 -184
- package/test-ai-context-understanding.sh +0 -21
- package/test-projects/django-app/.ai-dev/ai_context.md +0 -92
- package/test-projects/django-app/.ai-dev/ai_rules.md +0 -47
- package/test-projects/django-app/.ai-dev/architecture.md +0 -57
- package/test-projects/django-app/.ai-dev/cache.json +0 -169
- package/test-projects/django-app/.ai-dev/context/flows/views.json +0 -10
- package/test-projects/django-app/.ai-dev/conventions.md +0 -51
- package/test-projects/django-app/.ai-dev/dependencies.json +0 -312
- package/test-projects/django-app/.ai-dev/entrypoints.md +0 -4
- package/test-projects/django-app/.ai-dev/files.json +0 -209
- package/test-projects/django-app/.ai-dev/graph/knowledge-graph.json +0 -36
- package/test-projects/django-app/.ai-dev/graph/module-graph.json +0 -145
- package/test-projects/django-app/.ai-dev/graph/symbol-graph.json +0 -1488
- package/test-projects/django-app/.ai-dev/graph/symbol-references.json +0 -1
- package/test-projects/django-app/.ai-dev/index-state.json +0 -294
- package/test-projects/django-app/.ai-dev/modules.json +0 -35
- package/test-projects/django-app/.ai-dev/project.json +0 -11
- package/test-projects/django-app/.ai-dev/repo_map.json +0 -412
- package/test-projects/django-app/.ai-dev/repo_map.md +0 -105
- package/test-projects/django-app/.ai-dev/schema.json +0 -5
- package/test-projects/django-app/.ai-dev/summary.md +0 -15
- package/test-projects/django-app/.ai-dev/symbols.json +0 -1
- package/test-projects/django-app/.ai-dev/tech_stack.md +0 -32
- package/test-projects/django-app/README.md +0 -91
- package/test-projects/django-app/blog/__init__.py +0 -0
- package/test-projects/django-app/blog/admin.py +0 -31
- package/test-projects/django-app/blog/models.py +0 -55
- package/test-projects/django-app/blog/serializers.py +0 -69
- package/test-projects/django-app/blog/urls.py +0 -14
- package/test-projects/django-app/blog/views.py +0 -96
- package/test-projects/django-app/django_app/__init__.py +0 -0
- package/test-projects/django-app/django_app/settings.py +0 -90
- package/test-projects/django-app/django_app/urls.py +0 -11
- package/test-projects/django-app/django_app/wsgi.py +0 -9
- package/test-projects/django-app/manage.py +0 -23
- package/test-projects/django-app/requirements.txt +0 -3
- package/test-projects/django-app/users/__init__.py +0 -0
- package/test-projects/django-app/users/admin.py +0 -42
- package/test-projects/django-app/users/models.py +0 -54
- package/test-projects/django-app/users/serializers.py +0 -113
- package/test-projects/django-app/users/urls.py +0 -13
- package/test-projects/django-app/users/views.py +0 -135
- package/test-projects/express-api/.ai-dev/ai_context.md +0 -112
- package/test-projects/express-api/.ai-dev/ai_rules.md +0 -50
- package/test-projects/express-api/.ai-dev/architecture.md +0 -62
- package/test-projects/express-api/.ai-dev/context/features/controllers.json +0 -13
- package/test-projects/express-api/.ai-dev/context/features/services.json +0 -13
- package/test-projects/express-api/.ai-dev/context/flows/auth.json +0 -12
- package/test-projects/express-api/.ai-dev/context/flows/user.json +0 -13
- package/test-projects/express-api/.ai-dev/conventions.md +0 -51
- package/test-projects/express-api/.ai-dev/dependencies.json +0 -54
- package/test-projects/express-api/.ai-dev/entrypoints.md +0 -17
- package/test-projects/express-api/.ai-dev/modules.json +0 -30
- package/test-projects/express-api/.ai-dev/project.json +0 -15
- package/test-projects/express-api/.ai-dev/repo_map.json +0 -100
- package/test-projects/express-api/.ai-dev/repo_map.md +0 -36
- package/test-projects/express-api/.ai-dev/schema.json +0 -5
- package/test-projects/express-api/.ai-dev/summary.md +0 -14
- package/test-projects/express-api/.ai-dev/symbols.json +0 -7
- package/test-projects/express-api/.ai-dev/tech_stack.md +0 -38
- package/test-projects/express-api/.ai-dev/tools.json +0 -10
- package/test-projects/express-api/controllers/authController.js +0 -32
- package/test-projects/express-api/controllers/userController.js +0 -51
- package/test-projects/express-api/index.js +0 -30
- package/test-projects/express-api/middleware/authMiddleware.js +0 -30
- package/test-projects/express-api/models/userRepository.js +0 -25
- package/test-projects/express-api/package.json +0 -18
- package/test-projects/express-api/services/authService.js +0 -17
- package/test-projects/express-api/services/userService.js +0 -28
- package/test-projects/fastapi-app/.ai-dev/ai_context.md +0 -89
- package/test-projects/fastapi-app/.ai-dev/ai_rules.md +0 -47
- package/test-projects/fastapi-app/.ai-dev/architecture.md +0 -39
- package/test-projects/fastapi-app/.ai-dev/cache.json +0 -125
- package/test-projects/fastapi-app/.ai-dev/conventions.md +0 -51
- package/test-projects/fastapi-app/.ai-dev/dependencies.json +0 -244
- package/test-projects/fastapi-app/.ai-dev/entrypoints.md +0 -4
- package/test-projects/fastapi-app/.ai-dev/files.json +0 -154
- package/test-projects/fastapi-app/.ai-dev/graph/knowledge-graph.json +0 -15
- package/test-projects/fastapi-app/.ai-dev/graph/module-graph.json +0 -78
- package/test-projects/fastapi-app/.ai-dev/graph/symbol-graph.json +0 -1724
- package/test-projects/fastapi-app/.ai-dev/graph/symbol-references.json +0 -51
- package/test-projects/fastapi-app/.ai-dev/index-state.json +0 -217
- package/test-projects/fastapi-app/.ai-dev/modules.json +0 -16
- package/test-projects/fastapi-app/.ai-dev/project.json +0 -9
- package/test-projects/fastapi-app/.ai-dev/repo_map.json +0 -298
- package/test-projects/fastapi-app/.ai-dev/repo_map.md +0 -74
- package/test-projects/fastapi-app/.ai-dev/schema.json +0 -5
- package/test-projects/fastapi-app/.ai-dev/summary.md +0 -12
- package/test-projects/fastapi-app/.ai-dev/symbols.json +0 -1
- package/test-projects/fastapi-app/.ai-dev/tech_stack.md +0 -32
- package/test-projects/fastapi-app/.ai-dev/tools.json +0 -10
- package/test-projects/fastapi-app/README.md +0 -118
- package/test-projects/fastapi-app/app/database.py +0 -21
- package/test-projects/fastapi-app/app/dependencies.py +0 -107
- package/test-projects/fastapi-app/app/main.py +0 -47
- package/test-projects/fastapi-app/app/models.py +0 -149
- package/test-projects/fastapi-app/app/routers/auth.py +0 -117
- package/test-projects/fastapi-app/app/routers/posts.py +0 -272
- package/test-projects/fastapi-app/app/schemas.py +0 -191
- package/test-projects/fastapi-app/requirements.txt +0 -10
- package/test-projects/flask-app/.ai-dev/ai_context.md +0 -94
- package/test-projects/flask-app/.ai-dev/ai_rules.md +0 -47
- package/test-projects/flask-app/.ai-dev/architecture.md +0 -49
- package/test-projects/flask-app/.ai-dev/cache.json +0 -157
- package/test-projects/flask-app/.ai-dev/context/features/app.json +0 -25
- package/test-projects/flask-app/.ai-dev/context/flows/routes.json +0 -14
- package/test-projects/flask-app/.ai-dev/conventions.md +0 -51
- package/test-projects/flask-app/.ai-dev/dependencies.json +0 -298
- package/test-projects/flask-app/.ai-dev/entrypoints.md +0 -4
- package/test-projects/flask-app/.ai-dev/files.json +0 -194
- package/test-projects/flask-app/.ai-dev/graph/knowledge-graph.json +0 -60
- package/test-projects/flask-app/.ai-dev/graph/module-graph.json +0 -95
- package/test-projects/flask-app/.ai-dev/graph/symbol-graph.json +0 -1448
- package/test-projects/flask-app/.ai-dev/graph/symbol-references.json +0 -45
- package/test-projects/flask-app/.ai-dev/index-state.json +0 -273
- package/test-projects/flask-app/.ai-dev/modules.json +0 -21
- package/test-projects/flask-app/.ai-dev/project.json +0 -13
- package/test-projects/flask-app/.ai-dev/repo_map.json +0 -400
- package/test-projects/flask-app/.ai-dev/repo_map.md +0 -98
- package/test-projects/flask-app/.ai-dev/summary.md +0 -13
- package/test-projects/flask-app/.ai-dev/symbols.json +0 -1
- package/test-projects/flask-app/.ai-dev/tech_stack.md +0 -32
- package/test-projects/flask-app/.ai-dev/tools.json +0 -10
- package/test-projects/flask-app/README.md +0 -129
- package/test-projects/flask-app/app/__init__.py +0 -46
- package/test-projects/flask-app/app/api/__init__.py +0 -7
- package/test-projects/flask-app/app/api/routes.py +0 -122
- package/test-projects/flask-app/app/auth/__init__.py +0 -7
- package/test-projects/flask-app/app/auth/forms.py +0 -52
- package/test-projects/flask-app/app/auth/routes.py +0 -68
- package/test-projects/flask-app/app/blog/__init__.py +0 -7
- package/test-projects/flask-app/app/blog/forms.py +0 -35
- package/test-projects/flask-app/app/blog/routes.py +0 -140
- package/test-projects/flask-app/app/main/__init__.py +0 -7
- package/test-projects/flask-app/app/main/routes.py +0 -88
- package/test-projects/flask-app/app/models.py +0 -177
- package/test-projects/flask-app/config.py +0 -64
- package/test-projects/flask-app/requirements.txt +0 -10
- package/test-projects/laravel-app/.ai-dev/ai_context.md +0 -97
- package/test-projects/laravel-app/.ai-dev/ai_rules.md +0 -47
- package/test-projects/laravel-app/.ai-dev/architecture.md +0 -60
- package/test-projects/laravel-app/.ai-dev/cache.json +0 -161
- package/test-projects/laravel-app/.ai-dev/context/features/app.json +0 -21
- package/test-projects/laravel-app/.ai-dev/context/flows/.json +0 -9
- package/test-projects/laravel-app/.ai-dev/context/flows/category.json +0 -12
- package/test-projects/laravel-app/.ai-dev/context/flows/comment.json +0 -12
- package/test-projects/laravel-app/.ai-dev/context/flows/post.json +0 -12
- package/test-projects/laravel-app/.ai-dev/context/flows/unnamed.json +0 -9
- package/test-projects/laravel-app/.ai-dev/conventions.md +0 -51
- package/test-projects/laravel-app/.ai-dev/dependencies.json +0 -6
- package/test-projects/laravel-app/.ai-dev/entrypoints.md +0 -4
- package/test-projects/laravel-app/.ai-dev/files.json +0 -199
- package/test-projects/laravel-app/.ai-dev/graph/knowledge-graph.json +0 -98
- package/test-projects/laravel-app/.ai-dev/graph/module-graph.json +0 -30
- package/test-projects/laravel-app/.ai-dev/graph/symbol-graph.json +0 -5
- package/test-projects/laravel-app/.ai-dev/graph/symbol-references.json +0 -1
- package/test-projects/laravel-app/.ai-dev/index-state.json +0 -280
- package/test-projects/laravel-app/.ai-dev/modules.json +0 -29
- package/test-projects/laravel-app/.ai-dev/project.json +0 -17
- package/test-projects/laravel-app/.ai-dev/repo_map.json +0 -419
- package/test-projects/laravel-app/.ai-dev/repo_map.md +0 -106
- package/test-projects/laravel-app/.ai-dev/schema.json +0 -5
- package/test-projects/laravel-app/.ai-dev/summary.md +0 -15
- package/test-projects/laravel-app/.ai-dev/symbols.json +0 -1
- package/test-projects/laravel-app/.ai-dev/tech_stack.md +0 -34
- package/test-projects/laravel-app/.ai-dev/tools.json +0 -10
- package/test-projects/laravel-app/README.md +0 -107
- package/test-projects/laravel-app/app/Http/Controllers/Api/CategoryController.php +0 -88
- package/test-projects/laravel-app/app/Http/Controllers/Api/CommentController.php +0 -56
- package/test-projects/laravel-app/app/Http/Controllers/Api/PostController.php +0 -174
- package/test-projects/laravel-app/app/Http/Controllers/Controller.php +0 -12
- package/test-projects/laravel-app/app/Models/Category.php +0 -34
- package/test-projects/laravel-app/app/Models/Comment.php +0 -51
- package/test-projects/laravel-app/app/Models/Post.php +0 -108
- package/test-projects/laravel-app/app/Models/User.php +0 -85
- package/test-projects/laravel-app/bootstrap/app.php +0 -25
- package/test-projects/laravel-app/composer.json +0 -35
- package/test-projects/laravel-app/routes/api.php +0 -40
- package/test-projects/nestjs-backend/.ai-dev/ai_context.md +0 -111
- package/test-projects/nestjs-backend/.ai-dev/ai_rules.md +0 -52
- package/test-projects/nestjs-backend/.ai-dev/architecture.md +0 -49
- package/test-projects/nestjs-backend/.ai-dev/cache.json +0 -169
- package/test-projects/nestjs-backend/.ai-dev/context/features/src.json +0 -23
- package/test-projects/nestjs-backend/.ai-dev/context/flows/auth.controller.json +0 -14
- package/test-projects/nestjs-backend/.ai-dev/context/flows/auth.json +0 -10
- package/test-projects/nestjs-backend/.ai-dev/context/flows/users..json +0 -10
- package/test-projects/nestjs-backend/.ai-dev/context/flows/users.controller.json +0 -14
- package/test-projects/nestjs-backend/.ai-dev/context/flows/users.json +0 -10
- package/test-projects/nestjs-backend/.ai-dev/conventions.md +0 -52
- package/test-projects/nestjs-backend/.ai-dev/dependencies.json +0 -152
- package/test-projects/nestjs-backend/.ai-dev/entrypoints.md +0 -18
- package/test-projects/nestjs-backend/.ai-dev/files.json +0 -209
- package/test-projects/nestjs-backend/.ai-dev/graph/knowledge-graph.json +0 -132
- package/test-projects/nestjs-backend/.ai-dev/graph/module-graph.json +0 -29
- package/test-projects/nestjs-backend/.ai-dev/graph/symbol-graph.json +0 -304
- package/test-projects/nestjs-backend/.ai-dev/graph/symbol-references.json +0 -5
- package/test-projects/nestjs-backend/.ai-dev/index-state.json +0 -294
- package/test-projects/nestjs-backend/.ai-dev/modules.json +0 -19
- package/test-projects/nestjs-backend/.ai-dev/project.json +0 -18
- package/test-projects/nestjs-backend/.ai-dev/repo_map.json +0 -427
- package/test-projects/nestjs-backend/.ai-dev/repo_map.md +0 -104
- package/test-projects/nestjs-backend/.ai-dev/schema.json +0 -5
- package/test-projects/nestjs-backend/.ai-dev/summary.md +0 -13
- package/test-projects/nestjs-backend/.ai-dev/symbols.json +0 -1
- package/test-projects/nestjs-backend/.ai-dev/tech_stack.md +0 -38
- package/test-projects/nestjs-backend/.ai-dev/tools.json +0 -10
- package/test-projects/nestjs-backend/package.json +0 -22
- package/test-projects/nestjs-backend/src/app.module.ts +0 -8
- package/test-projects/nestjs-backend/src/auth/auth.controller.ts +0 -22
- package/test-projects/nestjs-backend/src/auth/auth.module.ts +0 -11
- package/test-projects/nestjs-backend/src/auth/auth.service.ts +0 -28
- package/test-projects/nestjs-backend/src/auth/dto/login.dto.ts +0 -4
- package/test-projects/nestjs-backend/src/auth/strategies/jwt.strategy.ts +0 -18
- package/test-projects/nestjs-backend/src/main.ts +0 -9
- package/test-projects/nestjs-backend/src/users/users.controller.ts +0 -32
- package/test-projects/nestjs-backend/src/users/users.module.ts +0 -10
- package/test-projects/nestjs-backend/src/users/users.service.ts +0 -42
- package/test-projects/nestjs-backend/tsconfig.json +0 -21
- package/test-projects/python-cli/.ai-dev/ai_context.md +0 -95
- package/test-projects/python-cli/.ai-dev/ai_rules.md +0 -47
- package/test-projects/python-cli/.ai-dev/architecture.md +0 -55
- package/test-projects/python-cli/.ai-dev/cache.json +0 -149
- package/test-projects/python-cli/.ai-dev/context/features/cli.json +0 -16
- package/test-projects/python-cli/.ai-dev/context/flows/list_.json +0 -9
- package/test-projects/python-cli/.ai-dev/context/flows/remove_.json +0 -9
- package/test-projects/python-cli/.ai-dev/conventions.md +0 -51
- package/test-projects/python-cli/.ai-dev/dependencies.json +0 -66
- package/test-projects/python-cli/.ai-dev/entrypoints.md +0 -4
- package/test-projects/python-cli/.ai-dev/files.json +0 -184
- package/test-projects/python-cli/.ai-dev/graph/knowledge-graph.json +0 -83
- package/test-projects/python-cli/.ai-dev/graph/module-graph.json +0 -31
- package/test-projects/python-cli/.ai-dev/graph/symbol-graph.json +0 -358
- package/test-projects/python-cli/.ai-dev/graph/symbol-references.json +0 -11
- package/test-projects/python-cli/.ai-dev/index-state.json +0 -259
- package/test-projects/python-cli/.ai-dev/modules.json +0 -21
- package/test-projects/python-cli/.ai-dev/project.json +0 -15
- package/test-projects/python-cli/.ai-dev/repo_map.json +0 -367
- package/test-projects/python-cli/.ai-dev/repo_map.md +0 -93
- package/test-projects/python-cli/.ai-dev/schema.json +0 -5
- package/test-projects/python-cli/.ai-dev/summary.md +0 -14
- package/test-projects/python-cli/.ai-dev/symbols.json +0 -1
- package/test-projects/python-cli/.ai-dev/tech_stack.md +0 -32
- package/test-projects/python-cli/.ai-dev/tools.json +0 -10
- package/test-projects/python-cli/__init__.py +0 -1
- package/test-projects/python-cli/cli/__init__.py +0 -1
- package/test-projects/python-cli/cli/add_command.py +0 -6
- package/test-projects/python-cli/cli/list_command.py +0 -7
- package/test-projects/python-cli/cli/remove_command.py +0 -6
- package/test-projects/python-cli/main.py +0 -34
- package/test-projects/python-cli/models/__init__.py +0 -2
- package/test-projects/python-cli/models/task.py +0 -19
- package/test-projects/python-cli/models/task_repository.py +0 -44
- package/test-projects/rails-app/.ai-dev/ai_context.md +0 -94
- package/test-projects/rails-app/.ai-dev/ai_rules.md +0 -47
- package/test-projects/rails-app/.ai-dev/architecture.md +0 -49
- package/test-projects/rails-app/.ai-dev/cache.json +0 -193
- package/test-projects/rails-app/.ai-dev/context/features/app.json +0 -24
- package/test-projects/rails-app/.ai-dev/context/features/config.json +0 -13
- package/test-projects/rails-app/.ai-dev/context/flows/application.json +0 -9
- package/test-projects/rails-app/.ai-dev/context/flows/application_.json +0 -9
- package/test-projects/rails-app/.ai-dev/context/flows/comments.json +0 -11
- package/test-projects/rails-app/.ai-dev/context/flows/comments_.json +0 -11
- package/test-projects/rails-app/.ai-dev/context/flows/posts.json +0 -11
- package/test-projects/rails-app/.ai-dev/context/flows/posts_.json +0 -11
- package/test-projects/rails-app/.ai-dev/context/flows/routes.json +0 -9
- package/test-projects/rails-app/.ai-dev/context/flows/users.json +0 -11
- package/test-projects/rails-app/.ai-dev/context/flows/users_.json +0 -11
- package/test-projects/rails-app/.ai-dev/conventions.md +0 -51
- package/test-projects/rails-app/.ai-dev/dependencies.json +0 -6
- package/test-projects/rails-app/.ai-dev/entrypoints.md +0 -4
- package/test-projects/rails-app/.ai-dev/files.json +0 -239
- package/test-projects/rails-app/.ai-dev/graph/knowledge-graph.json +0 -130
- package/test-projects/rails-app/.ai-dev/graph/module-graph.json +0 -27
- package/test-projects/rails-app/.ai-dev/graph/symbol-graph.json +0 -5
- package/test-projects/rails-app/.ai-dev/graph/symbol-references.json +0 -1
- package/test-projects/rails-app/.ai-dev/index-state.json +0 -336
- package/test-projects/rails-app/.ai-dev/modules.json +0 -26
- package/test-projects/rails-app/.ai-dev/project.json +0 -22
- package/test-projects/rails-app/.ai-dev/repo_map.json +0 -486
- package/test-projects/rails-app/.ai-dev/repo_map.md +0 -117
- package/test-projects/rails-app/.ai-dev/schema.json +0 -5
- package/test-projects/rails-app/.ai-dev/summary.md +0 -13
- package/test-projects/rails-app/.ai-dev/symbols.json +0 -1
- package/test-projects/rails-app/.ai-dev/tech_stack.md +0 -32
- package/test-projects/rails-app/.ai-dev/tools.json +0 -10
- package/test-projects/rails-app/Gemfile +0 -38
- package/test-projects/rails-app/README.md +0 -140
- package/test-projects/rails-app/Rakefile +0 -8
- package/test-projects/rails-app/app/controllers/api/comments_controller.rb +0 -75
- package/test-projects/rails-app/app/controllers/api/posts_controller.rb +0 -68
- package/test-projects/rails-app/app/controllers/api/users_controller.rb +0 -54
- package/test-projects/rails-app/app/controllers/application_controller.rb +0 -31
- package/test-projects/rails-app/app/models/comment.rb +0 -34
- package/test-projects/rails-app/app/models/post.rb +0 -36
- package/test-projects/rails-app/app/models/user.rb +0 -28
- package/test-projects/rails-app/app/services/post_service.rb +0 -92
- package/test-projects/rails-app/app/services/user_service.rb +0 -76
- package/test-projects/rails-app/config/application.rb +0 -27
- package/test-projects/rails-app/config/environment.rb +0 -7
- package/test-projects/rails-app/config/routes.rb +0 -15
- package/test-projects/react-app/.ai-dev/ai_context.md +0 -96
- package/test-projects/react-app/.ai-dev/architecture.md +0 -39
- package/test-projects/react-app/.ai-dev/cache.json +0 -153
- package/test-projects/react-app/.ai-dev/context/features/src.json +0 -18
- package/test-projects/react-app/.ai-dev/context/flows/UsersPage.json +0 -14
- package/test-projects/react-app/.ai-dev/context/flows/dashboard.json +0 -9
- package/test-projects/react-app/.ai-dev/context/flows/login.json +0 -9
- package/test-projects/react-app/.ai-dev/context/flows/users.json +0 -9
- package/test-projects/react-app/.ai-dev/dependencies.json +0 -128
- package/test-projects/react-app/.ai-dev/entrypoints.md +0 -4
- package/test-projects/react-app/.ai-dev/files.json +0 -189
- package/test-projects/react-app/.ai-dev/graph/knowledge-graph.json +0 -112
- package/test-projects/react-app/.ai-dev/graph/module-graph.json +0 -31
- package/test-projects/react-app/.ai-dev/graph/symbol-graph.json +0 -868
- package/test-projects/react-app/.ai-dev/graph/symbol-references.json +0 -31
- package/test-projects/react-app/.ai-dev/index-state.json +0 -266
- package/test-projects/react-app/.ai-dev/modules.json +0 -17
- package/test-projects/react-app/.ai-dev/project.json +0 -16
- package/test-projects/react-app/.ai-dev/repo_map.json +0 -391
- package/test-projects/react-app/.ai-dev/repo_map.md +0 -94
- package/test-projects/react-app/.ai-dev/schema.json +0 -5
- package/test-projects/react-app/.ai-dev/summary.md +0 -13
- package/test-projects/react-app/.ai-dev/symbols.json +0 -1
- package/test-projects/react-app/.ai-dev/tools.json +0 -10
- package/test-projects/react-app/package.json +0 -16
- package/test-projects/react-app/src/App.tsx +0 -21
- package/test-projects/react-app/src/context/AuthContext.tsx +0 -41
- package/test-projects/react-app/src/hooks/useAuth.ts +0 -10
- package/test-projects/react-app/src/main.tsx +0 -10
- package/test-projects/react-app/src/pages/DashboardPage.tsx +0 -17
- package/test-projects/react-app/src/pages/LoginPage.tsx +0 -41
- package/test-projects/react-app/src/pages/UsersPage.tsx +0 -36
- package/test-projects/react-app/src/services/userService.ts +0 -37
- package/test-projects/salesforce-cli/.ai-dev/ai_context.md +0 -89
- package/test-projects/salesforce-cli/.ai-dev/ai_rules.md +0 -47
- package/test-projects/salesforce-cli/.ai-dev/architecture.md +0 -39
- package/test-projects/salesforce-cli/.ai-dev/cache.json +0 -125
- package/test-projects/salesforce-cli/.ai-dev/context/features/force-app.json +0 -14
- package/test-projects/salesforce-cli/.ai-dev/context/flows/account.json +0 -9
- package/test-projects/salesforce-cli/.ai-dev/context/flows/opportunity.json +0 -9
- package/test-projects/salesforce-cli/.ai-dev/conventions.md +0 -51
- package/test-projects/salesforce-cli/.ai-dev/dependencies.json +0 -6
- package/test-projects/salesforce-cli/.ai-dev/entrypoints.md +0 -4
- package/test-projects/salesforce-cli/.ai-dev/files.json +0 -154
- package/test-projects/salesforce-cli/.ai-dev/graph/knowledge-graph.json +0 -64
- package/test-projects/salesforce-cli/.ai-dev/graph/module-graph.json +0 -13
- package/test-projects/salesforce-cli/.ai-dev/graph/symbol-graph.json +0 -148
- package/test-projects/salesforce-cli/.ai-dev/graph/symbol-references.json +0 -1
- package/test-projects/salesforce-cli/.ai-dev/index-state.json +0 -217
- package/test-projects/salesforce-cli/.ai-dev/modules.json +0 -12
- package/test-projects/salesforce-cli/.ai-dev/project.json +0 -14
- package/test-projects/salesforce-cli/.ai-dev/repo_map.json +0 -328
- package/test-projects/salesforce-cli/.ai-dev/repo_map.md +0 -80
- package/test-projects/salesforce-cli/.ai-dev/schema.json +0 -5
- package/test-projects/salesforce-cli/.ai-dev/summary.md +0 -13
- package/test-projects/salesforce-cli/.ai-dev/symbols.json +0 -1
- package/test-projects/salesforce-cli/.ai-dev/tech_stack.md +0 -31
- package/test-projects/salesforce-cli/.ai-dev/tools.json +0 -10
- package/test-projects/salesforce-cli/.forceignore +0 -27
- package/test-projects/salesforce-cli/force-app/main/default/classes/AccountController.cls +0 -24
- package/test-projects/salesforce-cli/force-app/main/default/classes/OpportunityController.cls +0 -25
- package/test-projects/salesforce-cli/force-app/main/default/objects/Project__c.object.xml +0 -45
- package/test-projects/salesforce-cli/force-app/main/default/triggers/AccountTrigger.trigger +0 -33
- package/test-projects/salesforce-cli/sfdx-project.json +0 -11
- package/test-projects/spring-boot-app/.ai-dev/ai_context.md +0 -91
- package/test-projects/spring-boot-app/.ai-dev/ai_rules.md +0 -48
- package/test-projects/spring-boot-app/.ai-dev/architecture.md +0 -39
- package/test-projects/spring-boot-app/.ai-dev/cache.json +0 -173
- package/test-projects/spring-boot-app/.ai-dev/context/features/src.json +0 -26
- package/test-projects/spring-boot-app/.ai-dev/context/flows/PostController.json +0 -19
- package/test-projects/spring-boot-app/.ai-dev/context/flows/UserController.json +0 -19
- package/test-projects/spring-boot-app/.ai-dev/context/flows/comment.json +0 -11
- package/test-projects/spring-boot-app/.ai-dev/context/flows/post.json +0 -14
- package/test-projects/spring-boot-app/.ai-dev/context/flows/user.json +0 -14
- package/test-projects/spring-boot-app/.ai-dev/conventions.md +0 -52
- package/test-projects/spring-boot-app/.ai-dev/dependencies.json +0 -326
- package/test-projects/spring-boot-app/.ai-dev/entrypoints.md +0 -4
- package/test-projects/spring-boot-app/.ai-dev/files.json +0 -214
- package/test-projects/spring-boot-app/.ai-dev/graph/knowledge-graph.json +0 -231
- package/test-projects/spring-boot-app/.ai-dev/graph/module-graph.json +0 -22
- package/test-projects/spring-boot-app/.ai-dev/graph/symbol-graph.json +0 -794
- package/test-projects/spring-boot-app/.ai-dev/graph/symbol-references.json +0 -70
- package/test-projects/spring-boot-app/.ai-dev/index-state.json +0 -301
- package/test-projects/spring-boot-app/.ai-dev/modules.json +0 -21
- package/test-projects/spring-boot-app/.ai-dev/project.json +0 -17
- package/test-projects/spring-boot-app/.ai-dev/repo_map.json +0 -461
- package/test-projects/spring-boot-app/.ai-dev/repo_map.md +0 -109
- package/test-projects/spring-boot-app/.ai-dev/schema.json +0 -5
- package/test-projects/spring-boot-app/.ai-dev/summary.md +0 -12
- package/test-projects/spring-boot-app/.ai-dev/symbols.json +0 -1
- package/test-projects/spring-boot-app/.ai-dev/tech_stack.md +0 -32
- package/test-projects/spring-boot-app/.ai-dev/tools.json +0 -10
- package/test-projects/spring-boot-app/.classpath +0 -57
- package/test-projects/spring-boot-app/.factorypath +0 -69
- package/test-projects/spring-boot-app/.project +0 -34
- package/test-projects/spring-boot-app/.settings/org.eclipse.core.resources.prefs +0 -4
- package/test-projects/spring-boot-app/.settings/org.eclipse.jdt.apt.core.prefs +0 -4
- package/test-projects/spring-boot-app/.settings/org.eclipse.jdt.core.prefs +0 -10
- package/test-projects/spring-boot-app/.settings/org.eclipse.m2e.core.prefs +0 -4
- package/test-projects/spring-boot-app/README.md +0 -122
- package/test-projects/spring-boot-app/pom.xml +0 -79
- package/test-projects/spring-boot-app/src/main/java/com/example/demo/DemoApplication.java +0 -12
- package/test-projects/spring-boot-app/src/main/java/com/example/demo/controllers/CommentController.java +0 -89
- package/test-projects/spring-boot-app/src/main/java/com/example/demo/controllers/PostController.java +0 -92
- package/test-projects/spring-boot-app/src/main/java/com/example/demo/controllers/UserController.java +0 -84
- package/test-projects/spring-boot-app/src/main/java/com/example/demo/models/Comment.java +0 -38
- package/test-projects/spring-boot-app/src/main/java/com/example/demo/models/Post.java +0 -56
- package/test-projects/spring-boot-app/src/main/java/com/example/demo/models/User.java +0 -44
- package/test-projects/spring-boot-app/src/main/java/com/example/demo/repositories/CommentRepository.java +0 -21
- package/test-projects/spring-boot-app/src/main/java/com/example/demo/repositories/PostRepository.java +0 -18
- package/test-projects/spring-boot-app/src/main/java/com/example/demo/repositories/UserRepository.java +0 -15
- package/test-projects/spring-boot-app/src/main/java/com/example/demo/services/PostService.java +0 -83
- package/test-projects/spring-boot-app/src/main/java/com/example/demo/services/UserService.java +0 -62
- package/test-projects/spring-boot-app/src/main/resources/application.properties +0 -22
- package/test-projects/spring-boot-app/target/classes/com/example/demo/DemoApplication.class +0 -0
- package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/CommentController$CommentCreateRequest.class +0 -0
- package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/CommentController$CommentUpdateRequest.class +0 -0
- package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/CommentController.class +0 -0
- package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/PostController$PostCreateRequest.class +0 -0
- package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/PostController$PostUpdateRequest.class +0 -0
- package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/PostController.class +0 -0
- package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/UserController$UserCreateRequest.class +0 -0
- package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/UserController$UserUpdateRequest.class +0 -0
- package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/UserController.class +0 -0
- package/test-projects/spring-boot-app/target/classes/com/example/demo/models/Comment.class +0 -0
- package/test-projects/spring-boot-app/target/classes/com/example/demo/models/Post.class +0 -0
- package/test-projects/spring-boot-app/target/classes/com/example/demo/models/User.class +0 -0
- package/test-projects/spring-boot-app/target/classes/com/example/demo/repositories/CommentRepository.class +0 -0
- package/test-projects/spring-boot-app/target/classes/com/example/demo/repositories/PostRepository.class +0 -0
- package/test-projects/spring-boot-app/target/classes/com/example/demo/repositories/UserRepository.class +0 -0
- package/test-projects/spring-boot-app/target/classes/com/example/demo/services/PostService.class +0 -0
- package/test-projects/spring-boot-app/target/classes/com/example/demo/services/UserService.class +0 -0
- package/tests/e2e/run-e2e.sh +0 -88
- /package/{test-projects/django-app/.ai-dev → ai-context}/tools.json +0 -0
|
@@ -0,0 +1,710 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll, afterAll } from "vitest";
|
|
2
|
+
import { FileInfo } from "../src/core/repoScanner";
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import os from "os";
|
|
6
|
+
import { extractSymbols } from "../src/analyzers/symbols";
|
|
7
|
+
|
|
8
|
+
const SALESFORCE_ENTERPRISE_PATH = path.join(process.cwd(), "test-projects/salesforce-enterprise");
|
|
9
|
+
|
|
10
|
+
describe("Salesforce Flows Detection", () => {
|
|
11
|
+
let tempDir: string;
|
|
12
|
+
|
|
13
|
+
beforeAll(() => {
|
|
14
|
+
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "salesforce-flows-test-"));
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
afterAll(() => {
|
|
18
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const createFileInfo = (filePath: string, extension: string, content: string): FileInfo => {
|
|
22
|
+
const fullPath = path.join(tempDir, filePath);
|
|
23
|
+
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
24
|
+
fs.writeFileSync(fullPath, content);
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
path: fullPath,
|
|
28
|
+
relativePath: filePath,
|
|
29
|
+
extension,
|
|
30
|
+
name: filePath.split("/").pop()?.replace(`.${extension}`, "") || "",
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// =========================================================================
|
|
35
|
+
// INTEGRATION TESTS - Using real Salesforce Enterprise test project
|
|
36
|
+
// =========================================================================
|
|
37
|
+
|
|
38
|
+
describe("Integration: Real Salesforce Enterprise Project", () => {
|
|
39
|
+
it("should detect both Flow files in the enterprise project", () => {
|
|
40
|
+
const flowsDir = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows");
|
|
41
|
+
const files = fs.readdirSync(flowsDir).filter(f => f.endsWith(".flow-meta.xml"));
|
|
42
|
+
|
|
43
|
+
expect(files).toHaveLength(2);
|
|
44
|
+
expect(files).toContain("Account_Create.flow-meta.xml");
|
|
45
|
+
expect(files).toContain("Opportunity_Update.flow-meta.xml");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("should read both Flow files successfully", () => {
|
|
49
|
+
const accountCreatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Account_Create.flow-meta.xml");
|
|
50
|
+
const opportunityUpdatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Opportunity_Update.flow-meta.xml");
|
|
51
|
+
|
|
52
|
+
const accountCreateContent = fs.readFileSync(accountCreatePath, "utf-8");
|
|
53
|
+
const opportunityUpdateContent = fs.readFileSync(opportunityUpdatePath, "utf-8");
|
|
54
|
+
|
|
55
|
+
expect(accountCreateContent).toContain("<Flow xmlns=");
|
|
56
|
+
expect(opportunityUpdateContent).toContain("<Flow xmlns=");
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// =========================================================================
|
|
61
|
+
// Account_Create.flow-meta.xml - Screen Flow
|
|
62
|
+
// =========================================================================
|
|
63
|
+
|
|
64
|
+
describe("Account_Create Flow (Screen Flow)", () => {
|
|
65
|
+
let accountCreateContent: string;
|
|
66
|
+
|
|
67
|
+
beforeAll(() => {
|
|
68
|
+
const accountCreatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Account_Create.flow-meta.xml");
|
|
69
|
+
accountCreateContent = fs.readFileSync(accountCreatePath, "utf-8");
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("should have correct apiVersion (59.0)", () => {
|
|
73
|
+
expect(accountCreateContent).toContain("<apiVersion>59.0</apiVersion>");
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("should have correct label (Account Create)", () => {
|
|
77
|
+
expect(accountCreateContent).toContain("<label>Account Create</label>");
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("should have processType as Flow (Screen Flow)", () => {
|
|
81
|
+
expect(accountCreateContent).toContain("<processType>Flow</processType>");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("should have status Active", () => {
|
|
85
|
+
expect(accountCreateContent).toContain("<status>Active</status>");
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe("Screen Elements", () => {
|
|
89
|
+
it("should have EnterAccountDetails screen", () => {
|
|
90
|
+
expect(accountCreateContent).toContain("<name>EnterAccountDetails</name>");
|
|
91
|
+
expect(accountCreateContent).toContain("<label>Enter Account Details</label>");
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("should have screen location coordinates", () => {
|
|
95
|
+
expect(accountCreateContent).toContain("<locationX>176</locationX>");
|
|
96
|
+
expect(accountCreateContent).toContain("<locationY>158</locationY>");
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("should allow back, finish, and pause on screen", () => {
|
|
100
|
+
expect(accountCreateContent).toContain("<allowBack>true</allowBack>");
|
|
101
|
+
expect(accountCreateContent).toContain("<allowFinish>true</allowFinish>");
|
|
102
|
+
expect(accountCreateContent).toContain("<allowPause>true</allowPause>");
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it("should have connector to ValidateAccountData", () => {
|
|
106
|
+
expect(accountCreateContent).toContain("<targetReference>ValidateAccountData</targetReference>");
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe("Input Fields", () => {
|
|
111
|
+
it("should have AccountName field (required)", () => {
|
|
112
|
+
expect(accountCreateContent).toContain("<name>AccountName</name>");
|
|
113
|
+
expect(accountCreateContent).toContain("<fieldType>InputField</fieldType>");
|
|
114
|
+
expect(accountCreateContent).toContain("<label>Account Name</label>");
|
|
115
|
+
expect(accountCreateContent).toContain("<required>true</required>");
|
|
116
|
+
expect(accountCreateContent).toContain("Enter the full legal name of the account");
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("should have Industry field", () => {
|
|
120
|
+
expect(accountCreateContent).toContain("<name>Industry</name>");
|
|
121
|
+
expect(accountCreateContent).toContain("<fieldType>InputField</fieldType>");
|
|
122
|
+
expect(accountCreateContent).toContain("<label>Industry</label>");
|
|
123
|
+
expect(accountCreateContent).toContain("<dataType>String</dataType>");
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it("should have AnnualRevenue field (Currency)", () => {
|
|
127
|
+
expect(accountCreateContent).toContain("<name>AnnualRevenue</name>");
|
|
128
|
+
expect(accountCreateContent).toContain("<fieldType>InputField</fieldType>");
|
|
129
|
+
expect(accountCreateContent).toContain("<label>Annual Revenue</label>");
|
|
130
|
+
expect(accountCreateContent).toContain("<dataType>Currency</dataType>");
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("should have Phone field", () => {
|
|
134
|
+
expect(accountCreateContent).toContain("<name>Phone</name>");
|
|
135
|
+
expect(accountCreateContent).toContain("<fieldType>InputField</fieldType>");
|
|
136
|
+
expect(accountCreateContent).toContain("<label>Phone</label>");
|
|
137
|
+
expect(accountCreateContent).toContain("<dataType>Phone</dataType>");
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("should have BillingStreet field", () => {
|
|
141
|
+
expect(accountCreateContent).toContain("<name>BillingStreet</name>");
|
|
142
|
+
expect(accountCreateContent).toContain("<fieldType>InputField</fieldType>");
|
|
143
|
+
expect(accountCreateContent).toContain("<label>Billing Street</label>");
|
|
144
|
+
expect(accountCreateContent).toContain("<dataType>String</dataType>");
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it("should have additional billing address fields", () => {
|
|
148
|
+
expect(accountCreateContent).toContain("<name>BillingCity</name>");
|
|
149
|
+
expect(accountCreateContent).toContain("<name>BillingState</name>");
|
|
150
|
+
expect(accountCreateContent).toContain("<name>BillingPostalCode</name>");
|
|
151
|
+
expect(accountCreateContent).toContain("<name>BillingCountry</name>");
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it("should have total of 9 input fields in screen", () => {
|
|
155
|
+
// Count <fields> elements within the <screens> section
|
|
156
|
+
const screensMatch = accountCreateContent.match(/<screens>([\s\S]*?)<\/screens>/);
|
|
157
|
+
expect(screensMatch).toBeTruthy();
|
|
158
|
+
const screensContent = screensMatch?.[1] || "";
|
|
159
|
+
const fieldMatches = screensContent.match(/<fields>/g);
|
|
160
|
+
expect(fieldMatches).toHaveLength(9);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
describe("Decision Elements", () => {
|
|
165
|
+
it("should have ValidateAccountData decision", () => {
|
|
166
|
+
expect(accountCreateContent).toContain("<name>ValidateAccountData</name>");
|
|
167
|
+
expect(accountCreateContent).toContain("<label>Validate Account Data</label>");
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it("should have decision location coordinates", () => {
|
|
171
|
+
expect(accountCreateContent).toContain("<locationX>176</locationX>");
|
|
172
|
+
expect(accountCreateContent).toContain("<locationY>326</locationY>");
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it("should have default connector label", () => {
|
|
176
|
+
expect(accountCreateContent).toContain("<defaultConnectorLabel>Default Outcome</defaultConnectorLabel>");
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it("should have IsValidAccount rule with conditions", () => {
|
|
180
|
+
expect(accountCreateContent).toContain("<name>IsValidAccount</name>");
|
|
181
|
+
expect(accountCreateContent).toContain("<conditionLogic>and</conditionLogic>");
|
|
182
|
+
expect(accountCreateContent).toContain("<leftValueReference>EnterAccountDetails.AccountName</leftValueReference>");
|
|
183
|
+
expect(accountCreateContent).toContain("<operator>IsNull</operator>");
|
|
184
|
+
expect(accountCreateContent).toContain("<label>Is Valid Account</label>");
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
describe("Action Elements", () => {
|
|
189
|
+
it("should have CreateAccountRecord action", () => {
|
|
190
|
+
expect(accountCreateContent).toContain("<name>CreateAccountRecord</name>");
|
|
191
|
+
expect(accountCreateContent).toContain("<label>Create Account Record</label>");
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it("should have action type CreateRecord", () => {
|
|
195
|
+
expect(accountCreateContent).toContain("<actionType>CreateRecord</actionType>");
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it("should have input parameters mapping to screen fields", () => {
|
|
199
|
+
expect(accountCreateContent).toContain("<elementReference>EnterAccountDetails.AccountName</elementReference>");
|
|
200
|
+
expect(accountCreateContent).toContain("<elementReference>EnterAccountDetails.Industry</elementReference>");
|
|
201
|
+
expect(accountCreateContent).toContain("<elementReference>EnterAccountDetails.AnnualRevenue</elementReference>");
|
|
202
|
+
expect(accountCreateContent).toContain("<elementReference>EnterAccountDetails.Phone</elementReference>");
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it("should target Account object", () => {
|
|
206
|
+
expect(accountCreateContent).toContain("<object>Account</object>");
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
describe("Start Element", () => {
|
|
211
|
+
it("should have start element with location", () => {
|
|
212
|
+
expect(accountCreateContent).toContain("<locationX>50</locationX>");
|
|
213
|
+
expect(accountCreateContent).toContain("<locationY>0</locationY>");
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it("should start with connector to EnterAccountDetails", () => {
|
|
217
|
+
expect(accountCreateContent).toContain("<targetReference>EnterAccountDetails</targetReference>");
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// =========================================================================
|
|
223
|
+
// Opportunity_Update.flow-meta.xml - Record-triggered Flow
|
|
224
|
+
// =========================================================================
|
|
225
|
+
|
|
226
|
+
describe("Opportunity_Update Flow (Record-triggered Flow)", () => {
|
|
227
|
+
let opportunityUpdateContent: string;
|
|
228
|
+
|
|
229
|
+
beforeAll(() => {
|
|
230
|
+
const opportunityUpdatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Opportunity_Update.flow-meta.xml");
|
|
231
|
+
opportunityUpdateContent = fs.readFileSync(opportunityUpdatePath, "utf-8");
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it("should have correct apiVersion (59.0)", () => {
|
|
235
|
+
expect(opportunityUpdateContent).toContain("<apiVersion>59.0</apiVersion>");
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it("should have correct label (Opportunity Update)", () => {
|
|
239
|
+
expect(opportunityUpdateContent).toContain("<label>Opportunity Update</label>");
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
it("should have processType as Flow (Record-triggered)", () => {
|
|
243
|
+
expect(opportunityUpdateContent).toContain("<processType>Flow</processType>");
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it("should have status Active", () => {
|
|
247
|
+
expect(opportunityUpdateContent).toContain("<status>Active</status>");
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
describe("Trigger Elements", () => {
|
|
251
|
+
it("should have OnOpportunityChange trigger", () => {
|
|
252
|
+
expect(opportunityUpdateContent).toContain("<name>OnOpportunityChange</name>");
|
|
253
|
+
expect(opportunityUpdateContent).toContain("<label>When an Opportunity is updated</label>");
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
it("should have trigger location coordinates", () => {
|
|
257
|
+
expect(opportunityUpdateContent).toContain("<locationX>0</locationX>");
|
|
258
|
+
expect(opportunityUpdateContent).toContain("<locationY>0</locationY>");
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it("should have trigger condition in Chinese (当一条记录被更新时)", () => {
|
|
262
|
+
expect(opportunityUpdateContent).toContain("<触发条件>When a record is updated</触发条件>");
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it("should trigger on Opportunity object", () => {
|
|
266
|
+
expect(opportunityUpdateContent).toContain("<object>Opportunity</object>");
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
it("should have trigger type Upon Create or Update", () => {
|
|
270
|
+
expect(opportunityUpdateContent).toContain("<triggerType>Upon Create or Update</triggerType>");
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
it("should have filter on StageName IsChanged", () => {
|
|
274
|
+
expect(opportunityUpdateContent).toContain("<filters>");
|
|
275
|
+
expect(opportunityUpdateContent).toContain("<field>StageName</field>");
|
|
276
|
+
expect(opportunityUpdateContent).toContain("<operator>IsChanged</operator>");
|
|
277
|
+
expect(opportunityUpdateContent).toContain("<booleanValue>true</booleanValue>");
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
describe("Decision Elements", () => {
|
|
282
|
+
it("should have CheckStageChange decision", () => {
|
|
283
|
+
expect(opportunityUpdateContent).toContain("<name>CheckStageChange</name>");
|
|
284
|
+
expect(opportunityUpdateContent).toContain("<label>Check Stage Change</label>");
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it("should have decision location coordinates", () => {
|
|
288
|
+
expect(opportunityUpdateContent).toContain("<locationX>128</locationX>");
|
|
289
|
+
expect(opportunityUpdateContent).toContain("<locationY>224</locationY>");
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it("should have default connector label (No Stage Change)", () => {
|
|
293
|
+
expect(opportunityUpdateContent).toContain("<defaultConnectorLabel>No Stage Change</defaultConnectorLabel>");
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it("should have StageChangedToNegotiation rule", () => {
|
|
297
|
+
expect(opportunityUpdateContent).toContain("<name>StageChangedToNegotiation</name>");
|
|
298
|
+
expect(opportunityUpdateContent).toContain("<conditionLogic>and</conditionLogic>");
|
|
299
|
+
expect(opportunityUpdateContent).toContain("<leftValueReference>$Opportunity.StageName</leftValueReference>");
|
|
300
|
+
expect(opportunityUpdateContent).toContain("<operator>Equal</operator>");
|
|
301
|
+
expect(opportunityUpdateContent).toContain("<stringValue>Negotiation/Review</stringValue>");
|
|
302
|
+
expect(opportunityUpdateContent).toContain("<label>Stage Changed to Negotiation</label>");
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it("should have StageChangedToClosedWon rule", () => {
|
|
306
|
+
expect(opportunityUpdateContent).toContain("<name>StageChangedToClosedWon</name>");
|
|
307
|
+
expect(opportunityUpdateContent).toContain("<conditionLogic>and</conditionLogic>");
|
|
308
|
+
expect(opportunityUpdateContent).toContain("<leftValueReference>$Opportunity.StageName</leftValueReference>");
|
|
309
|
+
expect(opportunityUpdateContent).toContain("<operator>Equal</operator>");
|
|
310
|
+
expect(opportunityUpdateContent).toContain("<stringValue>Closed Won</stringValue>");
|
|
311
|
+
expect(opportunityUpdateContent).toContain("<label>Stage Changed to Closed Won</label>");
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it("should have 2 decision rules", () => {
|
|
315
|
+
const ruleMatches = opportunityUpdateContent.match(/<name>StageChangedTo/g);
|
|
316
|
+
expect(ruleMatches).toHaveLength(2);
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
describe("Action Elements", () => {
|
|
321
|
+
it("should have UpdateProbabilityHigh action", () => {
|
|
322
|
+
expect(opportunityUpdateContent).toContain("<name>UpdateProbabilityHigh</name>");
|
|
323
|
+
expect(opportunityUpdateContent).toContain("<label>Set Probability to High</label>");
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
it("should have action type UpdateRecord", () => {
|
|
327
|
+
expect(opportunityUpdateContent).toContain("<actionType>UpdateRecord</actionType>");
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
it("should have OpportunityId input parameter", () => {
|
|
331
|
+
expect(opportunityUpdateContent).toContain("<name>OpportunityId</name>");
|
|
332
|
+
expect(opportunityUpdateContent).toContain("<elementReference>$Opportunity.Id</elementReference>");
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
it("should have Probability input parameter with value 90", () => {
|
|
336
|
+
expect(opportunityUpdateContent).toContain("<name>Probability</name>");
|
|
337
|
+
expect(opportunityUpdateContent).toContain("<numberValue>90</numberValue>");
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it("should have SendWinNotification action", () => {
|
|
341
|
+
expect(opportunityUpdateContent).toContain("<name>SendWinNotification</name>");
|
|
342
|
+
expect(opportunityUpdateContent).toContain("<label>Send Win Notification</label>");
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it("should have action type EmailAlert", () => {
|
|
346
|
+
expect(opportunityUpdateContent).toContain("<actionType>EmailAlert</actionType>");
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
it("should have flowTransactionModel", () => {
|
|
350
|
+
expect(opportunityUpdateContent).toContain("<flowTransactionModel>CurrentTransaction</flowTransactionModel>");
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
describe("Start Element", () => {
|
|
355
|
+
it("should have start element with location", () => {
|
|
356
|
+
expect(opportunityUpdateContent).toContain("<locationX>50</locationX>");
|
|
357
|
+
expect(opportunityUpdateContent).toContain("<locationY>0</locationY>");
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
it("should start with connector to CheckStageChange", () => {
|
|
361
|
+
expect(opportunityUpdateContent).toContain("<targetReference>CheckStageChange</targetReference>");
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
// =========================================================================
|
|
367
|
+
// FLOW FILE STRUCTURE VERIFICATION
|
|
368
|
+
// =========================================================================
|
|
369
|
+
|
|
370
|
+
describe("Flow File Structure", () => {
|
|
371
|
+
it("should have valid XML declaration", () => {
|
|
372
|
+
const accountCreatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Account_Create.flow-meta.xml");
|
|
373
|
+
const opportunityUpdatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Opportunity_Update.flow-meta.xml");
|
|
374
|
+
|
|
375
|
+
const accountCreateContent = fs.readFileSync(accountCreatePath, "utf-8");
|
|
376
|
+
const opportunityUpdateContent = fs.readFileSync(opportunityUpdatePath, "utf-8");
|
|
377
|
+
|
|
378
|
+
expect(accountCreateContent).toContain("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
|
379
|
+
expect(opportunityUpdateContent).toContain("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
it("should have correct Salesforce Flow namespace", () => {
|
|
383
|
+
const accountCreatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Account_Create.flow-meta.xml");
|
|
384
|
+
const opportunityUpdatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Opportunity_Update.flow-meta.xml");
|
|
385
|
+
|
|
386
|
+
const accountCreateContent = fs.readFileSync(accountCreatePath, "utf-8");
|
|
387
|
+
const opportunityUpdateContent = fs.readFileSync(opportunityUpdatePath, "utf-8");
|
|
388
|
+
|
|
389
|
+
expect(accountCreateContent).toContain('xmlns="http://soap.sforce.com/2006/04/metadata"');
|
|
390
|
+
expect(opportunityUpdateContent).toContain('xmlns="http://soap.sforce.com/2006/04/metadata"');
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
it("should have Flow root element in both files", () => {
|
|
394
|
+
const accountCreatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Account_Create.flow-meta.xml");
|
|
395
|
+
const opportunityUpdatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Opportunity_Update.flow-meta.xml");
|
|
396
|
+
|
|
397
|
+
const accountCreateContent = fs.readFileSync(accountCreatePath, "utf-8");
|
|
398
|
+
const opportunityUpdateContent = fs.readFileSync(opportunityUpdatePath, "utf-8");
|
|
399
|
+
|
|
400
|
+
expect(accountCreateContent).toContain("<Flow xmlns=");
|
|
401
|
+
expect(opportunityUpdateContent).toContain("<Flow xmlns=");
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
it("should have interviewLabel in both flows", () => {
|
|
405
|
+
const accountCreatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Account_Create.flow-meta.xml");
|
|
406
|
+
const opportunityUpdatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Opportunity_Update.flow-meta.xml");
|
|
407
|
+
|
|
408
|
+
const accountCreateContent = fs.readFileSync(accountCreatePath, "utf-8");
|
|
409
|
+
const opportunityUpdateContent = fs.readFileSync(opportunityUpdatePath, "utf-8");
|
|
410
|
+
|
|
411
|
+
expect(accountCreateContent).toContain("<interviewLabel>Account Create Flow-1</interviewLabel>");
|
|
412
|
+
expect(opportunityUpdateContent).toContain("<interviewLabel>Opportunity Update Flow-1</interviewLabel>");
|
|
413
|
+
});
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
// =========================================================================
|
|
417
|
+
// FLOW TYPES COMPARISON
|
|
418
|
+
// =========================================================================
|
|
419
|
+
|
|
420
|
+
describe("Flow Types Comparison", () => {
|
|
421
|
+
it("should distinguish Screen Flow (Account_Create) from Record-triggered Flow (Opportunity_Update)", () => {
|
|
422
|
+
const accountCreatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Account_Create.flow-meta.xml");
|
|
423
|
+
const opportunityUpdatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Opportunity_Update.flow-meta.xml");
|
|
424
|
+
|
|
425
|
+
const accountCreateContent = fs.readFileSync(accountCreatePath, "utf-8");
|
|
426
|
+
const opportunityUpdateContent = fs.readFileSync(opportunityUpdatePath, "utf-8");
|
|
427
|
+
|
|
428
|
+
// Account_Create has screens element (Screen Flow indicator)
|
|
429
|
+
expect(accountCreateContent).toContain("<screens>");
|
|
430
|
+
expect(accountCreateContent).not.toContain("<triggers>");
|
|
431
|
+
|
|
432
|
+
// Opportunity_Update has triggers element (Record-triggered Flow indicator)
|
|
433
|
+
expect(opportunityUpdateContent).toContain("<triggers>");
|
|
434
|
+
expect(opportunityUpdateContent).not.toContain("<screens>");
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
it("should have different start element targets based on flow type", () => {
|
|
438
|
+
const accountCreatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Account_Create.flow-meta.xml");
|
|
439
|
+
const opportunityUpdatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Opportunity_Update.flow-meta.xml");
|
|
440
|
+
|
|
441
|
+
const accountCreateContent = fs.readFileSync(accountCreatePath, "utf-8");
|
|
442
|
+
const opportunityUpdateContent = fs.readFileSync(opportunityUpdatePath, "utf-8");
|
|
443
|
+
|
|
444
|
+
// Account_Create starts with screen (EnterAccountDetails)
|
|
445
|
+
expect(accountCreateContent).toContain("<targetReference>EnterAccountDetails</targetReference>");
|
|
446
|
+
|
|
447
|
+
// Opportunity_Update starts with decision (CheckStageChange)
|
|
448
|
+
expect(opportunityUpdateContent).toContain("<targetReference>CheckStageChange</targetReference>");
|
|
449
|
+
});
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
// =========================================================================
|
|
453
|
+
// UNIT TESTS - Flow XML parsing patterns
|
|
454
|
+
// =========================================================================
|
|
455
|
+
|
|
456
|
+
describe("Unit: Flow XML parsing patterns", () => {
|
|
457
|
+
it("should parse Flow metadata elements", () => {
|
|
458
|
+
const flowXml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
459
|
+
<Flow xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
460
|
+
<apiVersion>59.0</apiVersion>
|
|
461
|
+
<interviewLabel>Test Flow-1</interviewLabel>
|
|
462
|
+
<label>Test Flow</label>
|
|
463
|
+
<processType>Flow</processType>
|
|
464
|
+
<status>Active</status>
|
|
465
|
+
</Flow>`;
|
|
466
|
+
|
|
467
|
+
expect(flowXml).toContain("<apiVersion>59.0</apiVersion>");
|
|
468
|
+
expect(flowXml).toContain("<label>Test Flow</label>");
|
|
469
|
+
expect(flowXml).toContain("<processType>Flow</processType>");
|
|
470
|
+
expect(flowXml).toContain("<status>Active</status>");
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
it("should parse Screen Flow elements", () => {
|
|
474
|
+
const screenFlowXml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
475
|
+
<Flow xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
476
|
+
<screens>
|
|
477
|
+
<name>TestScreen</name>
|
|
478
|
+
<label>Test Screen</label>
|
|
479
|
+
<fields>
|
|
480
|
+
<name>TestField</name>
|
|
481
|
+
<fieldType>InputField</fieldType>
|
|
482
|
+
<required>true</required>
|
|
483
|
+
</fields>
|
|
484
|
+
</screens>
|
|
485
|
+
</Flow>`;
|
|
486
|
+
|
|
487
|
+
expect(screenFlowXml).toContain("<screens>");
|
|
488
|
+
expect(screenFlowXml).toContain("<name>TestScreen</name>");
|
|
489
|
+
expect(screenFlowXml).toContain("<fieldType>InputField</fieldType>");
|
|
490
|
+
expect(screenFlowXml).toContain("<required>true</required>");
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
it("should parse Record-triggered Flow elements", () => {
|
|
494
|
+
const recordTriggeredFlowXml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
495
|
+
<Flow xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
496
|
+
<triggers>
|
|
497
|
+
<name>TestTrigger</name>
|
|
498
|
+
<object>TestObject__c</object>
|
|
499
|
+
<triggerType>Upon Create or Update</triggerType>
|
|
500
|
+
<filters>
|
|
501
|
+
<field>Status__c</field>
|
|
502
|
+
<operator>Equal</operator>
|
|
503
|
+
</filters>
|
|
504
|
+
</triggers>
|
|
505
|
+
</Flow>`;
|
|
506
|
+
|
|
507
|
+
expect(recordTriggeredFlowXml).toContain("<triggers>");
|
|
508
|
+
expect(recordTriggeredFlowXml).toContain("<name>TestTrigger</name>");
|
|
509
|
+
expect(recordTriggeredFlowXml).toContain("<object>TestObject__c</object>");
|
|
510
|
+
expect(recordTriggeredFlowXml).toContain("<triggerType>Upon Create or Update</triggerType>");
|
|
511
|
+
expect(recordTriggeredFlowXml).toContain("<filters>");
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
it("should parse Decision elements with rules", () => {
|
|
515
|
+
const decisionFlowXml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
516
|
+
<Flow xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
517
|
+
<decisions>
|
|
518
|
+
<name>CheckCondition</name>
|
|
519
|
+
<rules>
|
|
520
|
+
<name>ConditionMet</name>
|
|
521
|
+
<conditions>
|
|
522
|
+
<leftValueReference>$Record.Status</leftValueReference>
|
|
523
|
+
<operator>Equal</operator>
|
|
524
|
+
<rightValue>
|
|
525
|
+
<stringValue>Active</stringValue>
|
|
526
|
+
</rightValue>
|
|
527
|
+
</conditions>
|
|
528
|
+
</rules>
|
|
529
|
+
</decisions>
|
|
530
|
+
</Flow>`;
|
|
531
|
+
|
|
532
|
+
expect(decisionFlowXml).toContain("<decisions>");
|
|
533
|
+
expect(decisionFlowXml).toContain("<name>CheckCondition</name>");
|
|
534
|
+
expect(decisionFlowXml).toContain("<rules>");
|
|
535
|
+
expect(decisionFlowXml).toContain("<name>ConditionMet</name>");
|
|
536
|
+
expect(decisionFlowXml).toContain("<leftValueReference>$Record.Status</leftValueReference>");
|
|
537
|
+
expect(decisionFlowXml).toContain("<stringValue>Active</stringValue>");
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
it("should parse Action elements", () => {
|
|
541
|
+
const actionFlowXml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
542
|
+
<Flow xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
543
|
+
<actions>
|
|
544
|
+
<name>UpdateRecord</name>
|
|
545
|
+
<label>Update Record</label>
|
|
546
|
+
<actionType>UpdateRecord</actionType>
|
|
547
|
+
<inputParameters>
|
|
548
|
+
<name>RecordId</name>
|
|
549
|
+
<value>
|
|
550
|
+
<elementReference>$Record.Id</elementReference>
|
|
551
|
+
</value>
|
|
552
|
+
</inputParameters>
|
|
553
|
+
</actions>
|
|
554
|
+
</Flow>`;
|
|
555
|
+
|
|
556
|
+
expect(actionFlowXml).toContain("<actions>");
|
|
557
|
+
expect(actionFlowXml).toContain("<name>UpdateRecord</name>");
|
|
558
|
+
expect(actionFlowXml).toContain("<actionType>UpdateRecord</actionType>");
|
|
559
|
+
expect(actionFlowXml).toContain("<elementReference>$Record.Id</elementReference>");
|
|
560
|
+
});
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
// =========================================================================
|
|
564
|
+
// FLOW SYMBOL EXTRACTION
|
|
565
|
+
// =========================================================================
|
|
566
|
+
|
|
567
|
+
describe("Flow Symbol Extraction", () => {
|
|
568
|
+
it("should extract Flow file as symbol (via XML extension)", () => {
|
|
569
|
+
const accountCreatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Account_Create.flow-meta.xml");
|
|
570
|
+
const content = fs.readFileSync(accountCreatePath, "utf-8");
|
|
571
|
+
|
|
572
|
+
// Flow files have .flow-meta.xml extension
|
|
573
|
+
// The symbol extractor handles XML files through the parser registry
|
|
574
|
+
const file = createFileInfo("force-app/main/default/flows/Account_Create.flow-meta.xml", "flow-meta.xml", content);
|
|
575
|
+
const result = extractSymbols([file]);
|
|
576
|
+
|
|
577
|
+
// XML files should be parsed (at minimum, the Flow root element should be recognized)
|
|
578
|
+
// Note: The current symbol extractor doesn't have specific Flow XML parsing
|
|
579
|
+
// but it should still process the file without error
|
|
580
|
+
expect(result).toBeDefined();
|
|
581
|
+
expect(result.symbols).toBeDefined();
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
it("should detect Flow metadata via XML content parsing", () => {
|
|
585
|
+
const accountCreatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Account_Create.flow-meta.xml");
|
|
586
|
+
const opportunityUpdatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Opportunity_Update.flow-meta.xml");
|
|
587
|
+
|
|
588
|
+
const accountCreateContent = fs.readFileSync(accountCreatePath, "utf-8");
|
|
589
|
+
const opportunityUpdateContent = fs.readFileSync(opportunityUpdatePath, "utf-8");
|
|
590
|
+
|
|
591
|
+
// Verify we can parse Flow name from XML
|
|
592
|
+
const accountCreateNameMatch = accountCreateContent.match(/<interviewLabel>([^<]+)-1<\/interviewLabel>/);
|
|
593
|
+
const opportunityUpdateNameMatch = opportunityUpdateContent.match(/<interviewLabel>([^<]+)-1<\/interviewLabel>/);
|
|
594
|
+
|
|
595
|
+
expect(accountCreateNameMatch).toBeTruthy();
|
|
596
|
+
expect(accountCreateNameMatch?.[1]).toBe("Account Create Flow");
|
|
597
|
+
expect(opportunityUpdateNameMatch).toBeTruthy();
|
|
598
|
+
expect(opportunityUpdateNameMatch?.[1]).toBe("Opportunity Update Flow");
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
it("should extract Flow type from processType element", () => {
|
|
602
|
+
const accountCreatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Account_Create.flow-meta.xml");
|
|
603
|
+
const opportunityUpdatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Opportunity_Update.flow-meta.xml");
|
|
604
|
+
|
|
605
|
+
const accountCreateContent = fs.readFileSync(accountCreatePath, "utf-8");
|
|
606
|
+
const opportunityUpdateContent = fs.readFileSync(opportunityUpdatePath, "utf-8");
|
|
607
|
+
|
|
608
|
+
const accountCreateTypeMatch = accountCreateContent.match(/<processType>(\w+)<\/processType>/);
|
|
609
|
+
const opportunityUpdateTypeMatch = opportunityUpdateContent.match(/<processType>(\w+)<\/processType>/);
|
|
610
|
+
|
|
611
|
+
expect(accountCreateTypeMatch?.[1]).toBe("Flow");
|
|
612
|
+
expect(opportunityUpdateTypeMatch?.[1]).toBe("Flow");
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
it("should extract Flow elements (screens, triggers, decisions, actions)", () => {
|
|
616
|
+
const accountCreatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Account_Create.flow-meta.xml");
|
|
617
|
+
const opportunityUpdatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Opportunity_Update.flow-meta.xml");
|
|
618
|
+
|
|
619
|
+
const accountCreateContent = fs.readFileSync(accountCreatePath, "utf-8");
|
|
620
|
+
const opportunityUpdateContent = fs.readFileSync(opportunityUpdatePath, "utf-8");
|
|
621
|
+
|
|
622
|
+
// Account_Create has screens and decisions and actions
|
|
623
|
+
expect(accountCreateContent).toMatch(/<screens>[\s\S]*<\/screens>/);
|
|
624
|
+
expect(accountCreateContent).toMatch(/<decisions>[\s\S]*<\/decisions>/);
|
|
625
|
+
expect(accountCreateContent).toMatch(/<actions>[\s\S]*<\/actions>/);
|
|
626
|
+
|
|
627
|
+
// Opportunity_Update has triggers and decisions and actions
|
|
628
|
+
expect(opportunityUpdateContent).toMatch(/<triggers>[\s\S]*<\/triggers>/);
|
|
629
|
+
expect(opportunityUpdateContent).toMatch(/<decisions>[\s\S]*<\/decisions>/);
|
|
630
|
+
expect(opportunityUpdateContent).toMatch(/<actions>[\s\S]*<\/actions>/);
|
|
631
|
+
});
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
// =========================================================================
|
|
635
|
+
// EDGE CASES
|
|
636
|
+
// =========================================================================
|
|
637
|
+
|
|
638
|
+
describe("Edge Cases", () => {
|
|
639
|
+
it("should handle flows with multiple decision rules", () => {
|
|
640
|
+
const accountCreatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Account_Create.flow-meta.xml");
|
|
641
|
+
const content = fs.readFileSync(accountCreatePath, "utf-8");
|
|
642
|
+
|
|
643
|
+
// ValidateAccountData decision has 1 rule
|
|
644
|
+
const validateAccountDecision = content.match(/<name>ValidateAccountData<\/name>[\s\S]*?<\/decisions>/);
|
|
645
|
+
expect(validateAccountDecision).toBeTruthy();
|
|
646
|
+
|
|
647
|
+
const ruleMatches = content.match(/<name>IsValidAccount<\/name>/g);
|
|
648
|
+
expect(ruleMatches).toHaveLength(1);
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
it("should handle flows with multiple actions", () => {
|
|
652
|
+
const opportunityUpdatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Opportunity_Update.flow-meta.xml");
|
|
653
|
+
const content = fs.readFileSync(opportunityUpdatePath, "utf-8");
|
|
654
|
+
|
|
655
|
+
// Opportunity_Update has 2 action blocks
|
|
656
|
+
const actionMatches = content.match(/<name>UpdateProbabilityHigh<\/name>|<name>SendWinNotification<\/name>/g);
|
|
657
|
+
expect(actionMatches).toHaveLength(2);
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
it("should handle flows with Chinese characters in trigger condition", () => {
|
|
661
|
+
const opportunityUpdatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Opportunity_Update.flow-meta.xml");
|
|
662
|
+
const content = fs.readFileSync(opportunityUpdatePath, "utf-8");
|
|
663
|
+
|
|
664
|
+
// Chinese characters in XML element
|
|
665
|
+
expect(content).toContain("<触发条件>When a record is updated</触发条件>");
|
|
666
|
+
});
|
|
667
|
+
|
|
668
|
+
it("should handle flows with different field data types", () => {
|
|
669
|
+
const accountCreatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Account_Create.flow-meta.xml");
|
|
670
|
+
const content = fs.readFileSync(accountCreatePath, "utf-8");
|
|
671
|
+
|
|
672
|
+
// Different data types in fields
|
|
673
|
+
expect(content).toContain("<dataType>String</dataType>");
|
|
674
|
+
expect(content).toContain("<dataType>Currency</dataType>");
|
|
675
|
+
expect(content).toContain("<dataType>Phone</dataType>");
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
it("should handle flows with conditionLogic variations", () => {
|
|
679
|
+
const opportunityUpdatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Opportunity_Update.flow-meta.xml");
|
|
680
|
+
const accountCreatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Account_Create.flow-meta.xml");
|
|
681
|
+
|
|
682
|
+
const opportunityUpdateContent = fs.readFileSync(opportunityUpdatePath, "utf-8");
|
|
683
|
+
const accountCreateContent = fs.readFileSync(accountCreatePath, "utf-8");
|
|
684
|
+
|
|
685
|
+
// Both use "and" condition logic
|
|
686
|
+
expect(opportunityUpdateContent).toContain("<conditionLogic>and</conditionLogic>");
|
|
687
|
+
expect(accountCreateContent).toContain("<conditionLogic>and</conditionLogic>");
|
|
688
|
+
});
|
|
689
|
+
|
|
690
|
+
it("should handle flows with element references ($Record, $Opportunity)", () => {
|
|
691
|
+
const opportunityUpdatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Opportunity_Update.flow-meta.xml");
|
|
692
|
+
const content = fs.readFileSync(opportunityUpdatePath, "utf-8");
|
|
693
|
+
|
|
694
|
+
// Opportunity_Update uses $Opportunity variable
|
|
695
|
+
expect(content).toContain("$Opportunity.StageName");
|
|
696
|
+
expect(content).toContain("$Opportunity.Id");
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
it("should handle flows with input/output field mappings", () => {
|
|
700
|
+
const accountCreatePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/flows/Account_Create.flow-meta.xml");
|
|
701
|
+
const content = fs.readFileSync(accountCreatePath, "utf-8");
|
|
702
|
+
|
|
703
|
+
// Element references in input parameters
|
|
704
|
+
expect(content).toContain("<elementReference>EnterAccountDetails.AccountName</elementReference>");
|
|
705
|
+
expect(content).toContain("<elementReference>EnterAccountDetails.Industry</elementReference>");
|
|
706
|
+
expect(content).toContain("<elementReference>EnterAccountDetails.AnnualRevenue</elementReference>");
|
|
707
|
+
expect(content).toContain("<elementReference>EnterAccountDetails.Phone</elementReference>");
|
|
708
|
+
});
|
|
709
|
+
});
|
|
710
|
+
});
|