Skip to content

Commit 1fc520c

Browse files
authored
fix: Parse.Hooks requests have double forward slash in URL (#2441)
BREAKING CHANGE: Internal REST requests for `Parse.Hooks` use a URL that contains a double forward slash, for example `http://localhost/parse//hooks/functions`. This release changes the double forward slash to a single forward slash.
1 parent dc03103 commit 1fc520c

File tree

2 files changed

+107
-42
lines changed

2 files changed

+107
-42
lines changed

src/ParseHooks.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export function remove(hook: HookDeleteArg) {
6161

6262
const DefaultController = {
6363
get(type: string, functionName?: string, triggerName?: string) {
64-
let url = '/hooks/' + type;
64+
let url = 'hooks/' + type;
6565
if (functionName) {
6666
url += '/' + functionName;
6767
if (triggerName) {
@@ -74,9 +74,9 @@ const DefaultController = {
7474
create(hook) {
7575
let url;
7676
if (hook.functionName && hook.url) {
77-
url = '/hooks/functions';
77+
url = 'hooks/functions';
7878
} else if (hook.className && hook.triggerName && hook.url) {
79-
url = '/hooks/triggers';
79+
url = 'hooks/triggers';
8080
} else {
8181
return Promise.reject({ error: 'invalid hook declaration', code: 143 });
8282
}
@@ -86,10 +86,10 @@ const DefaultController = {
8686
remove(hook) {
8787
let url;
8888
if (hook.functionName) {
89-
url = '/hooks/functions/' + hook.functionName;
89+
url = 'hooks/functions/' + hook.functionName;
9090
delete hook.functionName;
9191
} else if (hook.className && hook.triggerName) {
92-
url = '/hooks/triggers/' + hook.className + '/' + hook.triggerName;
92+
url = 'hooks/triggers/' + hook.className + '/' + hook.triggerName;
9393
delete hook.className;
9494
delete hook.triggerName;
9595
} else {
@@ -101,10 +101,10 @@ const DefaultController = {
101101
update(hook) {
102102
let url;
103103
if (hook.functionName && hook.url) {
104-
url = '/hooks/functions/' + hook.functionName;
104+
url = 'hooks/functions/' + hook.functionName;
105105
delete hook.functionName;
106106
} else if (hook.className && hook.triggerName && hook.url) {
107-
url = '/hooks/triggers/' + hook.className + '/' + hook.triggerName;
107+
url = 'hooks/triggers/' + hook.className + '/' + hook.triggerName;
108108
delete hook.className;
109109
delete hook.triggerName;
110110
} else {

src/__tests__/Hooks-test.js

Lines changed: 100 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,27 @@ jest.dontMock('../decode');
44
jest.dontMock('../encode');
55
jest.dontMock('../ParseError');
66
jest.dontMock('../ParseObject');
7+
jest.dontMock('../RESTController');
78

89
const Hooks = require('../ParseHooks');
910
const CoreManager = require('../CoreManager');
11+
const RESTController = require('../RESTController');
1012

1113
const defaultController = CoreManager.getHooksController();
1214
const { sendRequest } = defaultController;
1315

16+
CoreManager.setInstallationController({
17+
currentInstallationId() {
18+
return Promise.resolve('iid');
19+
},
20+
currentInstallation() {},
21+
updateInstallationOnDisk() {},
22+
});
23+
CoreManager.set('APPLICATION_ID', 'A');
24+
CoreManager.set('JAVASCRIPT_KEY', 'B');
25+
CoreManager.set('MASTER_KEY', 'C');
26+
CoreManager.set('VERSION', 'V');
27+
1428
describe('Hooks', () => {
1529
beforeEach(() => {
1630
const run = jest.fn();
@@ -19,125 +33,176 @@ describe('Hooks', () => {
1933
result: {},
2034
})
2135
);
36+
const ajax = jest.fn();
37+
ajax.mockReturnValue(
38+
Promise.resolve({
39+
response: {},
40+
})
41+
);
42+
RESTController.ajax = ajax;
2243
defaultController.sendRequest = run;
2344
CoreManager.setHooksController(defaultController);
45+
CoreManager.setRESTController(RESTController);
2446
});
2547

26-
it('shoud properly build GET functions', () => {
48+
it('should properly build GET functions', async () => {
2749
Hooks.getFunctions();
2850

2951
expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([
3052
'GET',
31-
'/hooks/functions',
53+
'hooks/functions',
3254
]);
55+
defaultController.sendRequest = sendRequest;
56+
await Hooks.getFunctions();
57+
expect(RESTController.ajax.mock.calls[0][1]).toBe('https://api.parse.com/1/hooks/functions');
3358
});
3459

35-
it('shoud properly build GET triggers', () => {
60+
it('should properly build GET triggers', async () => {
3661
Hooks.getTriggers();
3762

3863
expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([
3964
'GET',
40-
'/hooks/triggers',
65+
'hooks/triggers',
4166
]);
67+
defaultController.sendRequest = sendRequest;
68+
await Hooks.getTriggers();
69+
expect(RESTController.ajax.mock.calls[0][1]).toBe('https://api.parse.com/1/hooks/triggers');
4270
});
4371

44-
it('shoud properly build GET function', () => {
72+
it('should properly build GET function', async () => {
4573
Hooks.getFunction('functionName');
4674

4775
expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([
4876
'GET',
49-
'/hooks/functions/functionName',
77+
'hooks/functions/functionName',
5078
]);
79+
defaultController.sendRequest = sendRequest;
80+
await Hooks.getFunction('functionName');
81+
expect(RESTController.ajax.mock.calls[0][1]).toBe(
82+
'https://api.parse.com/1/hooks/functions/functionName'
83+
);
5184
});
5285

53-
it('shoud properly build GET trigger', () => {
86+
it('should properly build GET trigger', async () => {
5487
Hooks.getTrigger('MyClass', 'beforeSave');
5588

5689
expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([
5790
'GET',
58-
'/hooks/triggers/MyClass/beforeSave',
91+
'hooks/triggers/MyClass/beforeSave',
5992
]);
93+
defaultController.sendRequest = sendRequest;
94+
await Hooks.getTrigger('MyClass', 'beforeSave');
95+
expect(RESTController.ajax.mock.calls[0][1]).toBe(
96+
'https://api.parse.com/1/hooks/triggers/MyClass/beforeSave'
97+
);
6098
});
6199

62-
it('shoud properly build POST function', () => {
63-
Hooks.createFunction('myFunction', 'https://dummy.com');
100+
it('should properly build POST function', async () => {
101+
Hooks.createFunction('myFunction', 'https://example.com');
64102

65103
expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([
66104
'POST',
67-
'/hooks/functions',
105+
'hooks/functions',
68106
{
69107
functionName: 'myFunction',
70-
url: 'https://dummy.com',
108+
url: 'https://example.com',
71109
},
72110
]);
111+
defaultController.sendRequest = sendRequest;
112+
await Hooks.createFunction('myFunction', 'https://example.com');
113+
expect(RESTController.ajax.mock.calls[0][1]).toBe('https://api.parse.com/1/hooks/functions');
73114
});
74115

75-
it('shoud properly build POST trigger', () => {
76-
Hooks.createTrigger('MyClass', 'beforeSave', 'https://dummy.com');
116+
it('should properly build POST trigger', async () => {
117+
Hooks.createTrigger('MyClass', 'beforeSave', 'https://example.com');
77118

78119
expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([
79120
'POST',
80-
'/hooks/triggers',
121+
'hooks/triggers',
81122
{
82123
className: 'MyClass',
83124
triggerName: 'beforeSave',
84-
url: 'https://dummy.com',
125+
url: 'https://example.com',
85126
},
86127
]);
128+
defaultController.sendRequest = sendRequest;
129+
await Hooks.createTrigger('MyClass', 'beforeSave', 'https://example.com');
130+
expect(RESTController.ajax.mock.calls[0][1]).toBe('https://api.parse.com/1/hooks/triggers');
87131
});
88132

89-
it('shoud properly build PUT function', () => {
90-
Hooks.updateFunction('myFunction', 'https://dummy.com');
133+
it('should properly build PUT function', async () => {
134+
Hooks.updateFunction('myFunction', 'https://example.com');
91135

92136
expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([
93137
'PUT',
94-
'/hooks/functions/myFunction',
138+
'hooks/functions/myFunction',
95139
{
96-
url: 'https://dummy.com',
140+
url: 'https://example.com',
97141
},
98142
]);
143+
defaultController.sendRequest = sendRequest;
144+
await Hooks.updateFunction('myFunction', 'https://example.com');
145+
expect(RESTController.ajax.mock.calls[0][1]).toBe(
146+
'https://api.parse.com/1/hooks/functions/myFunction'
147+
);
99148
});
100149

101-
it('shoud properly build PUT trigger', () => {
102-
Hooks.updateTrigger('MyClass', 'beforeSave', 'https://dummy.com');
150+
it('should properly build PUT trigger', async () => {
151+
Hooks.updateTrigger('MyClass', 'beforeSave', 'https://example.com');
103152

104153
expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([
105154
'PUT',
106-
'/hooks/triggers/MyClass/beforeSave',
155+
'hooks/triggers/MyClass/beforeSave',
107156
{
108-
url: 'https://dummy.com',
157+
url: 'https://example.com',
109158
},
110159
]);
160+
defaultController.sendRequest = sendRequest;
161+
await Hooks.updateTrigger('MyClass', 'beforeSave', 'https://example.com');
162+
expect(RESTController.ajax.mock.calls[0][1]).toBe(
163+
'https://api.parse.com/1/hooks/triggers/MyClass/beforeSave'
164+
);
111165
});
112166

113-
it('shoud properly build removeFunction', () => {
167+
it('should properly build removeFunction', async () => {
114168
Hooks.removeFunction('myFunction');
115169

116170
expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([
117171
'PUT',
118-
'/hooks/functions/myFunction',
172+
'hooks/functions/myFunction',
119173
{ __op: 'Delete' },
120174
]);
175+
176+
defaultController.sendRequest = sendRequest;
177+
await Hooks.removeFunction('myFunction');
178+
expect(RESTController.ajax.mock.calls[0][1]).toBe(
179+
'https://api.parse.com/1/hooks/functions/myFunction'
180+
);
121181
});
122182

123-
it('shoud properly build removeTrigger', () => {
183+
it('should properly build removeTrigger', async () => {
124184
Hooks.removeTrigger('MyClass', 'beforeSave');
125185

126186
expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([
127187
'PUT',
128-
'/hooks/triggers/MyClass/beforeSave',
188+
'hooks/triggers/MyClass/beforeSave',
129189
{ __op: 'Delete' },
130190
]);
191+
defaultController.sendRequest = sendRequest;
192+
await Hooks.removeTrigger('MyClass', 'beforeSave');
193+
expect(RESTController.ajax.mock.calls[0][1]).toBe(
194+
'https://api.parse.com/1/hooks/triggers/MyClass/beforeSave'
195+
);
131196
});
132197

133-
it('shoud throw invalid create', async () => {
198+
it('should throw invalid create', async () => {
134199
expect.assertions(10);
135200
const p1 = Hooks.create({ functionName: 'myFunction' }).catch(err => {
136201
expect(err.code).toBe(143);
137202
expect(err.error).toBe('invalid hook declaration');
138203
});
139204

140-
const p2 = Hooks.create({ url: 'http://dummy.com' }).catch(err => {
205+
const p2 = Hooks.create({ url: 'http://example.com' }).catch(err => {
141206
expect(err.code).toBe(143);
142207
expect(err.error).toBe('invalid hook declaration');
143208
});
@@ -147,7 +212,7 @@ describe('Hooks', () => {
147212
expect(err.error).toBe('invalid hook declaration');
148213
});
149214

150-
const p4 = Hooks.create({ className: 'MyClass', url: 'http://dummy.com' }).catch(err => {
215+
const p4 = Hooks.create({ className: 'MyClass', url: 'http://example.com' }).catch(err => {
151216
expect(err.code).toBe(143);
152217
expect(err.error).toBe('invalid hook declaration');
153218
});
@@ -160,7 +225,7 @@ describe('Hooks', () => {
160225
await Promise.all([p1, p2, p3, p4, p5]);
161226
});
162227

163-
it('shoud throw invalid update', async () => {
228+
it('should throw invalid update', async () => {
164229
expect.assertions(6);
165230
const p1 = Hooks.update({ functionssName: 'myFunction' }).catch(err => {
166231
expect(err.code).toBe(143);
@@ -172,14 +237,14 @@ describe('Hooks', () => {
172237
expect(err.error).toBe('invalid hook declaration');
173238
});
174239

175-
const p3 = Hooks.update({ className: 'MyClass', url: 'http://dummy.com' }).catch(err => {
240+
const p3 = Hooks.update({ className: 'MyClass', url: 'http://example.com' }).catch(err => {
176241
expect(err.code).toBe(143);
177242
expect(err.error).toBe('invalid hook declaration');
178243
});
179244
await Promise.all([p1, p2, p3]);
180245
});
181246

182-
it('shoud throw invalid remove', async () => {
247+
it('should throw invalid remove', async () => {
183248
expect.assertions(6);
184249
const p1 = Hooks.remove({ functionssName: 'myFunction' }).catch(err => {
185250
expect(err.code).toBe(143);
@@ -191,7 +256,7 @@ describe('Hooks', () => {
191256
expect(err.error).toBe('invalid hook declaration');
192257
});
193258

194-
const p3 = Hooks.remove({ className: 'MyClass', url: 'http://dummy.com' }).catch(err => {
259+
const p3 = Hooks.remove({ className: 'MyClass', url: 'http://example.com' }).catch(err => {
195260
expect(err.code).toBe(143);
196261
expect(err.error).toBe('invalid hook declaration');
197262
});

0 commit comments

Comments
 (0)