Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

scenario-mock-server

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

scenario-mock-server - npm Package Compare versions

Comparing version 1.1.0 to 1.2.0

15

dist/index.d.ts
import * as server_with_kill from 'server-with-kill';
import express from 'express';
type Scenario = {
type ScenarioWithOptionalProperties = {
name?: string;

@@ -10,3 +10,6 @@ description?: string;

extend?: string;
} | Mock[];
group?: string;
};
type Scenario = ScenarioWithOptionalProperties | Mock[];
type Groups = Record<string, string>;
type ApiScenario = {

@@ -17,2 +20,3 @@ id: string;

selected: boolean;
group: null | string;
};

@@ -66,2 +70,3 @@ type ScenarioMap = Record<string, Scenario>;

scenariosPath?: string;
groupsPath?: string;
cookieMode?: boolean;

@@ -74,12 +79,14 @@ parallelContextSize?: number;

declare function run({ scenarios, options, }: {
declare function run({ scenarios, options, groups, }: {
scenarios: ScenarioMap;
options?: Options;
groups?: Groups;
}): server_with_kill.ServerWithKill;
declare function createExpressApp({ scenarios: externalScenarioMap, options, }: {
declare function createExpressApp({ scenarios: externalScenarioMap, options, groups, }: {
scenarios: ScenarioMap;
options?: Omit<Options, 'port'>;
groups?: Groups;
}): ReturnType<typeof express>;
export { ApiScenario, GraphQlMock, HttpMock, Mock, Operation, Options, Scenario, createExpressApp, run };

@@ -82,5 +82,7 @@ "use strict";

uiPath,
scenarios
scenarios,
groups
}) {
return /* @__PURE__ */ import_react.default.createElement("html", { lang: "en" }, /* @__PURE__ */ import_react.default.createElement("head", null, /* @__PURE__ */ import_react.default.createElement("meta", { charSet: "utf-8" }), /* @__PURE__ */ import_react.default.createElement("meta", { name: "viewport", content: "width=device-width,initial-scale=1" }), /* @__PURE__ */ import_react.default.createElement("title", null, updatedScenarioName ? "Updated - " : "", "Scenarios - Scenario Mock Server"), /* @__PURE__ */ import_react.default.createElement(
return /* @__PURE__ */ import_react.default.createElement("html", { lang: "en" }, /* @__PURE__ */ import_react.default.createElement("head", null, /* @__PURE__ */ import_react.default.createElement("meta", { charSet: "utf-8" }), /* @__PURE__ */ import_react.default.createElement("meta", { name: "viewport", content: "width=device-width,initial-scale=1" }), /* @__PURE__ */ import_react.default.createElement("title", null, `${updatedScenarioName ? "Updated - " : ""}Scenarios - Scenario Mock
Server`), /* @__PURE__ */ import_react.default.createElement(
"link",

@@ -91,12 +93,3 @@ {

}
)), /* @__PURE__ */ import_react.default.createElement("body", null, /* @__PURE__ */ import_react.default.createElement("main", null, /* @__PURE__ */ import_react.default.createElement(ScenarioUpdateInfo, { updatedScenarioName }), /* @__PURE__ */ import_react.default.createElement("form", { className: "stack-1", method: "POST", action: uiPath }, /* @__PURE__ */ import_react.default.createElement("p", null, /* @__PURE__ */ import_react.default.createElement("a", { href: uiPath }, "Refresh page")), /* @__PURE__ */ import_react.default.createElement(CallToActionButton, null), /* @__PURE__ */ import_react.default.createElement("fieldset", { className: "stack-3" }, /* @__PURE__ */ import_react.default.createElement("legend", null, /* @__PURE__ */ import_react.default.createElement("h1", null, "Scenarios")), /* @__PURE__ */ import_react.default.createElement("div", { className: "stack-3" }, scenarios.map((scenario) => /* @__PURE__ */ import_react.default.createElement("div", { key: scenario.id }, /* @__PURE__ */ import_react.default.createElement(
"input",
{
type: "radio",
id: scenario.id,
name: "scenarioId",
value: scenario.id,
defaultChecked: scenario.selected
}
), /* @__PURE__ */ import_react.default.createElement("label", { htmlFor: scenario.id }, scenario.name), scenario.description ? /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("br", null), /* @__PURE__ */ import_react.default.createElement("details", null, /* @__PURE__ */ import_react.default.createElement("summary", null, "Description"), /* @__PURE__ */ import_react.default.createElement("div", { className: "description" }, scenario.description))) : null)))), /* @__PURE__ */ import_react.default.createElement(CallToActionButton, null)))));
)), /* @__PURE__ */ import_react.default.createElement("body", null, /* @__PURE__ */ import_react.default.createElement("main", null, /* @__PURE__ */ import_react.default.createElement(ScenarioUpdateInfo, { updatedScenarioName }), /* @__PURE__ */ import_react.default.createElement("form", { className: "stack-1", method: "POST", action: uiPath }, /* @__PURE__ */ import_react.default.createElement("p", null, /* @__PURE__ */ import_react.default.createElement("a", { href: uiPath }, "Refresh page")), /* @__PURE__ */ import_react.default.createElement(CallToActionButton, null), /* @__PURE__ */ import_react.default.createElement("fieldset", { className: "stack-3" }, /* @__PURE__ */ import_react.default.createElement("legend", null, /* @__PURE__ */ import_react.default.createElement("h1", null, "Scenarios")), scenarios.some(({ group }) => group !== null) ? /* @__PURE__ */ import_react.default.createElement(GroupedScenarios, { groups, scenarios }) : /* @__PURE__ */ import_react.default.createElement(ScenarioList, { scenarios })), /* @__PURE__ */ import_react.default.createElement(CallToActionButton, null)))));
}

@@ -114,2 +107,32 @@ function ScenarioUpdateInfo({

}
var NULL_GROUP_ID = "sms-other";
function GroupedScenarios({
groups,
scenarios
}) {
const groupedScenarios = {};
scenarios.forEach((scenario) => {
const group = scenario.group === null ? NULL_GROUP_ID : scenario.group;
groupedScenarios[group] = groupedScenarios[group] || [];
groupedScenarios[group].push(scenario);
});
const groupsWithLabelIds = Object.keys(groups);
const groupsWithoutLabelIds = Object.keys(groupedScenarios).filter(
(groupId) => !groupsWithLabelIds.includes(groupId) && groupId !== NULL_GROUP_ID
);
const groupEntries = Object.entries(groups).concat(groupsWithoutLabelIds.map((groupId) => [groupId, groupId])).concat([[NULL_GROUP_ID, "Other"]]);
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, groupEntries.map(([groupId, groupName]) => /* @__PURE__ */ import_react.default.createElement("div", { key: groupId }, /* @__PURE__ */ import_react.default.createElement("h2", null, groupName), /* @__PURE__ */ import_react.default.createElement(ScenarioList, { scenarios: groupedScenarios[groupId] }))));
}
function ScenarioList({ scenarios }) {
return /* @__PURE__ */ import_react.default.createElement("div", { className: "stack-3" }, scenarios.map((scenario) => /* @__PURE__ */ import_react.default.createElement("div", { key: scenario.id }, /* @__PURE__ */ import_react.default.createElement(
"input",
{
type: "radio",
id: scenario.id,
name: "scenarioId",
value: scenario.id,
defaultChecked: scenario.selected
}
), /* @__PURE__ */ import_react.default.createElement("label", { htmlFor: scenario.id }, scenario.name), scenario.description ? /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("br", null), /* @__PURE__ */ import_react.default.createElement("details", null, /* @__PURE__ */ import_react.default.createElement("summary", null, "Description"), /* @__PURE__ */ import_react.default.createElement("div", { className: "description" }, scenario.description))) : null)));
}

@@ -209,7 +232,8 @@ // src/cookies.ts

const allScenarios = scenarios.map(
({ id, name, description }) => ({
({ id, name, description, group }) => ({
id,
name,
description: description === void 0 ? null : description,
selected: id === scenarioId
selected: id === scenarioId,
group: group === void 0 ? null : group
})

@@ -307,3 +331,4 @@ );

setCookie,
getServerScenarioId
getServerScenarioId,
groups
}) {

@@ -319,3 +344,5 @@ const { data } = getScenarios({

});
const html = (0, import_server.renderToStaticMarkup)(/* @__PURE__ */ import_react2.default.createElement(Html, { uiPath, scenarios: data }));
const html = (0, import_server.renderToStaticMarkup)(
/* @__PURE__ */ import_react2.default.createElement(Html, { uiPath, scenarios: data, groups })
);
return "<!DOCTYPE html>\n" + html;

@@ -331,3 +358,4 @@ }

setServerContext,
setServerScenarioId
setServerScenarioId,
groups
}) {

@@ -343,7 +371,8 @@ const updatedScenarioName = scenarioMap[scenarioId].name;

});
const allScenarios = scenarios.map(({ id, name, description }) => ({
const allScenarios = scenarios.map(({ id, name, description, group }) => ({
id,
name,
description: description === void 0 ? null : description,
selected: id === scenarioId
selected: id === scenarioId,
group: group === void 0 ? null : group
}));

@@ -356,2 +385,3 @@ const html = (0, import_server.renderToStaticMarkup)(

scenarios: allScenarios,
groups,
updatedScenarioName

@@ -762,5 +792,28 @@ }

// src/express.ts
function scenarioHasGroup(scenario) {
return !Array.isArray(scenario) && scenario.group != null;
}
function validateAllGroupsHaveNames({
scenarios,
groups
}) {
const uniqueGroups = Array.from(
Object.values(scenarios).filter(scenarioHasGroup).reduce((set, { group }) => {
set.add(group);
return set;
}, /* @__PURE__ */ new Set()).values()
);
const groupsWithoutNames = uniqueGroups.filter((group) => !groups[group]);
if (groupsWithoutNames.length > 0) {
console.warn(
`The following groups do not have a name: ${groupsWithoutNames.join(
", "
)}`
);
}
}
function createExpressApp({
scenarios: externalScenarioMap,
options = {}
options = {},
groups = {}
}) {

@@ -771,5 +824,7 @@ const {

scenariosPath = "/scenarios",
groupsPath = "/groups",
cookieMode = false,
parallelContextSize = 10
} = options;
validateAllGroupsHaveNames({ scenarios: externalScenarioMap, groups });
const { scenarios, scenarioMap } = generateScenarios(externalScenarioMap);

@@ -799,3 +854,4 @@ const { initialScenarioId, initialContext } = generatInitialValues(

getServerScenarioId,
scenarios
scenarios,
groups
});

@@ -815,3 +871,4 @@ res.send(html);

setServerContext,
setServerScenarioId
setServerScenarioId,
groups
});

@@ -844,2 +901,11 @@ res.send(html);

});
app.get(groupsPath, (_, res) => {
expressResponse(res, {
status: 200,
headers: {
"content-type": "application/json"
},
data: Object.entries(groups).map(([id, name]) => ({ id, name }))
});
});
app.use(async (req, res) => {

@@ -945,3 +1011,4 @@ const internalRequest = {

scenarios,
options = {}
options = {},
groups = {}
}) {

@@ -951,3 +1018,4 @@ const _a = options, { port = 3e3 } = _a, restOfOptions = __objRest(_a, ["port"]);

scenarios,
options: restOfOptions
options: restOfOptions,
groups
});

@@ -954,0 +1022,0 @@ return (0, import_server_with_kill.transform)(

{
"name": "scenario-mock-server",
"version": "1.1.0",
"version": "1.2.0",
"description": "Mock server powered by scenarios",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -16,6 +16,11 @@ # Scenario Mock Server

- [sms-context-id header](#sms-context-id-header)
- [Additional API paths](#additional-api-paths)
- [/scenarios](#scenarios)
- [/select-scenario](#select-scenario)
- [/groups](#groups)
- [API](#api)
- [createExpressApp](#createexpressapp)
- [run](#run)
- [scenarios](#scenarios)
- [scenarios](#scenarios-1)
- [groups](#groups-1)
- [options](#options)

@@ -125,2 +130,47 @@ - [Types](#types)

## Additional API paths
In addition to responding to API requests as set up by the currently active scenario a few additional endpoints exist that return json:
- `/scenarios`
- `/select-scenario`
- `/groups`
These paths can be modified by using `options` (in case they clash with paths from scnearios).
### /scenarios
Returns an array of scenarios available. Use `GET`.
```ts
type ApiScenario = {
id: string;
name: string;
description: null | string;
selected: boolean;
group: null | string;
};
```
### /select-scenario
Allows you to select which scenario is active. Use `PUT` and the following body:
```json
{
"scenarioId": "{SCENARIO_YOU_WANT_TO_SELECT}"
}
```
### /groups
Returns an array of groups. Use `GET`.
```ts
type ApiGroup = {
id: string;
name: string;
};
```
## API

@@ -142,3 +192,3 @@

> `{ [scenarioId]: Array<Mock> | { name, description, context, mocks, extend } }`
> `{ [scenarioId]: Array<Mock> | { name, description, context, mocks, extend, group } }`

@@ -156,6 +206,18 @@ <!-- https://www.tablesgenerator.com/markdown_tables -->

| extend | `string` | `undefined` | Use for extending other scenarios. Requires a scenario id. |
| group | `string` | `undefined` | Used for grouping scenarios in the UI. |
#### groups
> `{ [groupId]: groupName }`
<!-- https://www.tablesgenerator.com/markdown_tables -->
| Property | Type | Default | Description |
| --------- | -------- | ---------- | ----------------------------------------------------- |
| groupId | `string` | _required_ | Group id. Matches with `group` assigned to scenarios. |
| groupName | `string` | _required_ | Used for heading in UI when groups exist. |
#### options
> `{ port, uiPath, selectScenarioPath, scenariosPath, cookieMode, parallelContextSize }` | defaults to `{}`
> `{ port, uiPath, selectScenarioPath, scenariosPath, groupsPath, cookieMode, parallelContextSize }` | defaults to `{}`

@@ -170,2 +232,3 @@ <!-- https://www.tablesgenerator.com/markdown_tables -->

| scenariosPath | `string` | `/scenarios` | API path for getting scenarios. `http://localhost:{port}{scenariosPath}` |
| groupsPath | `string` | `/groups` | API path for getting groups. `http://localhost:{port}{groupsPath}` |
| cookieMode | `boolean` | `false` | Whether or not to store scenario selections in a cookie rather than directly in the server |

@@ -172,0 +235,0 @@ | parallelContextSize | `number` | `10` | How large to make the number of contexts that can run in parallel. See [Running tests in parallel](#running-tests-in-parallel) |

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc