Skip to content

Commit 419353a

Browse files
committed
Merge branch 'fix/new-availability-logic' into fix/availability-doctor-copy-pass
2 parents 7db5f84 + aa224ec commit 419353a

13 files changed

Lines changed: 337 additions & 97 deletions

locale/defaultMessages.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,10 @@
192192
"context": "expired on label",
193193
"string": "Expired on {date}"
194194
},
195+
"/0QqzO": {
196+
"context": "aria-label for the warning icon inside a channel issue badge",
197+
"string": "Warning"
198+
},
195199
"/0gMCW": {
196200
"string": "Try to refresh the page or go navigate to a different page and back."
197201
},
@@ -7330,6 +7334,10 @@
73307334
"cY42ht": {
73317335
"string": "Password cannot be entirely numeric"
73327336
},
7337+
"cYjzDx": {
7338+
"context": "aria-label for the info icon inside an availability issue callout",
7339+
"string": "Information"
7340+
},
73337341
"cZN5Jd": {
73347342
"context": "Webhook details events",
73357343
"string": "Events"
@@ -7622,6 +7630,10 @@
76227630
"context": "button",
76237631
"string": "Choose file"
76247632
},
7633+
"eXcTEd": {
7634+
"context": "aria-label for the error icon inside an availability issue callout",
7635+
"string": "Error"
7636+
},
76257637
"eY+BKQ": {
76267638
"string": "The extension manifest was not found. ({errorCode})"
76277639
},
@@ -8216,6 +8228,10 @@
82168228
"context": "button",
82178229
"string": "Apply"
82188230
},
8231+
"iBY7aI": {
8232+
"context": "aria-label for the warning icon inside an availability issue callout",
8233+
"string": "Warning"
8234+
},
82198235
"iEeIhY": {
82208236
"context": "draft order",
82218237
"string": "Customer"
@@ -8728,6 +8744,10 @@
87288744
"context": "btn label",
87298745
"string": "Go to orders"
87308746
},
8747+
"kyOwDW": {
8748+
"context": "aria-label for the error icon inside a channel issue badge",
8749+
"string": "Error"
8750+
},
87318751
"l0a2tU": {
87328752
"context": "onboarding step description",
87338753
"string": "Go to all products from where you can create a new product and view it in all product list. View the product in GraphQL"

src/products/components/ProductDoctor/AvailabilityCard.test.tsx

Lines changed: 53 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Wrapper from "@test/wrapper";
2-
import { fireEvent, render, screen } from "@testing-library/react";
2+
import { fireEvent, render, screen, within } from "@testing-library/react";
33

44
import { AvailabilityCard, PublicApiVerificationBadge } from "./AvailabilityCard";
55
import { type ChannelVerificationResult } from "./hooks/usePublicApiVerification";
@@ -50,7 +50,7 @@ const baseDiagnostics = (overrides: Partial<DiagnosticsResult> = {}): Diagnostic
5050
});
5151

5252
describe("AvailabilityCard / StockAvailabilityModeIndicator", () => {
53-
it("renders the legacy mode indicator when shop uses shipping-zone stock availability", () => {
53+
it("renders the legacy mode label when shop uses shipping-zone stock availability", () => {
5454
// Arrange
5555
const diagnostics = baseDiagnostics({ useLegacyShippingZoneStockAvailability: true });
5656

@@ -59,14 +59,12 @@ describe("AvailabilityCard / StockAvailabilityModeIndicator", () => {
5959
wrapper: Wrapper,
6060
});
6161

62-
// Assert
63-
const indicator = screen.getByTestId("stock-availability-mode-indicator");
64-
65-
expect(indicator).toHaveAttribute("data-test-mode", "legacy");
66-
expect(indicator).toHaveTextContent(/legacy/i);
62+
// Assert — mode is communicated to the user via visible copy.
63+
expect(screen.getByText(/uses shipping zones \(legacy\)/i)).toBeInTheDocument();
64+
expect(screen.queryByText(/direct warehouse-channel/i)).toBeNull();
6765
});
6866

69-
it("renders the direct mode indicator when shop uses direct warehouse-channel link", () => {
67+
it("renders the direct mode label when shop uses the direct warehouse-channel link", () => {
7068
// Arrange
7169
const diagnostics = baseDiagnostics({ useLegacyShippingZoneStockAvailability: false });
7270

@@ -76,10 +74,8 @@ describe("AvailabilityCard / StockAvailabilityModeIndicator", () => {
7674
});
7775

7876
// Assert
79-
const indicator = screen.getByTestId("stock-availability-mode-indicator");
80-
81-
expect(indicator).toHaveAttribute("data-test-mode", "direct");
82-
expect(indicator).toHaveTextContent(/direct warehouse-channel/i);
77+
expect(screen.getByText(/direct warehouse-channel/i)).toBeInTheDocument();
78+
expect(screen.queryByText(/uses shipping zones \(legacy\)/i)).toBeNull();
8379
});
8480

8581
it("does not render the indicator while diagnostics are loading", () => {
@@ -91,8 +87,9 @@ describe("AvailabilityCard / StockAvailabilityModeIndicator", () => {
9187
wrapper: Wrapper,
9288
});
9389

94-
// Assert - indicator only renders when channels list is shown
95-
expect(screen.queryByTestId("stock-availability-mode-indicator")).toBeNull();
90+
// Assert — neither label is rendered (indicator shows only with the channels list).
91+
expect(screen.queryByText(/uses shipping zones \(legacy\)/i)).toBeNull();
92+
expect(screen.queryByText(/direct warehouse-channel/i)).toBeNull();
9693
});
9794
});
9895

@@ -106,9 +103,18 @@ const makeIssue = (overrides: Partial<AvailabilityIssue> = {}): AvailabilityIssu
106103
...overrides,
107104
});
108105

106+
/**
107+
* Channel header severity gating — these tests assert what the user actually
108+
* sees: which icon is rendered (queried by accessible name), whether a count
109+
* number is visible, and whether the badge appears at all.
110+
*
111+
* The pure selection/escalation logic that drives the props is unit-tested
112+
* separately in `utils/issueBadge.test.ts`; here we only verify the
113+
* UI consequences.
114+
*/
109115
describe("AvailabilityCard channel header severity gating", () => {
110-
it("does not promote info-only issues into the channel issue badge", () => {
111-
// Arrange - direct mode, single info advisory (e.g. no shipping zones)
116+
it("does not render the issue badge for info-only advisories", () => {
117+
// Arrange direct mode, single info advisory.
112118
const diagnostics = baseDiagnostics({
113119
useLegacyShippingZoneStockAvailability: false,
114120
issues: [makeIssue({ severity: "info" })],
@@ -121,19 +127,20 @@ describe("AvailabilityCard channel header severity gating", () => {
121127
wrapper: Wrapper,
122128
});
123129

124-
// Assert - no IssueBadge in the header
130+
// Assert no IssueBadge in the header.
125131
expect(screen.queryByTestId("channel-issue-badge")).toBeNull();
126132

127-
// Expand the channel accordion to inspect the issue callout in the body
133+
// Expand the channel accordion and verify the info-style icon is rendered
134+
// for the issue callout (this is what the user perceives — Info icon
135+
// rather than warning/error iconography).
128136
fireEvent.click(screen.getByText("Default Channel"));
129137

130-
const callout = screen.getByTestId("availability-issue-callout");
131-
132-
expect(callout).toHaveAttribute("data-test-severity", "info");
138+
expect(screen.getByTestId("product-doctor-issue-callout-icon-info")).toBeInTheDocument();
139+
expect(screen.getByLabelText("Information")).toBeInTheDocument();
133140
});
134141

135-
it("still surfaces warnings via the channel issue badge", () => {
136-
// Arrange - legacy mode, warning-level issue
142+
it("surfaces a single warning via the channel issue badge with no visible count", () => {
143+
// Arrange legacy mode, one warning-level issue.
137144
const diagnostics = baseDiagnostics({
138145
useLegacyShippingZoneStockAvailability: true,
139146
issues: [makeIssue({ id: "no-stock", severity: "warning", message: "No stock" })],
@@ -146,19 +153,25 @@ describe("AvailabilityCard channel header severity gating", () => {
146153
wrapper: Wrapper,
147154
});
148155

149-
// Assert
156+
// Assert — the warning icon is shown inside the badge…
150157
const badge = screen.getByTestId("channel-issue-badge");
151158

152-
expect(badge).toHaveAttribute("data-test-type", "warning");
153-
expect(badge).toHaveAttribute("data-test-count", "1");
159+
expect(
160+
within(badge).getByTestId("product-doctor-issue-badge-icon-warning"),
161+
).toBeInTheDocument();
162+
// …no error icon is shown…
163+
expect(within(badge).queryByTestId("product-doctor-issue-badge-icon-error")).toBeNull();
164+
// …and there is no visible count number (count text only renders for >1).
165+
expect(within(badge).queryByTestId("product-doctor-issue-badge-count")).toBeNull();
154166
});
155167

156-
it("counts only blocking issues in the channel issue badge when info issues co-exist", () => {
157-
// Arrange - one warning, two info advisories on the same channel
168+
it("renders a visible count and the warning icon when multiple header-worthy issues exist alongside info advisories", () => {
169+
// Arrange — two warnings + two info advisories on the same channel.
158170
const diagnostics = baseDiagnostics({
159171
useLegacyShippingZoneStockAvailability: false,
160172
issues: [
161173
makeIssue({ id: "no-stock", severity: "warning", message: "No stock" }),
174+
makeIssue({ id: "no-warehouses", severity: "warning", message: "No warehouses" }),
162175
makeIssue({ id: "no-shipping-zones", severity: "info", message: "No shipping zones" }),
163176
makeIssue({
164177
id: "stock-outside-channel-warehouses",
@@ -175,15 +188,17 @@ describe("AvailabilityCard channel header severity gating", () => {
175188
wrapper: Wrapper,
176189
});
177190

178-
// Assert - badge count reflects the single blocking issue only
191+
// Assert — visible count reflects the two header-worthy issues only.
179192
const badge = screen.getByTestId("channel-issue-badge");
180193

181-
expect(badge).toHaveAttribute("data-test-count", "1");
182-
expect(badge).toHaveAttribute("data-test-type", "warning");
194+
expect(within(badge).getByTestId("product-doctor-issue-badge-count")).toHaveTextContent("2");
195+
expect(
196+
within(badge).getByTestId("product-doctor-issue-badge-icon-warning"),
197+
).toBeInTheDocument();
183198
});
184199

185-
it("escalates to error styling when at least one issue is an error", () => {
186-
// Arrange - mix of error and warning, plus info
200+
it("renders the error icon when at least one header issue is an error", () => {
201+
// Arrange error + warning + info.
187202
const diagnostics = baseDiagnostics({
188203
useLegacyShippingZoneStockAvailability: true,
189204
issues: [
@@ -200,11 +215,13 @@ describe("AvailabilityCard channel header severity gating", () => {
200215
wrapper: Wrapper,
201216
});
202217

203-
// Assert - badge type prefers error severity, count is the blocking total
218+
// Assert error icon appears, warning icon does not.
204219
const badge = screen.getByTestId("channel-issue-badge");
205220

206-
expect(badge).toHaveAttribute("data-test-type", "error");
207-
expect(badge).toHaveAttribute("data-test-count", "2");
221+
expect(within(badge).getByTestId("product-doctor-issue-badge-icon-error")).toBeInTheDocument();
222+
expect(within(badge).queryByTestId("product-doctor-issue-badge-icon-warning")).toBeNull();
223+
// Visible count covers the two header-worthy issues (the info advisory is excluded).
224+
expect(within(badge).getByTestId("product-doctor-issue-badge-count")).toHaveTextContent("2");
208225
});
209226
});
210227

src/products/components/ProductDoctor/AvailabilityCard.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,6 @@ const StockAvailabilityModeIndicator = ({
457457
gap={2}
458458
__cursor="help"
459459
data-test-id="stock-availability-mode-indicator"
460-
data-test-mode={useLegacyShippingZoneStockAvailability ? "legacy" : "direct"}
461460
>
462461
<Layers size={14} color="var(--mu-colors-text-default2)" />
463462
<Text size={2} color="default2">

0 commit comments

Comments
 (0)