How to Automate WeChat Mini‑Program Testing with miniprogram‑automator

This article explains how the JD.com "Jingxi" mini‑program uses the official miniprogram‑automator SDK to build an automated disaster‑recovery testing workflow that launches the devtools, simulates user actions, intercepts network requests, generates screenshots, and validates fallback behavior with manual comparison.

Aotu Lab
Aotu Lab
Aotu Lab
How to Automate WeChat Mini‑Program Testing with miniprogram‑automator

Overview

The mini‑program disaster‑recovery drill requires automated navigation, network fault injection, screenshot capture, and manual verification. The official miniprogram‑automator SDK (npm package https://www.npmjs.com/package/miniprogram-automator ) provides WebDriver‑like control over WeChat mini‑programs.

Key SDK Capabilities

Launch WeChat DevTools CLI and open a project.

Navigate to any page (e.g., reLaunch('/pages/index/index')).

Query and interact with elements ( page.$('.banner'), tap()).

Read element attributes and size.

Mock any wx API, especially wx.request, to return custom responses.

Inject arbitrary JavaScript into the AppService.

Capture full‑page screenshots.

Typical Automation Flow

Launch the development version of WeChat DevTools via the CLI.

Open the target page and perform user actions (click, swipe, pull‑down refresh, scroll).

Intercept network requests and replace responses (e.g., HTTP 500, malformed JSON).

Capture a screenshot for each simulated scenario.

Clear local storage when needed.

Trigger UI recovery actions such as the refresh button.

Restore the original wx.request implementation and end the session.

Test Case Definition

Test data are stored in JSON files to separate configuration from script logic. The structure contains a global section (shared parameters) and case‑specific objects.

{
  "global": {
    "url": "/pages/index/index",
    "pageName": "index",
    "pageDesc": "Home",
    "device": "iPhone X"
  },
  "homePageApi": {
    "id": 1,
    "module": "home_page_api",
    "moduleDesc": "Home main API",
    "api": "https://example.com/api/home",
    "operation": "mock status 500",
    "expectRules": [
      "1. With cache, show cached data",
      "2. Without cache, request disaster API and show fallback",
      "3. Both APIs fail, show error and refresh button",
      "4. Restore network, click refresh, show normal data"
    ],
    "screenshot": [
      {"name": "normal", "desc": "Normal scenario"},
      {"name": "500_cache", "desc": "Cache present, main API returns 500"},
      {"name": "500_no_cache", "desc": "No cache, main API returns 500"},
      {"name": "500_no_cache_500_disaster", "desc": "Both APIs return 500"},
      {"name": "500_no_cache_recover", "desc": "Network recovers after 500"}
    ]
  }
}

Core Script Snippets

Launch and page navigation

const automator = require('miniprogram-automator');

const miniProgram = await automator.launch({
  cliPath: '/Applications/wechatwebdevtools.app/Contents/MacOS/cli',
  projectPath: '/absolute/path/to/jx_project'
});
await miniProgram.reLaunch('/pages/index/index');

Screenshot capture

await miniProgram.screenshot({ path: 'jx_weapp_index_home_page_500.png' });

Mock data generator

const getMockData = (url, type, value) => {
  const result = { data: 'test', cookies: [], header: {}, statusCode: 200 };
  switch (type) {
    case 'data': result.data = getMockResponse(url, value); break;
    case 'cookies': result.cookies = value; break;
    case 'header': result.header = value; break;
    case 'statusCode': result.statusCode = value; break;
  }
  return { rule: url, result };
};

const mockData = [
  getMockData('https://example.com/api/home', 'statusCode', 500),
  getMockData('https://example.com/api/disaster', 'data', { /* abnormal payload */ })
];

Intercept wx.request

const interceptAPI = async (miniProgram, mockData) => {
  await miniProgram.mockWxMethod('request', (obj, data) => {
    for (const item of data) {
      if (obj.url.includes(item.rule)) return item.result;
    }
    return new Promise(resolve => {
      obj.success = res => resolve(res);
      obj.fail = err => resolve(err);
      this.origin(obj);
    });
  }, mockData);
};

await interceptAPI(miniProgram, mockData);

Clear storage

await miniProgram.callWxMethod('clearStorage');

Trigger UI refresh button

const page = await miniProgram.currentPage();
const $refreshBtn = await page.$('.page-error__refresh-btn');
await $refreshBtn.tap();

Restore original request method

await miniProgram.restoreWxMethod('request');

Running the Tests

Add a script entry to package.json:

{
  "scripts": {
    "start": "node test/index.js"
  }
}

Environment requirements:

Node.js ≥ 8.0

Mini‑program base library version ≥ 2.7.3

WeChat DevTools version ≥ 1.02.1907232

Execute with:

$ npm run start

Shadow DOM Handling

Many components are rendered inside a Shadow DOM, which isolates their subtree from the main DOM. To interact with such elements, first obtain the shadow host, then query inside it.

const page = await miniProgram.currentPage();
const $searchBarShadow = await page.$('search-bar'); // shadow host
const $searchBar = await $searchBarShadow.$('.search-bar'); // real element
await $searchBar.tap();

Additional Scenarios

Pull‑down refresh :

await miniProgram.callWxMethod('startPullDownRefresh');

Scroll to a specific DOM :

const page = await miniProgram.currentPage();
const $tabShadow = await page.$('recommend-tab');
const $tab = await $tabShadow.$('.recommend');
const { top } = await $tab.offset();
await miniProgram.pageScrollTo(top);

Event logging :

miniProgram.on('console', msg => console.log(msg.type, msg.args));
page.on('error', e => console.error(e));

Conclusion

The first phase of mini‑program automated disaster‑recovery testing is complete. Scripts generate screenshots for normal, 500‑error, cache‑present, and network‑recovery scenarios; humans then compare the images to verify UI fallback behavior. The approach is now part of the monthly drill and serves as a foundation for a future multi‑platform SDK that will unify H5 and mini‑program testing.

References

miniprogram‑automator: https://www.npmjs.com/package/miniprogram-automator

Selenium WebDriver: https://www.selenium.dev/projects/

Puppeteer: https://pptr.dev/

Whistle (network proxy): https://wproxy.org/whistle/

frontendSDKJavaScriptMiniProgramTestingWeChat
Aotu Lab
Written by

Aotu Lab

Aotu Lab, founded in October 2015, is a front-end engineering team serving multi-platform products. The articles in this public account are intended to share and discuss technology, reflecting only the personal views of Aotu Lab members and not the official stance of JD.com Technology.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.