How to automate the Wechat Mini Program

Naren Chejara
5 min readNov 9, 2019

--

WeChat is a very popular mobile application in China, developed and maintained by Tencent. The Mini Programs are a small application that functions within the WeChat application. The Mini Programs are gaining popularity in the china market, there are more than one million mini-programs are up and running on the WeChat platform that helps consumers do almost everything including marketing, online shopping, games, etc.

The Mini Programs are widely adopted by the individual, started up, small and big organizations that means the ecosystem of the mini-program is more & more diverse and complex, therefore, it’s essential to publish an adequate quality of the mini-program that can increase the user experience and confidence.

In this article, We are going to learn how to do end 2 end automation testing on the mini program. I presume that you are familiar with the node JS — refer Node.js Get Started tutorial, in case you want to know more about node js or want to get familiar with node JS

Let’s get started!

Configure the Machine

Download and install Node JS and WeChat dev tool (v1.02.1910120) in your machine.

$ mkdir e2e_min_program
$ cd e2e_min_program
$ npm init -y //-y is use to keep default value withou
$ npm i -S miniprogram-automator

The above snippet does do the following

  • Make a directory for end 2 end automation test project
  • Initialize NPM package
  • Install node dependencies (miniprogram-automator ).

Miniprogram-automator is the official NPM module from weixin team and there are four main key areas to focus before writing automation code

  • A simulator is representing an object that can be used to launch or connect to the application in “Wechat Devtools IDE”
  • Mini App is an instance of your application that initialized after an application launched in the simulator, This instance can be used to perform actions such as navigating between the pages, relaunching the application, redirecting, get the active page, close the application and the simulator, etc.
  • Page class can be used to perform actions on the page such as wait, find elements, set page data, call page methods directly, etc.
  • Element class can be used to perform actions on the elements such as to get text, tap on the element, trigger element event and find the element within element.

Launch Simulator

Create a test spec file (contact-spec.js), copy & paste codes and run the test (node contact-spec.js)

const simulator = require("miniprogram-automator");

(async () => {


const miniApp = await simulator.launch({
cliPath: "/Applications/wechatwebdevtools.app/Contents/MacOS/cli",
projectPath: `${__dirname}/../../test_app/`
});


// Get the current page for next actions
let page = await miniApp.currentPage();


//close the mini app
await miniApp.close();


}
)();

The above code snippet will launch the simulator, redirect the user to the default page and initialized a page instance by calling ‘miniApp.currentPage()’ method.

Tips:

  1. Enabled the service port for external communication such as CLI or HTTP
  2. As per the official document, automated test supports from v1.02.1907300 version, Please check the IDE version if launching fail error persistent

Navigate to page

The Mini program Automator library has a ‘navigateTo’ function to navigate between the pages.

// Navigate to the specific page
page = await miniApp.navigateTo('../contact/contact');

Page Data

The library has exposed data & setData methods for handling page data, Let’s see how to call use them

// Get Paga Data
let data = await page.data();
console.log(data);

// Output
//{
// name: '',
// phone: '',
// phoneTypes: [
// { key: 0, type: 'Home', checked: true },
// { key: 1, type: 'Office' }
// ],
// msg: '',
// showResult: false
//}


// SetData
data.test = "This property add from the automation";
await page.setData(data);

console.log(await page.data());

// Output

//{
// name: 'Naren chejara',
// phone: '12345678910',
// phoneTypes: [
// { key: 0, type: 'Home', checked: true },
// { key: 1, type: 'Office' }
// ],
// msg: '',
// showResult: false
//}

Call Method

The library also exposes a callMethod function to call the function from the page directly, This function is useful for clean up or set test precondition data

// Clear page data by calling 'tapOnClear' method
await page.callMethod("tapOnClear");

console.log(await page.data());

// Output

//{
// name: '',
// phone: '',
// phoneTypes: [
// { key: 0, type: 'Home', checked: true },
// { key: 1, type: 'Office' }
// ],
// msg: '',
// showResult: false

//}

Find Element(s)

The library has exposed $ and $$ functions to find element(s), similar to selenium and puppeteer. $() is used to find a single element and $$() is used to find an array of the element.

const page = await miniApp.currentPage();
await page.waitFor(1000);
const titleElement = await page.$('[id="title"]');

The above code snippet does do the following

  • Get the current page instance and assigned to the page object
  • Wait 1000 milliseconds (sometimes rendering element is a bit slow, therefore, it is good practice to ensure that the element rendered successfully)
  • Find an element (based on the CSS selector) and assigned to the titleElement object

Actions on the Element

  • $() & $$() | Find the element within the element (nested )
  • size() | Obtain the width and height of the element
  • offset() | Obtain the left and top offset of the element
  • text() | Obtain text of the element (similar to the inner text)
  • attribute() | Obtain the value of the specified attribute
  • wxml() | Obtain the inner mark up (wxml stands for Weixin markup language)
  • outerWxml() | Obtain the outer mark up
  • value() | Obtain the value of the input box (in short this method will get the value of the value attribute).
  • style() | Obtain the value of the Style attribute, pass the name of the style that you want to obtain
  • callMethod() | Call a function directly form the test.
  • tap() | Tap on the element
  • trigger() | trigger event of the element

I have covered most of the useful actions to get started to automate mini-program, please note that the library is new and updating continuously and there is high possibility that some functionality may change and not work as described, therefore, It’s recommended to refer the official document.

Here is the full program or you can visit my Github repository HERE

const simulator = require("miniprogram-automator");

(async () => {

let prg = `${__dirname}/../../test_app`

const miniApp = await simulator.launch({
projectPath: `${__dirname}/../../test_app/`
});


let page = await miniApp.currentPage();
page = await miniApp.navigateTo('../contact/contact');
await page.waitFor(1000);

// Get Paga Data
let data = await page.data();
console.log(data);


// SetData
data.name = "Naren chejara";
data.phone = "12345678910";
await page.setData(data);
console.log(await page.data());


// Clear page data by calling 'tapOnClear' method
await page.callMethod("tapOnClear");
console.log(await page.data());


// Find and element
const titleElement = await page.$('[id="title"]');


// Get size of the element
console.log("Size of the element: %j", await titleElement.size())

// Get offset of the element
console.log("Offset of the element: %j", await titleElement.offset());


//Get text of the element
let title = await titleElement.text();
console.log(`Title of the contact page: ${title}`);

//Get the value of the attribute
let attr = await titleElement.attribute("id");
console.log(`The value of the 'id' attribute: ${attr}`);

//Get wxml (weixin markup language)
let wxml = await titleElement.wxml();
console.log(`Weixin markup language: ${wxml}`);


//Get wxml (weixin markup language)
let outerWxml = await titleElement.outerWxml();
console.log(`Outer wiexin markup language: ${outerWxml}`);

// Type in Name element
let name = await page.$('[id="name"]');
await name.trigger('input', {value: "Naren Chejara"});

// Get the vsalue of the Input element
await page.waitFor(500);
let value = await name.value();
console.log(`Value of the input box is: ${value}`);

//close the mini app
await miniApp.close();

}

)();

--

--