Suitecloud Unit Testing allows you to use unit testing with Jest for your SDF projects.
- Provides a default configuration to run unit tests with Jest in SDF projects.
- Supports unit testing for SuiteScript 2.X files.
- Provides SuiteScript 2.X stubs for the following SuiteScript modules:
- N/http
- N/https
- N/record
- N/search
- Allows you to create custom stubs for SuiteScript 2.X or custom modules.
- Supports code coverage capabilities through Jest.
- Node.js version 12.14.0 LTS or greater
- An SDF project
If you use SuiteCloud CLI for Node.js, you can install SuiteCloud Unit Testing when running the project:create
command by following the questions prompted. This way, your project is initialized with SuiteCloud Unit Testing, and all the dependencies are being taken care of.
⚠ SuiteCloud Unit Testing is installed as a
devDependency
.
However, if you want to configure SuiteCloud Unit Testing manually, do the following:
- Inside of your SDF project folder, create a
src
folder. - Move your project files inside of the
src
folder. - To initialize the NPM package, from the root of your SDF project folder, run
npm init
.
💡 A
package.json
file is created in your SDF project folder.
- In your
package.json
file, add the following code:
{
"scripts": {
"test": "jest"
}
}
- From the root of your SDF project folder, run the followig command:
npm install --save-dev @oracle/suitecloud-unit-testing jest
- Create a
__tests__
folder, inside of the root of your SDF project folder. - Create a
sample-test.js
file, inside of the__tests__
folder, with the following content:
describe('Basic jest test with simple assert', () => {
it('should assert stings are equal', () => {
const a = 'foobar';
const b = 'foobar';
expect(a).toMatch(b);
});
});
- From the root of your SDF project folder, run
npm test
to run your test. You should see an output similar to following:
PASS __tests__/sample-test.js
Basic jest test with simple assert
√ should assert stings are equal (2ms)
💡 If you want to run tests with coverage, from the root of your SDF project folder, run
npm test --coverage
.
You successfully ran your first test for an SDF project!
To properly run your tests against the SuiteScript 2.X files of your SDF project, create a jest.config.js
file inside of the root of your SDF project folder.
The jest.config.js
file must follow a specific structure. Depending on your SDF project type, check one of the following examples:
- For Account Customization Projects:
const SuiteCloudJestConfiguration = require("@oracle/suitecloud-unit-testing/jest-configuration/SuiteCloudJestConfiguration");
module.exports = SuiteCloudJestConfiguration.build({
projectFolder: 'src', //or your SDF project folder
projectType: SuiteCloudJestConfiguration.ProjectType.ACP,
});
- For SuiteApps:
const SuiteCloudJestConfiguration = require("@oracle/suitecloud-unit-testing/jest-configuration/SuiteCloudJestConfiguration");
module.exports = SuiteCloudJestConfiguration.build({
projectFolder: 'src', //or your SDF project folder
projectType: SuiteCloudJestConfiguration.ProjectType.SUITEAPP,
});
Here you can find two examples on how to use SuiteCloud Unit Testing with an SDF project.
The first example covers testing for the N/record module, which is fully mocked in SuiteCloud Unit Testing. Whereas the second example covers the testing of a module that is not mocked in SuiteCloud Unit Testing, by using a custom stub.
💡 You can manually mock any module that is still not supported in SuiteCloud Unit Testing.
This example follows the structure presented below:
myAccountCustomizationProject
├── __tests__
│ └── sample-test.js
├── node_modules
├── src
│ ├── AccountConfiguration
│ ├── FileCabinet
│ ├── SuiteScripts
│ └── Suitelet.js
│ ├── Objects
│ ├── Translations
│ ├── deploy.xml
│ └── manifest.xml
├── jest.config.js
├── suitecloud.config.js
├── package-lock.json
├── package.json
└── project.json
See below the content of the SuiteCloud Unit Testing files:
jest.config.js
file
const SuiteCloudJestConfiguration = require("@oracle/suitecloud-unit-testing/jest-configuration/SuiteCloudJestConfiguration");
module.exports = SuiteCloudJestConfiguration.build({
projectFolder: 'src',
projectType: SuiteCloudJestConfiguration.ProjectType.ACP,
});
Suitelet.js
file
/**
* @NApiVersion 2.x
* @NScriptType Suitelet
* @NModuleScope SameAccount
*/
define(["N/record"], function(record) {
return {
onRequest: function(context) {
if (context.request.method === 'GET') {
const salesOrderId = context.request.parameters.salesOrderId;
let salesOrderRecord = record.load({id: salesOrderId});
salesOrderRecord.setValue({fieldId: 'memo', value: "foobar"});
salesOrderRecord.save({enableSourcing: false});
}
}
};
});
Suitelet.test.js
file
import Suitelet from "SuiteScripts/Suitelet";
import record from "N/record";
import Record from "N/record/instance";
jest.mock("N/record");
jest.mock("N/record/instance");
beforeEach(() => {
jest.clearAllMocks();
});
describe("Suitelet Test", () => {
it("Sales Order memo field has been updated", () => {
// given
const context = {
request: {
method: 'GET',
parameters: {
salesOrderId: 1352
}
}
};
record.load.mockReturnValue(Record);
Record.save.mockReturnValue(1352);
// when
Suitelet.onRequest(context);
// then
expect(record.load).toHaveBeenCalledWith({id: 1352});
expect(Record.setValue).toHaveBeenCalledWith({fieldId: 'memo', value: 'foobar'});
expect(Record.save).toHaveBeenCalledWith({enableSourcing: false});
});
});
This example follows the structure presented below:
myAccountCustomizationProject
├── customStubs
│ └── http.js
├── __tests__
│ └── http.test.js
├── node_modules
├── src
│ ├── AccountConfiguration
│ ├── FileCabinet
│ ├── SuiteScripts
│ ├── Templates
│ ├── Web Site Hosting Files
│ ├── Objects
│ ├── Translations
│ ├── deploy.xml
│ └── manifest.xml
├── jest.config.js
├── suitecloud.config.js
├── package-lock.json
├── package.json
└── project.json
See below the content of the SuiteCloud Unit Testing files:
jest.config.js
file
const SuiteCloudJestConfiguration = require("@oracle/suitecloud-unit-testing/jest-configuration/SuiteCloudJestConfiguration");
module.exports = SuiteCloudJestConfiguration.build({
projectFolder: 'src',
projectType: SuiteCloudJestConfiguration.ProjectType.ACP,
customStubs: [
{
module: "N/http",
path: "<rootDir>/customStubs/http.js"
}
]
});
http.js
file: This is the stub file. It partially mocks NetSuite's N/http module.
💡 The JSDoc annotations are copied from NetSuite's N/http module, but are not required to run SuiteCloud unit testing.
define([], function() {
/**
* @namespace http
*/
var http = function() {};
/**
* Send a HTTP GET request and return a reponse from a server.
*
* @governance 10 units
* @restriction Server SuiteScript only
*
* @param {Object} options
* @param {string} options.url the HTTP URL being requested
* @param {Object} options.headers (optional) The HTTP headers
* @return {ClientResponse}
*
* @throws {SuiteScriptError} SSS_MISSING_REQD_ARGUMENT if a required argument is missing
* @throws {SuiteScriptError} SSS_INVALID_URL if an incorrect protocol is used (ex: http in the HTTPS module)
*
* @since 2015.2
*/
http.prototype.get = function(options) {};
/**
* @exports N/http
* @namespace http
*/
return new http();
});
http.test.js
file
import http from 'N/http';
jest.mock('N/http');
beforeEach(() => {
jest.clearAllMocks();
});
describe('Sample test with user defined http module stub', () => {
it('should call http get method', () => {
// given
const clientResponseMock = {
code: 200,
body: {
data: 'foobar'
}
// more properties and functions here if needed
};
http.get.mockReturnValue(clientResponseMock);
const options = {
url: 'https://netsuite.com'
};
// when
const clientResponse = http.get(options);
// then
expect(http.get).toHaveBeenCalledWith(options);
expect(clientResponse).toMatchObject({
code: 200,
body: {
data: 'foobar'
}
});
});
});
Suitecloud Unit Testing is an open source project. Pull Requests are currently not being accepted. See CONTRIBUTING for details.
Copyright (c) 2020 Oracle and/or its affiliates The Universal Permissive License (UPL), Version 1.0.