@@ -0,0 +1,2344 @@
+package arez.integration.observed;%0A%0Aimport arez.Arez;%0Aimport arez.Flags;%0Aimport arez.Observer;%0Aimport arez.annotations.ArezComponent;%0Aimport arez.annotations.Observable;%0Aimport arez.annotations.Observed;%0Aimport arez.annotations.ObserverRef;%0Aimport arez.annotations.OnDepsChanged;%0Aimport arez.integration.AbstractArezIntegrationTest;%0Aimport org.realityforge.guiceyloops.shared.ValueUtil;%0Aimport org.testng.annotations.Test;%0Aimport static org.testng.Assert.*;%0A%0Apublic class ObservedManualScheduleTest%0A  extends AbstractArezIntegrationTest%0A%7B%0A  @ArezComponent%0A  public static abstract class TestComponent1%0A  %7B%0A    int _renderCallCount;%0A    int _depsChangedCallCount;%0A%0A    @Observed%0A    void render()%0A    %7B%0A      getValue();%0A      _renderCallCount++;%0A    %7D%0A%0A    @OnDepsChanged%0A    final void onRenderDepsChanged()%0A    %7B%0A      _depsChangedCallCount++;%0A    %7D%0A%0A    @ObserverRef%0A    abstract Observer getRenderObserver();%0A%0A    @SuppressWarnings( %22UnusedReturnValue%22 )%0A    @Observable%0A    abstract long getValue();%0A%0A    abstract void setValue( long value );%0A  %7D%0A%0A  @Test%0A  public void scenario()%0A    throws Exception%0A  %7B%0A    final TestComponent1 component = new ObservedManualScheduleTest_Arez_TestComponent1();%0A%0A    assertEquals( component._renderCallCount, 1 );%0A    assertEquals( component._depsChangedCallCount, 0 );%0A%0A    // Scheduling should have no impact as not dirty%0A    Arez.context().safeAction( null, true, false, () -%3E component.getRenderObserver().schedule() );%0A%0A    assertEquals( component._renderCallCount, 1 );%0A    assertEquals( component._depsChangedCallCount, 0 );%0A%0A    // Trigger a dependency change, mark observer as dirty%0A    safeAction( () -%3E component.setValue( ValueUtil.randomLong() ) );%0A%0A    assertEquals( component._renderCallCount, 1 );%0A    assertEquals( component._depsChangedCallCount, 1 );%0A%0A    // Trigger a dependency change - but should not invoke onRenderDepsChanged as still dirty%0A    safeAction( () -%3E component.setValue( ValueUtil.randomLong() ) );%0A%0A    assertEquals( component._renderCallCount, 1 );%0A    assertEquals( component._depsChangedCallCount, 1 );%0A%0A    // Scheduling should actually run render!%0A    Arez.context().safeAction( null, true, false, () -%3E component.getRenderObserver().schedule() );%0A%0A    assertEquals( component._renderCallCount, 2 );%0A    assertEquals( component._depsChangedCallCount, 1 );%0A  %7D%0A%7D%0A

Add integration tests to ensure manual scheduling works as expected