Preparing migration from v3 to v4
If you are already using Mocks Server v2.x you should migrate first from v2.x to v3.x, and then read this chapter to prepare migration to v4.x.
Preface
By the days of this doc was published, we were deprecating some things in v3 that were definitively removed in v4. Every change in v3.x was completely backward compatible, but users upgrading to v3 minor versions would probably receive alerts about usage of deprecated methods, etc.
So, every time you upgrade to a v3 minor version and receive a deprecation alert, you can come to this page and see how to adapt your code for the v4 version, so you'll be able to prepare to it progressively and finally update to v4 with very few breaking changes.
Note that this document is mainly written in future tense, because when it was written the version 4 was not released yet. Anyway, all changes and processes described here are still valid, and this doc can be used as a guide to update from v3.0 version to v3.12, and then modify your code progressively to be ready to update to v4.
Alerts are logged and displayed in the interactive CLI, apart from being available using any of the Mocks Server APIs.
If you are already using v3.x, then update to v3.12, which is compatible with v3.x and v4.x. You will receive alerts for each thing you have to change before updating to v4.x. So, you can modify your code progressively until there are no more alerts, and then you'll be able to update to v4 reading the migrating from v3 doc.
Changes summary
The main breaking changes in v4.x will be:
- Main concepts will be renamed. Read main concepts below for further info.
- Some JavaScript API methods will be removed. Read JavaScript API below for further info.
- Some options will be changed. Read options below for further info.
- The REST API will be server in a different port. Read REST API below for further info.
- Legacy alerts object will be removed. Read alerts for further info.
- Arguments received by the plugins. Read plugins below for further info.
- Remove support for defining plugins as objects or functions. Read plugins below for further info.
- Default route variants handler will be removed. Read route variants handlers below for further info.
- The JavaScript API for developing variants handlers will change. Read route variants handlers API below for further info.
Changes in other packages
- Cypress commands. The
@mocks-server/cypress-commandspackage release 5.0 and above can be used only with Mocks Server >=3.6. Command names have been renamed, so it is a breaking change. But any@mocks-server/cypress-commands@4.xversion will continue working with Mocks Server 3.x. So, you can continue using Cypress Commands 4.x and update Mocks Server to the latest 3.x version in order to migrate progressively. - Admin API Client. The
@mocks-server/admin-api-clientpackage release 6.0 and above can be used only with Mocks Server >=3.6. Methods have been renamed, so it is a breaking change. But any@mocks-server/admin-api-client@5.xversion will continue working with Mocks Server 3.x. So, you can continue usingadmin-api-client5.x and update Mocks Server to the latest 3.x version in order to migrate progressively.
Main concepts
mocks- The "mocks" concept has been renamed to "collections". All docs, API, logs and file names now make reference to "collections" instead of "mocks". The main change needed to be prepared for the v4 release is to rename themocks/mocks.[js|json]file intomocks/collections.[js|json].- The
routesVariantsorroutesVariantsproperty in mock definitions has been renamed intoroutes.
- The
JavaScript API
core.tracer: Thetracerobject will be completely removed and using it from v3.2 produces an alert. You must usecore.loggerinstead, which is already namespaced when passed to plugins and route middlewares. Read the logger API docs for further info.core.restartServer: TherestartServermethod will be removed and using it from v3.6 produces an alert. You must usecore.server.restartinstead. Read the server API docs for further info.core.addRouter: TheaddRoutermethod will be removed and using it from v3.6 produces an alert.core.server.addRoutermust be used instead. Read the server API docs for further info.core.removeRouter: TheremoveRoutermethod will be removed and using it from v3.6 produces an alert.core.server.removeRoutermust be used instead. Read the server API docs for further info.core.addRoutesHandler: TheaddRoutesHandlermethod will be removed and using it from v3.6 produces an alert.core.variantHandlers.registermust be used instead. Read the variantHandlers API docs for further info.core.onChangeMocks: TheonChangeMocksmethod will be removed and using it from v3.6 produces an alert.core.mock.onChangemust be used instead. Read the mock API docs for further info.core.loadMocks: TheloadMocksmethod will be removed and using it from v3.6 produces an alert.core.mock.createLoadersmust be used instead. Read the mock API docs for further info.core.loadRoutes: TheloadRoutesmethod will be removed and using it from v3.6 produces an alert.core.mock.createLoadersmust be used instead. Read the mock API docs for further info.core.mocks.restoreRoutesVariants: Themocks.restoreRoutesVariantsmethod will be removed and using it from v3.6 produces an alert.core.mock.restoreRouteVariantsmust be used instead. Read the mock API docs for further info.core.mocks.customRoutesVariants: Themocks.customRoutesVariantsgetter will be removed and using it from v3.6 produces an alert.core.mock.customRouteVariantsmust be used instead. Read the mock API docs for further info.core.mocks.plainRoutes: Themocks.plainRoutesgetter will be removed and using it from v3.6 produces an alert.core.mock.routes.plaingetter must be used instead. Read the mock API docs for further info.core.mocks.plainRoutesVariants: Themocks.plainRoutesVariantsgetter will be removed and using it from v3.6 produces an alert.core.mock.routes.plainVariantsgetter must be used instead, but take into account that the items properties have changed in the new getter. Read the mock API docs for further info.core.mocks.current: Themocks.currentgetter and setter will be removed and using it from v3.6 produces an alert.core.mock.collections.selectedgetter andcore.mocks.collections.selectmethod must be used instead. Read the mock API docs for further info.core.mocks.ids: Themocks.idsgetter will be removed and using them from v3.6 produces alerts.core.mock.collections.idsgetter must be used instead. Read the mock API docs for further info.core.mocks.plainMocks: Themocks.plainMocksgetter will be removed and using it from v3.6 produces an alert.core.mock.collections.plaingetter must be used instead, but take into account that the items properties have changed in the new getter. Read the mock API docs for further info.core.logs: Thecore.logsgetter will be removed and using them from v3.6 produces an alert.core.logger.globalStoregetter must be used instead. Read the logger API docs for further info.core.onChangeAlerts: Thecore.onChangeAlertsmethod will be removed and using them from v3.6 produces an alert.core.alerts.root.onChangemethod must be used instead. Read the alerts API docs for further info.core.onChangeLogs: Thecore.onChangeLogsmethod will be removed and using them from v3.6 produces an alert.core.logger.onChangeGlobalStoremethod must be used instead. Read the logger API docs for further info.
Options
mocks.selected: This option will be removed. Usemock.collections.selectedinstead.mocks.delay: This option will be removed. Usemock.routes.delayinstead.routesHandlers: This option will be removed. UsevariantHandlers.registerinstead.
REST API
From v3.6, a new REST API server is started in a different port of the API mock. URLs and models was changed too, and Swagger UI was added. Review the new REST API docs for further info. The legacy API in the /admin path will be still available in all v3.x versions, but using it will produce an alert.
Alerts
- The
core.alertsgetter in the core when created programmatically was different to thecore.alertsproperty received in the plugins from v3.2 due to backward compatibility reasons. In v4 it will return analertsinstance in the first case too. In the first case, it was returning a plain alerts collection. So, if you are using a programmatic root core, you should start usingcore.alertsApi.customFlatto get the same values, because that alias will be maintained in v4. Note that, when receiving the core as a parameter in plugins, you should continue using thealertsproperty, which will not change in v4. - The
addAlertandremoveAlertsmethods that were being passed to plugins were deprecated in v3.1, and they will be removed in v4. Plugins are receiving analertsproperty in the core to be used instead, which was also available in the root programmatic core usingcore.alertsApi. Read the alerts API docs for further info.
Plugins
Core property
In version v3.1 a core property was added to the argument passed to the plugins. From v3.2, the whole core API was passed as first argument, but with some methods specifically scoped for the plugin. The core property was also maintained for backward compatibility but using it produced an alert. So, in v4 the core property will be definitively removed.
V3 example:
class Plugin {
constructor({ logger, core, addAlert, removeAlerts }) {
// core property was almost an alias containing again all of the rest of properties received
}
}
V4 example:
class Plugin {
constructor({ logger }) {
// core property is no longer received
}
}
Formats
From version v3.4, loading any plugin created as a function or as a plain object will produce an alert. In v4.x, plugins will have to be defined only as classes. So, it is strongly recommended that any other format of plugin is converted into a class while using >=v3.4, so the code will be ready for migrating to v4.x.
Route variants handlers
From Mocks Server v3.5, new variants handlers were added: json and middleware. The plugin-proxy package was also updated, and it added a new proxy-v4 handler. In Mocks Server v4.0, these handlers will have to be used instead of the default one.
This was made because in v3.x, the properties of the route variants differed depending on the used handler, and this made difficult to validate them and could produce conflicts between variant properties and specific handler properties. In v4.x, all of the handlers properties must be defined in the options property of the variant, which will be mandatory. The variant handler will be to be defined in the mandatory type property.
The code can be migrated from v3.5, which will be compatible both with the new way and old way of defining variants in order to allow a progressive migration. The way of migrating the code depends of the format of the variant:
Migrating variants defined as plain response object
Variants using the default handler containing a plain object response and a status can be migrated simply adding a type: "json" property, and renaming the response property into options. So, a variant defined in version lower than 3.5 as:
module.exports = [
{
id: "get-users",
url: "/api/users",
method: "GET",
variants: [
{
id: "success",
response: {
status: 200,
body: USERS,
},
},
]
},
]
From v3.6 it has to be defined as:
module.exports = [
{
id: "get-users",
url: "/api/users",
method: "GET",
variants: [
{
id: "success",
type: "json", // Add variant type property with "json" value
options: {
status: 200,
body: USERS,
},
},
]
},
]
Migrating variants defined as plain text response
Variants using the default handler containing a plain text response and a status can be migrated simply adding a type: "text" property, and renaming the response property into options. So, a variant defined in version lower than 3.7 as:
module.exports = [
{
id: "get-users",
url: "/api/users",
method: "GET",
variants: [
{
id: "success",
response: {
status: 200,
body: "Foo text",
},
},
]
},
]
From v3.7 it has to be defined as:
module.exports = [
{
id: "get-users",
url: "/api/users",
method: "GET",
variants: [
{
id: "success",
type: "text", // Add variant type property with "text" value
options: {
status: 200,
body: "Foo text",
},
},
]
},
]
Migrating variants with empty body
Variants using the default handler without body and a status can be migrated simply adding a type: "status" property. So, a variant defined in version lower than 3.8 as:
module.exports = [
{
id: "get-users",
url: "/api/users",
method: "GET",
variants: [
{
id: "success",
response: {
status: 200,
},
},
]
},
]
From v3.8 it has to be defined as:
module.exports = [
{
id: "get-users",
url: "/api/users",
method: "GET",
variants: [
{
id: "success",
type: "status", // Add variant type property with "status" value
options: {
status: 200,
},
},
]
},
]
Migrating variants defined as middlewares
Variants defining the response property as a function (middlewares) in version lower than v3.5 must to be migrated adding a type: "middleware". The response property has to be converted into an options object containing a middleware property, which must contain the function. So, A variant defined in version lower than 3.5 as:
module.exports = [
{
id: "get-users",
url: "/api/users",
method: "GET",
variants: [
{
id: "real",
response: (req, res, next) => next(),
},
]
},
]
From v3.6 it has to be defined as:
module.exports = [
{
id: "get-users",
url: "/api/users",
method: "GET",
variants: [
{
id: "real",
type: "middleware", // Add the type property with "middleware" value
options: { // Move the function to a "middleware" property under "options"
middleware: (req, res, next) => next(),
},
},
]
},
]
Migrating proxy variants
In v3.5 a new handler was added: proxy-v4. This handler is compatible with the coming Mocks Server v4 version, while the proxy one can still be used. So, in order to adapt the code to the v4 version, it is recommended to migrate all of the variants using the proxy handler in order to use the new proxy-v4 one. In the proxy-v4 handler, all of the properties for the variant handler have to be defined under the options property of the variant, instead of defining them in the root level.
So, a proxy variant defined in version lower than 3.5 as:
module.exports = [
{
id: "get-user",
url: "/api/users/:id",
method: "GET"],
variants: [
{
id: "real-api",
handler: "proxy",
host: "http://127.0.0.1:8080",
options: {
userResDecorator: (function(proxyRes, proxyResData, userReq, userRes) {
data = JSON.parse(proxyResData.toString('utf8'));
data.name = `Modified ${data.name}`;
return JSON.stringify(data);
})
},
},
],
},
];
From v3.6 it has to be defined as:
module.exports = [
{
id: "get-user",
url: "/api/users/:id",
method: "GET"],
variants: [
{
id: "real-api",
type: "proxy-v4", // Change to "proxy-v4"
options: { // Move host and options properties under the variant options property
host: "http://127.0.0.1:8080",
options: {
userResDecorator: (function(proxyRes, proxyResData, userReq, userRes) {
data = JSON.parse(proxyResData.toString('utf8'));
data.name = `Modified ${data.name}`;
return JSON.stringify(data);
})
},
},
},
],
},
];
Route variants handlers API
In versions lower than v3.4, the properties of the route variants differed depending on the used handler, and this made difficult to validate them and could produce conflicts between variant properties and specific handler properties. From v3.5, a new way of defining variant handlers was introduced, and it will be the only way from v4.x. In the new format, the middleware method of the Handler classes will receive as first parameter only the properties defined in the options property of the route variant instead of all of the route variant properties. This ensures that the Handlers can only use the properties that they should use.
From v3.5, you can use the new API adding a static version property returning 4 to the class, so Mocks Server can know which parameters it should pass to the class. Note that doing this will imply next things:
- The
middlewaremethod will receive as first argument only the properties defined in theoptionsproperty of the variant instead of all the variant properties. - The
validationSchemaproperty will be scoped only to theoptionsproperties instead of all of the variant properties. - The
plainResponsePreviewproperty must be renamed intopreview.
So, a route handler defined in v3.4 as:
// ./CustomRoutesHandler.js
class CustomRoutesHandler {
static get id() {
return "error";
}
static get validationSchema() {
return {
type: "object",
properties: {
response: {
type: "object",
properties: {
code: {
type: "number",
},
message: {
type: "string",
},
},
required: ["code", "message"],
additionalProperties: false,
}
},
required: ["response"],
};
}
constructor(variant, core) {
this._code = variant.response.code;
this._message = variant.response.message;
this._core = core;
}
middleware(req, res, next) {
this._core.logger.info("Sending response");
res.status(this._code);
res.send({
message: this._message
});
}
get plainResponsePreview() {
return {
body: {
message: this._message
},
status: this._code,
};
}
}
module.exports = CustomRoutesHandler;
From v3.5 it should be changed into:
// ./CustomRoutesHandler.js
class CustomRoutesHandler {
static get id() {
return "error";
}
// Return 4 in version to use the new API
static get version() {
return "4";
}
// Validate only the content of the variant `options` property
static get validationSchema() {
return {
type: "object",
properties: {
code: {
type: "number",
},
message: {
type: "string",
},
},
required: ["code", "message"],
additionalProperties: false,
};
}
// Receives the options property in the constructor instead of the whole variant
constructor(options, core) {
this._code = options.code;
this._message = options.message;
this._core = core;
}
middleware(req, res, next) {
this._core.logger.info("Sending response");
res.status(this._code);
res.send({
message: this._message
});
}
// Rename plainResponsePreview into preview
get preview() {
return {
body: {
message: this._message
},
status: this._code,
};
}
}
module.exports = CustomRoutesHandler;