Skip to content

Commit ad334ac

Browse files
committed
Add unit tests for instance and device crash/safe mode notifications
1 parent d8c452c commit ad334ac

1 file changed

Lines changed: 85 additions & 7 deletions

File tree

test/unit/forge/routes/logging/index_spec.js

Lines changed: 85 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const should = require('should') // eslint-disable-line
22
const sinon = require('sinon')
33

4+
const { Roles } = require('../../../../../forge/lib/roles')
45
const setup = require('../setup')
56

67
describe('Logging API', function () {
@@ -17,27 +18,43 @@ describe('Logging API', function () {
1718
device1: null,
1819
device2: null
1920
},
20-
team1: null,
21+
ATeam: null,
2122
project1: null,
2223
project2: null,
2324
device1: null,
2425
device2: null,
25-
alice: null
26+
alice: null,
27+
bob: null,
28+
chris: null,
29+
dave: null
2630
}
2731

2832
before(async function () {
2933
app = await setup({})
3034
factory = app.factory
35+
TestObjects.ATeam = app.team
3136
TestObjects.application = app.application
3237
TestObjects.alice = await app.db.models.User.byUsername('alice')
33-
TestObjects.team1 = app.team
38+
// owner of ATeam
39+
TestObjects.bob = await app.db.models.User.create({ username: 'bob', name: 'Bob Fett', email: 'bob@example.com', password: 'bbPassword', sso_enabled: true })
40+
await app.db.controllers.Team.addUser(TestObjects.ATeam, TestObjects.bob, Roles.Owner)
41+
// member of ATeam
42+
TestObjects.chris = await app.db.models.User.create({ username: 'chris', name: 'Chris Kenobi', email: 'chris@example.com', password: 'ccPassword', sso_enabled: true })
43+
await app.db.controllers.Team.addUser(TestObjects.ATeam, TestObjects.chris, Roles.Member)
44+
// viewer of ATeam
45+
TestObjects.dave = await app.db.models.User.create({ username: 'dave', name: 'Dave Vader', email: 'dave@example.com', password: 'ddPassword', sso_enabled: true })
46+
await app.db.controllers.Team.addUser(TestObjects.ATeam, TestObjects.dave, Roles.Viewer)
47+
// dashboard viewer of ATeam
48+
TestObjects.eve = await app.db.models.User.create({ username: 'eve', name: 'Eve Skywalker', email: 'eve@example.com', password: 'eePassword', sso_enabled: true })
49+
await app.db.controllers.Team.addUser(TestObjects.ATeam, TestObjects.eve, Roles.Dashboard)
50+
3451
TestObjects.project1 = app.project
3552
TestObjects.project2 = await app.db.models.Project.create({ name: 'project2', type: '', url: '' })
36-
const device1 = await factory.createDevice({ name: generateName('device-1') }, TestObjects.team1, null, TestObjects.application)
53+
const device1 = await factory.createDevice({ name: generateName('device-1') }, TestObjects.ATeam, null, TestObjects.application)
3754
TestObjects.device1 = await app.db.models.Device.byId(device1.id)
38-
const device2 = await factory.createDevice({ name: generateName('device-2') }, TestObjects.team1, null, TestObjects.application)
55+
const device2 = await factory.createDevice({ name: generateName('device-2') }, TestObjects.ATeam, null, TestObjects.application)
3956
TestObjects.device2 = await app.db.models.Device.byId(device2.id)
40-
await TestObjects.team1.addProject(TestObjects.project2)
57+
await TestObjects.ATeam.addProject(TestObjects.project2)
4158
TestObjects.tokens.project1 = (await TestObjects.project1.refreshAuthTokens()).token
4259
TestObjects.tokens.project2 = (await TestObjects.project2.refreshAuthTokens()).token
4360
TestObjects.tokens.device1 = (await TestObjects.device1.refreshAuthTokens()).token
@@ -54,7 +71,7 @@ describe('Logging API', function () {
5471
after(async () => {
5572
app && await app.close()
5673
delete TestObjects.tokens
57-
delete TestObjects.team1
74+
delete TestObjects.ATeam
5875
delete TestObjects.project1
5976
delete TestObjects.project2
6077
delete TestObjects.device1
@@ -63,7 +80,9 @@ describe('Logging API', function () {
6380
delete TestObjects.application
6481
app.db.controllers.Project.addProjectModule.restore()
6582
app.db.controllers.Project.removeProjectModule.restore()
83+
sinon.restore()
6684
})
85+
6786
describe('instance audit logging', function () {
6887
it('Accepts valid token', async function () {
6988
const url = `/logging/${TestObjects.project1.id}/audit`
@@ -374,4 +393,63 @@ describe('Logging API', function () {
374393
})
375394
})
376395
})
396+
397+
describe('adds notification', function () {
398+
beforeEach(function () {
399+
sinon.stub(app.notifications, 'send')
400+
})
401+
afterEach(async function () {
402+
await app.db.models.Notification.destroy({ where: {} })
403+
app.notifications.send.restore()
404+
})
405+
it('for every member and owner when instance crashed', async function () {
406+
await testSimulateLogEvent('instance', 'crashed', 'error', TestObjects.project1, TestObjects.tokens.project1)
407+
})
408+
it('for every member and owner when device crashed', async function () {
409+
await testSimulateLogEvent('device', 'crashed', 'error', TestObjects.device1, TestObjects.tokens.device1)
410+
})
411+
it('for every member and owner when instance safe-mode', async function () {
412+
await testSimulateLogEvent('instance', 'safe-mode', 'warning', TestObjects.project1, TestObjects.tokens.project1)
413+
})
414+
it('for every member and owner when device safe-mode', async function () {
415+
await testSimulateLogEvent('device', 'safe-mode', 'warning', TestObjects.device1, TestObjects.tokens.device1)
416+
})
417+
418+
async function testSimulateLogEvent (kind, event, severity, model, token) {
419+
const id = kind === 'instance' ? model.id : model.hashid
420+
const type = `${kind}-${event}`
421+
const reference = `${type}:${id}`
422+
const baseUrl = kind === 'instance' ? '/logging' : '/logging/device'
423+
const url = `${baseUrl}/${id}/audit`
424+
const response = await app.inject({
425+
method: 'POST',
426+
url,
427+
headers: {
428+
authorization: `Bearer ${token}`
429+
},
430+
payload: { event }
431+
})
432+
response.should.have.property('statusCode', 200)
433+
// should be called for every member and owner
434+
app.notifications.send.callCount.should.equal(3) // alice, bob, chris
435+
const calls = app.notifications.send.getCalls()
436+
for (const call of calls) {
437+
const args = call.args
438+
// func signature of notification.send (user, type, data, reference = null, options = null)
439+
args.should.have.length(5)
440+
args[0].should.be.an.instanceOf(app.db.models.User)
441+
args[0].should.have.property('id').and.be.oneOf([TestObjects.alice.id, TestObjects.bob.id, TestObjects.chris.id])
442+
args[1].should.equal(type)
443+
args[2].should.be.an.Object()
444+
args[2].should.have.property(kind).and.be.an.Object() // instance or device
445+
args[2][kind].should.have.property('id').and.equal(id)
446+
args[2][kind].should.have.property('name').and.equal(model.name)
447+
args[2].should.have.property('meta').and.be.an.Object()
448+
args[2].meta.should.have.property('severity', severity)
449+
args[3].should.equal(reference)
450+
args[4].should.be.an.Object()
451+
args[4].should.have.property('upsert', true) // crash and safe notifications use upsert option
452+
}
453+
}
454+
})
377455
})

0 commit comments

Comments
 (0)