hardpy 0.12.1__py3-none-any.whl → 0.14.0__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.
- hardpy/cli/cli.py +18 -11
- hardpy/common/config.py +5 -0
- hardpy/common/stand_cloud/connector.py +142 -135
- hardpy/common/stand_cloud/oauth2.py +88 -0
- hardpy/common/stand_cloud/registration.py +50 -211
- hardpy/common/stand_cloud/token_manager.py +119 -0
- hardpy/common/stand_cloud/utils.py +33 -0
- hardpy/hardpy_panel/frontend/dist/assets/{allPaths-B26356fZ.js → allPaths-CV5wjLMB.js} +1 -1
- hardpy/hardpy_panel/frontend/dist/assets/{allPathsLoader-0BeGWuiy.js → allPathsLoader-JIzW_pSb.js} +2 -2
- hardpy/hardpy_panel/frontend/dist/assets/browser-ponyfill-CccdstaD.js +2 -0
- hardpy/hardpy_panel/frontend/dist/assets/index-6RIgWzcZ.js +790 -0
- hardpy/hardpy_panel/frontend/dist/assets/{splitPathsBySizeLoader-BEs5IL5-.js → splitPathsBySizeLoader-DkZadBcn.js} +1 -1
- hardpy/hardpy_panel/frontend/dist/index.html +1 -1
- hardpy/hardpy_panel/frontend/dist/locales/de/translation.json +60 -0
- hardpy/hardpy_panel/frontend/dist/locales/en/translation.json +60 -0
- hardpy/hardpy_panel/frontend/dist/locales/es/translation.json +60 -0
- hardpy/hardpy_panel/frontend/dist/locales/fr/translation.json +60 -0
- hardpy/hardpy_panel/frontend/dist/locales/ja/translation.json +60 -0
- hardpy/hardpy_panel/frontend/dist/locales/ru/translation.json +60 -0
- hardpy/hardpy_panel/frontend/dist/locales/zh/translation.json +60 -0
- hardpy/pytest_hardpy/plugin.py +47 -28
- hardpy/pytest_hardpy/pytest_call.py +7 -3
- hardpy/pytest_hardpy/reporter/base.py +8 -0
- hardpy/pytest_hardpy/reporter/hook_reporter.py +25 -8
- hardpy/pytest_hardpy/result/report_loader/stand_cloud_loader.py +8 -2
- {hardpy-0.12.1.dist-info → hardpy-0.14.0.dist-info}/METADATA +2 -1
- {hardpy-0.12.1.dist-info → hardpy-0.14.0.dist-info}/RECORD +30 -21
- hardpy/common/stand_cloud/oauth_callback.py +0 -95
- hardpy/common/stand_cloud/token_storage.py +0 -27
- hardpy/hardpy_panel/frontend/dist/assets/index-Bl_IX0Up.js +0 -790
- {hardpy-0.12.1.dist-info → hardpy-0.14.0.dist-info}/WHEEL +0 -0
- {hardpy-0.12.1.dist-info → hardpy-0.14.0.dist-info}/entry_points.txt +0 -0
- {hardpy-0.12.1.dist-info → hardpy-0.14.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as o,a as _,b as i,p as c,I as u}from"./index-
|
|
1
|
+
import{_ as o,a as _,b as i,p as c,I as u}from"./index-6RIgWzcZ.js";var p=function(n,s){return o(void 0,void 0,void 0,function(){var a,r;return _(this,function(e){switch(e.label){case 0:return a=c(n),s!==u.STANDARD?[3,2]:[4,i(()=>import("./index-xb4M2ucX.js").then(t=>t.I),[])];case 1:return r=e.sent(),[3,4];case 2:return[4,i(()=>import("./index-BMEat_ws.js").then(t=>t.I),[])];case 3:r=e.sent(),e.label=4;case 4:return[2,r[a]]}})})};export{p as splitPathsBySizeLoader};
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
Learn how to configure a non-root public URL by running `npm run build`.
|
|
26
26
|
-->
|
|
27
27
|
<title>HardPy Operator Panel</title>
|
|
28
|
-
<script type="module" crossorigin src="/assets/index-
|
|
28
|
+
<script type="module" crossorigin src="/assets/index-6RIgWzcZ.js"></script>
|
|
29
29
|
<link rel="stylesheet" crossorigin href="/assets/index-BwCQzehg.css">
|
|
30
30
|
</head>
|
|
31
31
|
<body>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"app": {
|
|
3
|
+
"title": "HardPy Bedienfeld",
|
|
4
|
+
"lastLaunch": "Letzter Start:",
|
|
5
|
+
"duration": "Dauer",
|
|
6
|
+
"seconds": "s",
|
|
7
|
+
"soundOn": "Ton einschalten",
|
|
8
|
+
"soundOff": "Ton ausschalten",
|
|
9
|
+
"debugOn": "Debug-Modus einschalten",
|
|
10
|
+
"debugOff": "Debug-Modus ausschalten",
|
|
11
|
+
"connection": "Verbindung wird hergestellt... 🧐🔎",
|
|
12
|
+
"dbError": "Datenbankverbindungsfehler. 🙅🏽♀️🚫",
|
|
13
|
+
"noEntries": "Keine Einträge in der Datenbank 🙅🏽♀️🚫",
|
|
14
|
+
"status": {
|
|
15
|
+
"ready": "bereit",
|
|
16
|
+
"run": "läuft",
|
|
17
|
+
"passed": "bestanden",
|
|
18
|
+
"failed": "fehlgeschlagen",
|
|
19
|
+
"stopped": "gestoppt",
|
|
20
|
+
"unknown": "unbekannt"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"button": {
|
|
24
|
+
"start": "Starten",
|
|
25
|
+
"stop": "Stoppen",
|
|
26
|
+
"confirm": "Bestätigen"
|
|
27
|
+
},
|
|
28
|
+
"error": {
|
|
29
|
+
"dbConnectionTitle": "Datenbankverbindungsfehler",
|
|
30
|
+
"dbConnectionMessage": "Verbindung zur Datenbank konnte nicht hergestellt werden"
|
|
31
|
+
},
|
|
32
|
+
"operatorDialog": {
|
|
33
|
+
"defaultTitle": "Nachricht",
|
|
34
|
+
"imageAlt": "Operator-Nachrichtenbild",
|
|
35
|
+
"htmlCodeTitle": "HTML-Code",
|
|
36
|
+
"htmlLinkTitle": "HTML-Link",
|
|
37
|
+
"enterAnswer": "Antwort eingeben",
|
|
38
|
+
"fieldNotEmpty": "Das Feld darf nicht leer sein",
|
|
39
|
+
"notificationTitle": "Benachrichtigung",
|
|
40
|
+
"notificationDesc": "Das Fenster wurde geschlossen. Tests gestoppt.",
|
|
41
|
+
"numericInputError": "Bitte geben Sie eine Zahl ein",
|
|
42
|
+
"radioButtonError": "Bitte wählen Sie eine Option",
|
|
43
|
+
"checkboxError": "Bitte wählen Sie mindestens eine Option"
|
|
44
|
+
},
|
|
45
|
+
"suiteList": {
|
|
46
|
+
"loadingTests": "Tests werden geladen... 🤔",
|
|
47
|
+
"refreshHint": "Versuchen Sie, die Seite zu aktualisieren.",
|
|
48
|
+
"standName": "Standortname",
|
|
49
|
+
"status": "Status",
|
|
50
|
+
"startTime": "Startzeit",
|
|
51
|
+
"finishTime": "Endzeit",
|
|
52
|
+
"alert": "Warnung"
|
|
53
|
+
},
|
|
54
|
+
"testSuite": {
|
|
55
|
+
"nameColumn": "Name",
|
|
56
|
+
"dataColumn": "Daten",
|
|
57
|
+
"loading": "Wird geladen...",
|
|
58
|
+
"stubName": "Testgruppe"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"app": {
|
|
3
|
+
"title": "HardPy Operator Panel",
|
|
4
|
+
"lastLaunch": "Last launch:",
|
|
5
|
+
"duration": "Duration",
|
|
6
|
+
"seconds": "s",
|
|
7
|
+
"soundOn": "Turn on the sound",
|
|
8
|
+
"soundOff": "Turn off the sound",
|
|
9
|
+
"debugOn": "Turn on the debug mode",
|
|
10
|
+
"debugOff": "Turn off the debug mode",
|
|
11
|
+
"connection": "Establishing a connection... 🧐🔎",
|
|
12
|
+
"dbError": "Database connection error. 🙅🏽♀️🚫",
|
|
13
|
+
"noEntries": "No entries in the database 🙅🏽♀️🚫",
|
|
14
|
+
"status": {
|
|
15
|
+
"ready": "ready",
|
|
16
|
+
"run": "run",
|
|
17
|
+
"passed": "pass",
|
|
18
|
+
"failed": "fail",
|
|
19
|
+
"stopped": "stopped",
|
|
20
|
+
"unknown": "unknown"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"button": {
|
|
24
|
+
"start": "Start",
|
|
25
|
+
"stop": "Stop",
|
|
26
|
+
"confirm": "Confirm"
|
|
27
|
+
},
|
|
28
|
+
"error": {
|
|
29
|
+
"dbConnectionTitle": "Database Connection Error",
|
|
30
|
+
"dbConnectionMessage": "Failed to establish connection with the database"
|
|
31
|
+
},
|
|
32
|
+
"operatorDialog": {
|
|
33
|
+
"defaultTitle": "Message",
|
|
34
|
+
"imageAlt": "Operator message image",
|
|
35
|
+
"htmlCodeTitle": "HTML Code",
|
|
36
|
+
"htmlLinkTitle": "HTML Link",
|
|
37
|
+
"enterAnswer": "Enter answer",
|
|
38
|
+
"fieldNotEmpty": "The field must not be empty",
|
|
39
|
+
"notificationTitle": "Notification",
|
|
40
|
+
"notificationDesc": "The window was closed. Tests stopped.",
|
|
41
|
+
"numericInputError": "Please enter a number",
|
|
42
|
+
"radioButtonError": "Please select one option",
|
|
43
|
+
"checkboxError": "Please select at least one option"
|
|
44
|
+
},
|
|
45
|
+
"suiteList": {
|
|
46
|
+
"loadingTests": "Loading tests... 🤔",
|
|
47
|
+
"refreshHint": "Try refreshing the page.",
|
|
48
|
+
"standName": "Stand name",
|
|
49
|
+
"status": "Status",
|
|
50
|
+
"startTime": "Start time",
|
|
51
|
+
"finishTime": "Finish time",
|
|
52
|
+
"alert": "Alert"
|
|
53
|
+
},
|
|
54
|
+
"testSuite": {
|
|
55
|
+
"nameColumn": "Name",
|
|
56
|
+
"dataColumn": "Data",
|
|
57
|
+
"loading": "Loading...",
|
|
58
|
+
"stubName": "Test Suite"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"app": {
|
|
3
|
+
"title": "Panel de operador HardPy",
|
|
4
|
+
"lastLaunch": "Última lanzamiento:",
|
|
5
|
+
"duration": "Duración",
|
|
6
|
+
"seconds": "s",
|
|
7
|
+
"soundOn": "Activar sonido",
|
|
8
|
+
"soundOff": "Desactivar sonido",
|
|
9
|
+
"debugOn": "Activar modo de depuración",
|
|
10
|
+
"debugOff": "Desactivar modo de depuración",
|
|
11
|
+
"connection": "Estableciendo conexión... 🧐🔎",
|
|
12
|
+
"dbError": "Error de conexión a la base de datos. 🙅🏽♀️🚫",
|
|
13
|
+
"noEntries": "No hay entradas en la base de datos 🙅🏽♀️🚫",
|
|
14
|
+
"status": {
|
|
15
|
+
"ready": "listo",
|
|
16
|
+
"run": "ejecutando",
|
|
17
|
+
"passed": "aprobado",
|
|
18
|
+
"failed": "fallado",
|
|
19
|
+
"stopped": "detenido",
|
|
20
|
+
"unknown": "desconocido"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"button": {
|
|
24
|
+
"start": "Iniciar",
|
|
25
|
+
"stop": "Detener",
|
|
26
|
+
"confirm": "Confirmar"
|
|
27
|
+
},
|
|
28
|
+
"error": {
|
|
29
|
+
"dbConnectionTitle": "Error de conexión a la base de datos",
|
|
30
|
+
"dbConnectionMessage": "No se pudo establecer la conexión con la base de datos"
|
|
31
|
+
},
|
|
32
|
+
"operatorDialog": {
|
|
33
|
+
"defaultTitle": "Mensaje",
|
|
34
|
+
"imageAlt": "Imagen del mensaje del operador",
|
|
35
|
+
"htmlCodeTitle": "Código HTML",
|
|
36
|
+
"htmlLinkTitle": "Enlace HTML",
|
|
37
|
+
"enterAnswer": "Ingrese respuesta",
|
|
38
|
+
"fieldNotEmpty": "El campo no debe estar vacío",
|
|
39
|
+
"notificationTitle": "Notificación",
|
|
40
|
+
"notificationDesc": "La ventana fue cerrada. Pruebas detenidas.",
|
|
41
|
+
"numericInputError": "Por favor ingrese un número",
|
|
42
|
+
"radioButtonError": "Por favor seleccione una opción",
|
|
43
|
+
"checkboxError": "Por favor seleccione al menos una opción"
|
|
44
|
+
},
|
|
45
|
+
"suiteList": {
|
|
46
|
+
"loadingTests": "Cargando pruebas... 🤔",
|
|
47
|
+
"refreshHint": "Intente actualizar la página.",
|
|
48
|
+
"standName": "Nombre del puesto",
|
|
49
|
+
"status": "Estado",
|
|
50
|
+
"startTime": "Hora de inicio",
|
|
51
|
+
"finishTime": "Hora de finalización",
|
|
52
|
+
"alert": "Alerta"
|
|
53
|
+
},
|
|
54
|
+
"testSuite": {
|
|
55
|
+
"nameColumn": "Nombre",
|
|
56
|
+
"dataColumn": "Datos",
|
|
57
|
+
"loading": "Cargando...",
|
|
58
|
+
"stubName": "Conjunto de pruebas"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"app": {
|
|
3
|
+
"title": "Panneau opérateur HardPy",
|
|
4
|
+
"lastLaunch": "Dernière lancement:",
|
|
5
|
+
"duration": "Durée",
|
|
6
|
+
"seconds": "s",
|
|
7
|
+
"soundOn": "Activer le son",
|
|
8
|
+
"soundOff": "Désactiver le son",
|
|
9
|
+
"debugOn": "Activer le mode débogage",
|
|
10
|
+
"debugOff": "Désactiver le mode débogage",
|
|
11
|
+
"connection": "Établissement de la connexion... 🧐🔎",
|
|
12
|
+
"dbError": "Erreur de connexion à la base de données. 🙅🏽♀️🚫",
|
|
13
|
+
"noEntries": "Aucune entrée dans la base de données 🙅🏽♀️🚫",
|
|
14
|
+
"status": {
|
|
15
|
+
"ready": "prêt",
|
|
16
|
+
"run": "en cours",
|
|
17
|
+
"passed": "réussi",
|
|
18
|
+
"failed": "échoué",
|
|
19
|
+
"stopped": "arrêté",
|
|
20
|
+
"unknown": "inconnu"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"button": {
|
|
24
|
+
"start": "Commencer",
|
|
25
|
+
"stop": "Arrêter",
|
|
26
|
+
"confirm": "Confirmer"
|
|
27
|
+
},
|
|
28
|
+
"error": {
|
|
29
|
+
"dbConnectionTitle": "Erreur de connexion à la base de données",
|
|
30
|
+
"dbConnectionMessage": "Échec de la connexion à la base de données"
|
|
31
|
+
},
|
|
32
|
+
"operatorDialog": {
|
|
33
|
+
"defaultTitle": "Message",
|
|
34
|
+
"imageAlt": "Image du message de l'opérateur",
|
|
35
|
+
"htmlCodeTitle": "Code HTML",
|
|
36
|
+
"htmlLinkTitle": "Lien HTML",
|
|
37
|
+
"enterAnswer": "Entrez la réponse",
|
|
38
|
+
"fieldNotEmpty": "Le champ ne doit pas être vide",
|
|
39
|
+
"notificationTitle": "Notification",
|
|
40
|
+
"notificationDesc": "La fenêtre a été fermée. Tests arrêtés.",
|
|
41
|
+
"numericInputError": "Veuillez entrer un nombre",
|
|
42
|
+
"radioButtonError": "Veuillez sélectionner une option",
|
|
43
|
+
"checkboxError": "Veuillez sélectionner au moins une option"
|
|
44
|
+
},
|
|
45
|
+
"suiteList": {
|
|
46
|
+
"loadingTests": "Chargement des tests... 🤔",
|
|
47
|
+
"refreshHint": "Essayez de rafraîchir la page.",
|
|
48
|
+
"standName": "Nom du stand",
|
|
49
|
+
"status": "Statut",
|
|
50
|
+
"startTime": "Heure de début",
|
|
51
|
+
"finishTime": "Heure de fin",
|
|
52
|
+
"alert": "Alerte"
|
|
53
|
+
},
|
|
54
|
+
"testSuite": {
|
|
55
|
+
"nameColumn": "Nom",
|
|
56
|
+
"dataColumn": "Données",
|
|
57
|
+
"loading": "Chargement...",
|
|
58
|
+
"stubName": "Suite de tests"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"app": {
|
|
3
|
+
"title": "HardPy オペレーターパネル",
|
|
4
|
+
"lastLaunch": "最終起動:",
|
|
5
|
+
"duration": "期間",
|
|
6
|
+
"seconds": "秒",
|
|
7
|
+
"soundOn": "音をオンにする",
|
|
8
|
+
"soundOff": "音をオフにする",
|
|
9
|
+
"debugOn": "デバッグモードをオンにする",
|
|
10
|
+
"debugOff": "デバッグモードをオフにする",
|
|
11
|
+
"connection": "接続を確立しています... 🧐🔎",
|
|
12
|
+
"dbError": "データベース接続エラー. 🙅🏽♀️🚫",
|
|
13
|
+
"noEntries": "データベースにエントリがありません 🙅🏽♀️🚫",
|
|
14
|
+
"status": {
|
|
15
|
+
"ready": "準備完了",
|
|
16
|
+
"run": "実行中",
|
|
17
|
+
"passed": "合格",
|
|
18
|
+
"failed": "不合格",
|
|
19
|
+
"stopped": "停止",
|
|
20
|
+
"unknown": "不明"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"button": {
|
|
24
|
+
"start": "開始",
|
|
25
|
+
"stop": "停止",
|
|
26
|
+
"confirm": "確認"
|
|
27
|
+
},
|
|
28
|
+
"error": {
|
|
29
|
+
"dbConnectionTitle": "データベース接続エラー",
|
|
30
|
+
"dbConnectionMessage": "データベースへの接続に失敗しました"
|
|
31
|
+
},
|
|
32
|
+
"operatorDialog": {
|
|
33
|
+
"defaultTitle": "メッセージ",
|
|
34
|
+
"imageAlt": "オペレーターメッセージ画像",
|
|
35
|
+
"htmlCodeTitle": "HTMLコード",
|
|
36
|
+
"htmlLinkTitle": "HTMLリンク",
|
|
37
|
+
"enterAnswer": "回答を入力",
|
|
38
|
+
"fieldNotEmpty": "フィールドは空にできません",
|
|
39
|
+
"notificationTitle": "通知",
|
|
40
|
+
"notificationDesc": "ウィンドウが閉じられました。テストを停止しました。",
|
|
41
|
+
"numericInputError": "数字を入力してください",
|
|
42
|
+
"radioButtonError": "いずれかのオプションを選択してください",
|
|
43
|
+
"checkboxError": "少なくとも1つのオプションを選択してください"
|
|
44
|
+
},
|
|
45
|
+
"suiteList": {
|
|
46
|
+
"loadingTests": "テストを読み込み中... 🤔",
|
|
47
|
+
"refreshHint": "ページを更新してみてください。",
|
|
48
|
+
"standName": "スタンド名",
|
|
49
|
+
"status": "ステータス",
|
|
50
|
+
"startTime": "開始時間",
|
|
51
|
+
"finishTime": "終了時間",
|
|
52
|
+
"alert": "警告"
|
|
53
|
+
},
|
|
54
|
+
"testSuite": {
|
|
55
|
+
"nameColumn": "名前",
|
|
56
|
+
"dataColumn": "データ",
|
|
57
|
+
"loading": "読み込み中...",
|
|
58
|
+
"stubName": "テストスイート"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"app": {
|
|
3
|
+
"title": "Панель оператора HardPy",
|
|
4
|
+
"lastLaunch": "Последний запуск:",
|
|
5
|
+
"duration": "Длительность",
|
|
6
|
+
"seconds": "с",
|
|
7
|
+
"soundOn": "Включить звук",
|
|
8
|
+
"soundOff": "Выключить звук",
|
|
9
|
+
"debugOn": "Включить режим отладки",
|
|
10
|
+
"debugOff": "Выключить режим отладки",
|
|
11
|
+
"connection": "Установка соединения... 🧐🔎",
|
|
12
|
+
"dbError": "Ошибка подключения к базе данных. 🙅🏽♀️🚫",
|
|
13
|
+
"noEntries": "Нет записей в базе данных 🙅🏽♀️🚫",
|
|
14
|
+
"status": {
|
|
15
|
+
"ready": "готов",
|
|
16
|
+
"run": "выполнение",
|
|
17
|
+
"passed": "успех",
|
|
18
|
+
"failed": "провалено",
|
|
19
|
+
"stopped": "остановлено",
|
|
20
|
+
"unknown": "неизвестно"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"button": {
|
|
24
|
+
"start": "Старт",
|
|
25
|
+
"stop": "Стоп",
|
|
26
|
+
"confirm": "Подтвердить"
|
|
27
|
+
},
|
|
28
|
+
"error": {
|
|
29
|
+
"dbConnectionTitle": "Ошибка подключения к базе данных",
|
|
30
|
+
"dbConnectionMessage": "Не удалось установить соединение с базой данных"
|
|
31
|
+
},
|
|
32
|
+
"operatorDialog": {
|
|
33
|
+
"defaultTitle": "Сообщение",
|
|
34
|
+
"imageAlt": "Изображение в сообщении оператора",
|
|
35
|
+
"htmlCodeTitle": "HTML код",
|
|
36
|
+
"htmlLinkTitle": "HTML ссылка",
|
|
37
|
+
"enterAnswer": "Введите ответ",
|
|
38
|
+
"fieldNotEmpty": "Поле не должно быть пустым",
|
|
39
|
+
"notificationTitle": "Уведомление",
|
|
40
|
+
"notificationDesc": "Окно было закрыто. Тесты остановлены.",
|
|
41
|
+
"numericInputError": "Пожалуйста, введите число",
|
|
42
|
+
"radioButtonError": "Пожалуйста, выберите один вариант",
|
|
43
|
+
"checkboxError": "Пожалуйста, выберите хотя бы один вариант"
|
|
44
|
+
},
|
|
45
|
+
"suiteList": {
|
|
46
|
+
"loadingTests": "Загрузка тестов... 🤔",
|
|
47
|
+
"refreshHint": "Попробуйте обновить страницу.",
|
|
48
|
+
"standName": "Название стенда",
|
|
49
|
+
"status": "Статус",
|
|
50
|
+
"startTime": "Время начала",
|
|
51
|
+
"finishTime": "Время завершения",
|
|
52
|
+
"alert": "Предупреждение"
|
|
53
|
+
},
|
|
54
|
+
"testSuite": {
|
|
55
|
+
"nameColumn": "Название",
|
|
56
|
+
"dataColumn": "Данные",
|
|
57
|
+
"loading": "Загрузка...",
|
|
58
|
+
"stubName": "Тестовый набор"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"app": {
|
|
3
|
+
"title": "HardPy 操作面板",
|
|
4
|
+
"lastLaunch": "上次启动:",
|
|
5
|
+
"duration": "持续时间",
|
|
6
|
+
"seconds": "秒",
|
|
7
|
+
"soundOn": "开启声音",
|
|
8
|
+
"soundOff": "关闭声音",
|
|
9
|
+
"debugOn": "开启调试模式",
|
|
10
|
+
"debugOff": "关闭调试模式",
|
|
11
|
+
"connection": "正在建立连接... 🧐🔎",
|
|
12
|
+
"dbError": "数据库连接错误. 🙅🏽♀️🚫",
|
|
13
|
+
"noEntries": "数据库中没有条目 🙅🏽♀️🚫",
|
|
14
|
+
"status": {
|
|
15
|
+
"ready": "就绪",
|
|
16
|
+
"run": "运行中",
|
|
17
|
+
"passed": "通过",
|
|
18
|
+
"failed": "失败",
|
|
19
|
+
"stopped": "已停止",
|
|
20
|
+
"unknown": "未知"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"button": {
|
|
24
|
+
"start": "开始",
|
|
25
|
+
"stop": "停止",
|
|
26
|
+
"confirm": "确认"
|
|
27
|
+
},
|
|
28
|
+
"error": {
|
|
29
|
+
"dbConnectionTitle": "数据库连接错误",
|
|
30
|
+
"dbConnectionMessage": "无法建立数据库连接"
|
|
31
|
+
},
|
|
32
|
+
"operatorDialog": {
|
|
33
|
+
"defaultTitle": "消息",
|
|
34
|
+
"imageAlt": "操作员消息图片",
|
|
35
|
+
"htmlCodeTitle": "HTML代码",
|
|
36
|
+
"htmlLinkTitle": "HTML链接",
|
|
37
|
+
"enterAnswer": "输入答案",
|
|
38
|
+
"fieldNotEmpty": "字段不能为空",
|
|
39
|
+
"notificationTitle": "通知",
|
|
40
|
+
"notificationDesc": "窗口已关闭。测试已停止。",
|
|
41
|
+
"numericInputError": "请输入数字",
|
|
42
|
+
"radioButtonError": "请选择一个选项",
|
|
43
|
+
"checkboxError": "请至少选择一个选项"
|
|
44
|
+
},
|
|
45
|
+
"suiteList": {
|
|
46
|
+
"loadingTests": "正在加载测试... 🤔",
|
|
47
|
+
"refreshHint": "尝试刷新页面。",
|
|
48
|
+
"standName": "测试台名称",
|
|
49
|
+
"status": "状态",
|
|
50
|
+
"startTime": "开始时间",
|
|
51
|
+
"finishTime": "完成时间",
|
|
52
|
+
"alert": "警报"
|
|
53
|
+
},
|
|
54
|
+
"testSuite": {
|
|
55
|
+
"nameColumn": "名称",
|
|
56
|
+
"dataColumn": "数据",
|
|
57
|
+
"loading": "加载中...",
|
|
58
|
+
"stubName": "测试套件"
|
|
59
|
+
}
|
|
60
|
+
}
|
hardpy/pytest_hardpy/plugin.py
CHANGED
|
@@ -175,6 +175,8 @@ class HardpyPlugin:
|
|
|
175
175
|
if "--collect-only" in session.config.invocation_params.args:
|
|
176
176
|
return
|
|
177
177
|
status = self._get_run_status(exitstatus)
|
|
178
|
+
if status == TestStatus.STOPPED:
|
|
179
|
+
self._stop_tests()
|
|
178
180
|
self._reporter.finish(status)
|
|
179
181
|
self._reporter.update_db_by_doc()
|
|
180
182
|
self._reporter.compact_all()
|
|
@@ -237,7 +239,8 @@ class HardpyPlugin:
|
|
|
237
239
|
|
|
238
240
|
con_data = ConnectionData()
|
|
239
241
|
|
|
240
|
-
|
|
242
|
+
# running tests depends on a connection to StandCloud
|
|
243
|
+
if con_data.sc_connection_only:
|
|
241
244
|
try:
|
|
242
245
|
sc_connector = StandCloudConnector(addr=con_data.sc_address)
|
|
243
246
|
except StandCloudError as exc:
|
|
@@ -407,45 +410,61 @@ class HardpyPlugin:
|
|
|
407
410
|
case ExitCode.TESTS_FAILED:
|
|
408
411
|
return TestStatus.FAILED
|
|
409
412
|
case ExitCode.INTERRUPTED:
|
|
410
|
-
self._stop_tests()
|
|
411
413
|
return TestStatus.STOPPED
|
|
412
414
|
case _:
|
|
413
415
|
return TestStatus.FAILED
|
|
414
416
|
|
|
415
417
|
def _stop_tests(self) -> None:
|
|
416
|
-
"""Update module and case statuses
|
|
418
|
+
"""Update module and case statuses to stopped and skipped."""
|
|
419
|
+
is_module_stopped = False
|
|
420
|
+
is_case_stopped = False
|
|
421
|
+
valid_statuses = {TestStatus.PASSED, TestStatus.FAILED, TestStatus.SKIPPED}
|
|
417
422
|
for module_id, module_data in self._results.items():
|
|
418
|
-
module_status =
|
|
419
|
-
|
|
420
|
-
# skip not ready and running modules
|
|
421
|
-
if module_status not in {TestStatus.READY, TestStatus.RUN}:
|
|
423
|
+
module_status = self._reporter.get_module_status(module_id)
|
|
424
|
+
if module_status in valid_statuses:
|
|
422
425
|
continue
|
|
423
426
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
self._reporter.set_module_stop_time(module_id)
|
|
429
|
-
|
|
430
|
-
# update case statuses
|
|
431
|
-
for module_key, module_value in module_data.items():
|
|
432
|
-
# module status is not a case_id
|
|
433
|
-
if module_key == "module_status":
|
|
427
|
+
is_module_stopped = self._stop_module(module_id, is_module_stopped)
|
|
428
|
+
for module_data_key in module_data:
|
|
429
|
+
# skip module status
|
|
430
|
+
if module_data_key == "module_status":
|
|
434
431
|
continue
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
module_id,
|
|
441
|
-
case_id,
|
|
442
|
-
TestStatus.STOPPED,
|
|
443
|
-
)
|
|
444
|
-
if self._reporter.get_case_start_time(module_id, case_id):
|
|
445
|
-
self._reporter.set_case_stop_time(module_id, case_id)
|
|
432
|
+
case_id = module_data_key
|
|
433
|
+
case_status = self._reporter.get_case_status(module_id, case_id)
|
|
434
|
+
if case_status in valid_statuses:
|
|
435
|
+
continue
|
|
436
|
+
is_case_stopped = self._stop_case(module_id, case_id, is_case_stopped)
|
|
446
437
|
|
|
447
438
|
self._reporter.update_db_by_doc()
|
|
448
439
|
|
|
440
|
+
def _stop_module(self, module_id: str, is_module_stopped: bool) -> bool:
|
|
441
|
+
# stopped status is set only once other statuses are skipped
|
|
442
|
+
if is_module_stopped is False:
|
|
443
|
+
module_status = TestStatus.STOPPED
|
|
444
|
+
is_module_stopped = True
|
|
445
|
+
if not self._reporter.get_module_start_time(module_id):
|
|
446
|
+
self._reporter.set_module_start_time(module_id)
|
|
447
|
+
self._reporter.set_module_stop_time(module_id)
|
|
448
|
+
else:
|
|
449
|
+
module_status = TestStatus.SKIPPED
|
|
450
|
+
self._results[module_id]["module_status"] = module_status
|
|
451
|
+
self._reporter.set_module_status(module_id, module_status)
|
|
452
|
+
return is_module_stopped
|
|
453
|
+
|
|
454
|
+
def _stop_case(self, module_id: str, case_id: str, is_case_stopped: bool) -> bool:
|
|
455
|
+
# stopped status is set only once other statuses are skipped
|
|
456
|
+
if is_case_stopped is False:
|
|
457
|
+
case_status = TestStatus.STOPPED
|
|
458
|
+
is_case_stopped = True
|
|
459
|
+
if not self._reporter.get_case_start_time(module_id, case_id):
|
|
460
|
+
self._reporter.set_case_start_time(module_id, case_id)
|
|
461
|
+
self._reporter.set_case_stop_time(module_id, case_id)
|
|
462
|
+
else:
|
|
463
|
+
case_status = TestStatus.SKIPPED
|
|
464
|
+
self._results[module_id][case_id] = case_status
|
|
465
|
+
self._reporter.set_case_status(module_id, case_id, case_status)
|
|
466
|
+
return is_case_stopped
|
|
467
|
+
|
|
449
468
|
def _decode_assertion_msg(
|
|
450
469
|
self,
|
|
451
470
|
error: (
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from dataclasses import dataclass
|
|
6
|
+
from inspect import stack
|
|
6
7
|
from os import environ
|
|
7
8
|
from time import sleep
|
|
8
9
|
from typing import Any
|
|
@@ -181,8 +182,8 @@ def set_message(msg: str, msg_key: str | None = None) -> None:
|
|
|
181
182
|
If not specified, a random ID will be generated.
|
|
182
183
|
"""
|
|
183
184
|
current_test = _get_current_test()
|
|
184
|
-
reporter = RunnerReporter()
|
|
185
185
|
|
|
186
|
+
reporter = RunnerReporter()
|
|
186
187
|
if msg_key is None:
|
|
187
188
|
msg_key = str(uuid4())
|
|
188
189
|
|
|
@@ -323,8 +324,8 @@ def run_dialog_box(dialog_box_data: DialogBox) -> Any: # noqa: ANN401
|
|
|
323
324
|
if not dialog_box_data.dialog_text:
|
|
324
325
|
msg = "The 'dialog_text' argument cannot be empty."
|
|
325
326
|
raise ValueError(msg)
|
|
326
|
-
current_test = _get_current_test()
|
|
327
327
|
reporter = RunnerReporter()
|
|
328
|
+
current_test = _get_current_test()
|
|
328
329
|
key = reporter.generate_key(
|
|
329
330
|
DF.MODULES,
|
|
330
331
|
current_test.module_id,
|
|
@@ -420,7 +421,10 @@ def _get_current_test() -> CurrentTestInfo:
|
|
|
420
421
|
current_node = environ.get("PYTEST_CURRENT_TEST")
|
|
421
422
|
|
|
422
423
|
if current_node is None:
|
|
423
|
-
|
|
424
|
+
reporter = RunnerReporter()
|
|
425
|
+
caller = stack()[1].function
|
|
426
|
+
msg = f"Function {caller} can't be called outside of the test."
|
|
427
|
+
reporter.set_alert(msg)
|
|
424
428
|
raise RuntimeError(msg)
|
|
425
429
|
|
|
426
430
|
module_delimiter = ".py::"
|
|
@@ -53,6 +53,14 @@ class BaseReporter:
|
|
|
53
53
|
self._runstore.update_doc_value(key, value)
|
|
54
54
|
self._statestore.update_doc_value(key, value)
|
|
55
55
|
|
|
56
|
+
def set_alert(self, alert: str) -> None:
|
|
57
|
+
"""Set alert message.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
alert (str): alert message
|
|
61
|
+
"""
|
|
62
|
+
self.set_doc_value(DF.ALERT, alert, statestore_only=True)
|
|
63
|
+
|
|
56
64
|
def update_db_by_doc(self) -> None:
|
|
57
65
|
"""Update database by current document."""
|
|
58
66
|
self._statestore.update_db()
|
|
@@ -129,6 +129,19 @@ class HookReporter(BaseReporter):
|
|
|
129
129
|
key = self.generate_key(DF.MODULES, module_id, DF.CASES, case_id, DF.STATUS)
|
|
130
130
|
self.set_doc_value(key, status)
|
|
131
131
|
|
|
132
|
+
def get_case_status(self, module_id: str, case_id: str) -> str:
|
|
133
|
+
"""Set test case status.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
module_id (str): module id
|
|
137
|
+
case_id (str): case id
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
str: test case status
|
|
141
|
+
"""
|
|
142
|
+
key = self.generate_key(DF.MODULES, module_id, DF.CASES, case_id, DF.STATUS)
|
|
143
|
+
return self._statestore.get_field(key)
|
|
144
|
+
|
|
132
145
|
def set_case_start_time(self, module_id: str, case_id: str) -> None:
|
|
133
146
|
"""Set test case start_time.
|
|
134
147
|
|
|
@@ -159,6 +172,18 @@ class HookReporter(BaseReporter):
|
|
|
159
172
|
key = self.generate_key(DF.MODULES, module_id, DF.STATUS)
|
|
160
173
|
self.set_doc_value(key, status)
|
|
161
174
|
|
|
175
|
+
def get_module_status(self, module_id: str) -> str:
|
|
176
|
+
"""Get test module status.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
module_id (str): module id
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
str: test module status
|
|
183
|
+
"""
|
|
184
|
+
key = self.generate_key(DF.MODULES, module_id, DF.STATUS)
|
|
185
|
+
return self._statestore.get_field(key)
|
|
186
|
+
|
|
162
187
|
def set_module_start_time(self, module_id: str) -> None:
|
|
163
188
|
"""Set test module status.
|
|
164
189
|
|
|
@@ -194,14 +219,6 @@ class HookReporter(BaseReporter):
|
|
|
194
219
|
)
|
|
195
220
|
self.set_doc_value(key, attempt, statestore_only=True)
|
|
196
221
|
|
|
197
|
-
def set_alert(self, alert: str) -> None:
|
|
198
|
-
"""Set alert message.
|
|
199
|
-
|
|
200
|
-
Args:
|
|
201
|
-
alert (str): alert message
|
|
202
|
-
"""
|
|
203
|
-
self.set_doc_value(DF.ALERT, alert, statestore_only=True)
|
|
204
|
-
|
|
205
222
|
def get_module_start_time(self, module_id: str) -> int:
|
|
206
223
|
"""Get module start time.
|
|
207
224
|
|