Skip to content

Commit

Permalink
feat: Port flat.js tests
Browse files Browse the repository at this point in the history
  • Loading branch information
danilofuchs committed Nov 7, 2023
1 parent be591ac commit 242390d
Show file tree
Hide file tree
Showing 4 changed files with 206 additions and 24 deletions.
5 changes: 5 additions & 0 deletions lib/src/unflatten.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/// Unflatten a map with keys such as `a.b.c: value` to a nested Map structure `{a: {b: {c: value}}}`.
///
/// If no [delimiter] is specified, will separate depth levels by `.`.
///
/// Unflattens arrays given that the keys are integers.
Map<String, dynamic> unflatten(
Map<String, dynamic> flatMap, {
String delimiter = ".",
Expand Down
35 changes: 35 additions & 0 deletions test/flat_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import 'package:flat/src/flatten.dart';
import 'package:flat/src/unflatten.dart';
import 'package:test/test.dart';

void main() {
group('flatten and unflatten', () {
test(
'Order of keys should not be changed after round trip flatten/unflatten',
() {
const obj = {
'b': 1,
'abc': {
'c': [
{
'd': 1,
'bca': 1,
'a': 1,
},
],
},
'a': 1,
};

final result = unflatten(flatten(obj));

expect(obj.keys, result.keys);
expect((obj['abc']! as Map).keys, (result['abc']! as Map).keys);
expect(
// ignore: avoid_dynamic_calls
(obj['abc']! as Map)['c'][0].keys,
(result['abc']! as Map).keys,
);
});
});
}
46 changes: 23 additions & 23 deletions test/flatten_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ void main() {
test('Flattens nested Map', () {
const obj = {
"a": 1,
"b": {"c": 2}
"b": {"c": 2},
};

const expected = {"a": 1, "b.c": 2};
Expand Down Expand Up @@ -40,7 +40,7 @@ void main() {

test('Preserves deep null', () {
const obj = {
"a": {"b": null}
"a": {"b": null},
};

const expected = {"a.b": null};
Expand All @@ -53,7 +53,7 @@ void main() {
test('Flattens List', () {
const obj = {
"a": "item",
"b": [0, 1]
"b": [0, 1],
};

const expected = {"a": "item", "b.0": 0, "b.1": 1};
Expand All @@ -71,10 +71,10 @@ void main() {
"d": "asd",
"a": {
"a": [
{"where": "a"}
]
}
}
{"where": "a"},
],
},
},
};

const expected = {"a": 1, "b.c": 2, "b.d": "asd", "b.a.a.0.where": "a"};
Expand All @@ -87,7 +87,7 @@ void main() {
test('Should delimit with optional delimiter parameter', () {
const obj = {
"a": 1,
"b": {"c": 2}
"b": {"c": 2},
};

const expected = {"a": 1, "b_c": 2};
Expand All @@ -102,16 +102,16 @@ void main() {
"a": 1,
"b": {
"c": [
{"d": 2}
]
}
{"d": 2},
],
},
};

const expected = {
"a": 1,
"b.c": [
{"d": 2}
]
{"d": 2},
],
};

final result = flatten(obj, safe: true);
Expand All @@ -124,18 +124,18 @@ void main() {
"a": {
"b": {
"c": {
"d": {"e": 1}
}
}
}
"d": {"e": 1},
},
},
},
};

const maxDepth = 3;

const expected = {
"a.b.c": {
"d": {"e": 1}
}
"d": {"e": 1},
},
};

final result = flatten(obj, maxDepth: maxDepth);
Expand All @@ -148,17 +148,17 @@ void main() {
const obj = {
"mediaData": {
"resources": [
{"uri": "spotify://", "mimeType": "audio/unknown"}
]
}
{"uri": "spotify://", "mimeType": "audio/unknown"},
],
},
};

final result =
flatten(jsonDecode(jsonEncode(obj)) as Map<String, dynamic>);

expect(result, {
"mediaData.resources.0.uri": "spotify://",
"mediaData.resources.0.mimeType": "audio/unknown"
"mediaData.resources.0.mimeType": "audio/unknown",
});
});
});
Expand Down
144 changes: 143 additions & 1 deletion test/unflatten_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,27 @@ void main() {
"world": {
"again": 'good morning',
},
}
},
};

final result = unflatten(obj);

expect(result, expected);
});

test('Object inside array', () {
const obj = {
'hello.0.again': 'good morning',
};

const expected = {
"hello": [
{
"world": {
"again": 'good morning',
},
},
],
};

final result = unflatten(obj);
Expand Down Expand Up @@ -66,5 +86,127 @@ void main() {

expect(result, expected);
});

test('nested objects do not clobber each other when a.b inserted before a',
() {
final obj = <String, dynamic>{};
obj['foo.bar'] = {'t': 123};
obj['foo'] = {'p': 333};

const expected = {
"foo": {
"bar": {
't': 123,
},
'p': 333,
},
};

final result = unflatten(obj);

expect(result, expected);
});

test('Custom Delimiter', () {
const obj = {
'hello world again': 'good morning',
};

const expected = {
"hello": {
"world": {
"again": 'good morning',
},
},
};

final result = unflatten(obj, delimiter: ' ');

expect(result, expected);
});

test('Messy', () {
const obj = {
'hello.world': 'again',
'lorem.ipsum': 'another',
'good.morning': {
'hash.key': {
'nested.deep': {
'and.even.deeper.still': 'hello',
},
},
},
'good.morning.again': {'testing.this': 'out'},
};

const expected = {
'hello': {'world': 'again'},
'lorem': {'ipsum': 'another'},
'good': {
'morning': {
'hash': {
'key': {
'nested': {
'deep': {
'and': {
'even': {
'deeper': {'still': 'hello'},
},
},
},
},
},
},
'again': {
'testing': {'this': 'out'},
},
},
},
};

final result = unflatten(obj);

expect(result, expected);
});

test('Should be unflatten array', () {
const obj = {
'a.0': 'foo',
'a.1': 'bar',
};

const expected = {
'a': ['foo', 'bar'],
};

final result = unflatten(obj);

expect(result, expected);
});

test('Does not interpret keys with numbers as arrays', () {
const obj = {'1key.2_key': 'ok'};

const expected = {
'1key': {'2_key': 'ok'},
};

final result = unflatten(obj);

expect(result, expected);
});

test('Empty objects should not be removed', () {
const obj = {'foo': [], 'bar': {}};

const expected = {
'foo': [],
'bar': {},
};

final result = unflatten(obj);

expect(result, expected);
});
});
}

0 comments on commit 242390d

Please sign in to comment.