Skip to content

Commit cfa22d0

Browse files
authored
Use spies for CloudCode logger tests (#5042)
1 parent 617e840 commit cfa22d0

File tree

1 file changed

+82
-92
lines changed

1 file changed

+82
-92
lines changed

spec/CloudCodeLogger.spec.js

Lines changed: 82 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,35 @@ const loremFile = __dirname + '/support/lorem.txt';
99

1010
describe('Cloud Code Logger', () => {
1111
let user;
12-
13-
beforeEach(done => {
12+
let spy;
13+
beforeEach(async () => {
1414
Parse.User.enableUnsafeCurrentUser();
1515
return reconfigureServer({
1616
// useful to flip to false for fine tuning :).
1717
silent: true,
18-
}).then(() => {
19-
return Parse.User.signUp('tester', 'abc')
20-
.then(loggedInUser => (user = loggedInUser))
21-
.then(() => Parse.User.logIn(user.get('username'), 'abc'))
22-
.then(() => done());
23-
});
18+
})
19+
.then(() => {
20+
return Parse.User.signUp('tester', 'abc')
21+
.catch(() => {})
22+
.then(loggedInUser => (user = loggedInUser))
23+
.then(() => Parse.User.logIn(user.get('username'), 'abc'));
24+
})
25+
.then(() => {
26+
spy = spyOn(
27+
Config.get('test').loggerController.adapter,
28+
'log'
29+
).and.callThrough();
30+
});
2431
});
2532

2633
// Note that helpers takes care of logout.
2734
// see helpers.js:afterEach
2835

2936
it('should expose log to functions', () => {
30-
const config = Config.get('test');
31-
const spy = spyOn(config.loggerController, 'log').and.callThrough();
32-
37+
const spy = spyOn(
38+
Config.get('test').loggerController,
39+
'log'
40+
).and.callThrough();
3341
Parse.Cloud.define('loggerTest', req => {
3442
req.log.info('logTest', 'info log', { info: 'some log' });
3543
req.log.error('logTest', 'error log', { error: 'there was an error' });
@@ -61,26 +69,21 @@ describe('Cloud Code Logger', () => {
6169
});
6270

6371
it('trigger should obfuscate password', done => {
64-
const logController = new LoggerController(new WinstonLoggerAdapter());
65-
6672
Parse.Cloud.beforeSave(Parse.User, req => {
6773
return req.object;
6874
});
6975

7076
Parse.User.signUp('tester123', 'abc')
71-
.then(() => logController.getLogs({ from: Date.now() - 500, size: 1000 }))
72-
.then(res => {
73-
const entry = res[0];
74-
expect(entry.message).not.toMatch(/password":"abc/);
75-
expect(entry.message).toMatch(/\*\*\*\*\*\*\*\*/);
77+
.then(() => {
78+
const entry = spy.calls.mostRecent().args;
79+
expect(entry[1]).not.toMatch(/password":"abc/);
80+
expect(entry[1]).toMatch(/\*\*\*\*\*\*\*\*/);
7681
done();
7782
})
7883
.then(null, e => done.fail(e));
7984
});
8085

8186
it('should expose log to trigger', done => {
82-
const logController = new LoggerController(new WinstonLoggerAdapter());
83-
8487
Parse.Cloud.beforeSave('MyObject', req => {
8588
req.log.info('beforeSave MyObject', 'info log', { info: 'some log' });
8689
req.log.error('beforeSave MyObject', 'error log', {
@@ -90,31 +93,29 @@ describe('Cloud Code Logger', () => {
9093
});
9194

9295
const obj = new Parse.Object('MyObject');
93-
obj
94-
.save()
95-
.then(() => {
96-
return logController.getLogs({ from: Date.now() - 500, size: 1000 });
97-
})
98-
.then(res => {
99-
expect(res.length).not.toBe(0);
100-
const lastLogs = res.slice(0, 3);
101-
const cloudTriggerMessage = lastLogs[0];
102-
const errorMessage = lastLogs[1];
103-
const infoMessage = lastLogs[2];
104-
expect(cloudTriggerMessage.level).toBe('info');
105-
expect(cloudTriggerMessage.triggerType).toEqual('beforeSave');
106-
expect(cloudTriggerMessage.message).toMatch(
107-
/beforeSave triggered for MyObject for user [^ ]*\n {2}Input: {}\n {2}Result: {}/
108-
);
109-
expect(cloudTriggerMessage.user).toBe(user.id);
110-
expect(errorMessage.level).toBe('error');
111-
expect(errorMessage.error).toBe('there was an error');
112-
expect(errorMessage.message).toBe('beforeSave MyObject error log');
113-
expect(infoMessage.level).toBe('info');
114-
expect(infoMessage.info).toBe('some log');
115-
expect(infoMessage.message).toBe('beforeSave MyObject info log');
116-
done();
117-
});
96+
obj.save().then(() => {
97+
const lastCalls = spy.calls.all().reverse();
98+
const cloudTriggerMessage = lastCalls[0].args;
99+
const errorMessage = lastCalls[1].args;
100+
const infoMessage = lastCalls[2].args;
101+
expect(cloudTriggerMessage[0]).toBe('info');
102+
expect(cloudTriggerMessage[2].triggerType).toEqual('beforeSave');
103+
expect(cloudTriggerMessage[1]).toMatch(
104+
/beforeSave triggered for MyObject for user [^ ]*\n {2}Input: {}\n {2}Result: {}/
105+
);
106+
expect(cloudTriggerMessage[2].user).toBe(user.id);
107+
expect(errorMessage[0]).toBe('error');
108+
expect(errorMessage[3].error).toBe('there was an error');
109+
expect(errorMessage[1] + ' ' + errorMessage[2]).toBe(
110+
'beforeSave MyObject error log'
111+
);
112+
expect(infoMessage[0]).toBe('info');
113+
expect(infoMessage[3].info).toBe('some log');
114+
expect(infoMessage[1] + ' ' + infoMessage[2]).toBe(
115+
'beforeSave MyObject info log'
116+
);
117+
done();
118+
});
118119
});
119120

120121
it('should truncate really long lines when asked to', () => {
@@ -125,18 +126,16 @@ describe('Cloud Code Logger', () => {
125126
});
126127

127128
it('should truncate input and result of long lines', done => {
128-
const logController = new LoggerController(new WinstonLoggerAdapter());
129129
const longString = fs.readFileSync(loremFile, 'utf8');
130130
Parse.Cloud.define('aFunction', req => {
131131
return req.params;
132132
});
133133

134134
Parse.Cloud.run('aFunction', { longString })
135-
.then(() => logController.getLogs({ from: Date.now() - 500, size: 1000 }))
136-
.then(logs => {
137-
const log = logs[0];
138-
expect(log.level).toEqual('info');
139-
expect(log.message).toMatch(
135+
.then(() => {
136+
const log = spy.calls.mostRecent().args;
137+
expect(log[0]).toEqual('info');
138+
expect(log[1]).toMatch(
140139
/Ran cloud function aFunction for user [^ ]* with:\n {2}Input: {.*?\(truncated\)$/m
141140
);
142141
done();
@@ -145,22 +144,19 @@ describe('Cloud Code Logger', () => {
145144
});
146145

147146
it('should log an afterSave', done => {
148-
const logController = new LoggerController(new WinstonLoggerAdapter());
149147
Parse.Cloud.afterSave('MyObject', () => {});
150148
new Parse.Object('MyObject')
151149
.save()
152-
.then(() => logController.getLogs({ from: Date.now() - 500, size: 1000 }))
153-
.then(logs => {
154-
const log = logs[0];
155-
expect(log.triggerType).toEqual('afterSave');
150+
.then(() => {
151+
const log = spy.calls.mostRecent().args;
152+
expect(log[2].triggerType).toEqual('afterSave');
156153
done();
157154
})
158155
// catch errors - not that the error is actually useful :(
159156
.then(null, e => done.fail(e));
160157
});
161158

162159
it('should log a denied beforeSave', done => {
163-
const logController = new LoggerController(new WinstonLoggerAdapter());
164160
Parse.Cloud.beforeSave('MyObject', () => {
165161
throw 'uh oh!';
166162
});
@@ -171,54 +167,51 @@ describe('Cloud Code Logger', () => {
171167
() => done.fail('this is not supposed to succeed'),
172168
() => new Promise(resolve => setTimeout(resolve, 100))
173169
)
174-
.then(() => logController.getLogs({ from: Date.now() - 500, size: 1000 }))
175-
.then(logs => {
176-
const log = logs[1]; // 0 is the 'uh oh!' from rejection...
177-
expect(log.level).toEqual('error');
178-
expect(log.error).toEqual({ code: 141, message: 'uh oh!' });
170+
.then(() => {
171+
const logs = spy.calls.all().reverse();
172+
const log = logs[1].args; // 0 is the 'uh oh!' from rejection...
173+
expect(log[0]).toEqual('error');
174+
const error = log[2].error;
175+
expect(error instanceof Parse.Error).toBeTruthy();
176+
expect(error.code).toBe(141);
177+
expect(error.message).toBe('uh oh!');
179178
done();
180179
});
181180
});
182181

183182
it('should log cloud function success', done => {
184-
const logController = new LoggerController(new WinstonLoggerAdapter());
185-
186183
Parse.Cloud.define('aFunction', () => {
187184
return 'it worked!';
188185
});
189186

190-
Parse.Cloud.run('aFunction', { foo: 'bar' })
191-
.then(() => logController.getLogs({ from: Date.now() - 500, size: 1000 }))
192-
.then(logs => {
193-
const log = logs[0];
194-
expect(log.level).toEqual('info');
195-
expect(log.message).toMatch(
196-
/Ran cloud function aFunction for user [^ ]* with:\n {2}Input: {"foo":"bar"}\n {2}Result: "it worked!/
197-
);
198-
done();
199-
});
187+
Parse.Cloud.run('aFunction', { foo: 'bar' }).then(() => {
188+
const log = spy.calls.mostRecent().args;
189+
expect(log[0]).toEqual('info');
190+
expect(log[1]).toMatch(
191+
/Ran cloud function aFunction for user [^ ]* with:\n {2}Input: {"foo":"bar"}\n {2}Result: "it worked!/
192+
);
193+
done();
194+
});
200195
});
201196

202197
it('should log cloud function failure', done => {
203-
const logController = new LoggerController(new WinstonLoggerAdapter());
204-
205198
Parse.Cloud.define('aFunction', () => {
206199
throw 'it failed!';
207200
});
208201

209202
Parse.Cloud.run('aFunction', { foo: 'bar' })
210-
.then(null, () =>
211-
logController.getLogs({ from: Date.now() - 500, size: 1000 })
212-
)
213-
.then(logs => {
214-
expect(logs[0].message).toBe('it failed!');
215-
const log = logs[1];
216-
expect(log.level).toEqual('error');
217-
expect(log.message).toMatch(
218-
/Failed running cloud function aFunction for user [^ ]* with:\n {2}Input: {"foo":"bar"}\n {2}Error: {"code":141,"message":"it failed!"}/
203+
.catch(() => {})
204+
.then(() => {
205+
const logs = spy.calls.all().reverse();
206+
expect(logs[0].args[1]).toBe('it failed!');
207+
const log = logs[1].args;
208+
expect(log[0]).toEqual('error');
209+
expect(log[1]).toMatch(
210+
/Failed running cloud function aFunction for user [^ ]* with:\n {2}Input: {"foo":"bar"}\n {2}Error:/
219211
);
220212
done();
221-
});
213+
})
214+
.catch(done.fail);
222215
});
223216

224217
xit('should log a changed beforeSave indicating a change', done => {
@@ -247,17 +240,14 @@ describe('Cloud Code Logger', () => {
247240
}).pend('needs more work.....');
248241

249242
it('cloud function should obfuscate password', done => {
250-
const logController = new LoggerController(new WinstonLoggerAdapter());
251-
252243
Parse.Cloud.define('testFunction', () => {
253244
return 'verify code success';
254245
});
255246

256247
Parse.Cloud.run('testFunction', { username: 'hawk', password: '123456' })
257-
.then(() => logController.getLogs({ from: Date.now() - 500, size: 1000 }))
258-
.then(res => {
259-
const entry = res[0];
260-
expect(entry.params.password).toMatch(/\*\*\*\*\*\*\*\*/);
248+
.then(() => {
249+
const entry = spy.calls.mostRecent().args;
250+
expect(entry[2].params.password).toMatch(/\*\*\*\*\*\*\*\*/);
261251
done();
262252
})
263253
.then(null, e => done.fail(e));

0 commit comments

Comments
 (0)