jest.unmock('chalk')
jest.mock('deepmerge')
jest.mock('fs')
jest.mock('log-symbols')
jest.mock('gulp-notify', () => {
  const gulpNotify: any = {}
  const onError = jest.fn()
  gulpNotify.onError = onError.mockReturnValue(onError)
  return gulpNotify
})
jest.mock('@babel/code-frame', () => ({
  codeFrameColumns: jest.fn(),
}))

import * as babelCodeFrame from '@babel/code-frame'
import * as notify from 'gulp-notify'
import {
  arrayMerge,
  checkAndLabel,
  errorDisplayHelper,
  esWbformatter,
  getFirstValidObject,
  getFrameColumns,
  getWbMessage,
  handleErrors,
  isChildOf,
  pathToUrl,
  setDisplayName,
  sureLazyImport,
} from '../../gulpfile.ts/lib/utils'

describe('arrayMerge', () => {
  it('should merge arrays', () => {
    const result = arrayMerge([1], [2], {
      isMergeableObject: () => false,
    })
    expect(result).toMatchObject([1, 2])
  })
})

describe('checkAndLabel', () => {
  it('should set the name', () => {
    const testFunc: any = () => {
      return 1
    }
    checkAndLabel(testFunc, 'hello')
    expect(testFunc.displayName).toEqual('hello')
  })
  it('should throw an error if a non-function is supplied', () => {
    try {
      checkAndLabel(false, 'hello')
    } catch (e) {
      expect(e).toBeTruthy()
    }
  })
})
describe('setDisplayName', () => {
  it('should set the name', () => {
    const testFunc: any = () => {
      return 1
    }
    setDisplayName(testFunc, 'hello')
    expect(testFunc.displayName).toEqual('hello')
  })
})

describe('errorDisplayHelper', () => {
  it('should have error and warning configs', () => {
    expect(errorDisplayHelper.error).toBeTruthy()
    expect(errorDisplayHelper.warning).toBeTruthy()
  })
})
describe('esWbformatter', () => {
  it('should return a function', () => {
    const result = esWbformatter({})
    expect(typeof result).toEqual('function')
  })
})
describe('getFirstValidObject', () => {
  it('should getFirstValidObject', () => {
    const result = getFirstValidObject(false, 'a', 'b', { hello: 1 })
    expect(result).toMatchObject({ hello: 1 })
  })
})
describe('getFrameColumns', () => {
  it('should getFrameColumns', () => {
    const spyCodeFrameColumns = jest.spyOn(babelCodeFrame, 'codeFrameColumns')
    spyCodeFrameColumns.mockReturnValue('hello \n trial \n test')
    const result = getFrameColumns('raw', {
      character: 'c',
      line: 1,
    })
    expect(spyCodeFrameColumns).toHaveBeenCalledWith(
      'raw',
      { start: { line: 1, column: 'c' } },
      { highlightCode: true }
    )
    expect(result).toContain('hello')
    expect(result).toContain('trial')
    expect(result).toContain('test')
  })
})
describe('getWbMessage', () => {
  it('should getWbMessage', () => {
    const result = getWbMessage({
      messageColor: {
        bold: jest.fn(),
        underline: jest.fn(),
      },
    })

    expect(typeof result).toBe('string')
  })
})

describe('handleErrors', () => {
  it('should call notify', () => {
    handleErrors('error')
    const spyOnError = jest.spyOn(notify, 'onError')
    expect(spyOnError).toHaveBeenCalled()
  })
})

describe('isChildOf', () => {
  it('should return true if child belongs to parent', () => {
    const result = isChildOf('hello/bello', 'hello')
    expect(result).toBeTruthy()
  })
  it('should return false if child does not belong to the parent', () => {
    const result = isChildOf('hello/bello', 'tee')
    expect(result).toBeFalsy()
  })
  it('should return false if child matches the parent', () => {
    const result = isChildOf('hello', 'hello')
    expect(result).toBeFalsy()
  })
})

describe('pathToUrl', () => {
  it('should replace slashes', () => {
    const result = pathToUrl('a\\b\\c')
    expect(result).toEqual('a/b/c')
  })
})

describe('sureLazyImport', () => {
  it('should be a lazy import function', () => {
    expect(typeof sureLazyImport).toBe('function')
  })
})
