import { expect } from "chai" ; import { forEach , isPlainObject , keys } from "lodash" ; import { buildUI5Model , buildUI5Class , expectExists , } from "@ui5-language-assistant/test-utils" ; import { UI5Class , UI5SemanticModel , UI5Type , } from "@ui5-language-assistant/semantic-model-types" ; import { resolveType , setParent } from "../src/resolve" ; import { getSymbolMaps } from "../src/utils" ; import { generate } from "../src/api" ; import { ClassSymbol , NamespaceSymbol , SymbolBase } from "../src/api-json" ; import { addViewDefaultAggregation } from "../src/fix-api-json" ; context ( "The ui5-language-assistant semantic model package unit tests" , ( ) => { describe ( "resolveType" , ( ) => { it ( "returns the same type if it's resolved" , ( ) => { const model = buildUI5Model ( { } ) ; const stringPrimitiveType = { kind : "PrimitiveType" , name : "String" , } ; expect ( resolveType ( { model , type : stringPrimitiveType , typeNameFix : { } , strict : true , } ) ) . to . equal ( stringPrimitiveType ) ; } ) ; } ) ; describe ( "setParent" , ( ) => { it ( "fails when parent is not found in the model" , ( ) => { const model = buildUI5Model ( { } ) ; const classFqn = "sap.MyClass" ; const classs = buildUI5Class ( { name : "MyClass" , } ) ; model . classes [ classFqn ] = classs ; expect ( ( ) => { setParent ( model , classFqn , classs ) ; } ) . to . throw ( "Symbol sap not found" ) ; } ) ; } ) ; describe ( "getSymbolMaps" , ( ) => { it ( "returns all object properties on the model" , ( ) => { const model = buildUI5Model ( { } ) ; const objectsOnModel = [ ] ; forEach ( model , ( property ) => { if ( isPlainObject ( property ) ) { objectsOnModel . push ( property ) ; } } ) ; expect ( getSymbolMaps ( model ) ) . to . contain . members ( objectsOnModel ) ; } ) ; } ) ; describe ( "generate" , ( ) => { function generateSymbol ( symbol ) { return generate ( { version : "1.74.0" , strict : true , typeNameFix : { } , libraries : { testLib : { "$schema-ref" : "http://schemas.sap.com/sapui5/designtime/api.json/1.0" , symbols : [ symbol ] , } , } , } ) ; } function generateAndVerifyClass ( partialClass ) { const symbol = { kind : "class" , basename : "rootSymbol" , name : "rootSymbol" , ... partialClass , } as ClassSymbol ; const result = generateSymbol ( symbol ) ; expect ( keys ( result . classes ) , "classes" ) . to . contain ( "rootSymbol" ) ; return result . classes [ "rootSymbol" ] ; } it ( "sets public visibility on constructor if visibility is not defined" , ( ) => { const result = generateAndVerifyClass ( { constructor : { description : "constructor with undefined visibility" , } , } as Partial < ClassSymbol > ) ; expectExists ( result . ctor , "constructor" ) ; expect ( result . ctor . visibility , "constructor visibility" ) . to . equal ( "public" ) ; } ) ; it ( "sets public visibility on event if visibility is not defined" , ( ) => { const result = generateAndVerifyClass ( { events : [ { name : "name" , } , ] , } ) ; expect ( result . events , "rootSymbol events" ) . to . have . lengthOf ( 1 ) ; expect ( result . events [ 0 ] . visibility , "event visibility" ) . to . equal ( "public" ) ; } ) ; it ( "doesn't set type when not defined on class property" , ( ) => { const result = generateAndVerifyClass ( { "ui5-metadata" : { properties : [ { name : "name" , } , ] , } , } ) ; expect ( result . properties , "rootSymbol properties" ) . to . have . lengthOf ( 1 ) ; expect ( result . properties [ 0 ] . type , "property type" ) . to . be . undefined ; } ) ; it ( "doesn't set type when not defined on class aggregation" , ( ) => { const result = generateAndVerifyClass ( { "ui5-metadata" : { aggregations : [ { name : "name" , } , ] , } , } ) ; expect ( result . aggregations , "rootSymbol aggregations" ) . to . have . lengthOf ( 1 ) ; expect ( result . aggregations [ 0 ] . type , "aggregation type" ) . to . be . undefined ; } ) ; it ( "sets cardinality to 0..n when not defined on class aggregation" , ( ) => { const result = generateAndVerifyClass ( { "ui5-metadata" : { aggregations : [ { name : "name" , } , ] , } , } ) ; expect ( result . aggregations , "rootSymbol aggregations" ) . to . have . lengthOf ( 1 ) ; expect ( result . aggregations [ 0 ] . cardinality , "aggregation cardinality" ) . to . equal ( "0..n" ) ; } ) ; it ( "doesn't set type when not defined on class association" , ( ) => { const result = generateAndVerifyClass ( { "ui5-metadata" : { associations : [ { name : "name" , } , ] , } , } ) ; expect ( result . associations , "rootSymbol associations" ) . to . have . lengthOf ( 1 ) ; expect ( result . associations [ 0 ] . type , "association type" ) . to . be . undefined ; } ) ; it ( "sets cardinality to 0..1 when not defined on class association" , ( ) => { const result = generateAndVerifyClass ( { "ui5-metadata" : { associations : [ { name : "name" , } , ] , } , } ) ; expect ( result . associations , "rootSymbol associations" ) . to . have . lengthOf ( 1 ) ; expect ( result . associations [ 0 ] . cardinality , "association cardinality" ) . to . equal ( "0..1" ) ; } ) ; it ( "doesn't set type when not defined on namespace field" , ( ) => { const symbol = { kind : "namespace" , basename : "rootNamespace" , name : "rootNamespace" , properties : [ { name : "myField" , } , ] , } ; const result = generateSymbol ( symbol ) ; expect ( keys ( result . namespaces ) , "namespaces" ) . to . contain ( "rootNamespace" ) ; const namespace = result . namespaces [ "rootNamespace" ] ; expect ( namespace . fields , "rootNamespace fields" ) . to . have . lengthOf ( 1 ) ; expect ( namespace . fields [ 0 ] . type , "field type" ) . to . be . undefined ; } ) ; describe ( "symbols is undefined" , ( ) => { const fileContent = { "$schema-ref" : "http://schemas.sap.com/sapui5/designtime/api.json/1.0" , version : "1.74.0" , library : "testLib" , } ; it ( "doesn't fail in strict mode" , ( ) => { const model = generate ( { version : fileContent . version , libraries : { testLib : fileContent } , typeNameFix : { } , strict : true , } ) ; expectExists ( model , "model" ) ; } ) ; it ( "doesn't fail in non-strict mode" , ( ) => { const model = generate ( { version : fileContent . version , libraries : { testLib : fileContent } , typeNameFix : { } , strict : false , } ) ; expectExists ( model , "model" ) ; } ) ; } ) ; } ) ; context ( "includedLibraries" , ( ) => { function generateFromLibraries ( libraries ) { const result = generate ( { version : "1.74.0" , strict : false , typeNameFix : { } , libraries : libraries , printValidationErrors : false , } ) ; return result ; } const libWithSymbol = { "$schema-ref" : "http://schemas.sap.com/sapui5/designtime/api.json/1.0" , symbols : [ { kind : "class" , basename : "rootSymbol" , name : "rootSymbol" , } , ] , } ; it ( "contains a valid library" , ( ) => { const result = generateFromLibraries ( { testLib : libWithSymbol , } ) ; expect ( result . includedLibraries , "includedLibraries" ) . to . deep . equal ( [ "testLib" , ] ) ; } ) ; it ( "contains an invalid library object" , ( ) => { const result = generateFromLibraries ( { testLib : { } , } ) ; expect ( result . includedLibraries , "includedLibraries" ) . to . deep . equal ( [ "testLib" , ] ) ; } ) ; it ( "contains an empty library" , ( ) => { const result = generateFromLibraries ( { testLib : "" , } ) ; expect ( result . includedLibraries , "includedLibraries" ) . to . deep . equal ( [ "testLib" , ] ) ; } ) ; it ( "contains all sent libraries" , ( ) => { const result = generateFromLibraries ( { testLib : libWithSymbol , lib2 : libWithSymbol , emptyLib : { } , } ) ; expect ( result . includedLibraries , "includedLibraries" ) . to . deep . equalInAnyOrder ( [ "testLib" , "lib2" , "emptyLib" ] ) ; } ) ; } ) ; context ( "API JSON fixes" , ( ) => { context ( "addViewDefaultAggregation" , ( ) => { it ( "doesn't fail when there is a sap.ui.core.mvc.View with no ui5-metadata" , ( ) => { addViewDefaultAggregation ( "sap.ui.core" , { symbols : [ { name : "sap.ui.core.mvc.View" , } , ] , } ) ; } ) ; } ) ; } ) ; } ) ;