| <!DOCTYPE html> |
| <html> |
| <!-- |
| Copyright 2012 The Closure Library Authors. All Rights Reserved. |
| |
| Use of this source code is governed by the Apache License, Version 2.0. |
| See the COPYING file for details. |
| --> |
| <head> |
| <title>Closure Unit Tests - goog.result.SimpleResult</title> |
| <script src="../base.js"></script> |
| <script> |
| |
| goog.require('goog.Timer'); |
| goog.require('goog.Promise'); |
| goog.require('goog.Thenable'); |
| goog.require('goog.result'); |
| goog.require('goog.testing.MockClock'); |
| goog.require('goog.testing.recordFunction'); |
| goog.require('goog.testing.jsunit'); |
| |
| </script> |
| </head> |
| <body> |
| <script> |
| |
| var result, mockClock, resultCallback; |
| |
| function setUpPage() { |
| mockClock = new goog.testing.MockClock(); |
| mockClock.install(); |
| } |
| |
| function setUp() { |
| mockClock.reset(); |
| resultCallback = new goog.testing.recordFunction(); |
| resultCallback1 = new goog.testing.recordFunction(); |
| resultCallback2 = new goog.testing.recordFunction(); |
| result = new goog.result.SimpleResult(); |
| } |
| |
| function tearDown() { |
| resultCallback = resultCallback1 = resultCallback2 = result = null; |
| } |
| |
| function tearDownPage() { |
| mockClock.uninstall(); |
| goog.dispose(mockClock); |
| } |
| |
| function testHandlersCalledOnSuccess() { |
| result.wait(resultCallback1); |
| result.wait(resultCallback2); |
| |
| assertEquals(goog.result.Result.State.PENDING, result.getState()); |
| assertEquals(0, resultCallback1.getCallCount()); |
| assertEquals(0, resultCallback2.getCallCount()); |
| |
| result.setValue(2); |
| |
| assertEquals(goog.result.Result.State.SUCCESS, result.getState()); |
| assertEquals(2, result.getValue()); |
| assertEquals(1, resultCallback1.getCallCount()); |
| assertEquals(1, resultCallback2.getCallCount()); |
| |
| var res1 = resultCallback1.popLastCall().getArgument(0); |
| assertObjectEquals(result, res1); |
| |
| var res2 = resultCallback2.popLastCall().getArgument(0); |
| assertObjectEquals(result, res2); |
| } |
| |
| function testCustomHandlerScope() { |
| result.wait(resultCallback1); |
| var scope = {}; |
| result.wait(resultCallback2, scope); |
| |
| result.setValue(2); |
| |
| assertEquals(1, resultCallback1.getCallCount()); |
| assertEquals(1, resultCallback2.getCallCount()); |
| |
| var this1 = resultCallback1.popLastCall().getThis(); |
| assertObjectEquals(goog.global, this1); |
| |
| var this2 = resultCallback2.popLastCall().getThis(); |
| assertObjectEquals(scope, this2); |
| } |
| |
| function testHandlersCalledOnError() { |
| result.wait(resultCallback1); |
| result.wait(resultCallback2); |
| assertEquals(goog.result.Result.State.PENDING, result.getState()); |
| |
| var error = "Network Error"; |
| result.setError(error); |
| |
| assertEquals(goog.result.Result.State.ERROR, result.getState()); |
| assertEquals(error, result.getError()); |
| assertEquals(1, resultCallback1.getCallCount()); |
| assertEquals(1, resultCallback2.getCallCount()); |
| |
| var res1 = resultCallback1.popLastCall().getArgument(0); |
| assertObjectEquals(result, res1); |
| var res2 = resultCallback2.popLastCall().getArgument(0); |
| assertObjectEquals(result, res2); |
| } |
| |
| function testAttachingHandlerOnSuccessfulResult() { |
| result.setValue(2); |
| assertEquals(goog.result.Result.State.SUCCESS, result.getState()); |
| assertEquals(2, result.getValue()); |
| // resultCallback should be called immediately on a resolved Result |
| assertEquals(0, resultCallback.getCallCount()); |
| |
| result.wait(resultCallback); |
| |
| assertEquals(1, resultCallback.getCallCount()); |
| var res = resultCallback.popLastCall().getArgument(0); |
| assertEquals(result, res); |
| } |
| |
| function testAttachingHandlerOnErrorResult() { |
| var error = { code: -1, errorString: "Invalid JSON" }; |
| result.setError(error); |
| assertEquals(goog.result.Result.State.ERROR, result.getState()); |
| assertEquals(error, result.getError()); |
| // resultCallback should be called immediately on a resolved Result |
| assertEquals(0, resultCallback.getCallCount()); |
| |
| result.wait(resultCallback); |
| |
| assertEquals(1, resultCallback.getCallCount()); |
| var res = resultCallback.popLastCall().getArgument(0); |
| assertEquals(result, res); |
| } |
| |
| function testExceptionThrownOnMultipleSuccessfulResolutionAttempts() { |
| result.setValue(1); |
| assertEquals(goog.result.Result.State.SUCCESS, result.getState()); |
| assertEquals(1, result.getValue()); |
| |
| // Try to set the value again |
| var e = assertThrows(goog.bind(result.setValue, result, 3)); |
| assertTrue(e instanceof goog.result.SimpleResult.StateError); |
| } |
| |
| function testExceptionThrownOnMultipleErrorResolutionAttempts() { |
| assertEquals(goog.result.Result.State.PENDING, result.getState()); |
| |
| result.setError(5); |
| |
| assertEquals(goog.result.Result.State.ERROR, result.getState()); |
| assertEquals(5, result.getError()); |
| // Try to set error again |
| var e = assertThrows(goog.bind(result.setError, result, 4)); |
| assertTrue(e instanceof goog.result.SimpleResult.StateError); |
| } |
| |
| function testExceptionThrownOnSuccessThenErrorResolutionAttempt() { |
| assertEquals(goog.result.Result.State.PENDING, result.getState()); |
| |
| result.setValue(1); |
| |
| assertEquals(goog.result.Result.State.SUCCESS, result.getState()); |
| assertEquals(1, result.getValue()); |
| |
| // Try to set error after setting value |
| var e = assertThrows(goog.bind(result.setError, result, 3)); |
| assertTrue(e instanceof goog.result.SimpleResult.StateError); |
| } |
| |
| function testExceptionThrownOnErrorThenSuccessResolutionAttempt() { |
| assertEquals(goog.result.Result.State.PENDING, result.getState()); |
| |
| var error = "fail"; |
| result.setError(error); |
| |
| assertEquals(goog.result.Result.State.ERROR, result.getState()); |
| assertEquals(error, result.getError()); |
| // Try to set value after setting error |
| var e = assertThrows(goog.bind(result.setValue, result, 1)); |
| assertTrue(e instanceof goog.result.SimpleResult.StateError); |
| } |
| |
| function testSuccessfulAsyncResolution() { |
| result.wait(resultCallback); |
| assertEquals(goog.result.Result.State.PENDING, result.getState()); |
| |
| goog.Timer.callOnce(function() { |
| result.setValue(1); |
| }); |
| mockClock.tick(); |
| |
| assertEquals(1, resultCallback.getCallCount()); |
| |
| var res = resultCallback.popLastCall().getArgument(0); |
| assertEquals(goog.result.Result.State.SUCCESS, res.getState()); |
| assertEquals(1, res.getValue()); |
| } |
| |
| function testErrorAsyncResolution() { |
| result.wait(resultCallback); |
| assertEquals(goog.result.Result.State.PENDING, result.getState()); |
| |
| var error = 'Network failure'; |
| goog.Timer.callOnce(function() { |
| result.setError(error); |
| }); |
| mockClock.tick(); |
| |
| assertEquals(1, resultCallback.getCallCount()); |
| var res = resultCallback.popLastCall().getArgument(0); |
| assertEquals(goog.result.Result.State.ERROR, res.getState()); |
| assertEquals(error, res.getError()); |
| } |
| |
| function testCancelStateAndReturn() { |
| assertFalse(result.isCanceled()); |
| var canceled = result.cancel(); |
| assertTrue(result.isCanceled()); |
| assertEquals(goog.result.Result.State.ERROR, result.getState()); |
| assertTrue(result.getError() instanceof goog.result.Result.CancelError); |
| assertTrue(canceled); |
| } |
| |
| function testErrorHandlersFireOnCancel() { |
| result.wait(resultCallback); |
| result.cancel(); |
| |
| assertEquals(1, resultCallback.getCallCount()); |
| var lastCall = resultCallback.popLastCall(); |
| var res = lastCall.getArgument(0); |
| assertEquals(goog.result.Result.State.ERROR, res.getState()); |
| assertTrue(res.getError() instanceof goog.result.Result.CancelError); |
| } |
| |
| function testCancelAfterSetValue() { |
| // cancel after setValue/setError => no-op |
| result.wait(resultCallback); |
| result.setValue(1); |
| |
| assertEquals(goog.result.Result.State.SUCCESS, result.getState()); |
| assertEquals(1, result.getValue()); |
| assertEquals(1, resultCallback.getCallCount()); |
| |
| result.cancel(); |
| |
| assertEquals(goog.result.Result.State.SUCCESS, result.getState()); |
| assertEquals(1, result.getValue()); |
| assertEquals(1, resultCallback.getCallCount()); |
| } |
| |
| function testSetValueAfterCancel() { |
| // setValue/setError after cancel => no-op |
| result.wait(resultCallback); |
| |
| result.cancel(); |
| assertTrue(result.isCanceled()); |
| assertTrue(result.getError() instanceof goog.result.Result.CancelError); |
| |
| result.setValue(1); |
| assertTrue(result.isCanceled()); |
| assertTrue(result.getError() instanceof goog.result.Result.CancelError); |
| |
| result.setError(3); |
| assertTrue(result.isCanceled()); |
| assertTrue(result.getError() instanceof goog.result.Result.CancelError); |
| } |
| |
| function testFromResolvedPromise() { |
| var promise = goog.Promise.resolve('resolved'); |
| result = goog.result.SimpleResult.fromPromise(promise); |
| assertEquals(goog.result.Result.State.PENDING, result.getState()); |
| mockClock.tick(); |
| assertEquals(goog.result.Result.State.SUCCESS, result.getState()); |
| assertEquals('resolved', result.getValue()); |
| assertEquals(undefined, result.getError()); |
| } |
| |
| function testFromRejectedPromise() { |
| var promise = goog.Promise.reject('rejected'); |
| result = goog.result.SimpleResult.fromPromise(promise); |
| assertEquals(goog.result.Result.State.PENDING, result.getState()); |
| mockClock.tick(); |
| assertEquals(goog.result.Result.State.ERROR, result.getState()); |
| assertEquals(undefined, result.getValue()); |
| assertEquals('rejected', result.getError()); |
| } |
| |
| function testThen() { |
| var value1, value2; |
| result.then(function(val1) { |
| return value1 = val1; |
| }).then(function(val2) { |
| value2 = val2; |
| }); |
| result.setValue('done'); |
| assertUndefined(value1); |
| assertUndefined(value2); |
| mockClock.tick(); |
| assertEquals('done', value1); |
| assertEquals('done', value2); |
| } |
| |
| function testThen_reject() { |
| var value, reason; |
| result.then( |
| function(v) { value = v; }, |
| function(r) { reason = r; }); |
| result.setError(new Error('oops')); |
| assertUndefined(value); |
| mockClock.tick(); |
| assertUndefined(value); |
| assertEquals('oops', reason.message); |
| } |
| |
| function testPromiseAll() { |
| var promise = goog.Promise.resolve('promise'); |
| goog.Promise.all([result, promise]).then(function(values) { |
| assertEquals(2, values.length); |
| assertEquals('result', values[0]); |
| assertEquals('promise', values[1]); |
| }); |
| result.setValue('result'); |
| mockClock.tick(); |
| } |
| |
| function testResolvingPromiseBlocksResult() { |
| var value; |
| goog.Promise.resolve('promise').then(function(value) { |
| result.setValue(value); |
| }); |
| result.wait(function(r) { |
| value = r.getValue(); |
| }); |
| assertUndefined(value); |
| mockClock.tick(); |
| assertEquals('promise', value); |
| } |
| |
| function testRejectingPromiseBlocksResult() { |
| var err; |
| goog.Promise.reject(new Error('oops')).then( |
| undefined /* opt_onResolved */, |
| function(reason) { |
| result.setError(reason); |
| }); |
| result.wait(function(r) { |
| err = r.getError(); |
| }); |
| assertUndefined(err); |
| mockClock.tick(); |
| assertEquals('oops', err.message); |
| } |
| |
| function testPromiseFromCanceledResult() { |
| var reason; |
| result.cancel(); |
| result.then( |
| undefined /* opt_onResolved */, |
| function(r) { |
| reason = r; |
| }); |
| mockClock.tick(); |
| assertTrue(reason instanceof goog.Promise.CancellationError); |
| } |
| |
| function testThenableInterface() { |
| assertTrue(goog.Thenable.isImplementedBy(result)); |
| } |
| |
| </script> |
| </body> |
| </html> |