text:
var ReactTestUtils = React.addons.TestUtils;
var expect = chai.expect;

var ReactableTestUtils = {
    resetTestEnvironment:  function() {
        React.unmountComponentAtNode($('div#test-node')[0]);
        $('div#test-node').remove();
    },

    // Expect the row specified to have the specified class
    expectRowClass: function(rowIndex, className) {
        var row = $($('#table tbody.reactable-data tr')[rowIndex]);
        expect(row).to.have.class(className);
    },

    // Expect the columns of a the data row specified to have the values in the array as their text values
    expectRowText: function(rowIndex, textArray) {
        var row = $($('#table tbody.reactable-data tr')[rowIndex]).find('td');

        expect(row.length).to.equal(textArray.length);

        for (var i = 0; i < row.length; i++) {
            expect($(row[i])).to.have.text(textArray[i]);
        }
    },

    testNode: function() {
        testNode = $('
').attr('id', 'test-node');
        $('body').append(testNode);
        testNode.empty();
        return testNode[0];
    }
};

describe('Reactable', function() {
    describe('directly passing a data array', function() {
        before(function() {
            React.render(
                React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                    { Name: 'Griffin Smith', Age: '18'},
                    { Age: '23', Name: 'Lee Salminen'},
                    { Age: '28', Position: 'Developer'},
                    { Name: 'Leonor Hyatt', Position: null}
                ]}),
                ReactableTestUtils.testNode()
            );
        });

        after(ReactableTestUtils.resetTestEnvironment);

        it('renders the table', function() {
            expect($('table#table.table')).to.exist;
        });

        it('renders the column headers in the table', function() {
            var headers = [];
            $('thead th').each(function() {
                headers.push($(this).text());
            });

            expect(headers).to.eql([ 'Name', 'Age', 'Position']);
        });

        it('renders the first row with the correct data', function() {
            ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', '']);
        });

        it('renders the second row with the correct data', function() {
            ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', '']);
        });

        it('renders the third row with the correct data', function() {
            ReactableTestUtils.expectRowText(2, ['', '28', 'Developer']);
        });

        it('handles null values', function() {
          ReactableTestUtils.expectRowText(3, ['Leonor Hyatt', '', '']);
        });
    });

    describe('adding
s to the
', function() {
        before(function() {
            React.render(
                React.createElement(Reactable.Table, {className: "table", id: "table"},
                    React.createElement(Reactable.Tr, {data: { Name: 'Griffin Smith', Age: '18'}}),
                    React.createElement(Reactable.Tr, {data: { Age: '23', Name: 'Lee Salminen'}}),
                    React.createElement(Reactable.Tr, {data: { Age: '28', Position: 'Developer'}})
                ),
                ReactableTestUtils.testNode()
            );
        });

        after(ReactableTestUtils.resetTestEnvironment);

        it('renders the table', function() {
            expect($('table#table.table')).to.exist;
        });

        it('renders the column headers in the table', function() {
            var headers = [];
            $('thead th').each(function() {
                headers.push($(this).text());
            });

            expect(headers).to.eql([ 'Name', 'Age', 'Position' ]);
        });

        it('renders the first row with the correct data', function() {
            ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', '']);
        });

        it('renders the second row with the correct data', function() {
            ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', '']);
        });

        it('renders the third row with the correct data', function() {
            ReactableTestUtils.expectRowText(2, ['', '28', 'Developer']);
        });
    });

    describe('adding s to the
s', function() {
        context('with only one ', function() {
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table"},
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Name"}, "Griffin Smith")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Name"}, "Lee Salminen")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Name"}, "Ian Zhang")
                        )
                    ),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('renders the table', function() {
                expect($('table#table.table')).to.exist;
            });

            it('renders the column headers in the table', function() {
                var headers = [];
                $('thead th').each(function() {
                    headers.push($(this).text());
                });

                expect(headers).to.eql(['Name']);
            });

            it('renders the first row with the correct data', function() {
                ReactableTestUtils.expectRowText(0, ['Griffin Smith']);
            });

            it('renders the second row with the correct data', function() {
                ReactableTestUtils.expectRowText(1, ['Lee Salminen']);
            });

            it('renders the third row with the correct data', function() {
                ReactableTestUtils.expectRowText(2, ['Ian Zhang']);
            });
        });

        context('with multiple s', function () {
            context('with plain text', function() {
                before(function() {
                    React.render(
                        React.createElement(Reactable.Table, {className: "table", id: "table"},
                            React.createElement(Reactable.Tr, null,
                                React.createElement(Reactable.Td, {column: "Name"}, "Griffin Smith"),
                                React.createElement(Reactable.Td, {column: "Age"}, "18")
                            ),
                            React.createElement(Reactable.Tr, null,
                                React.createElement(Reactable.Td, {column: "Name"}, "Lee Salminen"),
                                React.createElement(Reactable.Td, {column: "Age"}, "23")
                            ),
                            React.createElement(Reactable.Tr, null,
                                React.createElement(Reactable.Td, {column: "Position"}, "Developer"),
                                React.createElement(Reactable.Td, {column: "Age"}, "28")
                            )
                        ),
                        ReactableTestUtils.testNode()
                    );
                });

                after(ReactableTestUtils.resetTestEnvironment);

                it('renders the table', function() {
                    expect($('table#table.table')).to.exist;
                });

                it('renders the column headers in the table', function() {
                    var headers = [];
                    $('thead th').each(function() {
                        headers.push($(this).text());
                    });

                    expect(headers).to.eql([ 'Name', 'Age', 'Position' ]);
                });

                it('renders the first row with the correct data', function() {
                    ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', '']);
                });

                it('renders the second row with the correct data', function() {
                    ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', '']);
                });

                it('renders the third row with the correct data', function() {
                    ReactableTestUtils.expectRowText(2, ['', '28', 'Developer']);
                });
            });
        });

        context('with React.DOM nodes inside', function() {
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table"},
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Name"}, React.createElement("b", null, "Griffin Smith")),
                            React.createElement(Reactable.Td, {column: "Age"}, React.createElement("em", null, "18"))
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Name"}, React.createElement("b", null, "Lee Salminen")),
                            React.createElement(Reactable.Td, {column: "Age"}, React.createElement("em", null, "23"))
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Position"}, React.createElement("b", null, "Developer")),
                            React.createElement(Reactable.Td, {column: "Age"}, React.createElement("em", null, "28"))
                        )
                    ),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('renders the table', function() {
                expect($('table#table.table')).to.exist;
            });

            it('renders the column headers in the table', function() {
                var headers = [];
                $('thead th').each(function() {
                    headers.push($(this).text());
                });

                expect(headers).to.eql([ 'Name', 'Age', 'Position' ]);
            });

            it('renders the first row with the correct data', function() {
                ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', '']);
            });

            it('renders the second row with the correct data', function() {
                ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', '']);
            });

            it('renders the third row with the correct data', function() {
                ReactableTestUtils.expectRowText(2, ['', '28', 'Developer']);
            });
        });

        context('with null s', function(){
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table"},
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Name"}, React.createElement("b", null, "Griffin Smith")),
                            null
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Name"}, React.createElement("b", null, "Lee Salminen")),
                            React.createElement(Reactable.Td, {column: "Age"}, React.createElement("em", null, "23"))
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Position"}, React.createElement("b", null, "Developer")),
                            React.createElement(Reactable.Td, {column: "Age"}, React.createElement("em", null, "28"))
                        )
                    ),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('renders the table', function() {
                expect($('table#table.table')).to.exist;
            });

            it('renders the column headers in the table', function() {
                var headers = [];
                $('thead th').each(function() {
                    headers.push($(this).text());
                });

                expect(headers).to.eql([ 'Name', 'Age', 'Position' ]);
            });

            it('renders the first row with the correct data', function() {
                ReactableTestUtils.expectRowText(0, ['Griffin Smith', '', '']);
            });

            it('renders the second row with the correct data', function() {
                ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', '']);
            });

            it('renders the third row with the correct data', function() {
                ReactableTestUtils.expectRowText(2, ['', '28', 'Developer']);
            });
        });

        context('with null
s', function(){
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table"},
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Name"}, React.createElement("b", null, "Griffin Smith")),
                            React.createElement(Reactable.Td, {column: "Age"}, React.createElement("em", null, "18"))
                        ),
                        null,
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Position"}, React.createElement("b", null, "Developer")),
                            React.createElement(Reactable.Td, {column: "Age"}, React.createElement("em", null, "28"))
                        )
                    ),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('renders the table', function() {
                expect($('table#table.table')).to.exist;
            });

            it('renders the column headers in the table', function() {
                var headers = [];
                $('thead th').each(function() {
                    headers.push($(this).text());
                });

                expect(headers).to.eql([ 'Name', 'Age', 'Position' ]);
            });

            it('renders the first row with the correct data', function() {
                ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', '']);
            });

            it('renders the second row with the correct data', function() {
                ReactableTestUtils.expectRowText(1, ['', '28', 'Developer']);
            });
        });
    });

    describe('passing through HTML props', function() {
        describe('adding
s with className to the
', function() {
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table"},
                        React.createElement(Reactable.Tr, {className: "rowClass1", data: { Name: 'Griffin Smith', Age: '18'}}),
                        React.createElement(Reactable.Tr, {className: "rowClass2", data: { Age: '23', Name: 'Lee Salminen'}}),
                        React.createElement(Reactable.Tr, {className: "rowClass3", data: { Age: '28', Position: 'Developer'}})
                    ),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('renders the table', function() {
                expect($('table#table.table')).to.exist;
            });

            it('renders the column headers in the table', function() {
                var headers = [];
                $('thead th').each(function() {
                    headers.push($(this).text());
                });

                expect(headers).to.eql([ 'Name', 'Age', 'Position' ]);
            });

            it('renders the first row with the correct class name', function() {
                ReactableTestUtils.expectRowClass(0, 'rowClass1');
            });

            it('renders the second row with the correct class name', function() {
                ReactableTestUtils.expectRowClass(1, 'rowClass2');
            });

            it('renders the third row with the correct class name', function() {
                ReactableTestUtils.expectRowClass(2, 'rowClass3');
            });
        });

        describe('adding s with classNames to the
', function() {
            before(function () {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table"},
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Name", className: "name-1"}, "Griffin Smith"),
                            React.createElement(Reactable.Td, {column: "Age"}, "18")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Name", className: "name-2"}, "Lee Salminen"),
                            React.createElement(Reactable.Td, {column: "Age"}, "23")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Position", className: "position"}, "Developer"),
                            React.createElement(Reactable.Td, {column: "Age"}, "28")
                        )
                    ),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('renders the first column with the correct class name', function() {
                expect($('td.name-1')).to.have.text('Griffin Smith');
            });

            it('renders the second column with the correct class name', function() {
                expect($('td.name-2')).to.have.text('Lee Salminen');
            });

            it('renders the third column with the correct class name', function() {
                expect($('td.position')).to.have.text('Developer');
            });
        });
    });

    describe('specifying an array of columns', function() {
        describe('as strings', function() {
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                        { Name: 'Griffin Smith', Age: '18', HideThis: 'one'},
                        { Age: '23', Name: 'Lee Salminen', HideThis: 'two'},
                        { Age: '28', Position: 'Developer'},
                    ], columns: ['Name', 'Age']}),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('omits columns not in the list', function() {
                var columns = $('tr.reactable-column-header th');
                expect(columns.length).to.equal(2);
                expect($(columns[0])).to.have.text('Name');
                expect($(columns[1])).to.have.text('Age');
            });

            it('adds class name for each column base on its label', function() {
                var columns = $('tr.reactable-column-header th');
                expect($(columns[0])).to.have.class('reactable-th-name');
                expect($(columns[1])).to.have.class('reactable-th-age');
            });
        });

        describe('as objects', function() {
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                        { name: 'Griffin Smith', age: '18', HideThis: 'one'},
                        { age: '23', name: 'Lee Salminen', HideThis: 'two'},
                        { age: '28', Position: 'Developer'},
                    ], columns: [
                        { key: 'name', label: 'Name' },
                        { key: 'age', label: 'Age' }
                    ]}),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('omits columns not in the list', function() {
                var columns = $('tr.reactable-column-header th');
                expect(columns.length).to.equal(2);
            });

            it('allows changing the labels of the columns', function() {
                var columns = $('tr.reactable-column-header th');
                expect($(columns[0])).to.have.text('Name');
                expect($(columns[1])).to.have.text('Age');
            });

            it('adds class name for each column base on its key', function() {
                var columns = $('tr.reactable-column-header th');
                expect($(columns[0])).to.have.class('reactable-th-name');
                expect($(columns[1])).to.have.class('reactable-th-age');
            });
        });
    });

    describe('unsafe() strings', function() {
        context('in the
 directly', function() {
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                        { Name: Reactable.unsafe('Griffin Smith'), Age: '18'},
                        { Age: '28', Position: Reactable.unsafe('Developer')},
                        { Age: '23', Name: Reactable.unsafe('Lee Salminen')},
                    ], sortable: ['Name']}),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('renders the HTML in the table cells', function() {
                var griffins_name = $('span#griffins-name');
                expect(griffins_name.length).to.equal(1);
                expect(griffins_name).to.have.text('Griffin Smith');

                var lees_name = $('span#lees-name');
                expect(lees_name.length).to.equal(1);
                expect(lees_name).to.have.text('Lee Salminen');

                var who_knows_job = $('span#who-knows-job');
                expect(who_knows_job.length).to.equal(1);
                expect(who_knows_job).to.have.text('Developer');
            });

            it('still allows sorting', function() {
                var nameHeader = $('#table thead tr.reactable-column-header th')[0];
                ReactTestUtils.Simulate.click(nameHeader);

                ReactableTestUtils.expectRowText(0, ['28', 'Developer', '']);
                ReactableTestUtils.expectRowText(1, ['18', '', 'Griffin Smith']);
                ReactableTestUtils.expectRowText(2, ['23', '', 'Lee Salminen']);
            });
        });

        context('in column labels', function() {
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                        { Name: 'Griffin Smith', Age: '18'},
                        { Age: '23', Name: 'Lee Salminen'},
                        { Age: '28', Position: 'Developer'}
                    ], columns: [
                        { key: 'Name', label: Reactable.unsafe('Name') },
                        { key: 'Age', label: Reactable.unsafe('Age') },
                        { key: 'Position', label: Reactable.unsafe('Position') }
                    ]}),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('renders the HTML in the column headers', function() {
                var headers = [];
                $('thead th').each(function() {
                    headers.push($(this).html());
                });

                expect(headers).to.eql([
                    'Name',
                    'Age',
                    'Position'
                ]);
            });
        });

        context('in the
s', function() {
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table"},
                        React.createElement(Reactable.Tr, {data: { Name: Reactable.unsafe('Griffin Smith'), Age: '18'}}),
                        React.createElement(Reactable.Tr, {data: { Age: '23', Name: Reactable.unsafe('Lee Salminen')}}),
                        React.createElement(Reactable.Tr, {data: { Age: '28', Position: Reactable.unsafe('Developer')}})
                    ),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('renders the HTML in the table cells', function() {
                var griffins_name = $('span#griffins-name');
                expect(griffins_name.length).to.equal(1);
                expect(griffins_name).to.have.text('Griffin Smith');

                var lees_name = $('span#lees-name');
                expect(lees_name.length).to.equal(1);
                expect(lees_name).to.have.text('Lee Salminen');

                var who_knows_job = $('span#who-knows-job');
                expect(who_knows_job.length).to.equal(1);
                expect(who_knows_job).to.have.text('Developer');
            });
        });

        context('in the s', function() {
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table"},
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Name"}, Reactable.unsafe('Griffin Smith')),
                            React.createElement(Reactable.Td, {column: "Age"}, "18")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Name"}, Reactable.unsafe('Lee Salminen')),
                            React.createElement(Reactable.Td, {column: "Age"}, "23")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Position"}, Reactable.unsafe('Developer')),
                            React.createElement(Reactable.Td, {column: "Age"}, "28")
                        )
                    ),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('renders the HTML in the table cells', function() {
                var griffins_name = $('span#griffins-name');
                expect(griffins_name.length).to.equal(1);
                expect(griffins_name).to.have.text('Griffin Smith');

                var lees_name = $('span#lees-name');
                expect(lees_name.length).to.equal(1);
                expect(lees_name).to.have.text('Lee Salminen');

                var who_knows_job = $('span#who-knows-job');
                expect(who_knows_job.length).to.equal(1);
                expect(who_knows_job).to.have.text('Developer');
            });
        });
    });

    describe('pagination', function() {
        describe('specifying itemsPerPage', function(){
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                        {'Name': 'Griffin Smith', 'Age': '18'},
                        {'Age': '23', 'Name': 'Lee Salminen'},
                        {'Age': '28', 'Position': 'Developer'},
                        {'Name': 'Griffin Smith', 'Age': '18'},
                        {'Age': '23', 'Name': 'Test Person'},
                        {'Name': 'Ian Zhang', 'Age': '28', 'Position': 'Developer'},
                        {'Name': 'Griffin Smith', 'Age': '18', 'Position': 'Software Developer'},
                        {'Age': '23', 'Name': 'Lee Salminen'},
                        {'Age': '28', 'Position': 'Developer'},
                    ], itemsPerPage: 4}),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('provides buttons for each page', function() {
                var pageButtons = $('#table tbody.reactable-pagination a.reactable-page-button');
                expect(pageButtons.length).to.equal(3);
                expect($(pageButtons[0])).to.have.text('1')
                expect($(pageButtons[1])).to.have.text('2')
                expect($(pageButtons[2])).to.have.text('3')
            });

            it('displays only the first n rows', function() {
                expect($('#table tbody.reactable-data tr').length).to.equal(4);
            });

            it('specifies a class on the currently active page', function() {
                var activePage = $('#table tbody.reactable-pagination a.reactable-page-button.reactable-current-page');
                expect(activePage.length).to.equal(1);
                expect(activePage).to.have.text('1');
            });

            describe('clicking page buttons', function() {
                beforeEach(function() {
                    var page2 = $('#table tbody.reactable-pagination a.reactable-page-button')[1];
                    ReactTestUtils.Simulate.click(page2);
                });

                it('loads the next n rows', function() {
                    var rows = $('#table tbody.reactable-data tr');
                    expect($($(rows[0]).find('td')[0])).to.have.text('Test Person');
                    expect($($(rows[1]).find('td')[0])).to.have.text('Ian Zhang');
                    expect($($(rows[2]).find('td')[0])).to.have.text('Griffin Smith');
                    expect($($(rows[3]).find('td')[0])).to.have.text('Lee Salminen');
                });

                it('puts an active class on the new active page', function() {
                    var activePage = $('#table tbody.reactable-pagination a.reactable-page-button.reactable-current-page');
                    expect(activePage.length).to.equal(1);
                    expect(activePage).to.have.text('2');
                });

                it('can go back to the original page', function() {
                    var page1 = $('#table tbody.reactable-pagination a.reactable-page-button')[0];
                    ReactTestUtils.Simulate.click(page1);

                    var rows = $('#table tbody.reactable-data tr');
                    expect($($(rows[0]).find('td')[0])).to.have.text('Griffin Smith');
                    expect($($(rows[1]).find('td')[0])).to.have.text('Lee Salminen');
                    expect($($(rows[2]).find('td')[0])).to.have.text('');
                    expect($($(rows[3]).find('td')[0])).to.have.text('Griffin Smith');
                });
            });
        });

        describe('specifying more itemsPerPage than items', function(){
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                        {'Name': 'Griffin Smith', 'Age': '18'},
                        {'Age': '23', 'Name': 'Lee Salminen'},
                        {'Age': '28', 'Position': 'Developer'},
                        {'Name': 'Griffin Smith', 'Age': '18'},
                        {'Age': '23', 'Name': 'Test Person'},
                        {'Name': 'Ian Zhang', 'Age': '28', 'Position': 'Developer'},
                        {'Name': 'Griffin Smith', 'Age': '18', 'Position': 'Software Developer'},
                        {'Age': '23', 'Name': 'Lee Salminen'},
                        {'Age': '28', 'Position': 'Developer'},
                    ], itemsPerPage: 20}),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('renders all rows', function(){
                expect($('#table tbody.reactable-data tr').length).to.equal(9);
            });

            it('provides buttons for 1 page', function() {
                var pageButtons = $('#table tbody.reactable-pagination a.reactable-page-button');
                expect(pageButtons.length).to.equal(1);
                expect($(pageButtons[0])).to.have.text('1')
            });
        });

        describe('not specifying itemsPerPage', function(){
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                        {'Name': 'Griffin Smith', 'Age': '18'},
                        {'Age': '23', 'Name': 'Lee Salminen'},
                        {'Age': '28', 'Position': 'Developer'},
                        {'Name': 'Griffin Smith', 'Age': '18'},
                        {'Age': '23', 'Name': 'Test Person'},
                        {'Name': 'Ian Zhang', 'Age': '28', 'Position': 'Developer'},
                        {'Name': 'Griffin Smith', 'Age': '18', 'Position': 'Software Developer'},
                        {'Age': '23', 'Name': 'Lee Salminen'},
                        {'Age': '28', 'Position': 'Developer'},
                    ]}),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('renders all rows', function(){
                expect($('#table tbody.reactable-data tr').length).to.equal(9);
            });
        });

        describe('specifying 0 itemsPerPage', function(){
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                        {'Name': 'Griffin Smith', 'Age': '18'},
                        {'Age': '23', 'Name': 'Lee Salminen'},
                        {'Age': '28', 'Position': 'Developer'},
                        {'Name': 'Griffin Smith', 'Age': '18'},
                        {'Age': '23', 'Name': 'Test Person'},
                        {'Name': 'Ian Zhang', 'Age': '28', 'Position': 'Developer'},
                        {'Name': 'Griffin Smith', 'Age': '18', 'Position': 'Software Developer'},
                        {'Age': '23', 'Name': 'Lee Salminen'},
                        {'Age': '28', 'Position': 'Developer'},
                    ], itemsPerPage: 0}),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('renders all rows', function(){
                expect($('#table tbody.reactable-data tr').length).to.equal(9);
            });
        });
    });

    describe('sorting', function(){
        describe('no default sort', function(){
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                        { Name: 'Lee Salminen', Age: '23', Position: 'Programmer'},
                        { Name: 'Griffin Smith', Age: '18', Position: 'Engineer'},
                        { Name: 'Ian Zhang', Age: '28', Position: 'Developer'}
                    ],
                    sortable: [
                        {
                            column: 'Name',
                            sortFunction: function(a, b){
                                // Sort by last name
                                var nameA = a.split(' ');
                                var nameB = b.split(' ');

                                return nameA[1].localeCompare(nameB[1]);
                            }
                        },
                        'Age',
                        'Position'
                    ]}),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('renders all rows with no sort', function(){
                ReactableTestUtils.expectRowText(0, ['Lee Salminen', '23', 'Programmer']);
                ReactableTestUtils.expectRowText(1, ['Griffin Smith', '18', 'Engineer']);
                ReactableTestUtils.expectRowText(2, ['Ian Zhang', '28', 'Developer']);
            });

            it('adds reactable-header-sortable to all headers', function(){
              var header = $('#table thead tr.reactable-column-header th')[0];
              expect($(header)).to.have.class('reactable-header-sortable');

              header = $('#table thead tr.reactable-column-header th')[1];
              expect($(header)).to.have.class('reactable-header-sortable');

              header = $('#table thead tr.reactable-column-header th')[2];
              expect($(header)).to.have.class('reactable-header-sortable');
            });

            it('sorts by text in ascending order', function(){
                var positionHeader = $('#table thead tr.reactable-column-header th')[2];
                ReactTestUtils.Simulate.click(positionHeader);

                ReactableTestUtils.expectRowText(0, ['Ian Zhang', '28', 'Developer']);
                ReactableTestUtils.expectRowText(1, ['Griffin Smith', '18', 'Engineer']);
                ReactableTestUtils.expectRowText(2, ['Lee Salminen', '23', 'Programmer']);

                // Make sure the headers have the right classes
                expect($(positionHeader)).to.have.class('reactable-header-sort-asc');
            });

            it('sorts by text in descending order', function(){
                var positionHeader = $('#table thead tr.reactable-column-header th')[2];
                ReactTestUtils.Simulate.click(positionHeader);

                ReactableTestUtils.expectRowText(0, ['Lee Salminen', '23', 'Programmer']);
                ReactableTestUtils.expectRowText(1, ['Griffin Smith', '18', 'Engineer']);
                ReactableTestUtils.expectRowText(2, ['Ian Zhang', '28', 'Developer']);

                // Make sure the headers have the right classes
                expect($(positionHeader)).to.have.class('reactable-header-sort-desc');
            });

            it('sorts by last name in ascending order', function(){
                var nameHeader = $('#table thead tr.reactable-column-header th')[0];
                ReactTestUtils.Simulate.click(nameHeader);

                ReactableTestUtils.expectRowText(0, ['Lee Salminen', '23', 'Programmer']);
                ReactableTestUtils.expectRowText(1, ['Griffin Smith', '18', 'Engineer']);
                ReactableTestUtils.expectRowText(2, ['Ian Zhang', '28', 'Developer']);

                // Make sure the headers have the right classes
                expect($(nameHeader)).to.have.class('reactable-header-sort-asc');
            });

            it('sorts by last name in descending order', function(){
                var nameHeader = $('#table thead tr.reactable-column-header th')[0];
                ReactTestUtils.Simulate.click(nameHeader);

                ReactableTestUtils.expectRowText(0, ['Ian Zhang', '28', 'Developer']);
                ReactableTestUtils.expectRowText(1, ['Griffin Smith', '18', 'Engineer']);
                ReactableTestUtils.expectRowText(2, ['Lee Salminen', '23', 'Programmer']);

                // Make sure the headers have the right classes
                expect($(nameHeader)).to.have.class('reactable-header-sort-desc');
            });
        });

        describe('passing `true` to sortable', function() {
            var component;
            before(function() {
                component = React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                        { Name: 'Lee Salminen', Age: '23', Position: 'Programmer'},
                        { Name: 'Griffin Smith', Age: '18', Position: 'Engineer'},
                        { Name: 'Ian Zhang', Age: '28', Position: 'Developer'}
                    ],
                    sortable: true}),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('sorts by the first column in ascending order', function(){
                var nameHeader = $('#table thead tr.reactable-column-header th')[0];
                ReactTestUtils.Simulate.click(nameHeader);

                ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', 'Engineer']);
                ReactableTestUtils.expectRowText(1, ['Ian Zhang', '28', 'Developer']);
                ReactableTestUtils.expectRowText(2, ['Lee Salminen', '23', 'Programmer']);

                // Make sure the headers have the right classes
                expect($(nameHeader)).to.have.class('reactable-header-sort-asc');
            });

            it('sorts by the first column in descending order', function(){
                var nameHeader = $('#table thead tr.reactable-column-header th')[0];
                ReactTestUtils.Simulate.click(nameHeader);

                ReactableTestUtils.expectRowText(0, ['Lee Salminen', '23', 'Programmer']);
                ReactableTestUtils.expectRowText(1, ['Ian Zhang', '28', 'Developer']);
                ReactableTestUtils.expectRowText(2, ['Griffin Smith', '18', 'Engineer']);

                // Make sure the headers have the right classes
                expect($(nameHeader)).to.have.class('reactable-header-sort-desc');
            });

            it('sorts by the second column in ascending order', function(){
                var nameHeader = $('#table thead tr.reactable-column-header th')[1];
                ReactTestUtils.Simulate.click(nameHeader);

                ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', 'Engineer']);
                ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', 'Programmer']);
                ReactableTestUtils.expectRowText(2, ['Ian Zhang', '28', 'Developer']);

                // Make sure the headers have the right classes
                expect($(nameHeader)).to.have.class('reactable-header-sort-asc');
            });

            it('sorts by the second column in descending order', function(){
                var nameHeader = $('#table thead tr.reactable-column-header th')[1];
                ReactTestUtils.Simulate.click(nameHeader);

                ReactableTestUtils.expectRowText(0, ['Ian Zhang', '28', 'Developer']);
                ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', 'Programmer']);
                ReactableTestUtils.expectRowText(2, ['Griffin Smith', '18', 'Engineer']);

                // Make sure the headers have the right classes
                expect($(nameHeader)).to.have.class('reactable-header-sort-desc');
            });

            it('sorts by the third column in ascending order', function(){
                var positionHeader = $('#table thead tr.reactable-column-header th')[2];
                ReactTestUtils.Simulate.click(positionHeader);

                ReactableTestUtils.expectRowText(0, ['Ian Zhang', '28', 'Developer']);
                ReactableTestUtils.expectRowText(1, ['Griffin Smith', '18', 'Engineer']);
                ReactableTestUtils.expectRowText(2, ['Lee Salminen', '23', 'Programmer']);

                // Make sure the headers have the right classes
                expect($(positionHeader)).to.have.class('reactable-header-sort-asc');
            });

            it('sorts by the third column in descending order', function(){
                var positionHeader = $('#table thead tr.reactable-column-header th')[2];
                ReactTestUtils.Simulate.click(positionHeader);

                ReactableTestUtils.expectRowText(0, ['Lee Salminen', '23', 'Programmer']);
                ReactableTestUtils.expectRowText(1, ['Griffin Smith', '18', 'Engineer']);
                ReactableTestUtils.expectRowText(2, ['Ian Zhang', '28', 'Developer']);

                // Make sure the headers have the right classes
                expect($(positionHeader)).to.have.class('reactable-header-sort-desc');
            });

            it('Keeps the same sort after rerendering', function(){
                expect(function() {component.setProps({update: true})}).to.not.throw(Error);

                ReactableTestUtils.expectRowText(0, ['Lee Salminen', '23', 'Programmer']);
                ReactableTestUtils.expectRowText(1, ['Griffin Smith', '18', 'Engineer']);
                ReactableTestUtils.expectRowText(2, ['Ian Zhang', '28', 'Developer']);
            });
        });

        describe('default sort', function(){
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                        { Name: 'Lee Salminen', Age: '23', Position: 'Programmer'},
                        { Name: 'Griffin Smith', Age: '18', Position: 'Engineer'},
                        { Name: 'Ian Zhang', Age: '28', Position: 'Developer'}
                    ],
                    sortable: [
                        {
                            column: 'Name',
                            sortFunction: function(a, b){
                                // Sort by last name
                                var nameA = a.split(' ');
                                var nameB = b.split(' ');

                                return nameA[1].localeCompare(nameB[1]);
                            }
                        },
                        'Age',
                        'Position'
                    ],
                    defaultSort: {column: 'Age', direction: 'desc'}}),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('renders all rows sorted by default column age descending', function(){
                ReactableTestUtils.expectRowText(0, ['Ian Zhang', '28', 'Developer']);
                ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', 'Programmer']);
                ReactableTestUtils.expectRowText(2, ['Griffin Smith', '18', 'Engineer']);
            });
        });

        describe('default sort no direction specified', function(){
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                        { Name: 'Lee Salminen', Age: '23', Position: 'Programmer'},
                        { Name: 'Griffin Smith', Age: '18', Position: 'Engineer'},
                        { Name: 'Ian Zhang', Age: '28', Position: 'Developer'}
                    ],
                    sortable: [
                        {
                            column: 'Name',
                            sortFunction: function(a, b){
                                // Sort by last name
                                var nameA = a.split(' ');
                                var nameB = b.split(' ');

                                return nameA[1].localeCompare(nameB[1]);
                            }
                        },
                        'Age',
                        'Position'
                    ],
                    defaultSort: 'Age'}),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('renders all rows sorted by default column age ascending', function(){
                ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', 'Engineer']);
                ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', 'Programmer']);
                ReactableTestUtils.expectRowText(2, ['Ian Zhang', '28', 'Developer']);
            });
        });

        describe('unsortable column', function(){
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                        { Name: 'Lee Salminen', Age: '23', Position: 'Programmer'},
                        { Name: 'Griffin Smith', Age: '18', Position: 'Engineer'},
                        { Name: 'Ian Zhang', Age: '28', Position: 'Developer'}
                    ],
                    sortable: [
                        'Age',
                        'Position'
                    ]}),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('leaves columns unsorted', function(){
                var nameHeader = $('#table thead tr.reactable-column-header th')[0];
                ReactTestUtils.Simulate.click(nameHeader);

                ReactableTestUtils.expectRowText(0, ['Lee Salminen', '23', 'Programmer']);
                ReactableTestUtils.expectRowText(1, ['Griffin Smith', '18', 'Engineer']);
                ReactableTestUtils.expectRowText(2, ['Ian Zhang', '28', 'Developer']);
            });
        });

        [Reactable.Sort.Numeric, Reactable.Sort.NumericInteger].forEach(function(method) {
            describe('numeric sort', function(){
                before(function() {
                    React.render(
                        React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                            { Count: '23'},
                            { Count: '18'},
                            { Count: '28'},
                            { Count: '1.23'},
                            { Count: 'a'},
                            { Count: 'z'},
                            { Count: '123'}
                        ],
                        columns: [{ key: 'Count', sortable: method }]}),
                        ReactableTestUtils.testNode()
                    );
                });

                after(function() {
                    ReactableTestUtils.resetTestEnvironment();
                });

                it('sorts columns numerically', function(){
                    var sortHeader = $('#table thead tr.reactable-column-header th')[0];
                    ReactTestUtils.Simulate.click(sortHeader);

                    ReactableTestUtils.expectRowText(0, ['1.23']);
                    ReactableTestUtils.expectRowText(1, ['18']);
                    ReactableTestUtils.expectRowText(2, ['23']);
                    ReactableTestUtils.expectRowText(3, ['28']);
                    ReactableTestUtils.expectRowText(4, ['123']);
                    ReactableTestUtils.expectRowText(5, ['a']);
                    ReactableTestUtils.expectRowText(6, ['z']);
                });
            });
        });

        describe('numeric sort with Tr and Td specified', function(){
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {
                        className: "table",
                        id: "table",
                        columns: [{ key: 'Count', sortable: Reactable.Sort.Numeric }]},
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Count"}, "23")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Count"}, "18")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Count"}, "28")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Count"}, "1.23")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Count"}, "a")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Count"}, "z")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Count"}, "123")
                        )
                    ),
                    ReactableTestUtils.testNode()
                );
            });

            after(function() {
                ReactableTestUtils.resetTestEnvironment();
            });

            it('sorts columns numerically', function(){
                var sortHeader = $('#table thead tr.reactable-column-header th')[0];
                ReactTestUtils.Simulate.click(sortHeader);

                ReactableTestUtils.expectRowText(0, ['1.23']);
                ReactableTestUtils.expectRowText(1, ['18']);
                ReactableTestUtils.expectRowText(2, ['23']);
                ReactableTestUtils.expectRowText(3, ['28']);
                ReactableTestUtils.expectRowText(4, ['123']);
                ReactableTestUtils.expectRowText(5, ['a']);
                ReactableTestUtils.expectRowText(6, ['z']);
            });
        });

        describe('numeric sort with Tr and Td specified and custom value', function(){
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {
                        className: "table",
                        id: "table",
                        columns: [{ key: 'Count', sortable: Reactable.Sort.Numeric }]},
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Count", value: 23}, "twenty-three")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Count", value: 18}, "eighteen")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Count", value: 28}, "twenty-eight")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Count", value: 1.23}, "one point two three")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Count", value: "a"}, "a")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Count", value: "z"}, "z")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Count", value: 123}, "one hundred twenty-three")
                        )
                    ),
                    ReactableTestUtils.testNode()
                );
            });

            after(function() {
                ReactableTestUtils.resetTestEnvironment();
            });

            it('sorts columns numerically', function(){
                var sortHeader = $('#table thead tr.reactable-column-header th')[0];
                ReactTestUtils.Simulate.click(sortHeader);

                ReactableTestUtils.expectRowText(0, ['one point two three']);
                ReactableTestUtils.expectRowText(1, ['eighteen']);
                ReactableTestUtils.expectRowText(2, ['twenty-three']);
                ReactableTestUtils.expectRowText(3, ['twenty-eight']);
                ReactableTestUtils.expectRowText(4, ['one hundred twenty-three']);
                ReactableTestUtils.expectRowText(5, ['a']);
                ReactableTestUtils.expectRowText(6, ['z']);
            });
        });

        describe('currency sort', function(){
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                        { Price: '1.25'},
                        { Price: '$1.01'},
                        { Price: '1'},
                        { Price: '$10,000'},
                        { Price: '$10,500'},
                        { Price: '$10'},
                        { Price: 'a'},
                        { Price: 'z'},
                        { Price: '$2'},
                        { Price: '$.5'},
                        { Price: '$0.60'},
                        { Price: '.1'},
                    ],
                    columns: [{ key: 'Price', sortable: Reactable.Sort.Currency }]}),
                    ReactableTestUtils.testNode()
                );
            });

            after(function() {
                ReactableTestUtils.resetTestEnvironment();
            });

            it('sorts columns numerically. parsing out currency symbols', function(){
                var sortHeader = $('#table thead tr.reactable-column-header th')[0];
                ReactTestUtils.Simulate.click(sortHeader);

                ReactableTestUtils.expectRowText(0, ['.1']);
                ReactableTestUtils.expectRowText(1, ['$.5']);
                ReactableTestUtils.expectRowText(2, ['$0.60']);
                ReactableTestUtils.expectRowText(3, ['1']);
                ReactableTestUtils.expectRowText(4, ['$1.01']);
                ReactableTestUtils.expectRowText(5, ['1.25']);
                ReactableTestUtils.expectRowText(6, ['$2']);
                ReactableTestUtils.expectRowText(7, ['$10']);
                ReactableTestUtils.expectRowText(8, ['$10,000']);
                ReactableTestUtils.expectRowText(9, ['$10,500']);
                ReactableTestUtils.expectRowText(10, ['a']);
                ReactableTestUtils.expectRowText(11, ['z']);
            });
        });

        describe('date sort', function(){
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                        { 'Date': '1/1/2014 11:00 AM'},
                        { 'Date': '1/1/2013 11:00 AM'},
                        { 'Date': '1/1/2014 4:30 PM'},
                        { 'Date': '4/3/2013'},
                        { 'Date': 'a'},
                        { 'Date': 'z'},
                    ],
                    columns: [{ key: 'Date', sortable: Reactable.Sort.Date }]}),
                    ReactableTestUtils.testNode()
                );
            });

            after(function() {
                ReactableTestUtils.resetTestEnvironment();
            });

            it('sorts columns by date', function(){
                var sortHeader = $('#table thead tr.reactable-column-header th')[0];
                ReactTestUtils.Simulate.click(sortHeader);

                ReactableTestUtils.expectRowText(0, ['1/1/2013 11:00 AM']);
                ReactableTestUtils.expectRowText(1, ['4/3/2013']);
                ReactableTestUtils.expectRowText(2, ['1/1/2014 11:00 AM']);
                ReactableTestUtils.expectRowText(3, ['1/1/2014 4:30 PM']);
                ReactableTestUtils.expectRowText(4, ['a']);
                ReactableTestUtils.expectRowText(5, ['z']);
            });
        });

        describe('case insensitive sorting', function(){
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                        { 'Name': 'Lee Salminen'},
                        { 'Name': 'Griffin Smith'},
                        { 'Name': 'Ian Zhang'},
                        { 'Name': 'lee Salminen'},
                        { 'Name': 'griffin smith'},
                        { 'Name': 'Ian zhang'},
                    ],
                    columns: [{ key: 'Name', sortable: Reactable.Sort.CaseInsensitive }]}),
                    ReactableTestUtils.testNode()
                );
            });

            after(function() {
                ReactableTestUtils.resetTestEnvironment();
            });

            it('sorts columns by value - case insensitive', function(){
                var sortHeader = $('#table thead tr.reactable-column-header th')[0];
                ReactTestUtils.Simulate.click(sortHeader);

                ReactableTestUtils.expectRowText(0, ['Griffin Smith']);
                ReactableTestUtils.expectRowText(1, ['griffin smith']);
                ReactableTestUtils.expectRowText(2, ['Ian Zhang']);
                ReactableTestUtils.expectRowText(3, ['Ian zhang']);
                ReactableTestUtils.expectRowText(4, ['Lee Salminen']);
                ReactableTestUtils.expectRowText(5, ['lee Salminen']);
            });
        });

        describe('custom sort with React Components', function(){
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                        {'Rank': React.createElement("span", {className: "3"}, "Third")},
                        {'Rank': React.createElement("span", {className: "1"}, "First")},
                        {'Rank': React.createElement("span", {className: "2"}, "Second")},
                    ],
                        columns: [{
                            key: 'Rank', sortable: function (a, b) {
                                // sort based on classname
                                return a.props.className.localeCompare(b.props.className);
                            }
                        }]}),
                    ReactableTestUtils.testNode()
                );
            });

            after(function() {
                ReactableTestUtils.resetTestEnvironment();
            });

            it('sorts columns by value', function(){
                var sortHeader = $('#table thead tr.reactable-column-header th')[0];
                ReactTestUtils.Simulate.click(sortHeader);

                ReactableTestUtils.expectRowText(0, ['First']);
                ReactableTestUtils.expectRowText(1, ['Second']);
                ReactableTestUtils.expectRowText(2, ['Third']);
            });
        });
    });

    describe('filtering', function() {
        describe('filtering with javascript objects for data', function(){
            var data = [{name:"Lee SomeoneElse", age:18},{name:"Lee Salminen", age:23},{name:"No Age", age:null}]
            before(function () {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table",
                        filterable: ['Name', 'Age']},
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Name", data: data[0].name}),
                            React.createElement(Reactable.Td, {column: "Age", data: data[0].age})
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Name", data: data[1].name}),
                            React.createElement(Reactable.Td, {column: "Age", data: data[1].age})
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "Name", data: data[2].name}),
                            React.createElement(Reactable.Td, {column: "Age", data: data[2].age})
                        )
                    ),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            it('filters case insensitive on specified columns', function() {
                var $filter = $('#table thead tr.reactable-filterer input.reactable-filter-input');

                $filter.val('lee');
                React.addons.TestUtils.Simulate.keyUp($filter[0]);

                ReactableTestUtils.expectRowText(0, ['Lee SomeoneElse', '18']);
                ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23']);
            });
        });

        describe('basic case-insensitive filtering', function(){
            before(function() {
                this.component = React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table",
                        filterable: ['State', 'Tag'],
                        filterPlaceholder: "Filter Results",
                        columns: ['State', 'Description', 'Tag']},
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "State"}, "New York"),
                            React.createElement(Reactable.Td, {column: "Description"}, "this is some text"),
                            React.createElement(Reactable.Td, {column: "Tag"}, "new")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "State"}, "New Mexico"),
                            React.createElement(Reactable.Td, {column: "Description"}, "lorem ipsum"),
                            React.createElement(Reactable.Td, {column: "Tag"}, "old")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "State"}, "Colorado"),
                            React.createElement(Reactable.Td, {column: "Description"},
                                "new description that shouldnt match filter"
                            ),
                            React.createElement(Reactable.Td, {column: "Tag"}, "old")
                        ),
                        React.createElement(Reactable.Tr, null,
                            React.createElement(Reactable.Td, {column: "State"}, "Alaska"),
                            React.createElement(Reactable.Td, {column: "Description"}, "bacon"),
                            React.createElement(Reactable.Td, {column: "Tag"}, "renewed")
                        )
                    ),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            context('from the filterer field', function() {
                it('filters case insensitive on specified columns', function() {
                    var $filter = $('#table thead tr.reactable-filterer input.reactable-filter-input');

                    $filter.val('new');
                    React.addons.TestUtils.Simulate.keyUp($filter[0]);

                    ReactableTestUtils.expectRowText(0, ['New York', 'this is some text', 'new']);
                    ReactableTestUtils.expectRowText(1, ['New Mexico', 'lorem ipsum', 'old']);
                    ReactableTestUtils.expectRowText(2, ['Alaska', 'bacon', 'renewed']);
                });

                it('filter placeholder is set', function(){
                    var $filter = $('#table thead tr.reactable-filterer input.reactable-filter-input');
                    expect($filter.attr("placeholder")).to.equal('Filter Results');
                })
            });

            context('from the function', function() {
                before(function() {
                    this.component.filterBy('york');
                });

                it('applies the filtering', function() {
                    ReactableTestUtils.expectRowText(0, ['New York', 'this is some text', 'new']);
                });

                it('updates the value of the filterer', function() {
                    var $filter = $('#table thead tr.reactable-filterer input.reactable-filter-input');
                    expect($filter).to.have.value('york');
                });
            });
        });

        context('filtering and pagination together', function(){
            before(function() {
                React.render(
                    React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                        {'State': 'New York', 'Description': 'this is some text', 'Tag': 'new'},
                        {'State': 'New Mexico', 'Description': 'lorem ipsum', 'Tag': 'old'},
                        {'State': 'Colorado', 'Description': 'new description that shouldn\'t match filter',
                            'Tag': 'old'},
                        {'State': 'Alaska', 'Description': 'bacon', 'Tag': 'renewed'},
                    ],
                        filterable: ['State', 'Tag'],
                        columns: ['State', 'Description', 'Tag'],
                        itemsPerPage: 2}),
                    ReactableTestUtils.testNode()
                );
            });

            after(ReactableTestUtils.resetTestEnvironment);

            afterEach(function() {
                var $filter = $('#table thead tr.reactable-filterer input.reactable-filter-input');
                $filter.val('');
                React.addons.TestUtils.Simulate.keyUp($filter[0]);
            });

            it('updates the pagination links', function() {
                var $filter = $('#table thead tr.reactable-filterer input.reactable-filter-input');

                $filter.val('colorado');
                React.addons.TestUtils.Simulate.keyUp($filter[0]);

                var pageButtons = $('#table tbody.reactable-pagination a.reactable-page-button');
                expect(pageButtons.length).to.equal(1);
                expect($(pageButtons[0])).to.have.text('1');
            });

            it('updates the current page if necessary', function() {
                var $filter = $('#table thead tr.reactable-filterer input.reactable-filter-input');
                var $pageButtons = $('#table tbody.reactable-pagination a.reactable-page-button');

                // Go to the last page
                React.addons.TestUtils.Simulate.click($pageButtons[1])

                // Then filter so that that page doesn't exist anymore
                $filter.val('colorado');
                React.addons.TestUtils.Simulate.keyUp($filter[0]);

                ReactableTestUtils.expectRowText(0, [
                    'Colorado',
                    "new description that shouldn't match filter",
                    'old'
                ]);
                var activePage = $('#table tbody.reactable-pagination ' +
                    'a.reactable-page-button.reactable-current-page');
                expect(activePage.length).to.equal(1);
                expect(activePage).to.have.text('1');
            });
        });
    });

    describe('directly passing a data array with non-string data', function() {
        before(function() {
            React.render(
                React.createElement(Reactable.Table, {className: "table", id: "table", data: [
                    { Name: 'Griffin Smith', Age: 18},
                    { Age: 23, Name: { toString: function() { return 'Lee Salminen' } } },
                    { Age: 28.45, Position: 'Developer'}
                ]}),
                ReactableTestUtils.testNode()
            );
        });

        after(ReactableTestUtils.resetTestEnvironment);

        it('renders the table', function() {
            expect($('table#table.table')).to.exist;
        });

        it('renders the column headers in the table', function() {
            var headers = [];
            $('thead th').each(function() {
                headers.push($(this).text());
            });

            expect(headers).to.eql([ 'Name', 'Age', 'Position']);
        });

        it('renders the first row with the correct data', function() {
            ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', '']);
        });

        it('renders the second row with the correct data', function() {
            ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', '']);
        });

        it('renders the third row with the correct data', function() {
            ReactableTestUtils.expectRowText(2, ['', '28.45', 'Developer']);
        });
    });

    describe('multiple tables on a page', function() {
        before(function() {
            this.parentTestNode = ReactableTestUtils.testNode();
            this.testNode1 = $('
').attr('id', 'test-node-1');
            this.testNode2 = $('
').attr('id', 'test-node-2');

            React.render(
                React.createElement(Reactable.Table, {className: "table", id: "table1", data: [
                    { Name: 'Griffin Smith', Age: '18'},
                    { Age: '23', Name: 'Lee Salminen'},
                    { Age: '28', Position: 'Developer'}
                ]}),
                this.testNode1[0]
            );

            React.render(
                React.createElement(Reactable.Table, {className: "table", id: "table2", data: [
                    { Moniker: 'Griffin Smith', Elderliness: '18'},
                    { Elderliness: '23', Moniker: 'Lee Salminen'},
                    { Elderliness: '28', Title: 'Developer'}
                ]}),
                this.testNode2[0]
            );
        });

        after(function() {
            $(this.parentTestNode).empty().remove();
        });

        it('renders the column headers in the first table', function() {
            var headers = [];
            this.testNode1.find('thead th').each(function() {
                headers.push($(this).text());
            });

            expect(headers).to.eql(['Name', 'Age', 'Position']);
        });

        it('renders the column headers in the second table', function() {
            var headers = [];
            this.testNode2.find('thead th').each(function() {
                headers.push($(this).text());
            });

            expect(headers).to.eql(['Moniker', 'Elderliness', 'Title']);
        });
    });
});


text:
require 'spec_helper'

describe Company do
  subject { Company.new }

  it "should respond to name and document" do
    should respond_to :name
    should respond_to :document
  end

  it "should generate document" do
    subject.document.should be_instance_of(Cnpj)
  end

  it "should have document number" do
    subject.document_number.should eq(subject.document.to_s)
  end

  it "should generate name" do
    subject.name.should be_instance_of(String)
  end
end

redpajama_set_name: RedPajamaGithub


text:
package jet.spring;

import com.hazelcast.jet.JetInstance;
import com.hazelcast.jet.config.JobConfig;
import com.hazelcast.jet.pipeline.Pipeline;
import com.hazelcast.jet.pipeline.Sinks;
import jet.spring.config.AppConfig;
import jet.spring.source.CustomSourceP;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Example of integrating Hazelcast Jet with Spring Boot. {@link AppConfig}
 * class is used as a configuration class and {@link SpringBootSample#submitJob()}
 * is mapped to url 'http://host:port/submitJob' using {@link RestController} and
 * {@link RequestMapping} annotations
 * <p>
 * Job uses a custom source implementation which has {@link com.hazelcast.spring.context.SpringAware}
 * annotation. This enables spring to auto-wire beans to created processors.
 */
@RestController
public class SpringBootSample {

    @Autowired
    JetInstance instance;

    public static void main(String[] args) {
        SpringApplication.run(AppConfig.class, args);
    }

    @RequestMapping("/submitJob")
    public void submitJob() {
        Pipeline pipeline = Pipeline.create();
        pipeline.drawFrom(CustomSourceP.customSource())
                .drainTo(Sinks.logger());

        JobConfig jobConfig = new JobConfig()
                .addClass(SpringBootSample.class)
                .addClass(CustomSourceP.class);
        instance.newJob(pipeline, jobConfig).join();
    }

}


text:
<?php

namespace Eddmash\PowerOrm\Tests\QueryApp\Models;

use Eddmash\PowerOrm\Model\Model;

class Order extends Model
{
    public function unboundFields()
    {
        return [
            'products' => Model::ManyToManyField(['to' => Product::class,
                'through' => OrderItem::class, 'relatedName' => 'orders', ]),
            'buyer' => Model::ForeignKey(['to' => User::class]),
            'date' => Model::DateField(['autoAddNow' => true]),
        ];
    }
}


text:
<?php

declare(strict_types = 1);

use PHPUnit\Framework\TestCase;
use Sop\ASN1\Type\Constructed\Sequence;
use Sop\ASN1\Type\Primitive\Integer;
use Sop\CryptoEncoding\PEM;
use Sop\CryptoTypes\AlgorithmIdentifier\Asymmetric\ECPublicKeyAlgorithmIdentifier;
use Sop\CryptoTypes\Asymmetric\EC\ECPrivateKey;
use Sop\CryptoTypes\Asymmetric\EC\ECPublicKey;
use Sop\CryptoTypes\Asymmetric\PrivateKeyInfo;

/**
 * @group asn1
 * @group ec
 *
 * @internal
 */
class ECPrivateKeyTest extends TestCase
{
    /**
     * @return ECPrivateKey
     */
    public function testDecode()
    {
        $pem = PEM::fromFile(TEST_ASSETS_DIR . '/ec/ec_private_key.pem');
        $pk = ECPrivateKey::fromDER($pem->data());
        $this->assertInstanceOf(ECPrivateKey::class, $pk);
        return $pk;
    }

    /**
     * @return ECPrivateKey
     */
    public function testFromPEM()
    {
        $pem = PEM::fromFile(TEST_ASSETS_DIR . '/ec/ec_private_key.pem');
        $pk = ECPrivateKey::fromPEM($pem);
        $this->assertInstanceOf(ECPrivateKey::class, $pk);
        return $pk;
    }

    /**
     * @depends testFromPEM
     */
    public function testToPEM(ECPrivateKey $pk)
    {
        $pem = $pk->toPEM();
        $this->assertInstanceOf(PEM::class, $pem);
        return $pem;
    }

    /**
     * @depends testToPEM
     */
    public function testRecodedPEM(PEM $pem)
    {
        $ref = PEM::fromFile(TEST_ASSETS_DIR . '/ec/ec_private_key.pem');
        $this->assertEquals($ref, $pem);
    }

    /**
     * @return ECPrivateKey
     */
    public function testFromPKIPEM()
    {
        $pem = PEM::fromFile(TEST_ASSETS_DIR . '/ec/private_key.pem');
        $pk = ECPrivateKey::fromPEM($pem);
        $this->assertInstanceOf(ECPrivateKey::class, $pk);
        return $pk;
    }

    /**
     * @depends testDecode
     */
    public function testPrivateKeyOctets(ECPrivateKey $pk)
    {
        $octets = $pk->privateKeyOctets();
        $this->assertIsString($octets);
    }

    /**
     * @depends testFromPKIPEM
     */
    public function testHasNamedCurveFromPKI(ECPrivateKey $pk)
    {
        $this->assertEquals(ECPublicKeyAlgorithmIdentifier::CURVE_PRIME256V1,
            $pk->namedCurve());
    }

    /**
     * @depends testDecode
     */
    public function testGetPublicKey(ECPrivateKey $pk)
    {
        $pub = $pk->publicKey();
        $ref = ECPublicKey::fromPEM(
            PEM::fromFile(TEST_ASSETS_DIR . '/ec/public_key.pem'));
        $this->assertEquals($ref, $pub);
    }

    /**
     * @depends testDecode
     */
    public function testGetPrivateKeyInfo(ECPrivateKey $pk)
    {
        $pki = $pk->privateKeyInfo();
        $this->assertInstanceOf(PrivateKeyInfo::class, $pki);
    }

    public function testInvalidVersion()
    {
        $pem = PEM::fromFile(TEST_ASSETS_DIR . '/ec/ec_private_key.pem');
        $seq = Sequence::fromDER($pem->data());
        $seq = $seq->withReplaced(0, new Integer(0));
        $this->expectException(\UnexpectedValueException::class);
        ECPrivateKey::fromASN1($seq);
    }

    public function testInvalidPEMType()
    {
        $pem = new PEM('nope', '');
        $this->expectException(\UnexpectedValueException::class);
        ECPrivateKey::fromPEM($pem);
    }

    public function testRSAKeyFail()
    {
        $pem = PEM::fromFile(TEST_ASSETS_DIR . '/rsa/private_key.pem');
        $this->expectException(\UnexpectedValueException::class);
        ECPrivateKey::fromPEM($pem);
    }

    /**
     * @depends testDecode
     */
    public function testNamedCurveNotSet(ECPrivateKey $pk)
    {
        $pk = $pk->withNamedCurve(null);
        $this->expectException(\LogicException::class);
        $pk->namedCurve();
    }

    public function testPublicKeyNotSet()
    {
        $pk = new ECPrivateKey("\0");
        $this->expectException(\LogicException::class);
        $pk->publicKey();
    }
}