@@ -26,6 +26,10 @@ import HeadlessPlayground, {
2626 HEADLESS_PLAYGROUND_RESET_ASSET_TEST_ID ,
2727 HEADLESS_PLAYGROUND_RESET_PAYMENT_METHOD_TEST_ID ,
2828 HEADLESS_PLAYGROUND_RESET_PROVIDER_TEST_ID ,
29+ HEADLESS_PLAYGROUND_ORDER_TRACKING_AWAIT_TEST_ID ,
30+ HEADLESS_PLAYGROUND_ORDER_TRACKING_REFRESH_TEST_ID ,
31+ HEADLESS_PLAYGROUND_ORDER_TRACKING_SECTION_TEST_ID ,
32+ HEADLESS_PLAYGROUND_ORDER_TRACKING_STATUS_BADGE_TEST_ID ,
2933 HEADLESS_PLAYGROUND_START_BUTTON_TEST_ID ,
3034 HEADLESS_PLAYGROUND_SUMMARY_DIVIDER_TEST_ID ,
3135 HEADLESS_PLAYGROUND_SUMMARY_TEST_ID ,
@@ -155,6 +159,10 @@ const mockUseRampsControllerInitialValues: ReturnType<
155159
156160let mockUseRampsControllerValues = mockUseRampsControllerInitialValues ;
157161
162+ const mockGetOrder = jest . fn ( ) ;
163+ const mockRefreshOrder = jest . fn ( ) ;
164+ const mockAwaitOrderTerminalState = jest . fn ( ) ;
165+
158166const mockUseHeadlessBuyInitialValues : ReturnType < typeof useHeadlessBuy > = {
159167 userRegion : mockUserRegion ,
160168 providers : mockProviders ,
@@ -163,6 +171,9 @@ const mockUseHeadlessBuyInitialValues: ReturnType<typeof useHeadlessBuy> = {
163171 tokens : { topTokens : mockTokens , allTokens : mockTokens } ,
164172 orders : [ ] ,
165173 getOrderById : mockGetOrderById ,
174+ getOrder : mockGetOrder ,
175+ refreshOrder : mockRefreshOrder ,
176+ awaitOrderTerminalState : mockAwaitOrderTerminalState ,
166177 getQuotes : mockGetQuotes ,
167178 startHeadlessBuy : mockStartHeadlessBuy ,
168179 isLoading : false ,
@@ -1182,5 +1193,186 @@ describe('HeadlessPlayground', () => {
11821193 screen . queryByTestId ( HEADLESS_PLAYGROUND_CANCEL_BUTTON_TEST_ID ) ,
11831194 ) . not . toBeOnTheScreen ( ) ;
11841195 } ) ;
1196+
1197+ describe ( 'Phase 9 order tracking panel' , ( ) => {
1198+ it ( 'does not render the order tracking panel before onOrderCreated fires' , async ( ) => {
1199+ await renderWithQuotes ( ) ;
1200+ expect (
1201+ screen . queryByTestId (
1202+ HEADLESS_PLAYGROUND_ORDER_TRACKING_SECTION_TEST_ID ,
1203+ ) ,
1204+ ) . not . toBeOnTheScreen ( ) ;
1205+ } ) ;
1206+
1207+ it ( 'renders order id, status, and refresh/await actions after onOrderCreated' , async ( ) => {
1208+ mockGetOrder . mockReturnValue ( {
1209+ providerOrderId : 'order-xyz' ,
1210+ status : 'PENDING' ,
1211+ provider : { id : '/providers/moonpay' } ,
1212+ walletAddress : '0xWALLET' ,
1213+ } ) ;
1214+ await renderWithQuotes ( ) ;
1215+ fireEvent . press (
1216+ screen . getByTestId ( `${ HEADLESS_PLAYGROUND_START_BUTTON_TEST_ID } -0` ) ,
1217+ ) ;
1218+ const callbacks = mockStartHeadlessBuy . mock . calls [ 0 ] [ 1 ] as {
1219+ onOrderCreated : ( orderId : string ) => void ;
1220+ } ;
1221+ act ( ( ) => {
1222+ callbacks . onOrderCreated ( 'order-xyz' ) ;
1223+ } ) ;
1224+ expect (
1225+ screen . getByTestId (
1226+ HEADLESS_PLAYGROUND_ORDER_TRACKING_SECTION_TEST_ID ,
1227+ ) ,
1228+ ) . toBeOnTheScreen ( ) ;
1229+ expect ( screen . getByText ( 'order-xyz' ) ) . toBeOnTheScreen ( ) ;
1230+ expect ( screen . getByText ( 'PENDING' ) ) . toBeOnTheScreen ( ) ;
1231+ } ) ;
1232+
1233+ it ( 'renders the (not yet in state) status placeholder when getOrder returns undefined' , async ( ) => {
1234+ mockGetOrder . mockReturnValue ( undefined ) ;
1235+ await renderWithQuotes ( ) ;
1236+ fireEvent . press (
1237+ screen . getByTestId ( `${ HEADLESS_PLAYGROUND_START_BUTTON_TEST_ID } -0` ) ,
1238+ ) ;
1239+ const callbacks = mockStartHeadlessBuy . mock . calls [ 0 ] [ 1 ] as {
1240+ onOrderCreated : ( orderId : string ) => void ;
1241+ } ;
1242+ act ( ( ) => {
1243+ callbacks . onOrderCreated ( 'order-xyz' ) ;
1244+ } ) ;
1245+ expect ( screen . getByText ( / n o t y e t i n s t a t e / i) ) . toBeOnTheScreen ( ) ;
1246+ } ) ;
1247+
1248+ it ( 'disables the refresh button when the order is not yet in state' , async ( ) => {
1249+ mockGetOrder . mockReturnValue ( undefined ) ;
1250+ await renderWithQuotes ( ) ;
1251+ fireEvent . press (
1252+ screen . getByTestId ( `${ HEADLESS_PLAYGROUND_START_BUTTON_TEST_ID } -0` ) ,
1253+ ) ;
1254+ const callbacks = mockStartHeadlessBuy . mock . calls [ 0 ] [ 1 ] as {
1255+ onOrderCreated : ( orderId : string ) => void ;
1256+ } ;
1257+ act ( ( ) => {
1258+ callbacks . onOrderCreated ( 'order-xyz' ) ;
1259+ } ) ;
1260+ const refreshButton = screen . getByTestId (
1261+ HEADLESS_PLAYGROUND_ORDER_TRACKING_REFRESH_TEST_ID ,
1262+ ) ;
1263+ expect ( refreshButton . props . accessibilityState ?. disabled ) . toBe ( true ) ;
1264+ } ) ;
1265+
1266+ it ( 'calls refreshOrder when the user taps the refresh button' , async ( ) => {
1267+ mockGetOrder . mockReturnValue ( {
1268+ providerOrderId : 'order-xyz' ,
1269+ status : 'PENDING' ,
1270+ provider : { id : '/providers/moonpay' } ,
1271+ walletAddress : '0xWALLET' ,
1272+ } ) ;
1273+ mockRefreshOrder . mockResolvedValue ( {
1274+ providerOrderId : 'order-xyz' ,
1275+ status : 'COMPLETED' ,
1276+ } ) ;
1277+ await renderWithQuotes ( ) ;
1278+ fireEvent . press (
1279+ screen . getByTestId ( `${ HEADLESS_PLAYGROUND_START_BUTTON_TEST_ID } -0` ) ,
1280+ ) ;
1281+ const callbacks = mockStartHeadlessBuy . mock . calls [ 0 ] [ 1 ] as {
1282+ onOrderCreated : ( orderId : string ) => void ;
1283+ } ;
1284+ act ( ( ) => {
1285+ callbacks . onOrderCreated ( 'order-xyz' ) ;
1286+ } ) ;
1287+ await act ( async ( ) => {
1288+ fireEvent . press (
1289+ screen . getByTestId (
1290+ HEADLESS_PLAYGROUND_ORDER_TRACKING_REFRESH_TEST_ID ,
1291+ ) ,
1292+ ) ;
1293+ } ) ;
1294+ expect ( mockRefreshOrder ) . toHaveBeenCalledWith ( 'order-xyz' ) ;
1295+ } ) ;
1296+
1297+ it ( 'renders an "Awaiting…" badge while awaitOrderTerminalState is in flight' , async ( ) => {
1298+ mockGetOrder . mockReturnValue ( {
1299+ providerOrderId : 'order-xyz' ,
1300+ status : 'PENDING' ,
1301+ provider : { id : '/providers/moonpay' } ,
1302+ walletAddress : '0xWALLET' ,
1303+ } ) ;
1304+ let resolveAwait : ( ( order : unknown ) => void ) | undefined ;
1305+ mockAwaitOrderTerminalState . mockImplementation (
1306+ ( ) =>
1307+ new Promise ( ( resolve ) => {
1308+ resolveAwait = resolve ;
1309+ } ) ,
1310+ ) ;
1311+ await renderWithQuotes ( ) ;
1312+ fireEvent . press (
1313+ screen . getByTestId ( `${ HEADLESS_PLAYGROUND_START_BUTTON_TEST_ID } -0` ) ,
1314+ ) ;
1315+ const callbacks = mockStartHeadlessBuy . mock . calls [ 0 ] [ 1 ] as {
1316+ onOrderCreated : ( orderId : string ) => void ;
1317+ } ;
1318+ act ( ( ) => {
1319+ callbacks . onOrderCreated ( 'order-xyz' ) ;
1320+ } ) ;
1321+ await act ( async ( ) => {
1322+ fireEvent . press (
1323+ screen . getByTestId (
1324+ HEADLESS_PLAYGROUND_ORDER_TRACKING_AWAIT_TEST_ID ,
1325+ ) ,
1326+ ) ;
1327+ } ) ;
1328+ expect (
1329+ screen . getByTestId (
1330+ HEADLESS_PLAYGROUND_ORDER_TRACKING_STATUS_BADGE_TEST_ID ,
1331+ ) ,
1332+ ) . toBeOnTheScreen ( ) ;
1333+ expect ( screen . getByText ( / A w a i t i n g / i) ) . toBeOnTheScreen ( ) ;
1334+
1335+ // Resolve the promise to keep the test isolation clean.
1336+ await act ( async ( ) => {
1337+ resolveAwait ?.( {
1338+ providerOrderId : 'order-xyz' ,
1339+ status : 'COMPLETED' ,
1340+ } ) ;
1341+ } ) ;
1342+ expect ( screen . getByText ( / T e r m i n a l s t a t e r e a c h e d / i) ) . toBeOnTheScreen ( ) ;
1343+ } ) ;
1344+
1345+ it ( 'renders a timed-out badge when awaitOrderTerminalState rejects with OrderTerminalStateTimeoutError' , async ( ) => {
1346+ const { OrderTerminalStateTimeoutError } =
1347+ jest . requireActual ( '../../headless' ) ;
1348+ mockGetOrder . mockReturnValue ( {
1349+ providerOrderId : 'order-xyz' ,
1350+ status : 'PENDING' ,
1351+ provider : { id : '/providers/moonpay' } ,
1352+ walletAddress : '0xWALLET' ,
1353+ } ) ;
1354+ mockAwaitOrderTerminalState . mockRejectedValue (
1355+ new OrderTerminalStateTimeoutError ( 'boom' ) ,
1356+ ) ;
1357+ await renderWithQuotes ( ) ;
1358+ fireEvent . press (
1359+ screen . getByTestId ( `${ HEADLESS_PLAYGROUND_START_BUTTON_TEST_ID } -0` ) ,
1360+ ) ;
1361+ const callbacks = mockStartHeadlessBuy . mock . calls [ 0 ] [ 1 ] as {
1362+ onOrderCreated : ( orderId : string ) => void ;
1363+ } ;
1364+ act ( ( ) => {
1365+ callbacks . onOrderCreated ( 'order-xyz' ) ;
1366+ } ) ;
1367+ await act ( async ( ) => {
1368+ fireEvent . press (
1369+ screen . getByTestId (
1370+ HEADLESS_PLAYGROUND_ORDER_TRACKING_AWAIT_TEST_ID ,
1371+ ) ,
1372+ ) ;
1373+ } ) ;
1374+ expect ( screen . getByText ( / T i m e d o u t / i) ) . toBeOnTheScreen ( ) ;
1375+ } ) ;
1376+ } ) ;
11851377 } ) ;
11861378} ) ;
0 commit comments