@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.
Files changed (49) hide show
  1. package/files/README.md +6 -5
  2. package/files/_htmlvalidateignore +2 -0
  3. package/files/cypress.config.ts +1 -0
  4. package/files/docs/build.mts +14 -0
  5. package/files/docs/index.md +2 -0
  6. package/files/docs/kattinformation/index.md +28 -0
  7. package/files/docs/package.json +5 -2
  8. package/files/docs/src/bundle-mocks.mjs +22 -0
  9. package/files/docs/src/global.d.ts +7 -0
  10. package/files/docs/src/main.js +17 -0
  11. package/files/docs/src/main.scss +22 -0
  12. package/files/docs/src/setup.ts +6 -1
  13. package/files/docs/tsconfig.json +1 -0
  14. package/files/etc/lib.api.md +1 -1
  15. package/files/etc/selectors.api.md +13 -0
  16. package/files/package.json +45 -29
  17. package/files/renovate.json +1 -0
  18. package/files/src/CatInfoEdit.vue +57 -0
  19. package/files/src/CatInfoLogic.spec.ts +118 -0
  20. package/files/src/CatInfoShow.vue +27 -0
  21. package/files/src/FcCatInfoComponent.cy.ts +74 -0
  22. package/files/src/FcCatInfoComponent.vue +81 -0
  23. package/files/src/FcCatInfoComponentLiveExample.vue +42 -0
  24. package/files/src/cat-api-mock.spec.ts +27 -0
  25. package/files/src/cat-api.mock.mts +26 -0
  26. package/files/src/cat-api.spec.ts +65 -0
  27. package/files/src/cat-api.ts +15 -0
  28. package/files/src/cat-data.ts +40 -0
  29. package/files/src/cat-info-logic.ts +52 -0
  30. package/files/src/cat-types.ts +11 -0
  31. package/files/src/examples/CatInfoExample.vue +20 -0
  32. package/files/src/index.ts +3 -1
  33. package/files/src/local.ts +1 -1
  34. package/files/src/mocks.mts +6 -0
  35. package/files/src/selectors/FcCatInfoComponent.selectors.ts +74 -0
  36. package/files/src/selectors/index.ts +1 -1
  37. package/files/src/style.scss +1 -0
  38. package/files/src/vite-dev/app.vue +1 -1
  39. package/files/tsconfig.lib.json +7 -1
  40. package/files/vite.config.mts +4 -0
  41. package/index.js +1 -0
  42. package/package.json +25 -8
  43. package/files/docs/components/AwesomeComponent.md +0 -27
  44. package/files/docs/components/index.md +0 -5
  45. package/files/src/AwesomeComponent.cy.ts +0 -9
  46. package/files/src/AwesomeComponent.vue +0 -45
  47. package/files/src/AwesomeComponentLogic.spec.ts +0 -30
  48. package/files/src/awesome-component-logic.ts +0 -28
  49. 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
- - [ ] apimock
84
- - [ ] bättre exempelkomponent
85
- - [ ] bättre enhetstest
86
- - [ ] bättre komponenttest
87
- - [ ] live exempel
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
@@ -1,2 +1,4 @@
1
1
  # generated files
2
2
  docs/public/
3
+ docs/node_modules/
4
+ docs/temp/
@@ -85,6 +85,7 @@ export default defineConfig({
85
85
  framework: "vue",
86
86
  bundler: "vite",
87
87
  },
88
+ excludeSpecPattern: ["temp/**"], // cloneman puts cy-files in temp folder during build
88
89
  },
89
90
  defaultBrowser: "chrome",
90
91
  hosts: { localhost: "127.0.0.1" },
@@ -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
+ );
@@ -1,3 +1,5 @@
1
1
  ---
2
2
  title: "@forsakringskassan/vue-lib-template"
3
3
  ---
4
+
5
+ För mer information om hur du skapar egna sidor, besök [docs-generator](https://forsakringskassan.github.io/docs-generator/latest/).
@@ -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
+ :::
@@ -7,11 +7,14 @@
7
7
  "start": "http-server public"
8
8
  },
9
9
  "devDependencies": {
10
- "@fkui/vue": "6.55.0",
11
- "@forsakringskassan/docs-generator": "3.6.2",
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,7 @@
1
+ export {};
2
+
3
+ declare global {
4
+ interface Window {
5
+ bundleMocks?: Promise<void>;
6
+ }
7
+ }
@@ -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();
@@ -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
+ }
@@ -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 });
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "extends": ["@tsconfig/recommended", "@tsconfig/node24"],
3
3
  "compilerOptions": {
4
+ "lib": ["DOM", "DOM.Iterable", "ESNext"],
4
5
  "types": ["node"]
5
6
  },
6
7
  "include": ["**/*.ts", "**/*.mts"],
@@ -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 AwesomeComponent: typeof __VLS_export;
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
  ```
@@ -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.55.0",
70
- "@fkui/font-default": "6.55.0",
71
- "@fkui/icon-lib-default": "6.55.0",
72
- "@fkui/logic": "6.55.0",
73
- "@fkui/test-utils": "6.55.0",
74
- "@fkui/theme-default": "6.55.0",
75
- "@fkui/vue": "6.55.0",
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.1.0",
79
- "@forsakringskassan/docs-generator": "3.6.2",
80
- "@forsakringskassan/docs-live-example": "3.0.1",
81
- "@forsakringskassan/eslint-config": "15.9.0",
82
- "@forsakringskassan/eslint-config-cli": "15.9.0",
83
- "@forsakringskassan/eslint-config-cypress": "15.9.0",
84
- "@forsakringskassan/eslint-config-jest": "15.9.0",
85
- "@forsakringskassan/eslint-config-typescript": "15.9.0",
86
- "@forsakringskassan/eslint-config-typescript-typeinfo": "15.9.0",
87
- "@forsakringskassan/eslint-config-vitest": "15.9.0",
88
- "@forsakringskassan/eslint-config-vue": "15.9.0",
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.5",
91
- "@forsakringskassan/vite-lib-config": "5.10.2",
92
- "@forsakringskassan/vitest-config-jsdom": "2.7.0",
93
- "@forsakringskassan/vue-lib-template": "1.0.4",
94
- "@html-validate/release-scripts": "7.6.8",
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.22.0",
113
+ "cloneman": "1.23.1",
100
114
  "core-js": "3.50.0",
101
- "cypress": "15.21.1",
102
- "cypress-html-validate": "9.0.0",
103
- "html-validate": "11.10.0",
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.4",
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": "4.1.11",
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
  }
@@ -3,6 +3,7 @@
3
3
  "ignoreDeps": [
4
4
  "@babel/core",
5
5
  "@babel/preset-env",
6
+ "@forsakringskassan/apimock-express",
6
7
  "@forsakringskassan/commitlint-config",
7
8
  "@forsakringskassan/cypress-axe",
8
9
  "@forsakringskassan/cypress-visual-regression",
@@ -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
+ });