mockaton 8.5.1 → 8.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -41,9 +41,9 @@ route, among other options. In addition, there’s a programmatic API,
41
41
  which is handy for setting up tests (see **Commander API** below).
42
42
 
43
43
  <picture>
44
- <source media="(prefers-color-scheme: light)" srcset="./README-dashboard-light.png">
45
- <source media="(prefers-color-scheme: dark)" srcset="./README-dashboard-dark.png">
46
- <img alt="Mockaton Dashboard Demo" src="./README-dashboard-light.png">
44
+ <source media="(prefers-color-scheme: light)" srcset="./pixaton-tests/pic-for-readme.vp1024x800.light.gold.png">
45
+ <source media="(prefers-color-scheme: dark)" srcset="./pixaton-tests/pic-for-readme.vp1024x800.dark.gold.png">
46
+ <img alt="Mockaton Dashboard" src="./pixaton-tests/pic-for-readme.vp1024x800.light.gold.png">
47
47
  </picture>
48
48
 
49
49
 
@@ -84,6 +84,8 @@ npm run start
84
84
 
85
85
  By the way, that directory has a script for opening Mockaton and Vite in one command.
86
86
 
87
+ <img src="./demo-app-vite/README-screenshot.png" alt="Mockaton Demo App Screenshot" style="max-width: 600px" />
88
+
87
89
 
88
90
  ## Use Cases
89
91
  ### Testing
package/TODO.md CHANGED
@@ -1,5 +1,4 @@
1
1
  # TODO
2
2
 
3
3
  - Refactor tests
4
- - Add Collect Proxied checkbox to the dashboard (remove Allow CORS)
5
- - Dashboard refresh (long polling ?)
4
+ - Dashboard refresh (long polling?)
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "mockaton",
3
3
  "description": "A deterministic server-side for developing and testing frontend clients",
4
4
  "type": "module",
5
- "version": "8.5.1",
5
+ "version": "8.6.0",
6
6
  "main": "index.js",
7
7
  "types": "index.d.ts",
8
8
  "license": "MIT",
@@ -11,11 +11,11 @@
11
11
  "test": "node --test src/**.test.js",
12
12
  "start": "node dev-mockaton.js",
13
13
  "start:ts": "node --import=tsx dev-mockaton.js",
14
- "test-ui": "node --test --import=./ui-tests/_setup.js --experimental-test-isolation=none \"./ui-tests/**/*.test.js\"",
14
+ "pixaton": "node --test --import=./pixaton-tests/_setup.js --experimental-test-isolation=none \"pixaton-tests/**/*.test.js\"",
15
15
  "outdated": "npm outdated --parseable | awk -F: '{ printf \"npm i %-30s ;# %s\\n\", $4, $2 }'"
16
16
  },
17
17
  "optionalDependencies": {
18
- "pixaton": ">=1.0.1",
18
+ "pixaton": ">=1.0.2",
19
19
  "puppeteer": ">=23.10.1"
20
20
  }
21
21
  }
package/src/Api.js CHANGED
@@ -26,6 +26,7 @@ export const apiGetRequests = new Map([
26
26
  [API.comments, listComments],
27
27
  [API.fallback, getProxyFallback],
28
28
  [API.cors, getIsCorsAllowed],
29
+ [API.collectProxied, getCollectProxied],
29
30
  [API.static, listStaticFiles]
30
31
  ])
31
32
 
@@ -50,6 +51,7 @@ function listComments(_, response) { sendJSON(response, mockBrokersCollection.ex
50
51
  function listMockBrokers(_, response) { sendJSON(response, mockBrokersCollection.getAll()) }
51
52
  function getProxyFallback(_, response) { sendJSON(response, config.proxyFallback) }
52
53
  function getIsCorsAllowed(_, response) { sendJSON(response, config.corsAllowed) }
54
+ function getCollectProxied(_, response) { sendJSON(response, config.collectProxied) }
53
55
 
54
56
  function listStaticFiles(req, response) {
55
57
  try {
package/src/Commander.js CHANGED
@@ -54,14 +54,13 @@ export class Commander {
54
54
  return this.#patch(API.fallback, proxyAddr)
55
55
  }
56
56
 
57
+ getCollectProxied() {
58
+ return this.#get(API.collectProxied)
59
+ }
57
60
  setCollectProxied(shouldCollect) {
58
61
  return this.#patch(API.collectProxied, shouldCollect)
59
62
  }
60
63
 
61
- reset() {
62
- return this.#patch(API.reset)
63
- }
64
-
65
64
  getCorsAllowed() {
66
65
  return this.#get(API.cors)
67
66
  }
@@ -72,4 +71,8 @@ export class Commander {
72
71
  listStaticFiles() {
73
72
  return this.#get(API.static)
74
73
  }
74
+
75
+ reset() {
76
+ return this.#patch(API.reset)
77
+ }
75
78
  }
package/src/Dashboard.css CHANGED
@@ -9,14 +9,14 @@
9
9
  --colorAccentAlt: #009c71;
10
10
  --colorBackground: #fff;
11
11
  --colorHeaderBackground: #f7f7f7;
12
- --colorComboBoxBackground: #fafafa;
12
+ --colorComboBoxBackground: #f7f7f7;
13
+ --colorSecondaryButtonBackground: #f5f5f5;
13
14
  --colorComboBoxHeaderBackground: #fff;
14
15
  --colorDisabled: #444;
15
16
  --colorHover: #dfefff;
16
17
  --colorLabel: #444;
17
18
  --colorLightRed: #ffe4ee;
18
19
  --colorRed: #da0f00;
19
- --colorSecondaryButtonBackground: #fafafa;
20
20
  --colorText: #000;
21
21
  }
22
22
  }
@@ -28,13 +28,13 @@
28
28
  --colorBackground: #161616;
29
29
  --colorHeaderBackground: #090909;
30
30
  --colorComboBoxBackground: #252525;
31
+ --colorSecondaryButtonBackground: #444;
31
32
  --colorComboBoxHeaderBackground: #222;
32
33
  --colorDisabled: #bbb;
33
34
  --colorHover: #023661;
34
35
  --colorLabel: #aaa;
35
36
  --colorLightRed: #ffe4ee;
36
37
  --colorRed: #f41606;
37
- --colorSecondaryButtonBackground: #444;
38
38
  --colorText: #fff;
39
39
  }
40
40
  }
@@ -49,12 +49,13 @@ body {
49
49
  color: var(--colorText);
50
50
  }
51
51
  * {
52
+ box-sizing: border-box;
52
53
  padding: 0;
53
54
  border: 0;
54
55
  margin: 0;
55
56
  font-family: system-ui, sans-serif;
56
57
  font-size: 100%;
57
- outline: 0
58
+ outline: 0;
58
59
  }
59
60
 
60
61
  select, a, input, button, summary {
@@ -91,7 +92,7 @@ menu {
91
92
  display: flex;
92
93
  width: 100%;
93
94
  align-items: flex-end;
94
- padding: 16px;
95
+ padding: 15px 16px;
95
96
  border-bottom: 1px solid rgba(127, 127, 127, 0.1);
96
97
  background: var(--colorHeaderBackground);
97
98
  box-shadow: var(--boxShadow1);
@@ -103,7 +104,9 @@ menu {
103
104
  margin-right: 18px;
104
105
  }
105
106
 
106
- label {
107
+ .Field {
108
+ min-width: 150px;
109
+
107
110
  span {
108
111
  display: block;
109
112
  color: var(--colorLabel);
@@ -112,27 +115,48 @@ menu {
112
115
 
113
116
  input[type=url],
114
117
  select {
118
+ width: 100%;
115
119
  height: 28px;
116
- width: 150px;
117
120
  padding: 4px 2px;
118
121
  border-right: 3px solid transparent;
119
- margin-top: 2px;
122
+ margin-top: 4px;
120
123
  font-size: 11px;
121
124
  background: var(--colorComboBoxHeaderBackground);
122
125
  border-radius: 6px;
123
126
  }
124
127
 
125
- input[type=url] {
126
- padding: 0 6px;
127
- box-shadow: var(--boxShadow1);
128
- color: var(--colorText);
128
+ &.FallbackBackend {
129
+ position: relative;
130
+ width: 194px;
131
+
132
+ input[type=url] {
133
+ padding: 0 6px;
134
+ box-shadow: var(--boxShadow1);
135
+ color: var(--colorText);
136
+ }
137
+
138
+ .SaveProxiedCheckbox {
139
+ position: absolute;
140
+ top: 0;
141
+ right: 0;
142
+ display: flex;
143
+ width: auto;
144
+ min-width: unset;
145
+ align-items: center;
146
+ font-size: 11px;
147
+ gap: 4px;
148
+
149
+ input:disabled + span {
150
+ opacity: 0.7;
151
+ }
152
+ }
129
153
  }
130
154
  }
131
155
 
132
156
  .ResetButton {
133
157
  padding: 4px 12px;
134
- margin-bottom: 4px;
135
158
  border: 1px solid var(--colorRed);
159
+ margin-bottom: 4px;
136
160
  background: transparent;
137
161
  color: var(--colorRed);
138
162
  border-radius: 50px;
@@ -144,13 +168,6 @@ menu {
144
168
  box-shadow: var(--boxShadow1);
145
169
  }
146
170
  }
147
-
148
- .CorsCheckbox {
149
- display: flex;
150
- align-items: center;
151
- margin-bottom: 8px;
152
- gap: 4px;
153
- }
154
171
  }
155
172
 
156
173
 
@@ -368,8 +385,8 @@ main {
368
385
 
369
386
  a {
370
387
  display: inline-block;
371
- border-radius: 6px;
372
388
  padding: 6px;
389
+ border-radius: 6px;
373
390
  color: var(--colorAccentAlt);
374
391
  text-decoration: none;
375
392
 
package/src/Dashboard.js CHANGED
@@ -4,7 +4,6 @@ import { DEFAULT_500_COMMENT } from '/ApiConstants.js'
4
4
 
5
5
 
6
6
  const Strings = {
7
- allow_cors: 'Allow CORS',
8
7
  bulk_select_by_comment: 'Bulk Select by Comment',
9
8
  bulk_select_by_comment_disabled_title: 'No mock files have comments, which are anything within parentheses on the filename.',
10
9
  click_link_to_preview: 'Click a link to preview it',
@@ -18,19 +17,22 @@ const Strings = {
18
17
  mock: 'Mock',
19
18
  no_mocks_found: 'No mocks found',
20
19
  reset: 'Reset',
20
+ save_proxied: 'Save Mocks',
21
21
  select_one: 'Select One',
22
22
  static: 'Static'
23
23
  }
24
24
 
25
25
  const CSS = {
26
- ResetButton: 'ResetButton',
27
- CorsCheckbox: 'CorsCheckbox',
28
26
  DelayToggler: 'DelayToggler',
27
+ FallbackBackend: 'FallbackBackend',
28
+ Field: 'Field',
29
29
  InternalServerErrorToggler: 'InternalServerErrorToggler',
30
30
  MockSelector: 'MockSelector',
31
31
  PayloadViewer: 'PayloadViewer',
32
32
  PreviewLink: 'PreviewLink',
33
33
  ProgressBar: 'ProgressBar',
34
+ ResetButton: 'ResetButton',
35
+ SaveProxiedCheckbox: 'SaveProxiedCheckbox',
34
36
  StaticFilesList: 'StaticFilesList',
35
37
 
36
38
  bold: 'bold',
@@ -49,7 +51,7 @@ function init() {
49
51
  mockaton.listMocks(),
50
52
  mockaton.listCookies(),
51
53
  mockaton.listComments(),
52
- mockaton.getCorsAllowed(),
54
+ mockaton.getCollectProxied(),
53
55
  mockaton.getProxyFallback(),
54
56
  mockaton.listStaticFiles()
55
57
  ].map(api => api.then(response => response.ok && response.json())))
@@ -63,7 +65,7 @@ function App(apiResponses) {
63
65
  document.body.appendChild(DevPanel(apiResponses))
64
66
  }
65
67
 
66
- function DevPanel([brokersByMethod, cookies, comments, corsAllowed, fallbackAddress, staticFiles]) {
68
+ function DevPanel([brokersByMethod, cookies, comments, collectProxied, fallbackAddress, staticFiles]) {
67
69
  const isEmpty = Object.keys(brokersByMethod).length === 0
68
70
  return (
69
71
  r('div', null,
@@ -71,8 +73,7 @@ function DevPanel([brokersByMethod, cookies, comments, corsAllowed, fallbackAddr
71
73
  r('img', { src: '/mockaton-logo.svg', width: 160, alt: Strings.title }),
72
74
  r(CookieSelector, { list: cookies }),
73
75
  r(BulkSelector, { comments }),
74
- r(ProxyFallbackField, { fallbackAddress }),
75
- r(CorsCheckbox, { corsAllowed }),
76
+ r(ProxyFallbackField, { fallbackAddress, collectProxied }),
76
77
  r(ResetButton)),
77
78
  isEmpty
78
79
  ? r('main', null, Strings.no_mocks_found)
@@ -94,7 +95,7 @@ function CookieSelector({ list }) {
94
95
  }
95
96
  const disabled = list.length <= 1
96
97
  return (
97
- r('label', null,
98
+ r('label', { className: CSS.Field },
98
99
  r('span', null, Strings.cookie),
99
100
  r('select', {
100
101
  autocomplete: 'off',
@@ -118,7 +119,7 @@ function BulkSelector({ comments }) {
118
119
  ? []
119
120
  : [Strings.select_one].concat(comments)
120
121
  return (
121
- r('label', null,
122
+ r('label', { className: CSS.Field },
122
123
  r('span', null, Strings.bulk_select_by_comment),
123
124
  r('select', {
124
125
  'data-qaid': 'BulkSelector',
@@ -132,41 +133,51 @@ function BulkSelector({ comments }) {
132
133
  }
133
134
 
134
135
 
135
- function ProxyFallbackField({ fallbackAddress = '' }) {
136
+ function ProxyFallbackField({ fallbackAddress = '', collectProxied }) {
137
+ const refSaveProxiedCheckbox = useRef()
136
138
  function onChange(event) {
137
139
  const input = event.currentTarget
140
+ refSaveProxiedCheckbox.current.disabled = !input.validity.valid || !input.value.trim()
138
141
  if (!input.validity.valid)
139
142
  input.reportValidity()
140
143
  else
141
- mockaton.setProxyFallback(input.value)
144
+ mockaton.setProxyFallback(input.value.trim())
142
145
  .catch(onError)
143
146
  }
144
147
  return (
145
- r('label', null,
146
- r('span', null, Strings.fallback_server),
147
- r('input', {
148
- type: 'url',
149
- autocomplete: 'none',
150
- placeholder: Strings.fallback_server_placeholder,
151
- value: fallbackAddress,
152
- onChange
148
+ r('div', { className: CSS.Field + ' ' + CSS.FallbackBackend },
149
+ r('label', null,
150
+ r('span', null, Strings.fallback_server),
151
+ r('input', {
152
+ type: 'url',
153
+ autocomplete: 'none',
154
+ placeholder: Strings.fallback_server_placeholder,
155
+ value: fallbackAddress,
156
+ onChange
157
+ })),
158
+ r(SaveProxiedCheckbox, {
159
+ collectProxied,
160
+ disabled: !fallbackAddress,
161
+ ref: refSaveProxiedCheckbox
153
162
  })))
154
163
  }
155
164
 
156
165
 
157
- function CorsCheckbox({ corsAllowed }) {
166
+ function SaveProxiedCheckbox({ ref, disabled, collectProxied }) {
158
167
  function onChange(event) {
159
- mockaton.setCorsAllowed(event.currentTarget.checked)
168
+ mockaton.setCollectProxied(event.currentTarget.checked)
160
169
  .catch(onError)
161
170
  }
162
171
  return (
163
- r('label', { className: CSS.CorsCheckbox },
172
+ r('label', { className: CSS.SaveProxiedCheckbox },
164
173
  r('input', {
174
+ ref,
165
175
  type: 'checkbox',
166
- checked: corsAllowed,
176
+ disabled,
177
+ checked: collectProxied,
167
178
  onChange
168
179
  }),
169
- Strings.allow_cors))
180
+ r('span', null, Strings.save_proxied)))
170
181
  }
171
182
 
172
183