@@ -8,12 +8,17 @@ import 'mock_firebase_database.dart';
88class MockDatabaseReference extends Mock implements DatabaseReference {
99 var _nodePath = '/' ;
1010 // ignore: prefer_final_fields
11- static final _persitedData = < String , dynamic > {};
11+ static var _persitedData = < String , dynamic > {};
1212 var _volatileData = < String , dynamic > {};
1313 MockDatabaseReference ();
1414 MockDatabaseReference ._(nodePath, [this ._volatileData]) {
1515 _nodePath += nodePath;
1616 }
17+ // TODO implement real [onchange] (may yield each change).
18+ Stream <Event > get onValue async * {
19+ final data = await once ();
20+ yield MockEvent ._(data.value);
21+ }
1722
1823 Map <String , dynamic > get _data {
1924 if (MockFirebaseDatabase .persistData) {
@@ -22,6 +27,13 @@ class MockDatabaseReference extends Mock implements DatabaseReference {
2227 return _volatileData;
2328 }
2429
30+ set _data (data) {
31+ if (MockFirebaseDatabase .persistData) {
32+ _persitedData = data;
33+ } else
34+ return _volatileData = data;
35+ }
36+
2537 @override
2638 String get path => _nodePath;
2739
@@ -38,78 +50,98 @@ class MockDatabaseReference extends Mock implements DatabaseReference {
3850 @override
3951 // ignore: missing_return
4052 Future <void > set (dynamic value, {dynamic priority}) {
53+ if (_nodePath == '/' ) {
54+ _data = value;
55+ return null ;
56+ }
4157 var nodePathWithoutSlashesAtEndAndStart =
4258 _nodePath.substring (1 , _nodePath.length - 1 );
4359 var nodesList = nodePathWithoutSlashesAtEndAndStart.split ('/' );
4460 var tempData = < String , dynamic > {};
4561 Map <String , dynamic > lastNodeInCurrentData;
4662 var nodeIndexReference = _Int (0 );
47- if (_data.isEmpty ) {
63+ if (_data[nodesList.first] == null ) {
4864 lastNodeInCurrentData = _data;
4965 } else {
50- lastNodeInCurrentData = getNode (
51- data: _data,
52- nodesList: nodesList,
53- nodeIndex: nodeIndexReference.increment (),
54- );
66+ lastNodeInCurrentData = _getNextNodeData (
67+ data: _data, nodesList: nodesList, nodeIndex: nodeIndexReference);
5568 }
5669 var nodeIndex = nodeIndexReference.value;
57- if (nodesList.length <= nodeIndex) {
70+ var noNewNodeToAdd = nodesList.length <= nodeIndex;
71+ if (noNewNodeToAdd) {
5872 lastNodeInCurrentData[nodesList.last] = value;
5973 return null ;
6074 }
6175 var firstNodeInNewData = nodesList[nodeIndex++ ];
6276 if (nodeIndex < nodesList.length) {
63- for (; nodeIndex < nodesList.length; nodeIndex++ ) {
64- if (nodeIndex + 1 < nodesList.length) {
65- tempData[nodesList[nodeIndex]] = {nodesList[nodeIndex + 1 ]: null };
66- tempData = tempData[nodesList[nodeIndex]];
67- } else {
68- tempData[nodesList[nodeIndex]] = value;
69- }
70- }
71- lastNodeInCurrentData
72- .addAll ({firstNodeInNewData: _makeSupportGenericValue (tempData)});
77+ tempData = _buildNewNodesTree (
78+ nodeIndex: nodeIndex,
79+ nodesList: nodesList,
80+ data: tempData,
81+ value: value,
82+ );
83+ lastNodeInCurrentData.addAll ({firstNodeInNewData: tempData});
7384 } else {
74- if (value is Map ) value = _makeSupportGenericValue ( value) ;
85+ if (value is Map ) value = value;
7586 lastNodeInCurrentData.addAll ({firstNodeInNewData: value});
7687 }
7788 }
7889
79- dynamic getNode (
80- {@required dynamic data,
81- @required List <String > nodesList,
82- @required _Int nodeIndex}) {
83- // print(data);
84- // print(nodeIndex.value);
85- if (nodesList.length == nodeIndex.value ||
86- ! (data[nodesList[nodeIndex.value]] is Map )) return data;
87- return getNode (
88- data: data[nodesList[nodeIndex.value]],
89- nodesList: nodesList,
90- nodeIndex: nodeIndex.increment ());
90+ Map <String , dynamic > _buildNewNodesTree ({
91+ @required dynamic data,
92+ @required List <String > nodesList,
93+ @required int nodeIndex,
94+ @required value,
95+ }) {
96+ var nextNodeIndex = nodeIndex + 1 ;
97+ if (nodeIndex + 1 < nodesList.length) {
98+ data[nodesList[nodeIndex]] = {nodesList[nextNodeIndex]: Object ()};
99+ _buildNewNodesTree (
100+ data: data[nodesList[nodeIndex]],
101+ nodesList: nodesList,
102+ nodeIndex: nextNodeIndex,
103+ value: value);
104+ } else
105+ data[nodesList[nodeIndex]] = value;
106+ return data;
107+ }
108+
109+ _getNextNodeData ({
110+ @required dynamic data,
111+ @required List <String > nodesList,
112+ @required _Int nodeIndex,
113+ }) {
114+ if (nodesList.length <= nodeIndex.value ||
115+ ! (data[nodesList[nodeIndex.value]] is Map )) {
116+ nodeIndex.increment ();
117+ return data;
118+ }
119+ return _getNextNodeData (
120+ data: data[nodesList[nodeIndex.value]],
121+ nodesList: nodesList,
122+ nodeIndex: nodeIndex.increment (),
123+ );
91124 }
92125
93126 @override
94127 Future <DataSnapshot > once () {
95- return Future (() {
96- var tempData = _data;
97- var nodePath = _nodePath.substring (1 , _nodePath.length - 1 );
98- var nodeList = nodePath.split ('/' );
99- if (nodeList.length > 1 ) {
100- for (var node in nodeList) {
101- nodePath = node;
102- if (tempData[node] == null ) {
103- nodePath = '' ;
104- break ;
105- }
106- if (tempData[node] is Map ) {
107- tempData = tempData[node];
108- }
128+ var tempData = _data;
129+ // remove start and end slashes.
130+ var nodePath = _nodePath.substring (1 , _nodePath.length - 1 );
131+ var nodeList = nodePath.split ('/' );
132+ if (nodeList.length > 1 ) {
133+ for (var i = 0 ; i < nodeList.length; i++ ) {
134+ nodePath = nodeList[i];
135+ var nonExistentNodeFound = tempData[nodePath] == null ;
136+ if (nonExistentNodeFound || (i + 1 ) == nodeList.length) {
137+ break ;
138+ }
139+ if (tempData[nodePath] is Map ) {
140+ tempData = tempData[nodePath];
109141 }
110142 }
111- return MockDataSnapshot (tempData[nodePath]);
112- } );
143+ }
144+ return Future . value ( MockDataSnapshot (tempData[nodePath]) );
113145 }
114146}
115147
@@ -122,13 +154,19 @@ class _Int {
122154 }
123155}
124156
125- Map <String , Object > _makeSupportGenericValue (Map <String , dynamic > data) {
126- var _dataWithGenericValue = {'__generic_mock_data_value__' : Object ()};
127- _dataWithGenericValue.addAll (data);
128- _dataWithGenericValue.forEach ((key, value) {
129- if (value is Map ) {
130- _dataWithGenericValue[key] = _makeSupportGenericValue (value);
131- }
132- });
133- return _dataWithGenericValue;
157+ class MockEvent extends Mock implements Event {
158+ MockEvent ._(data) : snapshot = MockDataSnapshot (data);
159+
160+ final DataSnapshot snapshot;
134161}
162+
163+ // Map<String, dynamic> _makeSupportGenericValue(Map<String, dynamic> data) {
164+ // var _dataWithGenericValue = {'__generic_mock_data_value__': Object()};
165+ // _dataWithGenericValue.addAll(data);
166+ // _dataWithGenericValue.forEach((key, value) {
167+ // if (value is Map) {
168+ // _dataWithGenericValue[key] = _makeSupportGenericValue(value);
169+ // }
170+ // });
171+ // return _dataWithGenericValue;
172+ // }
0 commit comments