import 'mocha' ; import { expect } from 'chai' ; import { IReadOnlyFunctionParameterCollection } from '@/application/Parser/Script/Compiler/Function/Parameter/IFunctionParameterCollection' ; import { FunctionParameterCollectionStub } from '@tests/unit/stubs/FunctionParameterCollectionStub' ; import { createCallerFunction , createFunctionWithInlineCode } from '@/application/Parser/Script/Compiler/Function/SharedFunction' ; import { IFunctionCall } from '@/application/Parser/Script/Compiler/Function/Call/IFunctionCall' ; import { FunctionCallStub } from '@tests/unit/stubs/FunctionCallStub' ; import { FunctionBodyType , ISharedFunction } from '@/application/Parser/Script/Compiler/Function/ISharedFunction' ; describe ( 'SharedFunction' , ( ) => { describe ( 'name' , ( ) => { runForEachFactoryMethod ( ( build ) => { it ( 'sets as expected' , ( ) => { const expected = 'expected-function-name' ; const builder = new SharedFunctionBuilder ( ) . withName ( expected ) ; const sut = build ( builder ) ; expect ( sut . name ) . equal ( expected ) ; } ) ; it ( 'throws if empty or undefined' , ( ) => { const expectedError = 'undefined function name' ; const invalidValues = [ undefined , '' ] ; for ( const invalidValue of invalidValues ) { const builder = new SharedFunctionBuilder ( ) . withName ( invalidValue ) ; const act = ( ) => build ( builder ) ; expect ( act ) . to . throw ( expectedError ) ; } } ) ; } ) ; } ) ; describe ( 'parameters' , ( ) => { runForEachFactoryMethod ( ( build ) => { it ( 'sets as expected' , ( ) => { const expected = new FunctionParameterCollectionStub ( ) . withParameterName ( 'test-parameter' ) ; const builder = new SharedFunctionBuilder ( ) . withParameters ( expected ) ; const sut = build ( builder ) ; expect ( sut . parameters ) . equal ( expected ) ; } ) ; it ( 'throws if undefined' , ( ) => { const expectedError = 'undefined parameters' ; const parameters = undefined ; const builder = new SharedFunctionBuilder ( ) . withParameters ( parameters ) ; const act = ( ) => build ( builder ) ; expect ( act ) . to . throw ( expectedError ) ; } ) ; } ) ; } ) ; describe ( 'body' , ( ) => { describe ( 'createFunctionWithInlineCode' , ( ) => { describe ( 'code' , ( ) => { it ( 'sets as expected' , ( ) => { const expected = 'expected-code' ; const sut = new SharedFunctionBuilder ( ) . withCode ( expected ) . createFunctionWithInlineCode ( ) ; expect ( sut . body . code . do ) . equal ( expected ) ; } ) ; it ( 'throws if empty or undefined' , ( ) => { const functionName = 'expected-function-name' ; const expectedError = `undefined code in function "${ functionName }"` ; const invalidValues = [ undefined , '' ] ; for ( const invalidValue of invalidValues ) { const act = ( ) => new SharedFunctionBuilder ( ) . withName ( functionName ) . withCode ( invalidValue ) . createFunctionWithInlineCode ( ) ; expect ( act ) . to . throw ( expectedError ) ; } } ) ; } ) ; describe ( 'revertCode' , ( ) => { it ( 'sets as expected' , ( ) => { const testData = [ 'expected-revert-code' , undefined , '' ] ; for ( const data of testData ) { const sut = new SharedFunctionBuilder ( ) . withRevertCode ( data ) . createFunctionWithInlineCode ( ) ; expect ( sut . body . code . revert ) . equal ( data ) ; } } ) ; } ) ; it ( 'sets type as expected' , ( ) => { const expectedType = FunctionBodyType . Code ; const sut = new SharedFunctionBuilder ( ) . createFunctionWithInlineCode ( ) ; expect ( sut . body . type ) . equal ( expectedType ) ; } ) ; it ( 'calls are undefined' , ( ) => { const expectedCalls = undefined ; const sut = new SharedFunctionBuilder ( ) . createFunctionWithInlineCode ( ) ; expect ( sut . body . calls ) . equal ( expectedCalls ) ; } ) ; } ) ; describe ( 'createCallerFunction' , ( ) => { describe ( 'callSequence' , ( ) => { it ( 'sets as expected' , ( ) => { const expected = [ new FunctionCallStub ( ) . withFunctionName ( 'firstFunction' ) , new FunctionCallStub ( ) . withFunctionName ( 'secondFunction' ) , ] ; const sut = new SharedFunctionBuilder ( ) . withCallSequence ( expected ) . createCallerFunction ( ) ; expect ( sut . body . calls ) . equal ( expected ) ; } ) ; it ( 'throws if undefined' , ( ) => { const functionName = 'invalidFunction' ; const callSequence = undefined ; const expectedError = `undefined call sequence in function "${ functionName }"` ; const act = ( ) => new SharedFunctionBuilder ( ) . withName ( functionName ) . withCallSequence ( callSequence ) . createCallerFunction ( ) ; expect ( act ) . to . throw ( expectedError ) ; } ) ; it ( 'throws if empty' , ( ) => { const functionName = 'invalidFunction' ; const callSequence = [ ] ; const expectedError = `empty call sequence in function "${ functionName }"` ; const act = ( ) => new SharedFunctionBuilder ( ) . withName ( functionName ) . withCallSequence ( callSequence ) . createCallerFunction ( ) ; expect ( act ) . to . throw ( expectedError ) ; } ) ; } ) ; it ( 'sets type as expected' , ( ) => { const expectedType = FunctionBodyType . Calls ; const sut = new SharedFunctionBuilder ( ) . createCallerFunction ( ) ; expect ( sut . body . type ) . equal ( expectedType ) ; } ) ; it ( 'code is undefined' , ( ) => { const expectedCode = undefined ; const sut = new SharedFunctionBuilder ( ) . createCallerFunction ( ) ; expect ( sut . body . code ) . equal ( expectedCode ) ; } ) ; } ) ; } ) ; } ) ; function runForEachFactoryMethod ( act ) { describe ( 'createCallerFunction' , ( ) => { const action = ( builder ) => builder . createCallerFunction ( ) ; act ( action ) ; } ) ; describe ( 'createFunctionWithInlineCode' , ( ) => { const action = ( builder ) => builder . createFunctionWithInlineCode ( ) ; act ( action ) ; } ) ; } class SharedFunctionBuilder { private name = 'name' ; private parameters : IReadOnlyFunctionParameterCollection = new FunctionParameterCollectionStub ( ) ; private callSequence : readonly IFunctionCall [ ] = [ new FunctionCallStub ( ) ] ; private code = 'code' ; private revertCode = 'revert-code' ; public createCallerFunction ( ) { return createCallerFunction ( this . name , this . parameters , this . callSequence ) ; } public createFunctionWithInlineCode ( ) { return createFunctionWithInlineCode ( this . name , this . parameters , this . code , this . revertCode ) ; } public withName ( name ) { this . name = name ; return this ; } public withParameters ( parameters ) { this . parameters = parameters ; return this ; } public withCode ( code ) { this . code = code ; return this ; } public withRevertCode ( revertCode ) { this . revertCode = revertCode ; return this ; } public withCallSequence ( callSequence ) { this . callSequence = callSequence ; return this ; } }