/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ 'use strict' ; import * as assert from 'assert' ; import { before , beforeEach , after } from 'mocha' ; import * as fs from 'fs' ; import * as vscode from 'vscode' ; import * as path from 'path' ; import * as extensionFunctions from '../../extensionFunctions' ; import { getValue } from '../../utils' ; import * as commandHandler from '../../commandHandler' ; import { removeFilesAndFolders } from '../../utils' ; import { waitUntil } from 'async-wait-until' ; import { didactManager } from '../../didactManager' ; import { expect } from 'chai' ; import { didactTutorialsProvider , revealTreeItem } from '../../extension' ; const url = require ( 'url-parse' ) ; const EDITOR_OPENED_TIMEOUT = 5000 ; const testMD = vscode . Uri . parse ( 'vscode://redhat.vscode-didact?extension=demos/markdown/didact-demo.didact.md' ) ; const testMD3 = vscode . Uri . parse ( 'vscode://redhat.vscode-didact?extension=demos/markdown/validation-test.didact.md' ) ; const testMD4 = vscode . Uri . parse ( 'vscode://redhat.vscode-didact?commandId=vscode.didact.registry.addUri&&https=raw.githubusercontent.com/redhat-developer/vscode-didact/0.4.0/examples/requirements.example.didact.md&&name=Requirements%20Example&&category=Test%20From%20The%20Web' ) ; const testMD5 = vscode . Uri . parse ( 'vscode://redhat.vscode-didact?https=raw.githubusercontent.com/redhat-developer/vscode-didact/0.4.0/examples/terminal.example.didact.md' ) ; const testExt = 'didact://?commandId=vscode.didact.extensionRequirementCheck&text=some-field-to-update$$redhat.vscode-didact' ; const testReq = 'didact://?commandId=vscode.didact.requirementCheck&text=uname-requirements-status$$uname$$Linux' ; const testReqMac = 'didact://?commandId=vscode.didact.requirementCheck&text=uname-requirements-status$$uname$$Darwin' ; const testReqWin = 'didact://?commandId=vscode.didact.requirementCheck&text=echo-requirements-status$$echo%20test$$test' ; const testReqCli = 'didact://?commandId=vscode.didact.cliCommandSuccessful&text=echo-cli-return-status$$echo%20test' ; const testWS = 'didact://?commandId=vscode.didact.workspaceFolderExistsCheck&text=workspace-folder-status' ; const testScaffold = 'didact://?commandId=vscode.didact.scaffoldProject&extFilePath=redhat.vscode-didact/demos/projectwithdidactfile.json' ; const testScaffoldOpen = 'didact://?commandId=vscode.didact.scaffoldProject&extFilePath=redhat.vscode-didact/src/test/data/scaffoldOpen.json' ; const OS_WINDOWS = "win32" ; const OS_LINUX = "linux" ; const OS_MACOS = "darwin" ; suite ( 'Didact test suite' , ( ) => { const extensionId = 'redhat.vscode-didact' ; const testWorkspace = path . resolve ( __dirname , '..' , '..' , '..' , './test Fixture with speci@l chars' ) ; const foldersAndFilesToRemove = [ 'anotherProject' , 'root' , ] ; after ( async ( ) => { await removeFilesAndFolders ( testWorkspace , foldersAndFilesToRemove ) ; } ) ; beforeEach ( async ( ) => { await removeFilesAndFolders ( testWorkspace , foldersAndFilesToRemove ) ; } ) ; before ( async ( ) => { assert . ok ( vscode . extensions . getExtension ( extensionId ) ) ; vscode . window . showInformationMessage ( 'Start all Didact tests.' ) ; const wsCheck = await extensionFunctions . validWorkspaceCheck ( 'undefined' ) ; console . log ( 'Workspace has a root folder: ' + wsCheck ) ; console . log ( `Test workspace: ' + "${ testWorkspace }"` ) ; console . log ( 'Test workspace exists: ' + fs . existsSync ( `"${ testWorkspace }"` ) ) ; const extensionDevelopmentPath = path . resolve ( __dirname , '../../../' ) ; console . log ( 'extensionDevelopmentPath: ' + extensionDevelopmentPath ) ; const extensionTestsPath = path . resolve ( __dirname , './index' ) ; console . log ( 'extensionTestsPath: ' + extensionTestsPath ) ; if ( ! wsCheck ) { assert . fail ( 'Workspace does not have a root folder' ) ; } } ) ; test ( 'Scaffold new project' , async function ( ) { try { await vscode . commands . executeCommand ( extensionFunctions . SCAFFOLD_PROJECT_COMMAND ) . then ( ( ) => { const createdGroovyFileInFolderStructure = path . resolve ( testWorkspace , './root/src/simple.groovy' ) ; assert . strictEqual ( fs . existsSync ( createdGroovyFileInFolderStructure ) , true ) ; } ) ; } catch ( error ) { assert . fail ( error ) ; } } ) ; test ( 'Scaffold new project, test for open: true file' , async function ( ) { try { await commandHandler . processInputs ( testScaffoldOpen ) . then ( async ( ) => { try { const predicate = ( ) => findEditorForFile ( 'simple.groovy' ) != undefined ; await waitUntil ( predicate , { timeout : EDITOR_OPENED_TIMEOUT , intervalBetweenAttempts : 1000 } ) ; } catch ( error ) { assert . fail ( `simple.groovy has not been opened in editor` ) ; } } ) ; } catch ( error ) { assert . fail ( error ) ; } } ) ; test ( 'Scaffold new project, test for standard file (no open)' , async function ( ) { await testScaffoldProjectDoesNotOpenFile ( `aThirdFile.txt` ) ; } ) ; test ( 'Scaffold new project, test for open: false file' , async function ( ) { await testScaffoldProjectDoesNotOpenFile ( `anotherFile.txt` ) ; } ) ; test ( 'Scaffold new project with a uri' , async function ( ) { await commandHandler . processInputs ( testScaffold ) . then ( ( ) => { const createdDidactFileInFolderStructure = path . resolve ( testWorkspace , './anotherProject/src/test.didact.md' ) ; assert . strictEqual ( fs . existsSync ( createdDidactFileInFolderStructure ) , true ) ; } ) . catch ( ( error ) => { assert . fail ( error ) ; } ) ; } ) ; test ( 'Test the extension checking' , async ( ) => { const href = testExt ; const parsedUrl = new url ( href , true ) ; const query = parsedUrl . query ; assert . notStrictEqual ( query . commandId , undefined ) ; if ( query . commandId ) { const commandId = getValue ( query . commandId ) ; const output = [ ] ; if ( query . text ) { const text = getValue ( query . text ) ; if ( text ) { commandHandler . handleText ( text , output ) ; } } assert . strictEqual ( output . length , 2 ) ; const extAvailable = await extensionFunctions . extensionCheck ( output [ 0 ] , output [ 1 ] ) ; assert . strictEqual ( extAvailable , true , `Found command ${ commandId } in Didact file but extension test is not found: ${ href }` ) ; } } ) ; test ( 'test the command line requirements checking' , async ( ) => { const href = testReqCli ; const parsedUrl = new url ( href , true ) ; const query = parsedUrl . query ; assert . notStrictEqual ( query . commandId , undefined ) ; if ( query . commandId ) { const commandId = getValue ( query . commandId ) ; const output = [ ] ; if ( query . text ) { const text = getValue ( query . text ) ; if ( text ) { commandHandler . handleText ( text , output ) ; } } assert . strictEqual ( output . length , 2 ) ; const reqAvailable = await extensionFunctions . cliExecutionCheck ( output [ 0 ] , output [ 1 ] ) ; assert . strictEqual ( reqAvailable , true , `Found command ${ commandId } in Didact file but did not receive 0 as return code: ${ href }` ) ; } } ) ; test ( 'test the command line requirement return checking' , async ( ) => { let href = '' ; const osName = process . platform ; if ( osName . startsWith ( OS_WINDOWS ) ) { href = testReqWin ; } else if ( osName . startsWith ( OS_LINUX ) ) { href = testReq ; } else if ( osName . startsWith ( OS_MACOS ) ) { href = testReqMac ; } const parsedUrl = new url ( href , true ) ; const query = parsedUrl . query ; assert . notStrictEqual ( query . commandId , undefined ) ; if ( query . commandId ) { const commandId = getValue ( query . commandId ) ; const output = [ ] ; if ( query . text ) { const text = getValue ( query . text ) ; if ( text ) { commandHandler . handleText ( text , output ) ; } } assert . strictEqual ( output . length , 3 ) ; const reqAvailable = await extensionFunctions . requirementCheck ( output [ 0 ] , output [ 1 ] , output [ 2 ] ) ; assert . strictEqual ( reqAvailable , true , `Found command ${ commandId } in Didact file but requirement test is not found: ${ href }` ) ; } } ) ; test ( 'test the workspace checking' , async ( ) => { const href = testWS . toString ( ) ; const parsedUrl = new url ( href , true ) ; const query = parsedUrl . query ; assert . notStrictEqual ( query . commandId , undefined ) ; if ( query . commandId ) { const commandId = getValue ( query . commandId ) ; const output = [ ] ; if ( query . text ) { const text = getValue ( query . text ) ; if ( text ) { commandHandler . handleText ( text , output ) ; } } assert . strictEqual ( output . length , 1 ) ; const wsAvailable = await extensionFunctions . validWorkspaceCheck ( output [ 0 ] ) ; assert . strictEqual ( wsAvailable , true , `Found command ${ commandId } in Didact file but workspace test failed: ${ href }` ) ; } } ) ; test ( 'Walk through the demo didact file to ensure that all commands exist in the VS Code system' , async ( ) => { await vscode . commands . executeCommand ( extensionFunctions . START_DIDACT_COMMAND , testMD ) . then ( async ( ) => { if ( didactManager . active ( ) ) { const commands = extensionFunctions . gatherAllCommandsLinks ( ) ; assert . strictEqual ( commands && commands . length > 0 , true ) ; const isOk = await extensionFunctions . validateDidactCommands ( commands ) ; if ( ! isOk ) { const vsCommands = await vscode . commands . getCommands ( true ) ; for ( const command of commands ) { const commandOk = extensionFunctions . validateCommand ( command , vsCommands ) ; if ( ! commandOk ) { console . log ( `--Missing Command ID ${ command }` ) ; } } } assert . strictEqual ( isOk , true , `Missing commands in test file.` ) ; } } ) ; } ) ; test ( 'Verify that validation fails when given a negative case' , async ( ) => { await vscode . commands . executeCommand ( extensionFunctions . START_DIDACT_COMMAND , testMD3 ) ; if ( didactManager . active ( ) ) { const commands = extensionFunctions . gatherAllCommandsLinks ( ) ; assert . strictEqual ( commands && commands . length > 0 , true ) ; const isOk = await extensionFunctions . validateDidactCommands ( commands ) ; assert . strictEqual ( isOk , false , `Invalid file should not have passed validation test` ) ; } } ) ; test ( 'Walk through the demo didact file to ensure that we get all the requirements commands successfully' , async ( ) => { await vscode . commands . executeCommand ( extensionFunctions . START_DIDACT_COMMAND , testMD ) . then ( async ( ) => { if ( didactManager . active ( ) ) { const hrefs = extensionFunctions . gatherAllRequirementsLinks ( ) ; console . log ( 'Gathered these requirements URIs: ' + hrefs ) ; assert . strictEqual ( hrefs && hrefs . length === 5 , true ) ; } } ) ; } ) ; test ( 'make sure we can open a didact file from a vscode extension' , async ( ) => { const titleToCheck = 'Didact Terminal Commands' ; await extensionFunctions . handleVSCodeUri ( testMD5 ) ; await waitUntil ( ( ) => didactManager . active ( ) ?. getCurrentTitle ( ) === titleToCheck , { timeout : EDITOR_OPENED_TIMEOUT , intervalBetweenAttempts : 1000 } ) ; expect ( didactManager . active ( ) ) . to . not . be . undefined ; expect ( didactManager . active ( ) ?. getCurrentTitle ( ) ) . to . equal ( titleToCheck ) ; } ) ; test ( 'make sure we can register a didact file from a vscode extension' , async ( ) => { const category = "Test From The Web" ; const tutorialName = "Requirements Example" ; await extensionFunctions . handleVSCodeUri ( testMD4 ) ; const catNode = didactTutorialsProvider . findCategoryNode ( category ) ; expect ( catNode ) . to . not . be . undefined ; await revealTreeItem ( catNode ) ; const foundTutorial = await didactTutorialsProvider . findTutorialNode ( category , tutorialName ) ; expect ( foundTutorial ) . to . not . be . undefined ; } ) ; } ) ; async function testScaffoldProjectDoesNotOpenFile ( fileName ) { try { await commandHandler . processInputs ( testScaffoldOpen ) . then ( async ( ) => { try { const predicate = ( ) => findEditorForFile ( 'simple.groovy' ) != undefined ; await waitUntil ( predicate , { timeout : EDITOR_OPENED_TIMEOUT , intervalBetweenAttempts : 1000 } ) . then ( ( ) => { assert . fail ( `${ fileName } was found opened in editor when it should not have been` ) ; } ) ; } catch ( error ) { assert . ok ( error ) ; } } ) ; } catch ( error ) { assert . fail ( error ) ; } } function findEditorForFile ( filename ) { if ( vscode . window . visibleTextEditors && vscode . window . visibleTextEditors . length > 0 ) { for ( let index = 0 ; index < vscode . window . visibleTextEditors . length ; index ++ ) { const textEditor = vscode . window . visibleTextEditors [ index ] ; if ( textEditor ?. document ?. fileName . endsWith ( `${ filename }` ) ) { return textEditor ; } } } return undefined ; }