Skip to content

Commit

Permalink
feat: add custom field for class name @W-13013140@ (#221)
Browse files Browse the repository at this point in the history
* add custom field for class name

* fix linting

* add unit tests

* update custom field name for clarity

* update comment with new custom field name

* update additional comments

* use annotation and create class name helper method
  • Loading branch information
joeluong-sfcc authored May 5, 2023
1 parent 4bd96d7 commit 51f2622
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 5 deletions.
51 changes: 50 additions & 1 deletion src/generate/apiModel.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import chaiFs from "chai-fs";

import fs from "fs-extra";

import { ApiModel } from "./";
import { ApiModel, SDK_ANNOTATION } from "./";
import { Name } from "../common/structures/name";
import tmp from "tmp";
import sinon from "sinon";
Expand All @@ -29,6 +29,16 @@ const invalidRamlFile = path.join(
"../../testResources/raml/invalid/search-invalid.raml"
);

const customFieldRamlFile = path.join(
__dirname,
"../../testResources/raml/custom-field/custom-field.raml"
);

const customFieldInvalidRamlFile = path.join(
__dirname,
"../../testResources/raml/custom-field-invalid/custom-field-invalid.raml"
);

const handlebarTemplate = path.join(
__dirname,
"../../testResources/handlebarTemplates/test.hbs"
Expand Down Expand Up @@ -102,6 +112,45 @@ describe("ApiModel tests", () => {
"Cannot update the name before the model is loaded"
);
});

it("uses title for class name if custom field is not set", async () => {
const api = new ApiModel("VALID", path.dirname(validRamlFile));
await api.init();
expect(api.name).to.deep.equal(new Name("Shop API"));
});

it("uses custom field for class name if set", async () => {
const api = new ApiModel("CUSTOM", path.dirname(customFieldRamlFile));
await api.init();
expect(api.name).to.deep.equal(new Name("Custom Shop API Name"));
});

it("uses first instance of custom field for class name if multiple are set", async () => {
const api = new ApiModel("CUSTOM", path.dirname(customFieldRamlFile));
await api.init();
expect(api.model.encodes.customDomainProperties.length).to.be.equal(2);
// class-name: Custom Shop API Name
expect(
api.model.encodes.customDomainProperties[0].name.toString()
).to.be.equal(SDK_ANNOTATION);
// class-name: Custom Shop API Name 2 (not used)
expect(
api.model.encodes.customDomainProperties[1].name.toString()
).to.be.equal(SDK_ANNOTATION);
expect(api.name).to.deep.equal(new Name("Custom Shop API Name"));
});

it("uses title if custom field is incorrectly set", async () => {
const api = new ApiModel(
"CUSTOM_INVALID",
path.dirname(customFieldInvalidRamlFile)
);
await api.init();
expect(
api.model.encodes.customDomainProperties[0].name.toString()
).to.be.equal(SDK_ANNOTATION); // custom field exists but not used
expect(api.name).to.deep.equal(new Name("Shop API from title"));
});
});

describe("ApiModel render tests", () => {
Expand Down
37 changes: 34 additions & 3 deletions src/generate/apiModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ import { ramlToolLogger } from "../common/logger";
import _ from "lodash";
import { ApiMetadata } from "./";

// export for testing
export const SDK_ANNOTATION = "commerce-sdk";
export const CUSTOM_CLASS_NAME_PROPERTY = "class-name";

/**
* An API represented as an AMF model. Includes the extracted data types
* defined in the spec. Common transformations of the name are cached for
Expand Down Expand Up @@ -64,6 +68,30 @@ export class ApiModel extends ApiMetadata {
);
}
}

/**
* @description - Retrieves custom class name if defined in RAML
* @returns {string | undefined} - returns string if custom class name is defined in RAML, undefined otherwise
* @memberof ApiModel
*/
private getCustomClassName(): string | undefined {
let customClassName: string | undefined;

const customSdkProperties =
this.model.encodes.customDomainProperties.filter(
(customProperty) => customProperty.name.toString() === SDK_ANNOTATION
);

if (customSdkProperties.length > 0) {
// NOTE: there can be multiple instances of `(commerce-sdk)` defined in RAML, we take the first one
customClassName =
customSdkProperties[0].extension["properties"]?.[
CUSTOM_CLASS_NAME_PROPERTY
]?.value.toString(); // If class-name cannot be found, expression will result in undefined
}
return customClassName;
}

/**
* @description - Updates the name identifier of the class if it differs from the one initially provided
* @memberof ApiModel
Expand All @@ -72,9 +100,12 @@ export class ApiModel extends ApiMetadata {
if (!this.model) {
throw new Error("Cannot update the name before the model is loaded");
}
this.name = new Name(
(this.model.encodes as model.domain.WebApi)?.name.value()
);

// class name is defaulted to title
let className = (this.model.encodes as model.domain.WebApi)?.name.value();
const customClassName = this.getCustomClassName();
if (customClassName) className = customClassName;
this.name = new Name(className);
}

/**
Expand Down
6 changes: 5 additions & 1 deletion src/generate/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,9 @@ export * as handlebarsAmfHelpers from "./handlebarsAmfHelpers";
export { HandlebarsWithAmfHelpers, registerPartial } from "./handlebarsConfig";

export { ApiMetadata } from "./apiMetadata";
export { ApiModel } from "./apiModel";
export {
ApiModel,
SDK_ANNOTATION,
CUSTOM_CLASS_NAME_PROPERTY,
} from "./apiModel";
export { loadApiDirectory } from "./loadApiDirectory";
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#%RAML 1.0

title: Shop API from title
(commerce-sdk): Custom Shop API Name (class name not set correctly)
baseUri: https://anypoint.mulesoft.com/mocking/api/v1/links/27d5ffea-96a7-447b-b595-2b0e837a20c6/s/-/dw/shop/v19_5
version: v1
description: This is a base shop api for testing purposes
protocols: https
mediaType: application/json
12 changes: 12 additions & 0 deletions testResources/raml/custom-field-invalid/exchange.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"main": "custom-field-invalid.raml",
"name": "Custom Field Invalid",
"classifier": "raml",
"tags": [],
"groupId": "893f605e-10e2-423a-bdb4-f952f56eb6d8",
"backwardsCompatible": false,
"assetId": "custom-field-invalid",
"version": "0.1.2",
"apiVersion": "v1",
"originalFormatVersion": "1.0"
}
12 changes: 12 additions & 0 deletions testResources/raml/custom-field/custom-field.raml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#%RAML 1.0

title: Shop API
(commerce-sdk):
class-name: Custom Shop API Name
(commerce-sdk):
class-name: Custom Shop API Name 2 (not used)
baseUri: https://anypoint.mulesoft.com/mocking/api/v1/links/27d5ffea-96a7-447b-b595-2b0e837a20c6/s/-/dw/shop/v19_5
version: v1
description: This is a base shop api for testing purposes
protocols: https
mediaType: application/json
12 changes: 12 additions & 0 deletions testResources/raml/custom-field/exchange.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"main": "custom-field.raml",
"name": "Custom Field",
"classifier": "raml",
"tags": [],
"groupId": "893f605e-10e2-423a-bdb4-f952f56eb6d8",
"backwardsCompatible": false,
"assetId": "custom-field",
"version": "0.1.2",
"apiVersion": "v1",
"originalFormatVersion": "1.0"
}

0 comments on commit 51f2622

Please sign in to comment.