import * as assert from 'power-assert'
import tcb from '../../../src/index'
import * as Config from '../../config.local'
import * as common from '../../common/index'

const app = tcb.init(Config)
const db = app.database()

describe('test/unit/collection.test.ts', () => {
    const collName = 'coll-1'
    const collection = db.collection(collName)
    const command = db.command
    const _ = command

    it('operator', async () => {
        let a
        a = _.gt(4)
        const result = await collection.where({ a }).update({ c: { d: _.mul(3) } })
    })
})

describe('stdDevPop', async () => {
    let studentsCollection = null
    const collectionName = 'test-students'
    const data = [
        { group: 'a', score: 84 },
        { group: 'a', score: 96 },
        { group: 'b', score: 80 },
        { group: 'b', score: 100 }
    ]

    beforeAll(async () => {
        studentsCollection = await common.safeCollection(db, collectionName)
        const success = await studentsCollection.create(data)
        assert.strictEqual(success, true)
    })

    afterAll(async () => {
        const success = await studentsCollection.remove()
        assert.strictEqual(success, true)
    })

    it('计算不同组的标准差', async () => {
        const $ = db.command.aggregate
        const result = await db
            .collection(collectionName)
            .aggregate()
            .group({
                _id: '$group',
                stdDev: $.stdDevPop('$score')
            })
            .end()
        const stdDevs = {
            a: null,
            b: null
        }
        result.data.forEach(item => (stdDevs[item._id] = item.stdDev))
        // a分组标准差为: 6; b分组标准差为: 10
        assert.strictEqual(stdDevs.a, 6)
        assert.strictEqual(stdDevs.b, 10)
    })
})

describe('stdDevSamp', async () => {
    let studentsCollection = null
    const collectionName = 'test-students'
    const data = [{ score: 80 }, { score: 100 }]

    beforeAll(async () => {
        studentsCollection = await common.safeCollection(db, collectionName)
        const success = await studentsCollection.create(data)
        assert.strictEqual(success, true)
    })

    afterAll(async () => {
        const success = await studentsCollection.remove()
        assert.strictEqual(success, true)
    })

    it('计算标准样本偏差', async () => {
        const $ = db.command.aggregate
        const result = await db
            .collection(collectionName)
            .aggregate()
            .group({
                _id: null,
                ageStdDev: $.stdDevSamp('$score')
            })
            .end()
        // data 的标准样本偏差为 14.14
        assert.strictEqual(result.data[0].ageStdDev.toFixed(2), '14.14')
    })
})

describe('sum', async () => {
    let goodsCollection = null
    const $ = db.command.aggregate
    const collectionName = 'test-goods'
    const data = [
        { cost: -10, price: 100 },
        { cost: -15, price: 1 },
        { cost: -10, price: 10 }
    ]

    beforeAll(async () => {
        goodsCollection = await common.safeCollection(db, collectionName)
        const success = await goodsCollection.create(data)
        assert.strictEqual(success, true)
    })

    afterAll(async () => {
        const success = await goodsCollection.remove()
        assert.strictEqual(success, true)
    })

    it('参数为单独字段', async () => {
        const result = await db
            .collection(collectionName)
            .aggregate()
            .group({
                _id: null,
                totalPrice: $.sum('$price')
            })
            .end()
        assert.strictEqual(result.data[0].totalPrice, 111)
    })

    it('参数为字段列表', async () => {
        const result = await db
            .collection(collectionName)
            .aggregate()
            .group({
                _id: null,
                totalProfit: $.sum($.sum(['$price', '$cost']))
            })
            .end()
        assert.strictEqual(result.data[0].totalProfit, 76)
    })
})

describe('let', async () => {
    let goodsCollection = null
    const $ = db.command.aggregate
    const collectionName = 'test-goods'
    const data = [
        { cost: -10, discount: 0.95, price: 100 },
        { cost: -15, discount: 0.98, price: 1 },
        { cost: -10, discount: 1, price: 10 }
    ]

    beforeAll(async () => {
        goodsCollection = await common.safeCollection(db, collectionName)
        const success = await goodsCollection.create(data)
        assert.strictEqual(success, true)
    })

    afterAll(async () => {
        const success = await goodsCollection.remove()
        assert.strictEqual(success, true)
    })

    it('参数为单独字段', async () => {
        const result = await db
            .collection(collectionName)
            .aggregate()
            .project({
                profit: $.let({
                    vars: {
                        priceTotal: $.multiply(['$price', '$discount'])
                    },
                    in: $.sum(['$$priceTotal', '$cost'])
                })
            })
            .end()
        assert.strictEqual(result.data.length, 3)
    })
})

describe('条件操作符', async () => {
    let goodsCollection = null
    const $ = db.command.aggregate
    const collectionName = 'test-goods'
    const data = [
        { name: 'a', amount: 100, desc: 'A' },
        { name: 'b', amount: 200, desc: null },
        { name: 'c', amount: 300 }
    ]

    beforeAll(async () => {
        goodsCollection = await common.safeCollection(db, collectionName)
        const success = await goodsCollection.create(data)
        assert.strictEqual(success, true)
    })

    afterAll(async () => {
        const success = await goodsCollection.remove()
        assert.strictEqual(success, true)
    })

    it('cond', async () => {
        const $ = db.command.aggregate
        const result = await db
            .collection(collectionName)
            .aggregate()
            .project({
                _id: 0,
                name: 1,
                discount: $.cond({
                    if: $.gte(['$amount', 200]),
                    then: 0.7,
                    else: 0.9
                })
            })
            .end()
        assert.deepStrictEqual(result.data, [
            { name: 'a', discount: 0.9 },
            { name: 'b', discount: 0.7 },
            { name: 'c', discount: 0.7 }
        ])
    })

    it('ifNull', async () => {
        const $ = db.command.aggregate
        const result = await db
            .collection(collectionName)
            .aggregate()
            .project({
                _id: 0,
                name: 1,
                desc: $.ifNull(['$desc', 'Not defined'])
            })
            .end()
        assert.deepStrictEqual(result.data, [
            { desc: 'A', name: 'a' },
            { desc: 'Not defined', name: 'b' },
            { desc: 'Not defined', name: 'c' }
        ])
    })

    it('switch', async () => {
        const $ = db.command.aggregate
        const result = await db
            .collection(collectionName)
            .aggregate()
            .project({
                _id: 0,
                name: 1,
                discount: $.switch({
                    branches: [
                        { case: $.gt(['$amount', 250]), then: 0.8 },
                        { case: $.gt(['$amount', 150]), then: 0.9 }
                    ],
                    default: 1
                })
            })
            .end()
        assert.deepStrictEqual(result.data, [
            { name: 'a', discount: 1 },
            { name: 'b', discount: 0.9 },
            { name: 'c', discount: 0.8 }
        ])
    })
})

describe('group操作符', async () => {
    let studentsCollection = null,
        passagesCollection = null
    const $ = db.command.aggregate

    const studentsName = 'test-students'
    const studentsData = [
        { group: 'a', name: 'stu1', score: 84 },
        { group: 'a', name: 'stu2', score: 96 },
        { group: 'b', name: 'stu3', score: 80 },
        { group: 'b', name: 'stu4', score: 100 }
    ]
    const passagesName = 'test-passages'
    const passagesData = [
        { category: 'web', tags: ['JavaScript', 'CSS'], title: 'title1' },
        { category: 'System', tags: ['C++', 'C'], title: 'title2' }
    ]

    beforeAll(async () => {
        studentsCollection = await common.safeCollection(db, studentsName)
        passagesCollection = await common.safeCollection(db, passagesName)
        assert.strictEqual(await studentsCollection.create(studentsData), true)
        assert.strictEqual(await passagesCollection.create(passagesData), true)
    })

    afterAll(async () => {
        assert.strictEqual(await studentsCollection.remove(), true)
        assert.strictEqual(await passagesCollection.remove(), true)
    })

    it('push', async () => {
        const result = await db
            .collection(studentsName)
            .aggregate()
            .group({
                _id: '$group',
                students: $.push({
                    name: '$name',
                    score: '$score'
                })
            })
            .end()
        const valid = result.data.every(item => 'students' in item)
        assert.strictEqual(valid, true)
    })

    it('max', async () => {
        const result = await db
            .collection(studentsName)
            .aggregate()
            .group({
                _id: '$group',
                maxScore: $.max('$score')
            })
            .end()

        assert.strictEqual(result.data.length, 2)
    })

    it('min', async () => {
        const result = await db
            .collection(studentsName)
            .aggregate()
            .group({
                _id: '$group',
                minScore: $.min('$score')
            })
            .end()

        assert.strictEqual(result.data.length, 2)
    })

    it('last', async () => {
        const result = await db
            .collection(studentsName)
            .aggregate()
            .sort({
                score: 1
            })
            .group({
                _id: null,
                max: $.last('$score')
            })
            .end()

        assert(result.data[0].max, 100)
    })

    it('first', async () => {
        const result = await db
            .collection(studentsName)
            .aggregate()
            .sort({
                score: 1
            })
            .group({
                _id: null,
                min: $.first('$score')
            })
            .end()

        assert(result.data[0].min, 80)
    })

    it('avg', async () => {
        const result = await db
            .collection(studentsName)
            .aggregate()
            .group({
                _id: null,
                average: $.avg('$score')
            })
            .end()

        assert(result.data[0].average, 90)
    })

    describe('addToSet', async () => {
        it('非数组字段', async () => {
            const result = await db
                .collection(passagesName)
                .aggregate()
                .group({
                    _id: null,
                    categories: $.addToSet('$category')
                })
                .end()

            assert(result.data[0].categories.length, 2)
        })

        it('数组字段', async () => {
            const result = await db
                .collection(passagesName)
                .aggregate()
                .group({
                    _id: null,
                    tagsList: $.addToSet('$tags')
                })
                .end()
            const valid = result.data.some(item => Array.isArray(item.tagsList))
            assert(valid, true)
        })
    })
})

describe('字面量操作符', async () => {
    let goodsCollection = null
    const $ = db.command.aggregate
    const collectionName = 'test-goods'
    const data = [{ price: '$1' }, { price: '$2.50' }, { price: '$3.60' }, { price: '$4.60' }]

    beforeAll(async () => {
        goodsCollection = await common.safeCollection(db, collectionName)
        const success = await goodsCollection.create(data)
        assert.strictEqual(success, true)
    })

    afterAll(async () => {
        const success = await goodsCollection.remove()
        assert.strictEqual(success, true)
    })

    it('以字面量的形式使用$', async () => {
        const $ = db.command.aggregate
        const result = await db
            .collection(collectionName)
            .aggregate()
            .project({
                _id: 0,
                isOneDollar: $.eq(['$price', $.literal('$1')])
            })
            .end()
        assert.deepStrictEqual(result.data, [
            { isOneDollar: true },
            { isOneDollar: false },
            { isOneDollar: false },
            { isOneDollar: false }
        ])
    })

    it('投影一个字段，对应的值为1', async () => {
        const $ = db.command.aggregate
        const result = await db
            .collection(collectionName)
            .aggregate()
            .project({
                _id: 0,
                price: 1,
                amount: $.literal(1)
            })
            .end()
        assert.deepStrictEqual(result.data, [
            { amount: 1, price: '$1' },
            { amount: 1, price: '$2.50' },
            { amount: 1, price: '$3.60' },
            { amount: 1, price: '$4.60' }
        ])
    })
})

describe('字符串操作符', async () => {
    let studentsCollection = null,
        personCollection = null
    const $ = db.command.aggregate

    const studentsName = 'test-students'
    const studentsData = [
        {
            birthday: '1999/12/12',
            date: new Date('1999/12/12'),
            firstName: 'Yuanxin',
            group: 'a',
            lastName: 'Dong',
            score: 84
        },
        {
            birthday: '1998/11/11',
            date: new Date('1998/11/11'),
            firstName: 'Weijia',
            group: 'a',
            lastName: 'Wang',
            score: 96
        },
        {
            birthday: '1997/10/10',
            date: new Date('1997/10/10'),
            firstName: 'Chengxi',
            group: 'b',
            lastName: 'Li',
            score: 80
        }
    ]

    const personName = 'test-person'
    const personData = [{ name: 'dongyuanxin', nickname: '心谭' }]

    beforeAll(async () => {
        studentsCollection = await common.safeCollection(db, studentsName)
        personCollection = await common.safeCollection(db, personName)
        assert.strictEqual(await studentsCollection.create(studentsData), true)
        assert.strictEqual(await personCollection.create(personData), true)
    })

    afterAll(async () => {
        assert.strictEqual(await studentsCollection.remove(), true)
        assert.strictEqual(await personCollection.remove(), true)
    })

    it('concat', async () => {
        const result = await db
            .collection(studentsName)
            .aggregate()
            .project({
                _id: 0,
                fullName: $.concat(['$firstName', ' ', '$lastName'])
            })
            .end()
        assert.deepStrictEqual(result.data, [
            { fullName: 'Yuanxin Dong' },
            { fullName: 'Weijia Wang' },
            { fullName: 'Chengxi Li' }
        ])
    })

    describe('dateToString', async () => {
        it('格式化日期', async () => {
            const result = await db
                .collection(studentsName)
                .aggregate()
                .project({
                    _id: 0,
                    formatDate: $.dateToString({
                        date: '$date',
                        format: '%Y-%m-%d'
                    })
                })
                .end()
            assert.deepStrictEqual(result.data, [
                { formatDate: '1999-12-11' },
                { formatDate: '1998-11-10' },
                { formatDate: '1997-10-09' }
            ])
        })

        it('时区时间', async () => {
            const result = await db
                .collection(studentsName)
                .aggregate()
                .project({
                    _id: 0,
                    formatDate: $.dateToString({
                        date: '$date',
                        format: '%H:%M:%S',
                        timezone: 'Asia/Shanghai'
                    })
                })
                .end()
            const valid = result.data.every(item => item.formatDate === '00:00:00')
            assert.ok(valid)
        })

        it('缺失情况的默认值', async () => {
            const result = await db
                .collection(studentsName)
                .aggregate()
                .project({
                    _id: 0,
                    formatDate: $.dateToString({
                        date: '$empty',
                        onNull: 'null'
                    })
                })
                .end()
            const valid = result.data.every(item => item.formatDate === 'null')
            assert.ok(valid)
        })
    })

    it('indexOfBytes', async () => {
        const result = await db
            .collection(studentsName)
            .aggregate()
            .project({
                _id: 0,
                aStrIndex: $.indexOfBytes(['$firstName', 'a'])
            })
            .end()
        assert.deepStrictEqual(result.data, [{ aStrIndex: 2 }, { aStrIndex: 5 }, { aStrIndex: -1 }])
    })

    it('indexOfCP', async () => {
        const result = await db
            .collection(studentsName)
            .aggregate()
            .project({
                _id: 0,
                aStrIndex: $.indexOfCP(['$firstName', 'a'])
            })
            .end()
        assert.deepStrictEqual(result.data, [{ aStrIndex: 2 }, { aStrIndex: 5 }, { aStrIndex: -1 }])
    })

    it('split', async () => {
        const result = await db
            .collection(studentsName)
            .aggregate()
            .project({
                _id: 0,
                birthday: $.split(['$birthday', '/'])
            })
            .end()
        assert.deepStrictEqual(result.data, [
            { birthday: ['1999', '12', '12'] },
            { birthday: ['1998', '11', '11'] },
            { birthday: ['1997', '10', '10'] }
        ])
    })

    it('strcasecmp', async () => {
        const result = await db
            .collection(studentsName)
            .aggregate()
            .project({
                _id: 0,
                result: $.strcasecmp(['$firstName', '$lastName'])
            })
            .end()
        assert.deepStrictEqual(result.data, [{ result: 1 }, { result: 1 }, { result: -1 }])
    })

    it.skip('strLenBytes', async () => {
        const result = await db
            .collection(personName)
            .aggregate()
            .project({
                _id: 0,
                nameLength: $.strLenBytes('$name'),
                nicknameLength: $.strLenBytes('$nickname')
            })
            .end()
        assert.deepStrictEqual(result.data, [{ nameLength: 11, nicknameLength: 6 }])
    })

    it.skip('strLenCP', async () => {
        const result = await db
            .collection(personName)
            .aggregate()
            .project({
                _id: 0,
                nameLength: $.strLenCP('$name'),
                nicknameLength: $.strLenCP('$nickname')
            })
            .end()
        assert.deepStrictEqual(result.data, [{ nameLength: 11, nicknameLength: 2 }])
    })

    it('substr', async () => {
        const result = await db
            .collection(studentsName)
            .aggregate()
            .project({
                _id: 0,
                year: $.substr(['$birthday', 0, 4]),
                month: $.substr(['$birthday', 5, 2]),
                day: $.substr(['$birthday', 8, -1])
            })
            .end()
        assert.deepStrictEqual(result.data, [
            { day: '12', month: '12', year: '1999' },
            { day: '11', month: '11', year: '1998' },
            { day: '10', month: '10', year: '1997' }
        ])
    })

    it('substrBytes', async () => {
        const result = await db
            .collection(studentsName)
            .aggregate()
            .project({
                _id: 0,
                year: $.substrBytes(['$birthday', 0, 4]),
                month: $.substrBytes(['$birthday', 5, 2]),
                day: $.substrBytes(['$birthday', 8, -1])
            })
            .end()
        assert.deepStrictEqual(result.data, [
            { day: '12', month: '12', year: '1999' },
            { day: '11', month: '11', year: '1998' },
            { day: '10', month: '10', year: '1997' }
        ])
    })

    test.skip('substrCP', async () => {
        const result = await db
            .collection(personName)
            .aggregate()
            .project({
                _id: 0,
                firstCh: $.substrCP(['$nickname', 0, 1])
            })
            .end()
        assert.deepStrictEqual(result.data, [{ firstCh: '心' }])
    })

    test('toLower', async () => {
        const result = await db
            .collection(studentsName)
            .aggregate()
            .project({
                _id: 0,
                result: $.toLower('$firstName')
            })
            .end()

        assert.deepStrictEqual(result.data, [
            { result: 'yuanxin' },
            { result: 'weijia' },
            { result: 'chengxi' }
        ])
    })

    test('toUpper', async () => {
        const result = await db
            .collection(studentsName)
            .aggregate()
            .project({
                _id: 0,
                result: $.toUpper('$lastName')
            })
            .end()
        assert.deepStrictEqual(result.data, [
            { result: 'DONG' },
            { result: 'WANG' },
            { result: 'LI' }
        ])
    })
})

describe('mergeObjects', async () => {
    let goodsCollection = null
    const $ = db.command.aggregate
    const collectionName = 'test-goods'
    const data = [
        { name: 'A', foo: { a: 1 }, bar: { b: 2 } },
        { name: 'A', foo: { c: 1 }, bar: { d: 2 } },
        { name: 'A', foo: { e: 1 }, bar: { f: 2 } }
    ]

    beforeAll(async () => {
        goodsCollection = await common.safeCollection(db, collectionName)
        const success = await goodsCollection.create(data)
        assert.strictEqual(success, true)
    })

    afterAll(async () => {
        const success = await goodsCollection.remove()
        assert.strictEqual(success, true)
    })

    it('在group中使用', async () => {
        const $ = db.command.aggregate
        const result = await db
            .collection(collectionName)
            .aggregate()
            .group({
                _id: '$name',
                mergedFoo: $.mergeObjects('$foo'),
                mergeBar: $.mergeObjects('$bar')
            })
            .end()
        assert.deepStrictEqual(result.data, [
            {
                _id: 'A',
                mergedFoo: { a: 1, c: 1, e: 1 },
                mergeBar: { b: 2, d: 2, f: 2 }
            }
        ])
    })

    it('在group以外使用', async () => {
        const $ = db.command.aggregate
        const result = await db
            .collection(collectionName)
            .aggregate()
            .project({
                _id: 0,
                foobar: $.mergeObjects(['$foo', '$bar'])
            })
            .end()
        assert.deepStrictEqual(result.data, [
            { foobar: { a: 1, b: 2 } },
            { foobar: { c: 1, d: 2 } },
            { foobar: { e: 1, f: 2 } }
        ])
    })
})

describe('集合操作', async () => {
    let goodsCollection = null
    const $ = db.command.aggregate
    const collectionName = 'test-goods'
    const data = [
        { arr: [true] },
        { arr: [] },
        { arr: [true, false] },
        { arr: [1] },
        { arr: [1, 0] },
        { arr: ['stark'] }
    ]

    beforeAll(async () => {
        goodsCollection = await common.safeCollection(db, collectionName)
        const success = await goodsCollection.create(data)
        assert.strictEqual(success, true)
    })

    afterAll(async () => {
        const success = await goodsCollection.remove()
        assert.strictEqual(success, true)
    })

    it('allElementsTrue', async () => {
        const $ = db.command.aggregate
        const result = await db
            .collection(collectionName)
            .aggregate()
            .project({
                _id: 0,
                allElementsTrue: $.allElementsTrue(['$arr'])
            })
            .end()
        assert.deepStrictEqual(result.data, [
            { allElementsTrue: true },
            { allElementsTrue: true },
            { allElementsTrue: false },
            { allElementsTrue: true },
            { allElementsTrue: false },
            { allElementsTrue: true }
        ])
    })

    it('anyElementTrue', async () => {
        const $ = db.command.aggregate
        const result = await db
            .collection(collectionName)
            .aggregate()
            .project({
                _id: 0,
                anyElementTrue: $.anyElementTrue(['$arr'])
            })
            .end()
        assert.deepStrictEqual(result.data, [
            { anyElementTrue: true },
            { anyElementTrue: false },
            { anyElementTrue: true },
            { anyElementTrue: true },
            { anyElementTrue: true },
            { anyElementTrue: true }
        ])
    })
})

describe('集合操作2', async () => {
    let goodsCollection = null
    const $ = db.command.aggregate
    const collectionName = 'test-goods'
    const data = [
        { A: [1, 2], B: [1, 2] },
        { A: [1, 2], B: [2, 1, 2] },
        { A: [1, 2], B: [1, 2, 3] },
        { A: [1, 2], B: [3, 1] },
        { A: [1, 2], B: [] },
        { A: [1, 2], B: [{}, []] },
        { A: [], B: [] },
        { A: [], B: [1] }
    ]

    beforeAll(async () => {
        goodsCollection = await common.safeCollection(db, collectionName)
        const success = await goodsCollection.create(data)
        assert.strictEqual(success, true)
    })

    afterAll(async () => {
        const success = await goodsCollection.remove()
        assert.strictEqual(success, true)
    })

    it('setDifference', async () => {
        const result = await db
            .collection(collectionName)
            .aggregate()
            .project({
                _id: 0,
                isBOnly: $.setDifference(['$B', '$A'])
            })
            .end()
        assert.deepStrictEqual(result.data, [
            { isBOnly: [] },
            { isBOnly: [] },
            { isBOnly: [3] },
            { isBOnly: [3] },
            { isBOnly: [] },
            { isBOnly: [{}, []] },
            { isBOnly: [] },
            { isBOnly: [1] }
        ])
    })

    it('setEquals', async () => {
        const result = await db
            .collection(collectionName)
            .aggregate()
            .project({
                _id: 0,
                sameElements: $.setEquals(['$A', '$B'])
            })
            .end()
        assert.deepStrictEqual(result.data, [
            { sameElements: true },
            { sameElements: true },
            { sameElements: false },
            { sameElements: false },
            { sameElements: false },
            { sameElements: false },
            { sameElements: true },
            { sameElements: false }
        ])
    })

    it('setIntersection', async () => {
        const result = await db
            .collection(collectionName)
            .aggregate()
            .project({
                _id: 0,
                setIntersection: $.setIntersection(['$A', '$B'])
            })
            .end()
        assert.deepStrictEqual(result.data, [
            { setIntersection: [1, 2] },
            { setIntersection: [1, 2] },
            { setIntersection: [1, 2] },
            { setIntersection: [1] },
            { setIntersection: [] },
            { setIntersection: [] },
            { setIntersection: [] },
            { setIntersection: [] }
        ])
    })

    it('setIsSubset', async () => {
        const result = await db
            .collection(collectionName)
            .aggregate()
            .project({
                _id: 0,
                setIsSubset: $.setIsSubset(['$A', '$B'])
            })
            .end()
        assert.deepStrictEqual(result.data, [
            { setIsSubset: true },
            { setIsSubset: true },
            { setIsSubset: true },
            { setIsSubset: false },
            { setIsSubset: false },
            { setIsSubset: false },
            { setIsSubset: true },
            { setIsSubset: true }
        ])
    })

    it('setUnion', async () => {
        const result = await db
            .collection(collectionName)
            .aggregate()
            .project({
                _id: 0,
                setUnion: $.setUnion(['$A', '$B'])
            })
            .end()
        assert.deepStrictEqual(result.data, [
            { setUnion: [1, 2] },
            { setUnion: [1, 2] },
            { setUnion: [1, 2, 3] },
            { setUnion: [1, 2, 3] },
            { setUnion: [1, 2] },
            { setUnion: [1, 2, {}, []] },
            { setUnion: [] },
            { setUnion: [1] }
        ])
    })
})
