Skip to content

Commit 139b9e1

Browse files
authored
Finding areas that are untested and need love (#4131)
* Makes InstallationRouter like others * Adds testing for Range file requests - Fixes issue with small requests (0-2) * Revert "Makes InstallationRouter like others" This reverts commit e2d2a16. * Better handling of errors in FilesRouter * Fix incorrectness in range requests * Better/simpler logic * Only on mongo at it requires Gridstore * Open file streaming to all adapters supporting it * Improves coverage of parsers * Ensures depreciation warning is effective * Removes unused function * de-duplicate logic * Removes necessity of overriding req.params.className on subclasses routers * Use babel-preset-env to ensure min-version compatible code * removes dead code * Leverage indexes in order to infer which field is duplicated upon signup - A note mentioned that it would be possible to leverage using the indexes on username/email to infer which is duplicated * Small nit * Better template to match column name * Restores original implementation for safety * nits
1 parent 3079270 commit 139b9e1

18 files changed

+474
-273
lines changed

.babelrc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
],
55
"presets": [
66
"es2015",
7-
"stage-0"
7+
"stage-3",
8+
["env", {
9+
"targets": {
10+
"node": "4.6"
11+
}
12+
}]
813
]
914
}

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@
4949
"babel-eslint": "^7.1.1",
5050
"babel-plugin-syntax-flow": "6.18.0",
5151
"babel-plugin-transform-flow-strip-types": "6.22.0",
52+
"babel-preset-env": "1.6.0",
5253
"babel-preset-es2015": "6.24.1",
53-
"babel-preset-stage-0": "6.24.1",
54+
"babel-preset-stage-3": "6.24.1",
5455
"babel-register": "6.26.0",
5556
"bcrypt-nodejs": "0.0.3",
5657
"cross-env": "5.0.2",

spec/CLI.spec.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,12 @@ describe('definitions', () => {
157157
}
158158
}
159159
});
160+
161+
it('should throw when using deprecated facebookAppIds', () => {
162+
expect(() => {
163+
definitions.facebookAppIds.action()
164+
}).toThrow();
165+
});
160166
});
161167

162168
describe('LiveQuery definitions', () => {

spec/ParseFile.spec.js

Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,4 +595,290 @@ describe('Parse.File testing', () => {
595595
done();
596596
});
597597
});
598+
599+
it('fails to upload an empty file', done => {
600+
var headers = {
601+
'Content-Type': 'application/octet-stream',
602+
'X-Parse-Application-Id': 'test',
603+
'X-Parse-REST-API-Key': 'rest'
604+
};
605+
request.post({
606+
headers: headers,
607+
url: 'http://localhost:8378/1/files/file.txt',
608+
body: '',
609+
}, (error, response, body) => {
610+
expect(error).toBe(null);
611+
expect(response.statusCode).toBe(400);
612+
expect(body).toEqual('{"code":130,"error":"Invalid file upload."}');
613+
done();
614+
});
615+
});
616+
617+
it('fails to upload without a file name', done => {
618+
var headers = {
619+
'Content-Type': 'application/octet-stream',
620+
'X-Parse-Application-Id': 'test',
621+
'X-Parse-REST-API-Key': 'rest'
622+
};
623+
request.post({
624+
headers: headers,
625+
url: 'http://localhost:8378/1/files/',
626+
body: 'yolo',
627+
}, (error, response, body) => {
628+
expect(error).toBe(null);
629+
expect(response.statusCode).toBe(400);
630+
expect(body).toEqual('{"code":122,"error":"Filename not provided."}');
631+
done();
632+
});
633+
});
634+
635+
it('fails to upload without a file name', done => {
636+
var headers = {
637+
'Content-Type': 'application/octet-stream',
638+
'X-Parse-Application-Id': 'test',
639+
'X-Parse-REST-API-Key': 'rest'
640+
};
641+
request.post({
642+
headers: headers,
643+
url: 'http://localhost:8378/1/files/',
644+
body: 'yolo',
645+
}, (error, response, body) => {
646+
expect(error).toBe(null);
647+
expect(response.statusCode).toBe(400);
648+
expect(body).toEqual('{"code":122,"error":"Filename not provided."}');
649+
done();
650+
});
651+
});
652+
653+
it('fails to delete an unkown file', done => {
654+
var headers = {
655+
'Content-Type': 'application/octet-stream',
656+
'X-Parse-Application-Id': 'test',
657+
'X-Parse-REST-API-Key': 'rest',
658+
'X-Parse-Master-Key': 'test'
659+
};
660+
request.delete({
661+
headers: headers,
662+
url: 'http://localhost:8378/1/files/file.txt',
663+
}, (error, response, body) => {
664+
expect(error).toBe(null);
665+
expect(response.statusCode).toBe(400);
666+
expect(body).toEqual('{"code":153,"error":"Could not delete file."}');
667+
done();
668+
});
669+
});
670+
671+
describe_only_db('mongo')('Gridstore Range tests', () => {
672+
it('supports range requests', done => {
673+
var headers = {
674+
'Content-Type': 'application/octet-stream',
675+
'X-Parse-Application-Id': 'test',
676+
'X-Parse-REST-API-Key': 'rest'
677+
};
678+
request.post({
679+
headers: headers,
680+
url: 'http://localhost:8378/1/files/file.txt',
681+
body: 'argle bargle',
682+
}, (error, response, body) => {
683+
expect(error).toBe(null);
684+
var b = JSON.parse(body);
685+
request.get({ url: b.url, headers: {
686+
'Content-Type': 'application/octet-stream',
687+
'X-Parse-Application-Id': 'test',
688+
'X-Parse-REST-API-Key': 'rest',
689+
'Range': 'bytes=0-5'
690+
} }, (error, response, body) => {
691+
expect(error).toBe(null);
692+
expect(body).toEqual('argle ');
693+
done();
694+
});
695+
});
696+
});
697+
698+
it('supports small range requests', done => {
699+
var headers = {
700+
'Content-Type': 'application/octet-stream',
701+
'X-Parse-Application-Id': 'test',
702+
'X-Parse-REST-API-Key': 'rest'
703+
};
704+
request.post({
705+
headers: headers,
706+
url: 'http://localhost:8378/1/files/file.txt',
707+
body: 'argle bargle',
708+
}, (error, response, body) => {
709+
expect(error).toBe(null);
710+
var b = JSON.parse(body);
711+
request.get({ url: b.url, headers: {
712+
'Content-Type': 'application/octet-stream',
713+
'X-Parse-Application-Id': 'test',
714+
'X-Parse-REST-API-Key': 'rest',
715+
'Range': 'bytes=0-2'
716+
} }, (error, response, body) => {
717+
expect(error).toBe(null);
718+
expect(body).toEqual('arg');
719+
done();
720+
});
721+
});
722+
});
723+
724+
// See specs https://www.greenbytes.de/tech/webdav/draft-ietf-httpbis-p5-range-latest.html#byte.ranges
725+
it('supports getting one byte', done => {
726+
var headers = {
727+
'Content-Type': 'application/octet-stream',
728+
'X-Parse-Application-Id': 'test',
729+
'X-Parse-REST-API-Key': 'rest'
730+
};
731+
request.post({
732+
headers: headers,
733+
url: 'http://localhost:8378/1/files/file.txt',
734+
body: 'argle bargle',
735+
}, (error, response, body) => {
736+
expect(error).toBe(null);
737+
var b = JSON.parse(body);
738+
request.get({ url: b.url, headers: {
739+
'Content-Type': 'application/octet-stream',
740+
'X-Parse-Application-Id': 'test',
741+
'X-Parse-REST-API-Key': 'rest',
742+
'Range': 'bytes=2-2'
743+
} }, (error, response, body) => {
744+
expect(error).toBe(null);
745+
expect(body).toEqual('g');
746+
done();
747+
});
748+
});
749+
});
750+
751+
it('supports getting last n bytes', done => {
752+
var headers = {
753+
'Content-Type': 'application/octet-stream',
754+
'X-Parse-Application-Id': 'test',
755+
'X-Parse-REST-API-Key': 'rest'
756+
};
757+
request.post({
758+
headers: headers,
759+
url: 'http://localhost:8378/1/files/file.txt',
760+
body: 'something different',
761+
}, (error, response, body) => {
762+
expect(error).toBe(null);
763+
var b = JSON.parse(body);
764+
request.get({ url: b.url, headers: {
765+
'Content-Type': 'application/octet-stream',
766+
'X-Parse-Application-Id': 'test',
767+
'X-Parse-REST-API-Key': 'rest',
768+
'Range': 'bytes=-4'
769+
} }, (error, response, body) => {
770+
expect(error).toBe(null);
771+
expect(body.length).toBe(4);
772+
expect(body).toEqual('rent');
773+
done();
774+
});
775+
});
776+
});
777+
778+
it('supports getting first n bytes', done => {
779+
var headers = {
780+
'Content-Type': 'application/octet-stream',
781+
'X-Parse-Application-Id': 'test',
782+
'X-Parse-REST-API-Key': 'rest'
783+
};
784+
request.post({
785+
headers: headers,
786+
url: 'http://localhost:8378/1/files/file.txt',
787+
body: 'something different',
788+
}, (error, response, body) => {
789+
expect(error).toBe(null);
790+
var b = JSON.parse(body);
791+
request.get({ url: b.url, headers: {
792+
'Content-Type': 'application/octet-stream',
793+
'X-Parse-Application-Id': 'test',
794+
'X-Parse-REST-API-Key': 'rest',
795+
'Range': 'bytes=10-'
796+
} }, (error, response, body) => {
797+
expect(error).toBe(null);
798+
expect(body).toEqual('different');
799+
done();
800+
});
801+
});
802+
});
803+
804+
function repeat(string, count) {
805+
var s = string;
806+
while (count > 0) {
807+
s += string;
808+
count--;
809+
}
810+
return s;
811+
}
812+
813+
it('supports large range requests', done => {
814+
var headers = {
815+
'Content-Type': 'application/octet-stream',
816+
'X-Parse-Application-Id': 'test',
817+
'X-Parse-REST-API-Key': 'rest'
818+
};
819+
request.post({
820+
headers: headers,
821+
url: 'http://localhost:8378/1/files/file.txt',
822+
body: repeat('argle bargle', 100)
823+
}, (error, response, body) => {
824+
expect(error).toBe(null);
825+
var b = JSON.parse(body);
826+
request.get({ url: b.url, headers: {
827+
'Content-Type': 'application/octet-stream',
828+
'X-Parse-Application-Id': 'test',
829+
'X-Parse-REST-API-Key': 'rest',
830+
'Range': 'bytes=13-240'
831+
} }, (error, response, body) => {
832+
expect(error).toBe(null);
833+
expect(body.length).toEqual(228);
834+
expect(body.indexOf('rgle barglea')).toBe(0);
835+
done();
836+
});
837+
});
838+
});
839+
840+
it('fails to stream unknown file', done => {
841+
request.get({ url: 'http://localhost:8378/1/files/test/file.txt', headers: {
842+
'Content-Type': 'application/octet-stream',
843+
'X-Parse-Application-Id': 'test',
844+
'X-Parse-REST-API-Key': 'rest',
845+
'Range': 'bytes=13-240'
846+
} }, (error, response, body) => {
847+
expect(error).toBe(null);
848+
expect(response.statusCode).toBe(404);
849+
expect(body).toEqual('File not found.');
850+
done();
851+
});
852+
});
853+
});
854+
855+
// Because GridStore is not loaded on PG, those are perfect
856+
// for fallback tests
857+
describe_only_db('postgres')('Default Range tests', () => {
858+
it('fallback to regular request', done => {
859+
var headers = {
860+
'Content-Type': 'application/octet-stream',
861+
'X-Parse-Application-Id': 'test',
862+
'X-Parse-REST-API-Key': 'rest'
863+
};
864+
request.post({
865+
headers: headers,
866+
url: 'http://localhost:8378/1/files/file.txt',
867+
body: 'argle bargle',
868+
}, (error, response, body) => {
869+
expect(error).toBe(null);
870+
var b = JSON.parse(body);
871+
request.get({ url: b.url, headers: {
872+
'Content-Type': 'application/octet-stream',
873+
'X-Parse-Application-Id': 'test',
874+
'X-Parse-REST-API-Key': 'rest',
875+
'Range': 'bytes=0-5'
876+
} }, (error, response, body) => {
877+
expect(error).toBe(null);
878+
expect(body).toEqual('argle bargle');
879+
done();
880+
});
881+
});
882+
});
883+
});
598884
});

spec/parsers.spec.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ import {
22
numberParser,
33
numberOrBoolParser,
44
booleanParser,
5+
objectParser,
6+
arrayParser,
7+
moduleOrObjectParser,
8+
nullParser,
59
} from '../src/cli/utils/parsers';
610

711
describe('parsers', () => {
@@ -31,4 +35,33 @@ describe('parsers', () => {
3135
expect(parser(1)).toEqual(true);
3236
expect(parser(2)).toEqual(false);
3337
});
38+
39+
it('parses correctly with objectParser', () => {
40+
const parser = objectParser;
41+
expect(parser({hello: 'world'})).toEqual({hello: 'world'});
42+
expect(parser('{"hello": "world"}')).toEqual({hello: 'world'});
43+
expect(() => {parser('string')}).toThrow();
44+
});
45+
46+
it('parses correctly with moduleOrObjectParser', () => {
47+
const parser = moduleOrObjectParser;
48+
expect(parser({hello: 'world'})).toEqual({hello: 'world'});
49+
expect(parser('{"hello": "world"}')).toEqual({hello: 'world'});
50+
expect(parser('string')).toEqual('string');
51+
});
52+
53+
it('parses correctly with arrayParser', () => {
54+
const parser = arrayParser;
55+
expect(parser([1,2,3])).toEqual([1,2,3]);
56+
expect(parser('{"hello": "world"}')).toEqual(['{"hello": "world"}']);
57+
expect(parser('1,2,3')).toEqual(['1','2','3']);
58+
expect(() => {parser(1)}).toThrow();
59+
});
60+
61+
it('parses correctly with nullParser', () => {
62+
const parser = nullParser;
63+
expect(parser('null')).toEqual(null);
64+
expect(parser(1)).toEqual(1);
65+
expect(parser('blabla')).toEqual('blabla');
66+
});
3467
});

src/Adapters/Storage/Mongo/MongoCollection.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,6 @@ export default class MongoCollection {
7979
return this._mongoCollection.updateMany(query, update);
8080
}
8181

82-
deleteOne(query) {
83-
return this._mongoCollection.deleteOne(query);
84-
}
85-
8682
deleteMany(query) {
8783
return this._mongoCollection.deleteMany(query);
8884
}

0 commit comments

Comments
 (0)