genUiCatalogDiff function

List<GenUiCatalogChange> genUiCatalogDiff(
  1. Map<String, Object?> before,
  2. Map<String, Object?> after
)

Every difference between two catalog documents, in the order a reader wants them: breaking first, then by where.

Both arguments are the JSON that genUiCatalogJson produces.

test('the catalog has not broken the agent', () {
  final changes = genUiCatalogDiff(
    jsonDecode(File('catalog.json').readAsStringSync()) as Map<String, Object?>,
    genUiCatalogJson(genUiCatalog),
  );

  expect(
    changes.where((change) => change.isBreaking),
    isEmpty,
    reason: changes.join('\n'),
  );
});

Implementation

List<GenUiCatalogChange> genUiCatalogDiff(
  Map<String, Object?> before,
  Map<String, Object?> after,
) {
  final changes = <GenUiCatalogChange>[];

  if (before['catalogId'] != after['catalogId']) {
    changes.add(
      GenUiCatalogChange(
        GenUiCatalogChangeKind.catalogIdChanged,
        where: 'catalog',
        detail: '${before['catalogId']} -> ${after['catalogId']}',
      ),
    );
  }

  final Map<String, Object?> oldComponents = _components(before);
  final Map<String, Object?> newComponents = _components(after);

  for (final name in <String>{...oldComponents.keys, ...newComponents.keys}) {
    final Object? oldComponent = oldComponents[name];
    final Object? newComponent = newComponents[name];
    if (oldComponent == null) {
      changes.add(
        GenUiCatalogChange(GenUiCatalogChangeKind.componentAdded, where: name),
      );
      continue;
    }
    if (newComponent == null) {
      changes.add(
        GenUiCatalogChange(
          GenUiCatalogChangeKind.componentRemoved,
          where: name,
        ),
      );
      continue;
    }
    changes.addAll(
      _componentChanges(
        name,
        (oldComponent as Map).cast<String, Object?>(),
        (newComponent as Map).cast<String, Object?>(),
      ),
    );
  }

  changes.sort((a, b) {
    if (a.isBreaking != b.isBreaking) return a.isBreaking ? -1 : 1;
    return a.where.compareTo(b.where);
  });
  return changes;
}