@forsakringskassan/devindex-menu 1.0.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 ADDED
@@ -0,0 +1,162 @@
1
+ # @forsakringskassan/devindex-menu
2
+
3
+ > npm install --save-dev @forsakringskassan/devindex-menu
4
+
5
+ Menu for development mode that can be used with advantage together with [fapimock-express](https://www.npmjs.com/package/@forsakringskassan/apimock-express).
6
+
7
+ ## Usage
8
+
9
+ The menu can be used in several types of applications. If you're using vue-cli, it can be used as follows:
10
+
11
+ ```js
12
+ require("@forsakringskassan/devindex-menu")([
13
+ {
14
+ key: "slow-load",
15
+ title: "Delay",
16
+ reloadOnChange: true,
17
+ execOnChange: "aGlobalMethod",
18
+ options: [
19
+ { title: "Normal loading", value: false },
20
+ { title: "Slow loading", value: true },
21
+ ],
22
+ },
23
+ ]);
24
+ ```
25
+
26
+ When execOnChange is set to a value, the global function with this name will be called on onChange of the dropdown list.
27
+
28
+ ## API
29
+
30
+ ```js
31
+ [
32
+ {
33
+ key: String,
34
+ title: String,
35
+ type: String (optional, default, "select")
36
+ description: String (optional),
37
+ reloadOnChange: Boolean (optional, default: true),
38
+ sessionStorage: Boolean (optional, default: false),
39
+ execOnChange: String (optional),
40
+ options: [], Array (see types below)
41
+ },
42
+ ]
43
+ ```
44
+
45
+ ## Use mocks directly
46
+
47
+ It's also possible to use mocks for `@forsakringskassan/apimock-express` directly.
48
+ In the types `MockMatcher` and `Mock` from `apimock-express` there is support for metadata that is read by the devindex-menu.
49
+
50
+ When defining the mock, add `meta.title` and `responses[i].response.label`.
51
+ These correspond to the dropdown label and the name of each option respectively.
52
+
53
+ ```diff
54
+ export default defineMock({
55
+ + meta: {
56
+ + title: "GET /dog",
57
+ + },
58
+ responses: [
59
+ createResponseByCookie(
60
+ cookie,
61
+ "border-collie-200",
62
+ {
63
+ + label: "Border collie (200)",
64
+ body: dogBorderCollie,
65
+ },
66
+ ),
67
+ ],
68
+ defaultResponse: {
69
+ + label: "Default – dachshund (200)",
70
+ status: 200,
71
+ body: dogDachshund,
72
+ },
73
+ );
74
+ ```
75
+
76
+ Inside the application, the mock is then sent directly to `devindexMenu`.
77
+
78
+ ```diff
79
+ import devindexMenu from "@forsakringskassan/devindex-menu";
80
+ +import getDogMock from "dog-api/dist/api/private/v1/dog_get.js";
81
+
82
+ devindexMenu([
83
+ {
84
+ key: "api-post-leash",
85
+ title: "POST /leash",
86
+ options: [{
87
+ title: "Tracking leash (200)",
88
+ value: "tracking-leash-200"
89
+ }],
90
+ },
91
+ + getDogMock,
92
+ ]);
93
+ ```
94
+
95
+ ### Type Definitions
96
+
97
+ #### select (default)
98
+
99
+ ```json
100
+ { title: String, value: String },
101
+ ```
102
+
103
+ #### Links
104
+
105
+ ```json
106
+ { title: String, href: String },
107
+
108
+ ```
109
+
110
+ #### SessionStorage - Pre-filling
111
+
112
+ If you specify `sessionStorage` as `true`, the value will be saved under `key` in `sessionStorage`.
113
+
114
+ In the example below, you'll get a `select` with the title `Pre-filling`. If you make a selection, `sessionStorage` will get a value `fk-dog-model`.
115
+
116
+ ```js
117
+ import coco from "./tests/mock/prefilled/coco.json";
118
+ import fido from "./tests/mock/prefilled/fido.json";
119
+
120
+ require("@forsakringskassan/devindex-menu")([
121
+ {
122
+ key: "fk-dog-model",
123
+ title: "Pre-filling",
124
+ sessionStorage: true,
125
+ options: [
126
+ { title: "None", value: "" },
127
+ { title: "Coco", value: coco },
128
+ { title: "Fido", value: fido },
129
+ ],
130
+ },
131
+ ]);
132
+ ```
133
+
134
+ ## Examples
135
+
136
+ ```js
137
+ require("@forsakringskassan/devindex-menu")([
138
+ {
139
+ key: "disable-translate",
140
+ title: "Text",
141
+ options: [
142
+ { title: "Translated text", value: "default" },
143
+ { title: "Show text keys", value: "true" },
144
+ ],
145
+ },
146
+ {
147
+ type: "links",
148
+ title: "Links",
149
+ options: [
150
+ {
151
+ title: "Applicant reviews application for additional cost",
152
+ href: "/#/review/8",
153
+ },
154
+ ],
155
+ },
156
+ ]);
157
+ ```
158
+
159
+ ## Development
160
+
161
+ To compile styling:
162
+ `npm run build`
@@ -0,0 +1,7 @@
1
+ export declare class DevindexPageObject {
2
+ selector: string;
3
+ el: () => Cypress.Chainable<JQuery>;
4
+ constructor();
5
+ toggleMenu(): void;
6
+ valj(id: string, value: string): void;
7
+ }
@@ -0,0 +1,214 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/menu.js
21
+ var menu_exports = {};
22
+ __export(menu_exports, {
23
+ default: () => menu_default
24
+ });
25
+ module.exports = __toCommonJS(menu_exports);
26
+
27
+ // raw-loader:./client.js?raw
28
+ var client_default = '/**\n * @param {string} cookieName\n * @param {string} cookieValue\n * @param {number} exdays\n * @returns {void}\n */\nfunction setCookie(cookieName, cookieValue, exdays) {\n var d = new Date();\n d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000);\n var expires = "expires=".concat(d.toUTCString());\n document.cookie = "".concat(cookieName, "=").concat(cookieValue, ";").concat(expires, ";path=/");\n}\n\n/**\n * @param {string} cookieName\n * @returns {string | undefined}\n */\nfunction getCookie(cookieName) {\n var name = "".concat(cookieName, "=");\n var decodedCookie = decodeURIComponent(document.cookie);\n var ca = decodedCookie.split(";");\n for (var i = 0; i < ca.length; i++) {\n var c = ca[i];\n while (c.charAt(0) === " ") {\n c = c.substring(1);\n }\n if (c.indexOf(name) === 0) {\n return c.substring(name.length, c.length);\n }\n }\n return undefined;\n}\n(function () {\n /** @type {NodeListOf<HTMLSelectElement>} */\n var selections = document.querySelectorAll(".secret-menu select");\n for (var i = 0; i < selections.length; i++) {\n var select = selections[i];\n select.value = getCookie(select.name) ? getCookie(select.name) : "default";\n if (select.getAttribute("data-sessionStorage") === "true") {\n var cookieValue = getCookie(select.name);\n if (cookieValue) {\n sessionStorage.setItem(select.name, atob(cookieValue));\n }\n }\n select.onchange = function (event) {\n var element = event.target;\n setCookie(element.name, element.value, 30);\n if (element.getAttribute("data-exec-on-change")) {\n window[element.getAttribute("data-exec-on-change")]();\n }\n if (element.getAttribute("data-reload") === "true") {\n location.reload(true);\n }\n if (element.getAttribute("data-sessionStorage") === "true") {\n var sessionKey = element.id;\n if (element.value) {\n var value = atob(element.value);\n console.log("Laddar sessionstorage ".concat(sessionKey, " med \\n ").concat(value));\n sessionStorage.setItem(sessionKey, value);\n } else {\n console.log("T\\xF6mmer sessionstorage");\n sessionStorage.removeItem(sessionKey);\n }\n location.reload(true);\n }\n };\n }\n var inputFields = document.querySelectorAll(".secret-menu input");\n for (var _i = 0; _i < inputFields.length; _i++) {\n var input = inputFields[_i];\n input.value = getCookie(input.name) ? getCookie(input.name) : "";\n input.oninput = function (event) {\n var element = event.target;\n setCookie(element.name, element.value, 30);\n };\n }\n\n /* Forcerar att sidan laddas om, \xE4ven n\xE4r l\xE4nken \xE4r av typen: /#/granska/8 */\n /** @type {NodeListOf<HTMLAnchorElement>} */\n var links = document.querySelectorAll(".secret-menu ul li a");\n for (var _i2 = 0; _i2 < links.length; _i2++) {\n var link = links[_i2];\n if (link.getAttribute("href").startsWith("/#")) {\n /**\n * @param {MouseEvent} event\n */\n link.onclick = function (event) {\n event.preventDefault();\n window.location.href = event.target.getAttribute("href");\n setTimeout(function () {\n console.log("Reload after click on hash-link.");\n location.reload();\n }, "500");\n };\n }\n }\n})();\nfunction toggleMenu() {\n var menu = document.querySelector(".secret-menu");\n menu.classList.toggle("open");\n}\nwindow.toggleMenu = toggleMenu;';
29
+
30
+ // src/style.scss
31
+ var style_default = `.secret-menu {
32
+ min-height: 100%;
33
+ background-color: #333;
34
+ top: 0;
35
+ left: 0;
36
+ bottom: 0;
37
+ width: 0;
38
+ z-index: 9999;
39
+ color: #efefef;
40
+ position: fixed;
41
+ }
42
+ .secret-menu .toggle {
43
+ border: 0;
44
+ position: fixed;
45
+ top: 20px;
46
+ left: 0px;
47
+ color: #fff;
48
+ background-color: #333;
49
+ border-radius: 0;
50
+ border-top-right-radius: 5px;
51
+ border-bottom-right-radius: 5px;
52
+ font-weight: bold;
53
+ z-index: 9999;
54
+ margin: 0;
55
+ padding: 10px;
56
+ box-shadow: none;
57
+ min-width: 40px;
58
+ }
59
+ .secret-menu .toggle span {
60
+ width: 20px;
61
+ height: 3px;
62
+ background-color: white;
63
+ margin: 3px 0;
64
+ display: block;
65
+ }
66
+ .secret-menu .menu {
67
+ width: 100%;
68
+ overflow: hidden;
69
+ }
70
+ .secret-menu.open {
71
+ width: 300px;
72
+ overflow: auto;
73
+ }
74
+ .secret-menu.open .toggle {
75
+ left: 300px;
76
+ }
77
+ .secret-menu.open .menu {
78
+ padding: 20px;
79
+ box-sizing: border-box;
80
+ }
81
+ .secret-menu label {
82
+ margin-bottom: 0.25rem;
83
+ }
84
+ .secret-menu label,
85
+ .secret-menu a {
86
+ color: #efefef;
87
+ display: block;
88
+ }
89
+ .secret-menu a:hover {
90
+ text-decoration: underline;
91
+ }
92
+ .secret-menu .sr-only {
93
+ position: absolute;
94
+ width: 1px;
95
+ height: 1px;
96
+ margin: -1px;
97
+ padding: 0;
98
+ overflow: hidden;
99
+ clip: rect(0, 0, 0, 0);
100
+ border: 0;
101
+ }
102
+ .secret-menu select {
103
+ color: #000;
104
+ margin-bottom: 1rem;
105
+ width: 100%;
106
+ height: 2.25rem;
107
+ font-size: 0.875rem;
108
+ }
109
+ .secret-menu input {
110
+ color: #000;
111
+ margin-bottom: 1rem;
112
+ width: 100%;
113
+ }`;
114
+
115
+ // src/menu.js
116
+ function generateOptionMarkupForSelect(setting) {
117
+ const reload = setting.reloadOnChange !== void 0 ? setting.reloadOnChange : true;
118
+ const description = setting.description ? `<p>${setting.description}</p>` : "";
119
+ const execOnChange = setting.execOnChange ? ` data-exec-on-change="${setting.execOnChange}"` : "";
120
+ let markup = `<label for="${setting.key}" class="label">${setting.title}</label>${description}<select id="${setting.key}" data-sessionStorage="${setting.sessionStorage}" data-reload="${reload}" ${execOnChange} name="${setting.key}" tabindex="-1">`;
121
+ setting.options.forEach((option) => {
122
+ const stateJson = typeof option.value === "string" ? option.value : JSON.stringify(option.value, null, 2);
123
+ const optionValue = setting.sessionStorage ? btoa(stateJson) : option.value;
124
+ markup += `<option value="${optionValue}">${option.title}</option>`;
125
+ });
126
+ markup = `${markup}</select>`;
127
+ return markup;
128
+ }
129
+ function generateOptionMarkupForLink(setting) {
130
+ const description = setting.description ? `<p>${setting.description}</p>` : "";
131
+ let markup = `${setting.title} ${description}<ul>`;
132
+ setting.options.forEach((option) => {
133
+ markup += `<li><a href="${option.href}">${option.title}</a></li>`;
134
+ });
135
+ markup = `${markup}</ul>`;
136
+ return markup;
137
+ }
138
+ function generateOptionMarkupForTextInput(setting) {
139
+ const description = setting.description ? `<p>${setting.description}</p>` : "";
140
+ return `${setting.title} ${description} <br /> <input name="${setting.key}" type="text"></input>`;
141
+ }
142
+ function generateOptionMarkup(setting) {
143
+ switch (setting.type) {
144
+ case "select":
145
+ return generateOptionMarkupForSelect(setting);
146
+ case "links":
147
+ return generateOptionMarkupForLink(setting);
148
+ case "text":
149
+ return generateOptionMarkupForTextInput(setting);
150
+ }
151
+ return "";
152
+ }
153
+ function isMock(userSettingsOrMock) {
154
+ return "responses" in userSettingsOrMock || "defaultResponse" in userSettingsOrMock;
155
+ }
156
+ function getFirstCookie(matcher) {
157
+ const entries = Object.entries(matcher.request.cookies);
158
+ const [key, value] = entries[0];
159
+ return { key, value };
160
+ }
161
+ function entryFromMock(mock) {
162
+ const { key } = getFirstCookie(mock.responses[0]);
163
+ const title = mock.meta.title ?? key;
164
+ const defaultEntry = {
165
+ title: mock.defaultResponse?.label ?? "Default",
166
+ value: "default"
167
+ };
168
+ return {
169
+ type: "select",
170
+ key,
171
+ title,
172
+ options: [
173
+ defaultEntry,
174
+ ...mock.responses.map((entry) => {
175
+ const { value } = getFirstCookie(entry);
176
+ return {
177
+ title: entry.response.label ?? value,
178
+ value
179
+ };
180
+ })
181
+ ]
182
+ };
183
+ }
184
+ var defaultSetting = {
185
+ type: "select"
186
+ };
187
+ var menu_default = (userSettingsAndMocks) => {
188
+ let settingsMarkup = "";
189
+ userSettingsAndMocks.map(
190
+ (userSettingOrMock) => isMock(userSettingOrMock) ? entryFromMock(userSettingOrMock) : userSettingOrMock
191
+ ).forEach((userSetting) => {
192
+ const setting = { ...defaultSetting, ...userSetting };
193
+ settingsMarkup = settingsMarkup + generateOptionMarkup(setting);
194
+ });
195
+ document.head.insertAdjacentHTML("beforeend", `<style>${style_default}</style>`);
196
+ document.body.insertAdjacentHTML(
197
+ "beforeend",
198
+ `
199
+ <div class="secret-menu" aria-hidden="true">
200
+ <button type="button" class="toggle" onclick="toggleMenu()">
201
+ <span></span>
202
+ <span></span>
203
+ <span></span>
204
+ <span class="sr-only">Hemlig meny</span>
205
+ </button>
206
+ <div class="menu">
207
+ ${settingsMarkup}
208
+ </div>
209
+ </div>`
210
+ );
211
+ const script = document.createElement("script");
212
+ script.innerText = client_default;
213
+ document.body.appendChild(script);
214
+ };
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/pageobjects/pageobjects.ts
21
+ var pageobjects_exports = {};
22
+ __export(pageobjects_exports, {
23
+ DevindexPageObject: () => DevindexPageObject
24
+ });
25
+ module.exports = __toCommonJS(pageobjects_exports);
26
+
27
+ // src/pageobjects/Devindex.pageobject.ts
28
+ var DevindexPageObject = class {
29
+ constructor() {
30
+ this.selector = ".secret-menu";
31
+ this.el = () => cy.get(this.selector);
32
+ }
33
+ toggleMenu() {
34
+ cy.get(".secret-menu > button").click();
35
+ }
36
+ valj(id, value) {
37
+ cy.get(`#${id}`).select(value);
38
+ }
39
+ };
@@ -0,0 +1,191 @@
1
+ // raw-loader:./client.js?raw
2
+ var client_default = '/**\n * @param {string} cookieName\n * @param {string} cookieValue\n * @param {number} exdays\n * @returns {void}\n */\nfunction setCookie(cookieName, cookieValue, exdays) {\n var d = new Date();\n d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000);\n var expires = "expires=".concat(d.toUTCString());\n document.cookie = "".concat(cookieName, "=").concat(cookieValue, ";").concat(expires, ";path=/");\n}\n\n/**\n * @param {string} cookieName\n * @returns {string | undefined}\n */\nfunction getCookie(cookieName) {\n var name = "".concat(cookieName, "=");\n var decodedCookie = decodeURIComponent(document.cookie);\n var ca = decodedCookie.split(";");\n for (var i = 0; i < ca.length; i++) {\n var c = ca[i];\n while (c.charAt(0) === " ") {\n c = c.substring(1);\n }\n if (c.indexOf(name) === 0) {\n return c.substring(name.length, c.length);\n }\n }\n return undefined;\n}\n(function () {\n /** @type {NodeListOf<HTMLSelectElement>} */\n var selections = document.querySelectorAll(".secret-menu select");\n for (var i = 0; i < selections.length; i++) {\n var select = selections[i];\n select.value = getCookie(select.name) ? getCookie(select.name) : "default";\n if (select.getAttribute("data-sessionStorage") === "true") {\n var cookieValue = getCookie(select.name);\n if (cookieValue) {\n sessionStorage.setItem(select.name, atob(cookieValue));\n }\n }\n select.onchange = function (event) {\n var element = event.target;\n setCookie(element.name, element.value, 30);\n if (element.getAttribute("data-exec-on-change")) {\n window[element.getAttribute("data-exec-on-change")]();\n }\n if (element.getAttribute("data-reload") === "true") {\n location.reload(true);\n }\n if (element.getAttribute("data-sessionStorage") === "true") {\n var sessionKey = element.id;\n if (element.value) {\n var value = atob(element.value);\n console.log("Laddar sessionstorage ".concat(sessionKey, " med \\n ").concat(value));\n sessionStorage.setItem(sessionKey, value);\n } else {\n console.log("T\\xF6mmer sessionstorage");\n sessionStorage.removeItem(sessionKey);\n }\n location.reload(true);\n }\n };\n }\n var inputFields = document.querySelectorAll(".secret-menu input");\n for (var _i = 0; _i < inputFields.length; _i++) {\n var input = inputFields[_i];\n input.value = getCookie(input.name) ? getCookie(input.name) : "";\n input.oninput = function (event) {\n var element = event.target;\n setCookie(element.name, element.value, 30);\n };\n }\n\n /* Forcerar att sidan laddas om, \xE4ven n\xE4r l\xE4nken \xE4r av typen: /#/granska/8 */\n /** @type {NodeListOf<HTMLAnchorElement>} */\n var links = document.querySelectorAll(".secret-menu ul li a");\n for (var _i2 = 0; _i2 < links.length; _i2++) {\n var link = links[_i2];\n if (link.getAttribute("href").startsWith("/#")) {\n /**\n * @param {MouseEvent} event\n */\n link.onclick = function (event) {\n event.preventDefault();\n window.location.href = event.target.getAttribute("href");\n setTimeout(function () {\n console.log("Reload after click on hash-link.");\n location.reload();\n }, "500");\n };\n }\n }\n})();\nfunction toggleMenu() {\n var menu = document.querySelector(".secret-menu");\n menu.classList.toggle("open");\n}\nwindow.toggleMenu = toggleMenu;';
3
+
4
+ // src/style.scss
5
+ var style_default = `.secret-menu {
6
+ min-height: 100%;
7
+ background-color: #333;
8
+ top: 0;
9
+ left: 0;
10
+ bottom: 0;
11
+ width: 0;
12
+ z-index: 9999;
13
+ color: #efefef;
14
+ position: fixed;
15
+ }
16
+ .secret-menu .toggle {
17
+ border: 0;
18
+ position: fixed;
19
+ top: 20px;
20
+ left: 0px;
21
+ color: #fff;
22
+ background-color: #333;
23
+ border-radius: 0;
24
+ border-top-right-radius: 5px;
25
+ border-bottom-right-radius: 5px;
26
+ font-weight: bold;
27
+ z-index: 9999;
28
+ margin: 0;
29
+ padding: 10px;
30
+ box-shadow: none;
31
+ min-width: 40px;
32
+ }
33
+ .secret-menu .toggle span {
34
+ width: 20px;
35
+ height: 3px;
36
+ background-color: white;
37
+ margin: 3px 0;
38
+ display: block;
39
+ }
40
+ .secret-menu .menu {
41
+ width: 100%;
42
+ overflow: hidden;
43
+ }
44
+ .secret-menu.open {
45
+ width: 300px;
46
+ overflow: auto;
47
+ }
48
+ .secret-menu.open .toggle {
49
+ left: 300px;
50
+ }
51
+ .secret-menu.open .menu {
52
+ padding: 20px;
53
+ box-sizing: border-box;
54
+ }
55
+ .secret-menu label {
56
+ margin-bottom: 0.25rem;
57
+ }
58
+ .secret-menu label,
59
+ .secret-menu a {
60
+ color: #efefef;
61
+ display: block;
62
+ }
63
+ .secret-menu a:hover {
64
+ text-decoration: underline;
65
+ }
66
+ .secret-menu .sr-only {
67
+ position: absolute;
68
+ width: 1px;
69
+ height: 1px;
70
+ margin: -1px;
71
+ padding: 0;
72
+ overflow: hidden;
73
+ clip: rect(0, 0, 0, 0);
74
+ border: 0;
75
+ }
76
+ .secret-menu select {
77
+ color: #000;
78
+ margin-bottom: 1rem;
79
+ width: 100%;
80
+ height: 2.25rem;
81
+ font-size: 0.875rem;
82
+ }
83
+ .secret-menu input {
84
+ color: #000;
85
+ margin-bottom: 1rem;
86
+ width: 100%;
87
+ }`;
88
+
89
+ // src/menu.js
90
+ function generateOptionMarkupForSelect(setting) {
91
+ const reload = setting.reloadOnChange !== void 0 ? setting.reloadOnChange : true;
92
+ const description = setting.description ? `<p>${setting.description}</p>` : "";
93
+ const execOnChange = setting.execOnChange ? ` data-exec-on-change="${setting.execOnChange}"` : "";
94
+ let markup = `<label for="${setting.key}" class="label">${setting.title}</label>${description}<select id="${setting.key}" data-sessionStorage="${setting.sessionStorage}" data-reload="${reload}" ${execOnChange} name="${setting.key}" tabindex="-1">`;
95
+ setting.options.forEach((option) => {
96
+ const stateJson = typeof option.value === "string" ? option.value : JSON.stringify(option.value, null, 2);
97
+ const optionValue = setting.sessionStorage ? btoa(stateJson) : option.value;
98
+ markup += `<option value="${optionValue}">${option.title}</option>`;
99
+ });
100
+ markup = `${markup}</select>`;
101
+ return markup;
102
+ }
103
+ function generateOptionMarkupForLink(setting) {
104
+ const description = setting.description ? `<p>${setting.description}</p>` : "";
105
+ let markup = `${setting.title} ${description}<ul>`;
106
+ setting.options.forEach((option) => {
107
+ markup += `<li><a href="${option.href}">${option.title}</a></li>`;
108
+ });
109
+ markup = `${markup}</ul>`;
110
+ return markup;
111
+ }
112
+ function generateOptionMarkupForTextInput(setting) {
113
+ const description = setting.description ? `<p>${setting.description}</p>` : "";
114
+ return `${setting.title} ${description} <br /> <input name="${setting.key}" type="text"></input>`;
115
+ }
116
+ function generateOptionMarkup(setting) {
117
+ switch (setting.type) {
118
+ case "select":
119
+ return generateOptionMarkupForSelect(setting);
120
+ case "links":
121
+ return generateOptionMarkupForLink(setting);
122
+ case "text":
123
+ return generateOptionMarkupForTextInput(setting);
124
+ }
125
+ return "";
126
+ }
127
+ function isMock(userSettingsOrMock) {
128
+ return "responses" in userSettingsOrMock || "defaultResponse" in userSettingsOrMock;
129
+ }
130
+ function getFirstCookie(matcher) {
131
+ const entries = Object.entries(matcher.request.cookies);
132
+ const [key, value] = entries[0];
133
+ return { key, value };
134
+ }
135
+ function entryFromMock(mock) {
136
+ const { key } = getFirstCookie(mock.responses[0]);
137
+ const title = mock.meta.title ?? key;
138
+ const defaultEntry = {
139
+ title: mock.defaultResponse?.label ?? "Default",
140
+ value: "default"
141
+ };
142
+ return {
143
+ type: "select",
144
+ key,
145
+ title,
146
+ options: [
147
+ defaultEntry,
148
+ ...mock.responses.map((entry) => {
149
+ const { value } = getFirstCookie(entry);
150
+ return {
151
+ title: entry.response.label ?? value,
152
+ value
153
+ };
154
+ })
155
+ ]
156
+ };
157
+ }
158
+ var defaultSetting = {
159
+ type: "select"
160
+ };
161
+ var menu_default = (userSettingsAndMocks) => {
162
+ let settingsMarkup = "";
163
+ userSettingsAndMocks.map(
164
+ (userSettingOrMock) => isMock(userSettingOrMock) ? entryFromMock(userSettingOrMock) : userSettingOrMock
165
+ ).forEach((userSetting) => {
166
+ const setting = { ...defaultSetting, ...userSetting };
167
+ settingsMarkup = settingsMarkup + generateOptionMarkup(setting);
168
+ });
169
+ document.head.insertAdjacentHTML("beforeend", `<style>${style_default}</style>`);
170
+ document.body.insertAdjacentHTML(
171
+ "beforeend",
172
+ `
173
+ <div class="secret-menu" aria-hidden="true">
174
+ <button type="button" class="toggle" onclick="toggleMenu()">
175
+ <span></span>
176
+ <span></span>
177
+ <span></span>
178
+ <span class="sr-only">Hemlig meny</span>
179
+ </button>
180
+ <div class="menu">
181
+ ${settingsMarkup}
182
+ </div>
183
+ </div>`
184
+ );
185
+ const script = document.createElement("script");
186
+ script.innerText = client_default;
187
+ document.body.appendChild(script);
188
+ };
189
+ export {
190
+ menu_default as default
191
+ };
@@ -0,0 +1,16 @@
1
+ // src/pageobjects/Devindex.pageobject.ts
2
+ var DevindexPageObject = class {
3
+ constructor() {
4
+ this.selector = ".secret-menu";
5
+ this.el = () => cy.get(this.selector);
6
+ }
7
+ toggleMenu() {
8
+ cy.get(".secret-menu > button").click();
9
+ }
10
+ valj(id, value) {
11
+ cy.get(`#${id}`).select(value);
12
+ }
13
+ };
14
+ export {
15
+ DevindexPageObject
16
+ };
@@ -0,0 +1 @@
1
+ export * from "./Devindex.pageobject";
package/menu.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ import { type Mock } from "@forsakringskassan/apimock-express";
2
+
3
+ export interface SelectOption {
4
+ title: string;
5
+ value: unknown;
6
+ }
7
+
8
+ export interface SelectSettings {
9
+ type?: "select";
10
+ key: string;
11
+ title: string;
12
+ reloadOnChange?: boolean;
13
+ execOnChange?: string;
14
+ description?: string;
15
+ sessionStorage?: boolean;
16
+ options: SelectOption[];
17
+ }
18
+
19
+ export interface LinkOption {
20
+ title: string;
21
+ href: string;
22
+ }
23
+
24
+ export interface LinkSettings {
25
+ type: "links";
26
+ title: string;
27
+ description?: string;
28
+ options: LinkOption[];
29
+ }
30
+
31
+ export type Settings = SelectSettings | LinkSettings;
32
+
33
+ export default function devindexMenu(
34
+ userSettingsAndMocks: Array<Settings | Mock>,
35
+ ): void;
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@forsakringskassan/devindex-menu",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "license": "ISC",
6
+ "author": "FK",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./menu.d.ts",
10
+ "require": "./dist/cjs/menu.js",
11
+ "import": "./dist/esm/menu.js"
12
+ },
13
+ "./pageobjects": {
14
+ "types": "./pageobjects.d.ts",
15
+ "require": "./dist/cjs/pageobjects/pageobjects.js",
16
+ "import": "./dist/esm/pageobjects/pageobjects.js"
17
+ }
18
+ },
19
+ "main": "dist/cjs/menu.js",
20
+ "module": "dist/esm/menu.js",
21
+ "types": "./menu.d.ts",
22
+ "files": [
23
+ "dist",
24
+ "pageobjects",
25
+ "./pageobjects.d.ts",
26
+ "./pageobjects.js",
27
+ "./menu.d.ts"
28
+ ],
29
+ "scripts": {
30
+ "prebuild": "rimraf dist && tsc",
31
+ "build": "node generate.mjs",
32
+ "eslint": "eslint --cache .",
33
+ "prettier:check": "prettier --check .",
34
+ "prettier:write": "prettier --write .",
35
+ "test": "npm run prettier:check && npm run eslint"
36
+ },
37
+ "commitlint": {
38
+ "extends": "@forsakringskassan/commitlint-config/no-jira"
39
+ },
40
+ "prettier": "@forsakringskassan/prettier-config",
41
+ "release": {
42
+ "extends": "@forsakringskassan/semantic-release-config"
43
+ },
44
+ "devDependencies": {
45
+ "@babel/core": "7.28.4",
46
+ "@babel/preset-env": "7.28.3",
47
+ "@forsakringskassan/apimock-express": "2.9.0",
48
+ "@forsakringskassan/commitlint-config": "3.1.2",
49
+ "@forsakringskassan/eslint-config": "13.1.0",
50
+ "@forsakringskassan/eslint-config-cli": "13.1.0",
51
+ "@forsakringskassan/eslint-config-cypress": "13.1.0",
52
+ "@forsakringskassan/eslint-config-jest": "13.1.0",
53
+ "@forsakringskassan/eslint-config-typescript": "13.1.0",
54
+ "@forsakringskassan/eslint-config-typescript-typeinfo": "13.1.0",
55
+ "@forsakringskassan/prettier-config": "3.1.7",
56
+ "@tsconfig/node16": "16.1.5",
57
+ "@types/node": "16.18.126",
58
+ "cypress": "15.4.0",
59
+ "esbuild": "0.25.10",
60
+ "esbuild-sass-plugin": "3.3.1",
61
+ "rimraf": "6.0.1",
62
+ "sass": "1.93.2",
63
+ "typescript": "5.9.3"
64
+ },
65
+ "engines": {
66
+ "node": ">= 16"
67
+ }
68
+ }
@@ -0,0 +1 @@
1
+ export * from "./dist/pageobjects";