import React from 'react';
import { screen, fireEvent, waitFor, act } from '@testing-library/react';
import { formatMessage, Segment } from '@theorchard/suite-frontend';
import { renderInAppContext } from '@theorchard/suite-testing';
import { waitForLoaded } from 'lib/test/helpers';
import { FEATURE_FLAGS } from 'src/constants';
import * as deleteSongWriter from 'src/data/mutations/deleteSongWriter/deleteSongWriter';
import * as orchardLabelById from 'src/data/queries/orchardLabel/orchardLabelById';
import * as orchardLabels from 'src/data/queries/orchardLabels/orchardLabels';
import * as publishers from 'src/data/queries/publishers/publishers';
import * as songWritersSearch from 'src/data/queries/songWritersSearch/songWritersSearch';
import { labelMock, labelsMock } from 'src/pages/songListPage/mocks';
import * as applicationContext from 'src/utils/applicationContext';
import { songUrl } from 'src/utils/urls';
import {
    publishersMock,
    songWritersQueryData,
    orchardLabelsMock,
    generateNMockSongWriters,
} from '../mocks';
import SongWriterListPage, { DEFAULT_SONGWRITER_SORT } from '../songWriters';

const pushMock = jest.fn();

// Songwriter-list sorting is behind ADMIN_UX_IMPROVEMENTS. With the flag off
// the page passes no sort to the query at all, which is what the pre-feature
// page did. Named for readability at the assertion sites.
const NO_SONGWRITER_SORT = undefined;

const SORT_ENABLED_CONTEXT = {
    identity: {
        features: { [FEATURE_FLAGS.ADMIN_UX_IMPROVEMENTS]: true },
    },
};

// The page derives its current page number from the router location, so tests
// that need to start on a later page point this at that page's pathname.
let mockPathname = '/song-writers/1';

jest.mock('react-router-dom', () => {
    const originalModule = jest.requireActual('react-router-dom');

    return {
        ...originalModule,
        useHistory: () => ({
            push: pushMock,
            location: {
                pathname: mockPathname,
                href: `https://publishing.qaorch.com${mockPathname}`,
            },
        }),
        Link: ({ to, children }: { to: string; children: React.ReactNode }) => (
            <a href={to} data-testid="mock-link">
                {children}
            </a>
        ),
    };
});

describe('<SongWriterListPage>', () => {
    const renderComponent = (page = 1, contextProps = {}) => {
        const defaultProps = {
            pathname: `/song-writers/${page}`,
        };

        const props = {
            ...defaultProps,
            ...contextProps,
        };

        return renderInAppContext(<SongWriterListPage />, props);
    };

    const deleteMutationSpy = jest.fn();
    let songWritersSearchSpy: jest.SpyInstance;

    beforeEach(() => {
        mockPathname = '/song-writers/1';
        pushMock.mockClear();

        Object.defineProperty(window, 'location', {
            writable: true,
            value: {
                assign: jest.fn(),
            },
        });

        jest.spyOn(Segment, 'trackEvent');

        songWritersSearchSpy = jest
            .spyOn(songWritersSearch, 'usePublishingSongWriters')
            .mockReturnValue({
                error: undefined,
                loading: false,
                data: songWritersQueryData,
                refetch: jest.fn(),
                networkStatus: 7,
            });

        jest.spyOn(publishers, 'usePublishingPublishers').mockReturnValue({
            error: undefined,
            loading: false,
            data: publishersMock,
            refetch: jest.fn(),
            networkStatus: 7,
        });

        jest.spyOn(orchardLabels, 'useOrchardLabels').mockReturnValue(
            labelsMock
        );
        jest.spyOn(deleteSongWriter, 'useDeleteSongWriter').mockReturnValue(
            deleteMutationSpy
        );
        jest.spyOn(
            orchardLabelById,
            'useOrchardLabelByIdQuery'
        ).mockReturnValue({
            loading: false,
            error: undefined,
            data: orchardLabelsMock[0],
        });
    });

    afterEach(() => {
        jest.restoreAllMocks();
    });

    it('has zero states in rows', async () => {
        renderComponent();
        await waitForLoaded();

        expect(screen.getAllByText('Not Registered').length).toBeTruthy();
    });

    it('can create a new writer', async () => {
        jest.spyOn(applicationContext, 'useApplicationContext').mockReturnValue(
            {
                label: labelMock.data[0],
                setLabel: jest.fn(),
                labelAlt: null,
                setLabelAlt: jest.fn(),
                pageFilters: { songPageSongWriters: null, brand: null },
                updatePageFilters: jest.fn(),
            }
        );

        renderComponent();
        await waitForLoaded();

        fireEvent.click(screen.getByText('New Writer'));

        expect(Segment.trackEvent).toHaveBeenCalledWith('Click - New Writer', {
            category: 'SongWriters',
        });
        expect(screen.getByText('Register a New Songwriter')).toBeTruthy();
    });

    it('can show empty state', async () => {
        jest.spyOn(
            songWritersSearch,
            'usePublishingSongWriters'
        ).mockReturnValue({
            error: undefined,
            loading: false,
            networkStatus: 7,
            data: {
                totalCount: 0,
                songWriters: [],
            },
            refetch: jest.fn(),
        });

        renderComponent();
        await waitForLoaded();

        expect(screen.getByText('You Have No Songwriters')).toBeTruthy();
    });

    it('common Label Picker should be render at header', async () => {
        const { container } = renderComponent();

        await waitForLoaded();

        const headerLabelPicker = container.querySelector(
            '.SongWriterListPage .AppHeader .HeaderLabelPicker .LabelSearchDropdown'
        );
        expect(headerLabelPicker).toBeTruthy();

        const pageTitle = container.querySelector(
            '.SongWriterListPage .AppHeader .breadcrumb'
        );
        expect(pageTitle).toBeFalsy();

        const listingLabelPickers = container.querySelector(
            '.SongWriterListPage .PageControls .LabelSearchDropdown'
        );
        expect(listingLabelPickers).toBeFalsy();
    });

    it('New Button should be disabled, if the label is not chosen', async () => {
        const { container } = renderComponent();

        await waitForLoaded();

        const newButtonDisabled = container.querySelector(
            '.SongWriterListPage .AppHeader .HelpTooltip button[disabled]'
        );
        expect(newButtonDisabled).toBeTruthy();
    });

    it('New Button should be enabled, if the label is chosen', async () => {
        jest.spyOn(applicationContext, 'useApplicationContext').mockReturnValue(
            {
                label: labelsMock.data[0],
                setLabel: jest.fn(),
                labelAlt: null,
                setLabelAlt: jest.fn(),
                pageFilters: { songPageSongWriters: null, brand: null },
                updatePageFilters: jest.fn(),
            }
        );

        const { container } = renderComponent();

        await waitForLoaded();

        const newButtonDisabled = container.querySelector(
            '.SongWriterListPage .AppHeader .HelpTooltip button[disabled]'
        );
        expect(newButtonDisabled).toBeFalsy();
        const newButton = container.querySelector(
            '.SongWriterListPage .AppHeader button'
        );
        expect(newButton).toBeTruthy();
    });

    test('can change pagesize', async () => {
        const mockData = generateNMockSongWriters();
        jest.spyOn(applicationContext, 'useApplicationContext').mockReturnValue(
            {
                label: null,
                setLabel: jest.fn(),
                labelAlt: null,
                setLabelAlt: jest.fn(),
                pageFilters: { songPageSongWriters: null, brand: null },
                updatePageFilters: jest.fn(),
            }
        );

        const songWritersMock = jest
            .spyOn(songWritersSearch, 'usePublishingSongWriters')
            .mockReturnValue({
                error: undefined,
                loading: false,
                data: mockData,
                refetch: jest.fn(),
                networkStatus: 7,
            });

        let selectedPageSize = 0;
        renderComponent();
        await act(async () => {
            await waitForLoaded();
        });

        const paginationMessage = (
            await screen.findAllByTestId('SuitePagination-message')
        )[0];
        await waitFor(() => {
            expect(paginationMessage).toBeTruthy();
        });
        act(() => {
            paginationMessage.click();
        });

        selectedPageSize = parseInt(
            (await screen.findAllByTestId('SegmentedButton-btn-text'))[0]
                .textContent || '0',
            10
        );

        (await screen.findAllByTestId('SegmentedButton-btn-text'))[0].click();

        await waitFor(() => {
            expect(songWritersMock).toHaveBeenLastCalledWith(
                {
                    brand: null,
                    label: null,
                    legalNameAndIpiSearch: null,
                    legalNameSearch: null,
                },
                1,
                selectedPageSize,
                'TITLE',
                'ASC',
                NO_SONGWRITER_SORT
            );
        });
    });

    test('uses filters from the application context', async () => {
        jest.spyOn(applicationContext, 'useApplicationContext').mockReturnValue(
            {
                label: null,
                setLabel: jest.fn(),
                labelAlt: null,
                setLabelAlt: jest.fn(),
                pageFilters: {
                    songPageSongWriters: null,
                    brand: null,
                    songWritersPageSongwriterSearch: '123456',
                },
                updatePageFilters: jest.fn(),
            }
        );

        const songWritersMock = jest.spyOn(
            songWritersSearch,
            'usePublishingSongWriters'
        );

        renderComponent();
        await act(async () => {
            await waitForLoaded();
        });

        await waitFor(() => {
            expect(songWritersMock).toHaveBeenLastCalledWith(
                {
                    brand: null,
                    label: null,
                    legalNameAndIpiSearch: true,
                    legalNameSearch: '123456',
                },
                1,
                25,
                'TITLE',
                'ASC',
                NO_SONGWRITER_SORT
            );
        });
    });

    describe('Brand selector', () => {
        it('Is shown for employees with full access', async () => {
            const { getByText } = renderComponent(1, {
                identity: {
                    isEmployee: true,
                    resources: [{ id: '*', name: 'All Orchard Labels' }],
                },
            });
            await waitForLoaded();
            expect(getByText('Brand')).toBeInTheDocument();
        });

        it('Is not shown for employees with not full access', async () => {
            const { queryByText } = renderComponent(1, {
                identity: {
                    isEmployee: true,
                },
            });
            await waitForLoaded();
            expect(queryByText('Brand')).not.toBeInTheDocument();
        });

        it('Is not shown for non employees with full access', async () => {
            const { queryByText } = renderComponent(1, {
                identity: {
                    isEmployee: false,
                    resources: [{ id: '*', name: 'All Orchard Labels' }],
                },
            });
            await waitForLoaded();
            expect(queryByText('Brand')).not.toBeInTheDocument();
        });

        it('Is not shown for non employees with not full access', async () => {
            const { queryByText } = renderComponent(1, {
                identity: {
                    isEmployee: false,
                },
            });
            await waitForLoaded();
            expect(queryByText('Brand')).not.toBeInTheDocument();
        });

        it('Can filter by Orchard brand', async () => {
            const { getByText } = renderComponent(1, {
                identity: {
                    isEmployee: true,
                    resources: [{ id: '*', name: 'All Orchard Labels' }],
                },
            });
            await waitForLoaded();

            fireEvent.click(getByText('Brand'));
            fireEvent.click(getByText('The Orchard'));

            expect(songWritersSearchSpy).toHaveBeenLastCalledWith(
                {
                    brand: 'THEORCHARD',
                    label: null,
                    legalNameAndIpiSearch: null,
                    legalNameSearch: null,
                },
                1,
                25,
                'TITLE',
                'ASC',
                NO_SONGWRITER_SORT
            );
        });

        it('Can filter by AWAL brand', async () => {
            const { getByText } = renderComponent(1, {
                identity: {
                    isEmployee: true,
                    resources: [{ id: '*', name: 'All Orchard Labels' }],
                },
            });
            await waitForLoaded();

            fireEvent.click(getByText('Brand'));
            fireEvent.click(getByText('AWAL'));

            expect(songWritersSearchSpy).toHaveBeenLastCalledWith(
                {
                    brand: 'AWAL',
                    label: null,
                    legalNameAndIpiSearch: null,
                    legalNameSearch: null,
                },
                1,
                25,
                'TITLE',
                'ASC',
                NO_SONGWRITER_SORT
            );
        });
    });

    describe('controlled and non-controlled labels', () => {
        beforeEach(() => {
            songWritersSearchSpy = jest
                .spyOn(songWritersSearch, 'usePublishingSongWriters')
                .mockReturnValue({
                    error: undefined,
                    loading: false,
                    data: {
                        totalCount: 3,
                        songWriters: [
                            {
                                id: '1',
                                legalName: 'Wade Warren',
                                professionallyKnownAs: [],
                                pro: 'ASCAP',
                                ipi: '123123123',
                                compositions: [{ id: '1', title: 'Song 1' }],
                                agreements: [
                                    {
                                        id: 'a1',
                                        controlled: true,
                                        compositions: [
                                            { id: '1', title: 'Song 1' },
                                        ],
                                        publisher: {
                                            id: '11',
                                            name: 'Wow Publisher',
                                            ipi: '48596bc',
                                            pro: null,
                                        },
                                    },
                                ],
                                vendor: {
                                    id: {
                                        vendorId: 12345,
                                        subaccountId: 0,
                                    },
                                    name: 'Label 12345',
                                    uuid: 'abc-123',
                                },
                            },
                            {
                                id: '2',
                                legalName: 'Dianne Russell',
                                professionallyKnownAs: [],
                                pro: null,
                                ipi: '',
                                compositions: [
                                    { id: '2', title: 'Song 2' },
                                    { id: '3', title: 'Song 3' },
                                    { id: '4', title: 'Song 4' },
                                ],
                                agreements: [
                                    {
                                        id: 'a2',
                                        controlled: false,
                                        compositions: [
                                            { id: '2', title: 'Song 2' },
                                            { id: '3', title: 'Song 3' },
                                            { id: '4', title: 'Song 4' },
                                        ],
                                        publisher: {
                                            id: '22',
                                            name: 'Amazing Publisher',
                                            ipi: '48596lm',
                                            pro: null,
                                        },
                                    },
                                ],
                                vendor: {
                                    id: {
                                        vendorId: 12345,
                                        subaccountId: 0,
                                    },
                                    name: 'Label 12345',
                                    uuid: 'abc-123',
                                },
                            },
                            {
                                id: '3',
                                legalName: 'Jenny Wilson',
                                professionallyKnownAs: [],
                                pro: 'BMI',
                                ipi: '123123123',
                                compositions: [],
                                agreements: [
                                    {
                                        id: 'a3',
                                        controlled: false,
                                        compositions: [],
                                        publisher: {
                                            id: '33',
                                            name: 'Great Publisher',
                                            ipi: '48596bh',
                                            pro: null,
                                        },
                                    },
                                ],
                                vendor: {
                                    id: {
                                        vendorId: 12345,
                                        subaccountId: 0,
                                    },
                                    name: 'Label 12345',
                                    uuid: 'abc-123',
                                },
                            },
                        ],
                    },
                    refetch: jest.fn(),
                    networkStatus: 7,
                });
        });

        it('displays correctly controlled and non-controlled labels', async () => {
            const { container } = renderComponent(1);

            const firstWriter = container.querySelector(
                'tbody tr:nth-child(1) td:nth-child(4) div.TruncatedText-inner'
            );
            const secondWriter = container.querySelector(
                'tbody tr:nth-child(2) td:nth-child(4) div.TruncatedText-inner'
            );
            const thirdWriter = container.querySelector(
                'tbody tr:nth-child(3) td:nth-child(4) div'
            );

            expect(firstWriter).toHaveTextContent('1 Controlled');
            expect(secondWriter).toHaveTextContent('3 Non-Controlled');
            expect(thirdWriter).toHaveTextContent('0');
        });

        it('displays correctly controlled and non-controlled labels and on click list of songs appears', async () => {
            const { getByText } = renderComponent(1);

            const controlledPill = getByText('1 Controlled');
            expect(controlledPill).toBeInTheDocument();
            fireEvent.click(controlledPill);

            const song1Link = await screen.findByText('Song 1');
            expect(song1Link).toBeInTheDocument();
            fireEvent.click(song1Link);
            expect(song1Link).toHaveAttribute('href', songUrl('1'));

            const nonControlledPill = getByText('3 Non-Controlled');
            expect(nonControlledPill).toBeInTheDocument();
            fireEvent.click(nonControlledPill);

            const song2Link = await screen.findByText('Song 2');
            expect(song2Link).toBeInTheDocument();
            fireEvent.click(song2Link);
            expect(song2Link).toHaveAttribute('href', songUrl('2'));

            const song3Link = await screen.findByText('Song 3');
            expect(song3Link).toBeInTheDocument();
            fireEvent.click(song3Link);
            expect(song3Link).toHaveAttribute('href', songUrl('3'));

            const song4Link = await screen.findByText('Song 4');
            expect(song4Link).toBeInTheDocument();
            fireEvent.click(song4Link);
            expect(song4Link).toHaveAttribute('href', songUrl('4'));
        });
    });

    describe('Professionally Known AS functionality', () => {
        beforeEach(() => {
            songWritersSearchSpy = jest
                .spyOn(songWritersSearch, 'usePublishingSongWriters')
                .mockReturnValue({
                    error: undefined,
                    loading: false,
                    data: {
                        totalCount: 3,
                        songWriters: [
                            {
                                id: '1',
                                legalName: 'Wade Warren',
                                professionallyKnownAs: ['Test PKA'],
                                pro: 'ASCAP',
                                ipi: '123123123',
                                compositions: [],
                                agreements: [
                                    {
                                        id: 'a1',
                                        controlled: true,
                                        compositions: [
                                            { id: '1', title: 'Song 1' },
                                        ],
                                        publisher: {
                                            id: '11',
                                            name: 'Wow Publisher',
                                            ipi: '48596bc',
                                            pro: null,
                                        },
                                    },
                                ],
                                vendor: {
                                    id: {
                                        vendorId: 12345,
                                        subaccountId: 0,
                                    },
                                    name: 'Label 12345',
                                    uuid: 'abc-123',
                                },
                            },
                        ],
                    },
                    refetch: jest.fn(),
                    networkStatus: 7,
                });
        });

        it('shows PKA values in songwriters list', async () => {
            const { getByText } = renderComponent(1, {});
            await act(async () => {
                await waitForLoaded();
            });

            expect(getByText('Test PKA')).toBeInTheDocument();
        });
    });

    describe('Sorting', () => {
        const getSortHeader = (container: HTMLElement) => {
            const header = container.querySelector(
                '.SongWriterListPage-sort-header'
            );
            if (!header)
                throw new Error('Could not find the legal name sort header');
            return header;
        };

        const getSongWriterColumnHeader = (container: HTMLElement) => {
            const header = container.querySelector('thead th');
            if (!header)
                throw new Error('Could not find the songwriter column header');
            return header;
        };

        const getLegalNames = (container: HTMLElement) =>
            Array.from(
                container.querySelectorAll(
                    'tbody tr td:nth-child(1) .Songs-link'
                )
            ).map(cell => cell.textContent);

        // The compositions nested under each songwriter are sorted by the
        // pre-existing $orderBy/$orderDir variables, which are a different enum
        // and are NOT part of this feature. They must be sent in both flag
        // states; gating them by mistake would silently regress the nested sort.
        // Args 3 and 4 of the hook are that nested sort.
        const nestedCompositionSortArgs = () => {
            const { calls } = songWritersSearchSpy.mock;
            const lastCall = calls[calls.length - 1] ?? [];

            return [lastCall[3], lastCall[4]];
        };

        describe('with the ADMIN_UX_IMPROVEMENTS flag on', () => {
            const renderWithSortEnabled = (page = 1) =>
                renderComponent(page, SORT_ENABLED_CONTEXT);

            it('asks the server for the default legal name sort', async () => {
                renderWithSortEnabled();
                await waitForLoaded();

                expect(songWritersSearchSpy).toHaveBeenLastCalledWith(
                    expect.anything(),
                    1,
                    25,
                    'TITLE',
                    'ASC',
                    { orderBy: 'LEGAL_NAME', orderDir: 'ASC' }
                );
                expect(DEFAULT_SONGWRITER_SORT).toEqual({
                    orderBy: 'LEGAL_NAME',
                    orderDir: 'ASC',
                });
            });

            it('sends the toggled sort to the query rather than reordering rows on the client', async () => {
                const { container } = renderWithSortEnabled();
                await waitForLoaded();

                // The mocked query returns rows in a non-alphabetical order. A
                // client-side sort would reorder these three visible rows; a
                // server-side sort leaves them exactly as the query returned
                // them.
                const orderBeforeSort = getLegalNames(container);
                expect(orderBeforeSort).toEqual([
                    'Wade Warren',
                    'Dianne Russell',
                    'Jenny Wilson',
                ]);

                fireEvent.click(getSortHeader(container));

                // The sort must be pushed to the query, so that the server can
                // sort the whole result set before slicing the requested page.
                await waitFor(() => {
                    expect(songWritersSearchSpy).toHaveBeenLastCalledWith(
                        expect.anything(),
                        1,
                        25,
                        'TITLE',
                        'ASC',
                        { orderBy: 'LEGAL_NAME', orderDir: 'DESC' }
                    );
                });

                // The already-fetched rows are untouched.
                expect(getLegalNames(container)).toEqual(orderBeforeSort);
            });

            it('toggles the direction back to ascending on a second click', async () => {
                const { container } = renderWithSortEnabled();
                await waitForLoaded();

                fireEvent.click(getSortHeader(container));
                await waitFor(() =>
                    expect(songWritersSearchSpy).toHaveBeenLastCalledWith(
                        expect.anything(),
                        1,
                        25,
                        'TITLE',
                        'ASC',
                        { orderBy: 'LEGAL_NAME', orderDir: 'DESC' }
                    )
                );

                fireEvent.click(getSortHeader(container));
                await waitFor(() =>
                    expect(songWritersSearchSpy).toHaveBeenLastCalledWith(
                        expect.anything(),
                        1,
                        25,
                        'TITLE',
                        'ASC',
                        { orderBy: 'LEGAL_NAME', orderDir: 'ASC' }
                    )
                );
            });

            it('reflects the active sort direction on the column header', async () => {
                const { container } = renderWithSortEnabled();
                await waitForLoaded();

                const header = () =>
                    container.querySelector(
                        'thead th[aria-sort]'
                    ) as HTMLElement;

                expect(header()).toHaveAttribute('aria-sort', 'ascending');

                fireEvent.click(getSortHeader(container));

                await waitFor(() =>
                    expect(header()).toHaveAttribute('aria-sort', 'descending')
                );
            });

            it('resets to the first page when the sort changes', async () => {
                mockPathname = '/song-writers/3';

                // totalCount must be big enough that page 3 genuinely exists,
                // otherwise the "page > totalPages" guard would redirect to
                // page 1 on its own and this test would pass for the wrong
                // reason.
                songWritersSearchSpy.mockReturnValue({
                    error: undefined,
                    loading: false,
                    data: { ...songWritersQueryData, totalCount: 100 },
                    refetch: jest.fn(),
                    networkStatus: 7,
                });

                const { container } = renderWithSortEnabled(3);
                await waitForLoaded();

                // Sanity check: the page really did start on page 3.
                expect(songWritersSearchSpy).toHaveBeenLastCalledWith(
                    expect.anything(),
                    3,
                    25,
                    'TITLE',
                    'ASC',
                    DEFAULT_SONGWRITER_SORT
                );

                pushMock.mockClear();
                fireEvent.click(getSortHeader(container));

                await waitFor(() =>
                    expect(pushMock).toHaveBeenCalledWith({
                        pathname: '/song-writers/1',
                        search: '',
                    })
                );
            });

            it('still sends the nested composition sort', async () => {
                const { container } = renderWithSortEnabled();
                await waitForLoaded();

                expect(nestedCompositionSortArgs()).toEqual(['TITLE', 'ASC']);

                // ...and it survives a change to the songwriter sort.
                fireEvent.click(getSortHeader(container));
                await waitFor(() =>
                    expect(songWritersSearchSpy).toHaveBeenLastCalledWith(
                        expect.anything(),
                        1,
                        25,
                        'TITLE',
                        'ASC',
                        { orderBy: 'LEGAL_NAME', orderDir: 'DESC' }
                    )
                );
                expect(nestedCompositionSortArgs()).toEqual(['TITLE', 'ASC']);
            });
        });

        describe('with the ADMIN_UX_IMPROVEMENTS flag off', () => {
            it('renders the songwriter column as a plain, non-sortable header', async () => {
                const { container } = renderComponent();
                await waitForLoaded();

                // This is exactly the markup the page had before the feature:
                // a bare <th> holding the label and nothing else.
                expect(getSongWriterColumnHeader(container).outerHTML).toBe(
                    `<th>${formatMessage('generic.songWriter')}</th>`
                );

                expect(
                    container.querySelector('.SongWriterListPage-sort-header')
                ).toBeNull();
                expect(
                    container.querySelector('thead th[aria-sort]')
                ).toBeNull();
                expect(container.querySelector('thead button')).toBeNull();
            });

            it('does nothing when the songwriter column header is clicked', async () => {
                const { container } = renderComponent();
                await waitForLoaded();

                pushMock.mockClear();
                fireEvent.click(getSongWriterColumnHeader(container));

                // No navigation (the flag-on path resets to page 1 here) and no
                // sort added to the query.
                expect(pushMock).not.toHaveBeenCalled();
                expect(songWritersSearchSpy).toHaveBeenLastCalledWith(
                    expect.anything(),
                    1,
                    25,
                    'TITLE',
                    'ASC',
                    NO_SONGWRITER_SORT
                );
            });

            it('does not send a songwriter sort to the query', async () => {
                renderComponent();
                await waitForLoaded();

                expect(songWritersSearchSpy).toHaveBeenLastCalledWith(
                    expect.anything(),
                    1,
                    25,
                    'TITLE',
                    'ASC',
                    NO_SONGWRITER_SORT
                );
            });

            it('still sends the nested composition sort', async () => {
                renderComponent();
                await waitForLoaded();

                expect(nestedCompositionSortArgs()).toEqual(['TITLE', 'ASC']);
            });
        });
    });

    it('can not delete an existing song writer if ALLOW_DELETE_SONG_WRITER FF is off', async () => {
        const { container } = renderComponent(1, {
            identity: {
                features: {
                    [FEATURE_FLAGS.ALLOW_DELETE_SONG_WRITER]: false,
                },
            },
        });
        await act(async () => {
            await waitForLoaded();
        });

        const glyphIcon = container.querySelector('.action-delete');

        expect(glyphIcon).toBeFalsy();
    });

    it('can not delete an existing song writer if song writer has associated composition', async () => {
        const { container, queryByText } = renderComponent(1, {
            identity: {
                features: {
                    [FEATURE_FLAGS.ALLOW_DELETE_SONG_WRITER]: true,
                },
            },
        });
        await act(async () => {
            await waitForLoaded();
        });

        const glyphIcon = container.querySelector('.action-delete');
        if (!glyphIcon) throw new Error('Could not find .action-delete');
        fireEvent.click(glyphIcon);

        await waitFor(() =>
            expect(
                queryByText('Yes, I want to delete this songwriter')
            ).toBeFalsy()
        );
    });

    it('can delete an existing song writer if song writer does not have associated composition', async () => {
        jest.spyOn(
            songWritersSearch,
            'usePublishingSongWriters'
        ).mockReturnValue({
            error: undefined,
            loading: false,
            data: {
                totalCount: 3,
                songWriters: [
                    {
                        id: '1',
                        legalName: 'Wade Warren',
                        professionallyKnownAs: [],
                        pro: 'ASCAP',
                        ipi: '123123123',
                        compositions: [],
                        agreements: [
                            {
                                id: 'a1',
                                controlled: true,
                                compositions: [],
                                publisher: {
                                    id: '11',
                                    name: 'Wow Publisher',
                                    ipi: '48596bc',
                                    pro: null,
                                },
                            },
                        ],
                        vendor: {
                            id: {
                                vendorId: 12345,
                                subaccountId: 0,
                            },
                            name: 'Label 12345',
                            uuid: 'abc-123',
                        },
                    },
                ],
            },
            refetch: jest.fn(),
            networkStatus: 7,
        });

        const { container, getByText } = renderComponent(1, {
            identity: {
                features: {
                    [FEATURE_FLAGS.ALLOW_DELETE_SONG_WRITER]: true,
                },
            },
        });
        await waitForLoaded();

        const glyphIcon = container.querySelector('.action-delete');
        if (!glyphIcon) throw new Error('Could not find .action-delete');
        fireEvent.click(glyphIcon);

        const confirmDeleteButton = getByText(
            'Yes, I want to delete this songwriter'
        );
        expect(confirmDeleteButton).toBeTruthy();

        fireEvent.click(confirmDeleteButton);
        expect(Segment.trackEvent).toHaveBeenCalledWith(
            'Click - Delete Song Writer',
            {
                category: 'Delete Songwriter',
                songWriterId: '1',
                songWriterName: 'Wade Warren',
            }
        );
        expect(deleteMutationSpy).toHaveBeenCalledWith({
            variables: { id: '1' },
        });
    });
});
