create-outsystems-astro 0.4.2 → 0.5.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 +5 -0
- package/package.json +1 -1
- package/template/.prettierignore +2 -1
- package/template/AGENTS.md +58 -5
- package/template/bun.lock +590 -332
- package/template/deno.json +8 -4
- package/template/deno.lock +893 -717
- package/template/eslint.config.mjs +1 -0
- package/template/package-lock.json +1961 -1876
- package/template/package.json +77 -38
- package/template/pnpm-lock.yaml +1607 -1175
- package/template/src/framework/angular/Counter.component.ts +25 -13
- package/template/src/framework/react/Counter.tsx +41 -9
- package/template/src/framework/vue/Counter.vue +49 -14
- package/template/src/pages/angular/angular-counter.astro +21 -5
- package/template/src/pages/react/react-counter.astro +45 -8
- package/template/src/pages/vue/vue-counter.astro +45 -4
- package/template/src/stores/.gitkeep +0 -0
- package/template/src/styles/index.css +65 -0
- package/template/test/e2e/react/react-counter.spec.ts +12 -2
- package/template/test/e2e/vue/vue-counter.spec.ts +12 -2
- package/template/test/integration/angular/Counter.component.spec.ts +1 -1
- package/template/test/integration/react/Counter.test.tsx +35 -10
- package/template/test/integration/vue/Counter.test.ts +42 -4
- package/template/yarn.lock +2597 -722
- /package/template/patches/{@analogjs+astro-angular+2.2.2.patch → @analogjs+astro-angular+2.3.0.patch} +0 -0
- /package/template/patches/{@angular+build+21.1.0.patch → @angular+build+21.2.0.patch} +0 -0
|
@@ -11,17 +11,29 @@ import { Operation, setCounterCount } from "../../lib/setCounterCount";
|
|
|
11
11
|
standalone: true,
|
|
12
12
|
template: `
|
|
13
13
|
<div class="counter-title" slot="header">Counter</div>
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
<div class="card-grid">
|
|
15
|
+
<div class="card">
|
|
16
|
+
Internal counter controls. It keeps state within the component.
|
|
17
|
+
<div class="card-content">
|
|
18
|
+
<div class="counter-controls">
|
|
19
|
+
<button (click)="subtract()">-</button>
|
|
20
|
+
<pre>{{ count() }}</pre>
|
|
21
|
+
<button (click)="add()">+</button>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
<div class="card">
|
|
26
|
+
The button sends the current count value to a function in the parent
|
|
27
|
+
component.
|
|
28
|
+
<div class="card-content">
|
|
29
|
+
<div>
|
|
30
|
+
<button class="card-btn" (click)="showParentMessage()">
|
|
31
|
+
Send value
|
|
32
|
+
</button>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
23
36
|
</div>
|
|
24
|
-
|
|
25
37
|
<div class="counter-logos">
|
|
26
38
|
<img [src]="outSystemsLogo" alt="OutSystems logo" />
|
|
27
39
|
<img [src]="astroLogo" alt="Astro logo" />
|
|
@@ -48,11 +60,11 @@ export default class CounterComponent implements OnInit {
|
|
|
48
60
|
showParentMessage() {
|
|
49
61
|
const fnName = this.messageFunctionName();
|
|
50
62
|
|
|
51
|
-
// Safety check to ensure the function exists on window
|
|
63
|
+
// Safety check to ensure the function exists on window.
|
|
52
64
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
53
|
-
if (typeof (
|
|
65
|
+
if (typeof (window as any)[fnName] === "function") {
|
|
54
66
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
55
|
-
(
|
|
67
|
+
(window as any)[fnName](this.count());
|
|
56
68
|
}
|
|
57
69
|
}
|
|
58
70
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useStore } from "@nanostores/react";
|
|
1
2
|
import { useState } from "react";
|
|
2
3
|
|
|
3
4
|
import AstroLogo from "../../images/astro.png?url";
|
|
@@ -20,19 +21,50 @@ export default function Counter({
|
|
|
20
21
|
const subtract = () =>
|
|
21
22
|
setCount((i) => setCounterCount(i, Operation.Subtract));
|
|
22
23
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
|
-
const showParentMessage = () => (
|
|
24
|
+
const showParentMessage = () => (window as any)[showMessage](count);
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
26
|
+
const nanoStoreValue = useStore((window as any).Stores["reactStore"]);
|
|
24
27
|
|
|
25
28
|
return (
|
|
26
29
|
<>
|
|
27
30
|
{header}
|
|
28
|
-
<div className="
|
|
29
|
-
<
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
<div className="card-grid">
|
|
32
|
+
<div className="card">
|
|
33
|
+
Internal counter controls. It keeps state within the component.
|
|
34
|
+
<div className="card-content">
|
|
35
|
+
<div className="counter-controls">
|
|
36
|
+
<button onClick={subtract}>-</button>
|
|
37
|
+
<pre>{count}</pre>
|
|
38
|
+
<button onClick={add}>+</button>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
<div className="card">
|
|
43
|
+
The button sends the current count value to a function in the parent
|
|
44
|
+
component.
|
|
45
|
+
<div className="card-content">
|
|
46
|
+
<div>
|
|
47
|
+
<button className="card-btn" onClick={showParentMessage}>
|
|
48
|
+
Send value
|
|
49
|
+
</button>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
<div className="card">
|
|
54
|
+
Slot content coming in to the component
|
|
55
|
+
<div className="card-content">
|
|
56
|
+
<div>{children}</div>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
<div className="card">
|
|
60
|
+
Nano Store content
|
|
61
|
+
<div className="card-content">
|
|
62
|
+
<div>
|
|
63
|
+
<strong>Nano Store value:</strong>
|
|
64
|
+
<div id="nanostore">{nanoStoreValue}</div>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
36
68
|
</div>
|
|
37
69
|
<div className="counter-logos">
|
|
38
70
|
<img alt="OutSystems logo" src={OutSystemsLogo} />
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { ref } from "vue";
|
|
3
|
+
import { useStore } from "@nanostores/vue";
|
|
3
4
|
|
|
4
|
-
import OutSystemsLogo from "../../images/outsystems.png?url";
|
|
5
5
|
import AstroLogo from "../../images/astro.png?url";
|
|
6
|
+
import OutSystemsLogo from "../../images/outsystems.png?url";
|
|
6
7
|
import { Operation, setCounterCount } from "../../lib/setCounterCount";
|
|
7
8
|
|
|
8
9
|
const props = defineProps<{
|
|
@@ -21,29 +22,63 @@ const subtract = () => {
|
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
const showParentMessage = () => {
|
|
24
|
-
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
26
|
+
(window as any)[props.showMessage](count.value);
|
|
25
27
|
};
|
|
28
|
+
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
30
|
+
const nanoStoreValue = useStore((window as any).Stores["vueStore"]);
|
|
26
31
|
</script>
|
|
27
32
|
|
|
28
33
|
<template>
|
|
29
|
-
<
|
|
30
|
-
<slot name="header" />
|
|
34
|
+
<slot name="header" />
|
|
31
35
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
<
|
|
36
|
+
<div class="card-grid">
|
|
37
|
+
<div class="card">
|
|
38
|
+
Internal counter controls. It keeps state within the component.
|
|
39
|
+
<div class="card-content">
|
|
40
|
+
<div class="counter-controls">
|
|
41
|
+
<button @click="subtract">-</button>
|
|
42
|
+
<pre>{{ count }}</pre>
|
|
43
|
+
<button @click="add">+</button>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
36
46
|
</div>
|
|
37
47
|
|
|
38
|
-
<
|
|
48
|
+
<div class="card">
|
|
49
|
+
The button sends the current count value to a function in the parent
|
|
50
|
+
component.
|
|
51
|
+
<div class="card-content">
|
|
52
|
+
<div>
|
|
53
|
+
<button class="card-btn" @click="showParentMessage">
|
|
54
|
+
Send value
|
|
55
|
+
</button>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
39
59
|
|
|
40
|
-
<div class="
|
|
41
|
-
|
|
60
|
+
<div class="card">
|
|
61
|
+
Slot content coming in to the component
|
|
62
|
+
<div class="card-content">
|
|
63
|
+
<div>
|
|
64
|
+
<slot />
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
42
67
|
</div>
|
|
43
68
|
|
|
44
|
-
<div class="
|
|
45
|
-
|
|
46
|
-
<
|
|
69
|
+
<div class="card">
|
|
70
|
+
Nano Store content
|
|
71
|
+
<div class="card-content">
|
|
72
|
+
<div>
|
|
73
|
+
<strong>Nano Store value:</strong>
|
|
74
|
+
<div id="nanostore">{{ nanoStoreValue }}</div>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
47
77
|
</div>
|
|
48
78
|
</div>
|
|
79
|
+
|
|
80
|
+
<div class="counter-logos">
|
|
81
|
+
<img alt="OutSystems logo" :src="OutSystemsLogo" />
|
|
82
|
+
<img alt="Astro logo" :src="AstroLogo" />
|
|
83
|
+
</div>
|
|
49
84
|
</template>
|
|
@@ -1,15 +1,31 @@
|
|
|
1
1
|
---
|
|
2
|
-
import CounterComponent from
|
|
2
|
+
import CounterComponent from "../../framework/angular/Counter.component";
|
|
3
3
|
import styles from "../../styles/index.css?url";
|
|
4
4
|
const initialCount = 5;
|
|
5
5
|
const showMessage = "showMessage";
|
|
6
6
|
---
|
|
7
|
+
|
|
7
8
|
<link href={styles} rel="stylesheet" />
|
|
8
9
|
<script is:inline>
|
|
9
|
-
|
|
10
|
+
window.showMessage = (count) => {
|
|
10
11
|
document.getElementById("counter").textContent = count;
|
|
11
12
|
};
|
|
12
13
|
</script>
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
<div
|
|
14
|
+
<div class="counter-title">HTML Content</div>
|
|
15
|
+
<div class="card-grid">
|
|
16
|
+
<div class="card">
|
|
17
|
+
Value sent back from component.
|
|
18
|
+
<div class="card-content">
|
|
19
|
+
<div style="text-align: center; margin-top: 30px;">
|
|
20
|
+
Counter value sent back: <br /><span id="counter"></span>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
<hr />
|
|
26
|
+
<CounterComponent
|
|
27
|
+
client:visible
|
|
28
|
+
initialCount={initialCount}
|
|
29
|
+
showMessage={showMessage}
|
|
30
|
+
/>
|
|
31
|
+
|
|
@@ -1,21 +1,58 @@
|
|
|
1
1
|
---
|
|
2
|
-
import CounterComponent from
|
|
2
|
+
import CounterComponent from "../../framework/react/Counter";
|
|
3
3
|
import styles from "../../styles/index.css?url";
|
|
4
4
|
const initialCount = 5;
|
|
5
5
|
const showMessage = "showMessage";
|
|
6
6
|
---
|
|
7
|
+
|
|
7
8
|
<link href={styles} rel="stylesheet" />
|
|
8
|
-
<script
|
|
9
|
-
|
|
9
|
+
<script>
|
|
10
|
+
import { atom } from "nanostores";
|
|
11
|
+
window["showMessage"] = (count) => {
|
|
10
12
|
document.getElementById("counter").textContent = count;
|
|
11
13
|
};
|
|
14
|
+
window.Stores = [];
|
|
15
|
+
window.Stores["reactStore"] = atom("Test Value");
|
|
16
|
+
document.addEventListener("DOMContentLoaded", function () {
|
|
17
|
+
const input = document.getElementById("store");
|
|
18
|
+
input.value = window.Stores["reactStore"].get();
|
|
19
|
+
});
|
|
12
20
|
</script>
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
21
|
+
<div class="counter-title">HTML Content</div>
|
|
22
|
+
<div class="card-grid">
|
|
23
|
+
<div class="card">
|
|
24
|
+
Value sent back from component.
|
|
25
|
+
<div class="card-content">
|
|
26
|
+
<div style="text-align: center; margin-top: 30px;">
|
|
27
|
+
Counter value sent back: <br /><span id="counter"></span>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
16
30
|
</div>
|
|
31
|
+
<div class="card">
|
|
32
|
+
Update Nano Store value
|
|
33
|
+
<div class="card-content">
|
|
34
|
+
<div style="text-align: center; margin-top: 30px;">
|
|
35
|
+
<input
|
|
36
|
+
id="store"
|
|
37
|
+
placeholder="Type something..."
|
|
38
|
+
type="text"
|
|
39
|
+
/><button
|
|
40
|
+
class="card-btn"
|
|
41
|
+
onclick="window.Stores['reactStore'].set(document.getElementById('store').value)"
|
|
42
|
+
>Update Store</button
|
|
43
|
+
>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
<hr />
|
|
49
|
+
<CounterComponent
|
|
50
|
+
client:only="react"
|
|
51
|
+
initialCount={initialCount}
|
|
52
|
+
showMessage={showMessage}
|
|
53
|
+
>
|
|
54
|
+
<div class="counter-title" slot="header">Counter Component</div>
|
|
17
55
|
<div style="text-align: center;">
|
|
18
|
-
<p>
|
|
56
|
+
<p><strong>This is content passed into the component.</strong></p>
|
|
19
57
|
</div>
|
|
20
58
|
</CounterComponent>
|
|
21
|
-
<div style="text-align: center; margin-top: 20px;">Counter value: <span id="counter"></span></div>
|
|
@@ -4,18 +4,59 @@ import styles from "../../styles/index.css?url";
|
|
|
4
4
|
const initialCount = 5;
|
|
5
5
|
const showMessage = "showMessage";
|
|
6
6
|
---
|
|
7
|
+
|
|
8
|
+
<link href={styles} rel="stylesheet" />
|
|
9
|
+
<script>
|
|
10
|
+
import { atom } from "nanostores";
|
|
11
|
+
window["showMessage"] = (count) => {
|
|
12
|
+
document.getElementById("counter").textContent = count;
|
|
13
|
+
};
|
|
14
|
+
window.Stores = [];
|
|
15
|
+
window.Stores["vueStore"] = atom("Test Value");
|
|
16
|
+
document.addEventListener("DOMContentLoaded", function () {
|
|
17
|
+
const input = document.getElementById("store");
|
|
18
|
+
input.value = window.Stores["vueStore"].get();
|
|
19
|
+
});
|
|
20
|
+
</script>
|
|
21
|
+
<div class="counter-title">HTML Content</div>
|
|
22
|
+
<div class="card-grid">
|
|
23
|
+
<div class="card">
|
|
24
|
+
Value sent back from component.
|
|
25
|
+
<div class="card-content">
|
|
26
|
+
<div style="text-align: center; margin-top: 30px;">
|
|
27
|
+
Counter value sent back: <br /><span id="counter"></span>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
<div class="card">
|
|
32
|
+
Update Nano Store value
|
|
33
|
+
<div class="card-content">
|
|
34
|
+
<div style="text-align: center; margin-top: 30px;">
|
|
35
|
+
<input
|
|
36
|
+
id="store"
|
|
37
|
+
placeholder="Type something..."
|
|
38
|
+
type="text"
|
|
39
|
+
/><button
|
|
40
|
+
class="card-btn"
|
|
41
|
+
onclick="window.Stores['vueStore'].set(document.getElementById('store').value)"
|
|
42
|
+
>Update Store</button
|
|
43
|
+
>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
<hr />
|
|
7
49
|
<link href={styles} rel="stylesheet" />
|
|
8
50
|
<script is:inline>
|
|
9
|
-
|
|
51
|
+
window.showMessage = (count) => {
|
|
10
52
|
document.getElementById("counter").textContent = count;
|
|
11
53
|
};
|
|
12
54
|
</script>
|
|
13
55
|
<CounterComponent client:only="vue" initialCount={initialCount} showMessage={showMessage}>
|
|
14
56
|
<div class="counter-title" slot="header">
|
|
15
|
-
Counter
|
|
57
|
+
Counter Component
|
|
16
58
|
</div>
|
|
17
59
|
<div style="text-align: center;">
|
|
18
|
-
<p>
|
|
60
|
+
<p>This is content passed into the component.</p>
|
|
19
61
|
</div>
|
|
20
62
|
</CounterComponent>
|
|
21
|
-
<div style="text-align: center; margin-top: 20px;">Counter value: <span id="counter"></span></div>
|
|
File without changes
|
|
@@ -11,10 +11,12 @@
|
|
|
11
11
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
12
12
|
margin-top: 0.5em;
|
|
13
13
|
place-items: center;
|
|
14
|
+
border: 1;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
.counter-message,
|
|
17
18
|
.logos {
|
|
19
|
+
font-size: 1.2em;
|
|
18
20
|
text-align: center;
|
|
19
21
|
}
|
|
20
22
|
|
|
@@ -28,3 +30,66 @@
|
|
|
28
30
|
.counter-logos img {
|
|
29
31
|
width: 150px;
|
|
30
32
|
}
|
|
33
|
+
|
|
34
|
+
.card {
|
|
35
|
+
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2); /* Add shadows to create the "card" effect */
|
|
36
|
+
transition: 0.3s; /* Smooth transition for hover effects */
|
|
37
|
+
border-radius: 5px; /* Rounded corners */
|
|
38
|
+
overflow: hidden; /* Ensures content stays within the rounded corners */
|
|
39
|
+
background-color: #fff;
|
|
40
|
+
padding: 10px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* On mouse-over, add a deeper shadow */
|
|
44
|
+
.card:hover {
|
|
45
|
+
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.card-image {
|
|
49
|
+
width: 100%; /* Image takes full width of the card */
|
|
50
|
+
height: 200px; /* Fixed height for consistency */
|
|
51
|
+
object-fit: cover; /* Ensures image covers the area without distortion */
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.card-content {
|
|
55
|
+
padding: 16px; /* Add some padding inside the card container */
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.card-title {
|
|
59
|
+
margin-top: 0;
|
|
60
|
+
font-size: 1.25rem;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.card-description {
|
|
64
|
+
color: #555;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.card-link {
|
|
68
|
+
display: inline-block;
|
|
69
|
+
margin-top: 10px;
|
|
70
|
+
color: dodgerblue;
|
|
71
|
+
text-decoration: none;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.card-grid {
|
|
75
|
+
display: grid;
|
|
76
|
+
/* Automatically fill columns with a minimum width of 250px and maximum of 1fr */
|
|
77
|
+
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
|
78
|
+
gap: 24px; /* Space between cards */
|
|
79
|
+
padding: 24px;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.card-btn {
|
|
83
|
+
margin-top: 20px;
|
|
84
|
+
padding: 10px 15px;
|
|
85
|
+
background-color: #007bff;
|
|
86
|
+
color: white;
|
|
87
|
+
border: none;
|
|
88
|
+
border-radius: 5px;
|
|
89
|
+
cursor: pointer;
|
|
90
|
+
align-self: flex-start; /* Button size */
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.card-btn:hover {
|
|
94
|
+
background-color: #0056b3;
|
|
95
|
+
}
|
|
@@ -6,11 +6,13 @@ test.beforeEach(async ({ page }) => {
|
|
|
6
6
|
|
|
7
7
|
test.describe("Has values", () => {
|
|
8
8
|
test("Should have header", async ({ page }) => {
|
|
9
|
-
await expect(page.getByText("Counter")).toBeVisible();
|
|
9
|
+
await expect(page.getByText("Counter Component")).toBeVisible();
|
|
10
10
|
});
|
|
11
11
|
|
|
12
12
|
test("Should have slot content", async ({ page }) => {
|
|
13
|
-
await expect(
|
|
13
|
+
await expect(
|
|
14
|
+
page.getByText("This is content passed into the component"),
|
|
15
|
+
).toBeVisible();
|
|
14
16
|
});
|
|
15
17
|
});
|
|
16
18
|
|
|
@@ -30,3 +32,11 @@ test.describe("Change counter", () => {
|
|
|
30
32
|
await expect(page.locator("span#counter")).toContainText("5");
|
|
31
33
|
});
|
|
32
34
|
});
|
|
35
|
+
|
|
36
|
+
test.describe("Update Nano Store", () => {
|
|
37
|
+
test("Should update Nano Store", async ({ page }) => {
|
|
38
|
+
await page.locator("#store").fill("Updated Value");
|
|
39
|
+
await page.getByRole("button", { name: "Update Store" }).click();
|
|
40
|
+
await expect(page.locator("#nanostore")).toHaveText("Updated Value");
|
|
41
|
+
});
|
|
42
|
+
});
|
|
@@ -6,11 +6,13 @@ test.beforeEach(async ({ page }) => {
|
|
|
6
6
|
|
|
7
7
|
test.describe("Has values", () => {
|
|
8
8
|
test("Should have header", async ({ page }) => {
|
|
9
|
-
await expect(page.getByText("Counter")).toBeVisible();
|
|
9
|
+
await expect(page.getByText("Counter Component")).toBeVisible();
|
|
10
10
|
});
|
|
11
11
|
|
|
12
12
|
test("Should have slot content", async ({ page }) => {
|
|
13
|
-
await expect(
|
|
13
|
+
await expect(
|
|
14
|
+
page.getByText("This is content passed into the component"),
|
|
15
|
+
).toBeVisible();
|
|
14
16
|
});
|
|
15
17
|
});
|
|
16
18
|
|
|
@@ -30,3 +32,11 @@ test.describe("Change counter", () => {
|
|
|
30
32
|
await expect(page.locator("span#counter")).toContainText("5");
|
|
31
33
|
});
|
|
32
34
|
});
|
|
35
|
+
|
|
36
|
+
test.describe("Update Nano Store", () => {
|
|
37
|
+
test("Should update Nano Store", async ({ page }) => {
|
|
38
|
+
await page.locator("#store").fill("Updated Value");
|
|
39
|
+
await page.getByRole("button", { name: "Update Store" }).click();
|
|
40
|
+
await expect(page.locator("#nanostore")).toHaveText("Updated Value");
|
|
41
|
+
});
|
|
42
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { fireEvent, render, screen } from "@testing-library/angular";
|
|
2
|
-
import { vi } from "vitest";
|
|
2
|
+
import { it, vi } from "vitest";
|
|
3
3
|
import CounterComponent from "../../../src/framework/angular/Counter.component";
|
|
4
4
|
|
|
5
5
|
describe("CounterComponent (Testing Library)", () => {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { fireEvent, render, screen } from "@testing-library/react";
|
|
1
|
+
import { act, fireEvent, render, screen } from "@testing-library/react";
|
|
2
|
+
import { it, vi } from "vitest";
|
|
3
|
+
|
|
2
4
|
import Counter from "../../../src/framework/react/Counter";
|
|
3
5
|
|
|
4
6
|
describe("Counter", () => {
|
|
@@ -9,14 +11,30 @@ describe("Counter", () => {
|
|
|
9
11
|
showMessage: "mockFunction",
|
|
10
12
|
};
|
|
11
13
|
|
|
14
|
+
let capturedListener: ((val: string) => void) | undefined;
|
|
15
|
+
let storeValue = "Mocked Nano Value";
|
|
16
|
+
|
|
12
17
|
beforeEach(() => {
|
|
13
|
-
// Mock the document function
|
|
14
18
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
-
(
|
|
19
|
+
(window as any).mockFunction = vi.fn();
|
|
20
|
+
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
22
|
+
(window as any).Stores = {
|
|
23
|
+
reactStore: {
|
|
24
|
+
get: vi.fn(() => storeValue),
|
|
25
|
+
listen: vi.fn((callback) => {
|
|
26
|
+
capturedListener = callback;
|
|
27
|
+
callback(storeValue);
|
|
28
|
+
return () => {};
|
|
29
|
+
}),
|
|
30
|
+
},
|
|
31
|
+
};
|
|
16
32
|
});
|
|
17
33
|
|
|
18
34
|
afterEach(() => {
|
|
19
35
|
vi.clearAllMocks();
|
|
36
|
+
capturedListener = undefined;
|
|
37
|
+
storeValue = "Mocked Nano Value";
|
|
20
38
|
});
|
|
21
39
|
|
|
22
40
|
it("renders the initial count", () => {
|
|
@@ -36,23 +54,30 @@ describe("Counter", () => {
|
|
|
36
54
|
|
|
37
55
|
it("increments count when add button is clicked", () => {
|
|
38
56
|
render(<Counter {...defaultProps} />);
|
|
39
|
-
|
|
40
|
-
fireEvent.click(addButton);
|
|
57
|
+
fireEvent.click(screen.getByRole("button", { name: "+" }));
|
|
41
58
|
expect(screen.getByText("6")).toBeInTheDocument();
|
|
42
59
|
});
|
|
43
60
|
|
|
44
61
|
it("decrements count when subtract button is clicked", () => {
|
|
45
62
|
render(<Counter {...defaultProps} />);
|
|
46
|
-
|
|
47
|
-
fireEvent.click(subtractButton);
|
|
63
|
+
fireEvent.click(screen.getByRole("button", { name: "-" }));
|
|
48
64
|
expect(screen.getByText("4")).toBeInTheDocument();
|
|
49
65
|
});
|
|
50
66
|
|
|
51
67
|
it("calls the show message function", () => {
|
|
52
68
|
render(<Counter {...defaultProps} />);
|
|
53
|
-
|
|
54
|
-
fireEvent.click(sendButton);
|
|
69
|
+
fireEvent.click(screen.getByRole("button", { name: "Send value" }));
|
|
55
70
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
56
|
-
expect((
|
|
71
|
+
expect((window as any).mockFunction).toHaveBeenCalledWith(5);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("updates the component when the nanostore value changes", async () => {
|
|
75
|
+
render(<Counter {...defaultProps} />);
|
|
76
|
+
expect(screen.getByText(/Mocked Nano Value/i)).toBeInTheDocument();
|
|
77
|
+
await act(async () => {
|
|
78
|
+
storeValue = "Updated Nano Value";
|
|
79
|
+
capturedListener?.("Updated Nano Value");
|
|
80
|
+
});
|
|
81
|
+
expect(await screen.findByText(/Updated Nano Value/i)).toBeInTheDocument();
|
|
57
82
|
});
|
|
58
83
|
});
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { fireEvent, render, screen } from "@testing-library/vue";
|
|
1
|
+
import { fireEvent, render, screen, waitFor } from "@testing-library/vue";
|
|
2
|
+
import { it, vi } from "vitest";
|
|
3
|
+
|
|
2
4
|
import Counter from "../../../src/framework/vue/Counter.vue";
|
|
3
5
|
|
|
4
6
|
describe("Counter", () => {
|
|
@@ -7,15 +9,34 @@ describe("Counter", () => {
|
|
|
7
9
|
showMessage: "mockFunction",
|
|
8
10
|
};
|
|
9
11
|
|
|
12
|
+
let capturedListener: ((val: string) => void) | undefined;
|
|
13
|
+
let storeValue = "Mocked Nano Value";
|
|
14
|
+
|
|
10
15
|
beforeEach(() => {
|
|
11
16
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
-
(
|
|
17
|
+
(window as any).mockFunction = vi.fn();
|
|
18
|
+
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
|
+
(window as any).Stores = {
|
|
21
|
+
vueStore: {
|
|
22
|
+
get: vi.fn(() => storeValue),
|
|
23
|
+
subscribe: vi.fn((callback) => {
|
|
24
|
+
capturedListener = callback;
|
|
25
|
+
callback(storeValue);
|
|
26
|
+
return () => {};
|
|
27
|
+
}),
|
|
28
|
+
},
|
|
29
|
+
};
|
|
13
30
|
});
|
|
14
31
|
|
|
15
32
|
afterEach(() => {
|
|
16
33
|
vi.clearAllMocks();
|
|
17
34
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
-
delete (
|
|
35
|
+
delete (window as any).mockFunction;
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
37
|
+
delete (window as any).Stores;
|
|
38
|
+
capturedListener = undefined;
|
|
39
|
+
storeValue = "Mocked Nano Value";
|
|
19
40
|
});
|
|
20
41
|
|
|
21
42
|
it("renders the initial count", () => {
|
|
@@ -88,6 +109,23 @@ describe("Counter", () => {
|
|
|
88
109
|
|
|
89
110
|
await fireEvent.click(screen.getByRole("button", { name: "Send value" }));
|
|
90
111
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
91
|
-
expect((
|
|
112
|
+
expect((window as any).mockFunction).toHaveBeenCalledWith(5);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("updates the component when the nanostore value changes", async () => {
|
|
116
|
+
render(Counter, {
|
|
117
|
+
props: defaultProps,
|
|
118
|
+
slots: {
|
|
119
|
+
default: "<div><p>Test Children</p></div>",
|
|
120
|
+
header: "<div>Test Header</div>",
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
expect(screen.getByText(/Mocked Nano Value/i)).toBeInTheDocument();
|
|
125
|
+
await waitFor(async () => {
|
|
126
|
+
storeValue = "Updated Nano Value";
|
|
127
|
+
capturedListener?.("Updated Nano Value");
|
|
128
|
+
});
|
|
129
|
+
expect(await screen.findByText(/Updated Nano Value/i)).toBeInTheDocument();
|
|
92
130
|
});
|
|
93
131
|
});
|