summaryrefslogtreecommitdiffstats
path: root/browser/components/storybook/stories/shopping-container.stories.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/storybook/stories/shopping-container.stories.mjs')
-rw-r--r--browser/components/storybook/stories/shopping-container.stories.mjs301
1 files changed, 301 insertions, 0 deletions
diff --git a/browser/components/storybook/stories/shopping-container.stories.mjs b/browser/components/storybook/stories/shopping-container.stories.mjs
new file mode 100644
index 0000000000..79ade4222e
--- /dev/null
+++ b/browser/components/storybook/stories/shopping-container.stories.mjs
@@ -0,0 +1,301 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// eslint-disable-next-line import/no-unresolved
+import { html, ifDefined } from "lit.all.mjs";
+// eslint-disable-next-line import/no-unassigned-import
+import "browser/components/shopping/content/shopping-container.mjs";
+// Bug 1845737: These should get imported by ShoppingMessageBar
+window.MozXULElement.insertFTLIfNeeded("browser/shopping.ftl");
+window.MozXULElement.insertFTLIfNeeded("toolkit/branding/brandings.ftl");
+// Mock for Glean
+if (typeof window.Glean == "undefined") {
+ window.Glean = new Proxy(() => {}, { get: () => window.Glean });
+}
+
+export default {
+ title: "Domain-specific UI Widgets/Shopping/Shopping Container",
+ component: "shopping-container",
+ parameters: {
+ status: "in-development",
+ },
+};
+
+const MOCK_HIGHLIGHTS = {
+ price: {
+ positive: ["This watch is great and the price was even better."],
+ negative: [],
+ neutral: [],
+ },
+ quality: {
+ positive: [
+ "Other than that, I am very impressed with the watch and it’s capabilities.",
+ "This watch performs above expectations in every way with the exception of the heart rate monitor.",
+ ],
+ negative: [
+ "Battery life is no better than the 3 even with the solar gimmick, probably worse.",
+ ],
+ neutral: [
+ "I have small wrists and still went with the 6X and glad I did.",
+ "I can deal with the looks, as Im now retired.",
+ ],
+ },
+ competitiveness: {
+ positive: [
+ "Bought this to replace my vivoactive 3.",
+ "I like that this watch has so many features, especially those that monitor health like SP02, respiration, sleep, HRV status, stress, and heart rate.",
+ ],
+ negative: [
+ "I do not use it for sleep or heartrate monitoring so not sure how accurate they are.",
+ ],
+ neutral: [
+ "I've avoided getting a smartwatch for so long due to short battery life on most of them.",
+ ],
+ },
+ "packaging/appearance": {
+ positive: ["Great cardboard box."],
+ negative: [],
+ neutral: [],
+ },
+ shipping: {
+ positive: [],
+ negative: [],
+ neutral: [],
+ },
+};
+
+const MOCK_RECOMMENDED_ADS = [
+ {
+ name: "VIVO Electric 60 x 24 inch Stand Up Desk | Black Table Top, Black Frame, Height Adjustable Standing Workstation with Memory Preset Controller (DESK-KIT-1B6B)",
+ url: "www.example.com",
+ price: "249.99",
+ currency: "USD",
+ grade: "A",
+ adjusted_rating: 4.6,
+ sponsored: true,
+ image_blob: new Blob(new Uint8Array(), { type: "image/jpeg" }),
+ },
+];
+
+const Template = ({
+ data,
+ isOffline,
+ isAnalysisInProgress,
+ analysisEvent,
+ productUrl,
+ userReportedAvailable,
+ adsEnabled,
+ adsEnabledByUser,
+ recommendationData,
+ analysisProgress,
+}) => html`
+ <style>
+ main {
+ /**
+ --shopping-header-background and sidebar background-color should
+ come from shopping.page.css, but they are not loaded when
+ viewing the sidebar in Storybook. Hardcode them here
+ */
+ --shopping-header-background: light-dark(#f9f9fb, #2b2a33);
+ background-color: var(--shopping-header-background);
+ width: 320px;
+ }
+ </style>
+
+ <main>
+ <shopping-container
+ .data=${data}
+ ?isOffline=${isOffline}
+ ?isAnalysisInProgress=${isAnalysisInProgress}
+ .analysisEvent=${analysisEvent}
+ productUrl=${ifDefined(productUrl)}
+ ?userReportedAvailable=${userReportedAvailable}
+ ?adsEnabled=${adsEnabled}
+ ?adsEnabledByUser=${adsEnabledByUser}
+ .recommendationData=${recommendationData}
+ analysisProgress=${analysisProgress}
+ >
+ </shopping-container>
+ </main>
+`;
+
+export const DefaultShoppingContainer = Template.bind({});
+DefaultShoppingContainer.args = {
+ data: {
+ product_id: "ABCD123",
+ needs_analysis: false,
+ adjusted_rating: 5,
+ grade: "B",
+ highlights: MOCK_HIGHLIGHTS,
+ },
+};
+
+export const NoHighlights = Template.bind({});
+NoHighlights.args = {
+ data: {
+ product_id: "ABCD123",
+ needs_analysis: false,
+ adjusted_rating: 5,
+ grade: "B",
+ },
+};
+
+/**
+ * There will be no animation if prefers-reduced-motion is enabled.
+ */
+export const Loading = Template.bind({});
+
+export const UnanalyzedProduct = Template.bind({});
+UnanalyzedProduct.args = {
+ data: {
+ adjusted_rating: null,
+ grade: null,
+ highlights: null,
+ product_id: null,
+ needs_analysis: true,
+ },
+};
+
+export const NewAnalysisInProgress = Template.bind({});
+NewAnalysisInProgress.args = {
+ isAnalysisInProgress: true,
+ analysisProgress: 15,
+};
+
+export const StaleProduct = Template.bind({});
+StaleProduct.args = {
+ data: {
+ product_id: "ABCD123",
+ needs_analysis: true,
+ adjusted_rating: 5,
+ grade: "B",
+ highlights: MOCK_HIGHLIGHTS,
+ },
+};
+
+export const ReanalysisInProgress = Template.bind({});
+ReanalysisInProgress.args = {
+ data: {
+ product_id: "ABCD123",
+ needs_analysis: true,
+ adjusted_rating: 5,
+ grade: "B",
+ highlights: MOCK_HIGHLIGHTS,
+ },
+ isAnalysisInProgress: true,
+ analysisProgress: 15,
+ analysisEvent: {
+ type: "ReanalysisRequested",
+ productUrl: "https://example.com/ABCD123",
+ },
+ productUrl: "https://example.com/ABCD123",
+};
+
+/**
+ * When ad functionality is enabled and the user wants the ad
+ * component visible.
+ */
+export const AdVisibleByUser = Template.bind({});
+AdVisibleByUser.args = {
+ data: {
+ product_id: "ABCD123",
+ needs_analysis: false,
+ adjusted_rating: 5,
+ grade: "B",
+ highlights: MOCK_HIGHLIGHTS,
+ },
+ adsEnabled: true,
+ adsEnabledByUser: true,
+ recommendationData: MOCK_RECOMMENDED_ADS,
+};
+
+/**
+ * When ad functionality is enabled, but the user wants the ad
+ * component hidden.
+ */
+export const AdHiddenByUser = Template.bind({});
+AdHiddenByUser.args = {
+ data: {
+ product_id: "ABCD123",
+ needs_analysis: false,
+ adjusted_rating: 5,
+ grade: "B",
+ highlights: MOCK_HIGHLIGHTS,
+ },
+ adsEnabled: true,
+ adsEnabledByUser: false,
+ recommendationData: MOCK_RECOMMENDED_ADS,
+};
+
+export const NotEnoughReviews = Template.bind({});
+NotEnoughReviews.args = {
+ data: {
+ adjusted_rating: null,
+ grade: null,
+ highlights: null,
+ product_id: "ABCD123",
+ needs_analysis: true,
+ },
+};
+
+export const ProductNotAvailable = Template.bind({});
+ProductNotAvailable.args = {
+ data: {
+ deleted_product: true,
+ product_id: "ABCD123",
+ needs_analysis: false,
+ adjusted_rating: 5,
+ grade: "B",
+ highlights: MOCK_HIGHLIGHTS,
+ },
+};
+
+export const ThanksForReporting = Template.bind({});
+ThanksForReporting.args = {
+ data: {
+ deleted_product: true,
+ product_id: "ABCD123",
+ needs_analysis: false,
+ adjusted_rating: 5,
+ grade: "B",
+ highlights: MOCK_HIGHLIGHTS,
+ },
+ userReportedAvailable: true,
+};
+
+export const UnavailableProductReported = Template.bind({});
+UnavailableProductReported.args = {
+ data: {
+ deleted_product: true,
+ deleted_product_reported: true,
+ product_id: "ABCD123",
+ needs_analysis: false,
+ adjusted_rating: 5,
+ grade: "B",
+ highlights: MOCK_HIGHLIGHTS,
+ },
+};
+
+export const PageNotSupported = Template.bind({});
+PageNotSupported.args = {
+ data: {
+ product_id: null,
+ adjusted_rating: null,
+ grade: null,
+ page_not_supported: true,
+ },
+};
+
+export const GenericError = Template.bind({});
+GenericError.args = {
+ data: {
+ status: 422,
+ error: "Unprocessable entity",
+ },
+};
+
+export const Offline = Template.bind({});
+Offline.args = {
+ isOffline: true,
+};