dmart 1.4.33__py3-none-any.whl → 1.4.36__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dmart/__init__.py +8 -0
- dmart/alembic/README +1 -0
- dmart/alembic/notes.txt +11 -0
- dmart/alembic/script.py.mako +28 -0
- dmart/alembic.ini +117 -0
- dmart/config.env.sample +27 -0
- dmart/conftest.py +13 -0
- dmart/curl.sh +196 -0
- dmart.py → dmart/dmart.py +47 -40
- dmart/hypercorn_config.toml +3 -0
- dmart/info.json +1 -0
- dmart/login_creds.sh +7 -0
- dmart/login_creds.sh.sample +7 -0
- main.py → dmart/main.py +4 -1
- dmart/manifest.sh +12 -0
- dmart/plugins/action_log/config.json +13 -0
- dmart/plugins/admin_notification_sender/config.json +13 -0
- dmart/plugins/ldap_manager/config.json +12 -0
- dmart/plugins/ldap_manager/dmart.schema +146 -0
- dmart/plugins/ldap_manager/slapd.conf +53 -0
- dmart/plugins/local_notification/config.json +13 -0
- dmart/plugins/realtime_updates_notifier/config.json +12 -0
- dmart/plugins/redis_db_update/config.json +13 -0
- dmart/plugins/resource_folders_creation/config.json +12 -0
- dmart/plugins/system_notification_sender/config.json +13 -0
- dmart/plugins/update_access_controls/config.json +12 -0
- dmart/publish.sh +57 -0
- dmart/pylint.sh +16 -0
- dmart/pyrightconfig.json +7 -0
- dmart/redis_connections.sh +13 -0
- dmart/reload.sh +56 -0
- dmart/run.sh +3 -0
- dmart/test_utils.py +34 -0
- {dmart-1.4.33.dist-info → dmart-1.4.36.dist-info}/METADATA +1 -1
- dmart-1.4.36.dist-info/RECORD +285 -0
- dmart-1.4.36.dist-info/entry_points.txt +2 -0
- dmart-1.4.36.dist-info/top_level.txt +1 -0
- dmart-1.4.33.dist-info/RECORD +0 -264
- dmart-1.4.33.dist-info/entry_points.txt +0 -2
- dmart-1.4.33.dist-info/top_level.txt +0 -24
- pytests/api_user_models_erros_test.py +0 -16
- pytests/api_user_models_requests_test.py +0 -98
- pytests/archive_test.py +0 -72
- pytests/base_test.py +0 -300
- pytests/get_settings_test.py +0 -14
- pytests/json_to_db_migration_test.py +0 -237
- pytests/service_test.py +0 -26
- pytests/test_info.py +0 -55
- pytests/test_status.py +0 -15
- utils/__init__.py +0 -0
- {alembic → dmart/alembic}/__init__.py +0 -0
- {alembic → dmart/alembic}/env.py +0 -0
- {alembic → dmart/alembic}/scripts/__init__.py +0 -0
- {alembic → dmart/alembic}/scripts/calculate_checksums.py +0 -0
- {alembic → dmart/alembic}/scripts/migration_f7a4949eed19.py +0 -0
- {alembic → dmart/alembic}/versions/0f3d2b1a7c21_add_authz_materialized_views.py +0 -0
- {alembic → dmart/alembic}/versions/10d2041b94d4_last_checksum_history.py +0 -0
- {alembic → dmart/alembic}/versions/1cf4e1ee3cb8_ext_permission_with_filter_fields_values.py +0 -0
- {alembic → dmart/alembic}/versions/26bfe19b49d4_rm_failedloginattempts.py +0 -0
- {alembic → dmart/alembic}/versions/3c8bca2219cc_add_otp_table.py +0 -0
- {alembic → dmart/alembic}/versions/6675fd9dfe42_remove_unique_from_sessions_table.py +0 -0
- {alembic → dmart/alembic}/versions/71bc1df82e6a_adding_user_last_login_at.py +0 -0
- {alembic → dmart/alembic}/versions/74288ccbd3b5_initial.py +0 -0
- {alembic → dmart/alembic}/versions/7520a89a8467_rm_activesession_table.py +0 -0
- {alembic → dmart/alembic}/versions/848b623755a4_make_created_nd_updated_at_required.py +0 -0
- {alembic → dmart/alembic}/versions/8640dcbebf85_add_notes_to_users.py +0 -0
- {alembic → dmart/alembic}/versions/91c94250232a_adding_fk_on_owner_shortname.py +0 -0
- {alembic → dmart/alembic}/versions/98ecd6f56f9a_ext_meta_with_owner_group_shortname.py +0 -0
- {alembic → dmart/alembic}/versions/9aae9138c4ef_indexing_created_at_updated_at.py +0 -0
- {alembic → dmart/alembic}/versions/__init__.py +0 -0
- {alembic → dmart/alembic}/versions/b53f916b3f6d_json_to_jsonb.py +0 -0
- {alembic → dmart/alembic}/versions/eb5f1ec65156_adding_user_locked_to_device.py +0 -0
- {alembic → dmart/alembic}/versions/f7a4949eed19_adding_query_policies_to_meta.py +0 -0
- {api → dmart/api}/__init__.py +0 -0
- {api → dmart/api}/info/__init__.py +0 -0
- {api → dmart/api}/info/router.py +0 -0
- {api → dmart/api}/managed/__init__.py +0 -0
- {api → dmart/api}/managed/router.py +0 -0
- {api → dmart/api}/managed/utils.py +0 -0
- {api → dmart/api}/public/__init__.py +0 -0
- {api → dmart/api}/public/router.py +0 -0
- {api → dmart/api}/qr/__init__.py +0 -0
- {api → dmart/api}/qr/router.py +0 -0
- {api → dmart/api}/user/__init__.py +0 -0
- {api → dmart/api}/user/model/__init__.py +0 -0
- {api → dmart/api}/user/model/errors.py +0 -0
- {api → dmart/api}/user/model/requests.py +0 -0
- {api → dmart/api}/user/model/responses.py +0 -0
- {api → dmart/api}/user/router.py +0 -0
- {api → dmart/api}/user/service.py +0 -0
- /bundler.py → /dmart/bundler.py +0 -0
- {config → dmart/config}/__init__.py +0 -0
- {config → dmart/config}/channels.json +0 -0
- {config → dmart/config}/notification.json +0 -0
- {cxb → dmart/cxb}/__init__.py +0 -0
- {cxb/client → dmart/cxb}/assets/@codemirror-Rn7_6DkE.js +0 -0
- {cxb/client → dmart/cxb}/assets/@edraj-CS4NwVbD.js +0 -0
- {cxb/client → dmart/cxb}/assets/@floating-ui-BwwcF-xh.js +0 -0
- {cxb/client → dmart/cxb}/assets/@formatjs-yKEsAtjs.js +0 -0
- {cxb/client → dmart/cxb}/assets/@fortawesome-DRW1UCdr.js +0 -0
- {cxb/client → dmart/cxb}/assets/@jsonquerylang-laKNoFFq.js +0 -0
- {cxb/client → dmart/cxb}/assets/@lezer-za4Q-8Ew.js +0 -0
- {cxb/client → dmart/cxb}/assets/@marijn-DXwl3gUT.js +0 -0
- {cxb/client → dmart/cxb}/assets/@popperjs-l0sNRNKZ.js +0 -0
- {cxb/client → dmart/cxb}/assets/@replit--ERk53eB.js +0 -0
- {cxb/client → dmart/cxb}/assets/@roxi-CGMFK4i8.js +0 -0
- {cxb/client → dmart/cxb}/assets/@typewriter-cCzskkIv.js +0 -0
- {cxb/client → dmart/cxb}/assets/@zerodevx-BlBZjKxu.js +0 -0
- {cxb/client → dmart/cxb}/assets/@zerodevx-CVEpe6WZ.css +0 -0
- {cxb/client → dmart/cxb}/assets/BreadCrumbLite-DAhOx38v.js +0 -0
- {cxb/client → dmart/cxb}/assets/EntryRenderer-25YDhRen.js +0 -0
- {cxb/client → dmart/cxb}/assets/EntryRenderer-DXytdFp9.css +0 -0
- {cxb/client → dmart/cxb}/assets/ListView-BpAycA2h.js +0 -0
- {cxb/client → dmart/cxb}/assets/ListView-U8of-_c-.css +0 -0
- {cxb/client → dmart/cxb}/assets/Prism--hMplq-p.js +0 -0
- {cxb/client → dmart/cxb}/assets/Prism-Uh6uStUw.css +0 -0
- {cxb/client → dmart/cxb}/assets/Table2Cols-BsbwicQm.js +0 -0
- {cxb/client → dmart/cxb}/assets/_..-BvT6vdHa.css +0 -0
- {cxb/client → dmart/cxb}/assets/_...404_-fuLH_rX9.js +0 -0
- {cxb/client → dmart/cxb}/assets/_...fallback_-Ba_NLmAE.js +0 -0
- {cxb/client → dmart/cxb}/assets/_module-Bfk8MiCs.js +0 -0
- {cxb/client → dmart/cxb}/assets/_module-CEW0D5oI.js +0 -0
- {cxb/client → dmart/cxb}/assets/_module-Dgq0ZVtz.js +0 -0
- {cxb/client → dmart/cxb}/assets/ajv-Cpj98o6Y.js +0 -0
- {cxb/client → dmart/cxb}/assets/axios-CG2WSiiR.js +0 -0
- {cxb/client → dmart/cxb}/assets/clsx-B-dksMZM.js +0 -0
- {cxb/client → dmart/cxb}/assets/codemirror-wrapped-line-indent-DPhKvljI.js +0 -0
- {cxb/client → dmart/cxb}/assets/compare-C3AjiGFR.js +0 -0
- {cxb/client → dmart/cxb}/assets/compute-scroll-into-view-Bl8rNFhg.js +0 -0
- {cxb/client → dmart/cxb}/assets/consolite-DlCuI0F9.js +0 -0
- {cxb/client → dmart/cxb}/assets/crelt-C8TCjufn.js +0 -0
- {cxb/client → dmart/cxb}/assets/date-fns-l0sNRNKZ.js +0 -0
- {cxb/client → dmart/cxb}/assets/deepmerge-rn4rBaHU.js +0 -0
- {cxb/client → dmart/cxb}/assets/dmart_services-AL6-IdDE.js +0 -0
- {cxb/client → dmart/cxb}/assets/downloadFile-D08i0YDh.js +0 -0
- {cxb/client → dmart/cxb}/assets/easy-signal-BiPFIK3O.js +0 -0
- {cxb/client → dmart/cxb}/assets/esm-env-rsSWfq8L.js +0 -0
- {cxb/client → dmart/cxb}/assets/export-OF_rTiXu.js +0 -0
- {cxb/client → dmart/cxb}/assets/fast-deep-equal-l0sNRNKZ.js +0 -0
- {cxb/client → dmart/cxb}/assets/fast-diff-C-IidNf4.js +0 -0
- {cxb/client → dmart/cxb}/assets/fast-uri-l0sNRNKZ.js +0 -0
- {cxb/client → dmart/cxb}/assets/flowbite-svelte-BLvjb-sa.js +0 -0
- {cxb/client → dmart/cxb}/assets/flowbite-svelte-CD54FDqW.css +0 -0
- {cxb/client → dmart/cxb}/assets/flowbite-svelte-icons-BI8GVhw_.js +0 -0
- {cxb/client → dmart/cxb}/assets/github-slugger-CQ4oX9Ud.js +0 -0
- {cxb/client → dmart/cxb}/assets/global-igKv-1g9.js +0 -0
- {cxb/client → dmart/cxb}/assets/hookar-BMRD9G9H.js +0 -0
- {cxb/client → dmart/cxb}/assets/immutable-json-patch-DtRO2E_S.js +0 -0
- {cxb/client → dmart/cxb}/assets/import-1vE3gBat.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-B-eTh-ZX.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-BVyxzKtH.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-BdeNM69f.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-C6cPO4op.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-CC-A1ipE.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-CTxJ-lDp.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-Cd-F5j_k.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-D742rwaM.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-DTfhnhwd.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-DdXRK7n9.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-DtiCmB4o.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-NBrXBlLA.css +0 -0
- {cxb/client → dmart/cxb}/assets/index-ac-Buu_H.js +0 -0
- {cxb/client → dmart/cxb}/assets/index-iYkH7C67.js +0 -0
- {cxb/client → dmart/cxb}/assets/info-B986lRiM.js +0 -0
- {cxb/client → dmart/cxb}/assets/intl-messageformat-Dc5UU-HB.js +0 -0
- {cxb/client → dmart/cxb}/assets/jmespath-l0sNRNKZ.js +0 -0
- {cxb/client → dmart/cxb}/assets/json-schema-traverse-l0sNRNKZ.js +0 -0
- {cxb/client → dmart/cxb}/assets/json-source-map-DRgZidqy.js +0 -0
- {cxb/client → dmart/cxb}/assets/jsonpath-plus-l0sNRNKZ.js +0 -0
- {cxb/client → dmart/cxb}/assets/jsonrepair-B30Dx381.js +0 -0
- {cxb/client → dmart/cxb}/assets/lodash-es-DZVAA2ox.js +0 -0
- {cxb/client → dmart/cxb}/assets/marked-DKjyhwJX.js +0 -0
- {cxb/client → dmart/cxb}/assets/marked-gfm-heading-id-U5zO829x.js +0 -0
- {cxb/client → dmart/cxb}/assets/marked-mangle-CDMeiHC6.js +0 -0
- {cxb/client → dmart/cxb}/assets/memoize-one-BdPwpGay.js +0 -0
- {cxb/client → dmart/cxb}/assets/natural-compare-lite-Bg2Xcf-o.js +0 -0
- {cxb/client → dmart/cxb}/assets/pagination-svelte-D5CyoiE_.js +0 -0
- {cxb/client → dmart/cxb}/assets/pagination-svelte-v10nAbbM.css +0 -0
- {cxb/client → dmart/cxb}/assets/plantuml-encoder-C47mzt9T.js +0 -0
- {cxb/client → dmart/cxb}/assets/prismjs-DTUiLGJu.js +0 -0
- {cxb/client → dmart/cxb}/assets/profile-BUf-tKMe.js +0 -0
- {cxb/client → dmart/cxb}/assets/query-CNmXTsgf.js +0 -0
- {cxb/client → dmart/cxb}/assets/queryHelpers-C9iBWwqe.js +0 -0
- {cxb/client → dmart/cxb}/assets/scroll-into-view-if-needed-KR58zyjF.js +0 -0
- {cxb/client → dmart/cxb}/assets/spaces-0oyGvpii.js +0 -0
- {cxb/client → dmart/cxb}/assets/style-mod-Bs6eFhZE.js +0 -0
- {cxb/client → dmart/cxb}/assets/svelte-B2XmcTi_.js +0 -0
- {cxb/client → dmart/cxb}/assets/svelte-awesome-COLlx0DN.css +0 -0
- {cxb/client → dmart/cxb}/assets/svelte-awesome-DhnMA6Q_.js +0 -0
- {cxb/client → dmart/cxb}/assets/svelte-datatables-net-CY7LBj6I.js +0 -0
- {cxb/client → dmart/cxb}/assets/svelte-floating-ui-BlS3sOAQ.js +0 -0
- {cxb/client → dmart/cxb}/assets/svelte-i18n-CT2KkQaN.js +0 -0
- {cxb/client → dmart/cxb}/assets/svelte-jsoneditor-BzfX6Usi.css +0 -0
- {cxb/client → dmart/cxb}/assets/svelte-jsoneditor-CUGSvWId.js +0 -0
- {cxb/client → dmart/cxb}/assets/svelte-select-CegQKzqH.css +0 -0
- {cxb/client → dmart/cxb}/assets/svelte-select-CjHAt_85.js +0 -0
- {cxb/client → dmart/cxb}/assets/tailwind-merge-CJvxXMcu.js +0 -0
- {cxb/client → dmart/cxb}/assets/tailwind-variants-Cj20BoQ3.js +0 -0
- {cxb/client → dmart/cxb}/assets/toast-B9WDyfyI.js +0 -0
- {cxb/client → dmart/cxb}/assets/tslib-pJfR_DrR.js +0 -0
- {cxb/client → dmart/cxb}/assets/typewriter-editor-DkTVIJdm.js +0 -0
- {cxb/client → dmart/cxb}/assets/user-DeK_NB5v.js +0 -0
- {cxb/client → dmart/cxb}/assets/vanilla-picker-l5rcX3cq.js +0 -0
- {cxb/client → dmart/cxb}/assets/w3c-keyname-Vcq4gwWv.js +0 -0
- {cxb/client → dmart/cxb}/config.json +0 -0
- {cxb/client → dmart/cxb}/config.sample.json +0 -0
- {cxb/client → dmart/cxb}/favicon.ico +0 -0
- {cxb/client → dmart/cxb}/favicon.png +0 -0
- {cxb/client → dmart/cxb}/index.html +0 -0
- {data_adapters → dmart/data_adapters}/__init__.py +0 -0
- {data_adapters → dmart/data_adapters}/adapter.py +0 -0
- {data_adapters → dmart/data_adapters}/base_data_adapter.py +0 -0
- {data_adapters → dmart/data_adapters}/file/__init__.py +0 -0
- {data_adapters → dmart/data_adapters}/file/adapter.py +0 -0
- {data_adapters → dmart/data_adapters}/file/adapter_helpers.py +0 -0
- {data_adapters → dmart/data_adapters}/file/archive.py +0 -0
- {data_adapters → dmart/data_adapters}/file/create_index.py +0 -0
- {data_adapters → dmart/data_adapters}/file/create_users_folders.py +0 -0
- {data_adapters → dmart/data_adapters}/file/custom_validations.py +0 -0
- {data_adapters → dmart/data_adapters}/file/drop_index.py +0 -0
- {data_adapters → dmart/data_adapters}/file/health_check.py +0 -0
- {data_adapters → dmart/data_adapters}/file/redis_services.py +0 -0
- {data_adapters → dmart/data_adapters}/helpers.py +0 -0
- {data_adapters → dmart/data_adapters}/sql/__init__.py +0 -0
- {data_adapters → dmart/data_adapters}/sql/adapter.py +0 -0
- {data_adapters → dmart/data_adapters}/sql/adapter_helpers.py +0 -0
- {data_adapters → dmart/data_adapters}/sql/create_tables.py +0 -0
- {data_adapters → dmart/data_adapters}/sql/create_users_folders.py +0 -0
- {data_adapters → dmart/data_adapters}/sql/db_to_json_migration.py +0 -0
- {data_adapters → dmart/data_adapters}/sql/health_check_sql.py +0 -0
- {data_adapters → dmart/data_adapters}/sql/json_to_db_migration.py +0 -0
- {data_adapters → dmart/data_adapters}/sql/update_query_policies.py +0 -0
- /data_generator.py → /dmart/data_generator.py +0 -0
- /get_settings.py → /dmart/get_settings.py +0 -0
- {languages → dmart/languages}/__init__.py +0 -0
- {languages → dmart/languages}/arabic.json +0 -0
- {languages → dmart/languages}/english.json +0 -0
- {languages → dmart/languages}/kurdish.json +0 -0
- {languages → dmart/languages}/loader.py +0 -0
- /migrate.py → /dmart/migrate.py +0 -0
- {models → dmart/models}/__init__.py +0 -0
- {models → dmart/models}/api.py +0 -0
- {models → dmart/models}/core.py +0 -0
- {models → dmart/models}/enums.py +0 -0
- /password_gen.py → /dmart/password_gen.py +0 -0
- {plugins → dmart/plugins}/__init__.py +0 -0
- {plugins → dmart/plugins}/action_log/__init__.py +0 -0
- {plugins → dmart/plugins}/action_log/plugin.py +0 -0
- {plugins → dmart/plugins}/admin_notification_sender/__init__.py +0 -0
- {plugins → dmart/plugins}/admin_notification_sender/plugin.py +0 -0
- {plugins → dmart/plugins}/ldap_manager/__init__.py +0 -0
- {plugins → dmart/plugins}/ldap_manager/plugin.py +0 -0
- {plugins → dmart/plugins}/local_notification/__init__.py +0 -0
- {plugins → dmart/plugins}/local_notification/plugin.py +0 -0
- {plugins → dmart/plugins}/realtime_updates_notifier/__init__.py +0 -0
- {plugins → dmart/plugins}/realtime_updates_notifier/plugin.py +0 -0
- {plugins → dmart/plugins}/redis_db_update/__init__.py +0 -0
- {plugins → dmart/plugins}/redis_db_update/plugin.py +0 -0
- {plugins → dmart/plugins}/resource_folders_creation/__init__.py +0 -0
- {plugins → dmart/plugins}/resource_folders_creation/plugin.py +0 -0
- {plugins → dmart/plugins}/system_notification_sender/__init__.py +0 -0
- {plugins → dmart/plugins}/system_notification_sender/plugin.py +0 -0
- {plugins → dmart/plugins}/update_access_controls/__init__.py +0 -0
- {plugins → dmart/plugins}/update_access_controls/plugin.py +0 -0
- /run_notification_campaign.py → /dmart/run_notification_campaign.py +0 -0
- /scheduled_notification_handler.py → /dmart/scheduled_notification_handler.py +0 -0
- /schema_migration.py → /dmart/schema_migration.py +0 -0
- /schema_modulate.py → /dmart/schema_modulate.py +0 -0
- /set_admin_passwd.py → /dmart/set_admin_passwd.py +0 -0
- /sync.py → /dmart/sync.py +0 -0
- {pytests → dmart/utils}/__init__.py +0 -0
- {utils → dmart/utils}/access_control.py +0 -0
- {utils → dmart/utils}/async_request.py +0 -0
- {utils → dmart/utils}/exporter.py +0 -0
- {utils → dmart/utils}/firebase_notifier.py +0 -0
- {utils → dmart/utils}/generate_email.py +0 -0
- {utils → dmart/utils}/helpers.py +0 -0
- {utils → dmart/utils}/hypercorn_config.py +0 -0
- {utils → dmart/utils}/internal_error_code.py +0 -0
- {utils → dmart/utils}/jwt.py +0 -0
- {utils → dmart/utils}/logger.py +0 -0
- {utils → dmart/utils}/middleware.py +0 -0
- {utils → dmart/utils}/notification.py +0 -0
- {utils → dmart/utils}/password_hashing.py +0 -0
- {utils → dmart/utils}/plugin_manager.py +0 -0
- {utils → dmart/utils}/query_policies_helper.py +0 -0
- {utils → dmart/utils}/regex.py +0 -0
- {utils → dmart/utils}/repository.py +0 -0
- {utils → dmart/utils}/router_helper.py +0 -0
- {utils → dmart/utils}/settings.py +0 -0
- {utils → dmart/utils}/sms_notifier.py +0 -0
- {utils → dmart/utils}/social_sso.py +0 -0
- {utils → dmart/utils}/templates/activation.html.j2 +0 -0
- {utils → dmart/utils}/templates/reminder.html.j2 +0 -0
- {utils → dmart/utils}/ticket_sys_utils.py +0 -0
- {utils → dmart/utils}/web_notifier.py +0 -0
- /websocket.py → /dmart/websocket.py +0 -0
- {dmart-1.4.33.dist-info → dmart-1.4.36.dist-info}/WHEEL +0 -0
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
from pydantic import ValidationError
|
|
3
|
-
|
|
4
|
-
from api.user.model.requests import (
|
|
5
|
-
OTPType,
|
|
6
|
-
SendOTPRequest,
|
|
7
|
-
PasswordResetRequest,
|
|
8
|
-
ConfirmOTPRequest,
|
|
9
|
-
UserLoginRequest,
|
|
10
|
-
Exception,
|
|
11
|
-
Error,
|
|
12
|
-
InternalErrorCode
|
|
13
|
-
)
|
|
14
|
-
import utils.regex as rgx
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def test_send_otp_request_valid_msisdn():
|
|
18
|
-
request = SendOTPRequest(msisdn="7777778110")
|
|
19
|
-
result = request.check_fields()
|
|
20
|
-
assert result == {"msisdn": "7777778110"}
|
|
21
|
-
|
|
22
|
-
def test_send_otp_request_valid_email():
|
|
23
|
-
request = SendOTPRequest(email="test@example.com")
|
|
24
|
-
result = request.check_fields()
|
|
25
|
-
assert result == {"email": "test@example.com"}
|
|
26
|
-
|
|
27
|
-
def test_send_otp_request_missing_fields():
|
|
28
|
-
# Ensure both fields are explicitly None
|
|
29
|
-
with pytest.raises(Exception) as excinfo:
|
|
30
|
-
SendOTPRequest(msisdn=None, email=None).check_fields()
|
|
31
|
-
assert excinfo.value.status_code == 422
|
|
32
|
-
assert excinfo.value.error.code == InternalErrorCode.EMAIL_OR_MSISDN_REQUIRED
|
|
33
|
-
|
|
34
|
-
def test_send_otp_request_too_many_fields():
|
|
35
|
-
with pytest.raises(Exception) as excinfo:
|
|
36
|
-
SendOTPRequest(msisdn="7777778110", email="test@example.com").check_fields()
|
|
37
|
-
assert excinfo.value.status_code == 422
|
|
38
|
-
assert excinfo.value.error.code == InternalErrorCode.INVALID_STANDALONE_DATA
|
|
39
|
-
|
|
40
|
-
def test_password_reset_request_valid_msisdn():
|
|
41
|
-
request = PasswordResetRequest(msisdn="7777778110")
|
|
42
|
-
result = request.check_fields()
|
|
43
|
-
assert result == {"msisdn": "7777778110"}
|
|
44
|
-
|
|
45
|
-
def test_password_reset_request_valid_email():
|
|
46
|
-
request = PasswordResetRequest(email="test@example.com")
|
|
47
|
-
result = request.check_fields()
|
|
48
|
-
assert result == {"email": "test@example.com"}
|
|
49
|
-
|
|
50
|
-
def test_password_reset_request_missing_fields():
|
|
51
|
-
with pytest.raises(Exception) as excinfo:
|
|
52
|
-
PasswordResetRequest().check_fields()
|
|
53
|
-
assert excinfo.value.status_code == 422
|
|
54
|
-
assert excinfo.value.error.code == InternalErrorCode.EMAIL_OR_MSISDN_REQUIRED
|
|
55
|
-
|
|
56
|
-
def test_password_reset_request_too_many_fields():
|
|
57
|
-
with pytest.raises(Exception) as excinfo:
|
|
58
|
-
PasswordResetRequest(msisdn="7777778110", email="test@example.com").check_fields()
|
|
59
|
-
assert excinfo.value.status_code == 422
|
|
60
|
-
assert excinfo.value.error.code == InternalErrorCode.INVALID_STANDALONE_DATA
|
|
61
|
-
|
|
62
|
-
def test_confirm_otp_request_valid():
|
|
63
|
-
request = ConfirmOTPRequest(msisdn="7777778110", code="123456")
|
|
64
|
-
assert request.msisdn == "7777778110"
|
|
65
|
-
assert request.code == "123456"
|
|
66
|
-
|
|
67
|
-
def test_confirm_otp_request_invalid_code():
|
|
68
|
-
with pytest.raises(ValidationError):
|
|
69
|
-
ConfirmOTPRequest(msisdn="7777778110", code="invalid")
|
|
70
|
-
|
|
71
|
-
def test_user_login_request_valid_shortname():
|
|
72
|
-
request = UserLoginRequest(shortname="john_doo", password="my_secure_password_@_93301")
|
|
73
|
-
result = request.check_fields()
|
|
74
|
-
assert result == {"shortname": "john_doo"}
|
|
75
|
-
|
|
76
|
-
def test_user_login_request_valid_email():
|
|
77
|
-
request = UserLoginRequest(email="test@example.com", password="my_secure_password_@_93301")
|
|
78
|
-
result = request.check_fields()
|
|
79
|
-
assert result == {"email": "test@example.com"}
|
|
80
|
-
|
|
81
|
-
def test_user_login_request_valid_msisdn():
|
|
82
|
-
request = UserLoginRequest(msisdn="7777778110", password="my_secure_password_@_93301")
|
|
83
|
-
result = request.check_fields()
|
|
84
|
-
assert result == {"msisdn": "7777778110"}
|
|
85
|
-
|
|
86
|
-
def test_user_login_request_missing_fields():
|
|
87
|
-
request = UserLoginRequest(password="my_secure_password_@_93301")
|
|
88
|
-
result = request.check_fields()
|
|
89
|
-
assert result == {}
|
|
90
|
-
|
|
91
|
-
def test_user_login_request_too_many_fields():
|
|
92
|
-
with pytest.raises(ValueError, match="Too many input has been passed"):
|
|
93
|
-
UserLoginRequest(shortname="john_doo", email="test@example.com", msisdn="7777778110", password="my_secure_password_@_93301").check_fields()
|
|
94
|
-
|
|
95
|
-
def test_user_login_request_missing_password():
|
|
96
|
-
request = UserLoginRequest(shortname="john_doo")
|
|
97
|
-
result = request.check_fields()
|
|
98
|
-
assert result == {"shortname": "john_doo"}
|
pytests/archive_test.py
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
# import pytest
|
|
2
|
-
# from unittest.mock import patch
|
|
3
|
-
# from time import time
|
|
4
|
-
# import argparse
|
|
5
|
-
# import asyncio
|
|
6
|
-
# from archive import redis_doc_to_meta, archive
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
# def test_redis_doc_to_meta():
|
|
10
|
-
# mock_record = {
|
|
11
|
-
# "resource_type": "record",
|
|
12
|
-
# "created_at": time(),
|
|
13
|
-
# "updated_at": time(),
|
|
14
|
-
# }
|
|
15
|
-
# expected_keys = ["resource_type", "created_at", "updated_at"]
|
|
16
|
-
# with patch("models.core.Record") as MockRecord:
|
|
17
|
-
# MockRecord.model_fields.keys.return_value = expected_keys
|
|
18
|
-
# MockRecord.model_validate.return_value = mock_record
|
|
19
|
-
# meta = redis_doc_to_meta(mock_record)
|
|
20
|
-
# assert meta == mock_record
|
|
21
|
-
# assert MockRecord.model_fields.keys.call_count == 3
|
|
22
|
-
# MockRecord.model_validate.assert_called_once()
|
|
23
|
-
#
|
|
24
|
-
# def main():
|
|
25
|
-
# parser = argparse.ArgumentParser(
|
|
26
|
-
# description="Script for archiving records from different spaces and subpaths."
|
|
27
|
-
# )
|
|
28
|
-
# parser.add_argument("space", type=str, help="The name of the space")
|
|
29
|
-
# parser.add_argument("subpath", type=str, help="The subpath within the space")
|
|
30
|
-
# parser.add_argument(
|
|
31
|
-
# "schema",
|
|
32
|
-
# type=str,
|
|
33
|
-
# help="The subpath within the space. Optional, if not provided move everything",
|
|
34
|
-
# nargs="?",
|
|
35
|
-
# )
|
|
36
|
-
# parser.add_argument(
|
|
37
|
-
# "olderthan",
|
|
38
|
-
# type=int,
|
|
39
|
-
# help="The number of day, older than which, the entries will be archived (based on updated_at)",
|
|
40
|
-
# )
|
|
41
|
-
#
|
|
42
|
-
# args = parser.parse_args()
|
|
43
|
-
# space = args.space
|
|
44
|
-
# subpath = args.subpath
|
|
45
|
-
# olderthan = args.olderthan
|
|
46
|
-
# schema = args.schema or "meta"
|
|
47
|
-
#
|
|
48
|
-
# asyncio.run(archive(space, subpath, schema, olderthan))
|
|
49
|
-
# print("Done.")
|
|
50
|
-
#
|
|
51
|
-
#
|
|
52
|
-
# @pytest.mark.asyncio
|
|
53
|
-
# @patch("argparse.ArgumentParser.parse_args")
|
|
54
|
-
# @patch("archive.archive")
|
|
55
|
-
# async def test_main(mock_archive, mock_parse_args):
|
|
56
|
-
# mock_args = argparse.Namespace(
|
|
57
|
-
# space="space",
|
|
58
|
-
# subpath="subpath",
|
|
59
|
-
# schema="schema",
|
|
60
|
-
# olderthan=1
|
|
61
|
-
# )
|
|
62
|
-
# mock_parse_args.return_value = mock_args
|
|
63
|
-
#
|
|
64
|
-
# with patch("asyncio.run") as mock_asyncio_run:
|
|
65
|
-
# mock_asyncio_run.side_effect = lambda x: asyncio.ensure_future(x)
|
|
66
|
-
# main()
|
|
67
|
-
#
|
|
68
|
-
# mock_parse_args.assert_called_once()
|
|
69
|
-
# mock_asyncio_run.assert_called_once()
|
|
70
|
-
#
|
|
71
|
-
# if __name__ == "__main__":
|
|
72
|
-
# pytest.main()
|
pytests/base_test.py
DELETED
|
@@ -1,300 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
from utils.settings import settings
|
|
3
|
-
from fastapi import status
|
|
4
|
-
from models.api import Query
|
|
5
|
-
from models.enums import QueryType, ResourceType, RequestType
|
|
6
|
-
|
|
7
|
-
superman = {}
|
|
8
|
-
alibaba = {}
|
|
9
|
-
|
|
10
|
-
with open("./login_creds.sh", "r") as file:
|
|
11
|
-
for line in file.readlines():
|
|
12
|
-
if line.strip().startswith("export SUPERMAN"):
|
|
13
|
-
superman = json.loads(str(line.strip().split("'")[1]))
|
|
14
|
-
if line.strip().startswith("export ALIBABA"):
|
|
15
|
-
alibaba = json.loads(str(line.strip().split("'")[1]))
|
|
16
|
-
|
|
17
|
-
MANAGEMENT_SPACE: str = f"{settings.management_space}"
|
|
18
|
-
USERS_SUBPATH: str = "users"
|
|
19
|
-
DEMO_SPACE: str = "test"
|
|
20
|
-
DEMO_SUBPATH: str = "content"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
async def get_superman_cookie(client) -> str:
|
|
24
|
-
response = await client.post(
|
|
25
|
-
"/user/login",
|
|
26
|
-
json={"shortname": superman["shortname"], "password": superman["password"]},
|
|
27
|
-
)
|
|
28
|
-
print(f"\n {response.json() = } \n creds: {superman = } \n")
|
|
29
|
-
assert response.status_code == status.HTTP_200_OK
|
|
30
|
-
# client.cookies.set("auth_token", response.cookies["auth_token"])
|
|
31
|
-
return str(response.cookies["auth_token"])
|
|
32
|
-
|
|
33
|
-
async def set_superman_cookie(client):
|
|
34
|
-
response = await client.post(
|
|
35
|
-
"/user/login",
|
|
36
|
-
json={"shortname": superman["shortname"], "password": superman["password"]},
|
|
37
|
-
)
|
|
38
|
-
print(f"\n {response.json() = } \n creds: {superman = } \n")
|
|
39
|
-
assert response.status_code == status.HTTP_200_OK
|
|
40
|
-
client.cookies.set("auth_token", response.cookies["auth_token"])
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
async def set_alibaba_cookie(client):
|
|
44
|
-
response = await client.post(
|
|
45
|
-
"/user/login",
|
|
46
|
-
json={"shortname": alibaba["shortname"], "password": alibaba["password"]},
|
|
47
|
-
)
|
|
48
|
-
print(f"\n {response.json() = } \n creds: {alibaba = } \n")
|
|
49
|
-
assert response.status_code == status.HTTP_200_OK
|
|
50
|
-
client.cookies.set("auth_token", response.cookies["auth_token"])
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
async def init_test_db(client) -> None:
|
|
54
|
-
# Create the space
|
|
55
|
-
await client.post(
|
|
56
|
-
"managed/request",
|
|
57
|
-
json={
|
|
58
|
-
"space_name": DEMO_SPACE,
|
|
59
|
-
"request_type": RequestType.create,
|
|
60
|
-
"records": [
|
|
61
|
-
{
|
|
62
|
-
"resource_type": ResourceType.space,
|
|
63
|
-
"subpath": "/",
|
|
64
|
-
"shortname": DEMO_SPACE,
|
|
65
|
-
"attributes": {},
|
|
66
|
-
}
|
|
67
|
-
],
|
|
68
|
-
},
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
# Create the folder
|
|
72
|
-
await client.post(
|
|
73
|
-
"/managed/request",
|
|
74
|
-
json={
|
|
75
|
-
"space_name": DEMO_SPACE,
|
|
76
|
-
"request_type": RequestType.create,
|
|
77
|
-
"records": [
|
|
78
|
-
{
|
|
79
|
-
"resource_type": ResourceType.folder,
|
|
80
|
-
"subpath": "/",
|
|
81
|
-
"shortname": DEMO_SUBPATH,
|
|
82
|
-
"attributes": {},
|
|
83
|
-
}
|
|
84
|
-
],
|
|
85
|
-
},
|
|
86
|
-
)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
async def delete_space(client) -> None:
|
|
90
|
-
headers = {"Content-Type": "application/json"}
|
|
91
|
-
endpoint = "/managed/request"
|
|
92
|
-
request_data = {
|
|
93
|
-
"space_name": DEMO_SPACE,
|
|
94
|
-
"request_type": RequestType.delete,
|
|
95
|
-
"records": [
|
|
96
|
-
{
|
|
97
|
-
"resource_type": ResourceType.space,
|
|
98
|
-
"subpath": "/",
|
|
99
|
-
"shortname": DEMO_SPACE,
|
|
100
|
-
"attributes": {},
|
|
101
|
-
}
|
|
102
|
-
],
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
assert_code_and_status_success(
|
|
106
|
-
await client.post(endpoint, json=request_data, headers=headers)
|
|
107
|
-
)
|
|
108
|
-
check_not_found(
|
|
109
|
-
await client.get(f"/managed/entry/space/{DEMO_SPACE}/__root__/{DEMO_SPACE}")
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
def check_repeated_shortname(response):
|
|
114
|
-
json_response = response.json()
|
|
115
|
-
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
|
116
|
-
assert "failed" == json_response.get("status")
|
|
117
|
-
assert "request" == json_response.get("error", {}).get("type")
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
def check_not_found(response):
|
|
121
|
-
json_response = response.json()
|
|
122
|
-
assert response.status_code == status.HTTP_404_NOT_FOUND
|
|
123
|
-
assert "failed" == json_response.get("status")
|
|
124
|
-
assert "db" == json_response.get("error").get("type")
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
def check_unauthorized(response):
|
|
128
|
-
json_response = response.json()
|
|
129
|
-
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
|
130
|
-
assert "failed" == json_response.get("status")
|
|
131
|
-
assert "auth" == json_response.get("error", {}).get("type")
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
def assert_code_and_status_success(response):
|
|
135
|
-
if response.status_code != status.HTTP_200_OK:
|
|
136
|
-
print(
|
|
137
|
-
"\n\n\n\n\n========================= ERROR RESPONSE: =========================n:",
|
|
138
|
-
response.json(),
|
|
139
|
-
"\n\n\n\n\n",
|
|
140
|
-
)
|
|
141
|
-
json_response = response.json()
|
|
142
|
-
print(f"{json_response=}")
|
|
143
|
-
assert response.status_code == status.HTTP_200_OK
|
|
144
|
-
assert json_response.get("status") == "success"
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
def assert_bad_request(response):
|
|
148
|
-
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
|
149
|
-
assert response.json()["status"] == "failed"
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
async def assert_resource_created(
|
|
153
|
-
client,
|
|
154
|
-
query: Query,
|
|
155
|
-
res_shortname: str,
|
|
156
|
-
res_subpath: str,
|
|
157
|
-
res_attributes: dict | None = None,
|
|
158
|
-
res_attachments: dict[str, int] | None = None,
|
|
159
|
-
):
|
|
160
|
-
if not query.search:
|
|
161
|
-
query.search = ""
|
|
162
|
-
response = await client.post(
|
|
163
|
-
"/managed/query",
|
|
164
|
-
json=query.model_dump(exclude_none=True),
|
|
165
|
-
)
|
|
166
|
-
assert_code_and_status_success(response)
|
|
167
|
-
json_response = response.json()
|
|
168
|
-
assert json_response["status"] == "success"
|
|
169
|
-
assert json_response["attributes"]["returned"] == query.limit
|
|
170
|
-
assert json_response["records"][0]["shortname"] == res_shortname
|
|
171
|
-
assert json_response["records"][0]["subpath"] in [res_subpath, f"/{res_subpath}"]
|
|
172
|
-
if res_attributes:
|
|
173
|
-
if "is_active" not in res_attributes:
|
|
174
|
-
res_attributes["is_active"] = False
|
|
175
|
-
if "tags" not in res_attributes:
|
|
176
|
-
res_attributes["tags"] = []
|
|
177
|
-
res_attributes["owner_shortname"] = "dmart"
|
|
178
|
-
|
|
179
|
-
json_response["records"][0]["attributes"].pop("created_at", None)
|
|
180
|
-
json_response["records"][0]["attributes"].pop("updated_at", None)
|
|
181
|
-
assert (
|
|
182
|
-
json_response["records"][0]["attributes"]["payload"]["body"]
|
|
183
|
-
== res_attributes["payload"]["body"]
|
|
184
|
-
)
|
|
185
|
-
|
|
186
|
-
# Assert correct attachments number for each attachment type returned
|
|
187
|
-
if res_attachments:
|
|
188
|
-
for attachment_key, attachments in json_response["records"][0][
|
|
189
|
-
"attachments"
|
|
190
|
-
].items():
|
|
191
|
-
if attachment_key in res_attachments:
|
|
192
|
-
assert len(attachments) == res_attachments[attachment_key]
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
async def assert_resource_deleted(client, space: str, subpath: str, shortname: str):
|
|
196
|
-
query = Query(
|
|
197
|
-
type=QueryType.search,
|
|
198
|
-
space_name=space,
|
|
199
|
-
subpath=subpath,
|
|
200
|
-
search="",
|
|
201
|
-
filter_shortnames=[shortname],
|
|
202
|
-
retrieve_json_payload=True,
|
|
203
|
-
limit=1,
|
|
204
|
-
)
|
|
205
|
-
response = await client.post("/managed/query", json=query.model_dump(exclude_none=True))
|
|
206
|
-
assert_code_and_status_success(response)
|
|
207
|
-
assert response.json()["status"] == "success"
|
|
208
|
-
assert response.json()["attributes"]["returned"] == 0
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
async def upload_resource_with_payload(
|
|
212
|
-
client,
|
|
213
|
-
space_name,
|
|
214
|
-
record_path: str,
|
|
215
|
-
payload_path: str,
|
|
216
|
-
payload_type,
|
|
217
|
-
attachment=False,
|
|
218
|
-
is_fail=False,
|
|
219
|
-
):
|
|
220
|
-
with open(record_path, "rb") as request_file, open(
|
|
221
|
-
payload_path, "rb"
|
|
222
|
-
) as media_file:
|
|
223
|
-
files = {
|
|
224
|
-
"request_record": ("record.json", request_file, "application/json"),
|
|
225
|
-
"payload_file": (media_file.name.split("/")[-1], media_file, payload_type),
|
|
226
|
-
}
|
|
227
|
-
response = await client.post(
|
|
228
|
-
"managed/resource_with_payload",
|
|
229
|
-
headers={},
|
|
230
|
-
data={"space_name": space_name},
|
|
231
|
-
files=files,
|
|
232
|
-
)
|
|
233
|
-
|
|
234
|
-
if is_fail:
|
|
235
|
-
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
|
236
|
-
else:
|
|
237
|
-
assert_code_and_status_success(response)
|
|
238
|
-
|
|
239
|
-
if attachment:
|
|
240
|
-
with open(record_path, 'r') as record_file:
|
|
241
|
-
record_data = json.loads(record_file.read())
|
|
242
|
-
subpath_parts = record_data["subpath"].split('/')
|
|
243
|
-
attach_parent_subpath, attach_parent_shortname = "/".join(subpath_parts[:-1]), subpath_parts[-1]
|
|
244
|
-
await assert_resource_created(
|
|
245
|
-
client,
|
|
246
|
-
query=Query(
|
|
247
|
-
type=QueryType.search,
|
|
248
|
-
space_name=space_name,
|
|
249
|
-
subpath=attach_parent_subpath,
|
|
250
|
-
filter_shortnames=[attach_parent_shortname],
|
|
251
|
-
retrieve_json_payload=True,
|
|
252
|
-
retrieve_attachments=True,
|
|
253
|
-
limit=1,
|
|
254
|
-
),
|
|
255
|
-
res_shortname=attach_parent_shortname,
|
|
256
|
-
res_subpath=attach_parent_subpath,
|
|
257
|
-
res_attachments={"media": 1},
|
|
258
|
-
)
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
async def delete_resource(client, resource_type: str, del_subpath: str, del_shortname: str):
|
|
262
|
-
headers = {"Content-Type": "application/json"}
|
|
263
|
-
endpoint = "/managed/request"
|
|
264
|
-
request_data = {
|
|
265
|
-
"space_name": DEMO_SPACE,
|
|
266
|
-
"request_type": RequestType.delete,
|
|
267
|
-
"records": [
|
|
268
|
-
{
|
|
269
|
-
"resource_type": resource_type,
|
|
270
|
-
"subpath": del_subpath,
|
|
271
|
-
"shortname": del_shortname,
|
|
272
|
-
"attributes": {},
|
|
273
|
-
}
|
|
274
|
-
],
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
response = await client.post(endpoint, json=request_data, headers=headers)
|
|
278
|
-
assert_code_and_status_success(response)
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
async def retrieve_content_folder(client):
|
|
282
|
-
response = await client.get(f"managed/entry/folder/{DEMO_SPACE}/{settings.root_subpath_mw}/{DEMO_SUBPATH}")
|
|
283
|
-
|
|
284
|
-
assert response.status_code == status.HTTP_200_OK
|
|
285
|
-
|
|
286
|
-
await assert_resource_created(
|
|
287
|
-
client,
|
|
288
|
-
query=Query(
|
|
289
|
-
type=QueryType.search,
|
|
290
|
-
space_name=DEMO_SPACE,
|
|
291
|
-
subpath="/",
|
|
292
|
-
filter_shortnames=[DEMO_SUBPATH],
|
|
293
|
-
filter_types=[ResourceType.folder],
|
|
294
|
-
retrieve_json_payload=True,
|
|
295
|
-
limit=1,
|
|
296
|
-
),
|
|
297
|
-
res_shortname=DEMO_SUBPATH,
|
|
298
|
-
res_subpath="/",
|
|
299
|
-
res_attributes={},
|
|
300
|
-
)
|
pytests/get_settings_test.py
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# test_script.py
|
|
2
|
-
import subprocess
|
|
3
|
-
import pytest
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
@pytest.mark.run(order=4)
|
|
7
|
-
def test_script_execution():
|
|
8
|
-
result = subprocess.run(
|
|
9
|
-
['python3', 'get_settings.py'],
|
|
10
|
-
capture_output=True,
|
|
11
|
-
text=True,
|
|
12
|
-
check=True
|
|
13
|
-
)
|
|
14
|
-
assert result.returncode == 0
|