Skip to content

Commit 7efa28d

Browse files
authored
Merge 2308022 into dc7574e
2 parents dc7574e + 2308022 commit 7efa28d

File tree

8 files changed

+72
-7
lines changed

8 files changed

+72
-7
lines changed

.changeset/warm-pillows-know.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@firebase/database-compat": patch
3+
"@firebase/database": patch
4+
---
5+
6+
Fixed faulty transaction bug causing filtered index queries to override default queries.

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ command, as follows:
126126

127127

128128
```bash
129-
# Select the Firebase project via the text-based UI.
129+
# Select the Firebase project via the text-based UI. This will run tools/config.js
130+
# and deploy from config/ to your Firebase project.
130131
$ yarn test:setup
131132

132133
# Specify the Firebase project via the command-line arguments.

config/database.rules.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
{
22
"rules": {
33
".read": true,
4-
".write": true
4+
".write": true,
5+
"testing": {
6+
".indexOn": "testIndex"
7+
}
58
}
69
}

packages/database-compat/test/helpers/util.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ export function getFreshRepo(path: Path) {
146146
'ISOLATED_REPO_' + freshRepoId++
147147
);
148148
activeFreshApps.push(app);
149-
return (app as any).database().ref(path.toString());
149+
return (app as any).database().ref(path.toString()); // TODO(mtewani): Remove explicit any
150150
}
151151

152152
export function getFreshRepoFromReference(ref) {

packages/database/src/core/view/ViewProcessor.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ function viewProcessorApplyServerMerge(
606606
// and event snap. I'm not sure if this will result in edge cases when a child is in one but
607607
// not the other.
608608
let curViewCache = viewCache;
609-
let viewMergeTree;
609+
let viewMergeTree: ImmutableTree<Node>;
610610
if (pathIsEmpty(path)) {
611611
viewMergeTree = changedChildren;
612612
} else {
@@ -641,7 +641,7 @@ function viewProcessorApplyServerMerge(
641641
viewMergeTree.children.inorderTraversal((childKey, childMergeTree) => {
642642
const isUnknownDeepMerge =
643643
!viewCache.serverCache.isCompleteForChild(childKey) &&
644-
childMergeTree.value === undefined;
644+
childMergeTree.value === null;
645645
if (!serverNode.hasChild(childKey) && !isUnknownDeepMerge) {
646646
const serverChild = viewCache.serverCache
647647
.getNode()

packages/database/test/exp/integration.test.ts

+51
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,14 @@ import {
2424
child,
2525
get,
2626
limitToFirst,
27+
onChildAdded,
2728
onValue,
29+
orderByChild,
2830
query,
2931
refFromURL,
3032
set,
3133
startAt,
34+
update,
3235
orderByKey
3336
} from '../../src/api/Reference_impl';
3437
import {
@@ -117,6 +120,54 @@ describe('Database@exp Tests', () => {
117120
unsubscribe();
118121
});
119122

123+
it('can properly handle unknown deep merges', async () => {
124+
// Note: This test requires `testIndex` to be added as an index.
125+
// Please run `yarn test:setup` to ensure that this gets added.
126+
const database = getDatabase(defaultApp);
127+
const root = ref(database, 'testing');
128+
await set(root, {});
129+
130+
const q = query(root, orderByChild('testIndex'), limitToFirst(2));
131+
132+
const i1 = child(root, 'i1');
133+
await set(root, {
134+
i1: {
135+
testIndex: 3,
136+
timestamp: Date.now(),
137+
action: 'test'
138+
},
139+
i2: {
140+
testIndex: 1,
141+
timestamp: Date.now(),
142+
action: 'test'
143+
},
144+
i3: {
145+
testIndex: 2,
146+
timestamp: Date.now(),
147+
action: 'test'
148+
}
149+
});
150+
const ec = EventAccumulatorFactory.waitsForExactCount(2);
151+
const onChildAddedCb = onChildAdded(q, snap => {
152+
ec.addEvent(snap);
153+
});
154+
const onValueCb = onValue(i1, () => {
155+
//no-op
156+
});
157+
await update(i1, {
158+
timestamp: `${Date.now()}|1`
159+
});
160+
const results = await ec.promise;
161+
results.forEach(result => {
162+
const value = result.val();
163+
expect(value).to.haveOwnProperty('timestamp');
164+
expect(value).to.haveOwnProperty('action');
165+
expect(value).to.haveOwnProperty('testIndex');
166+
});
167+
onChildAddedCb();
168+
onValueCb();
169+
});
170+
120171
// Tests to make sure onValue's data does not get mutated after calling get
121172
it('calls onValue only once after get request with a non-default query', async () => {
122173
const { readerRef } = getRWRefs(getDatabase(defaultApp));

packages/database/test/helpers/EventAccumulator.ts

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717

1818
export const EventAccumulatorFactory = {
19+
// TODO: Convert to use generics to take the most advantage of types.
1920
waitsForCount: maxCount => {
2021
// Note: This should be used sparingly as it can result in more events being raised than expected
2122
let count = 0;

scripts/emulator-testing/emulators/database-emulator.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import * as request from 'request';
1919

2020
import { Emulator } from './emulator';
2121

22+
import * as rulesJSON from '../../../config/database.rules.json';
23+
2224
export class DatabaseEmulator extends Emulator {
2325
namespace: string;
2426

@@ -35,13 +37,14 @@ export class DatabaseEmulator extends Emulator {
3537
}
3638

3739
setPublicRules(): Promise<number> {
38-
console.log('Setting rule {".read": true, ".write": true} to emulator ...');
40+
const jsonRules = JSON.stringify(rulesJSON);
41+
console.log(`Setting rule ${jsonRules} to emulator ...`);
3942
return new Promise<number>((resolve, reject) => {
4043
request.put(
4144
{
4245
uri: `http://localhost:${this.port}/.settings/rules.json?ns=${this.namespace}`,
4346
headers: { Authorization: 'Bearer owner' },
44-
body: '{ "rules": { ".read": true, ".write": true } }'
47+
body: jsonRules
4548
},
4649
(error, response, body) => {
4750
if (error) reject(error);

0 commit comments

Comments
 (0)