* ⚡ Release 3.1.3 (#5267) * ⚡ Release 3.1.3 * Update CHANGELOG.md * ⬆️ Bump winston and winston-daily-rotate-file Bumps [winston](https://github.com/winstonjs/winston) and [winston-daily-rotate-file](https://github.com/winstonjs/winston-daily-rotate-file). These dependencies needed to be updated together. Updates `winston` from 2.4.4 to 3.1.0 - [Release notes](https://github.com/winstonjs/winston/releases) - [Changelog](https://github.com/winstonjs/winston/blob/master/CHANGELOG.md) - [Commits](https://github.com/winstonjs/winston/compare/2.4.4...3.1.0) Updates `winston-daily-rotate-file` from 1.7.2 to 3.5.1 - [Release notes](https://github.com/winstonjs/winston-daily-rotate-file/releases) - [Commits](https://github.com/winstonjs/winston-daily-rotate-file/compare/v1.7.2...v3.5.1) Signed-off-by: dependabot[bot] <support@dependabot.com> * Rewrote WinstonLogger to work with winston 3.x api * Changed winston logger test to use winston-transport * Added winston-transport dependency * Close and remove transports before adding them again * Changed to strict equal * Override adapter name * Updated and added getLogs tests * Bump winston and winston-daily-rotate-file Bumps [winston](https://github.com/winstonjs/winston) and [winston-daily-rotate-file](https://github.com/winstonjs/winston-daily-rotate-file). These dependencies needed to be updated together. Updates `winston` from 2.4.4 to 3.2.0 - [Release notes](https://github.com/winstonjs/winston/releases) - [Changelog](https://github.com/winstonjs/winston/blob/master/CHANGELOG.md) - [Commits](https://github.com/winstonjs/winston/compare/2.4.4...3.2.0) Updates `winston-daily-rotate-file` from 1.7.2 to 3.6.0 - [Release notes](https://github.com/winstonjs/winston-daily-rotate-file/releases) - [Commits](https://github.com/winstonjs/winston-daily-rotate-file/compare/v1.7.2...v3.6.0) Signed-off-by: dependabot[bot] <support@dependabot.com> * Fixed tests, updated parse logging * Fixed tests, better error logging * Fix failing tests * Updates as per review
290 lines
9.0 KiB
JavaScript
290 lines
9.0 KiB
JavaScript
'use strict';
|
|
|
|
const MongoStorageAdapter = require('../lib/Adapters/Storage/Mongo/MongoStorageAdapter')
|
|
.default;
|
|
const { MongoClient } = require('mongodb');
|
|
const databaseURI =
|
|
'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase';
|
|
|
|
const fakeClient = {
|
|
s: { options: { dbName: null } },
|
|
db: () => null,
|
|
};
|
|
|
|
// These tests are specific to the mongo storage adapter + mongo storage format
|
|
// and will eventually be moved into their own repo
|
|
describe_only_db('mongo')('MongoStorageAdapter', () => {
|
|
beforeEach(done => {
|
|
new MongoStorageAdapter({ uri: databaseURI })
|
|
.deleteAllClasses()
|
|
.then(done, fail);
|
|
});
|
|
|
|
it('auto-escapes symbols in auth information', () => {
|
|
spyOn(MongoClient, 'connect').and.returnValue(Promise.resolve(fakeClient));
|
|
new MongoStorageAdapter({
|
|
uri:
|
|
'mongodb://user!with@+ symbols:password!with@+ symbols@localhost:1234/parse',
|
|
}).connect();
|
|
expect(MongoClient.connect).toHaveBeenCalledWith(
|
|
'mongodb://user!with%40%2B%20symbols:password!with%40%2B%20symbols@localhost:1234/parse',
|
|
jasmine.any(Object)
|
|
);
|
|
});
|
|
|
|
it("doesn't double escape already URI-encoded information", () => {
|
|
spyOn(MongoClient, 'connect').and.returnValue(Promise.resolve(fakeClient));
|
|
new MongoStorageAdapter({
|
|
uri:
|
|
'mongodb://user!with%40%2B%20symbols:password!with%40%2B%20symbols@localhost:1234/parse',
|
|
}).connect();
|
|
expect(MongoClient.connect).toHaveBeenCalledWith(
|
|
'mongodb://user!with%40%2B%20symbols:password!with%40%2B%20symbols@localhost:1234/parse',
|
|
jasmine.any(Object)
|
|
);
|
|
});
|
|
|
|
// https://github.com/parse-community/parse-server/pull/148#issuecomment-180407057
|
|
it('preserves replica sets', () => {
|
|
spyOn(MongoClient, 'connect').and.returnValue(Promise.resolve(fakeClient));
|
|
new MongoStorageAdapter({
|
|
uri:
|
|
'mongodb://test:testpass@ds056315-a0.mongolab.com:59325,ds059315-a1.mongolab.com:59315/testDBname?replicaSet=rs-ds059415',
|
|
}).connect();
|
|
expect(MongoClient.connect).toHaveBeenCalledWith(
|
|
'mongodb://test:testpass@ds056315-a0.mongolab.com:59325,ds059315-a1.mongolab.com:59315/testDBname?replicaSet=rs-ds059415',
|
|
jasmine.any(Object)
|
|
);
|
|
});
|
|
|
|
it('stores objectId in _id', done => {
|
|
const adapter = new MongoStorageAdapter({ uri: databaseURI });
|
|
adapter
|
|
.createObject('Foo', { fields: {} }, { objectId: 'abcde' })
|
|
.then(() => adapter._rawFind('Foo', {}))
|
|
.then(results => {
|
|
expect(results.length).toEqual(1);
|
|
const obj = results[0];
|
|
expect(obj._id).toEqual('abcde');
|
|
expect(obj.objectId).toBeUndefined();
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('find succeeds when query is within maxTimeMS', done => {
|
|
const maxTimeMS = 250;
|
|
const adapter = new MongoStorageAdapter({
|
|
uri: databaseURI,
|
|
mongoOptions: { maxTimeMS },
|
|
});
|
|
adapter
|
|
.createObject('Foo', { fields: {} }, { objectId: 'abcde' })
|
|
.then(() =>
|
|
adapter._rawFind('Foo', { $where: `sleep(${maxTimeMS / 2})` })
|
|
)
|
|
.then(
|
|
() => done(),
|
|
err => {
|
|
done.fail(`maxTimeMS should not affect fast queries ${err}`);
|
|
}
|
|
);
|
|
});
|
|
|
|
it('find fails when query exceeds maxTimeMS', done => {
|
|
const maxTimeMS = 250;
|
|
const adapter = new MongoStorageAdapter({
|
|
uri: databaseURI,
|
|
mongoOptions: { maxTimeMS },
|
|
});
|
|
adapter
|
|
.createObject('Foo', { fields: {} }, { objectId: 'abcde' })
|
|
.then(() =>
|
|
adapter._rawFind('Foo', { $where: `sleep(${maxTimeMS * 2})` })
|
|
)
|
|
.then(
|
|
() => {
|
|
done.fail('Find succeeded despite taking too long!');
|
|
},
|
|
err => {
|
|
expect(err.name).toEqual('MongoError');
|
|
expect(err.code).toEqual(50);
|
|
expect(err.message).toMatch('operation exceeded time limit');
|
|
done();
|
|
}
|
|
);
|
|
});
|
|
|
|
it('stores pointers with a _p_ prefix', done => {
|
|
const obj = {
|
|
objectId: 'bar',
|
|
aPointer: {
|
|
__type: 'Pointer',
|
|
className: 'JustThePointer',
|
|
objectId: 'qwerty',
|
|
},
|
|
};
|
|
const adapter = new MongoStorageAdapter({ uri: databaseURI });
|
|
adapter
|
|
.createObject(
|
|
'APointerDarkly',
|
|
{
|
|
fields: {
|
|
objectId: { type: 'String' },
|
|
aPointer: { type: 'Pointer', targetClass: 'JustThePointer' },
|
|
},
|
|
},
|
|
obj
|
|
)
|
|
.then(() => adapter._rawFind('APointerDarkly', {}))
|
|
.then(results => {
|
|
expect(results.length).toEqual(1);
|
|
const output = results[0];
|
|
expect(typeof output._id).toEqual('string');
|
|
expect(typeof output._p_aPointer).toEqual('string');
|
|
expect(output._p_aPointer).toEqual('JustThePointer$qwerty');
|
|
expect(output.aPointer).toBeUndefined();
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('handles object and subdocument', done => {
|
|
const adapter = new MongoStorageAdapter({ uri: databaseURI });
|
|
const schema = { fields: { subdoc: { type: 'Object' } } };
|
|
const obj = { subdoc: { foo: 'bar', wu: 'tan' } };
|
|
adapter
|
|
.createObject('MyClass', schema, obj)
|
|
.then(() => adapter._rawFind('MyClass', {}))
|
|
.then(results => {
|
|
expect(results.length).toEqual(1);
|
|
const mob = results[0];
|
|
expect(typeof mob.subdoc).toBe('object');
|
|
expect(mob.subdoc.foo).toBe('bar');
|
|
expect(mob.subdoc.wu).toBe('tan');
|
|
const obj = { 'subdoc.wu': 'clan' };
|
|
return adapter.findOneAndUpdate('MyClass', schema, {}, obj);
|
|
})
|
|
.then(() => adapter._rawFind('MyClass', {}))
|
|
.then(results => {
|
|
expect(results.length).toEqual(1);
|
|
const mob = results[0];
|
|
expect(typeof mob.subdoc).toBe('object');
|
|
expect(mob.subdoc.foo).toBe('bar');
|
|
expect(mob.subdoc.wu).toBe('clan');
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('handles creating an array, object, date', done => {
|
|
const adapter = new MongoStorageAdapter({ uri: databaseURI });
|
|
const obj = {
|
|
array: [1, 2, 3],
|
|
object: { foo: 'bar' },
|
|
date: {
|
|
__type: 'Date',
|
|
iso: '2016-05-26T20:55:01.154Z',
|
|
},
|
|
};
|
|
const schema = {
|
|
fields: {
|
|
array: { type: 'Array' },
|
|
object: { type: 'Object' },
|
|
date: { type: 'Date' },
|
|
},
|
|
};
|
|
adapter
|
|
.createObject('MyClass', schema, obj)
|
|
.then(() => adapter._rawFind('MyClass', {}))
|
|
.then(results => {
|
|
expect(results.length).toEqual(1);
|
|
const mob = results[0];
|
|
expect(mob.array instanceof Array).toBe(true);
|
|
expect(typeof mob.object).toBe('object');
|
|
expect(mob.date instanceof Date).toBe(true);
|
|
return adapter.find('MyClass', schema, {}, {});
|
|
})
|
|
.then(results => {
|
|
expect(results.length).toEqual(1);
|
|
const mob = results[0];
|
|
expect(mob.array instanceof Array).toBe(true);
|
|
expect(typeof mob.object).toBe('object');
|
|
expect(mob.date.__type).toBe('Date');
|
|
expect(mob.date.iso).toBe('2016-05-26T20:55:01.154Z');
|
|
done();
|
|
})
|
|
.catch(error => {
|
|
console.log(error);
|
|
fail();
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('handles updating a single object with array, object date', done => {
|
|
const adapter = new MongoStorageAdapter({ uri: databaseURI });
|
|
|
|
const schema = {
|
|
fields: {
|
|
array: { type: 'Array' },
|
|
object: { type: 'Object' },
|
|
date: { type: 'Date' },
|
|
},
|
|
};
|
|
|
|
adapter
|
|
.createObject('MyClass', schema, {})
|
|
.then(() => adapter._rawFind('MyClass', {}))
|
|
.then(results => {
|
|
expect(results.length).toEqual(1);
|
|
const update = {
|
|
array: [1, 2, 3],
|
|
object: { foo: 'bar' },
|
|
date: {
|
|
__type: 'Date',
|
|
iso: '2016-05-26T20:55:01.154Z',
|
|
},
|
|
};
|
|
const query = {};
|
|
return adapter.findOneAndUpdate('MyClass', schema, query, update);
|
|
})
|
|
.then(results => {
|
|
const mob = results;
|
|
expect(mob.array instanceof Array).toBe(true);
|
|
expect(typeof mob.object).toBe('object');
|
|
expect(mob.date.__type).toBe('Date');
|
|
expect(mob.date.iso).toBe('2016-05-26T20:55:01.154Z');
|
|
return adapter._rawFind('MyClass', {});
|
|
})
|
|
.then(results => {
|
|
expect(results.length).toEqual(1);
|
|
const mob = results[0];
|
|
expect(mob.array instanceof Array).toBe(true);
|
|
expect(typeof mob.object).toBe('object');
|
|
expect(mob.date instanceof Date).toBe(true);
|
|
done();
|
|
})
|
|
.catch(error => {
|
|
console.log(error);
|
|
fail();
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('handleShutdown, close connection', done => {
|
|
const adapter = new MongoStorageAdapter({ uri: databaseURI });
|
|
|
|
const schema = {
|
|
fields: {
|
|
array: { type: 'Array' },
|
|
object: { type: 'Object' },
|
|
date: { type: 'Date' },
|
|
},
|
|
};
|
|
|
|
adapter.createObject('MyClass', schema, {}).then(() => {
|
|
expect(adapter.database.serverConfig.isConnected()).toEqual(true);
|
|
adapter.handleShutdown();
|
|
expect(adapter.database.serverConfig.isConnected()).toEqual(false);
|
|
done();
|
|
});
|
|
});
|
|
});
|