@forsakringskassan/vue-lib-template 1.0.4 → 1.1.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/files/README.md +6 -5
- package/files/_htmlvalidateignore +2 -0
- package/files/cypress.config.ts +1 -0
- package/files/docs/build.mts +14 -0
- package/files/docs/index.md +2 -0
- package/files/docs/kattinformation/index.md +28 -0
- package/files/docs/package.json +5 -2
- package/files/docs/src/bundle-mocks.mjs +22 -0
- package/files/docs/src/global.d.ts +7 -0
- package/files/docs/src/main.js +17 -0
- package/files/docs/src/main.scss +22 -0
- package/files/docs/src/setup.ts +6 -1
- package/files/docs/tsconfig.json +1 -0
- package/files/etc/lib.api.md +1 -1
- package/files/etc/selectors.api.md +13 -0
- package/files/package.json +45 -29
- package/files/renovate.json +1 -0
- package/files/src/CatInfoEdit.vue +57 -0
- package/files/src/CatInfoLogic.spec.ts +118 -0
- package/files/src/CatInfoShow.vue +27 -0
- package/files/src/FcCatInfoComponent.cy.ts +74 -0
- package/files/src/FcCatInfoComponent.vue +81 -0
- package/files/src/FcCatInfoComponentLiveExample.vue +42 -0
- package/files/src/cat-api-mock.spec.ts +27 -0
- package/files/src/cat-api.mock.mts +26 -0
- package/files/src/cat-api.spec.ts +65 -0
- package/files/src/cat-api.ts +15 -0
- package/files/src/cat-data.ts +40 -0
- package/files/src/cat-info-logic.ts +52 -0
- package/files/src/cat-types.ts +11 -0
- package/files/src/examples/CatInfoExample.vue +20 -0
- package/files/src/index.ts +3 -1
- package/files/src/local.ts +1 -1
- package/files/src/mocks.mts +6 -0
- package/files/src/selectors/FcCatInfoComponent.selectors.ts +74 -0
- package/files/src/selectors/index.ts +1 -1
- package/files/src/style.scss +1 -0
- package/files/src/vite-dev/app.vue +1 -1
- package/files/tsconfig.lib.json +7 -1
- package/files/vite.config.mts +4 -0
- package/index.js +1 -0
- package/package.json +25 -8
- package/files/docs/components/AwesomeComponent.md +0 -27
- package/files/docs/components/index.md +0 -5
- package/files/src/AwesomeComponent.cy.ts +0 -9
- package/files/src/AwesomeComponent.vue +0 -45
- package/files/src/AwesomeComponentLogic.spec.ts +0 -30
- package/files/src/awesome-component-logic.ts +0 -28
- package/files/src/examples/DummyExample.vue +0 -7
package/files/README.md
CHANGED
|
@@ -80,9 +80,10 @@ Dokumentationen genereras med [`@forsakringskassan/docs-generator`](https://fors
|
|
|
80
80
|
- [x] npm run build
|
|
81
81
|
- [x] npm run build:docs
|
|
82
82
|
- [x] npm run start:docs
|
|
83
|
-
- [
|
|
84
|
-
- [
|
|
85
|
-
- [
|
|
86
|
-
- [
|
|
87
|
-
- [
|
|
83
|
+
- [x] apimock
|
|
84
|
+
- [x] bättre exempelkomponent
|
|
85
|
+
- [x] bättre enhetstest
|
|
86
|
+
- [x] bättre komponenttest
|
|
87
|
+
- [x] live exempel
|
|
88
88
|
- [ ] skill för att skapa live exempel
|
|
89
|
+
- [ ] skript för att rensa demo-filer
|
package/files/cypress.config.ts
CHANGED
package/files/docs/build.mts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { copyFileSync } from "node:fs";
|
|
1
2
|
import path from "node:path";
|
|
2
3
|
import {
|
|
3
4
|
Generator,
|
|
@@ -17,10 +18,18 @@ const docs = new Generator(import.meta.url, {
|
|
|
17
18
|
],
|
|
18
19
|
});
|
|
19
20
|
|
|
21
|
+
docs.compileScript("main", "./src/main.js", {
|
|
22
|
+
appendTo: "body",
|
|
23
|
+
});
|
|
24
|
+
|
|
20
25
|
docs.compileStyle("main", "./src/main.scss", {
|
|
21
26
|
appendTo: "head",
|
|
22
27
|
});
|
|
23
28
|
|
|
29
|
+
docs.compileScript("mocks", "./src/bundle-mocks.mjs", {
|
|
30
|
+
appendTo: "head",
|
|
31
|
+
});
|
|
32
|
+
|
|
24
33
|
await docs.build([
|
|
25
34
|
{
|
|
26
35
|
include: ["**/*.md"],
|
|
@@ -32,3 +41,8 @@ await docs.build([
|
|
|
32
41
|
fileReader: vueFileReader,
|
|
33
42
|
},
|
|
34
43
|
]);
|
|
44
|
+
|
|
45
|
+
copyFileSync(
|
|
46
|
+
"../node_modules/msw/lib/mockServiceWorker.js",
|
|
47
|
+
"./public/mock-service-worker.js",
|
|
48
|
+
);
|
package/files/docs/index.md
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Kattinformation
|
|
3
|
+
status: Draft
|
|
4
|
+
layout: component
|
|
5
|
+
component: FcCatInfoComponent
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Komponenten kan visa kattdata i visningsläge eller i ett redigerbart läge.
|
|
9
|
+
Den hämtar kattdata från ett mockat backend.
|
|
10
|
+
|
|
11
|
+
```import live-example
|
|
12
|
+
FcCatInfoComponentLiveExample.vue
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Tänk på att
|
|
16
|
+
|
|
17
|
+
- Detta är en exempelkomponent.
|
|
18
|
+
- Den ska inte användas i produktion.
|
|
19
|
+
|
|
20
|
+
## Copy
|
|
21
|
+
|
|
22
|
+
- Använd tydlig och begriplig text.
|
|
23
|
+
|
|
24
|
+
## API
|
|
25
|
+
|
|
26
|
+
::: api
|
|
27
|
+
vue:FcCatInfoComponent
|
|
28
|
+
:::
|
package/files/docs/package.json
CHANGED
|
@@ -7,11 +7,14 @@
|
|
|
7
7
|
"start": "http-server public"
|
|
8
8
|
},
|
|
9
9
|
"devDependencies": {
|
|
10
|
-
"@fkui/
|
|
11
|
-
"@
|
|
10
|
+
"@fkui/icon-lib-default": "6.57.1",
|
|
11
|
+
"@fkui/vue": "6.57.1",
|
|
12
|
+
"@forsakringskassan/apimock-express": "4.0.0",
|
|
13
|
+
"@forsakringskassan/docs-generator": "3.6.4",
|
|
12
14
|
"@tsconfig/node24": "24.0.5",
|
|
13
15
|
"@tsconfig/recommended": "1.0.13",
|
|
14
16
|
"http-server": "14.1.1",
|
|
17
|
+
"msw": "2.15.0",
|
|
15
18
|
"vue": "3.5.42"
|
|
16
19
|
}
|
|
17
20
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { matchRequest } from "@forsakringskassan/apimock-express/browser";
|
|
2
|
+
import { http } from "msw";
|
|
3
|
+
import { setupWorker } from "msw/browser";
|
|
4
|
+
import mocks from "../../src/mocks.mts";
|
|
5
|
+
|
|
6
|
+
const handlers = [
|
|
7
|
+
http.all("/api/*", async (req) => {
|
|
8
|
+
return await matchRequest(mocks, req.request);
|
|
9
|
+
}),
|
|
10
|
+
];
|
|
11
|
+
const worker = setupWorker(...handlers);
|
|
12
|
+
// eslint-disable-next-line no-undef -- technical debt
|
|
13
|
+
const rootUrl = document.documentElement.dataset["rootUrl"];
|
|
14
|
+
const url = `${rootUrl}/mock-service-worker.js`;
|
|
15
|
+
|
|
16
|
+
// Used in setup.ts
|
|
17
|
+
// eslint-disable-next-line unicorn/no-global-object-property-assignment, no-undef -- technical debt
|
|
18
|
+
window.bundleMocks = worker.start({
|
|
19
|
+
serviceWorker: {
|
|
20
|
+
url,
|
|
21
|
+
},
|
|
22
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { config } from "@fkui/vue";
|
|
2
|
+
|
|
3
|
+
function importDefault(m) {
|
|
4
|
+
return m.default ?? m;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
async function importIcons() {
|
|
8
|
+
const icons = importDefault(await import(process.env.DOCS_ICON_LIB));
|
|
9
|
+
|
|
10
|
+
for (const entry of Object.values(icons)) {
|
|
11
|
+
entry.injectSpritesheet();
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
config.teleportTarget = document.querySelector("#teleport-target");
|
|
16
|
+
|
|
17
|
+
await importIcons();
|
package/files/docs/src/main.scss
CHANGED
|
@@ -1 +1,23 @@
|
|
|
1
1
|
@use "@forsakringskassan/docs-generator/style.css";
|
|
2
|
+
@use "@fkui/theme-default" as theme with (
|
|
3
|
+
$global: false
|
|
4
|
+
);
|
|
5
|
+
@use "@fkui/font-default" as font with (
|
|
6
|
+
$global: false
|
|
7
|
+
);
|
|
8
|
+
@use "@fkui/design";
|
|
9
|
+
@use "@fkui/design/lib/fonts.css";
|
|
10
|
+
@use "@forsakringskassan/docs-live-example";
|
|
11
|
+
|
|
12
|
+
@include font.font-face;
|
|
13
|
+
|
|
14
|
+
:root {
|
|
15
|
+
@include theme.auto;
|
|
16
|
+
@include font.font-family;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
html,
|
|
20
|
+
body {
|
|
21
|
+
margin: 0;
|
|
22
|
+
padding: 0;
|
|
23
|
+
}
|
package/files/docs/src/setup.ts
CHANGED
|
@@ -10,8 +10,13 @@ import {
|
|
|
10
10
|
} from "@fkui/vue";
|
|
11
11
|
import { type SetupOptions } from "@forsakringskassan/docs-generator";
|
|
12
12
|
|
|
13
|
-
export function setup(options: SetupOptions): void {
|
|
13
|
+
export async function setup(options: SetupOptions): Promise<void> {
|
|
14
14
|
const { rootComponent, selector } = options;
|
|
15
|
+
|
|
16
|
+
// Set in bundle-mocks.mjs, wait on mock service worker to be ready.
|
|
17
|
+
if (window.bundleMocks) {
|
|
18
|
+
await window.bundleMocks;
|
|
19
|
+
}
|
|
15
20
|
const app = createApp({
|
|
16
21
|
render() {
|
|
17
22
|
return h(FErrorHandlingApp, { defaultComponent: rootComponent });
|
package/files/docs/tsconfig.json
CHANGED
package/files/etc/lib.api.md
CHANGED
|
@@ -12,7 +12,7 @@ import { PublicProps } from 'vue';
|
|
|
12
12
|
// Warning: (ae-forgotten-export) The symbol "__VLS_export" needs to be exported by the entry point index.d.ts
|
|
13
13
|
//
|
|
14
14
|
// @public (undocumented)
|
|
15
|
-
export const
|
|
15
|
+
export const FcCatInfoComponent: typeof __VLS_export;
|
|
16
16
|
|
|
17
17
|
// (No @packageDocumentation comment for this package)
|
|
18
18
|
|
|
@@ -4,6 +4,19 @@
|
|
|
4
4
|
|
|
5
5
|
```ts
|
|
6
6
|
|
|
7
|
+
// @public
|
|
8
|
+
export function FcCatInfoComponentSelectors(selector?: string): Readonly<{
|
|
9
|
+
readonly selector: string;
|
|
10
|
+
loadingContainer(): string;
|
|
11
|
+
viewContainer(): string;
|
|
12
|
+
editContainer(): string;
|
|
13
|
+
nameInput(): string;
|
|
14
|
+
ageInput(): string;
|
|
15
|
+
breedInput(): string;
|
|
16
|
+
colorInput(): string;
|
|
17
|
+
favoriteFoodInput(): string;
|
|
18
|
+
}>;
|
|
19
|
+
|
|
7
20
|
// (No @packageDocumentation comment for this package)
|
|
8
21
|
|
|
9
22
|
```
|
package/files/package.json
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "${name}",
|
|
3
3
|
"version": "${version}",
|
|
4
|
+
"description": "Vue library template based on Cloneman",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"template",
|
|
7
|
+
"vue",
|
|
8
|
+
"cloneman",
|
|
9
|
+
"library"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://github.com/Forsakringskassan/vue-lib-template#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/Forsakringskassan/vue-lib-template/issues"
|
|
14
|
+
},
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"author": "Försäkringskassan",
|
|
4
17
|
"exports": {
|
|
5
18
|
".": {
|
|
6
19
|
"types": "./dist/types/index.d.ts",
|
|
@@ -66,51 +79,52 @@
|
|
|
66
79
|
"devDependencies": {
|
|
67
80
|
"@babel/core": "7.29.7",
|
|
68
81
|
"@babel/preset-env": "7.29.7",
|
|
69
|
-
"@fkui/design": "6.
|
|
70
|
-
"@fkui/font-default": "6.
|
|
71
|
-
"@fkui/icon-lib-default": "6.
|
|
72
|
-
"@fkui/logic": "6.
|
|
73
|
-
"@fkui/test-utils": "6.
|
|
74
|
-
"@fkui/theme-default": "6.
|
|
75
|
-
"@fkui/vue": "6.
|
|
82
|
+
"@fkui/design": "6.57.1",
|
|
83
|
+
"@fkui/font-default": "6.57.0",
|
|
84
|
+
"@fkui/icon-lib-default": "6.57.1",
|
|
85
|
+
"@fkui/logic": "6.57.1",
|
|
86
|
+
"@fkui/test-utils": "6.57.1",
|
|
87
|
+
"@fkui/theme-default": "6.57.1",
|
|
88
|
+
"@fkui/vue": "6.57.1",
|
|
89
|
+
"@forsakringskassan/apimock-express": "4.0.0",
|
|
76
90
|
"@forsakringskassan/commitlint-config": "4.2.8",
|
|
77
91
|
"@forsakringskassan/cypress-axe": "5.1.5",
|
|
78
|
-
"@forsakringskassan/cypress-visual-regression": "5.
|
|
79
|
-
"@forsakringskassan/docs-generator": "3.6.
|
|
80
|
-
"@forsakringskassan/docs-live-example": "3.0.
|
|
81
|
-
"@forsakringskassan/eslint-config": "15.9.
|
|
82
|
-
"@forsakringskassan/eslint-config-cli": "15.9.
|
|
83
|
-
"@forsakringskassan/eslint-config-cypress": "15.9.
|
|
84
|
-
"@forsakringskassan/eslint-config-jest": "15.9.
|
|
85
|
-
"@forsakringskassan/eslint-config-typescript": "15.9.
|
|
86
|
-
"@forsakringskassan/eslint-config-typescript-typeinfo": "15.9.
|
|
87
|
-
"@forsakringskassan/eslint-config-vitest": "15.9.
|
|
88
|
-
"@forsakringskassan/eslint-config-vue": "15.9.
|
|
92
|
+
"@forsakringskassan/cypress-visual-regression": "5.2.0",
|
|
93
|
+
"@forsakringskassan/docs-generator": "3.6.4",
|
|
94
|
+
"@forsakringskassan/docs-live-example": "3.0.2",
|
|
95
|
+
"@forsakringskassan/eslint-config": "15.9.5",
|
|
96
|
+
"@forsakringskassan/eslint-config-cli": "15.9.3",
|
|
97
|
+
"@forsakringskassan/eslint-config-cypress": "15.9.3",
|
|
98
|
+
"@forsakringskassan/eslint-config-jest": "15.9.2",
|
|
99
|
+
"@forsakringskassan/eslint-config-typescript": "15.9.2",
|
|
100
|
+
"@forsakringskassan/eslint-config-typescript-typeinfo": "15.9.2",
|
|
101
|
+
"@forsakringskassan/eslint-config-vitest": "15.9.4",
|
|
102
|
+
"@forsakringskassan/eslint-config-vue": "15.9.6",
|
|
89
103
|
"@forsakringskassan/prettier-config": "3.7.8",
|
|
90
|
-
"@forsakringskassan/stylelint-config": "3.4.
|
|
91
|
-
"@forsakringskassan/vite-lib-config": "5.
|
|
92
|
-
"@forsakringskassan/vitest-config-jsdom": "
|
|
93
|
-
"@forsakringskassan/vue-lib-template": "1.0
|
|
94
|
-
"@html-validate/release-scripts": "7.6.
|
|
104
|
+
"@forsakringskassan/stylelint-config": "3.4.6",
|
|
105
|
+
"@forsakringskassan/vite-lib-config": "5.11.0",
|
|
106
|
+
"@forsakringskassan/vitest-config-jsdom": "5.0.0",
|
|
107
|
+
"@forsakringskassan/vue-lib-template": "1.1.0",
|
|
108
|
+
"@html-validate/release-scripts": "7.6.11",
|
|
95
109
|
"@types/node": "24.13.3",
|
|
96
110
|
"@typescript/native": "npm:typescript@7.0.2",
|
|
97
111
|
"@vue/server-renderer": "3.5.42",
|
|
98
112
|
"@vue/test-utils": "2.5.0",
|
|
99
|
-
"cloneman": "1.
|
|
113
|
+
"cloneman": "1.23.1",
|
|
100
114
|
"core-js": "3.50.0",
|
|
101
|
-
"cypress": "
|
|
102
|
-
"cypress-html-validate": "9.
|
|
103
|
-
"html-validate": "11.
|
|
115
|
+
"cypress": "16.0.0",
|
|
116
|
+
"cypress-html-validate": "9.1.0",
|
|
117
|
+
"html-validate": "11.14.0",
|
|
104
118
|
"html-validate-markdown": "6.0.0",
|
|
105
119
|
"html-validate-vue": "9.3.1",
|
|
106
120
|
"mocha-junit-reporter": "2.2.1",
|
|
107
121
|
"mocha-multi-reporters": "1.5.1",
|
|
108
|
-
"npm-pkg-lint": "5.2.
|
|
122
|
+
"npm-pkg-lint": "5.2.5",
|
|
109
123
|
"npm-run-all2": "9.0.3",
|
|
110
124
|
"rimraf": "6.1.3",
|
|
111
125
|
"typescript": "npm:@typescript/typescript6@6.0.2",
|
|
112
126
|
"vite": "8.2.2",
|
|
113
|
-
"vitest": "
|
|
127
|
+
"vitest": "5.0.0",
|
|
114
128
|
"vue": "3.5.42",
|
|
115
129
|
"vue-tsc": "3.3.11"
|
|
116
130
|
},
|
|
@@ -130,7 +144,9 @@
|
|
|
130
144
|
"cypress": true,
|
|
131
145
|
"esbuild": true,
|
|
132
146
|
"fsevents": false,
|
|
147
|
+
"msw": false,
|
|
133
148
|
"unrs-resolver": true
|
|
134
149
|
},
|
|
150
|
+
"cloneman": {},
|
|
135
151
|
"externalDependencies": []
|
|
136
152
|
}
|
package/files/renovate.json
CHANGED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { FButton, FNumericTextField, FTextField, FValidationForm } from "@fkui/vue";
|
|
3
|
+
import { type Cat } from "./cat-types";
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
cat: Cat;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const props = defineProps<Props>();
|
|
10
|
+
|
|
11
|
+
const emit = defineEmits<{
|
|
12
|
+
(e: "submit", cat: Cat): void;
|
|
13
|
+
(e: "cancel"): void;
|
|
14
|
+
}>();
|
|
15
|
+
|
|
16
|
+
// Create a local copy for editing
|
|
17
|
+
const editForm = { ...props.cat };
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<template>
|
|
21
|
+
<div data-test="cat-info-edit">
|
|
22
|
+
<f-validation-form @submit="emit('submit', editForm)">
|
|
23
|
+
<template #error-message> Oj, du har glömt fylla i något. Gå till: </template>
|
|
24
|
+
<template #default>
|
|
25
|
+
<f-text-field v-model="editForm.name" v-validation.required.maxLength="100" v-test="'edit-name'">
|
|
26
|
+
Namn
|
|
27
|
+
</f-text-field>
|
|
28
|
+
|
|
29
|
+
<f-numeric-text-field v-model="editForm.age" v-validation.required v-test="'edit-age'">
|
|
30
|
+
Ålder
|
|
31
|
+
</f-numeric-text-field>
|
|
32
|
+
|
|
33
|
+
<f-text-field v-model="editForm.breed" v-validation.required.maxLength="100" v-test="'edit-breed'">
|
|
34
|
+
Ras
|
|
35
|
+
</f-text-field>
|
|
36
|
+
|
|
37
|
+
<f-text-field v-model="editForm.color" v-validation.required.maxLength="100" v-test="'edit-color'">
|
|
38
|
+
Färg
|
|
39
|
+
</f-text-field>
|
|
40
|
+
|
|
41
|
+
<f-text-field
|
|
42
|
+
v-model="editForm.favoriteFood"
|
|
43
|
+
v-validation.maxLength="500"
|
|
44
|
+
v-test="'edit-favorite-food'"
|
|
45
|
+
>
|
|
46
|
+
Favoritmat
|
|
47
|
+
</f-text-field>
|
|
48
|
+
<div class="button-group">
|
|
49
|
+
<f-button class="button-group__item" size="large" variant="primary" type="submit"> Spara </f-button>
|
|
50
|
+
<f-button class="button-group__item" size="large" variant="secondary" @click="emit('cancel')">
|
|
51
|
+
Avbryt
|
|
52
|
+
</f-button>
|
|
53
|
+
</div>
|
|
54
|
+
</template>
|
|
55
|
+
</f-validation-form>
|
|
56
|
+
</div>
|
|
57
|
+
</template>
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { catGetById } from "./cat-api";
|
|
3
|
+
import { useCatInfo } from "./cat-info-logic";
|
|
4
|
+
|
|
5
|
+
vi.mock(import("./cat-api"));
|
|
6
|
+
//vi.useFakeTimers();
|
|
7
|
+
|
|
8
|
+
describe("useCatInfo", () => {
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
vi.mocked(catGetById).mockReset();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("should have initial state", () => {
|
|
14
|
+
expect.assertions(3);
|
|
15
|
+
const { loading, cat, error } = useCatInfo();
|
|
16
|
+
expect(loading.value).toBe(false);
|
|
17
|
+
expect(cat.value).toBeNull();
|
|
18
|
+
expect(error.value).toBeNull();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("should set loading then data for valid cat ID", async () => {
|
|
22
|
+
expect.assertions(5);
|
|
23
|
+
const { loading, cat, error, fetchCat } = useCatInfo();
|
|
24
|
+
const mockCat = {
|
|
25
|
+
id: "whiskers-001",
|
|
26
|
+
name: "Whiskers McFluffington",
|
|
27
|
+
age: 3,
|
|
28
|
+
breed: "European Shorthair",
|
|
29
|
+
color: "Orange Tabby",
|
|
30
|
+
favoriteFood: "Tuna",
|
|
31
|
+
};
|
|
32
|
+
vi.mocked(catGetById).mockResolvedValue(mockCat);
|
|
33
|
+
|
|
34
|
+
const fetchPromise = fetchCat("whiskers-001");
|
|
35
|
+
|
|
36
|
+
// loading should be true immediately
|
|
37
|
+
expect(loading.value).toBe(true);
|
|
38
|
+
|
|
39
|
+
await fetchPromise;
|
|
40
|
+
|
|
41
|
+
expect(loading.value).toBe(false);
|
|
42
|
+
expect(cat.value).not.toBeNull();
|
|
43
|
+
expect(cat.value?.name).toBe("Whiskers McFluffington");
|
|
44
|
+
expect(error.value).toBeNull();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("should set error for invalid cat ID", async () => {
|
|
48
|
+
expect.assertions(4);
|
|
49
|
+
const { loading, cat, error, fetchCat } = useCatInfo();
|
|
50
|
+
vi.mocked(catGetById).mockRejectedValue(
|
|
51
|
+
new Error("Cat with ID 'invalid-id' not found"),
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
await fetchCat("invalid-id");
|
|
55
|
+
|
|
56
|
+
expect(loading.value).toBe(false);
|
|
57
|
+
expect(cat.value).toBeNull();
|
|
58
|
+
expect(error.value).not.toBeNull();
|
|
59
|
+
expect(error.value).toContain("not found");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("should modify cat data", () => {
|
|
63
|
+
expect.assertions(2);
|
|
64
|
+
const { cat, updateCat } = useCatInfo();
|
|
65
|
+
const testCat = {
|
|
66
|
+
id: "test",
|
|
67
|
+
name: "Original",
|
|
68
|
+
age: 5,
|
|
69
|
+
breed: "Test",
|
|
70
|
+
color: "Test",
|
|
71
|
+
favoriteFood: "Test",
|
|
72
|
+
};
|
|
73
|
+
cat.value = testCat;
|
|
74
|
+
|
|
75
|
+
updateCat({ ...testCat, name: "Updated" });
|
|
76
|
+
|
|
77
|
+
expect(cat.value.name).toBe("Updated");
|
|
78
|
+
expect(cat.value.age).toBe(5);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("should fetch cat for luna-002", async () => {
|
|
82
|
+
expect.assertions(2);
|
|
83
|
+
const { cat, fetchCat } = useCatInfo();
|
|
84
|
+
const mockCat = {
|
|
85
|
+
id: "luna-002",
|
|
86
|
+
name: "Luna the Midnight Prowler",
|
|
87
|
+
age: 2,
|
|
88
|
+
breed: "Bombay",
|
|
89
|
+
color: "Midnight Black",
|
|
90
|
+
favoriteFood: "Salmon",
|
|
91
|
+
};
|
|
92
|
+
vi.mocked(catGetById).mockResolvedValue(mockCat);
|
|
93
|
+
|
|
94
|
+
await fetchCat("luna-002");
|
|
95
|
+
|
|
96
|
+
expect(cat.value!.name).toBe("Luna the Midnight Prowler");
|
|
97
|
+
expect(cat.value!.color).toBe("Midnight Black");
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("should fetch cat for muffin-003", async () => {
|
|
101
|
+
expect.assertions(2);
|
|
102
|
+
const { cat, fetchCat } = useCatInfo();
|
|
103
|
+
const mockCat = {
|
|
104
|
+
id: "muffin-003",
|
|
105
|
+
name: "Sir Muffin III",
|
|
106
|
+
age: 5,
|
|
107
|
+
breed: "Maine Coon",
|
|
108
|
+
color: "Calico",
|
|
109
|
+
favoriteFood: "Chicken",
|
|
110
|
+
};
|
|
111
|
+
vi.mocked(catGetById).mockResolvedValue(mockCat);
|
|
112
|
+
|
|
113
|
+
await fetchCat("muffin-003");
|
|
114
|
+
|
|
115
|
+
expect(cat.value!.name).toBe("Sir Muffin III");
|
|
116
|
+
expect(cat.value!.breed).toBe("Maine Coon");
|
|
117
|
+
});
|
|
118
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from "vue";
|
|
3
|
+
import { FDefinitionList } from "@fkui/vue";
|
|
4
|
+
import { type Cat } from "./cat-types";
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
cat: Cat;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const props = defineProps<Props>();
|
|
11
|
+
|
|
12
|
+
const catDefinitions = computed(() => {
|
|
13
|
+
return [
|
|
14
|
+
{ term: "Namn", definition: props.cat.name },
|
|
15
|
+
{ term: "Ålder", definition: `${props.cat.age} år` },
|
|
16
|
+
{ term: "Ras", definition: props.cat.breed },
|
|
17
|
+
{ term: "Färg", definition: props.cat.color },
|
|
18
|
+
{ term: "Favoritmat", definition: props.cat.favoriteFood },
|
|
19
|
+
];
|
|
20
|
+
});
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<template>
|
|
24
|
+
<div data-test="cat-info-view">
|
|
25
|
+
<f-definition-list :definitions="catDefinitions" />
|
|
26
|
+
</div>
|
|
27
|
+
</template>
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { FLoaderSelectors } from "@fkui/vue/selectors";
|
|
2
|
+
import FcCatInfoComponent from "./FcCatInfoComponent.vue";
|
|
3
|
+
import { cats } from "./cat-data";
|
|
4
|
+
import { FcCatInfoComponentSelectors } from "./selectors";
|
|
5
|
+
|
|
6
|
+
describe("FcCatInfoComponent", () => {
|
|
7
|
+
const testCat = cats[0];
|
|
8
|
+
const catInfoSelectors = FcCatInfoComponentSelectors();
|
|
9
|
+
const loaderSelectors = FLoaderSelectors();
|
|
10
|
+
|
|
11
|
+
it("verifies loading text", () => {
|
|
12
|
+
cy.mount(FcCatInfoComponent, {
|
|
13
|
+
props: {
|
|
14
|
+
catId: testCat.id,
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
cy.get(catInfoSelectors.loadingContainer()).should("be.visible");
|
|
19
|
+
cy.get(loaderSelectors.waitText()).should(
|
|
20
|
+
"contain.text",
|
|
21
|
+
"Hämtar kattinformation...",
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("verifies all fields in view mode have correct data", () => {
|
|
26
|
+
cy.mount(FcCatInfoComponent, {
|
|
27
|
+
props: {
|
|
28
|
+
catId: testCat.id,
|
|
29
|
+
isEditable: false,
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Wait for loading to disappear
|
|
34
|
+
cy.get(catInfoSelectors.loadingContainer()).should("not.exist");
|
|
35
|
+
|
|
36
|
+
const view = catInfoSelectors.viewContainer();
|
|
37
|
+
cy.get(view).should("be.visible");
|
|
38
|
+
|
|
39
|
+
cy.get(view).contains(testCat.name).should("be.visible");
|
|
40
|
+
cy.get(view).contains(`${testCat.age} år`).should("be.visible");
|
|
41
|
+
cy.get(view).contains(testCat.breed).should("be.visible");
|
|
42
|
+
cy.get(view).contains(testCat.color).should("be.visible");
|
|
43
|
+
cy.get(view).contains(testCat.favoriteFood).should("be.visible");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("verifies all fields in edit mode have correct data", () => {
|
|
47
|
+
cy.mount(FcCatInfoComponent, {
|
|
48
|
+
props: {
|
|
49
|
+
catId: testCat.id,
|
|
50
|
+
isEditable: true,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Wait for loading to disappear
|
|
55
|
+
cy.get(catInfoSelectors.loadingContainer()).should("not.exist");
|
|
56
|
+
cy.get(catInfoSelectors.editContainer()).should("be.visible");
|
|
57
|
+
|
|
58
|
+
cy.get(catInfoSelectors.nameInput())
|
|
59
|
+
.should("be.visible")
|
|
60
|
+
.should("have.value", testCat.name);
|
|
61
|
+
cy.get(catInfoSelectors.ageInput())
|
|
62
|
+
.should("be.visible")
|
|
63
|
+
.should("have.value", testCat.age.toString());
|
|
64
|
+
cy.get(catInfoSelectors.breedInput())
|
|
65
|
+
.should("be.visible")
|
|
66
|
+
.should("have.value", testCat.breed);
|
|
67
|
+
cy.get(catInfoSelectors.colorInput())
|
|
68
|
+
.should("be.visible")
|
|
69
|
+
.should("have.value", testCat.color);
|
|
70
|
+
cy.get(catInfoSelectors.favoriteFoodInput())
|
|
71
|
+
.should("be.visible")
|
|
72
|
+
.should("have.value", testCat.favoriteFood);
|
|
73
|
+
});
|
|
74
|
+
});
|