diff --git a/android/ozon/GetCardInfoScript.cpp b/android/ozon/GetCardInfoScript.cpp index 18255b3..b556876 100644 --- a/android/ozon/GetCardInfoScript.cpp +++ b/android/ozon/GetCardInfoScript.cpp @@ -45,6 +45,11 @@ void GetCardInfoScript::doStart() { const TaskDumpMeta dumpMeta{{}, 0, {}, {}, app.bankProfileId, app.phone, device.id, app.appVersion}; TaskDumpRecorder::Scope dumpScope("ozon", "FETCH_CARDS", m_deviceId, dumpMeta, &m_error); + // Версионный трек приложения → версионно-зависимый парсинг (см. AppVersionTrack.h). + xmlScreenParser.setVersionTrack(Ozon::trackForVersion(app.appVersion)); + qDebug() << "[Ozon::GetCardInfo] appVersion=" << app.appVersion + << "→ track" << Ozon::trackName(xmlScreenParser.versionTrack()); + // Читаем текущий экран xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); diff --git a/android/ozon/GetLastTransactionsScript.cpp b/android/ozon/GetLastTransactionsScript.cpp index 890628d..53148bb 100644 --- a/android/ozon/GetLastTransactionsScript.cpp +++ b/android/ozon/GetLastTransactionsScript.cpp @@ -112,6 +112,11 @@ void GetLastTransactionsScript::doStart() { const TaskDumpMeta dumpMeta{m_materialId, firstAmount, {}, {}, app.bankProfileId, app.phone, device.id, app.appVersion}; TaskDumpRecorder::Scope dumpScope("ozon", "FETCH_TRANSACTIONS", m_deviceId, dumpMeta, &m_error); + // Версионный трек приложения → версионно-зависимый парсинг (см. AppVersionTrack.h). + xmlScreenParser.setVersionTrack(Ozon::trackForVersion(app.appVersion)); + qDebug() << "[Ozon::GetLastTransactions] appVersion=" << app.appVersion + << "→ track" << Ozon::trackName(xmlScreenParser.versionTrack()); + if (!navigateToTransactionList(device, app)) { emit finishedWithResult(m_error); return; diff --git a/android/ozon/GetProfileInfoScript.cpp b/android/ozon/GetProfileInfoScript.cpp index f9cff95..7c74719 100644 --- a/android/ozon/GetProfileInfoScript.cpp +++ b/android/ozon/GetProfileInfoScript.cpp @@ -40,6 +40,11 @@ void GetProfileInfoScript::doStart() { const TaskDumpMeta dumpMeta{{}, 0, {}, {}, app.bankProfileId, app.phone, device.id, app.appVersion}; TaskDumpRecorder::Scope dumpScope("ozon", "FETCH_PROFILE_INFO", m_deviceId, dumpMeta, &m_error); + // Версионный трек приложения → версионно-зависимый парсинг (см. AppVersionTrack.h). + xmlScreenParser.setVersionTrack(Ozon::trackForVersion(app.appVersion)); + qDebug() << "[Ozon::GetProfileInfo] appVersion=" << app.appVersion + << "→ track" << Ozon::trackName(xmlScreenParser.versionTrack()); + // Читаем текущий экран xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); diff --git a/android/ozon/LoginAndCheckAccountsScript.cpp b/android/ozon/LoginAndCheckAccountsScript.cpp index ba0798e..a287ffd 100644 --- a/android/ozon/LoginAndCheckAccountsScript.cpp +++ b/android/ozon/LoginAndCheckAccountsScript.cpp @@ -43,6 +43,11 @@ void LoginAndCheckAccountsScript::doStart() { const TaskDumpMeta dumpMeta{{}, 0, {}, {}, app.bankProfileId, app.phone, device.id, app.appVersion}; TaskDumpRecorder::Scope dumpScope("ozon", "FETCH_PROFILE", m_deviceId, dumpMeta, &m_error); + // Версионный трек приложения → версионно-зависимый парсинг (см. AppVersionTrack.h). + xmlScreenParser.setVersionTrack(Ozon::trackForVersion(app.appVersion)); + qDebug() << "[Ozon::LoginAndCheckAccounts] appVersion=" << app.appVersion + << "→ track" << Ozon::trackName(xmlScreenParser.versionTrack()); + xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); if (!runAppAndGoToHomeScreen(m_deviceId, app.package, app.pinCode, device.screenWidth, device.screenHeight)) { diff --git a/android/ozon/PayByCardScript.cpp b/android/ozon/PayByCardScript.cpp index 50dfc6b..132eaa0 100644 --- a/android/ozon/PayByCardScript.cpp +++ b/android/ozon/PayByCardScript.cpp @@ -94,6 +94,11 @@ void PayByCardScript::doStart() { const TaskDumpMeta dumpMeta{m_account.materialId, m_amount, {}, m_cardNumber, app.bankProfileId, app.phone, device.id, app.appVersion}; TaskDumpRecorder::Scope dumpScope("ozon", "CREATE_TRANSACTION_CARD", adbId, dumpMeta, &m_error); + // Версионный трек приложения → версионно-зависимый парсинг (см. AppVersionTrack.h). + xmlScreenParser.setVersionTrack(Ozon::trackForVersion(app.appVersion)); + qDebug() << "[Ozon::PayByCard] appVersion=" << app.appVersion + << "→ track" << Ozon::trackName(xmlScreenParser.versionTrack()); + xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(adbId, ++m_counter)); // Закрываем рекламный bottom sheet @@ -162,6 +167,10 @@ void PayByCardScript::makePayment( }; // 1. Нажимаем "Перевести" на домашнем экране Node transferBtn = xmlScreenParser.findButtonNode("Перевести", false); + if (transferBtn.isEmpty()) { + // Compose-UI Ozon (>= 19.x): у кнопки пустой text, тест-id в content-desc. + transferBtn = xmlScreenParser.findNodeByContentDesc("transfer-button-shared"); + } if (transferBtn.isEmpty()) { m_error = "Кнопка 'Перевести' не найдена на домашнем экране"; qWarning() << "[PayByCard]" << m_error; diff --git a/android/ozon/PayByPhoneScript.cpp b/android/ozon/PayByPhoneScript.cpp index 216896d..44b42ba 100644 --- a/android/ozon/PayByPhoneScript.cpp +++ b/android/ozon/PayByPhoneScript.cpp @@ -103,6 +103,11 @@ void PayByPhoneScript::doStart() { const TaskDumpMeta dumpMeta{m_account.materialId, m_amount, m_phone, {}, app.bankProfileId, app.phone, device.id, app.appVersion}; TaskDumpRecorder::Scope dumpScope("ozon", "CREATE_TRANSACTION_PHONE", adbId, dumpMeta, &m_error); + // Версионный трек приложения → версионно-зависимый парсинг (см. AppVersionTrack.h). + xmlScreenParser.setVersionTrack(Ozon::trackForVersion(app.appVersion)); + qDebug() << "[Ozon::PayByPhone] appVersion=" << app.appVersion + << "→ track" << Ozon::trackName(xmlScreenParser.versionTrack()); + xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(adbId, ++m_counter)); // Закрываем рекламный bottom sheet @@ -176,6 +181,10 @@ void PayByPhoneScript::makePayment( // открывает промо "До 3 000 за рекомендацию". Тапаем в левую четверть, чтобы // гарантированно попасть мимо бейджа. Node transferBtn = xmlScreenParser.findButtonNode("Перевести", false); + if (transferBtn.isEmpty()) { + // Compose-UI Ozon (>= 19.x): у кнопки пустой text, тест-id в content-desc. + transferBtn = xmlScreenParser.findNodeByContentDesc("transfer-button-shared"); + } if (transferBtn.isEmpty()) { m_error = "Кнопка 'Перевести' не найдена на домашнем экране"; qWarning() << "[PayByPhone]" << m_error; diff --git a/android/ozon/ScreenXmlParser.cpp b/android/ozon/ScreenXmlParser.cpp index 345a0d0..57088b9 100644 --- a/android/ozon/ScreenXmlParser.cpp +++ b/android/ozon/ScreenXmlParser.cpp @@ -257,13 +257,17 @@ Node ScreenXmlParser::findNodeByContentDesc(const QString &contentDesc) { } bool ScreenXmlParser::isHomeScreen() { - // Домашний экран Ozon Банка: одновременно присутствуют кнопки "Перевести" и "Пополнить" + // Домашний экран Ozon Банка: одновременно присутствуют кнопки "Перевести" и "Пополнить". + // Старый UI отдавал их видимым text. Compose-сборки Ozon (>= 19.x) text не отдают — + // у кнопок пустой text, а тест-id лежит в content-desc (transfer-button-shared / + // replenish-button). Поддерживаем оба варианта. bool hasTransfer = false; bool hasTopUp = false; for (const Node &node: m_nodes) { const QString t = node.text.trimmed(); - if (t == "Перевести") hasTransfer = true; - if (t == "Пополнить") hasTopUp = true; + const QString cd = node.contentDesc.trimmed(); + if (t == "Перевести" || cd == "transfer-button-shared") hasTransfer = true; + if (t == "Пополнить" || cd == "replenish-button") hasTopUp = true; if (hasTransfer && hasTopUp) return true; } return false; @@ -605,8 +609,11 @@ QList ScreenXmlParser::findPinCodeNodes(const QString &pinCode) { static const QRegularExpression digitRx(R"(^(?:key\s+)?(\d)$)", QRegularExpression::CaseInsensitiveOption); for (const Node &node : m_nodes) { if (!node.clickable || node.width() <= 0 || node.height() <= 0) continue; - const QString t = node.text.trimmed(); - if (const auto match = digitRx.match(t); match.hasMatch()) { + // Цифра живёт в text ("1"/"key 1") в старом UI, либо — в Compose-сборках Ozon + // (>= 19.x) — в content-desc ("key 1") при пустом text. + auto match = digitRx.match(node.text.trimmed()); + if (!match.hasMatch()) match = digitRx.match(node.contentDesc.trimmed()); + if (match.hasMatch()) { digitMap[match.captured(1)] = node; } } diff --git a/android/ozon/ScreenXmlParser.h b/android/ozon/ScreenXmlParser.h index 8a73480..1ef296e 100644 --- a/android/ozon/ScreenXmlParser.h +++ b/android/ozon/ScreenXmlParser.h @@ -5,6 +5,7 @@ #include "android/xml/Node.h" #include "db/MaterialInfo.h" #include "db/TransactionInfo.h" +#include "AppVersionTrack.h" namespace Ozon { @@ -16,6 +17,13 @@ public: ~ScreenXmlParser() override; + // Версионный трек приложения проставляется один раз в начале скрипта: + // parser.setVersionTrack(Ozon::trackForVersion(app.appVersion)); + // Версионно-зависимые методы парсинга используют m_track как явный шов + // (см. AppVersionTrack.h). По умолчанию — новейший известный формат. + void setVersionTrack(AppVersionTrack track) { m_track = track; } + AppVersionTrack versionTrack() const { return m_track; } + Node tryToFindBannerOrDialog(int width, int height); Node tryToFindSecurityBanner(); @@ -133,6 +141,7 @@ public: private: QList m_nodes; QDomElement m_xml; + AppVersionTrack m_track = AppVersionTrack::V19_19_1; QList findPinCodeNodes(const QString &pinCode); }; diff --git a/assets/ozon/19.19.1/NOTES.md b/assets/ozon/19.19.1/NOTES.md new file mode 100644 index 0000000..d3cd0ed --- /dev/null +++ b/assets/ozon/19.19.1/NOTES.md @@ -0,0 +1,103 @@ +# Ozon 19.19.1 — расхождения вёрстки с парсером + +Устройство: Pixel 7, Android 17. Версия Ozon: **19.19.1** (versionCode 16030308). +Пакет: `ru.ozon.fintech.finance`. + +Общий вывод: приложение переехало на **Compose-семантику** — интерактивные контролы +(кнопки, вкладки) больше не несут видимый `text`, а выставляют стабильные тест-id в +`content-desc`. Текстовый контент (балансы, заголовки, строки списков) по-прежнему в `text`. +Парсер во многих местах матчит по `node.text` → ломается. Чинить переходом на `content-desc`. + +## Найденные расхождения + +### 1. PIN-пад (`findPinCodeNodes`, способ 1) — экран `pin_code` +- Было: цифра в `text="key 1"` (регулярка `^(?:key\s+)?(\d)$` по `node.text`). +- Стало: `text=""`, цифра в **`content-desc="key 1"`** (class Button). +- Эффект: способ 1 находит 0 цифр, спасает только геометрический fallback (способ 2) — хрупко + (кнопка отпечатка `bioauth` 86×87 почти попадает в группу «квадратных»). +- Фикс: в способе 1 матчить регуляркой и `node.text`, и `content-desc`. + +### 2. Главный экран (`isHomeScreen`) — экран `home_page` +- Было: требует одновременно `text=="Перевести"` и `text=="Пополнить"`. +- Стало: этих текстов нет. Кнопки — `content-desc`: `transfer-button-shared` (Перевести), + `replenish-button` (Пополнить), `qr-code-button` (Оплата QR). +- Нижняя навигация — `content-desc`: `Главная|FINANCE_TAB1` … `Ещё|FINANCE_TAB5`. +- Эффект: `isHomeScreen()` всегда возвращает false → флоу не стартует. +- Фикс: детектить по `content-desc` (`transfer-button-shared`+`replenish-button` или `FINANCE_TAB1`). + +### 2b. `findButtonNode("Перевести")` на главной — PayByPhone/PayByCard старт +- `findButtonNode()` матчит ТОЛЬКО `node.text` (class Button). Кнопка «Перевести» на главной — + `content-desc="transfer-button-shared"`, `text=""` → возвращает пусто. +- Эффект: `PayByPhoneScript` (стр.178) и `PayByCardScript` (стр.164) падают на старте: + «Кнопка 'Перевести' не найдена на домашнем экране». Аналогично «Пополнить» = `replenish-button`. +- Фикс: тапать кнопку действия на главной по `content-desc` (`transfer-button-shared` / + `replenish-button` / `qr-code-button`), либо расширить `findButtonNode` на `content-desc`. + +## ПРИМЕНЁННЫЕ ПРАВКИ (собрано и проверено на дампах 19.19.1) + +Все детекторы сделаны обратносовместимыми (сначала `text`, затем fallback на `content-desc`) — +старые сборки Ozon продолжают работать. + +1. `ScreenXmlParser::findPinCodeNodes` (способ 1) — цифра матчится и в `text`, и в `content-desc` + (`key N`). На дампе нашёл 10/10 цифр. +2. `ScreenXmlParser::isHomeScreen` — детект по `text` ИЛИ `content-desc` + (`transfer-button-shared` / `replenish-button`). На дампе → true. +3. `PayByPhoneScript` + `PayByCardScript` — домашняя «Перевести»: fallback + `findNodeByContentDesc("transfer-button-shared")` после пустого `findButtonNode`. + +### Каркас версионности — `android/ozon/AppVersionTrack.h` (по образцу Dushanbe) +- `enum AppVersionTrack { Legacy (<19.19.1), V19_19_1 (>=19.19.1, новейший по умолчанию) }`. +- `trackForVersion(appVersion)` через `QVersionNumber`; неизвестная/новее порога → новейший трек. +- `ScreenXmlParser`: `setVersionTrack()`/`versionTrack()`, член `m_track = V19_19_1`. +- Во всех 6 скриптах: `xmlScreenParser.setVersionTrack(Ozon::trackForVersion(app.appVersion))` + + лог `appVersion → track` сразу после `dumpScope`. +- Веток по `m_track` пока НЕТ (детекторы обратносовместимы) — трек это явный шов под будущие + расхождения и маркер в логах. Как добавлять новую версию — см. комментарий в AppVersionTrack.h. + +## Проверено на 19.19.1 и РАБОТАЕТ без правок + +- `isProfileScreen()` — тексты «Аккаунт»+«Выйти» на месте. +- `parseProfilePhone()` — режет склейку «+7 953 803 83 18 Номер телефона» по подстроке. +- `parseProfileFullName()` — ФИО «Галина Терехина» берётся как TextView между «Аккаунт» и телефоном. +- `findUserNameOnHomeScreen()` — «Галина Т.» в верхней зоне. +- Карта: «Показать»/«Реквизиты карты»/`findFullCardNumber` — номер `2204 3210 8610 9865`, + срок `12/35`, CVV `774` читаются. Тексты в `text`. +- `isTransactionListScreen()` — WebView text=«Операции». +- `findTransactionButtons()` — находит строки; поддерживает оба варианта (текст в Button и во вложенной View с ₽). +- `parseTransactionDetail()` — дата `26.05.2026, 18:56`, телефон `+7 (950) 128-60-90`, имя над телефоном. + +## Платёжный флоу — проверено реальными переводами (по скрипту) + +Сделаны 2 реальных перевода с устройства: СБП 50₽ на Альфа (+7 985 553-28-96) и +по карте 100₽+45₽ комиссия на карту Альфа 2200 1545 1435 0684. + +- Старт «Перевести» на главной — см. расхождение 2b (content-desc). +- Дальше всё на текстовых маркерах РАБОТАЕТ: «Платежи и переводы», «По номеру телефона», + «По номеру карты», «Перевод по номеру карты», «Номер карты получателя», «Сумма от», + «Продолжить», «Подтвердите перевод», «Перевести N ₽», «Успешно». +- Выбор банка (СБП): список — кнопки с числовым `content-desc` (ID банка, напр. Альфа=100000000008), + «Другой банк» = `content-desc="other-bank-item"`. Скрипт это уже поддерживает. +- Ввод названия банка кириллицей — ТОЛЬКО через ADBKeyboard (`com.android.adbkeyboard`): + `adb shell input text` кидает NullPointerException на кириллице. Скрипт использует + `enableAdbIMEKeyboard`/`inputAdbIMEText` — корректно. +- OCR ID операции: на СБП-чеке (Документы) есть «ID операции A6I5...» — `extractTransactionId` сработает. + На внутреннем Ozon-чеке поля «ID операции» НЕТ (см. transaction_document). + +## Снятые дампы (assets/ozon/19.19.1/) + +Корень: pin_code, home_page, profile, card_screen, card_screen_open, card_screen_hide, +payments_page, last_transactions (+ баннер «Аналитика финансов» = transaction_banner inline), +transaction_info, transaction_document. + +pay/: pay_buy_phone, pay_to_new_number, pay_buy_phone_select_bank, pay_buy_phone_select_bank_1, +pay_buy_phone_enter_sum, confirm_payment (=pay_buy_phone_check_data), confirm_payment_success +(=pay_buy_phone_sent_success), pay_by_card, pay_by_card_enter_sum, pay_by_card_success. + +## Ещё не снято +- account_requisites ⚠️ (флоу в коде закомментирован) — пропущено +- transaction_info_spb — пропущено по решению (есть свежая СБП-операция, если понадобится) +- pay_buy_phone_default_bank — пропущено (всегда вводим новый номер) +- confirm_payment_error — экран ошибки, сложно воспроизвести +- home_page_2, ask_biometry +- Баннеры/оверлеи: home_ad_1, google_play, banner_ipoteka, card_banner, select_bank, + onboarding ⚠️, security ⚠️, system_permission ⚠️ (всплывают ситуативно) diff --git a/assets/ozon/19.19.1/capture.sh b/assets/ozon/19.19.1/capture.sh new file mode 100755 index 0000000..6d1f71e --- /dev/null +++ b/assets/ozon/19.19.1/capture.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +# Снимок экрана Ozon: PNG + uiautomator XML под одним именем. +# Использование: ./capture.sh <имя> -> assets/ozon/19.19.1/<имя>.png|.xml +# ./capture.sh pay/<имя> -> кладёт в подпапку pay/ +set -euo pipefail +NAME="${1:?usage: capture.sh }" +DIR="$(cd "$(dirname "$0")" && pwd)" +OUT="$DIR/$NAME" +mkdir -p "$(dirname "$OUT")" + +# screenshot +adb exec-out screencap -p > "$OUT.png" + +# ui hierarchy +adb shell uiautomator dump /sdcard/window_dump.xml >/dev/null 2>&1 +adb pull /sdcard/window_dump.xml "$OUT.xml" >/dev/null 2>&1 + +PXSIZE=$(stat -f%z "$OUT.png" 2>/dev/null || echo 0) +echo "saved: $NAME.png (${PXSIZE}b) + $NAME.xml" diff --git a/assets/ozon/19.19.1/card_screen.png b/assets/ozon/19.19.1/card_screen.png new file mode 100644 index 0000000..e2c2f78 Binary files /dev/null and b/assets/ozon/19.19.1/card_screen.png differ diff --git a/assets/ozon/19.19.1/card_screen.xml b/assets/ozon/19.19.1/card_screen.xml new file mode 100644 index 0000000..0df9079 --- /dev/null +++ b/assets/ozon/19.19.1/card_screen.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/ozon/19.19.1/card_screen_hide.png b/assets/ozon/19.19.1/card_screen_hide.png new file mode 100644 index 0000000..1570de7 Binary files /dev/null and b/assets/ozon/19.19.1/card_screen_hide.png differ diff --git a/assets/ozon/19.19.1/card_screen_hide.xml b/assets/ozon/19.19.1/card_screen_hide.xml new file mode 100644 index 0000000..e402ff2 --- /dev/null +++ b/assets/ozon/19.19.1/card_screen_hide.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/ozon/19.19.1/card_screen_open.png b/assets/ozon/19.19.1/card_screen_open.png new file mode 100644 index 0000000..d578e1c Binary files /dev/null and b/assets/ozon/19.19.1/card_screen_open.png differ diff --git a/assets/ozon/19.19.1/card_screen_open.xml b/assets/ozon/19.19.1/card_screen_open.xml new file mode 100644 index 0000000..63d2e8d --- /dev/null +++ b/assets/ozon/19.19.1/card_screen_open.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/ozon/19.19.1/home_page.png b/assets/ozon/19.19.1/home_page.png new file mode 100644 index 0000000..46ba774 Binary files /dev/null and b/assets/ozon/19.19.1/home_page.png differ diff --git a/assets/ozon/19.19.1/home_page.xml b/assets/ozon/19.19.1/home_page.xml new file mode 100644 index 0000000..9c3ba46 --- /dev/null +++ b/assets/ozon/19.19.1/home_page.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/ozon/19.19.1/last_transactions.png b/assets/ozon/19.19.1/last_transactions.png new file mode 100644 index 0000000..0ae2fd8 Binary files /dev/null and b/assets/ozon/19.19.1/last_transactions.png differ diff --git a/assets/ozon/19.19.1/last_transactions.xml b/assets/ozon/19.19.1/last_transactions.xml new file mode 100644 index 0000000..30140bc --- /dev/null +++ b/assets/ozon/19.19.1/last_transactions.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/ozon/19.19.1/pay/confirm_payment.png b/assets/ozon/19.19.1/pay/confirm_payment.png new file mode 100644 index 0000000..efcc41f Binary files /dev/null and b/assets/ozon/19.19.1/pay/confirm_payment.png differ diff --git a/assets/ozon/19.19.1/pay/confirm_payment.xml b/assets/ozon/19.19.1/pay/confirm_payment.xml new file mode 100644 index 0000000..f3eee9f --- /dev/null +++ b/assets/ozon/19.19.1/pay/confirm_payment.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/ozon/19.19.1/pay/confirm_payment_success.png b/assets/ozon/19.19.1/pay/confirm_payment_success.png new file mode 100644 index 0000000..9b9c58b Binary files /dev/null and b/assets/ozon/19.19.1/pay/confirm_payment_success.png differ diff --git a/assets/ozon/19.19.1/pay/confirm_payment_success.xml b/assets/ozon/19.19.1/pay/confirm_payment_success.xml new file mode 100644 index 0000000..e3ebe70 --- /dev/null +++ b/assets/ozon/19.19.1/pay/confirm_payment_success.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/ozon/19.19.1/pay/pay_buy_phone.png b/assets/ozon/19.19.1/pay/pay_buy_phone.png new file mode 100644 index 0000000..68c9a08 Binary files /dev/null and b/assets/ozon/19.19.1/pay/pay_buy_phone.png differ diff --git a/assets/ozon/19.19.1/pay/pay_buy_phone.xml b/assets/ozon/19.19.1/pay/pay_buy_phone.xml new file mode 100644 index 0000000..8bbe9b7 --- /dev/null +++ b/assets/ozon/19.19.1/pay/pay_buy_phone.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/ozon/19.19.1/pay/pay_buy_phone_check_data.png b/assets/ozon/19.19.1/pay/pay_buy_phone_check_data.png new file mode 100644 index 0000000..efcc41f Binary files /dev/null and b/assets/ozon/19.19.1/pay/pay_buy_phone_check_data.png differ diff --git a/assets/ozon/19.19.1/pay/pay_buy_phone_check_data.xml b/assets/ozon/19.19.1/pay/pay_buy_phone_check_data.xml new file mode 100644 index 0000000..f3eee9f --- /dev/null +++ b/assets/ozon/19.19.1/pay/pay_buy_phone_check_data.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/ozon/19.19.1/pay/pay_buy_phone_enter_sum.png b/assets/ozon/19.19.1/pay/pay_buy_phone_enter_sum.png new file mode 100644 index 0000000..220094e Binary files /dev/null and b/assets/ozon/19.19.1/pay/pay_buy_phone_enter_sum.png differ diff --git a/assets/ozon/19.19.1/pay/pay_buy_phone_enter_sum.xml b/assets/ozon/19.19.1/pay/pay_buy_phone_enter_sum.xml new file mode 100644 index 0000000..bd7da20 --- /dev/null +++ b/assets/ozon/19.19.1/pay/pay_buy_phone_enter_sum.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/ozon/19.19.1/pay/pay_buy_phone_select_bank.png b/assets/ozon/19.19.1/pay/pay_buy_phone_select_bank.png new file mode 100644 index 0000000..40c8456 Binary files /dev/null and b/assets/ozon/19.19.1/pay/pay_buy_phone_select_bank.png differ diff --git a/assets/ozon/19.19.1/pay/pay_buy_phone_select_bank.xml b/assets/ozon/19.19.1/pay/pay_buy_phone_select_bank.xml new file mode 100644 index 0000000..82692e7 --- /dev/null +++ b/assets/ozon/19.19.1/pay/pay_buy_phone_select_bank.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/ozon/19.19.1/pay/pay_buy_phone_select_bank_1.png b/assets/ozon/19.19.1/pay/pay_buy_phone_select_bank_1.png new file mode 100644 index 0000000..74d6d11 Binary files /dev/null and b/assets/ozon/19.19.1/pay/pay_buy_phone_select_bank_1.png differ diff --git a/assets/ozon/19.19.1/pay/pay_buy_phone_select_bank_1.xml b/assets/ozon/19.19.1/pay/pay_buy_phone_select_bank_1.xml new file mode 100644 index 0000000..985777a --- /dev/null +++ b/assets/ozon/19.19.1/pay/pay_buy_phone_select_bank_1.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/ozon/19.19.1/pay/pay_buy_phone_sent_success.png b/assets/ozon/19.19.1/pay/pay_buy_phone_sent_success.png new file mode 100644 index 0000000..9b9c58b Binary files /dev/null and b/assets/ozon/19.19.1/pay/pay_buy_phone_sent_success.png differ diff --git a/assets/ozon/19.19.1/pay/pay_buy_phone_sent_success.xml b/assets/ozon/19.19.1/pay/pay_buy_phone_sent_success.xml new file mode 100644 index 0000000..e3ebe70 --- /dev/null +++ b/assets/ozon/19.19.1/pay/pay_buy_phone_sent_success.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/ozon/19.19.1/pay/pay_by_card.png b/assets/ozon/19.19.1/pay/pay_by_card.png new file mode 100644 index 0000000..9b65d02 Binary files /dev/null and b/assets/ozon/19.19.1/pay/pay_by_card.png differ diff --git a/assets/ozon/19.19.1/pay/pay_by_card.xml b/assets/ozon/19.19.1/pay/pay_by_card.xml new file mode 100644 index 0000000..5aced20 --- /dev/null +++ b/assets/ozon/19.19.1/pay/pay_by_card.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/ozon/19.19.1/pay/pay_to_new_number.png b/assets/ozon/19.19.1/pay/pay_to_new_number.png new file mode 100644 index 0000000..4d3209a Binary files /dev/null and b/assets/ozon/19.19.1/pay/pay_to_new_number.png differ diff --git a/assets/ozon/19.19.1/pay/pay_to_new_number.xml b/assets/ozon/19.19.1/pay/pay_to_new_number.xml new file mode 100644 index 0000000..3f1db81 --- /dev/null +++ b/assets/ozon/19.19.1/pay/pay_to_new_number.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/ozon/19.19.1/payments_page.png b/assets/ozon/19.19.1/payments_page.png new file mode 100644 index 0000000..7ed0d94 Binary files /dev/null and b/assets/ozon/19.19.1/payments_page.png differ diff --git a/assets/ozon/19.19.1/payments_page.xml b/assets/ozon/19.19.1/payments_page.xml new file mode 100644 index 0000000..5e3c637 --- /dev/null +++ b/assets/ozon/19.19.1/payments_page.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/ozon/19.19.1/pin_code.png b/assets/ozon/19.19.1/pin_code.png new file mode 100644 index 0000000..5565811 Binary files /dev/null and b/assets/ozon/19.19.1/pin_code.png differ diff --git a/assets/ozon/19.19.1/pin_code.xml b/assets/ozon/19.19.1/pin_code.xml new file mode 100644 index 0000000..25278c4 --- /dev/null +++ b/assets/ozon/19.19.1/pin_code.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/ozon/19.19.1/profile.png b/assets/ozon/19.19.1/profile.png new file mode 100644 index 0000000..07d0b35 Binary files /dev/null and b/assets/ozon/19.19.1/profile.png differ diff --git a/assets/ozon/19.19.1/profile.xml b/assets/ozon/19.19.1/profile.xml new file mode 100644 index 0000000..cda51b9 --- /dev/null +++ b/assets/ozon/19.19.1/profile.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/ozon/19.19.1/transaction_document.png b/assets/ozon/19.19.1/transaction_document.png new file mode 100644 index 0000000..c712b88 Binary files /dev/null and b/assets/ozon/19.19.1/transaction_document.png differ diff --git a/assets/ozon/19.19.1/transaction_document.xml b/assets/ozon/19.19.1/transaction_document.xml new file mode 100644 index 0000000..13c9573 --- /dev/null +++ b/assets/ozon/19.19.1/transaction_document.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/ozon/19.19.1/transaction_info.png b/assets/ozon/19.19.1/transaction_info.png new file mode 100644 index 0000000..7342a9b Binary files /dev/null and b/assets/ozon/19.19.1/transaction_info.png differ diff --git a/assets/ozon/19.19.1/transaction_info.xml b/assets/ozon/19.19.1/transaction_info.xml new file mode 100644 index 0000000..713bb82 --- /dev/null +++ b/assets/ozon/19.19.1/transaction_info.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/ozon_screens.md b/docs/ozon_screens.md index c2ebee1..0406df9 100644 --- a/docs/ozon_screens.md +++ b/docs/ozon_screens.md @@ -1,82 +1,95 @@ # Ozon — экраны и дампы -Чек-лист экранных дампов для банка **Ozon** (`appCode: ozon`). Используется, когда -выходит новая версия приложения и нужно понять, **какие экраны переснять**. +Чек-лист экранных дампов для банка **Ozon** (`appCode: ozon`, +пакет `ru.ozon.fintech.finance`). Используется, когда выходит новая версия приложения +и нужно понять, **какие экраны переснять**. ## Как пользоваться при выходе новой версии -1. Завести папку `assets/ozon/<новая_версия>/` (по образцу `assets/dushanbe/<версия>/`). +1. Завести папку `assets/ozon/<новая_версия>/` (по образцу `assets/ozon/19.19.1/`). + Платёжные экраны — в подпапку `pay/`. 2. Пройти по чек-листу ниже и снять XML+скриншот каждого экрана на устройстве с новой - версией. Дампы кладутся под теми же именами (платёжные — в подпапку `pay/`). + версией под теми же именами. Удобно скриптом `assets/ozon/19.19.1/capture.sh <имя>` + (кладёт `<имя>.png` + `<имя>.xml`; для платёжных — `pay/<имя>`). 3. Сверить новый дамп с картинкой ниже. -4. Если вёрстка/тексты разошлись с парсером — обновить `android/ozon/ScreenXmlParser.cpp`. +4. Если вёрстка/тексты разошлись с парсером — поправить `android/ozon/ScreenXmlParser.cpp` + и при необходимости завести новый трек в `android/ozon/AppVersionTrack.h`. ## Версионирование -Сейчас парсер Ozon **не версионируется** — опирается на текстовые маркеры -(`android/ozon/ScreenXmlParser.cpp`), а эталонные дампы лежат в корне `assets/ozon/` -(платёжные — в `assets/ozon/pay/`) без разбивки по версиям. +Парсер Ozon **версионируется**: `android/ozon/AppVersionTrack.h`, треки +**Legacy** (< 19.19.1, старый UI с подписями в `text`) / **V19_19_1** (>= 19.19.1, по +умолчанию). Скрипты выставляют трек один раз: `setVersionTrack(trackForVersion(app.appVersion))`. +Новый трек добавляется **только** если вёрстка реально разошлась — иначе хватает +свежих эталонных дампов в `assets/ozon/<версия>/`. -Ozon **тоже будет версионироваться**: конвенция папок `assets/ozon/<версия>/` вводится -на будущее по образцу Dushanbe. Когда вёрстка разойдётся между версиями, по аналогии с -`android/dushanbe/AppVersionTrack.h` понадобится завести `Ozon::AppVersionTrack` и -вызывать `setVersionTrack(...)` в скриптах. +**Ключевое расхождение 19.19.1:** приложение переехало на Compose-семантику — +интерактив (кнопки, вкладки, цифры пин-пада) больше не несёт видимый `text`, а отдаёт +стабильные тест-id в `content-desc`. Детекторы сделаны обратносовместимыми (матч сначала +по `text`, затем fallback на `content-desc`), правки применены в `findPinCodeNodes` / +`isHomeScreen` / `PayBy{Card,Phone}Script`. Подробности — `assets/ozon/19.19.1/NOTES.md`. -**Картинка под каждым экраном — текущий дамп из корня.** Когда появятся папки -`assets/ozon/<версия>/`, применяется тот же fallback по убыванию версии, что у Dushanbe. -Экраны без эталонного дампа помечены ⚠️ — их надо снять в первую очередь. +**Картинка под каждым экраном — самый свежий доступный дамп** (приоритет `19.19.1` → корень +`assets/ozon/`). Подпись «Текущий дамп» показывает, из какой версии реально взята картинка. +Экраны без дампа под новую версию помечены 🔲 «ещё не снято под 19.19.1»; без эталона вообще — ⚠️. --- ## 0. Общие баннеры / оверлеи Всплывают поверх любого экрана и должны закрываться во всех задачах для прохождения флоу. +Снимаются ситуативно (когда поймаются на экране) — под 19.19.1 пока не пересняты. -#### Реклама на главной — `home_ad_1` +#### Реклама на главной — `home_ad_1` 🔲 Рекламный bottom-sheet (`tryToFindAdBanner()`, `resource-id design_bottom_sheet`). -- [ ] Снять под новую версию +- [ ] Снять под 19.19.1 - Текущий дамп: **текущий (без версии)** - home_ad_1 -#### Обновление Google Play — `google_play` +#### Обновление Google Play — `google_play` 🔲 In-app update bottom-sheet (`tryToFindGooglePlayBanner()`). -- [ ] Снять под новую версию +- [ ] Снять под 19.19.1 - Текущий дамп: **текущий (без версии)** - google_play -#### Баннер ипотеки — `banner_ipoteka` +#### Баннер ипотеки — `banner_ipoteka` 🔲 Промо-баннер на главной. -- [ ] Снять под новую версию +- [ ] Снять под 19.19.1 - Текущий дамп: **текущий (без версии)** - banner_ipoteka -#### Баннер карты — `card_banner` +#### Баннер карты — `card_banner` 🔲 Промо-баннер «Заказать карту» на главной. -- [ ] Снять под новую версию +- [ ] Снять под 19.19.1 - Текущий дамп: **текущий (без версии)** - card_banner -#### Выбор (bottom-sheet) — `select_bank` -Шторка выбора (`tryToFindSelectBottomSheet()`). -- [ ] Снять под новую версию +#### Выбор (bottom-sheet) — `select_bank` 🔲 +Шторка выбора (`tryToFindSelectBottomSheet()`). Не путать с экраном выбора банка СБП +(`pay/pay_buy_phone_select_bank`). +- [ ] Снять под 19.19.1 - Текущий дамп: **текущий (без версии)** - select_bank #### Онбординг «Обновили главную» ⚠️ `resource-id onboarding_viewpager`, кнопка «Пропустить» (`tryToFindOnboardingBanner()`). -- [ ] **Эталонный дамп ещё не снят — приоритет при следующем съёме** +- [ ] **Эталонный дамп ещё не снят** - Текущий дамп: _нет_ #### Баннер безопасности ⚠️ «Мы заботимся о вашей безопасности» (`tryToFindSecurityBanner()`). -- [ ] **Эталонный дамп ещё не снят — приоритет при следующем съёме** +- [ ] **Эталонный дамп ещё не снят** - Текущий дамп: _нет_ #### Системный диалог разрешений ⚠️ `com.google.android.permissioncontroller`, кнопка «ЗАПРЕТИТЬ» (`tryToFindSystemPermissionDenyButton()`). -- [ ] **Эталонный дамп ещё не снят — приоритет при следующем съёме** +- [ ] **Эталонный дамп ещё не снят** - Текущий дамп: _нет_ +> Замечено в 19.19.1, но ещё не снято как эталон: шторка «Разрешите доступ к камере» +> (для QR/паспорта, кнопка «Не сейчас») и баннер «Разрешите доступ к контактам» на экране +> «Кому перевести» — обе закрываются по «Не сейчас». + --- ## 1. Мастер установок (`BankSetupWizard`) @@ -86,60 +99,65 @@ In-app update bottom-sheet (`tryToFindGooglePlayBanner()`). ### 1.1. Пин-код / вход (`LoginAndCheckAccountsScript`) #### Главный экран — `home_page` -Кнопки «Перевести» + «Пополнить» (`isHomeScreen()`). -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- home_page +Кнопки «Перевести» + «Пополнить» (`isHomeScreen()`). В 19.19.1 — `content-desc` +`transfer-button-shared` / `replenish-button`, вкладки `Главная|FINANCE_TAB1…5`. +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- home_page -#### Главный экран (альт. вид) — `home_page_2` +#### Главный экран (альт. вид) — `home_page_2` 🔲 Альтернативное состояние главной. -- [ ] Снять под новую версию +- [ ] Снять под 19.19.1 - Текущий дамп: **текущий (без версии)** - home_page_2 #### Ввод PIN — `pin_code` -Экран ввода пин-кода (`tryToFindPinCode()`). -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- pin_code +Экран ввода пин-кода (`tryToFindPinCode()` по тексту «Не помню код-пароль»). В 19.19.1 +цифры в `content-desc="key N"` (см. `findPinCodeNodes`). +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- pin_code -#### Запрос биометрии — `ask_biometry` +#### Запрос биометрии — `ask_biometry` 🔲 Диалог предложения включить биометрию. -- [ ] Снять под новую версию +- [ ] Снять под 19.19.1 - Текущий дамп: **текущий (без версии)** - ask_biometry ### 1.2. Профиль (`GetProfileInfoScript`) #### Профиль / Аккаунт — `profile` -Заголовок «Аккаунт» + кнопка «Выйти» (`isProfileScreen()`), ФИО и телефон. -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- profile +Заголовок «Аккаунт» + кнопка «Выйти» (`isProfileScreen()`), ФИО и телефон. На 19.19.1 +парсинг работает (телефон режется по «… Номер телефона»). +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- profile ### 1.3. Карты (`GetCardInfoScript`) #### Карта — `card_screen` -Основное состояние экрана карты. -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- card_screen +Основное состояние экрана карты (реквизиты маскированы, кнопка «Показать»). +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- card_screen #### Карта (развёрнута) — `card_screen_open` -Карта с раскрытыми деталями. -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- card_screen_open +Реквизиты раскрыты («Показать» → полный номер/срок/CVV, кнопка «Скрыть»). +`findFullCardNumber` читает номер. +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- card_screen_open #### Карта (свёрнута) — `card_screen_hide` -Карта со скрытыми деталями. -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- card_screen_hide +Реквизиты скрыты (маскированы). +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- card_screen_hide #### Реквизиты счёта ⚠️ Заголовок «Реквизиты счёта» (`isAccountRequisitesScreen()`, `parseAccountNumberFromRequisites()`). -- [ ] **Эталонный дамп ещё не снят — приоритет при следующем съёме** +Флоу в `GetCardInfoScript` сейчас закомментирован. +- [ ] **Эталонный дамп ещё не снят** - Текущий дамп: _нет_ --- @@ -149,42 +167,45 @@ In-app update bottom-sheet (`tryToFindGooglePlayBanner()`). ### 2.1. Список истории #### Страница платежей — `payments_page` -Раздел платежей/операций. -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- payments_page +Раздел «Платежи и переводы» (он же старт платёжных флоу: «По номеру телефона», +«По номеру карты», «Между счетами»). +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- payments_page #### Последние транзакции — `last_transactions` -Список операций (`isTransactionListScreen()`, `findTransactionButtons()`). -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- last_transactions +Список операций — WebView «Операции» (`isTransactionListScreen()`, `findTransactionButtons()` +поддерживает текст в Button и во вложенной View с ₽). +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- last_transactions -#### Баннер в списке транзакций — `transaction_banner` -Промо-баннер внутри списка операций. -- [ ] Снять под новую версию +#### Баннер в списке транзакций — `transaction_banner` 🔲 +Промо-баннер «Аналитика финансов» внутри списка операций. В 19.19.1 виден inline на дампе +`last_transactions` (отдельный кроп не снимался). +- [ ] Снять под 19.19.1 (отдельно) - Текущий дамп: **текущий (без версии)** - transaction_banner ### 2.2. Детали транзакции #### Детали транзакции — `transaction_info` -Дата, отправитель, телефон, сумма (`parseTransactionDetail()`). -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- transaction_info +Дата+время, имя, телефон, сумма (`parseTransactionDetail()`). +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- transaction_info -#### Детали транзакции (СБП) — `transaction_info_spb` -Версия деталей для перевода через СБП. -- [ ] Снять под новую версию +#### Детали транзакции (СБП) — `transaction_info_spb` 🔲 +Версия деталей для перевода через СБП в другой банк. +- [ ] Снять под 19.19.1 - Текущий дамп: **текущий (без версии)** - transaction_info_spb #### Документ операции — `transaction_document` -Чек/документ по операции. -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- transaction_document +Чек/документ по операции (PDF-картинка, OCR). На СБП-чеке есть «ID операции». +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- transaction_document --- @@ -193,102 +214,101 @@ In-app update bottom-sheet (`tryToFindGooglePlayBanner()`). ### 3.1. Платёж по карте (`PayByCardScript`) #### Перевод по номеру карты — `pay/pay_by_card` -Экран ввода номера карты получателя (WebView). -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- pay_by_card +Экран «Перевод по номеру карты» (`movable-pan-iframe`), поле «Номер карты получателя». +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- pay_by_card #### Ввод суммы — `pay/pay_by_card_enter_sum` -Поле суммы перевода по карте. -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- pay_by_card_enter_sum +Карта распознана (банк-получатель), сумма введена, посчитана комиссия, кнопка «Перевести N ₽». +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- pay_by_card_enter_sum #### Успех — `pay/pay_by_card_success` -Экран успешного перевода по карте. -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- pay_by_card_success +Экран «Успешно −N ₽» (включая комиссию). +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- pay_by_card_success ### 3.2. Платёж по телефону (`PayByPhoneScript`) #### Перевод по номеру — `pay/pay_buy_phone` -Основной экран перевода по номеру телефона. -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- pay_buy_phone +Экран «Кому перевести»: поле «Номер телефона получателя» + последние переводы. +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- pay_buy_phone #### Ввод суммы — `pay/pay_buy_phone_enter_sum` -Поле суммы перевода по номеру. -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- pay_buy_phone_enter_sum +Экран «По номеру телефона»: счёт списания, получатель (с банком/СБП), «Сумма до …». +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- pay_buy_phone_enter_sum #### Выбор банка — `pay/pay_buy_phone_select_bank` -Список банков получателя. -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- pay_buy_phone_select_bank +Список банков получателя (СБП): Озон/Альфа/Т-Банк/«Другой банк» (`other-bank-item`). +Банки — кнопки с числовым `content-desc` (ID банка). +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- pay_buy_phone_select_bank -#### Выбор банка (альт. вид) — `pay/pay_buy_phone_select_bank_1` -Альтернативное состояние выбора банка. -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- pay_buy_phone_select_bank_1 +#### Выбор банка — поиск — `pay/pay_buy_phone_select_bank_1` +Экран поиска банка после «Другой банк» (EditText hint «Название банка»). Ввод кириллицы — +только через ADBKeyboard (`com.android.adbkeyboard`); `adb input text` кириллицу не умеет. +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- pay_buy_phone_select_bank_1 -#### Банк по умолчанию — `pay/pay_buy_phone_default_bank` -Экран с предустановленным банком получателя. -- [ ] Снять под новую версию +#### Банк по умолчанию — `pay/pay_buy_phone_default_bank` 🔲 +Экран с предустановленным банком получателя (путь «старого» номера — не снимался). +- [ ] Снять под 19.19.1 - Текущий дамп: **текущий (без версии)** - pay_buy_phone_default_bank #### Проверка данных — `pay/pay_buy_phone_check_data` -Экран сверки данных перед отправкой. -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- pay_buy_phone_check_data +Экран «Подтвердите перевод»: банк получателя, счёт списания, сумма (то же, что `confirm_payment`). +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- pay_buy_phone_check_data #### Перевод на новый номер — `pay/pay_to_new_number` -Ввод нового, ранее не использованного номера. -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- pay_to_new_number +Экран «Кому перевести» с введённым новым номером. +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- pay_to_new_number -#### Перевод на старый номер — `pay/pay_to_old_number` -Выбор ранее использованного номера. -- [ ] Снять под новую версию +#### Перевод на старый номер — `pay/pay_to_old_number` 🔲 +Выбор ранее использованного номера (по решению не снимался — всегда вводим новый номер). +- [ ] Снять под 19.19.1 - Текущий дамп: **текущий (без версии)** - pay_to_old_number #### Отправлено — `pay/pay_buy_phone_sent_success` -Экран успешной отправки перевода по номеру. -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- pay_buy_phone_sent_success +Экран успешной отправки перевода по номеру (то же, что `confirm_payment_success`). +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- pay_buy_phone_sent_success ### 3.3. Подтверждение (общее для обоих) #### Подтверждение платежа — `pay/confirm_payment` -Экран подтверждения операции. -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- confirm_payment +Экран «Подтвердите перевод», кнопка «Перевести N ₽». +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- confirm_payment #### Подтверждение — успех — `pay/confirm_payment_success` -Успешное подтверждение, с него снимается ID операции. -- [ ] Снять под новую версию -- Текущий дамп: **текущий (без версии)** -- confirm_payment_success +Чек «Успешно −N ₽» (СБП), с него снимается ID операции (через документ/OCR). +- [x] Снято под 19.19.1 +- Текущий дамп: **19.19.1** +- confirm_payment_success -#### Подтверждение — ошибка — `pay/confirm_payment_error` -Экран ошибки подтверждения платежа. -- [ ] Снять под новую версию +#### Подтверждение — ошибка — `pay/confirm_payment_error` 🔲 +Экран ошибки подтверждения платежа (сложно воспроизвести). +- [ ] Снять под 19.19.1 - Текущий дамп: **текущий (без версии)** - confirm_payment_error - - - --- ## Сводные галереи (только экраны, используемые в коде) @@ -299,23 +319,17 @@ _Эталонные дампы, на которые сейчас нет акти | | | | | | | | | |---|---|---|---|---|---|---|---| -|
home_page
текущий (без версии) |
profile
текущий (без версии) | | | | | | | +|
home_page
19.19.1 |
profile
19.19.1 |
card_screen
19.19.1 | | | | | | ### Задача `fetch_transactions` (`FetchTransactions`) | | | | | | | | | |---|---|---|---|---|---|---|---| -|
payments_page
текущий (без версии) |
last_transactions
текущий (без версии) |
transaction_info
текущий (без версии) | | | | | | +|
payments_page
19.19.1 |
last_transactions
19.19.1 |
transaction_info
19.19.1 |
transaction_document
19.19.1 | | | | | ### Задача `create_transaction` (`CreateTransaction`) | | | | | | | | | |---|---|---|---|---|---|---|---| -|
pay_by_card
текущий (без версии) |
pay_by_card_enter_sum
текущий (без версии) |
pay_by_card_success
текущий (без версии) |
pay_buy_phone
текущий (без версии) |
pay_buy_phone_enter_sum
текущий (без версии) |
pay_buy_phone_select_bank
текущий (без версии) |
pay_buy_phone_default_bank
текущий (без версии) |
pay_to_new_number
текущий (без версии) | -|
pay_to_old_number
текущий (без версии) |
pay_buy_phone_sent_success
текущий (без версии) |
confirm_payment
текущий (без версии) |
confirm_payment_success
текущий (без версии) |
confirm_payment_error
текущий (без версии) | | | | - -### Оставшиеся экраны (баннеры/оверлеи, вне серверных задач) - -| | | | | | | | | -|---|---|---|---|---|---|---|---| -|
home_ad_1
текущий (без версии) |
google_play
текущий (без версии) | | | | | | | +|
pay_by_card
19.19.1 |
pay_by_card_enter_sum
19.19.1 |
pay_by_card_success
19.19.1 |
pay_buy_phone
19.19.1 |
pay_buy_phone_enter_sum
19.19.1 |
pay_buy_phone_select_bank
19.19.1 |
pay_to_new_number
19.19.1 | | +|
select_bank_1
19.19.1 |
pay_buy_phone_sent_success
19.19.1 |
confirm_payment
19.19.1 |
confirm_payment_success
19.19.1 | | | | | diff --git a/tests/mock_server/default_profile.json b/tests/mock_server/default_profile.json index 6348111..7091dc5 100644 --- a/tests/mock_server/default_profile.json +++ b/tests/mock_server/default_profile.json @@ -13,7 +13,7 @@ "device_label": "Pixel 7", "materials": [ { - "id": "d49d3d02-ecce-4e00-97d5-0c52da6fd0db", + "id": "e1234f11-b99d-4930-9f86-75148601f683", "state": "enabled", "card_number": "2204321035207919", "currency": 643 diff --git a/tests/mock_server/mock_server.py b/tests/mock_server/mock_server.py index be1a598..1de7060 100644 --- a/tests/mock_server/mock_server.py +++ b/tests/mock_server/mock_server.py @@ -345,6 +345,21 @@ def current_profile(): }) +@app.get("/api/v1/profile/get_info") +def profile_get_info(): + return ok({"id": _profile_id}) + + +@app.post("/api/v1/profile/ping") +def profile_ping(): + return ok({}) + + +@app.get("/api/v1/profile/ping") +def profile_ping_get(): + return ok({}) + + @app.post("/api/v1/profile/bank_profile") def bank_profile_create(): body = request.get_json(silent=True) or {}