@apistudio/apim-cli
Version:
CLI for API Management Products
432 lines (400 loc) • 15.9 kB
text/typescript
import { BaseTransformer } from '../core/impl/base-transformer.impl';
import { TransformConfig } from '../core/models/model';
import { WrappedAsset } from '../core/models/zip-processor.interface';
describe('Template Processing', () => {
let transformer: BaseTransformer;
beforeEach(() => {
transformer = new BaseTransformer();
});
describe('processTemplate method', () => {
it('should handle undefined values in templates', async () => {
// Arrange
const wrappedAsset: WrappedAsset = {
inputSchema: {
kind: 'Test',
apiVersion: 'v1',
metadata: {
name: 'test',
version: '1.0.0'
},
spec: {
existingField: 'exists'
}
},
metadata: {
name: 'test',
version: '1.0.0'
}
};
const config: TransformConfig = {
transformations: {
replacements: [
{
target: '$.Test.value',
value: 'Prefix {{$.spec.nonExistentField}} Suffix',
precedence: 10,
operation: 'replace'
}
]
}
};
// Act
const result = await transformer.transform(wrappedAsset, config);
// Assert
expect(result.outputAsset).toEqual({
Test: {
value: 'Prefix Suffix'
}
});
});
it('should skip replacements when all template values are undefined', async () => {
// Arrange
const wrappedAsset: WrappedAsset = {
inputSchema: {
kind: 'Test',
apiVersion: 'v1',
metadata: {
name: 'test',
version: '1.0.0'
},
spec: {}
},
metadata: {
name: 'test',
version: '1.0.0'
}
};
const config: TransformConfig = {
transformations: {
replacements: [
{
target: '$.Test.value',
value: '{{$.spec.nonExistentField}}',
precedence: 10,
operation: 'replace'
}
]
}
};
// Act
const result = await transformer.transform(wrappedAsset, config);
// Assert
expect(result.outputAsset).toEqual({});
});
it('should handle undefined values in object templates', async () => {
// Arrange
const wrappedAsset: WrappedAsset = {
inputSchema: {
kind: 'Test',
apiVersion: 'v1',
metadata: {
name: 'test',
version: '1.0.0'
},
spec: {
existingField: 'exists'
}
},
metadata: {
name: 'test',
version: '1.0.0'
}
};
const config: TransformConfig = {
transformations: {
replacements: [
{
target: '$.Test.object',
value: {
valid: '{{$.spec.existingField}}',
invalid: '{{$.spec.nonExistentField}}'
},
precedence: 10,
operation: 'replace'
}
]
}
};
// Act
const result = await transformer.transform(wrappedAsset, config);
// Assert
expect(result.outputAsset).toEqual({
Test: {
object: {
valid: 'exists'
// invalid field should be omitted
}
}
});
});
it('should handle undefined values in array templates', async () => {
// Arrange
const wrappedAsset: WrappedAsset = {
inputSchema: {
kind: 'Test',
apiVersion: 'v1',
metadata: {
name: 'test',
version: '1.0.0'
},
spec: {
field1: 'value1',
field3: 'value3'
}
},
metadata: {
name: 'test',
version: '1.0.0'
}
};
const config: TransformConfig = {
transformations: {
replacements: [
{
target: '$.Test.array',
value: [
'{{$.spec.field1}}',
'{{$.spec.field2}}', // Doesn't exist
'{{$.spec.field3}}'
],
precedence: 10,
operation: 'replace'
}
]
}
};
// Act
const result = await transformer.transform(wrappedAsset, config);
// Assert
expect(result.outputAsset).toEqual({
Test: {
array: [
'value1',
// field2 should be filtered out
'value3'
]
}
});
});
});
describe('Multiple asset generation', () => {
it('should support generating multiple assets from one input', async () => {
// Arrange
const wrappedAsset: WrappedAsset = {
inputSchema: {
kind: 'Redact',
apiVersion: 'api.ibm.com/v1',
metadata: {
name: 'redact-request',
version: '1.0.0',
namespace: 'sample'
},
spec: {
message: {
messageName: 'request',
queryParameters: ['token', 'trace'],
headers: ['X-API-Key', 'X-Auth-Token'],
body: {
captures: {
jsonata: ['doc.key.password', 'doc.key.user']
}
}
}
}
},
metadata: {
name: 'redact-request',
version: '1.0.0',
namespace: 'sample'
}
};
const config: TransformConfig = {
transformations: {
replacements: [
{
target: '$',
value: [],
precedence: 1,
condition: '$.kind === "Redact"'
},
{
target: '$',
value: {
redact: {
messageQueryParam: {
message: '{{$.spec.message.messageName}}',
paramNames: '{{$.spec.message.queryParameters}}'
}
}
},
operation: 'push',
precedence: 2,
condition: '$.spec.message && $.spec.message.queryParameters && $.spec.message.queryParameters.length > 0'
},
{
target: '$',
value: {
redact: {
messageHeader: {
message: '{{$.spec.message.messageName}}',
headerNames: '{{$.spec.message.headers}}'
}
}
},
operation: 'push',
precedence: 3,
condition: '$.spec.message && $.spec.message.headers && $.spec.message.headers.length > 0'
},
{
target: '$',
value: {
redact: {
messageBody: {
message: '{{$.spec.message.messageName}}',
captures: {
jsonata: '{{$.spec.message.body.captures.jsonata}}'
}
}
}
},
operation: 'push',
precedence: 4,
condition: '$.spec.message && $.spec.message.body && $.spec.message.body.captures && $.spec.message.body.captures.jsonata && $.spec.message.body.captures.jsonata.length > 0'
}
]
}
};
// Act
const result = await transformer.transform(wrappedAsset, config);
// Assert
expect(Array.isArray(result.outputAsset)).toBe(true);
expect(result.outputAsset.length).toBe(3);
// Check that all three expected assets are present
expect(result.outputAsset).toContainEqual({
redact: {
messageQueryParam: {
message: 'request',
paramNames: ['token', 'trace']
}
}
});
expect(result.outputAsset).toContainEqual({
redact: {
messageHeader: {
message: 'request',
headerNames: ['X-API-Key', 'X-Auth-Token']
}
}
});
expect(result.outputAsset).toContainEqual({
redact: {
messageBody: {
message: 'request',
captures: {
jsonata: ['doc.key.password', 'doc.key.user']
}
}
}
});
});
it('should handle non-existent fields in multiple asset generation', async () => {
// Arrange
const wrappedAsset: WrappedAsset = {
inputSchema: {
kind: 'Redact',
apiVersion: 'api.ibm.com/v1',
metadata: {
name: 'redact-request',
version: '1.0.0',
namespace: 'sample'
},
spec: {
message: {
messageName: 'request',
queryParameters: ['token', 'trace']
// No headers or body
}
}
},
metadata: {
name: 'redact-request',
version: '1.0.0',
namespace: 'sample'
}
};
const config: TransformConfig = {
transformations: {
replacements: [
{
target: '$',
value: [],
precedence: 1,
condition: '$.kind === "Redact"'
},
{
target: '$',
value: {
redact: {
messageQueryParam: {
message: '{{$.spec.message.messageName}}',
paramNames: '{{$.spec.message.queryParameters}}'
}
}
},
operation: 'push',
precedence: 2,
condition: '$.spec.message && $.spec.message.queryParameters && $.spec.message.queryParameters.length > 0'
},
{
target: '$',
value: {
redact: {
messageHeader: {
message: '{{$.spec.message.messageName}}',
headerNames: '{{$.spec.message.headers}}'
}
}
},
operation: 'push',
precedence: 3,
condition: '$.spec.message && $.spec.message.headers && $.spec.message.headers.length > 0'
},
{
target: '$',
value: {
redact: {
messageBody: {
message: '{{$.spec.message.messageName}}',
captures: {
jsonata: '{{$.spec.message.body.captures.jsonata}}'
}
}
}
},
operation: 'push',
precedence: 4,
condition: '$.spec.message && $.spec.message.body && $.spec.message.body.captures && $.spec.message.body.captures.jsonata && $.spec.message.body.captures.jsonata.length > 0'
}
]
}
};
// Act
const result = await transformer.transform(wrappedAsset, config);
// Assert
expect(Array.isArray(result.outputAsset)).toBe(true);
expect(result.outputAsset.length).toBe(1);
// Only the queryParameters asset should be present
expect(result.outputAsset).toEqual([
{
redact: {
messageQueryParam: {
message: 'request',
paramNames: ['token', 'trace']
}
}
}
]);
});
});
});
// Made with Bob