create-outsystems-astro 0.4.2 → 0.6.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 (39) hide show
  1. package/README.md +5 -0
  2. package/bin/cli.js +6 -1
  3. package/package.json +1 -1
  4. package/template/.prettierignore +4 -1
  5. package/template/.prettierrc +4 -0
  6. package/template/AGENTS.md +104 -15
  7. package/template/astro.config.mjs +2 -0
  8. package/template/bun.lock +621 -656
  9. package/template/deno.json +1 -5
  10. package/template/deno.lock +1303 -977
  11. package/template/eslint.config.mjs +19 -0
  12. package/template/output.ts +14 -2
  13. package/template/package-lock.json +3949 -4042
  14. package/template/package.json +62 -58
  15. package/template/pnpm-lock.yaml +2431 -1927
  16. package/template/pnpm-workspace.yaml +6 -0
  17. package/template/src/framework/angular/Counter.component.ts +25 -13
  18. package/template/src/framework/react/Counter.tsx +41 -9
  19. package/template/src/framework/svelte/Counter.svelte +77 -0
  20. package/template/src/framework/vue/Counter.vue +49 -14
  21. package/template/src/pages/angular/angular-counter.astro +30 -10
  22. package/template/src/pages/react/react-counter.astro +58 -16
  23. package/template/src/pages/svelte/svelte-counter.astro +63 -0
  24. package/template/src/pages/vue/vue-counter.astro +61 -15
  25. package/template/src/stores/.gitkeep +0 -0
  26. package/template/src/styles/index.css +65 -0
  27. package/template/svelte.config.js +5 -0
  28. package/template/test/e2e/react/react-counter.spec.ts +12 -2
  29. package/template/test/e2e/svelte/svelte-counter.spec.ts +42 -0
  30. package/template/test/e2e/vue/vue-counter.spec.ts +12 -2
  31. package/template/test/integration/angular/Counter.component.spec.ts +1 -1
  32. package/template/test/integration/react/Counter.test.tsx +35 -10
  33. package/template/test/integration/svelte/Counter.test.ts +81 -0
  34. package/template/test/integration/svelte/SlotCounter.wrapper.svelte +27 -0
  35. package/template/test/integration/vue/Counter.test.ts +42 -4
  36. package/template/vitest.config.ts +17 -2
  37. package/template/yarn.lock +3656 -2059
  38. /package/template/patches/{@analogjs+astro-angular+2.2.2.patch → @analogjs+astro-angular+2.3.0.patch} +0 -0
  39. /package/template/patches/{@angular+build+21.1.0.patch → @angular+build+21.2.0.patch} +0 -0
@@ -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(page.getByText("Slot content")).toBeVisible();
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
+ });
@@ -0,0 +1,42 @@
1
+ import { expect, test } from "@playwright/test";
2
+
3
+ test.beforeEach(async ({ page }) => {
4
+ await page.goto("/svelte/svelte-counter");
5
+ });
6
+
7
+ test.describe("Has values", () => {
8
+ test("Should have header", async ({ page }) => {
9
+ await expect(page.getByText("Counter 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
+ });
@@ -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(page.getByText("Slot content")).toBeVisible();
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
- (document as any).mockFunction = vi.fn();
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
- const addButton = screen.getByRole("button", { name: "+" });
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
- const subtractButton = screen.getByRole("button", { name: "-" });
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
- const sendButton = screen.getByRole("button", { name: "Send value" });
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((document as any).mockFunction).toHaveBeenCalledWith(5);
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
  });
@@ -0,0 +1,81 @@
1
+ import { act, fireEvent, render, screen } from "@testing-library/svelte";
2
+ import { writable } from "svelte/store";
3
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
4
+ import Counter from "../../../src/framework/svelte/Counter.svelte";
5
+ import SlotCounter from "./SlotCounter.wrapper.svelte";
6
+
7
+ describe("Counter.svelte", () => {
8
+ const defaultProps = {
9
+ initialCount: 5,
10
+ showMessage: "mockFunction",
11
+ };
12
+
13
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
+ let mockStore: any;
15
+
16
+ beforeEach(() => {
17
+ mockStore = writable("Mocked Nano Value");
18
+
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
+ svelteStore: mockStore,
25
+ };
26
+ });
27
+
28
+ afterEach(() => {
29
+ vi.clearAllMocks();
30
+ });
31
+
32
+ it("renders the initial count", () => {
33
+ render(Counter, { props: defaultProps });
34
+ expect(screen.getByText("5")).toBeInTheDocument();
35
+ });
36
+
37
+ it("renders slots (header and default)", () => {
38
+ render(SlotCounter);
39
+
40
+ expect(screen.getByText("Test Header")).toBeInTheDocument();
41
+ expect(screen.getByText("Test Children")).toBeInTheDocument();
42
+ });
43
+
44
+ it("increments count when add button is clicked", async () => {
45
+ render(Counter, { props: defaultProps });
46
+ const addButton = screen.getByRole("button", { name: "+" });
47
+
48
+ await fireEvent.click(addButton);
49
+ expect(screen.getByText("6")).toBeInTheDocument();
50
+ });
51
+
52
+ it("decrements count when subtract button is clicked", async () => {
53
+ render(Counter, { props: defaultProps });
54
+ const subtractButton = screen.getByRole("button", { name: "-" });
55
+
56
+ await fireEvent.click(subtractButton);
57
+ expect(screen.getByText("4")).toBeInTheDocument();
58
+ });
59
+
60
+ it("calls the show message function", async () => {
61
+ render(Counter, { props: defaultProps });
62
+ const sendButton = screen.getByRole("button", { name: "Send value" });
63
+
64
+ await fireEvent.click(sendButton);
65
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
+ expect((window as any).mockFunction).toHaveBeenCalledWith(5);
67
+ });
68
+
69
+ it("updates the component when the nanostore value changes", async () => {
70
+ render(Counter, { props: defaultProps });
71
+
72
+ expect(screen.getByText(/Mocked Nano Value/i)).toBeInTheDocument();
73
+
74
+ // Update the Svelte store
75
+ await act(() => {
76
+ mockStore.set("Updated Nano Value");
77
+ });
78
+
79
+ expect(screen.getByText(/Updated Nano Value/i)).toBeInTheDocument();
80
+ });
81
+ });
@@ -0,0 +1,27 @@
1
+ <script lang="ts">
2
+ import { vi } from "vitest";
3
+
4
+ import Counter from "../../../src/framework/svelte/Counter.svelte";
5
+
6
+ export let initialCount = 5;
7
+ export let showMessage = "mockFn";
8
+
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
+ (window as any)[showMessage] = vi.fn();
11
+
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
+ (window as any).Stores = {
14
+ svelteStore: {
15
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
16
+ subscribe: (fn: any) => {
17
+ fn("test-store-value");
18
+ return () => {};
19
+ },
20
+ },
21
+ };
22
+ </script>
23
+
24
+ <Counter {initialCount} {showMessage}>
25
+ <h1 slot="header">Test Header</h1>
26
+ <div>Test Children</div>
27
+ </Counter>
@@ -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
- (document as any).mockFunction = vi.fn();
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 (document as any).mockFunction;
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((document as any).mockFunction).toHaveBeenCalledWith(5);
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
  });
@@ -1,10 +1,11 @@
1
1
  /// <reference types="vitest" />
2
2
  import angular from "@analogjs/vite-plugin-angular";
3
+ import { svelte } from "@sveltejs/vite-plugin-svelte";
3
4
  import react from "@vitejs/plugin-react";
4
5
  import vue from "@vitejs/plugin-vue";
5
6
  import { defineConfig } from "vitest/config";
6
7
 
7
- export default defineConfig({
8
+ export default defineConfig(({ mode }) => ({
8
9
  test: {
9
10
  projects: [
10
11
  {
@@ -30,6 +31,20 @@ export default defineConfig({
30
31
  setupFiles: ["test/setup-test-env.ts"],
31
32
  },
32
33
  },
34
+ {
35
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
+ plugins: [svelte() as any],
37
+ resolve: {
38
+ conditions: mode === "test" ? ["browser"] : [],
39
+ },
40
+ test: {
41
+ environment: "happy-dom",
42
+ globals: true,
43
+ include: ["test/integration/svelte/**/*.test.ts"],
44
+ name: "svelte",
45
+ setupFiles: ["test/setup-test-env.ts"],
46
+ },
47
+ },
33
48
  {
34
49
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
50
  plugins: [vue() as any],
@@ -53,4 +68,4 @@ export default defineConfig({
53
68
  ],
54
69
  reporters: ["default"],
55
70
  },
56
- });
71
+ }));