import {
    uuidgen,
    kebabToProperCase,
    snakeToCamelCase,
    renameKeys,
    matcher
} from 'web-foundation/etc/util';

describe('Utility Functions', function() {
    describe('kebabToProperCase', function() {
        it('should properly transform kebab to proper case', function() {
            const testStr = 'foo-bar';

            expect(kebabToProperCase(testStr)).to.equal('Foo Bar');
        });

        it('should work for some edge cases', function() {
            const testStrA = 'foo-b',
                testStrB = 'f-b',
                testStrC = 'foo';

            expect(kebabToProperCase(testStrA)).to.equal('Foo B');
            expect(kebabToProperCase(testStrB)).to.equal('F B');
            expect(kebabToProperCase(testStrC)).to.equal('Foo');
        });
    });

    describe('snakeToCamelCase', function() {
        it('should properly transform snake_case to camelCase', function() {
            const testStr = 'foo_bar';

            expect(snakeToCamelCase(testStr)).to.equal('fooBar');
        });

        it('should work for some edge cases', function() {
            const testStrA = 'foo_b',
                testStrB = 'f_b',
                testStrC = 'foo';

            expect(snakeToCamelCase(testStrA)).to.equal('fooB');
            expect(snakeToCamelCase(testStrB)).to.equal('fB');
            expect(snakeToCamelCase(testStrC)).to.equal('foo');
        });
    });

    describe('matcher', function() {
        it('should match for me or give me the fallback', function() {
            const find = matcher(
                {
                    dog: 'bark',
                    bird: 'chirp'
                },
                {
                    cat: 'meow'
                },
                null, // not a hash, should be ignored
                4, // not a hash, should be ignored
                'fallback');

            expect(find('cat')).to.equal('meow');
            expect(find('asdf')).to.equal('fallback');
        });
    });

    describe('renameKeys', function() {
        it('should rename all the keys if deep', function() {
            const obj = {
                'a_var': {
                    'cat_scratch_var': 1,
                    'dog_bark_var': 2
                },
                'b_var': {
                    'fish_swim_var': 1,
                    'ant_dead_var': 2
                },
                'c_var': 4,
                'd_var': [
                    {
                        'best_cereal': 'cheerios',
                        'best_soda': 'dr pepper'
                    }
                ]
            };

            const renamed = renameKeys(obj, snakeToCamelCase, true);

            expect(renamed).to.have.property('aVar');
            expect(renamed).to.not.have.property('a_var');
            expect(renamed).to.have.property('bVar');
            expect(renamed).to.not.have.property('b_var');
            expect(renamed).to.have.property('cVar');
            expect(renamed).to.not.have.property('c_var');
            expect(renamed).to.have.property('dVar');
            expect(renamed).to.not.have.property('d_var');

            expect(renamed.aVar).to.have.property('catScratchVar');
            expect(renamed.aVar).to.have.property('dogBarkVar');
            expect(renamed.bVar).to.have.property('fishSwimVar');
            expect(renamed.bVar).to.have.property('antDeadVar');

            expect(renamed.dVar[0]).to.have.property('bestCereal');
            expect(renamed.dVar[0]).to.have.property('bestSoda');
        });

        it('should work for arrays too', function() {
            const arr = [
                {
                    'a_var': 2
                },
                {
                    'b_var': 6
                }
            ];

            const renamed = renameKeys(arr, snakeToCamelCase);

            expect(renamed[0]).to.have.property('aVar');
            expect(renamed[1]).to.have.property('bVar');
        });

        it('should throw an error if not given a callback', function() {
            const obj = {
                'a_var': 2
            };

            expect(renameKeys.bind(null, obj)).to.throw(Error);
        });

        it('should not be deep by default', function() {
            const obj = {
                'a_var': {
                    'b_var': {
                        prop: 'value'
                    }
                }
            };

            expect(renameKeys(obj, snakeToCamelCase, false)).to.deep.equal({
                aVar: {
                    'b_var': {
                        prop: 'value'
                    }
                }
            });
        });
    });

    describe('uuidgen', function() {
        const uuidRegExp = new RegExp([
            '^[0-9a-f]{8}-',
            '[0-9a-f]{4}-',
            '[1-5][0-9a-f]{3}-',
            '[89ab][0-9a-f]{3}-',
            '[0-9a-f]{12}$'
        ].join(''), 'i');

        it('should generate a uuid', function() {
            const uuid = uuidgen();

            expect(uuid).to.match(uuidRegExp);
        });
    });
});
