<commit_before>// LICENSE : MIT
"use strict";
import * as assert from "assert";
import sinon = require("sinon");
import { SyncNoDispatchUseCase } from "./use-case/SyncNoDispatchUseCase";
import { Dispatcher, Payload, UseCase } from "../src/";
import { UseCaseExecutorImpl } from "../src/UseCaseExecutor";
import { CallableUseCase } from "./use-case/CallableUseCase";
import { ThrowUseCase } from "./use-case/ThrowUseCase";
import { isWillExecutedPayload } from "../src/payload/WillExecutedPayload";
import { isDidExecutedPayload } from "../src/payload/DidExecutedPayload";
import { isCompletedPayload } from "../src/payload/CompletedPayload";
import { isErrorPayload } from "../src/payload/ErrorPayload";

const shouldNotCalled = () => {
    throw new Error("This should not be called");
};

describe("UseCaseExecutor", function() {
    describe("#executor", () => {
        let consoleErrorStub: any = null;
        beforeEach(() => {
            consoleErrorStub = sinon.stub(console, "error");
        });
        afterEach(() => {
            consoleErrorStub.restore();
        });
        it("should catch sync throwing error in UseCase", () => {
            const dispatcher = new Dispatcher();
            const executor = new UseCaseExecutorImpl({
                useCase: new ThrowUseCase(),
                dispatcher,
                parent: null
            });
            return executor.executor(useCase => useCase.execute()).then(
                () => {
                    throw new Error("SHOULD NOT CALLED");
                },
                error => {
                    assert(error instanceof Error, "should be caught error");
                }
            );
        });
        it("should throw error when pass non-executor function and output console.error", () => {
            const dispatcher = new Dispatcher();
            const executor = new UseCaseExecutorImpl({
                useCase: new SyncNoDispatchUseCase(),
                dispatcher,
                parent: null
            });
            return executor.executor(" THIS IS WRONG " as any).then(
                () => {
                    throw new Error("SHOULD NOT CALLED");
                },
                error => {
                    assert.ok(consoleErrorStub.called, "should be called console.error");
                    const warningMessage = consoleErrorStub.getCalls()[0].args[0];
                    assert.ok(/executor.*? arguments should be function/.test(error.message));
                    assert.equal(
                        warningMessage,
                        "Warning(UseCase): executor argument should be function. But this argument is not function: "
                    );
                }
            );
        });
        it("should accept executor(useCase => {}) function arguments", () => {
            const dispatcher = new Dispatcher();
            const callableUseCase = new CallableUseCase();
            const executor = new UseCaseExecutorImpl({
                useCase: callableUseCase,
                dispatcher,
                parent: null
            });
            return executor.executor(useCase => useCase.execute()).then(
                () => {
                    assert(callableUseCase.isExecuted, "UseCase#execute should be called");
                },
                error => {
                    throw new error();
                }
            );
        });
        it("executor(useCase => {}) useCase is actual wrapper object", () => {
            const dispatcher = new Dispatcher();
            const executor = new UseCaseExecutorImpl({
                useCase: new SyncNoDispatchUseCase(),
                dispatcher,
                parent: null
            });
            return executor.executor(useCase => {
                assert(useCase instanceof UseCase === false, "useCase is wrapped object. it is not UseCase");
                assert(typeof useCase.execute === "function", "UseCase#execute is callable");
                return useCase.execute();
            });
        });
        it("can call useCase.execute() by async", done => {
            const dispatcher = new Dispatcher();
            const callableUseCase = new CallableUseCase();
            const executor = new UseCaseExecutorImpl({
                useCase: callableUseCase,
                dispatcher,
                parent: null
            });
            executor
                .executor(useCase => {
                    Promise.resolve().then(() => {
                        useCase.execute();
                    });
                })
                .then(() => {
                    assert(callableUseCase.isExecuted, "UseCase#execute is called");
                    done();
                });
            // sync check
            assert(callableUseCase.isExecuted === false, "UseCase#execute is not called yet.");
        });
        it("should show warning when UseCase#execute twice", () => {
            const dispatcher = new Dispatcher();
            const executor = new UseCaseExecutorImpl({
                useCase: new SyncNoDispatchUseCase(),
                dispatcher,
                parent: null
            });
            return executor
                .executor(useCase => {
                    useCase.execute();
                    useCase.execute();
                })
                .then(() => {
                    assert.ok(consoleErrorStub.called, "should be called console.error");
                    const warningMessage = consoleErrorStub.getCalls()[0].args[0];
                    assert.ok(/Warning\(UseCase\)/i.test(warningMessage), warningMessage);
                });
        });
    });
    describe("when UseCase throw error", function() {
        // Test: https://github.com/almin/almin/issues/310#issuecomment-359249751
        it("dispatch will -> error -> did -> complete", function() {
            const callStack: string[] = [];
            const expectedCallStack = ["will", "error", "did", "complete"];
            const dispatcher = new Dispatcher();
            const executor = new UseCaseExecutorImpl({
                useCase: new ThrowUseCase(),
                dispatcher,
                parent: null
            });
            // then
            executor.onDispatch(payload => {
                if (isWillExecutedPayload(payload)) {
                    callStack.push("will");
                } else if (isDidExecutedPayload(payload)) {
                    callStack.push("did");
                } else if (isCompletedPayload(payload)) {
                    callStack.push("complete");
                } else if (isErrorPayload(payload)) {
                    callStack.push("error");
                }
            });
            // when
            return executor.execute().catch(() => {
                assert.deepStrictEqual(callStack, expectedCallStack);
            });
        });
    });
    describe("when UseCase is successful completion", function() {
        it("dispatch will -> did", function() {
            // given
            const expectedPayload = {
                type: "SyncUseCase",
                value: "value"
            };<commit_msg>chore(almin): use deepEqual for browser<commit_after>// LICENSE : MIT
"use strict";
import * as assert from "assert";
import sinon = require("sinon");
import { SyncNoDispatchUseCase } from "./use-case/SyncNoDispatchUseCase";
import { Dispatcher, Payload, UseCase } from "../src/";
import { UseCaseExecutorImpl } from "../src/UseCaseExecutor";
import { CallableUseCase } from "./use-case/CallableUseCase";
import { ThrowUseCase } from "./use-case/ThrowUseCase";
import { isWillExecutedPayload } from "../src/payload/WillExecutedPayload";
import { isDidExecutedPayload } from "../src/payload/DidExecutedPayload";
import { isCompletedPayload } from "../src/payload/CompletedPayload";
import { isErrorPayload } from "../src/payload/ErrorPayload";

const shouldNotCalled = () => {
    throw new Error("This should not be called");
};

describe("UseCaseExecutor", function() {
    describe("#executor", () => {
        let consoleErrorStub: any = null;
        beforeEach(() => {
            consoleErrorStub = sinon.stub(console, "error");
        });
        afterEach(() => {
            consoleErrorStub.restore();
        });
        it("should catch sync throwing error in UseCase", () => {
            const dispatcher = new Dispatcher();
            const executor = new UseCaseExecutorImpl({
                useCase: new ThrowUseCase(),
                dispatcher,
                parent: null
            });
            return executor.executor(useCase => useCase.execute()).then(
                () => {
                    throw new Error("SHOULD NOT CALLED");
                },
                error => {
                    assert(error instanceof Error, "should be caught error");
                }
            );
        });
        it("should throw error when pass non-executor function and output console.error", () => {
            const dispatcher = new Dispatcher();
            const executor = new UseCaseExecutorImpl({
                useCase: new SyncNoDispatchUseCase(),
                dispatcher,
                parent: null
            });
            return executor.executor(" THIS IS WRONG " as any).then(
                () => {
                    throw new Error("SHOULD NOT CALLED");
                },
                error => {
                    assert.ok(consoleErrorStub.called, "should be called console.error");
                    const warningMessage = consoleErrorStub.getCalls()[0].args[0];
                    assert.ok(/executor.*? arguments should be function/.test(error.message));
                    assert.equal(
                        warningMessage,
                        "Warning(UseCase): executor argument should be function. But this argument is not function: "
                    );
                }
            );
        });
        it("should accept executor(useCase => {}) function arguments", () => {
            const dispatcher = new Dispatcher();
            const callableUseCase = new CallableUseCase();
            const executor = new UseCaseExecutorImpl({
                useCase: callableUseCase,
                dispatcher,
                parent: null
            });
            return executor.executor(useCase => useCase.execute()).then(
                () => {
                    assert(callableUseCase.isExecuted, "UseCase#execute should be called");
                },
                error => {
                    throw new error();
                }
            );
        });
        it("executor(useCase => {}) useCase is actual wrapper object", () => {
            const dispatcher = new Dispatcher();
            const executor = new UseCaseExecutorImpl({
                useCase: new SyncNoDispatchUseCase(),
                dispatcher,
                parent: null
            });
            return executor.executor(useCase => {
                assert(useCase instanceof UseCase === false, "useCase is wrapped object. it is not UseCase");
                assert(typeof useCase.execute === "function", "UseCase#execute is callable");
                return useCase.execute();
            });
        });
        it("can call useCase.execute() by async", done => {
            const dispatcher = new Dispatcher();
            const callableUseCase = new CallableUseCase();
            const executor = new UseCaseExecutorImpl({
                useCase: callableUseCase,
                dispatcher,
                parent: null
            });
            executor
                .executor(useCase => {
                    Promise.resolve().then(() => {
                        useCase.execute();
                    });
                })
                .then(() => {
                    assert(callableUseCase.isExecuted, "UseCase#execute is called");
                    done();
                });
            // sync check
            assert(callableUseCase.isExecuted === false, "UseCase#execute is not called yet.");
        });
        it("should show warning when UseCase#execute twice", () => {
            const dispatcher = new Dispatcher();
            const executor = new UseCaseExecutorImpl({
                useCase: new SyncNoDispatchUseCase(),
                dispatcher,
                parent: null
            });
            return executor
                .executor(useCase => {
                    useCase.execute();
                    useCase.execute();
                })
                .then(() => {
                    assert.ok(consoleErrorStub.called, "should be called console.error");
                    const warningMessage = consoleErrorStub.getCalls()[0].args[0];
                    assert.ok(/Warning\(UseCase\)/i.test(warningMessage), warningMessage);
                });
        });
    });
    describe("when UseCase throw error", function() {
        // Test: https://github.com/almin/almin/issues/310#issuecomment-359249751
        it("dispatch will -> error -> did -> complete", function() {
            const callStack: string[] = [];
            const expectedCallStack = ["will", "error", "did", "complete"];
            const dispatcher = new Dispatcher();
            const executor = new UseCaseExecutorImpl({
                useCase: new ThrowUseCase(),
                dispatcher,
                parent: null
            });
            // then
            executor.onDispatch(payload => {
                if (isWillExecutedPayload(payload)) {
                    callStack.push("will");
                } else if (isDidExecutedPayload(payload)) {
                    callStack.push("did");
                } else if (isCompletedPayload(payload)) {
                    callStack.push("complete");
                } else if (isErrorPayload(payload)) {
                    callStack.push("error");
                }
            });
            // when
            return executor.execute().catch(() => {
                assert.deepEqual(callStack, expectedCallStack);
            });
        });
    });
    describe("when UseCase is successful completion", function() {
        it("dispatch will -> did", function() {
            // given
            const expectedPayload = {
                type: "SyncUseCase",
                value: "value"
            };
{'fraction_non_alphanumeric': 0.1158866824052215, 'fraction_numerical': 0.0022219136231079015, 'mean_word_length': 1.5352930822038373, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 67, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4031835', 'n_tokens_mistral': 3479, 'n_tokens_neox': 3296, 'n_words': 810}