anchor.diff:  
   @JS()
   external List getNonUpdatingSetStateLifeCycleCalls();
  +
  +/// A test helper to record lifecycle calls
  +abstract class LifecycleTestHelper {
  +  Map context;
  +  Map props;
  +  Map state;
  +
  +  List lifecycleCalls = [];
  +
  +  dynamic lifecycleCall(String memberName, {List arguments: const [], defaultReturnValue()}) {
  +    lifecycleCalls.add({
  +      'memberName': memberName,
  +      'arguments': arguments,
  +      'props': props == null ? null : new Map.from(props),
  +      'state': state == null ? null : new Map.from(state),
  +      'context': new Map.from(context ?? const {}),
  +    });
  +
  +    var lifecycleCallback = props == null ? null : props[memberName];
  +    if (lifecycleCallback != null) {
  +      return Function.apply(lifecycleCallback, []
  +          ..add(this)
  +          ..addAll(arguments));
  +    }
  +
  +    if (defaultReturnValue != null) {
  +      return defaultReturnValue();
  +    }
  +
  +    return null;
  +  }
  +}
   
   ReactDartComponentFactoryProxy SetStateTest = react.registerComponent(() => new _SetStateTest());
   class _SetStateTest extends react.Component {
  
positive.code: ReactDartComponentFactoryProxy LifecycleTestWithContext = react.registerComponent(() => new _LifecycleTestWithContext());
  class _LifecycleTestWithContext extends _LifecycleTest {
    @override
    Iterable<String> get contextKeys => const ['foo'];
  }
  
  ReactDartComponentFactoryProxy LifecycleTest = react.registerComponent(() => new _LifecycleTest());
  class _LifecycleTest extends react.Component {
    List lifecycleCalls = [];
  
    dynamic lifecycleCall(String memberName, {List arguments: const [], defaultReturnValue()}) {
      lifecycleCalls.add({
        'memberName': memberName,
        'arguments': arguments,
        'props': props == null ? null : new Map.from(props),
        'state': state == null ? null : new Map.from(state),
        'context': new Map.from(context ?? const {}),
      });
  
      var lifecycleCallback = props == null ? null : props[memberName];
      if (lifecycleCallback != null) {
        return Function.apply(lifecycleCallback, []
            ..add(this)
            ..addAll(arguments));
      }
  
      if (defaultReturnValue != null) {
        return defaultReturnValue();
      }
  
      return null;
    }
  
    void componentWillMount() => lifecycleCall('componentWillMount');
    void componentDidMount() => lifecycleCall('componentDidMount');
    void componentWillUnmount() => lifecycleCall('componentWillUnmount');
  
negative.code: 
        expect(component.lifecycleCalls, equals([
          matchCall('componentWillUnmount'),
        ]));
      });
  
      test('does not call getChildContext when childContextKeys is empty', () {
        var mountNode = new DivElement();
        var instance = react_dom.render(ContextWrapperWithoutKeys({'foo': false}, LifecycleTestWithContext({})), mountNode);
        _ContextWrapperWithoutKeys component = getDartComponent(instance);
  
        expect(component.lifecycleCalls, isEmpty);
      });
  
      test('calls getChildContext when childContextKeys exist', () {
        var mountNode = new DivElement();
        var instance = react_dom.render(ContextWrapper({'foo': false}, LifecycleTestWithContext({})), mountNode);
        _ContextWrapper component = getDartComponent(instance);
  
        expect(component.lifecycleCalls, equals([
          matchCall('getChildContext'),
        ]));
      });
  
  