0.5.1 • Published 4 months ago

expo-screenshotter v0.5.1

Weekly downloads
-
License
MIT
Repository
github
Last release
4 months ago

📱 Expo Screenshotter

npm version License GitHub Issues Build Status


✨ Features

Note: Device framing is fully implemented for both iPhone and Android frames. The tool will take your screenshot and overlay the device frame on top of it, maintaining the screenshot's dimensions.


🆕 What's New in v0.4.0

  • Screenshot Report Generation: Automatically generate a beautiful HTML report of all screenshots taken

🚀 Installation

npm install -g expo-screenshotter

🖼️ Device Frame Assets

To use the device frame feature, you need to have the frame images in the correct location.

  • Pill=true, Color=Space Black.png
  • Pill=true, Color=Gold.png
  • Pill=true, Color=Silver.png
  • Pill=true, Color=Deep Purple.png
  • Pill=False, Color=Starlight.png
  • Pill=False, Color=Midnight.png
  • Pill=False, Color=Red.png
  • Pill=False, Color=Blue.png
  • Android Compact Black.png
  • Android Compact Silver.png
  • Android Medium Black.png
  • Android Medium Silver.png

If you're using this tool as a dependency in your project, you may need to create the appropriate asset directories and add the frame images manually.


📋 Usage

There are three main commands:

Initialize Configuration

expo-screenshotter init

This creates a default expo-screenshotter.json configuration file in your project. You can then customize this file for your needs.

If you're using Expo Router, the tool will detect it and offer to automatically scan your project for routes:

Do you want us to automatically detect all routes for you? (Y/n):

If you select yes, the tool will: 1. Scan your app or src/app directory for route files 2. Detect routes based on Expo Router conventions (including route groups with parentheses) 3. Show you the detected routes and present an interactive menu with three options:

  • Select specific routes interactively: Opens a checkbox interface where you can use arrow keys to navigate, space to select routes, and enter to confirm
  • Use all detected routes: Includes all detected routes in your configuration
  • Use default routes: Uses the default example routes instead

This makes it much easier to get started with complex Expo Router projects!

Take Screenshots

expo-screenshotter capture

This will use your expo-screenshotter.json configuration to take screenshots. Make sure your Expo web app is running first with expo start --web.

Generate Report

expo-screenshotter report

This will generate an HTML report from existing screenshots in your output directory. You can specify a custom directory with the --dir option:

expo-screenshotter report --dir ./my-screenshots

⚙️ Configuration File (expo-screenshotter.json)

The configuration file controls which routes to screenshot, at what sizes, and with what options. You can create this file manually or use the init command, which can automatically detect routes in Expo Router projects.

{
  "views": [
    {
      "name": "Home",
      "path": "/"
    },
    {
      "name": "Form with Input",
      "path": "/form",
      "interactions": [
        {
          "type": "type",
          "selector": "input[placeholder=\"First Name\"]",
          "text": "John"
        },
        {
          "type": "wait",
          "waitTime": 500
        },
        {
          "type": "type",
          "selector": "input[placeholder=\"Last Name\"]",
          "text": "Doe"
        },
        {
          "type": "wait",
          "waitTime": 1000
        }
      ],
      "waitAfterInteractions": 1000
    },
    {
      "name": "Button Click",
      "path": "/buttons",
      "interactions": [
        {
          "type": "click",
          "selector": "button.primary-button"
        },
        {
          "type": "wait",
          "waitTime": 2000
        }
      ],
      "waitAfterInteractions": 1000
    }
  ],
  "sizes": [
    {
      "width": 375,
      "height": 812,
      "name": "iPhone X"
    },
    {
      "width": 1280,
      "height": 800,
      "name": "Tablet"
    },
    {
      "width": 2560,
      "height": 1440,
      "name": "Desktop"
    },
    {
      "width": 1280,
      "height": 800,
      "name": "Tablet Full Page",
      "fullPage": true
    },
    {
      "width": 375,
      "height": 812,
      "name": "iPhone X with Frame",
      "useDeviceFrame": true,
      "deviceType": "iphone",
      "iphoneOptions": {
        "pill": true,
        "color": "Space Black"
      }
    },
    {
      "width": 375,
      "height": 812,
      "name": "iPhone X with Gold Frame",
      "useDeviceFrame": true,
      "deviceType": "iphone",
      "iphoneOptions": {
        "pill": true,
        "color": "Gold"
      }
    },
    {
      "width": 375,
      "height": 812,
      "name": "iPhone X with Custom Size",
      "useDeviceFrame": true,
      "deviceType": "iphone",
      "iphoneOptions": {
        "pill": true,
        "color": "Gold",
        "width": 1242,
        "height": 2688
      }
    },
    {
      "width": 360,
      "height": 740,
      "name": "Android Medium Black",
      "useDeviceFrame": true,
      "deviceType": "android",
      "androidOptions": {
        "size": "medium",
        "color": "black"
      }
    },
    {
      "width": 360,
      "height": 740,
      "name": "Android Compact Silver",
      "useDeviceFrame": true,
      "deviceType": "android",
      "androidOptions": {
        "size": "compact",
        "color": "silver"
      }
    },
    {
      "width": 360,
      "height": 740,
      "name": "Android with Custom Size",
      "useDeviceFrame": true,
      "deviceType": "android",
      "androidOptions": {
        "size": "medium",
        "color": "black",
        "width": 1080,
        "height": 2340
      }
    }
  ],
  "outputDir": "./screenshots",
  "expoUrl": "http://localhost:8081",
  "waitTime": 2000,
  "waitForSelector": "#my-element",
  "fullPage": false,
  "useDeviceFrame": false,
  "generateReport": true,
  "iphoneOptions": {
    "pill": true,
    "color": "Space Black"
  },
  "androidOptions": {
    "size": "medium",
    "color": "black"
  }
}

🔧 Advanced Configuration Options

  • waitTime: Delay in milliseconds before taking screenshots (default: 1000)
  • waitForSelector: CSS selector to wait for before taking screenshots (e.g., "#my-element")
  • fullPage: Set to true to capture the entire scrollable content for all sizes (default: false)
  • useDeviceFrame: Set to true to place all screenshots inside device frames (default: false)
  • deviceType: Default device frame type to use ('iphone' or 'android')
  • generateReport: Set to true to automatically generate an HTML report of all screenshots (default: true)
  • iphoneOptions: Options for iPhone frames:
    • pill: Set to true for pill-style (iPhone 14 Pro+) or false for notch-style (iPhone 13, 14)
    • color: iPhone color ('Gold', 'Space Black', 'Silver', 'Deep Purple', 'Starlight', 'Midnight', 'Red', 'Blue')
    • width: Optional target width for the final image (for custom resizing)
    • height: Optional target height for the final image (for custom resizing)
  • androidOptions: Options for Android frames:
    • size: Android device size ('compact' or 'medium')
    • color: Android device color ('black' or 'silver')
    • width: Optional target width for the final image (for custom resizing)
    • height: Optional target height for the final image (for custom resizing)

Each size in the sizes array can have these additional options:

  • fullPage: Override the global fullPage setting for this specific size
  • scrollY: Scroll vertically by specified pixels before capturing
  • scrollX: Scroll horizontally by specified pixels before capturing
  • useDeviceFrame: Override the global useDeviceFrame setting for this specific size
  • deviceType: Override the global deviceType setting for this specific size
  • iphoneOptions: Override the global iPhone frame options for this specific size
    • Including width and height properties to resize the final framed image to specific dimensions
  • androidOptions: Override the global Android frame options for this specific size
    • Including width and height properties to resize the final framed image to specific dimensions

For example, to wait for a specific element and capture a full-page screenshot with device frames:

{
  "waitForSelector": "#content-loaded",
  "waitTime": 3000,
  "useDeviceFrame": true,
  "deviceType": "iphone",
  "iphoneOptions": {
    "pill": true,
    "color": "Gold"
  },
  "sizes": [
    {
      "name": "Full Page Mobile",
      "width": 375,
      "height": 812,
      "fullPage": true
    },
    {
      "name": "Scrolled Desktop",
      "width": 1280,
      "height": 800,
      "scrollY": 500
    },
    {
      "name": "iPhone with Notch",
      "width": 375,
      "height": 812,
      "iphoneOptions": {
        "pill": false,
        "color": "Midnight"
      }
    },
    {
      "name": "iPhone with Custom Size",
      "width": 375,
      "height": 812,
      "useDeviceFrame": true,
      "deviceType": "iphone",
      "iphoneOptions": {
        "pill": true,
        "color": "Gold",
        "width": 1242,
        "height": 2688
      }
    },
    {
      "name": "Android Medium Black",
      "width": 360,
      "height": 740,
      "deviceType": "android",
      "androidOptions": {
        "size": "medium",
        "color": "black"
      }
    },
    {
      "name": "Android Compact Silver",
      "width": 360,
      "height": 740,
      "deviceType": "android",
      "androidOptions": {
        "size": "compact",
        "color": "silver"
      }
    },
    {
      "name": "Android with Custom Size",
      "width": 360,
      "height": 740,
      "useDeviceFrame": true,
      "deviceType": "android",
      "androidOptions": {
        "size": "medium",
        "color": "black",
        "width": 1080,
        "height": 2340
      }
    }
  ]
}

Each view in the views array can have these additional options:

  • interactions: An array of interactions to perform before taking screenshots:
    • Type interactions: { "type": "type", "selector": "CSS_SELECTOR", "text": "TEXT_TO_TYPE" }
    • Click interactions: { "type": "click", "selector": "CSS_SELECTOR" }
    • Wait interactions: { "type": "wait", "waitTime": MILLISECONDS }
  • waitAfterInteractions: Time in milliseconds to wait after all interactions are complete before taking screenshots

For example, to fill out a form and click a button before taking screenshots:

{
  "name": "Form Submission",
  "path": "/contact",
  "interactions": [
    {
      "type": "type",
      "selector": "input[name='name']",
      "text": "John Doe"
    },
    {
      "type": "type",
      "selector": "input[name='email']",
      "text": "john@example.com"
    },
    {
      "type": "type",
      "selector": "textarea[name='message']",
      "text": "This is a test message"
    },
    {
      "type": "click",
      "selector": "button[type='submit']"
    },
    {
      "type": "wait",
      "waitTime": 2000
    }
  ],
  "waitAfterInteractions": 1000
}

📊 Screenshot Report

The tool can automatically generate a beautiful HTML report of all screenshots taken. This makes it easy to view and share your screenshots with team members or clients.

  • Visual Grid Layout: All screenshots are displayed in a responsive grid layout
  • Screenshot Information: Each screenshot card shows the view name, size, and file path
  • Interactive UI: Hover effects and clean design for easy browsing
  • Automatic Generation: Reports can be generated automatically during capture or separately with the report command

Enabling Report Generation

You can enable automatic report generation in your configuration file:

{
  "generateReport": true,
  // ... other configuration options
}

This option is enabled by default in new configurations created with the init command.

Generating Reports Separately

You can also generate a report from existing screenshots without recapturing them:

expo-screenshotter report

This command will scan your output directory for screenshots and generate an HTML report. You can specify a custom directory with the --dir option:

expo-screenshotter report --dir ./my-screenshots

The report will be saved as screenshot-report.html in your output directory.


📱 Available Device Frame Options


🛠️ Development

# Clone the repository
git clone https://github.com/TheRealPerson98/expo-screenshotter.git
cd expo-screenshotter

# Install dependencies
npm install

# Build the project
npm run build

The project uses ESLint for code quality:

# Run linting
npm run lint

# Fix linting issues automatically
npm run lint:fix

📝 License

This software is dual-licensed:

For Individual/Open Source Use

MIT © Person98 LLC - Jace Sleeman (@TheRealPerson98)

This software can be used freely in personal and open-source projects. For commercial use, please refer to the license terms or contact for licensing options.


📸 Examples

Testing

To run the tests:

npm test

Test Setup

The tests use a mock server to simulate an Expo app and mock the screenshot capture process. The tests are designed to run in isolation and not interfere with each other.

Test Files

  • basic.test.ts: Tests basic functionality like initializing a configuration file and taking screenshots.
  • advanced.test.ts: Tests advanced features like device frames, interactions, and full-page screenshots.
  • programmatic.test.ts: Tests the programmatic API.

Mock Server

The tests use a mock server (MockExpoServer) to simulate an Expo app. The server serves static HTML pages that can be used for testing.

Test Configuration

The test configuration is defined in setup.ts and includes:

  • Output directory for screenshots
  • Mock server port
  • Expo URL

Troubleshooting

TypeScript Errors

If you encounter TypeScript errors when running the tests, make sure you have the correct TypeScript configuration. The tests use a separate tsconfig.json file in the __tests__ directory.

Port Conflicts

If you encounter port conflicts when running the tests, you can modify the port numbers in the test files. Each test file uses a different port to avoid conflicts.

PowerShell Execution Policy

If you're using PowerShell and encounter execution policy errors, you can run the tests with:

powershell -ExecutionPolicy Bypass -Command "npm test"
0.5.0

4 months ago

0.4.0

4 months ago

0.5.1

4 months ago

0.3.0

5 months ago

0.2.0

5 months ago

0.1.1

5 months ago

0.1.0

5 months ago