// Copyright 2012 The Closure Library Authors. All Rights Reserved.
// Use of this source code is governed by the Apache License, Version 2.0.
goog.module('goog.result.chainTest');
goog.setTestOnly();
const MockClock = goog.require('goog.testing.MockClock');
const Timer = goog.require('goog.Timer');
const googResult = goog.require('goog.result');
const testSuite = goog.require('goog.testing.testSuite');
const testingRecordFunction = goog.require('goog.testing.recordFunction');
let actionCallback;
let counter;
let dependentResult;
let givenResult;
let mockClock;
// SYNCHRONOUS TESTS:
// ASYNCHRONOUS TESTS:
// HELPER FUNCTIONS:
// Assert that the recordFunction was called once with an argument of
// 'result' (the second argument) which has a state of SUCCESS and
// a value of 'value' (the third argument).
function assertSuccess(recordFunction, result, value) {
assertEquals(1, recordFunction.getCallCount());
const res = recordFunction.popLastCall().getArgument(0);
assertEquals(result, res);
assertEquals(googResult.Result.State.SUCCESS, res.getState());
assertEquals(value, res.getValue());
}
// Assert that the recordFunction was called once with an argument of
// 'result' (the second argument) which has a state of ERROR.
function assertError(recordFunction, result, value) {
assertEquals(1, recordFunction.getCallCount());
const res = recordFunction.popLastCall().getArgument(0);
assertEquals(result, res);
assertEquals(googResult.Result.State.ERROR, res.getState());
assertEquals(value, res.getError());
}
// Assert that the recordFunction wasn't called
function assertNoCall(recordFunction) {
assertEquals(0, recordFunction.getCallCount());
}
testSuite({
setUpPage() {
mockClock = new MockClock();
mockClock.install();
},
setUp() {
mockClock.reset();
givenResult = new googResult.SimpleResult();
dependentResult = new googResult.SimpleResult();
counter = new testingRecordFunction();
actionCallback = testingRecordFunction((result) => dependentResult);
},
tearDown() {
givenResult = dependentResult = counter = null;
},
tearDownPage() {
mockClock.uninstall();
},
testChainWhenBothResultsSuccess() {
const finalResult = googResult.chain(givenResult, actionCallback);
googResult.wait(finalResult, counter);
givenResult.setValue(1);
dependentResult.setValue(2);
assertSuccess(actionCallback, givenResult, 1);
assertSuccess(counter, finalResult, 2);
},
testChainWhenFirstResultError() {
const finalResult = googResult.chain(givenResult, actionCallback);
googResult.wait(finalResult, counter);
givenResult.setError(4);
assertNoCall(actionCallback);
assertError(counter, finalResult, 4);
},
testChainWhenSecondResultError() {
const finalResult = googResult.chain(givenResult, actionCallback);
googResult.wait(finalResult, counter);
givenResult.setValue(1);
dependentResult.setError(5);
assertSuccess(actionCallback, givenResult, 1);
assertError(counter, finalResult, 5);
},
testChainCancelFirstResult() {
const finalResult = googResult.chain(givenResult, actionCallback);
googResult.wait(finalResult, counter);
googResult.cancelParentResults(finalResult);
assertNoCall(actionCallback);
assertTrue(givenResult.isCanceled());
assertTrue(finalResult.isCanceled());
},
testChainCancelSecondResult() {
const finalResult = googResult.chain(givenResult, actionCallback);
googResult.wait(finalResult, counter);
givenResult.setValue(1);
googResult.cancelParentResults(finalResult);
assertSuccess(actionCallback, givenResult, 1);
assertTrue(dependentResult.isCanceled());
assertTrue(finalResult.isCanceled());
},
testDoubleChainCancel() {
const intermediateResult = googResult.chain(givenResult, actionCallback);
const finalResult = googResult.chain(intermediateResult, actionCallback);
assertTrue(googResult.cancelParentResults(finalResult));
assertTrue(finalResult.isCanceled());
assertTrue(intermediateResult.isCanceled());
assertFalse(givenResult.isCanceled());
assertFalse(googResult.cancelParentResults(finalResult));
},
testCustomScope() {
const scope = {};
const finalResult = googResult.chain(givenResult, actionCallback, scope);
googResult.wait(finalResult, counter);
givenResult.setValue(1);
dependentResult.setValue(2);
assertEquals(scope, actionCallback.popLastCall().getThis());
},
testChainAsyncWhenBothResultsSuccess() {
const finalResult = googResult.chain(givenResult, actionCallback);
googResult.wait(finalResult, counter);
Timer.callOnce(() => {
givenResult.setValue(1);
});
mockClock.tick();
assertSuccess(actionCallback, givenResult, 1);
Timer.callOnce(() => {
dependentResult.setValue(2);
});
mockClock.tick();
assertSuccess(counter, finalResult, 2);
},
testChainAsyncWhenFirstResultError() {
const finalResult = googResult.chain(givenResult, actionCallback);
googResult.wait(finalResult, counter);
Timer.callOnce(() => {
givenResult.setError(6);
});
mockClock.tick();
assertNoCall(actionCallback);
assertError(counter, finalResult, 6);
},
testChainAsyncWhenSecondResultError() {
const finalResult = googResult.chain(givenResult, actionCallback);
googResult.wait(finalResult, counter);
Timer.callOnce(() => {
givenResult.setValue(1);
});
mockClock.tick();
assertSuccess(actionCallback, givenResult, 1);
Timer.callOnce(() => {
dependentResult.setError(7);
});
mockClock.tick();
assertError(counter, finalResult, 7);
},
testChainAsyncCancelFirstResult() {
const finalResult = googResult.chain(givenResult, actionCallback);
googResult.wait(finalResult, counter);
Timer.callOnce(() => {
googResult.cancelParentResults(finalResult);
});
mockClock.tick();
assertNoCall(actionCallback);
assertTrue(givenResult.isCanceled());
assertTrue(finalResult.isCanceled());
},
testChainAsyncCancelSecondResult() {
const finalResult = googResult.chain(givenResult, actionCallback);
googResult.wait(finalResult, counter);
Timer.callOnce(() => {
givenResult.setValue(1);
});
mockClock.tick();
assertSuccess(actionCallback, givenResult, 1);
Timer.callOnce(() => {
googResult.cancelParentResults(finalResult);
});
mockClock.tick();
assertTrue(dependentResult.isCanceled());
assertTrue(finalResult.isCanceled());
},
});