Efficiently Mocking Sitecore Layout Data and NextAuth Sessions in Storybook

Streamlining Sitecore and NextAuth mocking in Storybook

November 14, 2024

By Sohrab Saboori

Mocking Sitecore Layout Data and NextAuth Sessions in Storybook

Developing React components with Next.js and Sitecore presents unique challenges, especially when your components depend on Sitecore's context data and authentication states managed by NextAuth. While Storybook offers a powerful environment for building and testing UI components in isolation, integrating it with Sitecore's layout data and NextAuth sessions in a Next.js project requires some extra setup.

In this guide, we'll show you how to efficiently mock Sitecore context data alongside NextAuth sessions within Storybook for a Next.js application. By mocking these contexts, you can simulate different Sitecore layouts and authentication states, allowing you to thoroughly test your components in isolation. This approach enhances your development workflow, making it more streamlined and efficient.

Why Mocking Contexts Matters

Components that rely on Sitecore's layout data or NextAuth's authentication states can't function properly without these contexts. When running your components in Storybook, the absence of these contexts can lead to errors or unexpected behavior. Mocking these contexts allows you to simulate different states and test your components thoroughly.

The Benefits

  • Isolation: Test components without running the entire app.
  • Flexibility: Simulate various authentication states and layout data.
  • Efficiency: Speed up development by avoiding context-related blockers.

Understanding Storybook Decorators

In Storybook, decorators are wrappers that allow you to add context providers or modify the rendering of your stories. They are essential for injecting providers like Context, Theme, or any custom context your components depend on.

Why Use Decorators for Context Providers?

Using decorators to wrap your stories ensures that every component has the necessary context to function. This approach:

  • Keeps your stories clean and focused.
  • Avoids repetition by setting global contexts.
  • Allows overriding contexts at the story level when needed.

Setting Up Global Decorators in preview.tsx

We'll start by configuring global decorators in Storybook's preview.tsx file.

Note: If your preview file is currently named preview.ts, it's preferable to rename it to preview.tsx since we'll be using JSX syntax. TypeScript requires the .tsx extension to properly parse JSX code.

// .storybook/preview.tsx
  import React from 'react';
  import { AppProvider } from '../path/to/AppProvider';
  import { SessionProvider } from 'next-auth/react';
  import { SitecoreContext } from '@sitecore-jss/sitecore-jss-react';
  const mockSession = {
   // Your mock Session data here
  };
  const mockLayoutData = {
    // Your mock Sitecore layout data here
  };
  const mockComponentFactory = (componentName) => {
    // Return a mock component based on the componentName
  };
  
export const decorators = [ (Story) => ( <AppProvider> <SessionProvider session={mockSession}> <SitecoreContext layoutData={mockLayoutData} componentFactory={mockComponentFactory} > <Story /> </SitecoreContext> </SessionProvider> </AppProvider> ), ];

Breaking Down the Decorator

  • AppProvider: Wraps your application with any global context or configurations.
  • SessionProvider with mockSession: Mocks NextAuth session data to simulate authenticated states.
  • SitecoreContext with mockLayoutData and mockComponentFactory: Provides mocked Sitecore layout data and a factory to render components.

Mocking NextAuth Session Data

Components that rely on authentication states need to know whether a user is logged in or not. Mocking NextAuth sessions allows you to simulate both authenticated and unauthenticated states.

const mockSession = {
    expires: '2023-01-01T00:00:00Z',
    user: {
      name: 'Storybook User',
      email: '[email protected]',
    },
  };
  
  • expires: A future date to indicate the session is valid.
  • user: An object containing user information.

Customizing Sessions Per Story

You can override mockSession in individual stories to test different scenarios, such as:

  • Different user roles.
  • Expired sessions.
  • Unauthenticated states.

Mocking Sitecore Context Data

Sitecore's layoutData represents the data that Sitecore provides to render components, including placeholders and fields. The componentFactory is responsible for mapping component names to React components.

const mockLayoutData = {
    sitecore: {
      context: {
        pageEditing: false,
      },
      route: {
        name: 'Home',
        placeholders: {
          'main-content': [
            {
              uid: '1',
              componentName: 'Header',
              fields: {
                title: { value: 'Welcome to Storybook' },
              },
            },
            // Add more mock components as needed
          ],
        },
      },
    },
  };
  
const mockComponentFactory = (componentName) => {
    const components = {
      Header: (props) => <h1>{props.fields.title.value}</h1>,
      // Map other components as needed
    };
    return components[componentName] || (() => <div>Component not found</div>);
  };
  

Overriding Mocks in Individual Stories

Different stories often require unique context data to accurately test various scenarios. Overriding mocks at the story level allows you to:

  • Test Components with Varied Data Inputs: Simulate different data states to understand how your component reacts.
  • Simulate Unique User Interactions: Configure distinct authentication states or contexts to test specific user journeys.

Example of Overriding Sitecore Context and NextAuth Session in a Story

In this example, we’ll see how to override both the Sitecore context and the NextAuth session at the story level for a component called MyComponent.

// src/components/MyComponent.stories.tsx
  import React from 'react';
  import { ComponentStory, ComponentMeta } from '@storybook/react';
  import { SitecoreContext } from '@sitecore-jss/sitecore-jss-react';
  import { SessionProvider } from 'next-auth/react';
  import MyComponent from './MyComponent';
  
export default { title: 'Components/MyComponent', component: MyComponent, parameters: { layout: 'fullscreen', }, } as ComponentMeta<typeof MyComponent>;
// Define a basic template const Template: ComponentStory<typeof MyComponent> = (args) => <MyComponent {...args} />;
// Default story using global decorators in preview.tsx export const Default = Template.bind({});
// Customized story with unique Sitecore context data and NextAuth session const customMockLayoutData = { sitecore: { context: { pageEditing: false, language: 'en', }, route: { name: 'Custom Page', displayName: 'Custom Page Display Name', fields: { pageTitle: { value: 'Custom Page Title' }, pageDescription: { value: 'Custom page description' }, }, placeholders: {}, }, }, };
const customMockSession = { expires: '2024-12-31T00:00:00Z', user: { name: 'Custom Story User', email: '[email protected]', }, };
export const CustomContextAndSessionStory = Template.bind({}); CustomContextAndSessionStory.decorators = [ (Story) => ( <SessionProvider session={customMockSession}> <SitecoreContext layoutData={customMockLayoutData}> <Story /> </SitecoreContext> </SessionProvider> ), ];

Explanation

  • Default Story: Uses the global decorators set in preview.tsx to provide default mock session and Sitecore context data.
  • CustomContextAndSessionStory: Overrides both the Sitecore context and NextAuth session for this specific story:
    • SitecoreContext uses customMockLayoutData to simulate a custom page layout.
    • SessionProvider uses customMockSession to simulate an authenticated user with custom data.

By overriding both the session and context at the story level, you can easily test how your component behaves with different user states and layouts, giving you powerful flexibility in Storybook.

Final Thoughts on Mocking Sitecore Data and NextAuth in Storybook

Mocking Sitecore context data and NextAuth sessions in Storybook enables you to create a streamlined, effective development environment. By applying these techniques, you can:

  • Enhance Development Speed: Test and iterate on components without needing to run the entire app, speeding up your workflow.
  • Improve Testing Accuracy: Simulate different layouts, user states, and data inputs to ensure your components behave as expected across all scenarios.
  • Simplify Complex Testing: Reduce the dependencies on external services and backend data, making it easier to test components in isolation.

Using Storybook with mocked Sitecore and NextAuth contexts creates a more flexible, reliable, and robust component testing process, enabling you to deliver higher-quality components with confidence.

References:

Photo of Fishtank employee Sohrab Saboori

Sohrab Saboori

Senior Full-Stack Developer

Sohrab is a Senior Front-End Developer with extensive experience in React, Next.js, JavaScript, and TypeScript. Sohrab is committed to delivering outstanding digital solutions that not only meet but exceed clients' expectations. His expertise in building scalable and efficient web applications, responsive websites, and e-commerce platforms is unparalleled. Sohrab has a keen eye for detail and a passion for creating seamless user experiences. He is a problem-solver at heart and enjoys working with clients to find innovative solutions to their digital needs. When he's not coding, you can find him lifting weights at the gym, pounding the pavement on the run, exploring the great outdoors, or trying new restaurants and cuisines. Sohrab believes in a healthy and balanced lifestyle and finds that these activities help fuel his creativity and problem-solving skills.