import 'mocha' ; import { expect } from 'chai' ; import { UserScriptGenerator } from '@/application/Context/State/Code/Generation/UserScriptGenerator' ; import { SelectedScript } from '@/application/Context/State/Selection/SelectedScript' ; import { ICodeBuilderFactory } from '@/application/Context/State/Code/Generation/ICodeBuilderFactory' ; import { ICodeBuilder } from '@/application/Context/State/Code/Generation/ICodeBuilder' ; import { ScriptStub } from '@tests/unit/stubs/ScriptStub' ; import { ScriptingDefinitionStub } from '@tests/unit/stubs/ScriptingDefinitionStub' ; describe ( 'UserScriptGenerator' , ( ) => { describe ( 'scriptingDefinition' , ( ) => { describe ( 'startCode' , ( ) => { it ( 'is prepended if not empty' , ( ) => { const sut = new UserScriptGenerator ( ) ; const startCode = 'Start\nCode' ; const script = new ScriptStub ( 'id' ) . withCode ( 'code\nmulti-lined' ) . toSelectedScript ( ) ; const definition = new ScriptingDefinitionStub ( ) . withStartCode ( startCode ) . withEndCode ( undefined ) ; const expectedStart = `${ startCode }\n` ; const code = sut . buildCode ( [ script ] , definition ) ; const actual = code . code ; expect ( actual . startsWith ( expectedStart ) ) ; } ) ; it ( 'is not prepended if empty' , ( ) => { const codeBuilderStub = new CodeBuilderStub ( ) ; const sut = new UserScriptGenerator ( mockCodeBuilderFactory ( codeBuilderStub ) ) ; const script = new ScriptStub ( 'id' ) . withCode ( 'code\nmulti-lined' ) . toSelectedScript ( ) ; const definition = new ScriptingDefinitionStub ( ) . withStartCode ( undefined ) . withEndCode ( undefined ) ; const expectedStart = codeBuilderStub . appendFunction ( script . script . name , script . script . code . execute ) . toString ( ) ; const code = sut . buildCode ( [ script ] , definition ) ; const actual = code . code ; expect ( actual . startsWith ( expectedStart ) ) ; } ) ; } ) ; describe ( 'endCode' , ( ) => { it ( 'is appended if not empty' , ( ) => { const sut = new UserScriptGenerator ( ) ; const endCode = 'End\nCode' ; const script = new ScriptStub ( 'id' ) . withCode ( 'code\nmulti-lined' ) . toSelectedScript ( ) ; const definition = new ScriptingDefinitionStub ( ) . withEndCode ( endCode ) ; const expectedEnd = `${ endCode }\n` ; const code = sut . buildCode ( [ script ] , definition ) ; const actual = code . code ; expect ( actual . endsWith ( expectedEnd ) ) ; } ) ; it ( 'is not appended if empty' , ( ) => { const codeBuilderStub = new CodeBuilderStub ( ) ; const sut = new UserScriptGenerator ( mockCodeBuilderFactory ( codeBuilderStub ) ) ; const script = new ScriptStub ( 'id' ) . withCode ( 'code\nmulti-lined' ) . toSelectedScript ( ) ; const expectedEnd = codeBuilderStub . appendFunction ( script . script . name , script . script . code . execute ) . toString ( ) ; const definition = new ScriptingDefinitionStub ( ) . withEndCode ( undefined ) ; const code = sut . buildCode ( [ script ] , definition ) ; const actual = code . code ; expect ( actual . endsWith ( expectedEnd ) ) ; } ) ; } ) ; } ) ; it ( 'appends revert script' , ( ) => { const sut = new UserScriptGenerator ( ) ; const scriptName = 'test non-revert script' ; const scriptCode = 'REM nop' ; const script = new ScriptStub ( 'id' ) . withName ( scriptName ) . withRevertCode ( scriptCode ) . toSelectedScript ( true ) ; const definition = new ScriptingDefinitionStub ( ) ; const actual = sut . buildCode ( [ script ] , definition ) ; expect ( actual . code ) . to . include ( `${ scriptName } (revert)` ) ; expect ( actual . code ) . to . include ( scriptCode ) ; } ) ; it ( 'appends non-revert script' , ( ) => { const sut = new UserScriptGenerator ( ) ; const scriptName = 'test non-revert script' ; const scriptCode = 'REM nop' ; const script = new ScriptStub ( 'id' ) . withName ( scriptName ) . withCode ( scriptCode ) ; const selectedScripts = [ new SelectedScript ( script , false ) ] ; const definition = new ScriptingDefinitionStub ( ) ; const actual = sut . buildCode ( selectedScripts , definition ) ; expect ( actual . code ) . to . include ( scriptName ) ; expect ( actual . code ) . to . not . include ( `${ scriptName } (revert)` ) ; expect ( actual . code ) . to . include ( scriptCode ) ; } ) ; describe ( 'scriptPositions' , ( ) => { it ( 'without script; returns empty' , ( ) => { const sut = new UserScriptGenerator ( ) ; const selectedScripts = [ ] ; const definition = new ScriptingDefinitionStub ( ) ; const actual = sut . buildCode ( selectedScripts , definition ) ; expect ( actual . scriptPositions . size ) . to . equal ( 0 ) ; } ) ; describe ( 'with scripts' , ( ) => { const totalStartCodeLines = 2 ; const totalFunctionNameLines = 4 ; const definition = new ScriptingDefinitionStub ( ) . withStartCode ( 'First line\nSecond line' ) ; describe ( 'single script' , ( ) => { const testCases = [ { name : 'single-lined' , scriptCode : 'only line' , codeLines : 1 , } , { name : 'multi-lined' , scriptCode : 'first line\nsecond line' , codeLines : 2 , } , ] ; const sut = new UserScriptGenerator ( ) ; for ( const testCase of testCases ) { it ( testCase . name , ( ) => { const expectedStartLine = totalStartCodeLines + 1 + 1 ; const expectedEndLine = expectedStartLine + totalFunctionNameLines + testCase . codeLines ; const selectedScript = new ScriptStub ( 'script-id' ) . withName ( 'script' ) . withCode ( testCase . scriptCode ) . toSelectedScript ( false ) ; const actual = sut . buildCode ( [ selectedScript ] , definition ) ; expect ( 1 ) . to . equal ( actual . scriptPositions . size ) ; const position = actual . scriptPositions . get ( selectedScript ) ; expect ( expectedStartLine ) . to . equal ( position . startLine , 'Unexpected start line position' ) ; expect ( expectedEndLine ) . to . equal ( position . endLine , 'Unexpected end line position' ) ; } ) ; } } ) ; it ( 'multiple scripts' , ( ) => { const sut = new UserScriptGenerator ( ) ; const selectedScripts = [ new ScriptStub ( '1' ) . withCode ( 'only line' ) , new ScriptStub ( '2' ) . withCode ( 'first line\nsecond line' ) , ] . map ( ( s ) => s . toSelectedScript ( ) ) ; const expectedFirstScriptStart = totalStartCodeLines + 1 + 1 ; const expectedFirstScriptEnd = expectedFirstScriptStart + totalFunctionNameLines + 1 ; const expectedSecondScriptStart = expectedFirstScriptEnd + 1 + 1 + 1 ; const expectedSecondScriptEnd = expectedSecondScriptStart + totalFunctionNameLines + 2 ; const actual = sut . buildCode ( selectedScripts , definition ) ; const firstPosition = actual . scriptPositions . get ( selectedScripts [ 0 ] ) ; const secondPosition = actual . scriptPositions . get ( selectedScripts [ 1 ] ) ; expect ( actual . scriptPositions . size ) . to . equal ( 2 ) ; expect ( expectedFirstScriptStart ) . to . equal ( firstPosition . startLine , 'Unexpected start line position (first script)' ) ; expect ( expectedFirstScriptEnd ) . to . equal ( firstPosition . endLine , 'Unexpected end line position (first script)' ) ; expect ( expectedSecondScriptStart ) . to . equal ( secondPosition . startLine , 'Unexpected start line position (second script)' ) ; expect ( expectedSecondScriptEnd ) . to . equal ( secondPosition . endLine , 'Unexpected end line position (second script)' ) ; } ) ; } ) ; } ) ; } ) ; function mockCodeBuilderFactory ( mock ) { return { create : ( ) => mock , } ; } class CodeBuilderStub implements ICodeBuilder { public currentLine = 0 ; private text = '' ; public appendLine ( code ? ) { this . text += this . text ? `${ code }\n` : code ; this . currentLine ++ ; return this ; } public appendTrailingHyphensCommentLine ( totalRepeatHyphens ) { return this . appendLine ( `trailing-hyphens-${ totalRepeatHyphens }` ) ; } public appendCommentLine ( commentLine ? ) { return this . appendLine ( `Comment | ${ commentLine }` ) ; } public appendCommentLineWithHyphensAround ( sectionName , totalRepeatHyphens ) { return this . appendLine ( `hyphens-around-${ totalRepeatHyphens } | Section name: ${ sectionName } | hyphens-around-${ totalRepeatHyphens }` ) ; } public appendFunction ( name , code ) { return this . appendLine ( `Function | Name: ${ name }` ) . appendLine ( `Function | Code: ${ code }` ) ; } public toString ( ) { return this . text ; } }