import 'mocha' ; import { expect } from 'chai' ; import { parseScript } from '@/application/Parser/Script/ScriptParser' ; import { parseDocUrls } from '@/application/Parser/DocumentationParser' ; import { RecommendationLevel } from '@/domain/RecommendationLevel' ; import { ICategoryCollectionParseContext } from '@/application/Parser/Script/ICategoryCollectionParseContext' ; import { ScriptCompilerStub } from '@tests/unit/stubs/ScriptCompilerStub' ; import { ScriptDataStub } from '@tests/unit/stubs/ScriptDataStub' ; import { EnumParserStub } from '@tests/unit/stubs/EnumParserStub' ; import { ScriptCodeStub } from '@tests/unit/stubs/ScriptCodeStub' ; import { CategoryCollectionParseContextStub } from '@tests/unit/stubs/CategoryCollectionParseContextStub' ; import { LanguageSyntaxStub } from '@tests/unit/stubs/LanguageSyntaxStub' ; describe ( 'ScriptParser' , ( ) => { describe ( 'parseScript' , ( ) => { it ( 'parses name as expected' , ( ) => { const expected = 'test-expected-name' ; const script = ScriptDataStub . createWithCode ( ) . withName ( expected ) ; const parseContext = new CategoryCollectionParseContextStub ( ) ; const actual = parseScript ( script , parseContext ) ; expect ( actual . name ) . to . equal ( expected ) ; } ) ; it ( 'parses docs as expected' , ( ) => { const docs = [ 'https://expected-doc1.com' , 'https://expected-doc2.com' ] ; const script = ScriptDataStub . createWithCode ( ) . withDocs ( docs ) ; const parseContext = new CategoryCollectionParseContextStub ( ) ; const expected = parseDocUrls ( script ) ; const actual = parseScript ( script , parseContext ) ; expect ( actual . documentationUrls ) . to . deep . equal ( expected ) ; } ) ; describe ( 'invalid script' , ( ) => { it ( 'throws when script is undefined' , ( ) => { const expectedError = 'undefined script' ; const parseContext = new CategoryCollectionParseContextStub ( ) ; const script = undefined ; const act = ( ) => parseScript ( script , parseContext ) ; expect ( act ) . to . throw ( expectedError ) ; } ) ; it ( 'throws when both function call and code are defined' , ( ) => { const expectedError = 'cannot define both "call" and "code"' ; const parseContext = new CategoryCollectionParseContextStub ( ) ; const script = ScriptDataStub . createWithCall ( ) . withCode ( 'code' ) ; const act = ( ) => parseScript ( script , parseContext ) ; expect ( act ) . to . throw ( expectedError ) ; } ) ; it ( 'throws when both function call and revertCode are defined' , ( ) => { const expectedError = 'cannot define "revertCode" if "call" is defined' ; const parseContext = new CategoryCollectionParseContextStub ( ) ; const script = ScriptDataStub . createWithCall ( ) . withRevertCode ( 'revert-code' ) ; const act = ( ) => parseScript ( script , parseContext ) ; expect ( act ) . to . throw ( expectedError ) ; } ) ; it ( 'throws when neither call or revertCode are defined' , ( ) => { const expectedError = 'must define either "call" or "code"' ; const parseContext = new CategoryCollectionParseContextStub ( ) ; const script = ScriptDataStub . createWithoutCallOrCodes ( ) ; const act = ( ) => parseScript ( script , parseContext ) ; expect ( act ) . to . throw ( expectedError ) ; } ) ; } ) ; describe ( 'level' , ( ) => { it ( 'accepts undefined level' , ( ) => { const undefinedLevels = [ '' , undefined ] ; undefinedLevels . forEach ( ( undefinedLevel ) => { const parseContext = new CategoryCollectionParseContextStub ( ) ; const script = ScriptDataStub . createWithCode ( ) . withRecommend ( undefinedLevel ) ; const actual = parseScript ( script , parseContext ) ; expect ( actual . level ) . to . equal ( undefined ) ; } ) ; } ) ; describe ( 'parses level as expected' , ( ) => { const expectedLevel = RecommendationLevel . Standard ; const expectedName = 'level' ; const levelText = 'standard' ; const script = ScriptDataStub . createWithCode ( ) . withRecommend ( levelText ) ; const parseContext = new CategoryCollectionParseContextStub ( ) ; const parserMock = new EnumParserStub < RecommendationLevel > ( ) . setup ( expectedName , levelText , expectedLevel ) ; const actual = parseScript ( script , parseContext , parserMock ) ; expect ( actual . level ) . to . equal ( expectedLevel ) ; } ) ; } ) ; describe ( 'code' , ( ) => { it ( 'parses "execute" as expected' , ( ) => { const expected = 'expected-code' ; const script = ScriptDataStub . createWithCode ( ) . withCode ( expected ) ; const parseContext = new CategoryCollectionParseContextStub ( ) ; const parsed = parseScript ( script , parseContext ) ; const actual = parsed . code . execute ; expect ( actual ) . to . equal ( expected ) ; } ) ; it ( 'parses "revert" as expected' , ( ) => { const expected = 'expected-revert-code' ; const script = ScriptDataStub . createWithCode ( ) . withRevertCode ( expected ) ; const parseContext = new CategoryCollectionParseContextStub ( ) ; const parsed = parseScript ( script , parseContext ) ; const actual = parsed . code . revert ; expect ( actual ) . to . equal ( expected ) ; } ) ; describe ( 'compiler' , ( ) => { it ( 'throws when context is not defined' , ( ) => { const expectedMessage = 'undefined context' ; const script = ScriptDataStub . createWithCode ( ) ; const context = undefined ; const act = ( ) => parseScript ( script , context ) ; expect ( act ) . to . throw ( expectedMessage ) ; } ) ; it ( 'gets code from compiler' , ( ) => { const expected = new ScriptCodeStub ( ) ; const script = ScriptDataStub . createWithCode ( ) ; const compiler = new ScriptCompilerStub ( ) . withCompileAbility ( script , expected ) ; const parseContext = new CategoryCollectionParseContextStub ( ) . withCompiler ( compiler ) ; const parsed = parseScript ( script , parseContext ) ; const actual = parsed . code ; expect ( actual ) . to . equal ( expected ) ; } ) ; } ) ; describe ( 'syntax' , ( ) => { it ( 'set from the context' , ( ) => { const commentDelimiter = 'should not throw' ; const duplicatedCode = `${ commentDelimiter } duplicate-line\n${ commentDelimiter } duplicate-line` ; const parseContext = new CategoryCollectionParseContextStub ( ) . withSyntax ( new LanguageSyntaxStub ( ) . withCommentDelimiters ( commentDelimiter ) ) ; const script = ScriptDataStub . createWithoutCallOrCodes ( ) . withCode ( duplicatedCode ) ; const act = ( ) => parseScript ( script , parseContext ) ; expect ( act ) . to . not . throw ( ) ; } ) ; } ) ; } ) ; } ) ; } ) ;