# Full product lifecycle, driven across BOTH apps in one run. # # Maestro's launchApp accepts an appId, so a single flow can alternate between # the admin app and the user app and verify each change immediately. # # Coverage: # - create a product + attach it to the slot (admin) # - it is searchable and orderable (user) # - suspend the SKU (admin) -> user: Unavailable # - change its units (quantity attribute) (admin) -> user: new unit # - flash: enable, then disable (admin) -> user: no 1 hr row # - add a second variant (multiple SKUs) (admin) -> user: variant count # - replace the image (admin) # - save and re-verify (user) # # Env (see e2e/run.sh): ADMIN_NAME, ADMIN_PASSWORD, PRODUCT_NAME, PRODUCT_PRICE, # TEST_IDENTIFIER, TEST_PASSWORD, SLOT_DELIVERY_LABEL # # NOTE: the image step drives the Android system Photo Picker, which only lists # photos already on the device — e2e/run.sh pushes a fixture image first. appId: in.freshyo.adminui --- # --- 1. Admin: create the product and attach it to the slot ------------------ # Reuses the standalone flows so the selectors live in one place. # Slot update disabled for now — only product create + update. - runFlow: admin-product.yaml # - runFlow: admin-attach-product.yaml # --- 2. User: the new product is searchable --------------------------------- # DISABLED while iterating on the admin side — re-enable to verify in the user # app (it is a long leg: app switch + CDN refresh + search). # - launchApp: # appId: in.freshyo.app # clearState: false # - tapOn: # text: "^Home$" # optional: true # - extendedWaitUntil: # visible: # id: "add-to-cart-icon" # timeout: 90000 # # The catalog is a versioned CDN file, so refresh to pick up the new product. # - swipe: # start: "50%,30%" # end: "50%,80%" # - waitForAnimationToEnd: # timeout: 10000 # - tapOn: "Search fresh meat..." # - extendedWaitUntil: # visible: "All Products" # timeout: 30000 # - inputText: ${PRODUCT_NAME} # - hideKeyboard # - extendedWaitUntil: # visible: "${PRODUCT_NAME}.*" # timeout: 120000 # # The card carries the unit notation and the price from the admin form. # - assertVisible: "Quantity: 0.5 kg" # --- 3. Admin: suspend the SKU, change its units, add a variant ------------- - launchApp: appId: in.freshyo.adminui clearState: false - extendedWaitUntil: visible: "Dashboard" timeout: 90000 - tapOn: "Products" - extendedWaitUntil: visible: "Search products..." timeout: 40000 - tapOn: "Search products..." - inputText: ${PRODUCT_NAME} - hideKeyboard - waitForAnimationToEnd: timeout: 5000 - tapOn: "Edit" - extendedWaitUntil: visible: "Enter product name" timeout: 40000 # Units: the quantity attribute value (auto-added, name is locked to "quantity"). # Scroll to it first — centering the checkbox labels below would push it off-screen. - scrollUntilVisible: element: text: "0.5 kg" direction: DOWN centerElement: true timeout: 30000 - tapOn: "0.5 kg" - eraseText - inputText: "1 kg" - hideKeyboard # Multi-SKU: a second variant with its own price and unit. The leading "+" is an # icon rather than part of the label, so match on the label alone. - scrollUntilVisible: element: text: ".*Add Variant" direction: DOWN centerElement: true timeout: 30000 - tapOn: ".*Add Variant" # Reveal the new card — it is added below the fold, and extendedWaitUntil never # scrolls. Only retry the button if the card is still absent AFTER scrolling (a # bare notVisible would be true while the card is merely off-screen and would # double-tap, adding a third variant). - scrollUntilVisible: element: text: "Variant 2" direction: DOWN centerElement: true timeout: 30000 - runFlow: when: notVisible: "Variant 2" commands: - waitForAnimationToEnd: timeout: 3000 - tapOn: ".*Add Variant" - scrollUntilVisible: element: text: "Variant 2" direction: DOWN centerElement: true timeout: 30000 - waitForAnimationToEnd: timeout: 5000 - scrollUntilVisible: element: text: "Selling price" direction: DOWN centerElement: true timeout: 30000 # Settle before tapping: a tap that lands while the list is still scrolling hits # nothing, which is why this field stayed empty before. - waitForAnimationToEnd: timeout: 5000 # Scroll to the price field — the second variant (index 1, shown as "Variant 2") # sits below the first, so this reveals it. Tapping an off-screen field does # nothing, hence the scroll first. - scrollUntilVisible: element: id: "variant-1-price" direction: DOWN centerElement: true timeout: 30000 - waitForAnimationToEnd: timeout: 5000 - tapOn: id: "variant-1-price" - inputText: "999" - hideKeyboard - scrollUntilVisible: element: text: "e.g. 0.5 kg" direction: DOWN centerElement: true timeout: 30000 # Variant 1's price/value are already filled, so only variant 2's empty fields # render these placeholders — exactly one match each, hence no index. - waitForAnimationToEnd: timeout: 5000 - tapOn: "e.g. 0.5 kg" - inputText: "2 kg" - hideKeyboard # Flash: turn it on, fill the flash price, then turn it back off. Tap the actual # checkbox (id), not the label text — the label is a plain Text that ignores taps. - scrollUntilVisible: element: id: "variant-0-flash" direction: DOWN centerElement: true timeout: 30000 - tapOn: id: "variant-0-flash" - waitForAnimationToEnd: timeout: 3000 - runFlow: when: visible: "Enter flash price" commands: - tapOn: "Enter flash price" - inputText: "399" - hideKeyboard - tapOn: id: "variant-0-flash" - waitForAnimationToEnd: timeout: 3000 # Suspend the SKU (the whole product effectively goes unavailable to users). - tapOn: id: "variant-0-suspend" # Replace the image: the add tile sits just below the checkboxes, and this is the # only path (expo-image-picker -> Android Photo Picker). - tapOn: point: "21%,61%" - waitForAnimationToEnd: timeout: 8000 - runFlow: when: visible: "This app can only access the photos you select" commands: - tapOn: point: "16%,32%" - waitForAnimationToEnd: timeout: 3000 # The confirm button is labelled "Add (1)" once a photo is selected, so it # can't be matched by a bare "Add". - runFlow: when: visible: "Add.*" commands: - tapOn: "Add.*" - runFlow: when: visible: "Done" commands: - tapOn: "Done" # Save everything. - scrollUntilVisible: element: text: "Save Changes" direction: DOWN centerElement: true timeout: 30000 - waitForAnimationToEnd: timeout: 5000 - tapOn: "Save Changes" # Retry while the button is still up: a tap that lands mid-settle is swallowed, # and the label only goes away once the mutation is actually in flight. - repeat: times: 5 commands: - runFlow: when: visible: "Save Changes" commands: - waitForAnimationToEnd: timeout: 3000 - tapOn: "Save Changes" - extendedWaitUntil: visible: "Product updated successfully!" timeout: 60000 - tapOn: "OK" # --- 4. User: the changes are visible --------------------------------------- # DISABLED while iterating on the admin side — re-enable to assert the effects # (suspended -> Out of Stock / UNAVAILABLE, new unit, no 1 hr row). # - launchApp: # appId: in.freshyo.app # clearState: false # - tapOn: # text: "^Home$" # optional: true # - extendedWaitUntil: # visible: # id: "add-to-cart-icon" # timeout: 90000 # - swipe: # start: "50%,30%" # end: "50%,80%" # - waitForAnimationToEnd: # timeout: 10000 # - tapOn: "Search fresh meat..." # - extendedWaitUntil: # visible: "All Products" # timeout: 30000 # - inputText: ${PRODUCT_NAME} # - hideKeyboard # # # Suspended SKU -> the card is marked out of stock and cannot be added. # - extendedWaitUntil: # visible: "${PRODUCT_NAME}.*" # timeout: 120000 # - assertVisible: "Out of Stock" # - assertVisible: "UNAVAILABLE"