xmpp-bot/test/xmpp.js

304 lines
8.8 KiB
JavaScript
Raw Normal View History

'use strict'
2019-10-20 03:01:59 +02:00
process.env.NODE_ENV = 'production'
const sinon = require('sinon')
const EventEmitter = require('events').EventEmitter
const mock = require('mock-require')
const xml = require('@xmpp/xml')
const jid = require('@xmpp/jid')
2019-10-20 03:01:59 +02:00
describe('XMPP component', () => {
const simpleXmppEvents = new EventEmitter()
2019-11-21 23:33:28 +01:00
let logger, config, outgoingStub, xmppSendStub, xmppCloseStub
before('Setup', (done) => {
// create default logger
logger = require('./../lib/logger')()
// get configuration
config = require('./../lib/config')(logger, './test/config.json')
// update logger with configuration
logger.updateConfig(config.logger)
// mock @xmpp/client module
xmppSendStub = sinon.stub().resolves()
2019-11-21 23:33:28 +01:00
xmppCloseStub = sinon.stub().resolves()
mock('@xmpp/client', {
client: () => {
this.start = async () => {}
2019-11-21 23:33:28 +01:00
this.stop = xmppCloseStub
this.send = xmppSendStub
this.on = (eventName, callback) => {
simpleXmppEvents.on(eventName, callback)
}
return this
},
xml: require('@xmpp/xml'),
jid: require('@xmpp/jid')
})
// mock outgoing
outgoingStub = sinon.stub()
mock('./../lib/outgoing', outgoingStub)
2019-11-21 23:33:28 +01:00
// mock logger trace
sinon.stub(logger, 'trace')
done()
})
2019-10-20 03:01:59 +02:00
after('Remove mocks', (done) => {
mock.stopAll()
2019-11-21 23:33:28 +01:00
logger.trace.restore()
done()
})
2019-10-20 03:01:59 +02:00
2019-11-21 23:33:28 +01:00
beforeEach('Reset outgoing and xmpp stub history', function () {
2019-10-20 03:01:59 +02:00
outgoingStub.resetHistory()
2019-11-21 23:33:28 +01:00
xmppSendStub.resetHistory()
xmppCloseStub.resetHistory()
2019-10-20 03:01:59 +02:00
})
describe('Connect to XMPP server', () => {
it('Should connect to XMPP server and join rooms when application start', (done) => {
require('./../lib/xmpp')(logger, config)
simpleXmppEvents.emit('online', jid('bot@domain-xmpp.ltd/resource'))
sinon.assert.called(xmppSendStub)
// 1 "send" call for presence and n "send" calls for joining rooms
2019-10-20 03:01:59 +02:00
let roomsLength = config.xmpp.rooms.length
sinon.assert.callCount(xmppSendStub, roomsLength + 1)
for (let index = 1; index < roomsLength + 1; index++) {
const args = xmppSendStub.args[index]
args.should.have.length(1)
let occupantJid = config.xmpp.rooms[index - 1].id + '/' + 'bot'
const stanza = xml(
'presence', {
to: occupantJid
},
xml(
'x', {
xmlns: 'http://jabber.org/protocol/muc'
}
)
)
args[0].should.deep.equal(stanza)
2019-10-20 03:01:59 +02:00
}
done()
})
2019-11-21 23:33:28 +01:00
it('Should trace connection status', (done) => {
simpleXmppEvents.emit('status', 'connecting')
sinon.assert.calledWith(logger.trace, 'Status changed to connecting')
done()
})
})
describe('Bot receive a presence stanza from someone', () => {
it('Should not trigger outgoing webhook', (done) => {
simpleXmppEvents.emit('stanza', xml(
'presence', {
from: 'someone@domain-xmpp.ltd',
to: 'bot@domain-xmpp.ltd'
}
))
sinon.assert.notCalled(outgoingStub)
done()
})
})
describe('Bot receive an empty message from someone', () => {
it('Should not trigger outgoing webhook', (done) => {
simpleXmppEvents.emit('stanza', xml(
'message', {
from: 'someone@domain-xmpp.ltd',
to: 'bot@domain-xmpp.ltd',
type: 'chat'
}
))
sinon.assert.notCalled(outgoingStub)
done()
})
2019-10-20 03:01:59 +02:00
})
describe('Bot receive a message from someone', () => {
2019-11-22 00:20:04 +01:00
it('Should trigger outgoing webhook with valid arguments and send a message delivery receipt', (done) => {
simpleXmppEvents.emit('stanza', xml(
'message', {
from: 'someone@domain-xmpp.ltd',
to: 'bot@domain-xmpp.ltd',
2019-11-22 00:20:04 +01:00
type: 'chat',
id: 'fcdd3d8c'
},
xml(
'body', {
},
2019-11-22 00:20:04 +01:00
'This is the message text'),
xml(
'request', {
xmlns: 'urn:xmpp:receipts'
})
))
2019-10-20 03:01:59 +02:00
sinon.assert.calledOnce(outgoingStub)
const args = outgoingStub.args[0]
args.should.have.length(8)
args[3].should.equal('someone')
args[4].should.equal('someone@domain-xmpp.ltd')
2019-10-20 03:01:59 +02:00
args[5].should.equal('This is the message text')
args[6].should.equal('chat')
2019-10-20 03:01:59 +02:00
args[7].should.equal('w1')
2019-11-22 00:20:04 +01:00
sinon.assert.calledOnce(xmppSendStub)
const receiptStanza = xml(
'message', {
to: 'someone@domain-xmpp.ltd'
},
xml(
'received', {
xmlns: 'urn:xmpp:receipts',
id: 'fcdd3d8c'
}
)
)
xmppSendStub.args[0][0].should.deep.equal(receiptStanza)
2019-10-20 03:01:59 +02:00
done()
})
})
describe('Bot receive a message from himself in a room', () => {
it('Should not trigger outgoing webhook', (done) => {
simpleXmppEvents.emit('stanza', xml(
'message', {
from: 'roomname@conference.domain-xmpp.ltd/bot',
to: 'roomname@conference.domain-xmpp.ltd',
type: 'groupchat'
},
xml(
'body', {
},
'This is the message text')
))
2019-10-20 03:01:59 +02:00
sinon.assert.notCalled(outgoingStub)
done()
})
})
describe('Bot receive a message in an unknown room', () => {
it('Should not trigger outgoing webhook', (done) => {
simpleXmppEvents.emit('stanza', xml(
'message', {
from: 'unknownroomname@conference.domain-xmpp.ltd/someone',
to: 'unknownroomname@conference.domain-xmpp.ltd',
type: 'groupchat'
},
xml(
'body', {
},
'This is the message text')
))
2019-10-20 03:01:59 +02:00
sinon.assert.notCalled(outgoingStub)
done()
})
})
describe('Bot receive an old message in a room', () => {
it('Should not trigger outgoing webhook', (done) => {
simpleXmppEvents.emit('groupchat', 'roomname@conference.domain-xmpp.ltd', 'someone', 'This is the message text', 'stamp')
simpleXmppEvents.emit('stanza', xml(
'message', {
from: 'roomname@conference.domain-xmpp.ltd/someone',
to: 'roomname@conference.domain-xmpp.ltd',
type: 'groupchat'
},
xml(
'body', {
},
'This is the message text'),
xml(
'delay', {
xmlns: 'urn:xmpp:delay',
from: 'roomname@conference.domain-xmpp.ltd'
},
'This is the message text')
))
2019-10-20 03:01:59 +02:00
sinon.assert.notCalled(outgoingStub)
done()
})
})
describe('Bot receive a message in a room', () => {
it('Should trigger outgoing webhook with valid arguments', (done) => {
simpleXmppEvents.emit('stanza', xml(
'message', {
from: 'roomname@conference.domain-xmpp.ltd/someone',
to: 'roomname@conference.domain-xmpp.ltd',
type: 'groupchat'
},
xml(
'body', {
},
'This is the message text')
))
2019-10-20 03:01:59 +02:00
sinon.assert.calledOnce(outgoingStub)
const args = outgoingStub.args[0]
args.should.have.length(8)
args[3].should.equal('someone')
args[4].should.equal('roomname@conference.domain-xmpp.ltd')
args[5].should.equal('This is the message text')
args[6].should.equal('groupchat')
2019-10-20 03:01:59 +02:00
args[7].should.equal('w1')
done()
})
})
2019-11-21 23:33:28 +01:00
describe('Send a message', () => {
it('Should call xmpp/client.send() with valid stanza', (done) => {
const xmpp = require('./../lib/xmpp')(logger, config)
xmpp.send('someone@domain-xmpp.ltd', 'This is the message text sent by bot', 'chat')
sinon.assert.calledOnce(xmppSendStub)
let stanza = xml(
'message', {
to: 'someone@domain-xmpp.ltd',
type: 'chat'
},
xml(
'body', {
},
'This is the message text sent by bot')
)
const args = xmppSendStub.args[0]
args.should.have.length(1)
args[0].should.deep.equal(stanza)
done()
})
})
describe('Close connection', () => {
it('Should call xmpp/client.stop()', (done) => {
const xmpp = require('./../lib/xmpp')(logger, config)
xmpp.close()
sinon.assert.calledOnce(xmppCloseStub)
done()
})
})
2019-10-20 03:01:59 +02:00
describe('XMPP server send an error', () => {
before(() => {
sinon.stub(process, 'exit')
})
after(() => {
process.exit.restore()
})
it('Should log error and exit with 99 code', (done) => {
2019-10-20 03:01:59 +02:00
let error = 'This the error text'
simpleXmppEvents.emit('error', new Error(error))
2019-10-20 03:01:59 +02:00
require('fs').readFile(config.logger.file.path + config.logger.file.filename, 'utf8', (err, data) => {
if (err) {
throw err
}
data.should.match(new RegExp('XMPP client encountered following error: ' + error + '\n$'))
sinon.assert.calledWith(process.exit, 99)
2019-10-20 03:01:59 +02:00
done()
})
})
})
})