From 8eadaa010c4ebf4b760fd8a3c97b061d2e8f2aa9 Mon Sep 17 00:00:00 2001 From: Christian Westgaard Date: Tue, 5 Mar 2024 14:37:21 +0100 Subject: [PATCH] Fix #69: Rename url to path and do not prefix with baseUrl Fix #72 Move sitemap field under portalSite Content ObjectType Fix #73: sitemap should return null in Guillotine when the app is not installed on the nearest site --- package-lock.json | 8 +- package.json | 2 +- src/main/resources/guillotine/constants.ts | 13 + src/main/resources/guillotine/guillotine.d.ts | 9 + src/main/resources/guillotine/guillotine.ts | 224 ++---------------- .../resources/guillotine/resolvers/sitemap.ts | 94 ++++++++ .../resources/guillotine/resolvers/urlset.ts | 126 ++++++++++ .../types/buildObjectTypeSiteMap.ts | 17 ++ .../types/buildObjectTypeSiteMapUrl.ts | 20 ++ .../resources/lib/app-sitemapxml/constants.ts | 9 + .../app-sitemapxml/queryForSitemapContent.ts | 12 +- test/guillotine/guillotine.test.ts | 65 +++-- 12 files changed, 356 insertions(+), 243 deletions(-) create mode 100644 src/main/resources/guillotine/constants.ts create mode 100644 src/main/resources/guillotine/guillotine.d.ts create mode 100644 src/main/resources/guillotine/resolvers/sitemap.ts create mode 100644 src/main/resources/guillotine/resolvers/urlset.ts create mode 100644 src/main/resources/guillotine/types/buildObjectTypeSiteMap.ts create mode 100644 src/main/resources/guillotine/types/buildObjectTypeSiteMapUrl.ts create mode 100644 src/main/resources/lib/app-sitemapxml/constants.ts diff --git a/package-lock.json b/package-lock.json index ad1a934..59fa958 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ }, "devDependencies": { "@enonic-types/global": "^7.14.0", - "@enonic-types/guillotine": "^0.0.2", + "@enonic-types/guillotine": "^7.1.0-B1", "@enonic-types/lib-content": "^7.14.0", "@enonic-types/lib-context": "^7.14.0", "@enonic-types/lib-portal": "^7.14.0", @@ -703,9 +703,9 @@ "dev": true }, "node_modules/@enonic-types/guillotine": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@enonic-types/guillotine/-/guillotine-0.0.2.tgz", - "integrity": "sha512-zHMaFSft6cyTc+slqsKGL55hvRwCDpCEvJpwrsCXqws7GXy5DbEZD0fsG7AdcLAUXKK9g2w6EzUxpYenDj3d3w==", + "version": "7.1.0-B1", + "resolved": "https://registry.npmjs.org/@enonic-types/guillotine/-/guillotine-7.1.0-B1.tgz", + "integrity": "sha512-YnfHY9iRmoOwEa4Cj1btRIWCEBdvRZJOS3DhjahPomj5bOy/6X5/7w0wwgxtnDsEbS9jMSqCKk7M3RzY7JP+ew==", "dev": true, "dependencies": { "@enonic-types/core": "^7.14.0", diff --git a/package.json b/package.json index 816e2f1..ec2dcbe 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "devDependencies": { "@enonic-types/global": "^7.14.0", - "@enonic-types/guillotine": "^0.0.2", + "@enonic-types/guillotine": "^7.1.0-B1", "@enonic-types/lib-content": "^7.14.0", "@enonic-types/lib-context": "^7.14.0", "@enonic-types/lib-portal": "^7.14.0", diff --git a/src/main/resources/guillotine/constants.ts b/src/main/resources/guillotine/constants.ts new file mode 100644 index 0000000..b8b294f --- /dev/null +++ b/src/main/resources/guillotine/constants.ts @@ -0,0 +1,13 @@ +export const DEBUG = false; +export const TRACE = false; +// const PROFILING = false; + +// In type names first letter should be uppercase +export const enum GraphQLTypeName { + SITEMAP = 'Sitemap', + SITEMAP_URL = 'Sitemap_Url', +} + +// In fields names first letter should be lowercase +export const SITEMAP_FIELD_NAME = 'sitemap'; +export const URLSET_FIELD_NAME = 'urlset'; diff --git a/src/main/resources/guillotine/guillotine.d.ts b/src/main/resources/guillotine/guillotine.d.ts new file mode 100644 index 0000000..2e0af90 --- /dev/null +++ b/src/main/resources/guillotine/guillotine.d.ts @@ -0,0 +1,9 @@ +export declare interface SiteMapResolverData { + baseUrl: string|null +} + +export declare interface SiteMapResolverLocaleContext { + siteJson: string + siteConfigJson: string + [x: string]: string +} diff --git a/src/main/resources/guillotine/guillotine.ts b/src/main/resources/guillotine/guillotine.ts index 4aff780..23f5f94 100644 --- a/src/main/resources/guillotine/guillotine.ts +++ b/src/main/resources/guillotine/guillotine.ts @@ -2,86 +2,27 @@ import type { Extensions, GraphQL, } from '@enonic-types/guillotine'; -import type {Site} from '@enonic-types/lib-content'; -import type { - SitemapXmlSiteConfig, - tChangeFreq, - tPriority, -} from '/types'; import {ObjectTypeName} from '@enonic-types/guillotine'; import { - get as getContentByKey, -} from '/lib/xp/content'; -import { - get as getContext, - run as runInContext -} from '/lib/xp/context'; -import {getSiteConfigFromSite} from '/guillotine/getSiteConfigFromSite'; -// import {safeMs} from '/guillotine/safeMs'; -import {queryForSitemapContent} from '/lib/app-sitemapxml/queryForSitemapContent'; - - -const DEBUG = false; -const TRACE = false; -// const PROFILING = false; - -// @ts-ignore -// const {currentTimeMillis} = Java.type('java.lang.System') as { -// currentTimeMillis: () => number -// } - - -// In type names first letter should be uppercase -const enum GraphQLTypeName { - SITEMAP = 'Sitemap', - SITEMAP_URL = 'SitemapUrl', -} - -// In fields names first letter should be lowercase -const SITEMAP_FIELD_NAME = 'sitemap'; -const URLSET_FIELD_NAME = 'urlset'; - - -interface SitemapUrl { - changefreq?: tChangeFreq - lastmod?: string - priority?: tPriority - url: string -} + SITEMAP_FIELD_NAME, + URLSET_FIELD_NAME, + GraphQLTypeName, +} from '/guillotine/constants'; +import {buildObjectTypeSiteMap} from '/guillotine/types/buildObjectTypeSiteMap'; +import {buildObjectTypeSiteMapUrl} from '/guillotine/types/buildObjectTypeSiteMapUrl'; +import {buildSitemapResolver} from './resolvers/sitemap'; +import {urlset} from '/guillotine/resolvers/urlset'; export const extensions = (graphQL: GraphQL): Extensions => ({ types: { - [GraphQLTypeName.SITEMAP]: { - description: 'Sitemap', - fields: { - urlset: { - type: graphQL.list(graphQL.reference(GraphQLTypeName.SITEMAP_URL)), - } - } - }, - [GraphQLTypeName.SITEMAP_URL]: { - description: 'Sitemap URL item', - fields: { - url: { - type: graphQL.nonNull(graphQL.GraphQLString), - }, - changefreq: { - type: graphQL.GraphQLString - }, - lastmod: { - type: graphQL.DateTime, - }, - priority: { - type: graphQL.GraphQLString - }, - } - } + [GraphQLTypeName.SITEMAP]: buildObjectTypeSiteMap(graphQL), + [GraphQLTypeName.SITEMAP_URL]: buildObjectTypeSiteMapUrl(graphQL), }, creationCallbacks: { - [ObjectTypeName.HeadlessCms]: (params) => { + [ObjectTypeName.portal_Site]: (params) => { params.addFields({ [SITEMAP_FIELD_NAME]: { type: graphQL.reference(GraphQLTypeName.SITEMAP), @@ -97,143 +38,14 @@ export const extensions = (graphQL: GraphQL): Extensions => ({ type: graphQL.list(graphQL.reference(GraphQLTypeName.SITEMAP_URL)), }, }); - } + }, }, resolvers: { - [ObjectTypeName.HeadlessCms]: { - [SITEMAP_FIELD_NAME]: (env) => { - TRACE && log.debug(`resolvers ${SITEMAP_FIELD_NAME} env: ${JSON.stringify(env, null, 4)}`); - const { - args, - localContext, - // source - } = env; - const { - branch, - project, - siteKey // NOTE: Can be undefined when x-guillotine-sitekey is missing - } = localContext; - TRACE && log.debug(`resolvers ${SITEMAP_FIELD_NAME} siteKey: ${siteKey}`); - if (!siteKey) { - return null; - } - const context = getContext(); - const { - authInfo: { - principals = [] // Handle undefined - } = {} - } = context; - return runInContext({ - branch, - repository: `com.enonic.cms.${project}`, - principals: principals || [] // Handle null - }, () => { - const site = getContentByKey>({key: siteKey}); - TRACE && log.debug(`resolvers ${SITEMAP_FIELD_NAME} site: ${JSON.stringify(site, null, 4)}`); - if (!site) { - return null; - } - const siteConfig = getSiteConfigFromSite({ - applicationKey: app.name, - site, - }); - return { - _site: site, - _siteConfig: siteConfig, - }; - }); // runInContext - } // SITEMAP_FIELD_NAME - }, // HeadlessCms + [ObjectTypeName.portal_Site]: { + [SITEMAP_FIELD_NAME]: buildSitemapResolver(graphQL), + }, [GraphQLTypeName.SITEMAP]: { - [URLSET_FIELD_NAME]: (env) => { - TRACE && log.debug(`resolvers ${URLSET_FIELD_NAME} env: ${JSON.stringify(env, null, 4)}`); - - const { - args, - localContext, - source - } = env; - TRACE && log.debug(`resolvers ${URLSET_FIELD_NAME} source: ${JSON.stringify(source, null, 4)}`); - - const { - _site, - _siteConfig - } = source as { - _site: Site, - _siteConfig: SitemapXmlSiteConfig - }; - - const { - branch, - project, - siteKey // NOTE: Can be undefined when x-guillotine-sitekey is missing - } = localContext; - TRACE && log.debug(`resolvers ${URLSET_FIELD_NAME} siteKey: ${siteKey}`); - - if (!siteKey) { - return null; - } - // const startMs = PROFILING ? currentTimeMillis() : 0; - const context = getContext(); - const { - authInfo: { - principals = [] // Handle undefined - } = {} - } = context; - return runInContext({ - branch, - repository: `com.enonic.cms.${project}`, - principals: principals || [] // Handle null - }, () => { - TRACE && log.debug(`resolvers ${URLSET_FIELD_NAME} _siteConfig: ${JSON.stringify(_siteConfig, null, 4)}`); - const { - overrideDomain = '', - } = _siteConfig || {}; - - const { - count - } = args; - - const { - changefreq, - priority, - result - } = queryForSitemapContent({ - count, - site: _site, - siteConfig: _siteConfig - }) - - // Go through the results and add the corresponding settings for each match. - const items: SitemapUrl[] = []; - for (let i = 0; i < result.hits.length; i++) { - if (result.hits[i].type) { - TRACE && log.debug(`resolvers ${URLSET_FIELD_NAME} result.hits[${i}].type: ${result.hits[i].type}`); - const path = result.hits[i]._path.replace(_site._path, '') || '/'; - items.push({ - changefreq: changefreq[result.hits[i].type], - lastmod: result.hits[i].modifiedTime, - priority: priority[result.hits[i].type], - url: overrideDomain ? `${overrideDomain}${path}`.replace(/\/\//g, '/') : path - }); - } - } - - DEBUG && log.debug(`resolvers ${URLSET_FIELD_NAME} first item: ${JSON.stringify(items[0], null, 4)}`); - TRACE && log.debug(`resolvers ${URLSET_FIELD_NAME} all items: ${JSON.stringify(items, null, 4)}`); - - // if (PROFILING) { - // const endMs = currentTimeMillis(); - // const durationMs = endMs - startMs; - // log.debug(`resolvers ${URLSET_FIELD_NAME} durationMs: ${safeMs(durationMs)}`); - // } - - return items; - // return { - // urlset: items - // }; - }); // runInContext - }, // SITEMAP_XML - }, // HEADLESS_CMS - } // resolvers + [URLSET_FIELD_NAME]: urlset(graphQL), + } + } }); diff --git a/src/main/resources/guillotine/resolvers/sitemap.ts b/src/main/resources/guillotine/resolvers/sitemap.ts new file mode 100644 index 0000000..21580b2 --- /dev/null +++ b/src/main/resources/guillotine/resolvers/sitemap.ts @@ -0,0 +1,94 @@ +import type {Site} from '@enonic-types/lib-content'; +import type { + DataFetcherResult, + GraphQL, + Resolver, +} from '@enonic-types/guillotine'; +import type { + SiteMapResolverData, + SiteMapResolverLocaleContext +} from '/guillotine/guillotine.d'; +import type { + SitemapXmlSiteConfig, + // tChangeFreq, + // tPriority, +} from '/types'; + +import {get as getContentByKey} from '/lib/xp/content'; +import { + get as getContext, + run as runInContext +} from '/lib/xp/context'; +// import { +// DEFAULT_PRIORITY, +// DEFAULT_UPDATE_PERIOD +// } from '/lib/app-sitemapxml/constants'; +import { + // DEBUG, + SITEMAP_FIELD_NAME, + TRACE, +} from '/guillotine/constants'; +import {getSiteConfigFromSite} from '/guillotine/getSiteConfigFromSite'; + + +export const buildSitemapResolver = (graphQL: GraphQL): Resolver< + {}, // args + {}, // localContext + Site, + DataFetcherResult|null +> => (env) => { + TRACE && log.debug(`resolvers ${SITEMAP_FIELD_NAME} env: ${JSON.stringify(env, null, 4)}`); + const { + // args, + localContext, + source: siteWithoutSiteConfig + } = env; + TRACE && log.debug(`resolvers ${SITEMAP_FIELD_NAME} siteWithoutSiteConfig: ${JSON.stringify(siteWithoutSiteConfig, null, 4)}`); + + const { + branch, + project, + // siteKey // NOTE: Can be undefined when x-guillotine-sitekey is missing + } = localContext; + // TRACE && log.debug(`resolvers ${SITEMAP_FIELD_NAME} siteKey: ${siteKey}`); + // if (!siteKey) { + // return null; + // } + const context = getContext(); + const { + authInfo: { + principals = [] // Handle undefined + } = {} + } = context; + return runInContext({ + branch, + repository: `com.enonic.cms.${project}`, + principals: principals || [] // Handle null + }, () => { + const site = getContentByKey>({key: siteWithoutSiteConfig._path}); + TRACE && log.debug(`resolvers ${SITEMAP_FIELD_NAME} site: ${JSON.stringify(site, null, 4)}`); + const siteConfig = getSiteConfigFromSite({ + applicationKey: app.name, + site: site as Site, + }); + if (!siteConfig) { + return null; + } + const { + overrideDomain: baseUrl = null + } = siteConfig || {}; + return graphQL.createDataFetcherResult< + SiteMapResolverData, + SiteMapResolverLocaleContext + >({ + data: __.toScriptValue({ + baseUrl, + }), + localContext: { + siteJson: JSON.stringify(site), + siteConfigJson: JSON.stringify(siteConfig), + }, + parentLocalContext: localContext, + }); + }); // runInContext +}; diff --git a/src/main/resources/guillotine/resolvers/urlset.ts b/src/main/resources/guillotine/resolvers/urlset.ts new file mode 100644 index 0000000..07b32d8 --- /dev/null +++ b/src/main/resources/guillotine/resolvers/urlset.ts @@ -0,0 +1,126 @@ +import type { + GraphQL, + Resolver, +} from '@enonic-types/guillotine'; +import type {Site} from '@enonic-types/lib-content'; +import type { + SiteMapResolverData, + SiteMapResolverLocaleContext +} from '/guillotine/guillotine.d'; +import type { + SitemapXmlSiteConfig, + tChangeFreq, + tPriority, +} from '/types'; + + +import {toStr} from '@enonic/js-utils/value/toStr'; +import { + get as getContext, + run as runInContext +} from '/lib/xp/context'; +import { + DEFAULT_PRIORITY, + DEFAULT_UPDATE_PERIOD +} from '/lib/app-sitemapxml/constants'; +import {queryForSitemapContent} from '/lib/app-sitemapxml/queryForSitemapContent'; +import { + DEBUG, + // PROFILING, + TRACE, + URLSET_FIELD_NAME +} from '/guillotine/constants'; +// import {safeMs} from '/guillotine/safeMs'; + + +interface SitemapUrl { + changefreq?: tChangeFreq + lastmod?: string + priority?: tPriority + path: string +} + +// @ts-ignore +// const {currentTimeMillis} = Java.type('java.lang.System') as { +// currentTimeMillis: () => number +// } + +export const urlset = (graphQL: GraphQL): Resolver< + { + count?: number + }, + SiteMapResolverLocaleContext, + SiteMapResolverData, + {} +> => (env) => { + TRACE && log.debug('%s resolver env: %s', URLSET_FIELD_NAME, toStr(env)); + const { + args, + localContext, + // source + } = env; + + const site = JSON.parse(localContext.siteJson as string) as Site; + TRACE && log.debug('%s resolver site: %s', URLSET_FIELD_NAME, toStr(site)); + + const siteConfig = JSON.parse(localContext.siteConfigJson as string) as SitemapXmlSiteConfig; + TRACE && log.debug('%s resolver siteConfig: %s', URLSET_FIELD_NAME, toStr(siteConfig)); + + const { + branch, + project, + } = localContext; + + // const startMs = PROFILING ? currentTimeMillis() : 0; + const context = getContext(); + const { + authInfo: { + principals = [] // Handle undefined + } = {} + } = context; + return runInContext({ + branch, + repository: `com.enonic.cms.${project}`, + principals: principals || [] // Handle null + }, () => { + const { + count + } = args; + + const { + changefreq, + priority, + result + } = queryForSitemapContent({ + count, + site, + siteConfig + }) + + // Go through the results and add the corresponding settings for each match. + const items: SitemapUrl[] = []; + for (let i = 0; i < result.hits.length; i++) { + if (result.hits[i].type) { + TRACE && log.debug('%s resolver result.hits[%s].type: %s', URLSET_FIELD_NAME, i, result.hits[i].type); + const path = result.hits[i]._path.replace(site._path, '') || '/'; + items.push({ + changefreq: changefreq[result.hits[i].type] === DEFAULT_UPDATE_PERIOD ? undefined : changefreq[result.hits[i].type], + lastmod: result.hits[i].modifiedTime, + priority: priority[result.hits[i].type] === DEFAULT_PRIORITY ? undefined : priority[result.hits[i].type], + path + }); + } + } + + DEBUG && log.debug('%s resolver first item: %s', URLSET_FIELD_NAME, toStr(items[0])); + TRACE && log.debug('%s resolver all items: %s', URLSET_FIELD_NAME, toStr(items)); + + // if (PROFILING) { + // const endMs = currentTimeMillis(); + // const durationMs = endMs - startMs; + // log.debug(`resolvers ${URLSET_FIELD_NAME} durationMs: ${safeMs(durationMs)}`); + // } + + return items; + }); +} diff --git a/src/main/resources/guillotine/types/buildObjectTypeSiteMap.ts b/src/main/resources/guillotine/types/buildObjectTypeSiteMap.ts new file mode 100644 index 0000000..358c957 --- /dev/null +++ b/src/main/resources/guillotine/types/buildObjectTypeSiteMap.ts @@ -0,0 +1,17 @@ +import type {GraphQL} from '@enonic-types/guillotine'; + + +import {GraphQLTypeName} from '/guillotine/constants'; + + +export const buildObjectTypeSiteMap = (graphQL: GraphQL) => ({ + description: 'Sitemap', + fields: { + baseUrl: { + type: graphQL.GraphQLString, + }, + urlset: { + type: graphQL.list(graphQL.reference(GraphQLTypeName.SITEMAP_URL)), + } + } +}); diff --git a/src/main/resources/guillotine/types/buildObjectTypeSiteMapUrl.ts b/src/main/resources/guillotine/types/buildObjectTypeSiteMapUrl.ts new file mode 100644 index 0000000..e0e57d5 --- /dev/null +++ b/src/main/resources/guillotine/types/buildObjectTypeSiteMapUrl.ts @@ -0,0 +1,20 @@ +import type {GraphQL} from '@enonic-types/guillotine'; + + +export const buildObjectTypeSiteMapUrl = (graphQL: GraphQL) => ({ + description: 'Sitemap URL item', + fields: { + changefreq: { + type: graphQL.GraphQLString + }, + lastmod: { + type: graphQL.DateTime, + }, + path: { + type: graphQL.nonNull(graphQL.GraphQLString), + }, + priority: { + type: graphQL.GraphQLString + }, + } +}); diff --git a/src/main/resources/lib/app-sitemapxml/constants.ts b/src/main/resources/lib/app-sitemapxml/constants.ts new file mode 100644 index 0000000..0bd7a89 --- /dev/null +++ b/src/main/resources/lib/app-sitemapxml/constants.ts @@ -0,0 +1,9 @@ +import type { + tChangeFreq, + tPriority, +} from '/types'; + + +export const DEFAULT_PRIORITY: tPriority = '0.5'; + +export const DEFAULT_UPDATE_PERIOD: tChangeFreq = 'monthly'; diff --git a/src/main/resources/lib/app-sitemapxml/queryForSitemapContent.ts b/src/main/resources/lib/app-sitemapxml/queryForSitemapContent.ts index 737d24e..b762e25 100644 --- a/src/main/resources/lib/app-sitemapxml/queryForSitemapContent.ts +++ b/src/main/resources/lib/app-sitemapxml/queryForSitemapContent.ts @@ -11,15 +11,15 @@ import {isSet} from '@enonic/js-utils/value/isSet'; import { query as contentQuery } from '/lib/xp/content'; +import { + DEFAULT_PRIORITY, + DEFAULT_UPDATE_PERIOD +} from '/lib/app-sitemapxml/constants'; const GLOBALS: { - updatePeriod: tChangeFreq - priority: tPriority alwaysAdd: string } = { - updatePeriod: 'monthly', - priority: '0.5', alwaysAdd: 'portal:site', }; @@ -54,8 +54,8 @@ export function queryForSitemapContent({ if (cty === GLOBALS.alwaysAdd) { siteAdded = true; } arrContentTypes.push(cty); - changefreq[cty] = siteMapArray[j].updatePeriod || GLOBALS.updatePeriod; - priority[cty] = siteMapArray[j].priority || GLOBALS.priority; + changefreq[cty] = siteMapArray[j].updatePeriod || DEFAULT_UPDATE_PERIOD; + priority[cty] = siteMapArray[j].priority || DEFAULT_PRIORITY; } // Default settings for site (frontpage) set to be changed and prioritized often. diff --git a/test/guillotine/guillotine.test.ts b/test/guillotine/guillotine.test.ts index c677f99..a02140f 100644 --- a/test/guillotine/guillotine.test.ts +++ b/test/guillotine/guillotine.test.ts @@ -42,13 +42,12 @@ globalThis.log = { debug: console.debug, } +// @ts-ignore TS2339: Property '__' does not exist on type 'typeof globalThis'. +globalThis.__ = { + toScriptValue: (value: unknown) => value +} const graphQL: GraphQL = { - createDataFetcherResult: () => ({ - data: null as unknown as ScriptValue, - // localContext: {}// as LocalContext, - // parentLocalContext: {}// as LocalContext - }), Date: '2021-01-01' as GraphQLDate, DateTime: '2021-01-01T00:00:00Z' as GraphQLDateTime, GraphQLBoolean: true as GraphQLBoolean, @@ -59,15 +58,24 @@ const graphQL: GraphQL = { Json: '{"json": "value"}' as GraphQLJson, LocalTime: '00:00:00' as GraphQLLocalTime, LocalDateTime: '2021-01-01T00:00:00' as GraphQLLocalDateTime, + createDataFetcherResult: ({data, localContext, parentLocalContext}) => ({ + source: data as any, + localContext: {...parentLocalContext, ...localContext} + }), + // createDataFetcherResult: () => ({ + // data: null as unknown as ScriptValue, + // // localContext: {}// as LocalContext, + // // parentLocalContext: {}// as LocalContext + // }), list: (type) => [type], nonNull: (type) => type, reference: (typeName) => { - if (typeName === 'SitemapUrl') { + if (typeName === 'Sitemap_Url') { return { changefreq: null, lastmod: '2021-01-01T00:00:00Z', + path: null, priority: null, - url: null }; } console.debug('reference typeName', typeName); @@ -142,7 +150,7 @@ describe('guillotine extensions', () => { creationCallbacks: { }, resolvers: { - HeadlessCms: { + portal_Site: { }, Sitemap: { } @@ -151,17 +159,20 @@ describe('guillotine extensions', () => { Sitemap: { description: 'Sitemap', fields: { + baseUrl: { + type: 'string' + }, urlset: { type: [{ changefreq: null, lastmod: '2021-01-01T00:00:00Z', + path: null, priority: null, - url: null }] } } }, - SitemapUrl: { + Sitemap_Url: { description: 'Sitemap URL item', fields: { changefreq: { @@ -170,12 +181,12 @@ describe('guillotine extensions', () => { lastmod: { type: '2021-01-01T00:00:00Z' }, - priority: { + path: { type: 'string' }, - url: { + priority: { type: 'string' - } + }, } } } @@ -188,7 +199,7 @@ describe('guillotine extensions', () => { // Sitemap: SitemapFunction // }, resolvers: { - HeadlessCms: { + portal_Site: { sitemap: sitemapResolver }, Sitemap: { @@ -202,39 +213,41 @@ describe('guillotine extensions', () => { localContext: { branch: 'master', project: 'project', - siteKey: siteContent._path }, - source: {} + source: siteContent }); // print(sitemapResolverResult); expect(sitemapResolverResult).toEqual({ - _site: siteContent, - _siteConfig: siteConfig + localContext: { + branch: 'master', + project: 'project', + siteJson: JSON.stringify(siteContent), + siteConfigJson: JSON.stringify(siteConfig) + }, + source: { + baseUrl: 'https://enonic.com' + }, }); const urlsetResolverResult = urlsetResolver({ args: { count: 10 }, - localContext: { - branch: 'master', - project: 'project', - siteKey: siteContent._path - }, - source: sitemapResolverResult, + localContext: sitemapResolverResult.localContext, + source: sitemapResolverResult.source, }); // print(urlsetResolverResult); expect(urlsetResolverResult).toEqual([ { changefreq: 'hourly', lastmod: undefined, + path: '/', priority: '1.0', - url: 'https:/enonic.com/' },{ changefreq: undefined, lastmod: undefined, + path: '/folderContentPath', priority: undefined, - url: 'https:/enonic.com/folderContentPath' } ]); }); // import