import React from 'react'

import { slotify } from '../slotify'

const Foo = React.forwardRef(function Foo() {
  return <div />
})
const Bar = React.forwardRef(function Bar() {
  return <div />
})
const Baz = React.forwardRef(function Baz() {
  return <div />
})
const Unexpected = React.forwardRef(function Fatal() {
  return <div />
})

describe('slotify', () => {
  it('should display slot children if encountered', () => {
    const slots = slotify(
      [
        <Foo>
          <div id="foo-child" />
        </Foo>,
        <Bar>
          <div id="bar-child" />
        </Bar>,
        <Baz bazattr="xyz" />,
      ],
      {
        foo: Foo,
        bar: Bar,
      }
    )

    expect(slots).toEqual({
      foo: {
        slotProps: {},
        slotRef: null,
        slotChildren: <div id="foo-child" />,
      },
      bar: {
        slotProps: {},
        slotRef: null,
        slotChildren: <div id="bar-child" />,
      },
    })
  })

  it('should display only those slots that are expected to see', () => {
    const slots = slotify(
      [
        <Foo ref={{ fooref: true }} fooattr="123">
          <div id="foo-child" />
        </Foo>,
        <Bar ref={{ barref: true }} barattr="abc">
          <div id="bar-child" />
        </Bar>,
        <Unexpected />,
      ],
      {
        foo: Foo,
        bar: Bar,
      }
    )

    expect(slots).toEqual({
      foo: {
        slotProps: {
          fooattr: '123',
        },
        slotRef: {
          fooref: true,
        },
        slotChildren: <div id="foo-child" />,
      },
      bar: {
        slotProps: {
          barattr: 'abc',
        },
        slotRef: {
          barref: true,
        },
        slotChildren: <div id="bar-child" />,
      },
    })
  })

  it('should not display slots that are not encountered among the children', () => {
    const slots = slotify(
      [
        <Foo>
          <div id="foo-child" />
        </Foo>,
        <Bar>
          <div />
        </Bar>,
        <Baz>
          <div />
        </Baz>,
      ],
      {
        foo: Foo,
      }
    )

    expect(slots).toEqual({
      foo: {
        slotProps: {},
        slotRef: null,
        slotChildren: <div id="foo-child" />,
      },
    })
  })

  it('should return slot props', () => {
    const slots = slotify([<Foo fooattr="123" />], {
      foo: Foo,
    })

    expect(slots.foo).toEqual({
      slotProps: {
        fooattr: '123',
      },
      slotRef: null,
    })
  })

  it('should return slot ref', () => {
    const slots = slotify([<Bar ref={{ barref: true }} />], {
      bar: Bar,
    })

    expect(slots.bar).toEqual({
      slotProps: {},
      slotRef: {
        barref: true,
      },
    })
  })

  it('should return empty props object if the slot container does not have props', () => {
    const slots = slotify([<Baz />], {
      baz: Baz,
    })

    expect(slots.baz).toEqual({
      slotProps: {},
      slotRef: null,
    })
  })
})
