create-outsystems-astro 0.7.2 → 0.8.1
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 +1 -0
- package/bin/cli.js +10 -1
- package/package.json +1 -1
- package/template/.github/workflows/test.yml +13 -13
- package/template/.prettierrc +1 -1
- package/template/AGENTS.md +74 -2
- package/template/astro.config.mjs +5 -0
- package/template/bun.lock +645 -190
- package/template/deno.json +1 -17
- package/template/deno.lock +902 -461
- package/template/eslint.config.mjs +5 -0
- package/template/package-lock.json +9370 -5570
- package/template/package.json +50 -89
- package/template/pnpm-lock.yaml +1627 -740
- package/template/src/framework/solid/Demo.tsx +85 -0
- package/template/src/framework/solid/Store.tsx +31 -0
- package/template/src/images/solid.png +0 -0
- package/template/src/pages/multi/store.astro +3 -1
- package/template/src/pages/solid/solid-demo.astro +65 -0
- package/template/src/stores/framework.ts +1 -0
- package/template/test/e2e/solid/solid-demo.spec.ts +42 -0
- package/template/test/integration/solid/Demo.test.tsx +90 -0
- package/template/vitest.config.ts +12 -0
- package/template/yarn.lock +958 -392
- /package/template/patches/{@angular+build+21.2.2.patch → @angular+build+21.2.5.patch} +0 -0
- /package/template/test/e2e/angular/{angular-counter.spec.ts → angular-demo.spec.ts} +0 -0
- /package/template/test/e2e/preact/{preact-counter.spec.ts → preact-demo.spec.ts} +0 -0
- /package/template/test/e2e/react/{react-counter.spec.ts → react-demo.spec.ts} +0 -0
- /package/template/test/e2e/svelte/{svelte-counter.spec.ts → svelte-demo.spec.ts} +0 -0
- /package/template/test/e2e/vue/{vue-counter.spec.ts → vue-demo.spec.ts} +0 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/** @jsxImportSource solid-js */
|
|
2
|
+
import { useStore } from "@nanostores/solid";
|
|
3
|
+
import { createSignal, type JSX } from "solid-js";
|
|
4
|
+
|
|
5
|
+
import AstroLogo from "../../images/astro.png?url";
|
|
6
|
+
import OutSystemsLogo from "../../images/outsystems.png?url";
|
|
7
|
+
import { Operation, setCounterCount } from "../../lib/setCounterCount";
|
|
8
|
+
import { setupStore } from "../../stores/demo";
|
|
9
|
+
|
|
10
|
+
interface DemoProps {
|
|
11
|
+
children?: JSX.Element;
|
|
12
|
+
header?: JSX.Element;
|
|
13
|
+
initialCount: number;
|
|
14
|
+
showMessage: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default function Demo(props: DemoProps) {
|
|
18
|
+
const [count, setCount] = createSignal(props.initialCount);
|
|
19
|
+
|
|
20
|
+
const store = setupStore("solidStore");
|
|
21
|
+
const nanoStoreValue = useStore(store);
|
|
22
|
+
|
|
23
|
+
const add = () => setCount((i) => setCounterCount(i, Operation.Add));
|
|
24
|
+
const subtract = () =>
|
|
25
|
+
setCount((i) => setCounterCount(i, Operation.Subtract));
|
|
26
|
+
|
|
27
|
+
const showParentMessage = () => {
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
|
+
const messageFunc = (window as any)[props.showMessage];
|
|
30
|
+
if (typeof messageFunc === "function") {
|
|
31
|
+
messageFunc(count());
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<>
|
|
37
|
+
{props.header}
|
|
38
|
+
|
|
39
|
+
<div class="card-grid">
|
|
40
|
+
<div class="card">
|
|
41
|
+
<strong>Solid counter component</strong>
|
|
42
|
+
<div class="card-content">
|
|
43
|
+
Internal counter controls. It keeps state within the component.
|
|
44
|
+
<div class="counter-controls">
|
|
45
|
+
<button onClick={subtract}>-</button>
|
|
46
|
+
<pre>{count()}</pre>
|
|
47
|
+
<button onClick={add}>+</button>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
The button sends the current count value to a function in the parent
|
|
51
|
+
component.
|
|
52
|
+
<div class="card-content">
|
|
53
|
+
<div>
|
|
54
|
+
<button class="card-btn" onClick={showParentMessage}>
|
|
55
|
+
Send value
|
|
56
|
+
</button>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<div class="card">
|
|
62
|
+
<strong>Nano Stores</strong>
|
|
63
|
+
<div class="card-content">
|
|
64
|
+
<div>
|
|
65
|
+
<strong>Value:</strong>
|
|
66
|
+
<div id="nanostore">{nanoStoreValue()}</div>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<div class="card">
|
|
72
|
+
<strong>Slot content</strong>
|
|
73
|
+
<div class="card-content">
|
|
74
|
+
<div>{props.children}</div>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<div class="counter-logos">
|
|
80
|
+
<img alt="OutSystems logo" src={OutSystemsLogo} />
|
|
81
|
+
<img alt="Astro logo" src={AstroLogo} />
|
|
82
|
+
</div>
|
|
83
|
+
</>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** @jsxImportSource solid-js */
|
|
2
|
+
import { useStore } from "@nanostores/solid";
|
|
3
|
+
|
|
4
|
+
import SolidLogo from "../../images/solid.png?url";
|
|
5
|
+
import { framework } from "../../stores/framework";
|
|
6
|
+
|
|
7
|
+
export default function Store() {
|
|
8
|
+
const selectedFramework = useStore(framework);
|
|
9
|
+
|
|
10
|
+
const setFramework = () => {
|
|
11
|
+
framework.set("Solid");
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<div class="card">
|
|
16
|
+
<strong>Solid Store</strong>
|
|
17
|
+
<div class="card-content">
|
|
18
|
+
<img alt="Solid logo" height={150} src={SolidLogo} />
|
|
19
|
+
<div>
|
|
20
|
+
<strong>Value:</strong>
|
|
21
|
+
<div id="nanostore">{selectedFramework()}</div>
|
|
22
|
+
</div>
|
|
23
|
+
<div>
|
|
24
|
+
<button class="card-btn" onClick={setFramework}>
|
|
25
|
+
Select React
|
|
26
|
+
</button>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
Binary file
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import AngularStore from "../../framework/angular/Store.component"
|
|
3
3
|
import PreactStore from "../../framework/preact/Store";
|
|
4
4
|
import ReactStore from "../../framework/react/Store";
|
|
5
|
+
import SolidStore from "../../framework/solid/Store";
|
|
5
6
|
import SvelteStore from "../../framework/svelte/Store.svelte";
|
|
6
7
|
import VueStore from "../../framework/vue/Store.vue";
|
|
7
8
|
import styles from "../../styles/index.css?url";
|
|
@@ -12,9 +13,10 @@ import styles from "../../styles/index.css?url";
|
|
|
12
13
|
</head>
|
|
13
14
|
<body>
|
|
14
15
|
<div class="card-grid">
|
|
15
|
-
<AngularStore client:
|
|
16
|
+
<AngularStore client:load />
|
|
16
17
|
<PreactStore client:only="preact" />
|
|
17
18
|
<ReactStore client:only="react" />
|
|
19
|
+
<SolidStore client:only="solid-js" />
|
|
18
20
|
<SvelteStore client:only="svelte" />
|
|
19
21
|
<VueStore client:only="vue" />
|
|
20
22
|
</div>
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
import DemoComponent from "../../framework/solid/Demo";
|
|
3
|
+
import styles from "../../styles/index.css?url";
|
|
4
|
+
const initialCount = 5;
|
|
5
|
+
const showMessage = "showMessage";
|
|
6
|
+
---
|
|
7
|
+
<html lang="en">
|
|
8
|
+
<head>
|
|
9
|
+
<link href={styles} rel="stylesheet" />
|
|
10
|
+
<script>
|
|
11
|
+
import { setupStore } from "../../stores/demo";
|
|
12
|
+
setupStore("solidStore");
|
|
13
|
+
window["showMessage"] = (count) => {
|
|
14
|
+
document.getElementById("counter").textContent = count;
|
|
15
|
+
};
|
|
16
|
+
document.addEventListener("DOMContentLoaded", function () {
|
|
17
|
+
const input = document.getElementById("store");
|
|
18
|
+
input.value = window.Stores["solidStore"].get();
|
|
19
|
+
});
|
|
20
|
+
</script>
|
|
21
|
+
</head>
|
|
22
|
+
<body>
|
|
23
|
+
<div class="counter-title">Astro Page</div>
|
|
24
|
+
<div class="card-grid">
|
|
25
|
+
<div class="card">
|
|
26
|
+
<strong>Counter component</strong>
|
|
27
|
+
<div class="card-content">
|
|
28
|
+
<div style="text-align: center; margin-top: 30px;">
|
|
29
|
+
Counter value:
|
|
30
|
+
<div>
|
|
31
|
+
<span id="counter"></span>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
<div class="card">
|
|
37
|
+
<strong>Nano Stores</strong>
|
|
38
|
+
<div class="card-content">
|
|
39
|
+
<div style="text-align: center; margin-top: 30px;">
|
|
40
|
+
<input
|
|
41
|
+
id="store"
|
|
42
|
+
placeholder="Type something..."
|
|
43
|
+
type="text"
|
|
44
|
+
/><button
|
|
45
|
+
class="card-btn"
|
|
46
|
+
onclick="window.Stores['solidStore'].set(document.getElementById('store').value)"
|
|
47
|
+
>Update Store</button
|
|
48
|
+
>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
<hr />
|
|
54
|
+
<DemoComponent
|
|
55
|
+
client:only="solid-js"
|
|
56
|
+
initialCount={initialCount}
|
|
57
|
+
showMessage={showMessage}
|
|
58
|
+
>
|
|
59
|
+
<div class="counter-title" slot="header">Solid Demo Component</div>
|
|
60
|
+
<div style="text-align: center;">
|
|
61
|
+
<p><em>This is content passed into the component.</em></p>
|
|
62
|
+
</div>
|
|
63
|
+
</DemoComponent>
|
|
64
|
+
</body>
|
|
65
|
+
</html>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { expect, test } from "@playwright/test";
|
|
2
|
+
|
|
3
|
+
test.beforeEach(async ({ page }) => {
|
|
4
|
+
await page.goto("/solid/solid-demo");
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
test.describe("Has values", () => {
|
|
8
|
+
test("Should have header", async ({ page }) => {
|
|
9
|
+
await expect(page.getByText("Solid Demo Component")).toBeVisible();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test("Should have slot content", async ({ page }) => {
|
|
13
|
+
await expect(
|
|
14
|
+
page.getByText("This is content passed into the component"),
|
|
15
|
+
).toBeVisible();
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test.describe("Change counter", () => {
|
|
20
|
+
test("Should increment counter when clicking + button", async ({ page }) => {
|
|
21
|
+
await page.getByRole("button", { name: "+" }).click();
|
|
22
|
+
await expect(page.locator("pre")).toContainText("6");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test("Should decrement counter when clicking - button", async ({ page }) => {
|
|
26
|
+
await page.getByRole("button", { name: "-" }).click();
|
|
27
|
+
await expect(page.locator("pre")).toContainText("4");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("Should show message on Send value", async ({ page }) => {
|
|
31
|
+
await page.getByRole("button", { name: "Send value" }).click();
|
|
32
|
+
await expect(page.locator("span#counter")).toContainText("5");
|
|
33
|
+
});
|
|
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
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/** @jsxImportSource solid-js */
|
|
2
|
+
import { cleanup, fireEvent, render, screen } from "@solidjs/testing-library";
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
|
+
|
|
5
|
+
import Demo from "../../../src/framework/solid/Demo";
|
|
6
|
+
|
|
7
|
+
describe("Demo", () => {
|
|
8
|
+
const defaultProps = {
|
|
9
|
+
children: <div>Test Children</div>,
|
|
10
|
+
header: <h1>Test Header</h1>,
|
|
11
|
+
initialCount: 5,
|
|
12
|
+
showMessage: "mockFunction",
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
let capturedListener: ((val: string) => void) | undefined;
|
|
16
|
+
let storeValue = "Mocked Nano Value";
|
|
17
|
+
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
|
+
(window as any).mockFunction = vi.fn();
|
|
21
|
+
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
|
+
(window as any).Stores = {
|
|
24
|
+
solidStore: {
|
|
25
|
+
get: vi.fn(() => storeValue),
|
|
26
|
+
listen: vi.fn((callback) => {
|
|
27
|
+
capturedListener = callback;
|
|
28
|
+
callback(storeValue);
|
|
29
|
+
return () => {};
|
|
30
|
+
}),
|
|
31
|
+
subscribe: vi.fn((callback) => {
|
|
32
|
+
capturedListener = callback;
|
|
33
|
+
callback(storeValue);
|
|
34
|
+
return () => {};
|
|
35
|
+
}),
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
afterEach(() => {
|
|
41
|
+
cleanup();
|
|
42
|
+
vi.clearAllMocks();
|
|
43
|
+
capturedListener = undefined;
|
|
44
|
+
storeValue = "Mocked Nano Value";
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("renders the initial count", () => {
|
|
48
|
+
render(() => <Demo {...defaultProps} />);
|
|
49
|
+
expect(screen.getByText("5")).toBeInTheDocument();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("renders header", () => {
|
|
53
|
+
render(() => <Demo {...defaultProps} />);
|
|
54
|
+
expect(screen.getByText("Test Header")).toBeInTheDocument();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("renders children", () => {
|
|
58
|
+
render(() => <Demo {...defaultProps} />);
|
|
59
|
+
expect(screen.getByText("Test Children")).toBeInTheDocument();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("increments count when add button is clicked", () => {
|
|
63
|
+
render(() => <Demo {...defaultProps} />);
|
|
64
|
+
fireEvent.click(screen.getByRole("button", { name: "+" }));
|
|
65
|
+
expect(screen.getByText("6")).toBeInTheDocument();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("decrements count when subtract button is clicked", () => {
|
|
69
|
+
render(() => <Demo {...defaultProps} />);
|
|
70
|
+
fireEvent.click(screen.getByRole("button", { name: "-" }));
|
|
71
|
+
expect(screen.getByText("4")).toBeInTheDocument();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("calls the show message function", () => {
|
|
75
|
+
render(() => <Demo {...defaultProps} />);
|
|
76
|
+
fireEvent.click(screen.getByRole("button", { name: "Send value" }));
|
|
77
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
78
|
+
expect((window as any).mockFunction).toHaveBeenCalledWith(5);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("updates the component when the nanostore value changes", async () => {
|
|
82
|
+
render(() => <Demo {...defaultProps} />);
|
|
83
|
+
expect(screen.getByText(/Mocked Nano Value/i)).toBeInTheDocument();
|
|
84
|
+
|
|
85
|
+
storeValue = "Updated Nano Value";
|
|
86
|
+
capturedListener?.("Updated Nano Value");
|
|
87
|
+
|
|
88
|
+
expect(await screen.findByText(/Updated Nano Value/i)).toBeInTheDocument();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -4,6 +4,7 @@ import preact from "@preact/preset-vite";
|
|
|
4
4
|
import { svelte } from "@sveltejs/vite-plugin-svelte";
|
|
5
5
|
import react from "@vitejs/plugin-react";
|
|
6
6
|
import vue from "@vitejs/plugin-vue";
|
|
7
|
+
import solid from "vite-plugin-solid";
|
|
7
8
|
import { defineConfig } from "vitest/config";
|
|
8
9
|
|
|
9
10
|
export default defineConfig(({ mode }) => ({
|
|
@@ -43,6 +44,17 @@ export default defineConfig(({ mode }) => ({
|
|
|
43
44
|
setupFiles: ["test/setup-test-env.ts"],
|
|
44
45
|
},
|
|
45
46
|
},
|
|
47
|
+
{
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
49
|
+
plugins: [solid() as any],
|
|
50
|
+
test: {
|
|
51
|
+
environment: "happy-dom",
|
|
52
|
+
globals: true,
|
|
53
|
+
include: ["test/integration/solid/**/*.test.tsx"],
|
|
54
|
+
name: "solid",
|
|
55
|
+
setupFiles: ["test/setup-test-env.ts"],
|
|
56
|
+
},
|
|
57
|
+
},
|
|
46
58
|
{
|
|
47
59
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
48
60
|
plugins: [svelte() as any],
|