wechaty-puppet
Version:
Abstract Puppet for Wechaty
381 lines • 15.1 kB
JavaScript
#!/usr/bin/env -S node --no-warnings --loader ts-node/esm
import { test, sinon, } from 'tstest';
import { MemoryCard, } from '../config.js';
import { ContactGender, ContactType, } from '../schemas/contact.js';
import { MessageType, } from '../schemas/message.js';
import { PuppetSkeleton } from './puppet-skeleton.js';
/**
* The Fixture
*/
import { PuppetTest, } from '../../tests/fixtures/puppet-test/puppet-test.js';
test('contactQueryFilterFunction()', async (t) => {
const TEXT_REGEX = 'query by regex';
const TEXT_TEXT = 'query by text';
const PAYLOAD_LIST = [
{
alias: TEXT_TEXT,
avatar: 'mock',
gender: ContactGender.Unknown,
id: 'id1',
name: TEXT_REGEX,
phone: [],
type: ContactType.Individual,
},
{
alias: TEXT_REGEX,
avatar: 'mock',
gender: ContactGender.Unknown,
id: 'id2',
name: TEXT_TEXT,
phone: [],
type: ContactType.Individual,
},
{
alias: TEXT_TEXT,
avatar: 'mock',
gender: ContactGender.Unknown,
id: 'id3',
name: TEXT_REGEX,
phone: [],
type: ContactType.Individual,
},
{
alias: TEXT_REGEX,
avatar: 'mock',
gender: ContactGender.Unknown,
id: 'id4',
name: TEXT_TEXT,
phone: [],
type: ContactType.Individual,
},
];
const REGEX_VALUE = new RegExp(TEXT_REGEX);
const TEXT_VALUE = TEXT_TEXT;
const puppet = new PuppetTest();
void t.test('filter name by regex', async (t) => {
const QUERY = { name: REGEX_VALUE };
const ID_LIST = ['id1', 'id3'];
const func = puppet.contactQueryFilterFactory(QUERY);
const idList = PAYLOAD_LIST.filter(func).map(payload => payload.id);
t.same(idList, ID_LIST, 'should filter the query to id list');
});
void t.test('filter name by text', async (t) => {
const QUERY = { name: TEXT_VALUE };
const ID_LIST = ['id2', 'id4'];
const func = puppet.contactQueryFilterFactory(QUERY);
const idList = PAYLOAD_LIST.filter(func).map(payload => payload.id);
t.same(idList, ID_LIST, 'should filter query to id list');
});
void t.test('filter alias by regex', async (t) => {
const QUERY = { alias: REGEX_VALUE };
const ID_LIST = ['id2', 'id4'];
const func = puppet.contactQueryFilterFactory(QUERY);
const idList = PAYLOAD_LIST.filter(func).map(payload => payload.id);
t.same(idList, ID_LIST, 'should filter query to id list');
});
void t.test('filter alias by text', async (t) => {
const QUERY = { alias: TEXT_VALUE };
const ID_LIST = ['id1', 'id3'];
const func = puppet.contactQueryFilterFactory(QUERY);
const idList = PAYLOAD_LIST.filter(func).map(payload => payload.id);
t.same(idList, ID_LIST, 'should filter query to id list');
});
void t.test('filter contact existing id', async (t) => {
const QUERY = { id: 'id1' };
const ID_LIST = ['id1'];
const func = puppet.contactQueryFilterFactory(QUERY);
const idList = PAYLOAD_LIST.filter(func).map(payload => payload.id);
t.same(idList, ID_LIST, 'should filter query to id list by id');
});
void t.test('filter contact non-existing id', async (t) => {
const QUERY = { id: 'fasdfsdfasfas' };
const ID_LIST = [];
const func = puppet.contactQueryFilterFactory(QUERY);
const idList = PAYLOAD_LIST.filter(func).map(payload => payload.id);
t.same(idList, ID_LIST, 'should filter query to id list by id');
});
void t.test('throw if filter key unknown', async (t) => {
t.throws(() => puppet.contactQueryFilterFactory({ xxxx: 'test' }), 'should throw');
});
void t.test('throw if filter key are more than one', async (t) => {
t.throws(() => puppet.contactQueryFilterFactory({
alias: 'test',
name: 'test',
}), 'should throw');
});
});
test('roomQueryFilterFunction()', async (t) => {
const TEXT_REGEX = 'query by regex';
const TEXT_TEXT = 'query by text';
const PAYLOAD_LIST = [
{
adminIdList: [],
id: 'id1',
memberIdList: [],
topic: TEXT_TEXT,
},
{
adminIdList: [],
id: 'id2',
memberIdList: [],
topic: TEXT_REGEX,
},
{
adminIdList: [],
id: 'id3',
memberIdList: [],
topic: TEXT_TEXT,
},
{
adminIdList: [],
id: 'id4',
memberIdList: [],
topic: TEXT_REGEX,
},
];
const REGEX_VALUE = new RegExp(TEXT_REGEX);
const TEXT_VALUE = TEXT_TEXT;
const puppet = new PuppetTest();
void t.test('filter name by regex', async (t) => {
const QUERY = { topic: REGEX_VALUE };
const ID_LIST = ['id2', 'id4'];
const func = puppet.roomQueryFilterFactory(QUERY);
const idList = PAYLOAD_LIST.filter(func).map(payload => payload.id);
t.same(idList, ID_LIST, 'should filter the query to id list');
});
void t.test('filter name by text', async (t) => {
const QUERY = { topic: TEXT_VALUE };
const ID_LIST = ['id1', 'id3'];
const func = puppet.roomQueryFilterFactory(QUERY);
const idList = PAYLOAD_LIST.filter(func).map(payload => payload.id);
t.same(idList, ID_LIST, 'should filter query to id list by text');
});
void t.test('filter name by existing id', async (t) => {
const QUERY = { id: 'id4' };
const ID_LIST = ['id4'];
const func = puppet.roomQueryFilterFactory(QUERY);
const idList = PAYLOAD_LIST.filter(func).map(payload => payload.id);
t.same(idList, ID_LIST, 'should filter query to id list by id');
});
void t.test('filter name by non-existing id', async (t) => {
const QUERY = { id: 'fsdfasfasfsdfsaf' };
const ID_LIST = [];
const func = puppet.roomQueryFilterFactory(QUERY);
const idList = PAYLOAD_LIST.filter(func).map(payload => payload.id);
t.same(idList, ID_LIST, 'should filter query to id list by id');
});
void t.test('throw if filter key unknown', async (t) => {
t.throws(() => puppet.roomQueryFilterFactory({ xxx: 'test' }), 'should throw');
});
void t.test('throw if filter key are more than one', async (t) => {
t.throws(() => puppet.roomQueryFilterFactory({
alias: 'test',
topic: 'test',
}), 'should throw');
});
});
/**
* Huan(202110): remove contactRoomList
* because it seems not being used by Wechaty at all
* and it is very to be implemented in the user land
*/
// test('contactRoomList()', async t => {
// const puppet = new PuppetTest()
// const sandbox = sinon.createSandbox()
// const CONTACT_ID_1 = 'contact-id-1'
// const CONTACT_ID_2 = 'contact-id-2'
// const CONTACT_ID_3 = 'contact-id-3'
// const ROOM_ID_1 = 'room-id-1'
// const ROOM_ID_2 = 'room-id-2'
// const ROOM_PAYLOAD_LIST: RoomPayload[] = [
// {
// adminIdList : [],
// id: ROOM_ID_1,
// memberIdList: [
// CONTACT_ID_1,
// CONTACT_ID_2,
// ],
// topic: 'room-topic-1',
// },
// {
// adminIdList : [],
// id: ROOM_ID_2,
// memberIdList: [
// CONTACT_ID_2,
// CONTACT_ID_3,
// ],
// topic: 'room-topic-2',
// },
// ]
// sandbox.stub(puppet, 'roomList').resolves(ROOM_PAYLOAD_LIST.map(payload => payload.id))
// sandbox.stub(puppet, 'roomPayload').callsFake(async roomId => {
// for (const payload of ROOM_PAYLOAD_LIST) {
// if (payload.id === roomId) {
// return payload
// }
// }
// throw new Error('no payload for room id ' + roomId)
// })
// const roomIdList1 = await puppet.contactRoomList(CONTACT_ID_1)
// const roomIdList2 = await puppet.contactRoomList(CONTACT_ID_2)
// const roomIdList3 = await puppet.contactRoomList(CONTACT_ID_3)
// t.same(roomIdList1, [ROOM_ID_1], 'should get room 1 for contact 1')
// t.same(roomIdList2, [ROOM_ID_1, ROOM_ID_2], 'should get room 1&2 for contact 2')
// t.same(roomIdList3, [ROOM_ID_2], 'should get room 2 for contact 3')
// })
/**
* Huan(202110): the reset logic has been refactored
* See: reset() method and 'reset' event breaking change #157
* https://github.com/wechaty/puppet/issues/157
*/
test.skip('reset event throttle for reset()', async (t) => {
const puppet = new PuppetTest({});
const sandbox = sinon.createSandbox();
const timer = sandbox.useFakeTimers();
const reset = sandbox.stub(puppet, 'reset');
await puppet.start();
puppet.emit('reset', { data: 'testing' });
t.equal(reset.callCount, 1, 'should call reset() immediately');
timer.tick(1000 - 1);
puppet.emit('reset', { data: 'testing 2' });
t.equal(reset.callCount, 1, 'should not call reset() again in the following 1 second');
timer.tick(1000 + 1);
puppet.emit('reset', { data: 'testing 2' });
t.equal(reset.callCount, 2, 'should call reset() again after 1 second');
sandbox.restore();
});
test('set memory() memory with a name', async (t) => {
const puppet = new PuppetTest();
const memory = new MemoryCard({ name: 'name' });
t.doesNotThrow(() => puppet.setMemory(memory), 'should not throw when set a named memory first time ');
t.throws(() => puppet.setMemory(memory), 'should throw when set a named memory second time');
});
test('messageQueryFilterFactory() one condition', async (t) => {
const EXPECTED_TEXT1 = 'text';
const EXPECTED_TEXT2 = 'regexp';
const EXPECTED_TEXT3 = 'fdsafasdfsdakljhj;lds';
const EXPECTED_ID1 = 'id1';
const TEXT_QUERY_TEXT = EXPECTED_TEXT1;
const TEXT_QUERY_ID = EXPECTED_ID1;
const TEXT_QUERY_RE = new RegExp(EXPECTED_TEXT2);
const QUERY_TEXT = {
text: TEXT_QUERY_TEXT,
};
const QUERY_RE = {
text: TEXT_QUERY_RE,
};
const QUERY_ID = {
id: TEXT_QUERY_ID,
};
const PAYLOAD_LIST = [
{
id: EXPECTED_ID1,
text: EXPECTED_TEXT1,
},
{
text: EXPECTED_TEXT2,
},
{
text: EXPECTED_TEXT3,
},
];
const puppet = new PuppetTest();
let filterFuncText;
let resultPayload;
filterFuncText = puppet.messageQueryFilterFactory(QUERY_TEXT);
resultPayload = PAYLOAD_LIST.filter(filterFuncText);
t.equal(resultPayload.length, 1, 'should get one result');
t.equal(resultPayload[0].text, EXPECTED_TEXT1, 'should get text1');
filterFuncText = puppet.messageQueryFilterFactory(QUERY_RE);
resultPayload = PAYLOAD_LIST.filter(filterFuncText);
t.equal(resultPayload.length, 1, 'should get one result');
t.equal(resultPayload[0].text, EXPECTED_TEXT2, 'should get text2');
filterFuncText = puppet.messageQueryFilterFactory(QUERY_ID);
resultPayload = PAYLOAD_LIST.filter(filterFuncText);
t.equal(resultPayload.length, 1, 'should get one result');
t.equal(resultPayload[0].id, EXPECTED_ID1, 'should get id1');
});
test('messageQueryFilterFactory() two condition', async (t) => {
const EXPECTED_TEXT_DATA = 'data';
const EXPECTED_TEXT_LINK = 'https://google.com';
const EXPECTED_TYPE_URL = MessageType.Url;
const EXPECTED_TYPE_TEXT = MessageType.Text;
const QUERY_TEXT = {
text: EXPECTED_TEXT_DATA,
};
const QUERY_TYPE = {
type: EXPECTED_TYPE_URL,
};
const QUERY_TYPE_TEXT = {
text: EXPECTED_TEXT_DATA,
type: EXPECTED_TYPE_URL,
};
const PAYLOAD_LIST = [
{
text: EXPECTED_TEXT_DATA,
type: MessageType.Text,
},
{
text: EXPECTED_TEXT_DATA,
type: MessageType.Url,
},
{
text: EXPECTED_TEXT_LINK,
type: MessageType.Text,
},
{
text: EXPECTED_TEXT_LINK,
type: MessageType.Url,
},
];
const puppet = new PuppetTest();
let filterFuncText;
let resultPayload;
filterFuncText = puppet.messageQueryFilterFactory(QUERY_TEXT);
resultPayload = PAYLOAD_LIST.filter(filterFuncText);
t.equal(resultPayload.length, 2, 'should get two result');
t.equal(resultPayload[0].text, EXPECTED_TEXT_DATA, 'should get text data');
t.equal(resultPayload[0].type, EXPECTED_TYPE_TEXT, 'should get type text');
t.equal(resultPayload[1].text, EXPECTED_TEXT_DATA, 'should get text data');
t.equal(resultPayload[1].type, EXPECTED_TYPE_URL, 'should get type url');
filterFuncText = puppet.messageQueryFilterFactory(QUERY_TYPE);
resultPayload = PAYLOAD_LIST.filter(filterFuncText);
t.equal(resultPayload.length, 2, 'should get two result');
t.equal(resultPayload[0].text, EXPECTED_TEXT_DATA, 'should get text data');
t.equal(resultPayload[0].type, EXPECTED_TYPE_URL, 'should get type url');
t.equal(resultPayload[1].text, EXPECTED_TEXT_LINK, 'should get text link');
t.equal(resultPayload[1].type, EXPECTED_TYPE_URL, 'should get type url ');
filterFuncText = puppet.messageQueryFilterFactory(QUERY_TYPE_TEXT);
resultPayload = PAYLOAD_LIST.filter(filterFuncText);
t.equal(resultPayload.length, 1, 'should get one result');
t.equal(resultPayload[0].text, EXPECTED_TEXT_DATA, 'should get text data');
t.equal(resultPayload[0].type, EXPECTED_TYPE_URL, 'should get type url');
});
test('name()', async (t) => {
const puppet = new PuppetTest();
const name = puppet.name();
const EXPECTED_NAME = 'puppet-test';
t.equal(name, EXPECTED_NAME, 'should get the child class package name');
});
test('version()', async (t) => {
const puppet = new PuppetTest();
const version = puppet.version();
const EXPECTED_VERSION = '1.0.0';
t.equal(version, EXPECTED_VERSION, 'should get the child class package version');
});
test('PuppetSkeleton: super.{start,stop}()', async (t) => {
const sandbox = sinon.createSandbox();
const startStub = sandbox.stub(PuppetSkeleton.prototype, 'start').resolves();
const stopStub = sandbox.stub(PuppetSkeleton.prototype, 'stop').resolves();
const puppet = new PuppetTest();
t.notOk(startStub.called, 'should init start flag with false');
t.notOk(stopStub.called, 'should init stop flag with false');
await puppet.start();
t.ok(startStub.called, 'should call the skeleton start(), which means all mixin start()s are chained correctly');
t.notOk(stopStub.called, 'should keep stop flag with false');
await puppet.stop();
t.ok(startStub.called, 'should keep start flag with true');
t.ok(stopStub.called, 'should call the skeleton stop(), which means all mixin stops()s are chained correctly');
sandbox.restore();
});
//# sourceMappingURL=puppet-abstract.spec.js.map