local promise = require('promise')
local dummy   = {dummy = 'dummy'}

describe('2.2.1: Both `onFulfilled` and `onRejected` are optional arguments.', function()
    describe('2.2.1.1: If `onFulfilled` is not a function, it must be ignored.', function()
        describe('applied to a directly-rejected promise', function()
            local function testNonFunction(nonFunction, stringRepresentation)
                it('`onFulfilled` is ' .. stringRepresentation, function()
                    promise.reject(dummy)
                        :thenCall(nonFunction, function()
                            done()
                        end)
                    assert.True(wait())
                end)
            end

            testNonFunction(nil, '`nil`')
            testNonFunction(false, '`false`')
            testNonFunction(5, '`5`')
            testNonFunction({}, '`a table`')
        end)

        describe('applied to a promise rejected and then chained off of', function()
            local function testNonFunction(nonFunction, stringRepresentation)
                it('`onFulfilled` is ' .. stringRepresentation, function()
                    promise.reject(dummy)
                        :thenCall(function() end, nil)
                        :thenCall(nonFunction, function()
                            done()
                        end)
                    assert.True(wait())
                end)
            end

            testNonFunction(nil, '`nil`')
            testNonFunction(false, '`false`')
            testNonFunction(5, '`5`')
            testNonFunction({}, '`a table`')
        end)
    end)

    describe('2.2.1.2: If `onRejected` is not a function, it must be ignored.', function()
        describe('applied to a directly-fulfilled promise', function()
            local function testNonFunction(nonFunction, stringRepresentation)
                it('`onRejected` is ' .. stringRepresentation, function()
                    promise.resolve(dummy)
                        :thenCall(function()
                            done()
                        end, nonFunction)
                    assert.True(wait())
                end)
            end

            testNonFunction(nil, '`nil`')
            testNonFunction(false, '`false`')
            testNonFunction(5, '`5`')
            testNonFunction({}, '`a table`')
        end)

        describe('applied to a promise fulfilled and then chained off of', function()
            local function testNonFunction(nonFunction, stringRepresentation)
                it('`onRejected` is ' .. stringRepresentation, function()
                    promise.resolve(dummy)
                        :thenCall(nil, function() end)
                        :thenCall(function()
                            done()
                        end, nonFunction)
                    assert.True(wait())
                end)
            end

            testNonFunction(nil, '`nil`')
            testNonFunction(false, '`false`')
            testNonFunction(5, '`5`')
            testNonFunction({}, '`a table`')
        end)
    end)
end)
