@@ -126,22 +126,33 @@ public async Task Test_AsyncRelayCommand_WithCancellation()
126126 {
127127 TaskCompletionSource < object > tcs = new TaskCompletionSource < object > ( ) ;
128128
129+ // We need to test the cancellation support here, so we use the overload with an input
130+ // parameter, which is a cancellation token. The token is the one that is internally managed
131+ // by the AsyncRelayCommand instance, and canceled when using IAsyncRelayCommand.Cancel().
129132 var command = new AsyncRelayCommand ( token => tcs . Task ) ;
130133
131134 List < PropertyChangedEventArgs > args = new List < PropertyChangedEventArgs > ( ) ;
132135
133136 command . PropertyChanged += ( s , e ) => args . Add ( e ) ;
134137
138+ // We have no canExecute parameter, so the command can always be invoked
135139 Assert . IsTrue ( command . CanExecute ( null ) ) ;
136140 Assert . IsTrue ( command . CanExecute ( new object ( ) ) ) ;
137141
142+ // The command isn't running, so it can't be canceled yet
138143 Assert . IsFalse ( command . CanBeCanceled ) ;
139144 Assert . IsFalse ( command . IsCancellationRequested ) ;
140145
146+ // Start the command, which will return the token from our task completion source.
147+ // We can use that to easily keep the command running while we do our tests, and then
148+ // stop the processing by completing the source when we need (see below).
141149 command . Execute ( null ) ;
142150
151+ // The command is running, so it can be canceled, as we used the token overload
143152 Assert . IsTrue ( command . CanBeCanceled ) ;
144153 Assert . IsFalse ( command . IsCancellationRequested ) ;
154+
155+ // Validate the various event args for all the properties that were updated when executing the command
145156 Assert . AreEqual ( args . Count , 4 ) ;
146157 Assert . AreEqual ( args [ 0 ] . PropertyName , nameof ( IAsyncRelayCommand . IsCancellationRequested ) ) ;
147158 Assert . AreEqual ( args [ 1 ] . PropertyName , nameof ( IAsyncRelayCommand . ExecutionTask ) ) ;
@@ -150,16 +161,21 @@ public async Task Test_AsyncRelayCommand_WithCancellation()
150161
151162 command . Cancel ( ) ;
152163
164+ // Verify that these two properties raised notifications correctly when canceling the command too.
165+ // We need to ensure all command properties support notifications so that users can bind to them.
153166 Assert . AreEqual ( args . Count , 6 ) ;
154167 Assert . AreEqual ( args [ 4 ] . PropertyName , nameof ( IAsyncRelayCommand . IsCancellationRequested ) ) ;
155168 Assert . AreEqual ( args [ 5 ] . PropertyName , nameof ( IAsyncRelayCommand . CanBeCanceled ) ) ;
156169
157170 Assert . IsTrue ( command . IsCancellationRequested ) ;
158171
172+ // Complete the source, which will mark the command as completed too (as it returned the same task)
159173 tcs . SetResult ( null ) ;
160174
161175 await command . ExecutionTask ! ;
162176
177+ // Verify that the command can no longer be canceled, and that the cancellation is
178+ // instead still true, as that's reset when executing a command and not on completion.
163179 Assert . IsFalse ( command . CanBeCanceled ) ;
164180 Assert . IsTrue ( command . IsCancellationRequested ) ;
165181 }
0 commit comments