@mohasinac/appkit 4.41.13 → 4.41.15
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.
- package/dist/_internal/server/features/auctions/actions.js +1 -1
- package/dist/_internal/server/features/cart/actions.js +4 -4
- package/dist/_internal/server/features/events/actions.js +2 -2
- package/dist/_internal/server/features/history/actions.js +2 -2
- package/dist/_internal/server/features/lottery/actions.js +1 -1
- package/dist/_internal/server/features/orders/actions.js +5 -5
- package/dist/_internal/server/features/pre-orders/actions.js +1 -1
- package/dist/_internal/server/features/promotions/actions.js +1 -1
- package/dist/_internal/server/features/reviews/actions.js +3 -3
- package/dist/_internal/server/features/wishlist/actions.js +3 -3
- package/dist/features/faq/components/FAQPageContent.d.ts +2 -0
- package/dist/features/faq/components/FAQPageContent.js +19 -2
- package/dist/features/homepage/components/AnnouncementBar.js +25 -1
- package/dist/features/tester/seed-data/authored/buying__order-detail-actions.js +17 -3
- package/dist/seed/orders-seed-data.js +19 -1
- package/dist/styles.css +1 -1
- package/dist/tailwind-utilities.css +1 -1
- package/package.json +1 -1
|
@@ -8,7 +8,7 @@ import { assertAuctionActive, assertBidAmount, assertNotAuctionOwner, shouldAuto
|
|
|
8
8
|
import { ValidationError } from "../../../shared/errors/index";
|
|
9
9
|
export async function placeBidAction(input) {
|
|
10
10
|
return wrapAction(async () => {
|
|
11
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
11
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
12
12
|
const parsed = placeBidActionSchema.safeParse(input);
|
|
13
13
|
if (!parsed.success)
|
|
14
14
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid bid input");
|
|
@@ -7,7 +7,7 @@ import { upsertCartItem, mergeGuestItems } from "./service";
|
|
|
7
7
|
import { ValidationError } from "../../../shared/errors/index";
|
|
8
8
|
export async function addToCartAction(input) {
|
|
9
9
|
return wrapAction(async () => {
|
|
10
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
10
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
11
11
|
const parsed = addToCartSchema.safeParse(input);
|
|
12
12
|
if (!parsed.success)
|
|
13
13
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid cart input");
|
|
@@ -17,7 +17,7 @@ export async function addToCartAction(input) {
|
|
|
17
17
|
}
|
|
18
18
|
export async function removeFromCartAction(input) {
|
|
19
19
|
return wrapAction(async () => {
|
|
20
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
20
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
21
21
|
const parsed = removeFromCartSchema.safeParse(input);
|
|
22
22
|
if (!parsed.success)
|
|
23
23
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid input");
|
|
@@ -27,14 +27,14 @@ export async function removeFromCartAction(input) {
|
|
|
27
27
|
}
|
|
28
28
|
export async function clearCartAction() {
|
|
29
29
|
return wrapAction(async () => {
|
|
30
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
30
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
31
31
|
await cartRepository.clearCart(user.uid);
|
|
32
32
|
return { success: true };
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
35
|
export async function mergeGuestCartAction(input) {
|
|
36
36
|
return wrapAction(async () => {
|
|
37
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
37
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
38
38
|
const parsed = mergeGuestCartSchema.safeParse(input);
|
|
39
39
|
if (!parsed.success)
|
|
40
40
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid cart data");
|
|
@@ -36,7 +36,7 @@ export async function updateEventAction(eventId, input) {
|
|
|
36
36
|
}
|
|
37
37
|
export async function registerForEventAction(input) {
|
|
38
38
|
return wrapAction(async () => {
|
|
39
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
39
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
40
40
|
const parsed = registerForEventSchema.safeParse(input);
|
|
41
41
|
if (!parsed.success)
|
|
42
42
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid registration input");
|
|
@@ -72,7 +72,7 @@ export async function registerForEventAction(input) {
|
|
|
72
72
|
}
|
|
73
73
|
export async function cancelEventRegistrationAction(entryId) {
|
|
74
74
|
return wrapAction(async () => {
|
|
75
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
75
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
76
76
|
const entry = await eventEntryRepository.findById(entryId);
|
|
77
77
|
if (!entry || entry.userId !== user.uid) {
|
|
78
78
|
throw new ValidationError("Registration not found or does not belong to you");
|
|
@@ -4,7 +4,7 @@ import { requireRoleUser } from "../../../../providers/auth-firebase/helpers";
|
|
|
4
4
|
import { historyRepository, } from "../../../../repositories";
|
|
5
5
|
export async function trackProductViewAction(productId, productType, productSnapshot) {
|
|
6
6
|
return wrapAction(async () => {
|
|
7
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
7
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
8
8
|
await historyRepository.track(user.uid, {
|
|
9
9
|
productId,
|
|
10
10
|
productType,
|
|
@@ -14,7 +14,7 @@ export async function trackProductViewAction(productId, productType, productSnap
|
|
|
14
14
|
}
|
|
15
15
|
export async function mergeGuestHistoryAction(guestItems) {
|
|
16
16
|
return wrapAction(async () => {
|
|
17
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
17
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
18
18
|
return historyRepository.merge(user.uid, guestItems);
|
|
19
19
|
});
|
|
20
20
|
}
|
|
@@ -28,7 +28,7 @@ function isDrawWindowOpen(config) {
|
|
|
28
28
|
export async function submitLotteryPullAction(input) {
|
|
29
29
|
return wrapAction(async () => {
|
|
30
30
|
// Auth — must be logged in
|
|
31
|
-
const user = await requireRoleUser(["buyer", "seller", "admin", "moderator", "employee"]);
|
|
31
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin", "moderator", "employee"]);
|
|
32
32
|
const parsed = submitLotteryPullSchema.safeParse(input);
|
|
33
33
|
if (!parsed.success) {
|
|
34
34
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid lottery pull input");
|
|
@@ -18,7 +18,7 @@ import { normalizeError } from "../../../../errors/normalize";
|
|
|
18
18
|
import { serverLogger } from "../../../../monitoring";
|
|
19
19
|
export async function createOrderAction(input) {
|
|
20
20
|
return wrapAction(async () => {
|
|
21
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
21
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
22
22
|
const parsed = createOrderSchema.safeParse(input);
|
|
23
23
|
if (!parsed.success)
|
|
24
24
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid order input");
|
|
@@ -31,7 +31,7 @@ export async function createOrderAction(input) {
|
|
|
31
31
|
}
|
|
32
32
|
export async function cancelOrderAction(input) {
|
|
33
33
|
return wrapAction(async () => {
|
|
34
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
34
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
35
35
|
const parsed = cancelOrderSchema.safeParse(input);
|
|
36
36
|
if (!parsed.success)
|
|
37
37
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid input");
|
|
@@ -50,7 +50,7 @@ export async function cancelOrderAction(input) {
|
|
|
50
50
|
*/
|
|
51
51
|
export async function requestReturnAction(input) {
|
|
52
52
|
return wrapAction(async () => {
|
|
53
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
53
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
54
54
|
const parsed = returnRequestSchema.safeParse(input);
|
|
55
55
|
if (!parsed.success)
|
|
56
56
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid input");
|
|
@@ -161,7 +161,7 @@ function notifyAdminsOfPaymentProof(order) {
|
|
|
161
161
|
}
|
|
162
162
|
export async function attachPaymentProofAction(orderId, proof) {
|
|
163
163
|
return wrapAction(async () => {
|
|
164
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
164
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
165
165
|
const order = await orderRepository.findById(orderId);
|
|
166
166
|
if (!order)
|
|
167
167
|
throw new OrderNotFoundError(orderId);
|
|
@@ -350,7 +350,7 @@ export async function adminRejectPaymentAsFraudAction(orderId, note) {
|
|
|
350
350
|
*/
|
|
351
351
|
export async function raiseOrderDisputeAction(orderId, reason) {
|
|
352
352
|
return wrapAction(async () => {
|
|
353
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
353
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
354
354
|
if (!reason.trim())
|
|
355
355
|
throw new ValidationError(REASON_REQUIRED_MSG);
|
|
356
356
|
const order = await orderRepository.findById(orderId);
|
|
@@ -7,7 +7,7 @@ import { assertPreOrderAvailable, computeDeposit } from "./service";
|
|
|
7
7
|
import { ValidationError } from "../../../shared/errors/index";
|
|
8
8
|
export async function reservePreOrderAction(input) {
|
|
9
9
|
return wrapAction(async () => {
|
|
10
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
10
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
11
11
|
const parsed = reservePreOrderSchema.safeParse(input);
|
|
12
12
|
if (!parsed.success)
|
|
13
13
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid reservation input");
|
|
@@ -9,7 +9,7 @@ import { ValidationError } from "../../../shared/errors/index";
|
|
|
9
9
|
const ERR_INVALID_COUPON_INPUT = "Invalid coupon input";
|
|
10
10
|
export async function applyCouponAction(input) {
|
|
11
11
|
return wrapAction(async () => {
|
|
12
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
12
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
13
13
|
const parsed = applyCouponSchema.safeParse(input);
|
|
14
14
|
if (!parsed.success)
|
|
15
15
|
throw new ValidationError(parsed.error.issues[0]?.message ?? ERR_INVALID_COUPON_INPUT);
|
|
@@ -8,7 +8,7 @@ import { createReviewSchema, replyToReviewSchema, deleteReviewSchema, } from "..
|
|
|
8
8
|
import { assertNotDuplicateReview, assertReviewOwnership, getReviewOrThrow, } from "./service";
|
|
9
9
|
export async function createReviewAction(input) {
|
|
10
10
|
return wrapAction(async () => {
|
|
11
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
11
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
12
12
|
const parsed = createReviewSchema.safeParse(input);
|
|
13
13
|
if (!parsed.success) {
|
|
14
14
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid input");
|
|
@@ -54,7 +54,7 @@ export async function replyToReviewAction(input) {
|
|
|
54
54
|
}
|
|
55
55
|
export async function deleteReviewAction(input) {
|
|
56
56
|
return wrapAction(async () => {
|
|
57
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
57
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
58
58
|
const parsed = deleteReviewSchema.safeParse(input);
|
|
59
59
|
if (!parsed.success) {
|
|
60
60
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid input");
|
|
@@ -71,7 +71,7 @@ export async function deleteReviewAction(input) {
|
|
|
71
71
|
}
|
|
72
72
|
export async function markReviewHelpfulAction(reviewId) {
|
|
73
73
|
return wrapAction(async () => {
|
|
74
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
74
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
75
75
|
await getReviewOrThrow(reviewId);
|
|
76
76
|
// Keyed on the voter so a repeated call is a no-op rather than another +1.
|
|
77
77
|
return reviewRepository.voteHelpful(reviewId, user.uid);
|
|
@@ -7,7 +7,7 @@ import { WISHLIST_MAX } from "../../../shared/features/wishlist/config";
|
|
|
7
7
|
import { WishlistCapError } from "../../../shared/features/wishlist/errors";
|
|
8
8
|
export async function addToWishlistAction(productId, extras) {
|
|
9
9
|
return wrapAction(async () => {
|
|
10
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
10
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
11
11
|
try {
|
|
12
12
|
return await wishlistRepository.addItem(user.uid, productId, extras);
|
|
13
13
|
}
|
|
@@ -21,13 +21,13 @@ export async function addToWishlistAction(productId, extras) {
|
|
|
21
21
|
}
|
|
22
22
|
export async function removeFromWishlistAction(productId) {
|
|
23
23
|
return wrapAction(async () => {
|
|
24
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
24
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
25
25
|
await wishlistRepository.removeItem(user.uid, productId);
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
export async function mergeGuestWishlistAction(guestItems) {
|
|
29
29
|
return wrapAction(async () => {
|
|
30
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
30
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
31
31
|
const merged = [];
|
|
32
32
|
for (const item of guestItems) {
|
|
33
33
|
try {
|
|
@@ -26,6 +26,8 @@ interface FAQPageContentProps {
|
|
|
26
26
|
resultCount: (count: number) => string;
|
|
27
27
|
inCategory: (categoryLabel: string) => string;
|
|
28
28
|
loading: string;
|
|
29
|
+
emptyTitle?: string;
|
|
30
|
+
emptyDescription?: string;
|
|
29
31
|
contactTitle: string;
|
|
30
32
|
contactDescription: string;
|
|
31
33
|
contactEmailUs: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { Alert, Div, Heading, Input, SlottedListingView, Text } from "../../../ui";
|
|
3
|
+
import { Alert, Div, EmptyState, Heading, Input, SlottedListingView, Text } from "../../../ui";
|
|
4
4
|
import { sortBy } from "../../../constants/sort";
|
|
5
5
|
import { FAQCategorySidebar } from "./FAQCategorySidebar";
|
|
6
6
|
import { FAQSortDropdown } from "./FAQSortDropdown";
|
|
@@ -69,7 +69,24 @@ export function FAQPageContent({ initialCategory = "all", categories, routeHelpe
|
|
|
69
69
|
* Saying so costs nothing and makes the next index gap
|
|
70
70
|
* self-reporting rather than a phantom empty state.
|
|
71
71
|
*/
|
|
72
|
-
_jsx(Alert, { variant: "error", title: "Couldn't load questions", children: "Something went wrong fetching these FAQs. Try a different sort or reload the page." })) :
|
|
72
|
+
_jsx(Alert, { variant: "error", title: "Couldn't load questions", children: "Something went wrong fetching these FAQs. Try a different sort or reload the page." })) : faqs.length === 0 ? (
|
|
73
|
+
/*
|
|
74
|
+
* 🛑 AN EXPLICIT EMPTY BRANCH — without it the page rendered a
|
|
75
|
+
* BARE WHITE AREA.
|
|
76
|
+
*
|
|
77
|
+
* The chain fell through to <FAQAccordion faqs={[]} />, which
|
|
78
|
+
* renders nothing at all. Measured on /faqs?q=zzzznope: the
|
|
79
|
+
* page showed "0 questions", the search box, a divider, and
|
|
80
|
+
* then blank space — no message anywhere in the DOM.
|
|
81
|
+
*
|
|
82
|
+
* A blank region is the worst possible answer here because it
|
|
83
|
+
* is indistinguishable from a page that failed to load, which
|
|
84
|
+
* is exactly the confusion the isError branch above exists to
|
|
85
|
+
* prevent. Three states, three distinct renderings: loading,
|
|
86
|
+
* failed, and genuinely nothing found.
|
|
87
|
+
*/
|
|
88
|
+
_jsx(EmptyState, { title: labels.emptyTitle ?? "No questions found", description: labels.emptyDescription ??
|
|
89
|
+
"Try a different search term, or pick another category from the list." })) : renderAccordion ? (renderAccordion(faqs)) : (_jsx(FAQAccordion, { faqs: faqs })), renderPagination: () => renderPagination?.(total) ?? null, total: total, isLoading: isLoading }), faqs.length > 0 ? (_jsx(Div, { className: "mt-12", children: _jsx(ContactCTA, { email: contact.email, phone: contact.phone, contactHref: routeHelpers.contactHref, labels: {
|
|
73
90
|
title: labels.contactTitle,
|
|
74
91
|
description: labels.contactDescription,
|
|
75
92
|
emailUs: labels.contactEmailUs,
|
|
@@ -55,8 +55,32 @@ export function AnnouncementBar({ message, link, className = "", onDismiss, over
|
|
|
55
55
|
}, [message, userAlreadyDismissed]);
|
|
56
56
|
if (dismissed)
|
|
57
57
|
return null;
|
|
58
|
+
/*
|
|
59
|
+
* 🛑 THE OVERLAY IS md AND UP ONLY — IT PAINTED OVER THE HERO HEADING ON
|
|
60
|
+
* EVERY PHONE WIDTH.
|
|
61
|
+
*
|
|
62
|
+
* `absolute` reserves no space, which is the whole point of the overlay: the
|
|
63
|
+
* hero's own top padding is sized to sit a ONE-LINE banner over it. A real
|
|
64
|
+
* announcement wraps on a narrow screen, grows downward, and there is
|
|
65
|
+
* nothing to stop it.
|
|
66
|
+
*
|
|
67
|
+
* Measured on production against the live announcement, against the <h1>:
|
|
68
|
+
*
|
|
69
|
+
* 320px → 30px overlap 768px → 10px clear
|
|
70
|
+
* 390px → 10px overlap 1280px → 10px clear
|
|
71
|
+
* 430px → 10px overlap
|
|
72
|
+
*
|
|
73
|
+
* So it was every phone width and no tablet or desktop width — which is why
|
|
74
|
+
* it survived: the breakpoints people check it at are the ones where the
|
|
75
|
+
* message still fits on one line.
|
|
76
|
+
*
|
|
77
|
+
* Below `md` it is an ordinary in-flow bar that pushes the hero down, with a
|
|
78
|
+
* SOLID background (the translucent + blur treatment only reads as
|
|
79
|
+
* deliberate when there is artwork behind it). From `md` up, the designed
|
|
80
|
+
* overlay is unchanged.
|
|
81
|
+
*/
|
|
58
82
|
const positionCls = overlay
|
|
59
|
-
? "absolute inset-x-0 top-0 z-20 bg-primary-700/85 backdrop-blur-sm"
|
|
83
|
+
? "relative md:absolute inset-x-0 top-0 z-20 bg-primary-700 md:bg-primary-700/85 md:backdrop-blur-sm"
|
|
60
84
|
: "relative left-1/2 right-1/2 w-screen -translate-x-1/2 bg-primary-700";
|
|
61
85
|
return (_jsx(Div, { className: `${positionCls} transition-opacity duration-200 ${mounted ? "opacity-100" : "opacity-0"} ${className}`, role: "banner", children: _jsx(Div, { paddingX: "x-page", className: "container mx-auto max-w-[1920px]", children: _jsxs(Row, { textWeight: "medium", textSize: "sm", className: "relative text-left text-white", padding: "y-xs", align: "center", justify: "start", children: [link ? (_jsx(TextLink, { href: link, className: "text-white underline", children: message })) : (_jsx(Span, { children: message })), _jsx(IconButton, { type: "button", onClick: () => {
|
|
62
86
|
saveLocalDismissal(message);
|
|
@@ -73,15 +73,29 @@ export const authored = {
|
|
|
73
73
|
roles: ["buyer"],
|
|
74
74
|
startPage: "/user/orders",
|
|
75
75
|
steps: [
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
/*
|
|
77
|
+
* 🛑 rehan, NOT vivaan — and the order changed with it.
|
|
78
|
+
*
|
|
79
|
+
* This said vivaan.kapoor@gmail.com (user-seto-kaiba), who does own
|
|
80
|
+
* order-1-20251107-11joon. But TWO other cases in this same batch use
|
|
81
|
+
* that order as a FOREIGN one, and a batch browses as exactly one
|
|
82
|
+
* identity — so the page could not be worked as authored: the same
|
|
83
|
+
* order had to be both owned and not-owned by the signed-in user.
|
|
84
|
+
*
|
|
85
|
+
* rehan.sheikh@gmail.com (user-yugi-muto) is the harness's `main`
|
|
86
|
+
* identity, and order-1-20260818-stdctx is one of its delivered orders.
|
|
87
|
+
* That makes the whole batch coherent under one session and leaves the
|
|
88
|
+
* access-control cases genuinely foreign.
|
|
89
|
+
*/
|
|
90
|
+
"Sign in as rehan.sheikh@gmail.com / TempPass123! — this persona owns the order below, and a return can only be requested on a delivered one.",
|
|
91
|
+
"Open /user/orders and open order-1-20260818-stdctx, which is delivered.",
|
|
78
92
|
"Use the Return action.",
|
|
79
93
|
"Give the reason: item not as described.",
|
|
80
94
|
"Submit the request.",
|
|
81
95
|
"Reload the order.",
|
|
82
96
|
"Open /user/returns and look for it.",
|
|
83
97
|
],
|
|
84
|
-
inputs: { orderId: "order-1-
|
|
98
|
+
inputs: { orderId: "order-1-20260818-stdctx", reason: "item not as described" },
|
|
85
99
|
expectedBehaviour: "A return request moves the order into Return Requested and appears on the returns surface. That status is deliberately an ACTIVE one — it is the seller's next action item, not a closed state — so the order must not disappear from the active list.",
|
|
86
100
|
expectedUiState: "The order's status reads Return Requested, and the same order is listed under /user/returns.",
|
|
87
101
|
expectedData: { statusAfterReturn: "return_requested" },
|
|
@@ -545,7 +545,25 @@ const acquisitionOrders = [
|
|
|
545
545
|
shippingCarrier: "Delhivery",
|
|
546
546
|
orderDate: daysAgo(12),
|
|
547
547
|
shippingDate: daysAgo(9),
|
|
548
|
-
|
|
548
|
+
/*
|
|
549
|
+
* 🛑 TWO DAYS, NOT SIX — THIS IS THE RETURN-WINDOW FIXTURE.
|
|
550
|
+
*
|
|
551
|
+
* A return can only be requested on a DELIVERED order inside the 7-day
|
|
552
|
+
* window, and you cannot reach "delivered" by buying in a test: it needs
|
|
553
|
+
* seller action. So the return flow is testable only if a seeded delivered
|
|
554
|
+
* order sits inside the window — and until now none did for the harness's
|
|
555
|
+
* own identity. Every candidate was 6, 7, 8, 20, 29 days old, so
|
|
556
|
+
* /user/orders/{id}/return answered 'The 7-day return window for this
|
|
557
|
+
* order has closed.' and the case could never be worked.
|
|
558
|
+
*
|
|
559
|
+
* Six days would have been inside the window today and OUTSIDE it
|
|
560
|
+
* tomorrow — a fixture that passes on Monday and fails on Tuesday is worse
|
|
561
|
+
* than one that always fails, because the failure looks like a regression.
|
|
562
|
+
* Two days leaves five days of margin.
|
|
563
|
+
*
|
|
564
|
+
* Do not raise this without checking RETURN_WINDOW_DAYS.
|
|
565
|
+
*/
|
|
566
|
+
deliveryDate: daysAgo(2),
|
|
549
567
|
createdAt: daysAgo(12),
|
|
550
568
|
updatedAt: daysAgo(6),
|
|
551
569
|
sourceContext: { path: "standard", listPrice: 999 },
|