From 1bfdd74d595202603a09b1d3cdd1ceb904fda576 Mon Sep 17 00:00:00 2001 From: Albin Ramovic Date: Tue, 12 Nov 2024 18:16:20 +0100 Subject: [PATCH 1/8] initial commit --- lib/ord.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ord.js b/lib/ord.js index 9fe8f0d..f9830c1 100644 --- a/lib/ord.js +++ b/lib/ord.js @@ -10,7 +10,7 @@ const { getRFC3339Date } = require('./date'); const _ = require("lodash"); const cds = require("@sap/cds"); const defaults = require("./defaults"); -const logger = cds.log('ord-plugin'); +const logger = cds.log('ord-plugin'); // TODO const path = require("path"); const initializeAppConfig = (csn) => { From 41e2e50daac64ab3bb13693d2a632e63e7ec5e7b Mon Sep 17 00:00:00 2001 From: Albin Ramovic Date: Wed, 13 Nov 2024 17:29:45 +0100 Subject: [PATCH 2/8] replace console.error with Logger --- __tests__/bookshop/.cdsrc.json | 3 ++- __tests__/unittest/extendOrdWithCustom.test.js | 2 +- lib/extendOrdWithCustom.js | 10 ++++++---- lib/logger.js | 11 +++++++++++ lib/metaData.js | 7 ++++--- lib/ord.js | 8 ++++---- lib/plugin.js | 10 +++++----- lib/templates.js | 5 +++-- 8 files changed, 36 insertions(+), 20 deletions(-) create mode 100644 lib/logger.js diff --git a/__tests__/bookshop/.cdsrc.json b/__tests__/bookshop/.cdsrc.json index 765bae6..759a00c 100644 --- a/__tests__/bookshop/.cdsrc.json +++ b/__tests__/bookshop/.cdsrc.json @@ -5,5 +5,6 @@ "description": "this is my custom description", "policyLevel": "sap:core:v1", "customOrdContentFile": "./ord/custom.ord.json" - } + }, + "DEBUG": false } \ No newline at end of file diff --git a/__tests__/unittest/extendOrdWithCustom.test.js b/__tests__/unittest/extendOrdWithCustom.test.js index 94d6dfd..7679c45 100644 --- a/__tests__/unittest/extendOrdWithCustom.test.js +++ b/__tests__/unittest/extendOrdWithCustom.test.js @@ -12,13 +12,13 @@ jest.mock("@sap/cds", () => { ...actualCds, env: {}, log: jest.fn(() => ({ + levels: { DEBUG: 0, WARN: 1 }, warn: jest.fn(() => console.warn('Mocked warning')), })), }; }); describe('extendOrdWithCustom', () => { - let appConfig = {}; beforeEach(() => { diff --git a/lib/extendOrdWithCustom.js b/lib/extendOrdWithCustom.js index 981d5c2..bc710f4 100644 --- a/lib/extendOrdWithCustom.js +++ b/lib/extendOrdWithCustom.js @@ -1,5 +1,6 @@ const { CONTENT_MERGE_KEY } = require('./constants'); const cds = require("@sap/cds"); +const { Logger } = require("./logger"); const path = require("path"); const _ = require('lodash'); @@ -29,12 +30,13 @@ function patchGeneratedOrdResources(destinationObj, sourceObj) { return cleanNullProperties(Object.values(destObj)); } -function compareAndHandleCustomORDContentWithExistingContent(ordContent, customORDContent, logger) { +function compareAndHandleCustomORDContentWithExistingContent(ordContent, customORDContent) { const clonedOrdContent = structuredClone(ordContent); for (const key in customORDContent) { const propertyType = typeof customORDContent[key]; if (propertyType !== 'object' && propertyType !== 'array') { - logger.warn('Found ord top level primitive ord property in customOrdFile:', key, ', please define it in .cdsrc.json.'); + Logger.warn(`Found ord top level primitive ord property in customOrdFile: ${key}. Please define it in .cdsrc.json.`); + continue; } if (key in ordContent) { @@ -54,11 +56,11 @@ function getCustomORDContent(appConfig) { return {}; } -function extendCustomORDContentIfExists(appConfig, ordContent, logger) { +function extendCustomORDContentIfExists(appConfig, ordContent) { const customORDContent = getCustomORDContent(appConfig); if (customORDContent) { - ordContent = compareAndHandleCustomORDContentWithExistingContent(ordContent, customORDContent, logger); + ordContent = compareAndHandleCustomORDContentWithExistingContent(ordContent, customORDContent); } return ordContent; } diff --git a/lib/logger.js b/lib/logger.js new file mode 100644 index 0000000..c94a23a --- /dev/null +++ b/lib/logger.js @@ -0,0 +1,11 @@ +const cds = require("@sap/cds"); + +const Logger = cds.log("ord-plugin", { + level: cds.env.DEBUG || process.env.DEBUG + ? cds.log.levels?.DEBUG + : cds.log.levels?.WARN, +}); + +module.exports = { + Logger, +}; diff --git a/lib/metaData.js b/lib/metaData.js index 4bee72c..9e45000 100644 --- a/lib/metaData.js +++ b/lib/metaData.js @@ -2,6 +2,7 @@ const cds = require('@sap/cds/lib'); const { compile: openapi } = require('@cap-js/openapi') const { compile: asyncapi } = require('@cap-js/asyncapi'); const { COMPILER_TYPES } = require('./constants'); +const { Logger } = require('./logger'); module.exports = async (data) => { const parts = data?.split("/").pop().replace(/\.json$/, '').split("."); @@ -16,7 +17,7 @@ module.exports = async (data) => { try { responseFile = openapi(csn, options); } catch (error) { - console.error("OpenApi error:", error.message); + Logger.error("OpenApi error:", error.message); throw error; } break; @@ -24,7 +25,7 @@ module.exports = async (data) => { try { responseFile = asyncapi(csn, options); } catch (error) { - console.error("AsyncApi error:", error.message); + Logger.error("AsyncApi error:", error.message); throw error; } break; @@ -32,7 +33,7 @@ module.exports = async (data) => { try { responseFile = await cds.compile(csn).to["edmx"](options); } catch (error) { - console.error("Edmx error:", error.message); + Logger.error("Edmx error:", error.message); throw error; } } diff --git a/lib/ord.js b/lib/ord.js index f9830c1..077a194 100644 --- a/lib/ord.js +++ b/lib/ord.js @@ -7,10 +7,10 @@ const { } = require('./templates'); const { extendCustomORDContentIfExists } = require('./extendOrdWithCustom'); const { getRFC3339Date } = require('./date'); +const { Logger } = require('./logger'); const _ = require("lodash"); const cds = require("@sap/cds"); const defaults = require("./defaults"); -const logger = cds.log('ord-plugin'); // TODO const path = require("path"); const initializeAppConfig = (csn) => { @@ -34,7 +34,7 @@ const initializeAppConfig = (csn) => { const eventApplicationNamespace = cds.env?.export?.asyncapi?.applicationNamespace; if (eventApplicationNamespace && ordNamespace !== eventApplicationNamespace) { - console.warn("ORD and AsyncAPI namespaces should be the same."); + Logger.warn('ORD and AsyncAPI namespaces should be the same.'); } for (const key of modelKeys) { @@ -123,7 +123,7 @@ function validateNamespace(appConfig) { let error = new Error( `Namespace is not defined in cdsrc.json or it is not in the format of ${appConfig.eventApplicationNamespace}..` ); - console.error("Namespace error:", error.message); + Logger.error("Namespace error:", error.message); throw error; } } @@ -167,7 +167,7 @@ module.exports = (csn) => { ordDocument.eventResources = eventResources; } - ordDocument = extendCustomORDContentIfExists(appConfig, ordDocument, logger); + ordDocument = extendCustomORDContentIfExists(appConfig, ordDocument); return ordDocument; }; diff --git a/lib/plugin.js b/lib/plugin.js index 4dd6fcf..b2028e4 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -1,5 +1,7 @@ -const { ord, getMetadata, defaults } = require("./"); const cds = require("@sap/cds"); +const { Logger } = require("./logger"); +const { ord, getMetadata, defaults } = require("./"); + cds.on("bootstrap", (app) => { app.use("/.well-known/open-resource-discovery", async (req, res) => { @@ -10,8 +12,7 @@ cds.on("bootstrap", (app) => { const { contentType, response } = await getMetadata(req.url); res.status(200).contentType(contentType).send(response); } catch (error) { - console.log(error); - console.log('Error while generating metadata'); + Logger.error(error, 'Error while generating metadata'); res.status(500).send(error.message); } } @@ -23,8 +24,7 @@ cds.on("bootstrap", (app) => { const data = ord(csn); return res.status(200).send(data); } catch (error) { - console.log(error); - console.log('Error while creating ORD document'); + Logger.error(error, 'Error while creating ORD document'); return res.status(500).send(error.message); } }); diff --git a/lib/templates.js b/lib/templates.js index a244152..fa16f9c 100644 --- a/lib/templates.js +++ b/lib/templates.js @@ -8,6 +8,7 @@ const { RESOURCE_VISIBILITY, SHORT_DESCRIPTION_PREFIX } = require("./constants"); +const { Logger } = require("./logger"); function unflatten(flattedObject) { let result = {} @@ -46,7 +47,7 @@ const _generatePaths = (srv, srvDefinition) => { //removing instances of graphql protocol from paths for (var index = paths.length - 1; index >= 0; index--) { if (paths[index].kind === "graphql") { - console.warn("Graphql protocol is not supported."); + Logger.warn('Graphql protocol is not supported.'); paths.splice(index, 1); } } @@ -106,7 +107,7 @@ const createGroupsTemplateForService = (serviceName, serviceDefinition, appConfi const ordExtensions = readORDExtensions(serviceDefinition); if (!serviceDefinition) { - console.warn("Unable to find service definition:", serviceName) + Logger.warn('Unable to find service definition:', serviceName) return undefined } From df171ce92549f65db70cf743d350c9bb489a15f9 Mon Sep 17 00:00:00 2001 From: Albin Ramovic Date: Thu, 14 Nov 2024 16:45:34 +0100 Subject: [PATCH 3/8] add 'non-existing custom ord file' test and small clean-up --- .../unittest/extendOrdWithCustom.test.js | 22 +++++++++---------- lib/extendOrdWithCustom.js | 22 ++++++------------- 2 files changed, 17 insertions(+), 27 deletions(-) diff --git a/__tests__/unittest/extendOrdWithCustom.test.js b/__tests__/unittest/extendOrdWithCustom.test.js index 7679c45..16d4d05 100644 --- a/__tests__/unittest/extendOrdWithCustom.test.js +++ b/__tests__/unittest/extendOrdWithCustom.test.js @@ -2,10 +2,6 @@ const cds = require("@sap/cds"); const path = require('path'); const { extendCustomORDContentIfExists } = require('../../lib/extendOrdWithCustom'); -jest.mock('path', () => ({ - join: jest.fn(), -})); - jest.mock("@sap/cds", () => { const actualCds = jest.requireActual('@sap/cds'); return { @@ -29,24 +25,26 @@ describe('extendOrdWithCustom', () => { }; }); - afterEach(() => { - jest.resetModules(); - jest.clearAllMocks(); - }); - describe('extendCustomORDContentIfExists', () => { - it('should skip if there is no custom ord file', () => { + it('should skip if there is no customOrdContentFile property in the .cdsrc.json', () => { const ordContent = {}; appConfig.env.customOrdContentFile = undefined; const result = extendCustomORDContentIfExists(appConfig, ordContent); expect(result).toEqual(ordContent); }); + it('should skip if customOrdContentFile property in the .cdsrc.json points to NON-EXISTING custom ord file', () => { + const ordContent = {}; + appConfig.env.customOrdContentFile = "./ord/NotExistingCustom.ord.json"; + const result = extendCustomORDContentIfExists(appConfig, ordContent); + expect(result).toEqual(ordContent); + }); + it('should ignore and log warn if found ord top-level primitive property in customOrdFile', () => { const ordContent = {}; const warningSpy = jest.spyOn(console, 'warn'); prepareTestEnvironment({ namespace: "sap.sample" }, appConfig, 'testCustomORDContentFileThrowErrors.json'); - const result = extendCustomORDContentIfExists(appConfig, ordContent, cds.log()); + const result = extendCustomORDContentIfExists(appConfig, ordContent); expect(warningSpy).toHaveBeenCalledTimes(3); expect(warningSpy).toHaveBeenCalledWith('Mocked warning'); @@ -120,5 +118,5 @@ describe('extendOrdWithCustom', () => { function prepareTestEnvironment(ordEnvVariables, appConfig, testFileName) { cds.env["ord"] = ordEnvVariables; appConfig.env.customOrdContentFile = testFileName; - path.join.mockReturnValue(`${__dirname}/utils/${testFileName}`); + jest.spyOn(path, 'join').mockReturnValue(`${__dirname}/utils/${testFileName}`); } diff --git a/lib/extendOrdWithCustom.js b/lib/extendOrdWithCustom.js index 71e75af..6847fa0 100644 --- a/lib/extendOrdWithCustom.js +++ b/lib/extendOrdWithCustom.js @@ -1,10 +1,9 @@ -const { CONTENT_MERGE_KEY } = require('./constants'); +const { CONTENT_MERGE_KEY } = require("./constants"); const cds = require("@sap/cds"); +const fs = require("fs"); const { Logger } = require("./logger"); const path = require("path"); -const _ = require('lodash'); - - +const _ = require("lodash"); function cleanNullProperties(obj) { for (const key in obj) { @@ -49,21 +48,14 @@ function compareAndHandleCustomORDContentWithExistingContent(ordContent, customO } function getCustomORDContent(appConfig) { - let customORDContent; - - if (appConfig.env?.customOrdContentFile) { - customORDContent = require(path.join(cds.root, appConfig.env.customOrdContentFile)); - } - return customORDContent; + if (!appConfig.env?.customOrdContentFile) return; + const pathToCustomORDContent = path.join(cds.root, appConfig.env?.customOrdContentFile); + if (fs.existsSync(pathToCustomORDContent)) return require(pathToCustomORDContent); } function extendCustomORDContentIfExists(appConfig, ordContent) { const customORDContent = getCustomORDContent(appConfig); - - if (customORDContent) { - ordContent = compareAndHandleCustomORDContentWithExistingContent(ordContent, customORDContent); - } - return ordContent; + return customORDContent ? compareAndHandleCustomORDContentWithExistingContent(ordContent, customORDContent) : ordContent; } module.exports = { From 193a81afd04f1866886a57269ee39f6a226d6d4f Mon Sep 17 00:00:00 2001 From: Albin Ramovic Date: Thu, 14 Nov 2024 16:54:19 +0100 Subject: [PATCH 4/8] minor changes --- __tests__/unittest/extendOrdWithCustom.test.js | 2 +- lib/extendOrdWithCustom.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/__tests__/unittest/extendOrdWithCustom.test.js b/__tests__/unittest/extendOrdWithCustom.test.js index 16d4d05..d483451 100644 --- a/__tests__/unittest/extendOrdWithCustom.test.js +++ b/__tests__/unittest/extendOrdWithCustom.test.js @@ -46,7 +46,7 @@ describe('extendOrdWithCustom', () => { prepareTestEnvironment({ namespace: "sap.sample" }, appConfig, 'testCustomORDContentFileThrowErrors.json'); const result = extendCustomORDContentIfExists(appConfig, ordContent); - expect(warningSpy).toHaveBeenCalledTimes(3); + expect(warningSpy).toHaveBeenCalledTimes(4); expect(warningSpy).toHaveBeenCalledWith('Mocked warning'); expect(result).toMatchSnapshot(); diff --git a/lib/extendOrdWithCustom.js b/lib/extendOrdWithCustom.js index 6847fa0..10babf6 100644 --- a/lib/extendOrdWithCustom.js +++ b/lib/extendOrdWithCustom.js @@ -50,7 +50,10 @@ function compareAndHandleCustomORDContentWithExistingContent(ordContent, customO function getCustomORDContent(appConfig) { if (!appConfig.env?.customOrdContentFile) return; const pathToCustomORDContent = path.join(cds.root, appConfig.env?.customOrdContentFile); - if (fs.existsSync(pathToCustomORDContent)) return require(pathToCustomORDContent); + if (fs.existsSync(pathToCustomORDContent)) { + Logger.warn(`Custom ORD content file not found at ${pathToCustomORDContent}`); + return require(pathToCustomORDContent); + } } function extendCustomORDContentIfExists(appConfig, ordContent) { From 7cc03b5526d73f4f0db3e8614277e55348049f9d Mon Sep 17 00:00:00 2001 From: Albin Ramovic Date: Thu, 14 Nov 2024 17:10:03 +0100 Subject: [PATCH 5/8] add mock for error log function --- __tests__/unittest/extendOrdWithCustom.test.js | 3 ++- lib/extendOrdWithCustom.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/__tests__/unittest/extendOrdWithCustom.test.js b/__tests__/unittest/extendOrdWithCustom.test.js index d483451..c1e3fb6 100644 --- a/__tests__/unittest/extendOrdWithCustom.test.js +++ b/__tests__/unittest/extendOrdWithCustom.test.js @@ -10,6 +10,7 @@ jest.mock("@sap/cds", () => { log: jest.fn(() => ({ levels: { DEBUG: 0, WARN: 1 }, warn: jest.fn(() => console.warn('Mocked warning')), + error: jest.fn(() => console.error('Mocked error')), })), }; }); @@ -46,7 +47,7 @@ describe('extendOrdWithCustom', () => { prepareTestEnvironment({ namespace: "sap.sample" }, appConfig, 'testCustomORDContentFileThrowErrors.json'); const result = extendCustomORDContentIfExists(appConfig, ordContent); - expect(warningSpy).toHaveBeenCalledTimes(4); + expect(warningSpy).toHaveBeenCalledTimes(3); expect(warningSpy).toHaveBeenCalledWith('Mocked warning'); expect(result).toMatchSnapshot(); diff --git a/lib/extendOrdWithCustom.js b/lib/extendOrdWithCustom.js index 10babf6..a7e5f37 100644 --- a/lib/extendOrdWithCustom.js +++ b/lib/extendOrdWithCustom.js @@ -51,7 +51,7 @@ function getCustomORDContent(appConfig) { if (!appConfig.env?.customOrdContentFile) return; const pathToCustomORDContent = path.join(cds.root, appConfig.env?.customOrdContentFile); if (fs.existsSync(pathToCustomORDContent)) { - Logger.warn(`Custom ORD content file not found at ${pathToCustomORDContent}`); + Logger.error(`Custom ORD content file not found at ${pathToCustomORDContent}`); return require(pathToCustomORDContent); } } From fddf27f060e5d9716936c06ba05a2d17bec10f85 Mon Sep 17 00:00:00 2001 From: Albin Ramovic Date: Thu, 14 Nov 2024 17:19:12 +0100 Subject: [PATCH 6/8] replace template literals with comma-separated values --- lib/extendOrdWithCustom.js | 4 ++-- lib/metaData.js | 6 +++--- lib/ord.js | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/extendOrdWithCustom.js b/lib/extendOrdWithCustom.js index a7e5f37..3d07528 100644 --- a/lib/extendOrdWithCustom.js +++ b/lib/extendOrdWithCustom.js @@ -34,7 +34,7 @@ function compareAndHandleCustomORDContentWithExistingContent(ordContent, customO for (const key in customORDContent) { const propertyType = typeof customORDContent[key]; if (propertyType !== 'object' && propertyType !== 'array') { - Logger.warn(`Found ord top level primitive ord property in customOrdFile: ${key}. Please define it in .cdsrc.json.`); + Logger.warn('Found ord top level primitive ord property in customOrdFile:', key, '. Please define it in .cdsrc.json.'); continue; } @@ -51,7 +51,7 @@ function getCustomORDContent(appConfig) { if (!appConfig.env?.customOrdContentFile) return; const pathToCustomORDContent = path.join(cds.root, appConfig.env?.customOrdContentFile); if (fs.existsSync(pathToCustomORDContent)) { - Logger.error(`Custom ORD content file not found at ${pathToCustomORDContent}`); + Logger.error('Custom ORD content file not found at', pathToCustomORDContent); return require(pathToCustomORDContent); } } diff --git a/lib/metaData.js b/lib/metaData.js index 9e45000..650775c 100644 --- a/lib/metaData.js +++ b/lib/metaData.js @@ -17,7 +17,7 @@ module.exports = async (data) => { try { responseFile = openapi(csn, options); } catch (error) { - Logger.error("OpenApi error:", error.message); + Logger.error('OpenApi error:', error.message); throw error; } break; @@ -25,7 +25,7 @@ module.exports = async (data) => { try { responseFile = asyncapi(csn, options); } catch (error) { - Logger.error("AsyncApi error:", error.message); + Logger.error('AsyncApi error:', error.message); throw error; } break; @@ -33,7 +33,7 @@ module.exports = async (data) => { try { responseFile = await cds.compile(csn).to["edmx"](options); } catch (error) { - Logger.error("Edmx error:", error.message); + Logger.error('Edmx error:', error.message); throw error; } } diff --git a/lib/ord.js b/lib/ord.js index c15159f..c8132bb 100644 --- a/lib/ord.js +++ b/lib/ord.js @@ -123,7 +123,7 @@ function validateNamespace(appConfig) { let error = new Error( `Namespace is not defined in cdsrc.json or it is not in the format of ${appConfig.eventApplicationNamespace}..` ); - Logger.error("Namespace error:", error.message); + Logger.error('Namespace error:', error.message); throw error; } } From 1a770a1da8f4516712f3bc4763024fee151547ad Mon Sep 17 00:00:00 2001 From: Albin Ramovic Date: Fri, 15 Nov 2024 12:51:36 +0100 Subject: [PATCH 7/8] minor changes: increase code-coverage in tests --- __tests__/unittest/extendOrdWithCustom.test.js | 2 +- __tests__/unittest/templates.test.js | 5 +++++ lib/templates.js | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/__tests__/unittest/extendOrdWithCustom.test.js b/__tests__/unittest/extendOrdWithCustom.test.js index c1e3fb6..4052a98 100644 --- a/__tests__/unittest/extendOrdWithCustom.test.js +++ b/__tests__/unittest/extendOrdWithCustom.test.js @@ -119,5 +119,5 @@ describe('extendOrdWithCustom', () => { function prepareTestEnvironment(ordEnvVariables, appConfig, testFileName) { cds.env["ord"] = ordEnvVariables; appConfig.env.customOrdContentFile = testFileName; - jest.spyOn(path, 'join').mockReturnValue(`${__dirname}/utils/${testFileName}`); + jest.spyOn(path, 'join').mockReturnValueOnce(`${__dirname}/utils/${testFileName}`); } diff --git a/__tests__/unittest/templates.test.js b/__tests__/unittest/templates.test.js index 3190f81..de9dfed 100644 --- a/__tests__/unittest/templates.test.js +++ b/__tests__/unittest/templates.test.js @@ -43,6 +43,11 @@ describe('templates', () => { }; expect(createGroupsTemplateForService(testServiceName, linkedModel, appConfig)).toEqual(testResult); }); + + it('should return undefined when no service definition', () => { + const testServiceName = 'testServiceName'; + expect(createGroupsTemplateForService(testServiceName, null, appConfig)).not.toBeDefined(); + }); }); describe('createAPIResourceTemplate', () => { diff --git a/lib/templates.js b/lib/templates.js index fa16f9c..6515cf3 100644 --- a/lib/templates.js +++ b/lib/templates.js @@ -52,7 +52,7 @@ const _generatePaths = (srv, srvDefinition) => { } } - //putting default as odata in case no supported protcol is there + //putting OData as default in case of non-supported protocol if (paths.length === 0) { srvDefinition["@odata"] = true; paths.push({ kind: "odata", path: protocols.path4(srvDefinition) }); From c8d1d98f9ae3cc7fa19918e27e7082006f3eeb4c Mon Sep 17 00:00:00 2001 From: Albin Ramovic Date: Fri, 15 Nov 2024 13:01:13 +0100 Subject: [PATCH 8/8] minor changes: increase code-coverage in tests --- __tests__/unittest/templates.test.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/__tests__/unittest/templates.test.js b/__tests__/unittest/templates.test.js index de9dfed..db86572 100644 --- a/__tests__/unittest/templates.test.js +++ b/__tests__/unittest/templates.test.js @@ -44,6 +44,16 @@ describe('templates', () => { expect(createGroupsTemplateForService(testServiceName, linkedModel, appConfig)).toEqual(testResult); }); + it('should return default value with a proper Service title when "Service" keyword is missing', () => { + const testServiceName = 'testServName'; + const testResult = { + groupId: 'sap.cds:service:customer.testNamespace:testServName', + groupTypeId: 'sap.cds:service', + title: 'testServName Service' + }; + expect(createGroupsTemplateForService(testServiceName, linkedModel, appConfig)).toEqual(testResult); + }); + it('should return undefined when no service definition', () => { const testServiceName = 'testServiceName'; expect(createGroupsTemplateForService(testServiceName, null, appConfig)).not.toBeDefined();