merge
This commit is contained in:
Luis Tejeda
2022-06-22 12:38:01 -05:00
12 changed files with 515 additions and 75 deletions

View File

@@ -6,13 +6,15 @@ const {
localPointer, localPointer,
jsonPointerLevelSeparator, jsonPointerLevelSeparator,
isLocalRef, isLocalRef,
jsonPointerDecodeAndReplace jsonPointerDecodeAndReplace,
generateObjectName
} = require('./jsonPointer'), } = require('./jsonPointer'),
traverseUtility = require('traverse'), traverseUtility = require('traverse'),
parse = require('./parse.js'), parse = require('./parse.js'),
{ ParseError } = require('./common/ParseError'); { ParseError } = require('./common/ParseError'),
const { getBundleRulesDataByVersion } = require('./common/versionUtils'), Utils = require('./utils'),
Utils = require('./utils'); crypto = require('crypto'),
{ getBundleRulesDataByVersion } = require('./common/versionUtils');
let path = require('path'), let path = require('path'),
pathBrowserify = require('path-browserify'), pathBrowserify = require('path-browserify'),
@@ -184,15 +186,45 @@ function setValueInComponents(keyInComponents, components, value, version) {
} }
} }
/**
* Calculates the has of a provided key and join its first 4 numbers at the end of the current key by a _
* @param {string} currentKey The key we will hash
* @returns {string} A key with a hashed part joined by _
*/
function createComponentHashedKey(currentKey) {
let hashPart = crypto.createHash('sha1')
.update(currentKey)
.digest('base64')
.substring(0, 4),
newKey = generateObjectName(currentKey, hashPart);
return newKey;
}
/**
* Generates a not repeated mainKey for the component
* @param {string} tempRef - The reference to the node we are processing
* @param {array} mainKeys - A list of previous generated mainKeys
* @returns {string} A generated mainKey from the provided tempRef
*/
function createComponentMainKey(tempRef, mainKeys) {
let newKey = generateObjectName(tempRef),
mainKey = mainKeys[newKey];
if (mainKey && mainKey !== tempRef) {
newKey = createComponentHashedKey(tempRef);
}
return newKey;
}
/** /**
* Return a trace from the current node's root to the place where we find a $ref * Return a trace from the current node's root to the place where we find a $ref
* @param {object} nodeContext - The current node we are processing * @param {object} nodeContext - The current node we are processing
* @param {object} property - The current property that contains the $ref * @param {object} tempRef - The tempRef from the $ref
* @param {object} mainKeys - The dictionary of the previous keys generated
* @param {string} version - The current version of the spec * @param {string} version - The current version of the spec
* @param {string} commonPathFromData - The common path in the file's paths * @param {string} commonPathFromData - The common path in the file's paths
* @returns {array} The trace to the place where the $ref appears * @returns {array} The trace to the place where the $ref appears
*/ */
function getTraceFromParentKeyInComponents(nodeContext, property, version, commonPathFromData) { function getTraceFromParentKeyInComponents(nodeContext, tempRef, mainKeys, version, commonPathFromData) {
const parents = [...nodeContext.parents].reverse(), const parents = [...nodeContext.parents].reverse(),
isArrayKeyRegexp = new RegExp('^\\d$', 'g'), isArrayKeyRegexp = new RegExp('^\\d$', 'g'),
key = nodeContext.key, key = nodeContext.key,
@@ -204,11 +236,31 @@ function getTraceFromParentKeyInComponents(nodeContext, property, version, commo
parentKeys : parentKeys :
[key, ...parentKeys], [key, ...parentKeys],
nodeTrace = getRootFileTrace(nodeParentsKey), nodeTrace = getRootFileTrace(nodeParentsKey),
[file, local] = property.split(localPointer), componentKey = createComponentMainKey(tempRef, mainKeys),
keyTraceInComponents = getKeyInComponents(nodeTrace, file, local, version, commonPathFromData); keyTraceInComponents = getKeyInComponents(nodeTrace, componentKey, version, commonPathFromData);
return keyTraceInComponents; return keyTraceInComponents;
} }
/**
* Modifies the generated trace if there is a collision with a key that exists in root components object
* @param {array} trace The generated trace
* @param {object} initialMainKeys the main keys in local components object if it exists
* @returns {array} A modified trace if there is any collision with local reusable objects
*/
function handleLocalCollisions(trace, initialMainKeys) {
if (trace.length === 0) {
return trace;
}
const componentType = trace[trace.length - 2],
initialKeysOfType = initialMainKeys[componentType],
generatedKeyIndex = trace.length - 1;
if (initialKeysOfType && initialKeysOfType.includes(trace[generatedKeyIndex])) {
trace[generatedKeyIndex] = createComponentHashedKey(trace[generatedKeyIndex]);
}
return trace;
}
/** /**
* Gets all the $refs from an object * Gets all the $refs from an object
* @param {object} currentNode - current node in process * @param {object} currentNode - current node in process
@@ -216,12 +268,15 @@ function getTraceFromParentKeyInComponents(nodeContext, property, version, commo
* @param {Function} pathSolver - function to resolve the Path * @param {Function} pathSolver - function to resolve the Path
* @param {string} parentFilename - The parent's filename * @param {string} parentFilename - The parent's filename
* @param {object} version - The version of the spec we are bundling * @param {object} version - The version of the spec we are bundling
* @param {object} rootMainKeys - A dictionary with the component keys in local components object and its mainKeys
* @param {string} commonPathFromData - The common path in the file's paths * @param {string} commonPathFromData - The common path in the file's paths
* @returns {object} - The references in current node and the new content from the node * @returns {object} - The references in current node and the new content from the node
*/ */
function getReferences (currentNode, isOutOfRoot, pathSolver, parentFilename, version, commonPathFromData) { function getReferences (currentNode, isOutOfRoot, pathSolver, parentFilename, version, rootMainKeys,
commonPathFromData) {
let referencesInNode = [], let referencesInNode = [],
nodeReferenceDirectory = {}; nodeReferenceDirectory = {},
mainKeys = {};
traverseUtility(currentNode).forEach(function (property) { traverseUtility(currentNode).forEach(function (property) {
if (property) { if (property) {
let hasReferenceTypeKey; let hasReferenceTypeKey;
@@ -236,7 +291,12 @@ function getReferences (currentNode, isOutOfRoot, pathSolver, parentFilename, ve
); );
if (hasReferenceTypeKey) { if (hasReferenceTypeKey) {
const tempRef = calculatePath(parentFilename, property.$ref), const tempRef = calculatePath(parentFilename, property.$ref),
nodeTrace = getTraceFromParentKeyInComponents(this, tempRef, version, commonPathFromData), nodeTrace = handleLocalCollisions(
getTraceFromParentKeyInComponents(this, tempRef, mainKeys, version),
rootMainKeys,
commonPathFromData
),
componentKey = nodeTrace[nodeTrace.length - 1],
referenceInDocument = getJsonPointerRelationToRoot( referenceInDocument = getJsonPointerRelationToRoot(
tempRef, tempRef,
nodeTrace, nodeTrace,
@@ -261,9 +321,12 @@ function getReferences (currentNode, isOutOfRoot, pathSolver, parentFilename, ve
node: newValue, node: newValue,
reference: referenceInDocument, reference: referenceInDocument,
traceToParent, traceToParent,
parentNodeKey: parentFilename parentNodeKey: parentFilename,
mainKeyInTrace: nodeTrace[nodeTrace.length - 1]
}; };
mainKeys[componentKey] = tempRef;
if (!added(property.$ref, referencesInNode)) { if (!added(property.$ref, referencesInNode)) {
referencesInNode.push({ path: pathSolver(property), keyInComponents: nodeTrace, newValue: this.node }); referencesInNode.push({ path: pathSolver(property), keyInComponents: nodeTrace, newValue: this.node });
} }
@@ -280,10 +343,11 @@ function getReferences (currentNode, isOutOfRoot, pathSolver, parentFilename, ve
* @param {Array} allData - array of { path, content} objects * @param {Array} allData - array of { path, content} objects
* @param {object} specRoot - root file information * @param {object} specRoot - root file information
* @param {string} version - The current version * @param {string} version - The current version
* @param {object} rootMainKeys - A dictionary with the component keys in local components object and its mainKeys
* @param {string} commonPathFromData - The common path in the file's paths * @param {string} commonPathFromData - The common path in the file's paths
* @returns {object} - Detect root files result object * @returns {object} - Detect root files result object
*/ */
function getNodeContentAndReferences (currentNode, allData, specRoot, version, commonPathFromData) { function getNodeContentAndReferences (currentNode, allData, specRoot, version, rootMainKeys, commonPathFromData) {
let graphAdj = [], let graphAdj = [],
missingNodes = [], missingNodes = [],
nodeContent; nodeContent;
@@ -301,6 +365,7 @@ function getNodeContentAndReferences (currentNode, allData, specRoot, version, c
removeLocalReferenceFromPath, removeLocalReferenceFromPath,
currentNode.fileName, currentNode.fileName,
version, version,
rootMainKeys,
commonPathFromData commonPathFromData
); );
@@ -418,6 +483,25 @@ function generateComponentsWrapper(parsedOasObject) {
return components; return components;
} }
/**
* Returns a dictionary with the resusable component keys and their mainKeys in document before the bundle
* @param {object} components - The wrapper with the root reusable components before the bundle
* @param {string} version - The spec version
* @returns {object} - A directory with the local components keys related with their mainKeys
*/
function getMainKeysFromComponents(components, version) {
const {
COMPONENTS_KEYS
} = getBundleRulesDataByVersion(version);
let componentsDictionary = {};
COMPONENTS_KEYS.forEach((key) => {
if (components[key]) {
componentsDictionary[key] = Object.keys(components[key]);
}
});
return componentsDictionary;
}
module.exports = { module.exports = {
/** /**
* Takes in an spec root file and an array of data files * Takes in an spec root file and an array of data files
@@ -433,6 +517,8 @@ module.exports = {
if (origin === BROWSER) { if (origin === BROWSER) {
path = pathBrowserify; path = pathBrowserify;
} }
const initialComponents = generateComponentsWrapper(specRoot.parsed.oasObject, version),
initialMainKeys = getMainKeysFromComponents(initialComponents, version);
let algorithm = new DFS(), let algorithm = new DFS(),
components = {}, components = {},
commonPathFromData = '', commonPathFromData = '',
@@ -441,7 +527,7 @@ module.exports = {
return fileData.fileName; return fileData.fileName;
})); }));
rootContextData = algorithm.traverseAndBundle(specRoot, (currentNode) => { rootContextData = algorithm.traverseAndBundle(specRoot, (currentNode) => {
return getNodeContentAndReferences(currentNode, allData, specRoot, version, commonPathFromData); return getNodeContentAndReferences(currentNode, allData, specRoot, version, initialMainKeys, commonPathFromData);
}); });
components = generateComponentsWrapper(specRoot.parsed.oasObject, version); components = generateComponentsWrapper(specRoot.parsed.oasObject, version);
generateComponentsObject( generateComponentsObject(

View File

@@ -22,17 +22,6 @@ function jsonPointerEncodeAndReplace(filePathName) {
return encodeURIComponent(filePathName.replace(tildes, escapedTildeString).replace(slashes, escapedSlashString)); return encodeURIComponent(filePathName.replace(tildes, escapedTildeString).replace(slashes, escapedSlashString));
} }
/**
* Get a path and return a valid key name in openapi spec
* @param {string} filePathName - The filePath from the ref called
* @returns {string} A valid in openapi object name
*/
function generateObjectName(filePathName) {
let validName = filePathName.replace(/\//g, '_').replace(/#/g, '-');
validName = validName.replace(/[^a-zA-Z0-9\.\-_]/g, '');
return validName;
}
/** /**
* Decodes a json pointer * Decodes a json pointer
* replaces ~0 and ~1 for tildes and slashes * replaces ~0 and ~1 for tildes and slashes
@@ -43,29 +32,41 @@ function jsonPointerDecodeAndReplace(filePathName) {
return decodeURIComponent(filePathName.replace(escapedSlash, jsonPointerLevelSeparator).replace(escapedTilde, '~')); return decodeURIComponent(filePathName.replace(escapedSlash, jsonPointerLevelSeparator).replace(escapedTilde, '~'));
} }
/**
* Get a path and return a valid key name in openapi spec
* @param {string} filePathName - The filePath from the ref called
* @param {string} hash - A calculated hash to join with the resultant generatedName
* @returns {string} A valid in openapi object name
*/
function generateObjectName(filePathName, hash = '') {
let decodedRef = jsonPointerDecodeAndReplace(filePathName),
validName = decodedRef.replace(/\//g, '_').replace(/#/g, '-'),
hashPart = hash ? `_${hash}` : '';
validName = `${validName.replace(/[^a-zA-Z0-9\.\-_]/g, '')}${hashPart}`;
return validName;
}
/** /**
* returns the key that the object in components will have could be nested * returns the key that the object in components will have could be nested
* @param {string} traceFromParent the node trace from root. * @param {string} traceFromParent the node trace from root.
* @param {string} filePathName the filePathName of the file * @param {string} mainKey - The generated mainKey for the components
* @param {string} localPath the local path that the pointer will reach
* @param {string} version - The current spec version * @param {string} version - The current spec version
* @param {string} commonPathFromData - The common path in the file's paths * @param {string} commonPathFromData - The common path in the file's paths
* @returns {Array} - the calculated keys in an array representing each nesting property name * @returns {Array} - the calculated keys in an array representing each nesting property name
*/ */
function getKeyInComponents(traceFromParent, filePathName, localPath, version, commonPathFromData) { function getKeyInComponents(traceFromParent, mainKey, version, commonPathFromData) {
const localPart = localPath ? `${localPointer}${localPath}` : '', const {
{ CONTAINERS,
CONTAINERS, DEFINITIONS,
DEFINITIONS, COMPONENTS_KEYS,
COMPONENTS_KEYS, INLINE,
INLINE, ROOT_CONTAINERS_KEYS
ROOT_CONTAINERS_KEYS } = getBundleRulesDataByVersion(version);
} = getBundleRulesDataByVersion(version);
let result, let result,
newFPN = filePathName.replace(commonPathFromData, ''), newFPN = mainKey.replace(generateObjectName(commonPathFromData), ''),
trace = [ trace = [
...traceFromParent, ...traceFromParent,
jsonPointerDecodeAndReplace(`${newFPN}${localPart}`) jsonPointerDecodeAndReplace(newFPN)
].reverse(), ].reverse(),
traceToKey = [], traceToKey = [],
matchFound = false, matchFound = false,
@@ -93,7 +94,7 @@ function getKeyInComponents(traceFromParent, filePathName, localPath, version, c
result = matchFound ? result = matchFound ?
traceToKey.reverse() : traceToKey.reverse() :
[]; [];
return result.map(generateObjectName); return result;
} }
/** /**

View File

@@ -0,0 +1,111 @@
{
"openapi": "3.0.0",
"info": {
"title": "Sample API",
"description": "Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/) or HTML.",
"version": "0.1.9"
},
"servers": [
{
"url": "http://api.example.com/v1",
"description": "Optional server description, e.g. Main (production) server"
},
{
"url": "http://staging-api.example.com",
"description": "Optional server description, e.g. Internal staging server for testing"
}
],
"paths": {
"/users/{userId}": {
"get": {
"summary": "Get a user by ID",
"responses": {
"200": {
"description": "A single user.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/_schemas___user.yaml"
}
}
}
}
}
}
},
"/users/weird": {
"get": {
"summary": "Get a user by ID",
"responses": {
"200": {
"description": "A single user.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/_schemas___user.yaml_RQm8"
}
}
}
}
}
}
},
"/users/other": {
"get": {
"summary": "Get a user by ID",
"responses": {
"200": {
"description": "A single user.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/_schemas___user.yaml_mvS0"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"_schemas___user.yaml": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"userName": {
"type": "string"
}
}
},
"_schemas___user.yaml_RQm8": {
"type": "object",
"properties": {
"otherCollisionedId": {
"type": "integer"
},
"someData": {
"type": "string"
}
}
},
"_schemas___user.yaml_mvS0": {
"type": "object",
"properties": {
"aCollisionedItem": {
"type": "integer"
},
"userName": {
"type": "string"
},
"randomString": {
"type": "string"
}
}
}
}
}
}

View File

@@ -0,0 +1,43 @@
openapi: 3.0.0
info:
title: Sample API
description: Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/) or HTML.
version: 0.1.9
servers:
- url: http://api.example.com/v1
description: Optional server description, e.g. Main (production) server
- url: http://staging-api.example.com
description: Optional server description, e.g. Internal staging server for testing
paths:
/users/{userId}:
get:
summary: Get a user by ID
responses:
200:
description: A single user.
content:
application/json:
schema:
$ref: "./schemas__/user.yaml"
/users/weird:
get:
summary: Get a user by ID
responses:
200:
description: A single user.
content:
application/json:
schema:
$ref: "./schemas_/_user.yaml"
/users/other:
get:
summary: Get a user by ID
responses:
200:
description: A single user.
content:
application/json:
schema:
$ref: "./schemas/__user.yaml"

View File

@@ -0,0 +1,8 @@
type: object
properties:
aCollisionedItem:
type: integer
userName:
type: string
randomString:
type: string

View File

@@ -0,0 +1,6 @@
type: object
properties:
otherCollisionedId:
type: integer
someData:
type: string

View File

@@ -0,0 +1,6 @@
type: object
properties:
id:
type: integer
userName:
type: string

View File

@@ -0,0 +1,80 @@
{
"openapi": "3.0.0",
"info": {
"title": "Sample API",
"description": "Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/) or HTML.",
"version": "0.1.9"
},
"servers": [
{
"url": "http://api.example.com/v1",
"description": "Optional server description, e.g. Main (production) server"
},
{
"url": "http://staging-api.example.com",
"description": "Optional server description, e.g. Internal staging server for testing"
}
],
"paths": {
"/users/{userId}": {
"get": {
"summary": "Get a user by ID",
"responses": {
"200": {
"description": "A single user.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/_schemas_user.yaml_zfNS"
}
}
}
}
}
}
},
"/users/other": {
"get": {
"summary": "Get a user by ID",
"responses": {
"200": {
"description": "A single user.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/_schemas_user.yaml"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"_schemas_user.yaml": {
"type": "object",
"properties": {
"componentInRootId": {
"type": "string"
}
}
},
"_schemas_user.yaml_zfNS": {
"type": "object",
"properties": {
"aCollisionedItem": {
"type": "integer"
},
"userName": {
"type": "string"
},
"randomString": {
"type": "string"
}
}
}
}
}
}

View File

@@ -0,0 +1,40 @@
openapi: 3.0.0
info:
title: Sample API
description: Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/) or HTML.
version: 0.1.9
servers:
- url: http://api.example.com/v1
description: Optional server description, e.g. Main (production) server
- url: http://staging-api.example.com
description: Optional server description, e.g. Internal staging server for testing
paths:
/users/{userId}:
get:
summary: Get a user by ID
responses:
200:
description: A single user.
content:
application/json:
schema:
$ref: "./schemas/user.yaml"
/users/other:
get:
summary: Get a user by ID
responses:
200:
description: A single user.
content:
application/json:
schema:
$ref: "#/components/schemas/_schemas_user.yaml"
components:
schemas:
"_schemas_user.yaml":
type: object
properties:
componentInRootId:
type: string

View File

@@ -0,0 +1,8 @@
type: object
properties:
aCollisionedItem:
type: integer
userName:
type: string
randomString:
type: string

View File

@@ -38,7 +38,9 @@ let expect = require('chai').expect,
compositeOneOf = path.join(__dirname, BUNDLES_FOLDER + '/composite_oneOf'), compositeOneOf = path.join(__dirname, BUNDLES_FOLDER + '/composite_oneOf'),
compositeNot = path.join(__dirname, BUNDLES_FOLDER + '/composite_not'), compositeNot = path.join(__dirname, BUNDLES_FOLDER + '/composite_not'),
compositeAnyOf = path.join(__dirname, BUNDLES_FOLDER + '/composite_anyOf'), compositeAnyOf = path.join(__dirname, BUNDLES_FOLDER + '/composite_anyOf'),
longPath = path.join(__dirname, BUNDLES_FOLDER + '/longPath'); longPath = path.join(__dirname, BUNDLES_FOLDER + '/longPath'),
schemaCollision = path.join(__dirname, BUNDLES_FOLDER + '/schema_collision_from_responses'),
schemaCollisionWRootComponent = path.join(__dirname, BUNDLES_FOLDER + '/schema_collision_w_root_components');
describe('bundle files method - 3.0', function () { describe('bundle files method - 3.0', function () {
@@ -1935,6 +1937,82 @@ describe('bundle files method - 3.0', function () {
} }
}); });
it('Should return bundled file as json - schema_collision_from_responses', async function () {
let contentRootFile = fs.readFileSync(schemaCollision + '/root.yaml', 'utf8'),
user = fs.readFileSync(schemaCollision + '/schemas_/_user.yaml', 'utf8'),
user1 = fs.readFileSync(schemaCollision + '/schemas/__user.yaml', 'utf8'),
user2 = fs.readFileSync(schemaCollision + '/schemas__/user.yaml', 'utf8'),
expected = fs.readFileSync(schemaCollision + '/expected.json', 'utf8'),
input = {
type: 'multiFile',
specificationVersion: '3.0',
rootFiles: [
{
path: '/root.yaml'
}
],
data: [
{
path: '/root.yaml',
content: contentRootFile
},
{
path: '/schemas__/user.yaml',
content: user2
},
{
path: '/schemas_/_user.yaml',
content: user
},
{
path: '/schemas/__user.yaml',
content: user1
}
],
options: {},
bundleFormat: 'JSON'
};
const res = await Converter.bundle(input);
expect(res).to.not.be.empty;
expect(res.result).to.be.true;
expect(res.output.specification.version).to.equal('3.0');
expect(JSON.stringify(JSON.parse(res.output.data[0].bundledContent), null, 2)).to.be.equal(expected);
});
it('Should return bundled file as json - schema_collision_w_root_components', async function () {
let contentRootFile = fs.readFileSync(schemaCollisionWRootComponent + '/root.yaml', 'utf8'),
user = fs.readFileSync(schemaCollisionWRootComponent + '/schemas/user.yaml', 'utf8'),
expected = fs.readFileSync(schemaCollisionWRootComponent + '/expected.json', 'utf8'),
input = {
type: 'multiFile',
specificationVersion: '3.0',
rootFiles: [
{
path: '/root.yaml'
}
],
data: [
{
path: '/root.yaml',
content: contentRootFile
},
{
path: '/schemas/user.yaml',
content: user
}
],
options: {},
bundleFormat: 'JSON'
};
const res = await Converter.bundle(input);
expect(res).to.not.be.empty;
expect(res.result).to.be.true;
expect(res.output.specification.version).to.equal('3.0');
expect(JSON.stringify(JSON.parse(res.output.data[0].bundledContent), null, 2)).to.be.equal(expected);
});
it('Should bundle long paths into shorter ones', async function () { it('Should bundle long paths into shorter ones', async function () {
let contentRootFile = fs.readFileSync(longPath + '/root.yaml', 'utf8'), let contentRootFile = fs.readFileSync(longPath + '/root.yaml', 'utf8'),
client = fs.readFileSync(longPath + '/client.json', 'utf8'), client = fs.readFileSync(longPath + '/client.json', 'utf8'),
@@ -2009,7 +2087,10 @@ describe('getReferences method when node does not have any reference', function(
userNode.oasObject, userNode.oasObject,
nodeIsRoot, nodeIsRoot,
removeLocalReferenceFromPath, removeLocalReferenceFromPath,
'the/parent/filename' 'the/parent/filename',
'3.0',
{},
''
); );
expect(result.referencesInNode).to.be.an('array').with.length(0); expect(result.referencesInNode).to.be.an('array').with.length(0);
@@ -2041,7 +2122,8 @@ describe('getReferences method when node does not have any reference', function(
userNode.oasObject, userNode.oasObject,
nodeIsRoot, nodeIsRoot,
removeLocalReferenceFromPath, removeLocalReferenceFromPath,
'the/parent/filename' 'the/parent/filename',
{}
); );
expect(result.nodeReferenceDirectory).to.be.an('object'); expect(result.nodeReferenceDirectory).to.be.an('object');
expect(Object.keys(result.nodeReferenceDirectory).length).to.equal(1); expect(Object.keys(result.nodeReferenceDirectory).length).to.equal(1);

View File

@@ -18,43 +18,12 @@ describe('getKeyInComponents function', function () {
expect(result).to.be.an('array').with.length(0); expect(result).to.be.an('array').with.length(0);
}); });
it('should return ["schemas", "_folder_pet.yaml"] when the filename scaped slash', function () { it('should return ["schemas", "_folder_pet.yaml"] when the filename is _folder_pet.yaml', function () {
const result = getKeyInComponents(['path', 'schemas'], '~1folder~1pet.yaml'); const result = getKeyInComponents(['path', 'schemas'], '_folder_pet.yaml', '3.0', '');
expect(result).to.be.an('array').with.length(2); expect(result).to.be.an('array').with.length(2);
expect(result[0]).to.equal('schemas'); expect(result[0]).to.equal('schemas');
expect(result[1]).to.equal('_folder_pet.yaml'); expect(result[1]).to.equal('_folder_pet.yaml');
}); });
it('should return ["schemas", "_folder_pet.yaml"] when the filename contains any slash', function () {
const result = getKeyInComponents(['path', 'schemas'], '/folder/pet.yaml');
expect(result).to.be.an('array').with.length(2);
expect(result[0]).to.equal('schemas');
expect(result[1]).to.equal('_folder_pet.yaml');
});
it('should return ["schemas", "_folder_pet.yaml-_Name"] when the filename contains any sacped slash' +
'and a local part using a scaped sharp', function () {
const result = getKeyInComponents(['path', 'schemas'], '~1folder~1pet.yaml%23~1Name');
expect(result).to.be.an('array').with.length(2);
expect(result[0]).to.equal('schemas');
expect(result[1]).to.equal('_folder_pet.yaml-_Name');
});
it('should return ["schemas", "_folder_pet.yaml-_Name"] when the filename contains any slash' +
'and a local part using a sharp', function () {
const result = getKeyInComponents(['path', 'schemas'], '/folder/pet.yaml#/Name');
expect(result).to.be.an('array').with.length(2);
expect(result[0]).to.equal('schemas');
expect(result[1]).to.equal('_folder_pet.yaml-_Name');
});
it('should return ["schemas", "_foldertest_pet.yaml-_Name"] when the filename contains any slash' +
'and a local part using a sharp and another not valid character', function () {
const result = getKeyInComponents(['path', 'schemas'], '/folder@test/pet@.yaml#/Name');
expect(result).to.be.an('array').with.length(2);
expect(result[0]).to.equal('schemas');
expect(result[1]).to.equal('_foldertest_pet.yaml-_Name');
});
}); });