> ## Documentation Index
> Fetch the complete documentation index at: https://www.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Testing Your Next.js App with Dynamic Labs SDK

> Learn how to set up Jest testing for Next.js applications using Dynamic Labs SDK, including mocking components and hooks.

This guide walks you through setting up Jest testing for a Next.js application that uses the Dynamic Labs SDK. You'll learn how to properly mock Dynamic components and hooks to write effective unit tests.

## Prerequisites

* Node.js installed on your machine
* Basic familiarity with Next.js and React Testing Library
* A Dynamic Labs account with an environment ID

## Step 1: Create a New Next.js Project

First, create a new Next.js application using the latest version:

```bash theme={"system"}
npx create-next-app@latest my-test-app
```

Follow the prompts to set up your project with TypeScript and other preferred options.

## Step 2: Install Dynamic Labs SDK

Install the required Dynamic Labs packages:

```bash theme={"system"}
npm install @dynamic-labs/sdk-react-core @dynamic-labs/ethereum
```

## Step 3: Add Dynamic to Your Application

### Configure the Layout

Open `src/app/layout.tsx` and add the `DynamicContextProvider`. Replace `<YOUR_ENVIRONMENT_ID>` with your actual environment ID from the Dynamic dashboard:

```tsx theme={"system"}
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import { DynamicContextProvider } from "@dynamic-labs/sdk-react-core";
import { EthereumWalletConnectors } from "@dynamic-labs/ethereum";

const geistSans = Geist({
  variable: "--font-geist-sans",
  subsets: ["latin"],
});

const geistMono = Geist_Mono({
  variable: "--font-geist-mono",
  subsets: ["latin"],
});

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body
        className={`${geistSans.variable} ${geistMono.variable} antialiased`}
      >
        <DynamicContextProvider
          theme="auto"
          settings={{
            environmentId: "<YOUR_ENVIRONMENT_ID>",
            walletConnectors: [EthereumWalletConnectors],
          }}
        >
          {children}
        </DynamicContextProvider>
      </body>
    </html>
  );
}
```

### Add the DynamicWidget

Open `src/app/page.tsx` and add the `DynamicWidget` component:

```tsx theme={"system"}
import { DynamicWidget } from "@dynamic-labs/sdk-react-core";

export default function Home() {
  return (
    <div className="font-sans grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20">
      <h1>Hello World</h1>
      <DynamicWidget />
    </div>
  );
}
```

## Step 4: Configure Jest for Testing

### Install Testing Dependencies

Install Jest and React Testing Library along with necessary type definitions:

```bash theme={"system"}
npm install -D jest jest-environment-jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom ts-node @types/jest
```

### Initialize Jest Configuration

Create a basic Jest configuration file:

```bash theme={"system"}
npm init jest@latest
```

### Configure Jest for Next.js

Create a `jest.config.ts` file in your project root with the following configuration:

```ts theme={"system"}
import type { Config } from "jest";
import nextJest from "next/jest.js";

const createJestConfig = nextJest({
  dir: "./",
});

const config: Config = {
  coverageProvider: "v8",
  testEnvironment: "jsdom",
};

export default createJestConfig(config);
```

### Set Up Jest Custom Matchers

Create a `jest.setup.ts` file in your project root to configure testing utilities:

```ts theme={"system"}
import "@testing-library/jest-dom";
```

### Update Jest Configuration

Update your `jest.config.ts` to include the setup file:

```ts theme={"system"}
import type { Config } from "jest";
import nextJest from "next/jest.js";

const createJestConfig = nextJest({
  dir: "./",
});

const config: Config = {
  coverageProvider: "v8",
  testEnvironment: "jsdom",
  setupFilesAfterEnv: ["<rootDir>/jest.setup.ts"],
};

export default createJestConfig(config);
```

## Step 5: Write Tests for Dynamic Components

### Test the Layout Component

Create a `__tests__/layout.test.jsx` file to test your layout:

```tsx theme={"system"}
import "@testing-library/jest-dom";
import { render, screen } from "@testing-library/react";
import Layout from "../src/app/layout";

// Mock the Dynamic SDK components to isolate layout logic in tests
jest.mock("@dynamic-labs/sdk-react-core", () => ({
  DynamicContextProvider: ({ children }) => (
    <div data-testid="dynamic-context">{children}</div>
  ),
}));

// Mock the Ethereum wallet connectors
jest.mock("@dynamic-labs/ethereum", () => ({
  EthereumWalletConnectors: [],
}));

// Mock Next.js font imports to avoid font loading issues in tests
jest.mock("next/font/google", () => ({
  Geist: () => ({ variable: "--font-geist-sans" }),
  Geist_Mono: () => ({ variable: "--font-geist-mono" }),
}));

describe("Layout", () => {
  it("renders Layout with children", () => {
    render(<Layout>Hello World</Layout>);

    const heading = screen.getByText("Hello World");
    const dynamicContext = screen.getByTestId("dynamic-context");

    expect(heading).toBeInTheDocument();
    expect(dynamicContext).toBeInTheDocument();
  });
});
```

### Test the Page Component

Create a `__tests__/page.test.jsx` file to test your page:

```tsx theme={"system"}
import "@testing-library/jest-dom";
import { render, screen } from "@testing-library/react";
import Page from "../src/app/page";

// Mock the Dynamic SDK components
jest.mock("@dynamic-labs/sdk-react-core", () => ({
  DynamicWidget: () => <div>DynamicWidget</div>,
}));

describe("Page", () => {
  it("renders a heading", () => {
    render(<Page />);

    const heading = screen.getByText("Hello World");

    expect(heading).toBeInTheDocument();
  });
});
```

## Step 6: Test Components Using Dynamic Hooks

### Update Your Page to Use Hooks

Modify `src/app/page.tsx` to use Dynamic hooks for displaying user information:

```tsx theme={"system"}
"use client";

import {
  DynamicWidget,
  useDynamicContext,
  useIsLoggedIn,
  useUserWallets,
} from "@dynamic-labs/sdk-react-core";

export default function Home() {
  const { sdkHasLoaded } = useDynamicContext();
  const isLoggedIn = useIsLoggedIn();
  const userWallets = useUserWallets();

  return (
    <div className="font-sans grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20">
      <h1>Hello World</h1>
      <p>SDK has loaded: {sdkHasLoaded ? "Yes" : "No"}</p>
      <p>Is logged in: {isLoggedIn ? "Yes" : "No"}</p>
      <p>
        User wallets:{" "}
        {userWallets.length > 0 ? (
          userWallets.map((wallet) => (
            <span key={wallet.address}>{wallet.address}</span>
          ))
        ) : (
          <span>No wallets</span>
        )}
      </p>
      <DynamicWidget />
    </div>
  );
}
```

### Test with Mocked Hooks

Update `__tests__/page.test.jsx` to properly mock and test Dynamic hooks:

```tsx theme={"system"}
import "@testing-library/jest-dom";
import { render, screen } from "@testing-library/react";
import Page from "../src/app/page";
import {
  useDynamicContext,
  useIsLoggedIn,
  useUserWallets,
} from "@dynamic-labs/sdk-react-core";

// Mock the Dynamic SDK components and hooks
jest.mock("@dynamic-labs/sdk-react-core", () => ({
  DynamicWidget: () => <div>DynamicWidget</div>,
  useDynamicContext: jest.fn(),
  useIsLoggedIn: jest.fn(),
  useUserWallets: jest.fn(),
}));

describe("Page", () => {
  beforeEach(() => {
    useDynamicContext.mockReturnValue({ sdkHasLoaded: true });
    useIsLoggedIn.mockReturnValue({ isLoggedIn: false });
    useUserWallets.mockReturnValue([]);
  });

  it("render render No wallets", () => {
    render(<Page />);

    expect(screen.getByText("No wallets")).toBeInTheDocument();
  });

  describe("when the has user logged in with wallets", () => {
    beforeEach(() => {
      useDynamicContext.mockReturnValue({ sdkHasLoaded: true });
      useIsLoggedIn.mockReturnValue({ isLoggedIn: true });
      useUserWallets.mockReturnValue([{ address: "0x123" }]);
    });

    it("render the list of wallets", () => {
      render(<Page />);

      const wallets = screen.getByText("0x123");

      expect(wallets).toBeInTheDocument();
    });
  });
});
```

## Understanding the Mocking Strategy

When testing components that use the Dynamic Labs SDK, the key approach is to mock the SDK modules and hooks:

### Mock the Entire Module

Mock `@dynamic-labs/sdk-react-core` to replace all components and hooks with Jest mock functions:

```jsx theme={"system"}
jest.mock("@dynamic-labs/sdk-react-core", () => ({
  DynamicWidget: () => <div>DynamicWidget</div>,
  DynamicContextProvider: ({ children }) => children,
  useDynamicContext: jest.fn(),
  useIsLoggedIn: jest.fn(),
  useUserWallets: jest.fn(),
}));
```

### Mock Individual Hooks

Each hook can return different values for different test scenarios:

```jsx theme={"system"}
beforeEach(() => {
  useDynamicContext.mockReturnValue({ sdkHasLoaded: true });
  useIsLoggedIn.mockReturnValue({ isLoggedIn: false });
  useUserWallets.mockReturnValue([]);
});
```

## Running Your Tests

Add a test script to your `package.json`:

```json theme={"system"}
{
  "scripts": {
    "test": "jest",
    "test:watch": "jest --watch"
  }
}
```

Run your tests:

```bash theme={"system"}
npm test
```

## Summary

You've successfully set up Jest testing for your Next.js application with Dynamic Labs SDK. The key takeaways are:

* Mock the entire `@dynamic-labs/sdk-react-core` module to replace components and hooks
* Use `jest.fn()` to create mock implementations that can return different values for different test scenarios
* Configure Jest custom matchers from `@testing-library/jest-dom` for better test assertions

This testing approach allows you to thoroughly test your application's behavior without needing to connect to actual wallets or authenticate real users during your test runs.
