Skip to content

Commit e821bae

Browse files
committed
First stab at more granular Datastore event types. Note that tests for write are still failing due to same issue as brought up in Google Group.
1 parent b2ec1b3 commit e821bae

File tree

2 files changed

+128
-44
lines changed

2 files changed

+128
-44
lines changed

spec/providers/datastore.spec.ts

Lines changed: 85 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -33,75 +33,132 @@ describe('Datastore Functions', () => {
3333
delete process.env.GCLOUD_PROJECT;
3434
});
3535

36-
describe('document builders', () => {
37-
function expectedTrigger(resource: string) {
36+
describe('document builders and event types', () => {
37+
function expectedTrigger(resource: string, eventType: string) {
3838
return {
3939
eventTrigger: {
4040
resource,
41-
eventType: `providers/${datastore.provider}/eventTypes/document.write`,
41+
eventType: `providers/${datastore.provider}/eventTypes/${eventType}`,
4242
},
4343
};
4444
}
4545

4646
it('should allow terse constructors', () => {
4747
let resource = 'projects/project1/databases/(default)/documents/users/{uid}';
4848
let cloudFunction = datastore.document('users/{uid}').onWrite(() => null);
49-
expect(cloudFunction.__trigger).to.deep.equal(expectedTrigger(resource));
49+
expect(cloudFunction.__trigger).to.deep.equal(expectedTrigger(resource, 'document.write'));
5050
});
5151

5252
it('should allow custom namespaces', () => {
5353
let resource = 'projects/project1/databases/(default)/documents@v2/users/{uid}';
5454
let cloudFunction = datastore.namespace('v2').document('users/{uid}').onWrite(() => null);
55-
expect(cloudFunction.__trigger).to.deep.equal(expectedTrigger(resource));
55+
expect(cloudFunction.__trigger).to.deep.equal(expectedTrigger(resource, 'document.write'));
5656
});
5757

5858
it('should allow custom databases', () => {
5959
let resource = 'projects/project1/databases/myDB/documents/users/{uid}';
6060
let cloudFunction = datastore.database('myDB').document('users/{uid}').onWrite(() => null);
61-
expect(cloudFunction.__trigger).to.deep.equal(expectedTrigger(resource));
61+
expect(cloudFunction.__trigger).to.deep.equal(expectedTrigger(resource, 'document.write'));
6262
});
6363

6464
it('should allow both custom database and namespace', () => {
6565
let resource = 'projects/project1/databases/myDB/documents@v2/users/{uid}';
6666
let cloudFunction = datastore.database('myDB').namespace('v2').document('users/{uid}').onWrite(() => null);
67-
expect(cloudFunction.__trigger).to.deep.equal(expectedTrigger(resource));
67+
expect(cloudFunction.__trigger).to.deep.equal(expectedTrigger(resource, 'document.write'));
68+
});
69+
70+
it('onCreate should have the "document.create" eventType', () => {
71+
let resource = 'projects/project1/databases/(default)/documents/users/{uid}';
72+
let eventType = datastore.document('users/{uid}').onCreate(() => null).__trigger.eventTrigger.eventType;
73+
expect(eventType).to.eq(expectedTrigger(resource, 'document.create').eventTrigger.eventType);
74+
});
75+
76+
it('onUpdate should have the "document.update" eventType', () => {
77+
let resource = 'projects/project1/databases/(default)/documents/users/{uid}';
78+
let eventType = datastore.document('users/{uid}').onUpdate(() => null).__trigger.eventTrigger.eventType;
79+
expect(eventType).to.eq(expectedTrigger(resource, 'document.update').eventTrigger.eventType);
80+
});
81+
82+
it('onDelete should have the "document.delete" eventType', () => {
83+
let resource = 'projects/project1/databases/(default)/documents/users/{uid}';
84+
let eventType = datastore.document('users/{uid}').onDelete(() => null).__trigger.eventTrigger.eventType;
85+
expect(eventType).to.eq(expectedTrigger(resource, 'document.delete').eventTrigger.eventType);
6886
});
6987
});
7088

7189
describe('dataConstructor', () => {
72-
let testEvent = {
73-
'data': {
74-
'oldValue': {
75-
'fields': {
76-
'key1': {
77-
'booleanValue': false,
78-
},
79-
'key2': {
80-
'integerValue': '111',
90+
function testEvent() {
91+
return {
92+
'data': {
93+
'oldValue': {
94+
'fields': {
95+
'key1': {
96+
'booleanValue': false,
97+
},
98+
'key2': {
99+
'integerValue': '111',
100+
},
81101
},
82102
},
83-
},
84-
'value': {
85-
'fields': {
86-
'key1': {
87-
'booleanValue': true,
88-
},
89-
'key2': {
90-
'integerValue': '123',
103+
'value': {
104+
'fields': {
105+
'key1': {
106+
'booleanValue': true,
107+
},
108+
'key2': {
109+
'integerValue': '123',
110+
},
91111
},
92112
},
93113
},
94-
},
95-
};
114+
};
115+
}
96116

97-
it('constructs appropriate fields and getters for event.data', () => {
117+
it('constructs appropriate fields and getters for event.data on "document.write" events', () => {
98118
let testFunction = datastore.document('path').onWrite((event) => {
119+
console.log(testEvent());
120+
console.log(event);
121+
console.log(JSON.stringify(event));
122+
expect(event.data.data()).to.deep.equal({key1: true, key2: 123});
123+
expect(event.data.get('key1')).to.equal(true);
124+
expect(event.data.previous.data()).to.deep.equal({key1: false, key2: 111});
125+
expect(event.data.previous.get('key1')).to.equal(false);
126+
});
127+
return testFunction(testEvent());
128+
});
129+
130+
it('constructs appropriate fields and getters for event.data on "document.create" events', () => {
131+
let testFunction = datastore.document('path').onCreate((event) => {
132+
expect(event.data.data()).to.deep.equal({key1: true, key2: 123});
133+
expect(event.data.get('key1')).to.equal(true);
134+
expect(event.data.previous.data()).to.deep.equal({});
135+
expect(event.data.previous.get('key1')).to.equal(null);
136+
});
137+
let event = testEvent();
138+
event.data.oldValue = null;
139+
return testFunction(event);
140+
});
141+
142+
it('constructs appropriate fields and getters for event.data on "document.update" events', () => {
143+
let testFunction = datastore.document('path').onUpdate((event) => {
99144
expect(event.data.data()).to.deep.equal({key1: true, key2: 123});
100145
expect(event.data.get('key1')).to.equal(true);
101146
expect(event.data.previous.data()).to.deep.equal({key1: false, key2: 111});
102147
expect(event.data.previous.get('key1')).to.equal(false);
103148
});
104-
return testFunction(testEvent);
149+
return testFunction(testEvent());
150+
});
151+
152+
it('constructs appropriate fields and getters for event.data on "document.delete" events', () => {
153+
let testFunction = datastore.document('path').onDelete((event) => {
154+
expect(event.data.data()).to.deep.equal({});
155+
expect(event.data.get('key1')).to.equal(null);
156+
expect(event.data.previous.data()).to.deep.equal({key1: false, key2: 111});
157+
expect(event.data.previous.get('key1')).to.equal(false);
158+
});
159+
let event = testEvent();
160+
event.data.value = null;
161+
return testFunction(event);
105162
});
106163
});
107164

src/providers/datastore.ts

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -69,22 +69,49 @@ export class DocumentBuilder {
6969
// TODO what validation do we want to do here?
7070
}
7171

72-
onWrite(handler: (event: Event<any>) => PromiseLike<any> | any): CloudFunction<any> {
73-
const dataConstructor = (raw: Event<any>) => {
74-
if (raw.data instanceof DeltaDocumentSnapshot) {
75-
return raw.data;
76-
}
77-
return new DeltaDocumentSnapshot(
78-
_.get(raw.data, 'value.fields', {}),
79-
_.get(raw.data, 'oldValue.fields', {})
80-
);
81-
};
82-
return makeCloudFunction({
83-
provider, handler,
84-
resource: this.resource,
85-
eventType: 'document.write',
86-
dataConstructor,
87-
});
72+
/** Respond to all document writes (creates, updates, or deletes). */
73+
onWrite(handler: (event: Event<DeltaDocumentSnapshot>) => PromiseLike<any> |
74+
any): CloudFunction<DeltaDocumentSnapshot> {
75+
return this.onOperation(handler, 'document.write');
76+
}
77+
78+
/** Respond only to document creations. */
79+
onCreate(handler: (event: Event<DeltaDocumentSnapshot>) => PromiseLike<any> |
80+
any): CloudFunction<DeltaDocumentSnapshot> {
81+
return this.onOperation(handler, 'document.create');
82+
}
83+
84+
/** Respond only to document updates. */
85+
onUpdate(handler: (event: Event<DeltaDocumentSnapshot>) => PromiseLike<any> |
86+
any): CloudFunction<DeltaDocumentSnapshot> {
87+
return this.onOperation(handler, 'document.update');
88+
}
89+
90+
/** Respond only to document deletions. */
91+
onDelete(handler: (event: Event<DeltaDocumentSnapshot>) => PromiseLike<any> |
92+
any): CloudFunction<DeltaDocumentSnapshot> {
93+
return this.onOperation(handler, 'document.delete');
94+
}
95+
96+
private onOperation(
97+
handler: (event: Event<DeltaDocumentSnapshot>) => PromiseLike<any> | any,
98+
eventType: string): CloudFunction<DeltaDocumentSnapshot> {
99+
100+
const dataConstructor = (raw: Event<any>) => {
101+
if (raw.data instanceof DeltaDocumentSnapshot) {
102+
return raw.data;
103+
}
104+
return new DeltaDocumentSnapshot(
105+
_.get(raw.data, 'value.fields', {}),
106+
_.get(raw.data, 'oldValue.fields', {})
107+
);
108+
};
109+
return makeCloudFunction({
110+
provider, handler,
111+
resource: this.resource,
112+
eventType: eventType,
113+
dataConstructor,
114+
});
88115
}
89116
}
90117

0 commit comments

Comments
 (0)