import { mockMatchMedia, render, screen } from '../test-utils';
import { Edit } from '@transferwise/icons';
import Link from '../link';
import { ListItem } from './ListItem';

mockMatchMedia();

describe('ListItem', () => {
  const cb = () => {};
  const title = '__title__';
  const subtitle = '__subtitle__';
  const valueTitle = '__valueTitle__';
  const valueSubtitle = '__valueSubtitle__';
  const additionalInfo = '__additionalInfo__';
  const additionalInfoAction = '__infoAction__';
  const prompt = '__prompt__';
  const disabledPromptMessage = '__disabledPromptMessage__';
  const promptAction = '__promptAction__';
  const promptWithLink = (
    <>
      {prompt}
      <Link href="wise.com">{promptAction}</Link>
      {prompt}
    </>
  );
  const promptWithButton = (
    <>
      {prompt}
      {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events */}
      <Link onClick={cb}>{promptAction}</Link>
      {prompt}
    </>
  );

  describe('aria and a11y attributes', () => {
    it('sets id on the container', () => {
      render(<ListItem id="custom-id" title={title} />);
      expect(screen.getByRole('listitem')).toHaveAttribute('id', 'custom-id');
    });

    it('sets aria-describedby with correct IDs for fully interactive list item with prompt and additionalInfo', () => {
      render(
        <ListItem
          title="Title"
          subtitle="Subtitle"
          control={<ListItem.Button>Hello</ListItem.Button>}
          additionalInfo={<ListItem.AdditionalInfo>Additional Info</ListItem.AdditionalInfo>}
          prompt={<ListItem.Prompt sentiment="positive">Hello</ListItem.Prompt>}
        />,
      );
      const item = screen.getByRole('button');
      const describedBy = item.getAttribute('aria-describedby') || '';
      expect(describedBy).toMatch(/_additional-info/);
      expect(describedBy).toMatch(/_prompt/);
    });

    it('sets aria-describedby with correct IDs for partially interactive list item with title, subtitle, value, subvalue, prompt and additionalInfo', () => {
      render(
        <ListItem
          title="Title"
          subtitle="Subtitle"
          valueTitle="100"
          valueSubtitle="200"
          control={<ListItem.Button partiallyInteractive>Hello</ListItem.Button>}
          additionalInfo={<ListItem.AdditionalInfo>Additional Info</ListItem.AdditionalInfo>}
          prompt={<ListItem.Prompt sentiment="negative">Hello</ListItem.Prompt>}
        />,
      );
      const item = screen.getByRole('button');
      const describedBy = item.getAttribute('aria-describedby') || '';
      expect(describedBy).toMatch(/_additional-info/);
      expect(describedBy).toMatch(/_prompt/);
      expect(describedBy).toMatch(/_title/);
      expect(describedBy).toMatch(/_subtitle/);
      expect(describedBy).toMatch(/_value/);
      expect(describedBy).toMatch(/_value-subtitle/);
    });

    it('sets aria-disabled when disabled', () => {
      render(<ListItem title={title} disabled />);
      expect(screen.getByRole('listitem')).toHaveAttribute('aria-disabled', 'true');
    });

    describe('Switch', () => {
      describe('has accessible name when used with:', () => {
        it('title', () => {
          render(<ListItem title={title} control={<ListItem.Switch onClick={cb} />} />);

          expect(screen.getByRole('switch')).toHaveAccessibleName(title);
        });

        it('title and subtitle', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              control={<ListItem.Switch onClick={cb} />}
            />,
          );

          expect(screen.getByRole('switch')).toHaveAccessibleName(`${title} ${subtitle}`);
        });

        it('title, subtitle, and valueTitle', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              control={<ListItem.Switch onClick={cb} />}
            />,
          );

          expect(screen.getByRole('switch')).toHaveAccessibleName(
            `${title} ${subtitle} ${valueTitle}`,
          );
        });

        it('title, subtitle, valueTitle, and valueSubtitle', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              control={<ListItem.Switch onClick={cb} />}
            />,
          );

          expect(screen.getByRole('switch')).toHaveAccessibleName(
            `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
          );
        });

        it('title, subtitle, valueTitle, valueSubtitle and inverted layout', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              inverted
              control={<ListItem.Switch onClick={cb} />}
            />,
          );

          expect(screen.getByRole('switch')).toHaveAccessibleName(
            `${subtitle} ${title} ${valueSubtitle} ${valueTitle}`,
          );
        });

        it('title, subtitle, valueTitle, valueSubtitle, and non-interactive additionalInfo', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
              control={<ListItem.Switch onClick={cb} />}
            />,
          );
          const control = screen.getByRole('switch');
          expect(control).toHaveAccessibleName(
            `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
          );
          expect(control).toHaveAccessibleDescription(additionalInfo);
        });

        it('title, subtitle, valueTitle, valueSubtitle, non-interactive additionalInfo, and prompt', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
              prompt={<ListItem.Prompt>{prompt}</ListItem.Prompt>}
              control={<ListItem.Switch onClick={cb} />}
            />,
          );

          const control = screen.getByRole('switch');
          expect(control).toHaveAccessibleName(
            `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
          );
          expect(control).toHaveAccessibleDescription(`${additionalInfo} ${prompt}`);
        });

        it('title, subtitle, valueTitle, valueSubtitle, non-interactive additionalInfo, prompt, and inverted layout', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
              prompt={<ListItem.Prompt>{prompt}</ListItem.Prompt>}
              inverted
              control={<ListItem.Switch onClick={cb} />}
            />,
          );

          const control = screen.getByRole('switch');
          expect(screen.getByRole('switch')).toHaveAccessibleName(
            `${subtitle} ${title} ${valueSubtitle} ${valueTitle}`,
          );
          expect(control).toHaveAccessibleDescription(`${additionalInfo} ${prompt}`);
        });
      });
    });

    describe('Radio', () => {
      describe('has accessible name when used with:', () => {
        it('title', () => {
          render(
            <ListItem
              title={title}
              control={<ListItem.Radio name="payment" value="card" onChange={cb} />}
            />,
          );

          expect(screen.getByRole('radio')).toHaveAccessibleName(title);
        });

        it('title and subtitle', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              control={<ListItem.Radio name="payment" value="card" onChange={cb} />}
            />,
          );

          expect(screen.getByRole('radio')).toHaveAccessibleName(`${title} ${subtitle}`);
        });

        it('title, subtitle, and valueTitle', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              control={<ListItem.Radio name="payment" value="card" onChange={cb} />}
            />,
          );

          expect(screen.getByRole('radio')).toHaveAccessibleName(
            `${title} ${subtitle} ${valueTitle}`,
          );
        });

        it('title, subtitle, valueTitle, and valueSubtitle', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              control={<ListItem.Radio name="payment" value="card" onChange={cb} />}
            />,
          );

          expect(screen.getByRole('radio')).toHaveAccessibleName(
            `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
          );
        });

        it('title, subtitle, valueTitle, valueSubtitle and inverted layout', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              inverted
              control={<ListItem.Radio name="payment" value="card" onChange={cb} />}
            />,
          );

          expect(screen.getByRole('radio')).toHaveAccessibleName(
            `${subtitle} ${title} ${valueSubtitle} ${valueTitle}`,
          );
        });

        it('title, subtitle, valueTitle, valueSubtitle, and non-interactive additionalInfo', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
              control={<ListItem.Radio name="payment" value="card" onChange={cb} />}
            />,
          );

          const control = screen.getByRole('radio');
          expect(control).toHaveAccessibleName(
            `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
          );
          expect(control).toHaveAccessibleDescription(additionalInfo);
        });

        it('title, subtitle, valueTitle, valueSubtitle, non-interactive additionalInfo, and prompt', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
              prompt={<ListItem.Prompt>{prompt}</ListItem.Prompt>}
              control={<ListItem.Radio name="payment" value="card" onChange={cb} />}
            />,
          );

          const control = screen.getByRole('radio');
          expect(control).toHaveAccessibleName(
            `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
          );
          expect(control).toHaveAccessibleDescription(`${additionalInfo} ${prompt}`);
        });

        it('title, subtitle, valueTitle, valueSubtitle, non-interactive additionalInfo, prompt, and inverted layout', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
              prompt={<ListItem.Prompt>{prompt}</ListItem.Prompt>}
              inverted
              control={<ListItem.Radio name="payment" value="card" onChange={cb} />}
            />,
          );

          const control = screen.getByRole('radio');
          expect(control).toHaveAccessibleName(
            `${subtitle} ${title} ${valueSubtitle} ${valueTitle}`,
          );
          expect(control).toHaveAccessibleDescription(`${additionalInfo} ${prompt}`);
        });
      });
    });

    describe('Navigation', () => {
      describe('has accessible name when used with:', () => {
        it('title', () => {
          render(<ListItem title={title} control={<ListItem.Navigation href="/settings" />} />);

          expect(screen.getByRole('link')).toHaveAccessibleName(title);
        });

        it('title and subtitle', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              control={<ListItem.Navigation href="/settings" />}
            />,
          );

          expect(screen.getByRole('link')).toHaveAccessibleName(`${title} ${subtitle}`);
        });

        it('title, subtitle, and valueTitle', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              control={<ListItem.Navigation href="/settings" />}
            />,
          );

          expect(screen.getByRole('link')).toHaveAccessibleName(
            `${title} ${subtitle} ${valueTitle}`,
          );
        });

        it('title, subtitle, valueTitle, and valueSubtitle', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              control={<ListItem.Navigation href="/settings" />}
            />,
          );

          expect(screen.getByRole('link')).toHaveAccessibleName(
            `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
          );
        });

        it('title, subtitle, valueTitle, valueSubtitle and inverted layout', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              inverted
              control={<ListItem.Navigation href="/settings" />}
            />,
          );

          expect(screen.getByRole('link')).toHaveAccessibleName(
            `${subtitle} ${title} ${valueSubtitle} ${valueTitle}`,
          );
        });

        it('title, subtitle, valueTitle, valueSubtitle, and non-interactive additionalInfo', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
              control={<ListItem.Navigation href="/settings" />}
            />,
          );

          const control = screen.getByRole('link');
          expect(control).toHaveAccessibleName(
            `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
          );
          expect(control).toHaveAccessibleDescription(additionalInfo);
        });

        it('title, subtitle, valueTitle, valueSubtitle, non-interactive additionalInfo, and prompt', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
              prompt={<ListItem.Prompt>{prompt}</ListItem.Prompt>}
              control={<ListItem.Navigation href="/settings" />}
            />,
          );

          const control = screen.getByRole('link');
          expect(control).toHaveAccessibleName(
            `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
          );
          expect(control).toHaveAccessibleDescription(`${additionalInfo} ${prompt}`);
        });

        it('title, subtitle, valueTitle, valueSubtitle, non-interactive additionalInfo, prompt, and inverted layout', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
              prompt={<ListItem.Prompt>{prompt}</ListItem.Prompt>}
              inverted
              control={<ListItem.Navigation href="/settings" />}
            />,
          );

          const control = screen.getByRole('link');
          expect(control).toHaveAccessibleName(
            `${subtitle} ${title} ${valueSubtitle} ${valueTitle}`,
          );
          expect(control).toHaveAccessibleDescription(`${additionalInfo} ${prompt}`);
        });
      });
    });

    describe('Checkbox', () => {
      describe('has accessible name when used with:', () => {
        it('title', () => {
          render(<ListItem title={title} control={<ListItem.Checkbox onChange={cb} />} />);

          expect(screen.getByRole('checkbox')).toHaveAccessibleName(title);
        });

        it('title and subtitle', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              control={<ListItem.Checkbox onChange={cb} />}
            />,
          );

          expect(screen.getByRole('checkbox')).toHaveAccessibleName(`${title} ${subtitle}`);
        });

        it('title, subtitle, and valueTitle', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              control={<ListItem.Checkbox onChange={cb} />}
            />,
          );

          expect(screen.getByRole('checkbox')).toHaveAccessibleName(
            `${title} ${subtitle} ${valueTitle}`,
          );
        });

        it('title, subtitle, valueTitle, and valueSubtitle', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              control={<ListItem.Checkbox onChange={cb} />}
            />,
          );

          expect(screen.getByRole('checkbox')).toHaveAccessibleName(
            `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
          );
        });

        it('title, subtitle, valueTitle, valueSubtitle and inverted layout', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              inverted
              control={<ListItem.Checkbox onChange={cb} />}
            />,
          );

          expect(screen.getByRole('checkbox')).toHaveAccessibleName(
            `${subtitle} ${title} ${valueSubtitle} ${valueTitle}`,
          );
        });

        it('title, subtitle, valueTitle, valueSubtitle, and non-interactive additionalInfo', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
              control={<ListItem.Checkbox onChange={cb} />}
            />,
          );

          const control = screen.getByRole('checkbox');
          expect(control).toHaveAccessibleName(
            `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
          );
          expect(control).toHaveAccessibleDescription(additionalInfo);
        });

        it('title, subtitle, valueTitle, valueSubtitle, non-interactive additionalInfo, and prompt', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
              prompt={<ListItem.Prompt>{prompt}</ListItem.Prompt>}
              control={<ListItem.Checkbox onChange={cb} />}
            />,
          );

          const control = screen.getByRole('checkbox');
          expect(control).toHaveAccessibleName(
            `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
          );
          expect(control).toHaveAccessibleDescription(`${additionalInfo} ${prompt}`);
        });

        it('title, subtitle, valueTitle, valueSubtitle, non-interactive additionalInfo, prompt, and inverted layout', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
              prompt={<ListItem.Prompt>{prompt}</ListItem.Prompt>}
              inverted
              control={<ListItem.Checkbox onChange={cb} />}
            />,
          );

          const control = screen.getByRole('checkbox');
          expect(control).toHaveAccessibleName(
            `${subtitle} ${title} ${valueSubtitle} ${valueTitle}`,
          );
          expect(control).toHaveAccessibleDescription(`${additionalInfo} ${prompt}`);
        });
      });
    });

    describe('IconButton', () => {
      describe('Fully interactive', () => {
        it('title', () => {
          render(
            <ListItem
              title={title}
              control={
                <ListItem.IconButton onClick={cb}>
                  <Edit />
                </ListItem.IconButton>
              }
            />,
          );

          expect(screen.getByRole('button')).toHaveAccessibleName(title);
        });

        it('title and subtitle', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              control={
                <ListItem.IconButton onClick={cb}>
                  <Edit />
                </ListItem.IconButton>
              }
            />,
          );

          expect(screen.getByRole('button')).toHaveAccessibleName(`${title} ${subtitle}`);
        });

        it('title, subtitle, and valueTitle', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              control={
                <ListItem.IconButton onClick={cb}>
                  <Edit />
                </ListItem.IconButton>
              }
            />,
          );

          expect(screen.getByRole('button')).toHaveAccessibleName(
            `${title} ${subtitle} ${valueTitle}`,
          );
        });

        it('title, subtitle, valueTitle, and valueSubtitle', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              control={
                <ListItem.IconButton onClick={cb}>
                  <Edit />
                </ListItem.IconButton>
              }
            />,
          );

          expect(screen.getByRole('button')).toHaveAccessibleName(
            `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
          );
        });

        it('title, subtitle, valueTitle, valueSubtitle and inverted layout', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              inverted
              control={
                <ListItem.IconButton onClick={cb}>
                  <Edit />
                </ListItem.IconButton>
              }
            />,
          );

          expect(screen.getByRole('button')).toHaveAccessibleName(
            `${subtitle} ${title} ${valueSubtitle} ${valueTitle}`,
          );
        });

        it('title, subtitle, valueTitle, valueSubtitle, and non-interactive additionalInfo', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
              control={
                <ListItem.IconButton onClick={cb}>
                  <Edit />
                </ListItem.IconButton>
              }
            />,
          );

          const control = screen.getByRole('button');
          expect(control).toHaveAccessibleName(
            `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
          );
          expect(control).toHaveAccessibleDescription(additionalInfo);
        });

        it('title, subtitle, valueTitle, valueSubtitle, non-interactive additionalInfo, and prompt', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
              prompt={<ListItem.Prompt>{prompt}</ListItem.Prompt>}
              control={
                <ListItem.IconButton onClick={cb}>
                  <Edit />
                </ListItem.IconButton>
              }
            />,
          );

          const control = screen.getByRole('button');
          expect(control).toHaveAccessibleName(
            `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
          );
          expect(control).toHaveAccessibleDescription(`${additionalInfo} ${prompt}`);
        });

        it('title, subtitle, valueTitle, valueSubtitle, non-interactive additionalInfo, prompt, and inverted layout', () => {
          render(
            <ListItem
              title={title}
              subtitle={subtitle}
              valueTitle={valueTitle}
              valueSubtitle={valueSubtitle}
              additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
              prompt={<ListItem.Prompt>{prompt}</ListItem.Prompt>}
              inverted
              control={
                <ListItem.IconButton onClick={cb}>
                  <Edit />
                </ListItem.IconButton>
              }
            />,
          );

          const control = screen.getByRole('button');
          expect(control).toHaveAccessibleName(
            `${subtitle} ${title} ${valueSubtitle} ${valueTitle}`,
          );
          expect(control).toHaveAccessibleDescription(`${additionalInfo} ${prompt}`);
        });
      });

      describe('Partially interactive', () => {
        describe('has accessible name when used with:', () => {
          it('title', () => {
            render(
              <ListItem
                title={title}
                control={
                  <ListItem.IconButton partiallyInteractive onClick={cb}>
                    <Edit />
                  </ListItem.IconButton>
                }
              />,
            );

            expect(screen.getByRole('button')).toHaveAccessibleName(title);
          });

          it('title and subtitle', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                control={
                  <ListItem.IconButton partiallyInteractive onClick={cb}>
                    <Edit />
                  </ListItem.IconButton>
                }
              />,
            );

            expect(screen.getByRole('button')).toHaveAccessibleName(`${title} ${subtitle}`);
          });

          it('title, subtitle, and valueTitle', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                control={
                  <ListItem.IconButton partiallyInteractive onClick={cb}>
                    <Edit />
                  </ListItem.IconButton>
                }
              />,
            );

            expect(screen.getByRole('button')).toHaveAccessibleName(
              `${title} ${subtitle} ${valueTitle}`,
            );
          });

          it('title, subtitle, valueTitle, and valueSubtitle', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                control={
                  <ListItem.IconButton partiallyInteractive onClick={cb}>
                    <Edit />
                  </ListItem.IconButton>
                }
              />,
            );

            expect(screen.getByRole('button')).toHaveAccessibleName(
              `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
            );
          });

          it('title, subtitle, valueTitle, valueSubtitle and inverted layout', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                inverted
                control={
                  <ListItem.IconButton partiallyInteractive onClick={cb}>
                    <Edit />
                  </ListItem.IconButton>
                }
              />,
            );

            expect(screen.getByRole('button')).toHaveAccessibleName(
              `${subtitle} ${title} ${valueSubtitle} ${valueTitle}`,
            );
          });

          it('title, subtitle, valueTitle, valueSubtitle, and non-interactive additionalInfo', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
                control={
                  <ListItem.IconButton partiallyInteractive onClick={cb}>
                    <Edit />
                  </ListItem.IconButton>
                }
              />,
            );

            expect(screen.getByRole('button')).toHaveAccessibleName(
              `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
            );
            expect(screen.getByRole('button')).toHaveAccessibleDescription(additionalInfo);
          });

          it('title, subtitle, valueTitle, valueSubtitle, and additionalInfo with link action', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                additionalInfo={
                  <ListItem.AdditionalInfo
                    action={{
                      label: additionalInfoAction,
                      href: 'wise.com',
                    }}
                  >
                    {additionalInfo}
                  </ListItem.AdditionalInfo>
                }
                control={
                  <ListItem.IconButton partiallyInteractive onClick={cb}>
                    <Edit />
                  </ListItem.IconButton>
                }
              />,
            );

            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(
              `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
            );
            expect(control).toHaveAccessibleDescription(
              `${additionalInfo} ${additionalInfoAction}`,
            );
          });

          it('title, subtitle, valueTitle, valueSubtitle, and additionalInfo with button action', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                additionalInfo={
                  <ListItem.AdditionalInfo action={{ label: additionalInfoAction, onClick: cb }}>
                    {additionalInfo}
                  </ListItem.AdditionalInfo>
                }
                control={
                  <ListItem.IconButton partiallyInteractive onClick={cb}>
                    <Edit />
                  </ListItem.IconButton>
                }
              />,
            );

            const control = screen.getAllByRole('button')[0];
            expect(control).toHaveAccessibleName(
              `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
            );
            expect(control).toHaveAccessibleDescription(
              `${additionalInfo} ${additionalInfoAction}`,
            );
          });

          it('title, subtitle, valueTitle, valueSubtitle, non-interactive additionalInfo, and prompt', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
                prompt={<ListItem.Prompt>{prompt}</ListItem.Prompt>}
                control={
                  <ListItem.IconButton partiallyInteractive onClick={cb}>
                    <Edit />
                  </ListItem.IconButton>
                }
              />,
            );
            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(
              `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
            );
            expect(control).toHaveAccessibleDescription(`${additionalInfo} ${prompt}`);
          });

          it('title, subtitle, valueTitle, valueSubtitle, non-interactive additionalInfo, and prompt with inline link', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
                prompt={<ListItem.Prompt>{promptWithLink}</ListItem.Prompt>}
                control={
                  <ListItem.IconButton partiallyInteractive onClick={cb}>
                    <Edit />
                  </ListItem.IconButton>
                }
              />,
            );
            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(
              `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
            );
            expect(screen.getByRole('button')).toHaveAccessibleDescription(
              `${additionalInfo} ${prompt} ${promptAction} ${prompt}`,
            );
          });

          it('title, subtitle, valueTitle, valueSubtitle, non-interactive additionalInfo, and prompt with inline button', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
                prompt={<ListItem.Prompt>{promptWithButton}</ListItem.Prompt>}
                control={
                  <ListItem.IconButton partiallyInteractive onClick={cb}>
                    <Edit />
                  </ListItem.IconButton>
                }
              />,
            );

            const control = screen.getAllByRole('button')[0];
            expect(control).toHaveAccessibleName(
              `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
            );
            expect(control).toHaveAccessibleDescription(
              `${additionalInfo} ${prompt} ${promptAction} ${prompt}`,
            );
          });

          it('title, subtitle, valueTitle, valueSubtitle, non-interactive additionalInfo, prompt, and inverted layout', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
                prompt={<ListItem.Prompt>{prompt}</ListItem.Prompt>}
                inverted
                control={
                  <ListItem.IconButton partiallyInteractive onClick={cb}>
                    <Edit />
                  </ListItem.IconButton>
                }
              />,
            );

            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(
              `${subtitle} ${title} ${valueSubtitle} ${valueTitle}`,
            );
            expect(control).toHaveAccessibleDescription(`${additionalInfo} ${prompt}`);
          });
        });
      });
    });

    describe('Button', () => {
      describe('Fully interactive', () => {
        describe('has accessible name when used with:', () => {
          it('title', () => {
            render(
              <ListItem
                title={title}
                control={<ListItem.Button onClick={cb}>Save</ListItem.Button>}
              />,
            );

            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(title);
            expect(control).toHaveAccessibleDescription(`Save`);
          });

          it('title and subtitle', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                control={<ListItem.Button onClick={cb}>Save</ListItem.Button>}
              />,
            );

            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(`${title} ${subtitle}`);
            expect(control).toHaveAccessibleDescription(`Save`);
          });

          it('title, subtitle, and valueTitle', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                control={<ListItem.Button onClick={cb}>Save</ListItem.Button>}
              />,
            );

            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(`${title} ${subtitle} ${valueTitle}`);
            expect(control).toHaveAccessibleDescription(`Save`);
          });

          it('title, subtitle, valueTitle, and valueSubtitle', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                control={<ListItem.Button onClick={cb}>Save</ListItem.Button>}
              />,
            );

            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(
              `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
            );
            expect(control).toHaveAccessibleDescription(`Save`);
          });

          it('title, subtitle, valueTitle, valueSubtitle and inverted layout', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                inverted
                control={<ListItem.Button onClick={cb}>Save</ListItem.Button>}
              />,
            );

            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(
              `${subtitle} ${title} ${valueSubtitle} ${valueTitle}`,
            );
            expect(control).toHaveAccessibleDescription(`Save`);
          });

          it('title, subtitle, valueTitle, valueSubtitle, and non-interactive additionalInfo', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
                control={<ListItem.Button onClick={cb}>Save</ListItem.Button>}
              />,
            );

            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(
              `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
            );
            expect(control).toHaveAccessibleDescription(`Save ${additionalInfo}`);
          });

          it('title, subtitle, valueTitle, valueSubtitle, non-interactive additionalInfo, and prompt', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
                prompt={<ListItem.Prompt>{prompt}</ListItem.Prompt>}
                control={<ListItem.Button onClick={cb}>Save</ListItem.Button>}
              />,
            );

            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(
              `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
            );
            expect(control).toHaveAccessibleDescription(`Save ${additionalInfo} ${prompt}`);
          });

          it('title, subtitle, valueTitle, valueSubtitle, non-interactive additionalInfo, prompt, and inverted layout', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
                prompt={<ListItem.Prompt>{prompt}</ListItem.Prompt>}
                inverted
                control={<ListItem.Button onClick={cb}>Save</ListItem.Button>}
              />,
            );

            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(
              `${subtitle} ${title} ${valueSubtitle} ${valueTitle}`,
            );
            expect(control).toHaveAccessibleDescription(`Save ${additionalInfo} ${prompt}`);
          });
        });
      });

      describe('Partially interactive', () => {
        describe('has accessible name when used with:', () => {
          it('title', () => {
            render(
              <ListItem
                title={title}
                control={
                  <ListItem.Button partiallyInteractive onClick={cb}>
                    Save
                  </ListItem.Button>
                }
              />,
            );

            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(`Save`);
            expect(control).toHaveAccessibleDescription(title);
          });

          it('title and subtitle', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                control={
                  <ListItem.Button partiallyInteractive onClick={cb}>
                    Save
                  </ListItem.Button>
                }
              />,
            );

            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(`Save`);
            expect(control).toHaveAccessibleDescription(`${title} ${subtitle}`);
          });

          it('title, subtitle, and valueTitle', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                control={
                  <ListItem.Button partiallyInteractive onClick={cb}>
                    Save
                  </ListItem.Button>
                }
              />,
            );

            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(`Save`);
            expect(control).toHaveAccessibleDescription(`${title} ${subtitle} ${valueTitle}`);
          });

          it('title, subtitle, valueTitle, and valueSubtitle', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                control={
                  <ListItem.Button partiallyInteractive onClick={cb}>
                    Save
                  </ListItem.Button>
                }
              />,
            );

            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(`Save`);
            expect(control).toHaveAccessibleDescription(
              `${title} ${subtitle} ${valueTitle} ${valueSubtitle}`,
            );
          });

          it('title, subtitle, valueTitle, valueSubtitle and inverted layout', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                inverted
                control={
                  <ListItem.Button partiallyInteractive onClick={cb}>
                    Save
                  </ListItem.Button>
                }
              />,
            );

            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(`Save`);
            expect(control).toHaveAccessibleDescription(
              `${subtitle} ${title} ${valueSubtitle} ${valueTitle}`,
            );
          });

          it('title, subtitle, valueTitle, valueSubtitle, and non-interactive additionalInfo', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
                control={
                  <ListItem.Button partiallyInteractive onClick={cb}>
                    Save
                  </ListItem.Button>
                }
              />,
            );

            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(`Save`);
            expect(control).toHaveAccessibleDescription(
              `${title} ${subtitle} ${valueTitle} ${valueSubtitle} ${additionalInfo}`,
            );
          });

          it('title, subtitle, valueTitle, valueSubtitle, and additionalInfo with link action', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                additionalInfo={
                  <ListItem.AdditionalInfo
                    action={{
                      label: additionalInfoAction,
                      href: 'wise.com',
                    }}
                  >
                    {additionalInfo}
                  </ListItem.AdditionalInfo>
                }
                control={
                  <ListItem.Button partiallyInteractive onClick={cb}>
                    Save
                  </ListItem.Button>
                }
              />,
            );

            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(`Save`);
            expect(control).toHaveAccessibleDescription(
              `${title} ${subtitle} ${valueTitle} ${valueSubtitle} ${additionalInfo} ${additionalInfoAction}`,
            );
          });

          it('title, subtitle, valueTitle, valueSubtitle, and additionalInfo with button action', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                additionalInfo={
                  <ListItem.AdditionalInfo action={{ label: additionalInfoAction, onClick: cb }}>
                    {additionalInfo}
                  </ListItem.AdditionalInfo>
                }
                control={
                  <ListItem.Button partiallyInteractive onClick={cb}>
                    Save
                  </ListItem.Button>
                }
              />,
            );

            const control = screen.getAllByRole('button')[0];
            expect(control).toHaveAccessibleName(`Save`);
            expect(control).toHaveAccessibleDescription(
              `${title} ${subtitle} ${valueTitle} ${valueSubtitle} ${additionalInfo} ${additionalInfoAction}`,
            );
          });

          it('title, subtitle, valueTitle, valueSubtitle, non-interactive additionalInfo, and prompt', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
                prompt={<ListItem.Prompt>{prompt}</ListItem.Prompt>}
                control={
                  <ListItem.Button partiallyInteractive onClick={cb}>
                    Save
                  </ListItem.Button>
                }
              />,
            );

            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(`Save`);
            expect(control).toHaveAccessibleDescription(
              `${title} ${subtitle} ${valueTitle} ${valueSubtitle} ${additionalInfo} ${prompt}`,
            );
          });

          it('title, subtitle, valueTitle, valueSubtitle, non-interactive additionalInfo, and prompt with inline link', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
                prompt={<ListItem.Prompt>{promptWithLink}</ListItem.Prompt>}
                control={
                  <ListItem.Button partiallyInteractive onClick={cb}>
                    Save
                  </ListItem.Button>
                }
              />,
            );

            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(`Save`);
            expect(control).toHaveAccessibleDescription(
              `${title} ${subtitle} ${valueTitle} ${valueSubtitle} ${additionalInfo} ${prompt} ${promptAction} ${prompt}`,
            );
          });

          it('title, subtitle, valueTitle, valueSubtitle, non-interactive additionalInfo, and prompt with inline button', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
                prompt={<ListItem.Prompt>{promptWithButton}</ListItem.Prompt>}
                control={
                  <ListItem.Button partiallyInteractive onClick={cb}>
                    Save
                  </ListItem.Button>
                }
              />,
            );

            const control = screen.getAllByRole('button')[0];
            expect(control).toHaveAccessibleName(`Save`);
            expect(control).toHaveAccessibleDescription(
              `${title} ${subtitle} ${valueTitle} ${valueSubtitle} ${additionalInfo} ${prompt} ${promptAction} ${prompt}`,
            );
          });

          it('title, subtitle, valueTitle, valueSubtitle, non-interactive additionalInfo, prompt, and inverted layout', () => {
            render(
              <ListItem
                title={title}
                subtitle={subtitle}
                valueTitle={valueTitle}
                valueSubtitle={valueSubtitle}
                additionalInfo={<ListItem.AdditionalInfo>{additionalInfo}</ListItem.AdditionalInfo>}
                prompt={<ListItem.Prompt>{prompt}</ListItem.Prompt>}
                inverted
                control={
                  <ListItem.Button partiallyInteractive onClick={cb}>
                    Save
                  </ListItem.Button>
                }
              />,
            );

            const control = screen.getByRole('button');
            expect(control).toHaveAccessibleName(`Save`);
            expect(control).toHaveAccessibleDescription(
              `${subtitle} ${title} ${valueSubtitle} ${valueTitle} ${additionalInfo} ${prompt}`,
            );
          });
        });
      });
    });
  });

  describe('spotlight', () => {
    it('only fully interactive variant can have spotlight:active', () => {
      render(<ListItem title="Test Title" spotlight="active" control={<ListItem.Navigation />} />);
      const listItem = screen.getByRole('listitem');
      expect(listItem).toHaveClass('wds-list-item-interactive');
      expect(listItem).toHaveClass('wds-list-item-spotlight-active');
      expect(listItem.querySelector('.wds-list-item-spotlight__border')).not.toBeInTheDocument();
    });

    it('only fully interactive variant can have spotlight:inactive', () => {
      render(
        <ListItem
          title="Test Title"
          spotlight="inactive"
          control={<ListItem.Switch onClick={cb} />}
        />,
      );
      const listItem = screen.getByRole('listitem');
      expect(listItem).toHaveClass('wds-list-item-interactive');
      expect(listItem).toHaveClass('wds-list-item-spotlight-inactive');
      expect(listItem.querySelector('.wds-list-item-spotlight__border')).toBeInTheDocument();
    });

    it('non interactive variant cannot have spotlight', () => {
      render(<ListItem title="Test Title" spotlight="inactive" />);
      const listItem = screen.getByRole('listitem');
      expect(listItem).toHaveClass('wds-list-item-non-interactive');
      expect(listItem).not.toHaveClass('wds-list-item-interactive');
      expect(listItem).not.toHaveClass('wds-list-item-spotlight-inactive');
      expect(listItem).not.toHaveClass('wds-list-item-spotlight-active');
      expect(listItem.querySelector('.wds-list-item-spotlight__border')).not.toBeInTheDocument();
    });
  });

  describe('disable states', () => {
    describe('short-lived', () => {
      it('should override existing prompt if disabled and disabledPromptMessage are set', () => {
        render(
          <ListItem
            title="Test Title"
            prompt={<ListItem.Prompt>{prompt}</ListItem.Prompt>}
            disabled
            disabledPromptMessage={disabledPromptMessage}
          />,
        );
        expect(screen.queryByText(prompt)).not.toBeInTheDocument();
        expect(screen.getByText(disabledPromptMessage)).toBeInTheDocument();
        expect(
          screen.getByTestId('InlinePrompt_Muted').parentNode?.parentNode?.parentNode,
        ).toHaveAttribute('id', expect.stringMatching(/_prompt$/));
      });

      it('should render muted prompt if disabled and disabledPromptMessage are set', () => {
        render(
          <ListItem title="Test Title" disabled disabledPromptMessage={disabledPromptMessage} />,
        );
        expect(screen.getByText(disabledPromptMessage)).toBeInTheDocument();
        expect(
          screen.getByTestId('InlinePrompt_Muted').parentNode?.parentNode?.parentNode,
        ).toHaveAttribute('id', expect.stringMatching(/_prompt$/));
      });
    });
  });
});
