@pact-foundation/pact
Version:
Pact for all things Javascript
292 lines • 15.3 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SynchronousMessageWithResponse = exports.SynchronousMessageWithTransport = exports.SynchronousMessageWithPluginContents = exports.SynchronousMessageWithResponseBuilder = exports.SynchronousMessageWithRequest = exports.SynchronousMessageWithRequestBuilder = exports.SynchronousMessageWithPlugin = exports.UnconfiguredSynchronousMessage = void 0;
var ramda_1 = require("ramda");
var configurationError_1 = __importDefault(require("../../errors/configurationError"));
var display_1 = require("../../v3/display");
var logger_1 = __importDefault(require("../../common/logger"));
var defaultPactDir = './pacts';
var UnconfiguredSynchronousMessage = /** @class */ (function () {
function UnconfiguredSynchronousMessage(pact, interaction, opts, cleanupFn) {
this.pact = pact;
this.interaction = interaction;
this.opts = opts;
this.cleanupFn = cleanupFn;
}
UnconfiguredSynchronousMessage.prototype.given = function (state, parameters) {
if (parameters) {
this.interaction.givenWithParams(state, JSON.stringify(parameters));
}
else {
this.interaction.given(state);
}
return this;
};
UnconfiguredSynchronousMessage.prototype.usingPlugin = function (config) {
this.pact.addPlugin(config.plugin, config.version);
return new SynchronousMessageWithPlugin(this.pact, this.interaction, this.opts, this.cleanupFn);
};
UnconfiguredSynchronousMessage.prototype.withRequest = function (r) {
return new SynchronousMessageWithRequest(this.pact, this.interaction, this.opts, this.cleanupFn);
};
return UnconfiguredSynchronousMessage;
}());
exports.UnconfiguredSynchronousMessage = UnconfiguredSynchronousMessage;
var SynchronousMessageWithPlugin = /** @class */ (function () {
function SynchronousMessageWithPlugin(pact, interaction, opts, cleanupFn) {
this.pact = pact;
this.interaction = interaction;
this.opts = opts;
this.cleanupFn = cleanupFn;
}
SynchronousMessageWithPlugin.prototype.usingPlugin = function (config) {
this.pact.addPlugin(config.plugin, config.version);
return this;
};
SynchronousMessageWithPlugin.prototype.withPluginContents = function (contents, contentType) {
this.interaction.withPluginRequestResponseInteractionContents(contentType, contents);
return new SynchronousMessageWithPluginContents(this.pact, this.interaction, this.opts, this.cleanupFn);
};
return SynchronousMessageWithPlugin;
}());
exports.SynchronousMessageWithPlugin = SynchronousMessageWithPlugin;
var SynchronousMessageWithRequestBuilder = /** @class */ (function () {
function SynchronousMessageWithRequestBuilder(pact, interaction, opts) {
this.pact = pact;
this.interaction = interaction;
this.opts = opts;
}
SynchronousMessageWithRequestBuilder.prototype.withContent = function (contentType, body) {
this.interaction.withRequestBinaryContents(body, contentType);
return this;
};
SynchronousMessageWithRequestBuilder.prototype.withJSONContent = function (content) {
if ((0, ramda_1.isEmpty)(content)) {
throw new configurationError_1.default('You must provide a valid JSON document or primitive for the Message.');
}
this.interaction.withRequestContents(JSON.stringify(content), 'application/json');
return this;
};
return SynchronousMessageWithRequestBuilder;
}());
exports.SynchronousMessageWithRequestBuilder = SynchronousMessageWithRequestBuilder;
var SynchronousMessageWithRequest = /** @class */ (function () {
function SynchronousMessageWithRequest(pact, interaction, opts, cleanupFn) {
this.pact = pact;
this.interaction = interaction;
this.opts = opts;
this.cleanupFn = cleanupFn;
}
SynchronousMessageWithRequest.prototype.withResponse = function (builder) {
builder(new SynchronousMessageWithResponseBuilder(this.pact, this.interaction, this.opts));
return new SynchronousMessageWithResponse(this.pact, this.interaction, this.opts, this.cleanupFn);
};
return SynchronousMessageWithRequest;
}());
exports.SynchronousMessageWithRequest = SynchronousMessageWithRequest;
var SynchronousMessageWithResponseBuilder = /** @class */ (function () {
function SynchronousMessageWithResponseBuilder(pact, interaction, opts) {
this.pact = pact;
this.interaction = interaction;
this.opts = opts;
}
SynchronousMessageWithResponseBuilder.prototype.withMetadata = function (metadata) {
var _this = this;
if ((0, ramda_1.isEmpty)(metadata)) {
throw new configurationError_1.default('You must provide valid metadata for the Message, or none at all');
}
(0, ramda_1.forEachObjIndexed)(function (v, k) {
_this.interaction.withMetadata("".concat(k), JSON.stringify(v));
}, metadata);
return this;
};
SynchronousMessageWithResponseBuilder.prototype.withContent = function (contentType, body) {
this.interaction.withResponseBinaryContents(body, contentType);
return this;
};
SynchronousMessageWithResponseBuilder.prototype.withJSONContent = function (content) {
if ((0, ramda_1.isEmpty)(content)) {
throw new configurationError_1.default('You must provide a valid JSON document or primitive for the Message.');
}
this.interaction.withResponseContents(JSON.stringify(content), 'application/json');
return this;
};
return SynchronousMessageWithResponseBuilder;
}());
exports.SynchronousMessageWithResponseBuilder = SynchronousMessageWithResponseBuilder;
var SynchronousMessageWithPluginContents = /** @class */ (function () {
function SynchronousMessageWithPluginContents(pact, interaction, opts, cleanupFn) {
this.pact = pact;
this.interaction = interaction;
this.opts = opts;
this.cleanupFn = cleanupFn;
}
SynchronousMessageWithPluginContents.prototype.executeTest = function (integrationTest) {
return executeNonTransportTest(this.pact, this.opts, integrationTest, this.cleanupFn);
};
SynchronousMessageWithPluginContents.prototype.startTransport = function (transport, address, // IP Address or hostname
config) {
var port = this.pact.pactffiCreateMockServerForTransport(address, transport, config ? JSON.stringify(config) : '');
return new SynchronousMessageWithTransport(this.pact, this.interaction, this.opts, port, address, this.cleanupFn);
};
return SynchronousMessageWithPluginContents;
}());
exports.SynchronousMessageWithPluginContents = SynchronousMessageWithPluginContents;
var SynchronousMessageWithTransport = /** @class */ (function () {
function SynchronousMessageWithTransport(pact, interaction, opts, port, address, cleanupFn) {
this.pact = pact;
this.interaction = interaction;
this.opts = opts;
this.port = port;
this.address = address;
this.cleanupFn = cleanupFn;
}
// TODO: this is basically the same as the HTTP variant, except only with a different test function wrapper
// extract these into smaller, testable chunks and re-use them
SynchronousMessageWithTransport.prototype.executeTest = function (integrationTest) {
return __awaiter(this, void 0, void 0, function () {
var val, error, e_1, matchingResults, errors, success, errorMessage;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, integrationTest({ port: this.port, address: this.address }, {})];
case 1:
val = _a.sent();
return [3 /*break*/, 3];
case 2:
e_1 = _a.sent();
error = e_1;
return [3 /*break*/, 3];
case 3:
matchingResults = this.pact.mockServerMismatches(this.port);
errors = (0, display_1.filterMissingFeatureFlag)(matchingResults);
success = this.pact.mockServerMatchedSuccessfully(this.port);
// Scenario: Pact validation failed
if (!success && errors.length > 0) {
errorMessage = 'Test failed for the following reasons:';
errorMessage += "\n\n ".concat((0, display_1.generateMockServerError)(matchingResults, '\t'));
cleanup(false, this.pact, this.opts, this.cleanupFn, this.port, true);
// If the tests throws an error, we need to rethrow the error, but print out
// any additional mock server errors to help the user understand what happened
// (The proximate cause here is often the HTTP 500 from the mock server,
// where the HTTP client then throws)
if (error) {
logger_1.default.error(errorMessage);
throw error;
}
// Test didn't throw, so we need to ensure the test fails
return [2 /*return*/, Promise.reject(new Error(errorMessage))];
}
// Scenario: test threw an error, but Pact validation was OK (error in client or test)
if (error) {
cleanup(false, this.pact, this.opts, this.cleanupFn, this.port, true);
throw error;
}
// Scenario: Pact validation passed, test didn't throw - return the callback value
cleanup(true, this.pact, this.opts, this.cleanupFn, this.port, true);
return [2 /*return*/, val];
}
});
});
};
return SynchronousMessageWithTransport;
}());
exports.SynchronousMessageWithTransport = SynchronousMessageWithTransport;
var SynchronousMessageWithResponse = /** @class */ (function () {
function SynchronousMessageWithResponse(pact, interaction, opts, cleanupFn) {
this.pact = pact;
this.interaction = interaction;
this.opts = opts;
this.cleanupFn = cleanupFn;
}
SynchronousMessageWithResponse.prototype.executeTest = function (integrationTest) {
var res = executeNonTransportTest(this.pact, this.opts, integrationTest, this.cleanupFn);
this.cleanupFn();
return res;
};
return SynchronousMessageWithResponse;
}());
exports.SynchronousMessageWithResponse = SynchronousMessageWithResponse;
var cleanup = function (success, pact, opts, cleanupFn, port, transport) {
if (transport === void 0) { transport = false; }
if (success) {
if (transport && port) {
pact.writePactFileForPluginServer(port, opts.dir || defaultPactDir, true);
}
else {
pact.writePactFile(opts.dir || defaultPactDir);
}
}
if (port) {
pact.cleanupMockServer(port);
}
pact.cleanupPlugins();
cleanupFn();
};
var executeNonTransportTest = function (pact, opts, integrationTest, cleanupFn) { return __awaiter(void 0, void 0, void 0, function () {
var val, error, e_2;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, integrationTest({})];
case 1:
val = _a.sent();
return [3 /*break*/, 3];
case 2:
e_2 = _a.sent();
error = e_2;
return [3 /*break*/, 3];
case 3:
// Scenario: test threw an error, but Pact validation was OK (error in client or test)
if (error) {
cleanup(false, pact, opts, cleanupFn);
throw error;
}
// Scenario: Pact validation passed, test didn't throw - return the callback value
cleanup(true, pact, opts, cleanupFn);
return [2 /*return*/, val];
}
});
}); };
//# sourceMappingURL=index.js.map