"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("@testing-library/react");
require("@testing-library/jest-dom");
const ResponseActions_1 = __importDefault(require("./ResponseActions"));
const user_event_1 = __importDefault(require("@testing-library/user-event"));
const react_icons_1 = require("@patternfly/react-icons");
const Message_1 = __importDefault(require("../Message"));
const ALL_ACTIONS = [
    { type: 'positive', label: 'Good response', clickedLabel: 'Good response recorded' },
    { type: 'negative', label: 'Bad response', clickedLabel: 'Bad response recorded' },
    { type: 'copy', label: 'Copy', clickedLabel: 'Copied' },
    { type: 'edit', label: 'Edit', clickedLabel: 'Editing' },
    { type: 'share', label: 'Share', clickedLabel: 'Shared' },
    { type: 'listen', label: 'Listen', clickedLabel: 'Listening' }
];
const CUSTOM_ACTIONS = [
    {
        regenerate: {
            ariaLabel: 'Regenerate',
            clickedAriaLabel: 'Regenerated',
            onClick: jest.fn(),
            tooltipContent: 'Regenerate',
            clickedTooltipContent: 'Regenerated',
            icon: (0, jsx_runtime_1.jsx)(react_icons_1.RedoIcon, {})
        },
        download: {
            ariaLabel: 'Download',
            clickedAriaLabel: 'Downloaded',
            onClick: jest.fn(),
            tooltipContent: 'Download',
            clickedTooltipContent: 'Downloaded',
            icon: (0, jsx_runtime_1.jsx)(react_icons_1.DownloadIcon, {})
        },
        info: {
            ariaLabel: 'Info',
            onClick: jest.fn(),
            tooltipContent: 'Info',
            icon: (0, jsx_runtime_1.jsx)(react_icons_1.InfoCircleIcon, {})
        }
    }
];
const ALL_ACTIONS_DATA_TEST = [
    { type: 'positive', label: 'Good response', dataTestId: 'positive' },
    { type: 'negative', label: 'Bad response', dataTestId: 'negative' },
    { type: 'copy', label: 'Copy', dataTestId: 'copy' },
    { type: 'edit', label: 'Edit', dataTestId: 'edit' },
    { type: 'share', label: 'Share', dataTestId: 'share' },
    { type: 'download', label: 'Download', dataTestId: 'download' },
    { type: 'listen', label: 'Listen', dataTestId: 'listen' }
];
describe('ResponseActions', () => {
    afterEach(() => {
        jest.clearAllMocks();
    });
    it('should handle click within group of buttons correctly', () => __awaiter(void 0, void 0, void 0, function* () {
        (0, react_1.render)((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: {
                positive: { onClick: jest.fn() },
                negative: { onClick: jest.fn() },
                copy: { onClick: jest.fn() },
                edit: { onClick: jest.fn() },
                share: { onClick: jest.fn() },
                download: { onClick: jest.fn() },
                listen: { onClick: jest.fn() }
            } }));
        const goodBtn = react_1.screen.getByRole('button', { name: 'Good response' });
        const badBtn = react_1.screen.getByRole('button', { name: 'Bad response' });
        const copyBtn = react_1.screen.getByRole('button', { name: 'Copy' });
        const editBtn = react_1.screen.getByRole('button', { name: 'Edit' });
        const shareBtn = react_1.screen.getByRole('button', { name: 'Share' });
        const downloadBtn = react_1.screen.getByRole('button', { name: 'Download' });
        const listenBtn = react_1.screen.getByRole('button', { name: 'Listen' });
        const buttons = [goodBtn, badBtn, copyBtn, editBtn, shareBtn, downloadBtn, listenBtn];
        buttons.forEach((button) => {
            expect(button).toBeTruthy();
        });
        yield user_event_1.default.click(goodBtn);
        expect(react_1.screen.getByRole('button', { name: 'Good response recorded' })).toHaveClass('pf-chatbot__button--response-action-clicked');
        let unclickedButtons = buttons.filter((button) => button !== goodBtn);
        unclickedButtons.forEach((button) => {
            expect(button).not.toHaveClass('pf-chatbot__button--response-action-clicked');
        });
        yield user_event_1.default.click(badBtn);
        expect(react_1.screen.getByRole('button', { name: 'Bad response recorded' })).toHaveClass('pf-chatbot__button--response-action-clicked');
        unclickedButtons = buttons.filter((button) => button !== badBtn);
        unclickedButtons.forEach((button) => {
            expect(button).not.toHaveClass('pf-chatbot__button--response-action-clicked');
        });
    }));
    it('should handle click outside of group of buttons correctly', () => __awaiter(void 0, void 0, void 0, function* () {
        // using message just so we have something outside the group that's rendered
        (0, react_1.render)((0, jsx_runtime_1.jsx)(Message_1.default, { name: "Bot", role: "bot", avatar: "", content: "I updated your account with those settings. You're ready to set up your first dashboard!", actions: {
                positive: {},
                negative: {}
            } }));
        const goodBtn = react_1.screen.getByRole('button', { name: 'Good response' });
        const badBtn = react_1.screen.getByRole('button', { name: 'Bad response' });
        expect(goodBtn).toBeTruthy();
        expect(badBtn).toBeTruthy();
        yield user_event_1.default.click(goodBtn);
        expect(react_1.screen.getByRole('button', { name: 'Good response recorded' })).toHaveClass('pf-chatbot__button--response-action-clicked');
        expect(badBtn).not.toHaveClass('pf-chatbot__button--response-action-clicked');
        yield user_event_1.default.click(badBtn);
        expect(react_1.screen.getByRole('button', { name: 'Bad response recorded' })).toHaveClass('pf-chatbot__button--response-action-clicked');
        expect(goodBtn).not.toHaveClass('pf-chatbot__button--response-action-clicked');
        yield user_event_1.default.click(react_1.screen.getByText("I updated your account with those settings. You're ready to set up your first dashboard!"));
        expect(goodBtn).not.toHaveClass('pf-chatbot__button--response-action-clicked');
        expect(badBtn).not.toHaveClass('pf-chatbot__button--response-action-clicked');
    }));
    it('should handle isClicked prop within group of buttons correctly', () => __awaiter(void 0, void 0, void 0, function* () {
        (0, react_1.render)((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: {
                positive: { 'data-testid': 'positive-btn', onClick: jest.fn(), isClicked: true },
                negative: { 'data-testid': 'negative-btn', onClick: jest.fn() }
            } }));
        expect(react_1.screen.getByTestId('positive-btn')).toHaveClass('pf-chatbot__button--response-action-clicked');
        expect(react_1.screen.getByTestId('negative-btn')).not.toHaveClass('pf-chatbot__button--response-action-clicked');
    }));
    it('should set "listen" button as active if its `isClicked` is true', () => __awaiter(void 0, void 0, void 0, function* () {
        (0, react_1.render)((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: {
                positive: { 'data-testid': 'positive-btn', onClick: jest.fn(), isClicked: false },
                negative: { 'data-testid': 'negative-btn', onClick: jest.fn(), isClicked: false },
                listen: { 'data-testid': 'listen-btn', onClick: jest.fn(), isClicked: true }
            } }));
        expect(react_1.screen.getByTestId('listen-btn')).toHaveClass('pf-chatbot__button--response-action-clicked');
        expect(react_1.screen.getByTestId('positive-btn')).not.toHaveClass('pf-chatbot__button--response-action-clicked');
        expect(react_1.screen.getByTestId('negative-btn')).not.toHaveClass('pf-chatbot__button--response-action-clicked');
    }));
    it('should prioritize "positive" when both "positive" and "negative" are set to clicked', () => __awaiter(void 0, void 0, void 0, function* () {
        (0, react_1.render)((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: {
                positive: { 'data-testid': 'positive-btn', onClick: jest.fn(), isClicked: true },
                negative: { 'data-testid': 'negative-btn', onClick: jest.fn(), isClicked: true }
            } }));
        // Positive button should take precendence
        expect(react_1.screen.getByTestId('positive-btn')).toHaveClass('pf-chatbot__button--response-action-clicked');
        expect(react_1.screen.getByTestId('negative-btn')).not.toHaveClass('pf-chatbot__button--response-action-clicked');
    }));
    it('should set an additional action button as active if it is initially clicked and no predefined are clicked', () => __awaiter(void 0, void 0, void 0, function* () {
        const [additionalActions] = CUSTOM_ACTIONS;
        const customActions = Object.assign({ positive: { 'data-testid': 'positive', onClick: jest.fn(), isClicked: false }, negative: { 'data-testid': 'negative', onClick: jest.fn(), isClicked: false } }, Object.keys(additionalActions).reduce((acc, actionKey) => {
            acc[actionKey] = Object.assign(Object.assign({}, additionalActions[actionKey]), { 'data-testid': actionKey, isClicked: actionKey === 'regenerate' });
            return acc;
        }, {}));
        (0, react_1.render)((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: customActions }));
        Object.keys(customActions).forEach((actionKey) => {
            if (actionKey === 'regenerate') {
                expect(react_1.screen.getByTestId(actionKey)).toHaveClass('pf-chatbot__button--response-action-clicked');
            }
            else {
                // Other actions should not have clicked class
                expect(react_1.screen.getByTestId(actionKey)).not.toHaveClass('pf-chatbot__button--response-action-clicked');
            }
        });
    }));
    it('should activate the clicked button and deactivate any previously active button', () => __awaiter(void 0, void 0, void 0, function* () {
        const actions = {
            positive: { 'data-testid': 'positive', onClick: jest.fn(), isClicked: false },
            negative: { 'data-testid': 'negative', onClick: jest.fn(), isClicked: true }
        };
        (0, react_1.render)((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: actions }));
        const negativeBtn = react_1.screen.getByTestId('negative');
        const positiveBtn = react_1.screen.getByTestId('positive');
        // negative button is initially clicked
        expect(negativeBtn).toHaveClass('pf-chatbot__button--response-action-clicked');
        expect(positiveBtn).not.toHaveClass('pf-chatbot__button--response-action-clicked');
        yield user_event_1.default.click(positiveBtn);
        // positive button should now have the clicked class
        expect(positiveBtn).toHaveClass('pf-chatbot__button--response-action-clicked');
        expect(negativeBtn).not.toHaveClass('pf-chatbot__button--response-action-clicked');
    }));
    it('should render buttons correctly', () => {
        ALL_ACTIONS.forEach(({ type, label }) => {
            (0, react_1.render)((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: { [type]: { onClick: jest.fn() } } }));
            expect(react_1.screen.getByRole('button', { name: label })).toBeTruthy();
        });
    });
    it('should be able to call onClick correctly', () => __awaiter(void 0, void 0, void 0, function* () {
        for (const { type, label } of ALL_ACTIONS) {
            const spy = jest.fn();
            (0, react_1.render)((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: { [type]: { onClick: spy } } }));
            yield user_event_1.default.click(react_1.screen.getByRole('button', { name: label }));
            expect(spy).toHaveBeenCalledTimes(1);
        }
    }));
    it('should swap clicked and non-clicked aria labels on click', () => __awaiter(void 0, void 0, void 0, function* () {
        for (const { type, label, clickedLabel } of ALL_ACTIONS) {
            (0, react_1.render)((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: { [type]: { onClick: jest.fn() } } }));
            expect(react_1.screen.getByRole('button', { name: label })).toBeTruthy();
            yield user_event_1.default.click(react_1.screen.getByRole('button', { name: label }));
            expect(react_1.screen.getByRole('button', { name: clickedLabel })).toBeTruthy();
        }
    }));
    it('should swap clicked and non-clicked tooltips on click', () => __awaiter(void 0, void 0, void 0, function* () {
        for (const { type, label, clickedLabel } of ALL_ACTIONS) {
            (0, react_1.render)((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: { [type]: { onClick: jest.fn() } } }));
            expect(react_1.screen.getByRole('button', { name: label })).toBeTruthy();
            yield user_event_1.default.click(react_1.screen.getByRole('button', { name: label }));
            expect(react_1.screen.getByRole('tooltip', { name: clickedLabel })).toBeTruthy();
        }
    }));
    it('should be able to change aria labels', () => {
        const actions = [
            { type: 'positive', ariaLabel: 'Thumbs up' },
            { type: 'negative', ariaLabel: 'Thumbs down' },
            { type: 'copy', ariaLabel: 'Copy the message' },
            { type: 'edit', ariaLabel: 'Edit this message' },
            { type: 'share', ariaLabel: 'Share it with friends' },
            { type: 'download', ariaLabel: 'Download your cool message' },
            { type: 'listen', ariaLabel: 'Listen up' }
        ];
        actions.forEach(({ type, ariaLabel }) => {
            (0, react_1.render)((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: { [type]: { onClick: jest.fn(), ariaLabel } } }));
            expect(react_1.screen.getByRole('button', { name: ariaLabel })).toBeTruthy();
        });
    });
    it('should be able to disable buttons', () => {
        ALL_ACTIONS.forEach(({ type, label }) => {
            (0, react_1.render)((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: { [type]: { onClick: jest.fn(), isDisabled: true } } }));
            expect(react_1.screen.getByRole('button', { name: label })).toBeDisabled();
        });
    });
    it('should be able to add class to buttons', () => {
        ALL_ACTIONS.forEach(({ type, label }) => {
            (0, react_1.render)((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: { [type]: { onClick: jest.fn(), className: 'test' } } }));
            expect(react_1.screen.getByRole('button', { name: label })).toHaveClass('test');
        });
    });
    it('should be able to add custom attributes to buttons', () => {
        ALL_ACTIONS_DATA_TEST.forEach(({ type, dataTestId }) => {
            (0, react_1.render)((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: { [type]: { onClick: jest.fn(), 'data-testid': dataTestId } } }));
            expect(react_1.screen.getByTestId(dataTestId)).toBeTruthy();
        });
    });
    it('should be able to add custom actions', () => {
        CUSTOM_ACTIONS.forEach((action) => {
            const key = Object.keys(action)[0];
            (0, react_1.render)((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: {
                    [key]: {
                        tooltipContent: action[key].tooltipContent,
                        onClick: action[key].onClick,
                        // doing this just because it's easier to test without a regex for the button name
                        ariaLabel: action[key].ariaLabel.toLowerCase(),
                        icon: action[key].icon,
                        'data-testid': action[key]
                    }
                } }));
            expect(react_1.screen.getByRole('button', { name: key })).toBeTruthy();
            expect(react_1.screen.getByTestId(action[key])).toBeTruthy();
        });
    });
    // we are testing for the reverse case already above
    it('should not deselect when clicking outside when persistActionSelection is true', () => __awaiter(void 0, void 0, void 0, function* () {
        (0, react_1.render)((0, jsx_runtime_1.jsx)(Message_1.default, { name: "Bot", role: "bot", avatar: "", content: "Test content", actions: {
                positive: {},
                negative: {}
            }, persistActionSelection: true }));
        const goodBtn = react_1.screen.getByRole('button', { name: 'Good response' });
        yield user_event_1.default.click(goodBtn);
        expect(react_1.screen.getByRole('button', { name: 'Good response recorded' })).toHaveClass('pf-chatbot__button--response-action-clicked');
        yield user_event_1.default.click(react_1.screen.getByText('Test content'));
        expect(react_1.screen.getByRole('button', { name: 'Good response recorded' })).toHaveClass('pf-chatbot__button--response-action-clicked');
    }));
    it('should switch selection to another button when persistActionSelection is true', () => __awaiter(void 0, void 0, void 0, function* () {
        (0, react_1.render)((0, jsx_runtime_1.jsx)(Message_1.default, { name: "Bot", role: "bot", avatar: "", content: "Test content", actions: {
                positive: {},
                negative: {}
            }, persistActionSelection: true }));
        const goodBtn = react_1.screen.getByRole('button', { name: 'Good response' });
        const badBtn = react_1.screen.getByRole('button', { name: 'Bad response' });
        yield user_event_1.default.click(goodBtn);
        expect(goodBtn).toHaveClass('pf-chatbot__button--response-action-clicked');
        yield user_event_1.default.click(badBtn);
        expect(badBtn).toHaveClass('pf-chatbot__button--response-action-clicked');
        expect(goodBtn).not.toHaveClass('pf-chatbot__button--response-action-clicked');
    }));
    it('should toggle off when clicking the same button when persistActionSelection is true', () => __awaiter(void 0, void 0, void 0, function* () {
        (0, react_1.render)((0, jsx_runtime_1.jsx)(Message_1.default, { name: "Bot", role: "bot", avatar: "", content: "Test content", actions: {
                positive: {},
                negative: {}
            }, persistActionSelection: true }));
        const goodBtn = react_1.screen.getByRole('button', { name: 'Good response' });
        yield user_event_1.default.click(goodBtn);
        expect(goodBtn).toHaveClass('pf-chatbot__button--response-action-clicked');
        yield user_event_1.default.click(goodBtn);
        expect(goodBtn).not.toHaveClass('pf-chatbot__button--response-action-clicked');
    }));
    it('should work with custom actions when persistActionSelection is true', () => __awaiter(void 0, void 0, void 0, function* () {
        const actions = {
            positive: { 'data-testid': 'positive', onClick: jest.fn() },
            negative: { 'data-testid': 'negative', onClick: jest.fn() },
            custom: {
                'data-testid': 'custom',
                onClick: jest.fn(),
                ariaLabel: 'Custom',
                tooltipContent: 'Custom action',
                icon: (0, jsx_runtime_1.jsx)(react_icons_1.DownloadIcon, {})
            }
        };
        (0, react_1.render)((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: actions, persistActionSelection: true }));
        const customBtn = react_1.screen.getByTestId('custom');
        yield user_event_1.default.click(customBtn);
        expect(customBtn).toHaveClass('pf-chatbot__button--response-action-clicked');
        yield user_event_1.default.click(customBtn);
        expect(customBtn).not.toHaveClass('pf-chatbot__button--response-action-clicked');
    }));
});
