import { createAppLocalVue, waitNT } from '@/../tests/utils' // should be the first to implement default mocks
import ChangePassword from '../landing/components/ChangePassword'
import { mount } from '@vue/test-utils'
import flushPromises from 'flush-promises'
import { loggedOutStore } from '@/../tests/factories/auth-store'
import store from '@/store'
import router from '@/router'

const localVue = createAppLocalVue()

describe('Login - Landing - Change Password', () => {
  describe('isChangePassword Prop Is True', () => {
    let wrapper, changePassword

    beforeEach(async () => {
      changePassword = jest.fn().mockImplementation(() => Promise.resolve(true))

      wrapper = mount(ChangePassword, {
        localVue,
        store,
        router,
        methods: {
          changePassword,
        },
        computed: {
          getLoggedInUser: () => ({ id: 1 }),
        },
      })

      await flushPromises()
    })

    it('Should display change password fields if isChangePassword prop is true', async () => {
      expect(wrapper.vm.$props.isChangePassword).toBeTruthy()
      expect(wrapper.isVueInstance()).toBeTruthy()
    })

    it('Should validate fields', async () => {
      wrapper.find({ ref: 'submitButton' }).trigger('click')

      await waitNT(wrapper.vm)
      expect(wrapper.vm.$validator.errors.any()).toBe(true)
      expect(changePassword).not.toBeCalled()
    })

    it('Should validate strong password', async () => {
      wrapper.find({ ref: 'currentPassword' }).setValue('password')
      wrapper.find({ ref: 'newPassword' }).setValue('password123')
      wrapper.find({ ref: 'confirmNewPassword' }).setValue('password123')
      wrapper.find({ ref: 'submitButton' }).trigger('click')

      await flushPromises()

      expect(wrapper.vm.$validator.errors.any()).toBe(true)
    })

    it('Should validate current password and new password should not match', async () => {
      wrapper.find({ ref: 'currentPassword' }).setValue('passWORD123')
      wrapper.find({ ref: 'newPassword' }).setValue('passWORD123')
      wrapper.find({ ref: 'confirmNewPassword' }).setValue('passWORD123')
      wrapper.find({ ref: 'submitButton' }).trigger('click')

      await flushPromises()

      expect(wrapper.find('.alert')).toBeTruthy()
      expect(wrapper.vm.$data.errSamePassword).toBeTruthy()
      expect(wrapper.find('.alert').text()).toContain(wrapper.vm.$data.errSamePassword)
    })

    it('Should call changePassword on valid form', async () => {
      wrapper.find({ ref: 'currentPassword' }).setValue('passWORD123')
      wrapper.find({ ref: 'newPassword' }).setValue('passWORD1234')
      wrapper.find({ ref: 'confirmNewPassword' }).setValue('passWORD1234')
      wrapper.find({ ref: 'submitButton' }).trigger('click')

      await flushPromises()

      expect(changePassword).toBeCalledWith({
        user_id: 1,
        currentPassword: 'passWORD123',
        newPassword: 'passWORD1234',
        retypeNewPassword: 'passWORD1234',
      })
    })
  })

  describe('isChangePassword Prop Is False', () => {
    let wrapper, changePassword

    beforeEach(async () => {
      changePassword = jest.fn().mockImplementation(() => Promise.resolve(true))

      wrapper = mount(ChangePassword, {
        localVue,
        store,
        router,
        methods: {
          changePassword,
        },
        computed: {
          getLoggedInUser: () => ({ id: 1 }),
        },
        props: {
          isChangePassword: false,
        },
      })

      await flushPromises()
    })

    it('Should validate fields', async () => {
      wrapper.find({ ref: 'submitButton' }).trigger('click')

      await waitNT(wrapper.vm)
      expect(wrapper.vm.$validator.errors.any()).toBe(true)
      expect(changePassword).not.toBeCalled()
    })

    it('Should validate strong password', async () => {
      wrapper.find({ ref: 'newPassword' }).setValue('password123')
      wrapper.find({ ref: 'confirmNewPassword' }).setValue('password123')
      wrapper.find({ ref: 'submitButton' }).trigger('click')

      await flushPromises()

      expect(wrapper.vm.$validator.errors.any()).toBe(true)
    })

    it('Should call changePassword on valid form', async () => {
      wrapper.find({ ref: 'newPassword' }).setValue('passWORD1234')
      wrapper.find({ ref: 'confirmNewPassword' }).setValue('passWORD1234')
      wrapper.find({ ref: 'submitButton' }).trigger('click')

      await flushPromises()

      expect(changePassword).toBeCalledWith({
        user_id: 1,
        currentPassword: '',
        newPassword: 'passWORD1234',
        retypeNewPassword: 'passWORD1234',
      })
    })
  })
})
