" Tests for GetLatestMNVScripts plugin

" mnv feature
set nocp
set cpo&mnv

" constants
const s:dotmnv= has("win32") ? "mnvfiles" : ".mnv"
const s:scriptdir = $"{$HOME}/{s:dotmnv}/GetLatest"
const s:mnvdir = expand("<script>:h:h:h")
const s:packages = {
    \ 'vmb': {
        \ 'spec': '4979 1 :AutoInstall: AnsiEsc.mnv',
        \ 'files': ['plugin/AnsiEscPlugin.mnv', 'autoload/AnsiEsc.mnv']
        \ },
    \ 'mnv.bz2': {
        \ 'spec': '514 1 :AutoInstall: mrswin.mnv',
        \ 'files': ['plugin/mrswin.mnv']
        \ },
    \ 'vba.gz': {
        \ 'spec': '120 1 :AutoInstall: Decho.mnv',
        \ 'package': 'GetLatest/Installed/Decho.vba',
        \ 'files': ['plugin/Decho.mnv', 'syntax/Decho.mnv']
        \ },
    \ 'tar.xz': {
        \ 'spec': '5632 1 :AutoInstall: dumpx',
        \ 'package': 'GetLatest/Installed/dumpx.tar',
        \ 'files': ['dumpx/plugin/dumpx.mnv', 'dumpx/doc/dumpx.txt']
        \ }
    \ }

" Before each test recreate the .mnv dir structure expected by GLVS and load the plugin
func SetUp()

    " add the required GetLatest dir (note $HOME is a dummy)
    call mkdir(s:scriptdir, "p")
    let &runtimepath = $"{$HOME}/{s:dotmnv},{s:mnvdir}/runtime"

    " add plugin dir
    call mkdir($"{$HOME}/{s:dotmnv}/plugin")

    " doc file is required for the packages which use :helptags
    let docdir = $"{$HOME}/{s:dotmnv}/doc"
    call mkdir(docdir, "p")
    exe $"split {docdir}/tags"
    w!
    bwipe!

    " load required plugins, getscript.mnv would be loaded manually by the test
    " (instead of relying on autoload) because set up depends on shell selection
    runtime plugin/mnvballPlugin.mnv
    runtime plugin/getscriptPlugin.mnv
endfunc

func CheckTool(tool)
    " define tools location
    if has('win32')
        if executable('git')
           let git_path = trim(system('powershell -Command "Split-Path (Split-Path (gcm git).Source)"'))
        endif

        if a:tool == 'bunzip2'
          if executable('bunzip2')
              let g:GetLatestMNVScripts_bunzip2= "bunzip2"
          elseif executable('7z')
              let g:GetLatestMNVScripts_bunzip2= "7z x"
          elseif exists('git_path')
              let g:GetLatestMNVScripts_bunzip2= $'{git_path}\usr\bin\bunzip2'
          else
              throw "Skipped: Missing tool to decompress .bz2 files"
          endif
        endif

        if a:tool == 'gunzip'
          if executable('gunzip')
              let g:GetLatestMNVScripts_gunzip= "gunzip"
          elseif executable('7z')
              let g:GetLatestMNVScripts_gunzip="7z e"
          elseif exists('git_path')
              let g:GetLatestMNVScripts_gunzip= $'{git_path}\usr\bin\gunzip'
          else
              throw "Skipped: Missing tool to decompress .gz files"
          endif
        endif

        if a:tool == 'unxz'
          if executable('unxz')
              let g:GetLatestMNVScripts_unxz= "unxz"
          elseif executable('7z')
              let g:GetLatestMNVScripts_unxz="7z x"
          elseif exists('git_path')
              let g:GetLatestMNVScripts_unxz= $'{git_path}\mingw64\bin\unxz'
          else
              throw "Skipped: Missing tool to decompress .xz files"
          endif
        endif
    else
        " Mac or Unix
        if a:tool == 'bunzip2'
            if executable('bunzip2')
                let g:GetLatestMNVScripts_bunzip2= "bunzip2"
            else
              throw "Skipped: Missing tool to decompress .bz2 files"
            endif
        endif

        if a:tool == 'gunzip'
            if executable('gunzip')
                let g:GetLatestMNVScripts_gunzip= "gunzip"
            else
                throw "Skipped: Missing tool to decompress .bz2 files"
            endif
        endif

        if a:tool == 'unxz'
            if executable('unxz')
                let g:GetLatestMNVScripts_unxz= "unxz"
            else
                throw "Skipped: Missing tool to decompress .xz files"
            endif
        endif
   endif
endfunc

" After each test remove the contents of the .mnv dir and reset the script
func TearDown()
    call delete($"{$HOME}/{s:dotmnv}", "rf")

    " getscript.mnv include guard
    unlet! g:loaded_getscript g:loaded_getscriptPlugin
    " remove all globals (shell dependents)
    let script_globals = keys(g:)
    call filter(script_globals, 'v:val =~ "GetLatestMNVScripts_"')
    if len(script_globals)
        call map(script_globals, '"g:" . v:val')
        exe "unlet " . script_globals->join()
    endif
endfunc

" Ancillary functions

func SetShell(shell)
    " select different shells
    if a:shell == "default"
        set shell& shellcmdflag& shellxquote& shellpipe& shellredir&
    elseif a:shell == "powershell" " help dos-powershell
        " powershell desktop is windows only
        if !has("win32")
            throw 'Skipped: powershell desktop is missing'
        endif
        set shell=powershell shellcmdflag=-NoProfile\ -Command shellxquote=\"
        set shellpipe=2>&1\ \|\ Out-File\ -Encoding\ default shellredir=2>&1\ \|\ Out-File\ -Encoding\ default
    elseif a:shell == "pwsh" " help dos-powershell
        " powershell core works crossplatform
        if !executable("pwsh")
            throw 'Skipped: powershell core is missing'
        endif
        set shell=pwsh shellcmdflag=-NoProfile\ -c shellpipe=>%s\ 2>&1 shellredir=>%s\ 2>&1
        if has("win32")
            set shellxquote=\"
        else
            set shellxquote=
        endif
    else
        call assert_report("Trying to select and unknown shell")
    endif

    " reload script to force new shell options
    runtime autoload/getscript.mnv
endfunc

func SelectScript(package)
    " add the corresponding file
    exe $"split {s:scriptdir}/GetLatestMNVScripts.dat"
    let scripts =<< trim END
        ScriptID SourceID Filename
        --------------------------
    END
    call setline(1, scripts)
    call append(line('$'), s:packages[a:package]['spec'])
    w!
    bwipe!
endfunc

func ValidateInstall(package)
    " check the package is expected
    call assert_true(s:packages->has_key(a:package), "This package is unexpected")

    " check if installation work out
    if s:packages[a:package]->has_key('package')
        let check = filereadable($"{$HOME}/{s:dotmnv}/".s:packages[a:package]['package'])
        call assert_true(check, "The plugin was not downloaded")
    endif

    call assert_true(s:packages[a:package]->has_key('files'), "This package lacks validation files")
    for file in s:packages[a:package]['files']
        let check = filereadable($"{$HOME}/{s:dotmnv}/".file)
        call assert_true(check, "The plugin was not installed")
    endfor
endfunc

" Tests
"
func Test_glvs_default_vmb()
    " select different shells
    call SetShell('default')

    " add the corresponding script
    call SelectScript('vmb')

    " load the plugins specified
    GLVS

    call ValidateInstall('vmb')
endfunc

func Test_glvs_pwsh_vmb()
    " select different shells
    call SetShell('pwsh')

    " add the corresponding script
    call SelectScript('vmb')

    " load the plugins specified
    GLVS

    call ValidateInstall('vmb')
endfunc

func Test_glvs_powershell_vmb()
    " select different shells
    call SetShell('powershell')

    " add the corresponding script
    call SelectScript('vmb')

    " load the plugins specified
    GLVS

    call ValidateInstall('vmb')
endfunc

func Test_glvs_default_mnv_bz2()
    call CheckTool('bunzip2')

    " select different shells
    call SetShell('default')

    " add the corresponding script
    call SelectScript('mnv.bz2')

    " load the plugins specified
    GLVS

    call ValidateInstall('mnv.bz2')
endfunc

func Test_glvs_powershell_mnv_bz2()
    call CheckTool('bunzip2')

    " select different shells
    call SetShell('powershell')

    " add the corresponding script
    call SelectScript('mnv.bz2')

    " load the plugins specified
    GLVS

    call ValidateInstall('mnv.bz2')
endfunc

func Test_glvs_pwsh_mnv_bz2()
    call CheckTool('bunzip2')

    " select different shells
    call SetShell('pwsh')

    " add the corresponding script
    call SelectScript('mnv.bz2')

    " load the plugins specified
    GLVS

    call ValidateInstall('mnv.bz2')
endfunc

func Test_glvs_default_vba_gz()
    call CheckTool('gunzip')

    " select different shells
    call SetShell('default')

    " add the corresponding script
    call SelectScript('vba.gz')

    " load the plugins specified
    GLVS

    call ValidateInstall('vba.gz')
endfunc

func Test_glvs_powershell_vba_gz()
    call CheckTool('gunzip')

    " select different shells
    call SetShell('powershell')

    " add the corresponding script
    call SelectScript('vba.gz')

    " load the plugins specified
    GLVS

    call ValidateInstall('vba.gz')
endfunc

func Test_glvs_pwsh_vba_gz()
    call CheckTool('gunzip')

    " select different shells
    call SetShell('pwsh')

    " add the corresponding script
    call SelectScript('vba.gz')

    " load the plugins specified
    GLVS

    call ValidateInstall('vba.gz')
endfunc

func Test_glvs_default_tar_xz()
    call CheckTool('unxz')

    " select different shells
    call SetShell('default')

    " add the corresponding script
    call SelectScript('tar.xz')

    " load the plugins specified
    GLVS

    call ValidateInstall('tar.xz')
endfunc

func Test_glvs_powershell_tar_xz()
    call CheckTool('unxz')

    " select different shells
    call SetShell('powershell')

    " add the corresponding script
    call SelectScript('tar.xz')

    " load the plugins specified
    GLVS

    call ValidateInstall('tar.xz')
endfunc

func Test_glvs_pwsh_tar_xz()
    call CheckTool('unxz')

    " select different shells
    call SetShell('pwsh')

    " add the corresponding script
    call SelectScript('tar.xz')

    " load the plugins specified
    GLVS

    call ValidateInstall('tar.xz')
endfunc

" mnv: set sw=4 ts=4 et:
