create-nube-app 0.1.0 → 0.2.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 (31) hide show
  1. package/package.json +27 -33
  2. package/templates/minimal/.vscode/extensions.json +8 -0
  3. package/templates/minimal/.vscode/settings.json +15 -0
  4. package/templates/minimal/README.md +21 -7
  5. package/templates/minimal/biome.json +12 -0
  6. package/templates/minimal/package.json +22 -11
  7. package/templates/minimal/src/main.test.ts +42 -0
  8. package/templates/minimal/src/main.ts +1 -1
  9. package/templates/minimal/tsconfig.json +9 -9
  10. package/templates/minimal/tsup.config.js +10 -10
  11. package/templates/minimal/vitest.config.ts +5 -0
  12. package/templates/minimal-ui/.vscode/extensions.json +8 -0
  13. package/templates/minimal-ui/.vscode/settings.json +15 -0
  14. package/templates/minimal-ui/README.md +21 -7
  15. package/templates/minimal-ui/biome.json +12 -0
  16. package/templates/minimal-ui/package.json +24 -15
  17. package/templates/minimal-ui/src/components/MyCustomField.test.ts +51 -0
  18. package/templates/minimal-ui/src/components/MyCustomField.ts +18 -0
  19. package/templates/minimal-ui/src/main.test.ts +52 -0
  20. package/templates/minimal-ui/src/main.ts +8 -24
  21. package/templates/minimal-ui/vitest.config.ts +5 -0
  22. package/templates/minimal-ui-jsx/.vscode/extensions.json +8 -0
  23. package/templates/minimal-ui-jsx/.vscode/settings.json +15 -0
  24. package/templates/minimal-ui-jsx/README.md +21 -8
  25. package/templates/minimal-ui-jsx/biome.json +12 -0
  26. package/templates/minimal-ui-jsx/package.json +15 -4
  27. package/templates/minimal-ui-jsx/src/components/MyCustomField.test.tsx +61 -0
  28. package/templates/minimal-ui-jsx/src/components/MyCustomField.tsx +17 -0
  29. package/templates/minimal-ui-jsx/src/main.test.tsx +52 -0
  30. package/templates/minimal-ui-jsx/src/main.tsx +8 -24
  31. package/templates/minimal-ui-jsx/vitest.config.ts +5 -0
package/package.json CHANGED
@@ -1,35 +1,29 @@
1
1
  {
2
- "name": "create-nube-app",
3
- "description": "Create Nube App",
4
- "author": "Tiendanube / Nuvemshop",
5
- "license": "MIT",
6
- "version": "0.1.0",
7
- "bin": {
8
- "create-nube-app": "dist/index.js"
9
- },
10
- "scripts": {
11
- "build": "tsup",
12
- "check": "biome check src/*",
13
- "check:fix": "biome check --write src/*"
14
- },
15
- "type": "module",
16
- "dependencies": {
17
- "@clack/prompts": "^0.10.0",
18
- "fs-extra": "^11.1.1"
19
- },
20
- "devDependencies": {
21
- "@biomejs/biome": "1.8.3",
22
- "@types/fs-extra": "^11.0.4",
23
- "@types/node": "^22.13.11",
24
- "@types/prompts": "^2.4.9",
25
- "tsup": "^8.4.0",
26
- "typescript": "^5.6.2"
27
- },
28
- "files": [
29
- "./dist",
30
- "README.md",
31
- "CHANGELOG.md",
32
- "LICENSE",
33
- "./templates"
34
- ]
2
+ "name": "create-nube-app",
3
+ "description": "Create Nube App",
4
+ "author": "Tiendanube / Nuvemshop",
5
+ "license": "MIT",
6
+ "version": "0.2.0",
7
+ "bin": {
8
+ "create-nube-app": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsup",
12
+ "check": "biome check src/*",
13
+ "check:fix": "biome check --write src/*"
14
+ },
15
+ "type": "module",
16
+ "dependencies": {
17
+ "@clack/prompts": "^0.10.0",
18
+ "fs-extra": "^11.1.1"
19
+ },
20
+ "devDependencies": {
21
+ "@biomejs/biome": "1.8.3",
22
+ "@types/fs-extra": "^11.0.4",
23
+ "@types/node": "^22.13.11",
24
+ "@types/prompts": "^2.4.9",
25
+ "tsup": "^8.4.0",
26
+ "typescript": "^5.6.2"
27
+ },
28
+ "files": ["./dist", "README.md", "CHANGELOG.md", "LICENSE", "./templates"]
35
29
  }
@@ -0,0 +1,8 @@
1
+ {
2
+ "recommendations": [
3
+ "biomejs.biome",
4
+ "vitest.explorer",
5
+ "ms-vscode.extension-test-runner",
6
+ "ambar.bundle-size"
7
+ ]
8
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "editor.formatOnSave": true,
3
+ "[javascript]": {
4
+ "editor.defaultFormatter": "biomejs.biome"
5
+ },
6
+ "[javascriptreact]": {
7
+ "editor.defaultFormatter": "biomejs.biome"
8
+ },
9
+ "[typescript]": {
10
+ "editor.defaultFormatter": "biomejs.biome"
11
+ },
12
+ "[typescriptreact]": {
13
+ "editor.defaultFormatter": "biomejs.biome"
14
+ },
15
+ }
@@ -1,11 +1,25 @@
1
- # Minimum setup for app development with NubeSDK
1
+ # Minimal App
2
2
 
3
- This project uses the type package in version `0.1.2-alpha` and `tsup` to compile typescript to javascript
3
+ This is a minimalist project using TypeScript and Tiendanube tools.
4
4
 
5
- # How to use
5
+ ## Available Scripts
6
6
 
7
- - install the development dependencies with the `npm install` command.
8
- - Then start the development changing the `src/main.ts` file.
9
- - To compile the project use the `npm run build` command.
7
+ ### Development
10
8
 
11
- The final script is created in the `dist` folder.
9
+ - `npm run dev` - Starts local development server
10
+ - `npm run build` - Builds the project using tsup
11
+ - `npm test` - Runs unit tests
12
+ - `npm run test:watch` - Runs tests in watch mode (automatically re-runs when changes are detected)
13
+ - `npm run test:coverage` - Runs tests and generates a coverage report
14
+
15
+ ### Code Quality
16
+
17
+ - `npm run format` - Formats all project files using Biome
18
+ - `npm run lint` - Runs linting on all project files using Biome
19
+
20
+ ## Technologies Used
21
+
22
+ - [TypeScript](https://www.typescriptlang.org/)
23
+ - [Vitest](https://vitest.dev/) for testing
24
+ - [Biome](https://biomejs.dev/) for formatting and linting
25
+ - [tsup](https://tsup.egoist.dev/) for building
@@ -0,0 +1,12 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
3
+ "organizeImports": {
4
+ "enabled": true
5
+ },
6
+ "linter": {
7
+ "enabled": true,
8
+ "rules": {
9
+ "recommended": true
10
+ }
11
+ }
12
+ }
@@ -1,13 +1,24 @@
1
1
  {
2
- "name": "minimal-app",
3
- "version": "1.0.2",
4
- "scripts": {
5
- "build": "tsup"
6
- },
7
- "author": "Tiendanube / Nuvemshop",
8
- "devDependencies": {
9
- "@tiendanube/nube-sdk-types": "0.4.0",
10
- "tsup": "^8.3.0",
11
- "typescript": "^5.6.2"
12
- }
2
+ "name": "template-minimal-app",
3
+ "version": "0.1.0",
4
+ "scripts": {
5
+ "dev": "concurrently -k -n BUILD,SERVE -c blue,green \"tsup --sourcemap inline --watch\" \"serve dist -l 8080 --cors\"",
6
+ "build": "tsup",
7
+ "test": "vitest run",
8
+ "test:watch": "vitest watch",
9
+ "test:coverage": "vitest run --coverage",
10
+ "format": "biome check --write ./src",
11
+ "lint": "biome check ./src"
12
+ },
13
+ "author": "Tiendanube / Nuvemshop",
14
+ "devDependencies": {
15
+ "@biomejs/biome": "^1.9.4",
16
+ "@tiendanube/nube-sdk-types": "0.4.0",
17
+ "@vitest/coverage-v8": "^3.0.9",
18
+ "concurrently": "^9.1.2",
19
+ "serve": "^14.2.4",
20
+ "tsup": "^8.3.0",
21
+ "typescript": "^5.6.2",
22
+ "vitest": "^3.0.9"
23
+ }
13
24
  }
@@ -0,0 +1,42 @@
1
+ import type { NubeSDK } from "@tiendanube/nube-sdk-types";
2
+ import { describe, expect, it, vi } from "vitest";
3
+ import { App } from "./main";
4
+
5
+ describe("App", () => {
6
+ it("should register cart:update event handler", () => {
7
+ // Mock NubeSDK
8
+ const mockNube: Partial<NubeSDK> = {
9
+ on: vi.fn(),
10
+ };
11
+
12
+ // Execute App function with mock
13
+ App(mockNube as NubeSDK);
14
+
15
+ // Verify if cart:update event was registered
16
+ expect(mockNube.on).toHaveBeenCalledWith(
17
+ "cart:update",
18
+ expect.any(Function),
19
+ );
20
+ });
21
+
22
+ it("should log cart data when cart:update event is triggered", () => {
23
+ // Mock console.log
24
+ const consoleSpy = vi.spyOn(console, "log");
25
+
26
+ // Mock NubeSDK
27
+ const mockNube: Partial<NubeSDK> = {
28
+ on: vi.fn((event, handler) => {
29
+ if (event === "cart:update") {
30
+ // Simulate event being triggered
31
+ handler({ cart: { id: "123", total: 100 } });
32
+ }
33
+ }),
34
+ };
35
+
36
+ // Execute App function with mock
37
+ App(mockNube as NubeSDK);
38
+
39
+ // Verify if console.log was called with cart data
40
+ expect(consoleSpy).toHaveBeenCalledWith({ id: "123", total: 100 });
41
+ });
42
+ });
@@ -2,6 +2,6 @@ import type { NubeSDK } from "@tiendanube/nube-sdk-types";
2
2
 
3
3
  export function App(nube: NubeSDK) {
4
4
  nube.on("cart:update", ({ cart }) => {
5
- console.log(cart);
5
+ console.log(cart, "cart");
6
6
  });
7
7
  }
@@ -1,10 +1,10 @@
1
1
  {
2
- "compilerOptions": {
3
- "target": "es2016",
4
- "module": "commonjs",
5
- "esModuleInterop": true,
6
- "forceConsistentCasingInFileNames": true,
7
- "strict": true,
8
- "skipLibCheck": true
9
- }
10
- }
2
+ "compilerOptions": {
3
+ "target": "es2016",
4
+ "module": "commonjs",
5
+ "esModuleInterop": true,
6
+ "forceConsistentCasingInFileNames": true,
7
+ "strict": true,
8
+ "skipLibCheck": true
9
+ }
10
+ }
@@ -1,14 +1,14 @@
1
1
  import { defineConfig } from "tsup";
2
2
 
3
3
  export default defineConfig({
4
- entry: ["./src/main.ts"],
5
- clean: true,
6
- format: ["esm"],
7
- dts: false,
8
- outDir: "./dist",
9
- minify: true,
10
- sourcemap: false,
11
- outExtension: ({ options }) => ({
12
- js: options.minify ? ".min.js" : ".js"
13
- })
4
+ entry: ["./src/main.ts"],
5
+ clean: true,
6
+ format: ["esm"],
7
+ dts: false,
8
+ outDir: "./dist",
9
+ minify: true,
10
+ sourcemap: false,
11
+ outExtension: ({ options }) => ({
12
+ js: options.minify ? ".min.js" : ".js",
13
+ }),
14
14
  });
@@ -0,0 +1,5 @@
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {},
5
+ });
@@ -0,0 +1,8 @@
1
+ {
2
+ "recommendations": [
3
+ "biomejs.biome",
4
+ "vitest.explorer",
5
+ "ms-vscode.extension-test-runner",
6
+ "ambar.bundle-size"
7
+ ]
8
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "editor.formatOnSave": true,
3
+ "[javascript]": {
4
+ "editor.defaultFormatter": "biomejs.biome"
5
+ },
6
+ "[javascriptreact]": {
7
+ "editor.defaultFormatter": "biomejs.biome"
8
+ },
9
+ "[typescript]": {
10
+ "editor.defaultFormatter": "biomejs.biome"
11
+ },
12
+ "[typescriptreact]": {
13
+ "editor.defaultFormatter": "biomejs.biome"
14
+ },
15
+ }
@@ -1,11 +1,25 @@
1
- # Minimum setup for app development with NubeSDK
1
+ # Minimal App with UI
2
2
 
3
- This project uses the type package in version `0.1.2-alpha` and `tsup` to compile typescript to javascript
3
+ This is a template project to develop custom apps for Tiendanube using declarative UI funcions
4
4
 
5
- # How to use
5
+ ## Available Scripts
6
6
 
7
- - install the development dependencies with the `npm install` command.
8
- - Then start the development changing the `src/main.ts` file.
9
- - To compile the project use the `npm run build` command.
7
+ ### Development
10
8
 
11
- The final script is created in the `dist` folder.
9
+ - `npm run dev` - Starts local development server
10
+ - `npm run build` - Builds the project using tsup
11
+ - `npm test` - Runs unit tests
12
+ - `npm run test:watch` - Runs tests in watch mode (automatically re-runs when changes are detected)
13
+ - `npm run test:coverage` - Runs tests and generates a coverage report
14
+
15
+ ### Code Quality
16
+
17
+ - `npm run format` - Formats all project files using Biome
18
+ - `npm run lint` - Runs linting on all project files using Biome
19
+
20
+ ## Technologies Used
21
+
22
+ - [TypeScript](https://www.typescriptlang.org/)
23
+ - [Vitest](https://vitest.dev/) for testing
24
+ - [Biome](https://biomejs.dev/) for formatting and linting
25
+ - [tsup](https://tsup.egoist.dev/) for building
@@ -0,0 +1,12 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
3
+ "organizeImports": {
4
+ "enabled": true
5
+ },
6
+ "linter": {
7
+ "enabled": true,
8
+ "rules": {
9
+ "recommended": true
10
+ }
11
+ }
12
+ }
@@ -1,17 +1,26 @@
1
1
  {
2
- "name": "minimal-ui-app",
3
- "version": "1.0.2",
4
- "type": "module",
5
- "scripts": {
6
- "build": "tsup"
7
- },
8
- "author": "Tiendanube / Nuvemshop",
9
- "dependencies": {
10
- "@tiendanube/nube-sdk-ui": "0.2.0"
11
- },
12
- "devDependencies": {
13
- "@tiendanube/nube-sdk-types": "0.4.0",
14
- "tsup": "^8.3.0",
15
- "typescript": "^5.6.2"
16
- }
2
+ "name": "template-minimal-ui-app",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "concurrently -k -n BUILD,SERVE -c blue,green \"tsup --sourcemap inline --watch\" \"serve dist -l 8080 --cors\"",
7
+ "build": "tsup",
8
+ "test": "vitest run",
9
+ "test:watch": "vitest watch",
10
+ "test:coverage": "vitest run --coverage",
11
+ "format": "biome check --write ./src",
12
+ "lint": "biome check ./src"
13
+ },
14
+ "author": "Tiendanube / Nuvemshop",
15
+ "devDependencies": {
16
+ "@biomejs/biome": "^1.9.4",
17
+ "@tiendanube/nube-sdk-ui": "0.2.0",
18
+ "@tiendanube/nube-sdk-types": "0.4.0",
19
+ "@vitest/coverage-v8": "^3.0.9",
20
+ "concurrently": "^9.1.2",
21
+ "serve": "^14.2.4",
22
+ "tsup": "^8.3.0",
23
+ "typescript": "^5.6.2",
24
+ "vitest": "^3.0.9"
25
+ }
17
26
  }
@@ -0,0 +1,51 @@
1
+ import type {
2
+ NubeComponent,
3
+ NubeComponentBox,
4
+ NubeComponentField,
5
+ NubeSDKState,
6
+ } from "@tiendanube/nube-sdk-types";
7
+ import { describe, expect, it, vi } from "vitest";
8
+ import { MyCustomField } from "./MyCustomField";
9
+
10
+ describe("MyCustomField", () => {
11
+ it("should render a Box with correct dimensions", () => {
12
+ const result = MyCustomField() as NubeComponentBox;
13
+
14
+ expect(result).toEqual({
15
+ type: "box",
16
+ width: 100,
17
+ height: 200,
18
+ children: expect.any(Array),
19
+ });
20
+ });
21
+
22
+ it("should render a Field component with correct props", () => {
23
+ const result = MyCustomField() as NubeComponentBox;
24
+ const children = result.children as NubeComponent[];
25
+ const field = children[0] as NubeComponentField;
26
+
27
+ expect(field).toEqual({
28
+ type: "field",
29
+ id: "my-custom-field",
30
+ label: "Name",
31
+ name: "Name",
32
+ onChange: expect.any(Function),
33
+ });
34
+ });
35
+
36
+ it("should log user input when field changes", () => {
37
+ const consoleSpy = vi.spyOn(console, "log");
38
+ const result = MyCustomField() as NubeComponentBox;
39
+ const children = result.children as NubeComponent[];
40
+ const field = children[0] as NubeComponentField;
41
+
42
+ // Simulate field change event
43
+ field.onChange?.({
44
+ type: "change",
45
+ state: {} as NubeSDKState,
46
+ value: "John Doe",
47
+ });
48
+
49
+ expect(consoleSpy).toHaveBeenCalledWith("User name: John Doe");
50
+ });
51
+ });
@@ -0,0 +1,18 @@
1
+ import { box, field } from "@tiendanube/nube-sdk-ui";
2
+
3
+ export function MyCustomField() {
4
+ return box({
5
+ width: 100,
6
+ height: 200,
7
+ children: [
8
+ field({
9
+ id: "my-custom-field",
10
+ label: "Name",
11
+ name: "Name",
12
+ onChange: (e) => {
13
+ console.log(`User name: ${e.value}`);
14
+ },
15
+ }),
16
+ ],
17
+ });
18
+ }
@@ -0,0 +1,52 @@
1
+ import type { NubeSDK, NubeSDKState } from "@tiendanube/nube-sdk-types";
2
+ import { describe, expect, it, vi } from "vitest";
3
+ import { App } from "./main";
4
+
5
+ // Mock do componente MyCustomField
6
+ vi.mock("./components/MyCustomField", () => ({
7
+ MyCustomField: vi.fn(() => ({
8
+ type: "box",
9
+ width: 100,
10
+ height: 100,
11
+ })),
12
+ }));
13
+
14
+ describe("App", () => {
15
+ it("should set MyCustomField component in after_line_items slot", () => {
16
+ // Mock NubeSDK
17
+ const mockNube: Partial<NubeSDK> = {
18
+ send: vi.fn(),
19
+ };
20
+
21
+ // Execute App function with mock
22
+ App(mockNube as NubeSDK);
23
+
24
+ // Verify if send was called with correct parameters
25
+ expect(mockNube.send).toHaveBeenCalledWith(
26
+ "ui:slot:set",
27
+ expect.any(Function),
28
+ );
29
+
30
+ // Get the slot setter function
31
+ const slotSetter = (mockNube.send as ReturnType<typeof vi.fn>).mock
32
+ .calls[0][1] as (state: NubeSDKState) => {
33
+ ui: { slots: { after_line_items: unknown } };
34
+ };
35
+
36
+ // Execute the slot setter function
37
+ const result = slotSetter({} as NubeSDKState);
38
+
39
+ // Verify if the slot was set with MyCustomField component
40
+ expect(result).toEqual({
41
+ ui: {
42
+ slots: {
43
+ after_line_items: expect.objectContaining({
44
+ type: "box",
45
+ width: 100,
46
+ height: 100,
47
+ }),
48
+ },
49
+ },
50
+ });
51
+ });
52
+ });
@@ -1,28 +1,12 @@
1
1
  import type { NubeSDK } from "@tiendanube/nube-sdk-types";
2
- import { box, field } from "@tiendanube/nube-sdk-ui";
2
+ import { MyCustomField } from "./components/MyCustomField";
3
3
 
4
4
  export function App(nube: NubeSDK) {
5
- nube.on("cart:update", ({ cart }) => {
6
- console.log(cart);
7
- });
8
-
9
- nube.send("ui:slot:set", () => ({
10
- ui: {
11
- slots: {
12
- after_line_items:
13
- box({
14
- width: 100, height: 200, children: [
15
- field({
16
- id: "myField",
17
- label: "Name",
18
- name: "Name",
19
- onChange: (e) => {
20
- console.log("User name: " + e.value)
21
- }
22
- })
23
- ]
24
- })
25
- }
26
- }
27
- }));
5
+ nube.send("ui:slot:set", () => ({
6
+ ui: {
7
+ slots: {
8
+ after_line_items: MyCustomField(),
9
+ },
10
+ },
11
+ }));
28
12
  }
@@ -0,0 +1,5 @@
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {},
5
+ });
@@ -0,0 +1,8 @@
1
+ {
2
+ "recommendations": [
3
+ "biomejs.biome",
4
+ "vitest.explorer",
5
+ "ms-vscode.extension-test-runner",
6
+ "ambar.bundle-size"
7
+ ]
8
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "editor.formatOnSave": true,
3
+ "[javascript]": {
4
+ "editor.defaultFormatter": "biomejs.biome"
5
+ },
6
+ "[javascriptreact]": {
7
+ "editor.defaultFormatter": "biomejs.biome"
8
+ },
9
+ "[typescript]": {
10
+ "editor.defaultFormatter": "biomejs.biome"
11
+ },
12
+ "[typescriptreact]": {
13
+ "editor.defaultFormatter": "biomejs.biome"
14
+ },
15
+ }
@@ -1,12 +1,25 @@
1
- # Minimum setup for UI app development with NubeSDK using JSX
1
+ # JSX App
2
2
 
3
- This project uses the type package in version `0.1.2-alpha` and `tsup` to compile typescript to javascript
3
+ This is a template project to develop custom apps for Tiendanube using JSX components
4
4
 
5
- # How to use
5
+ ## Available Scripts
6
6
 
7
- - install the development dependencies with the `npm install` command.
8
- - Then start the development changing the `src/main.tsx` file.
9
- - To compile the project use the `npm run build` command.
10
- - The contents of the `src/jsx` is required for JSX support, in the future we will provide a new `npm` package with the JSX support embedded.
7
+ ### Development
11
8
 
12
- The final script is created in the `dist` folder.
9
+ - `npm run dev` - Starts local development server
10
+ - `npm run build` - Builds the project using tsup
11
+ - `npm test` - Runs unit tests
12
+ - `npm run test:watch` - Runs tests in watch mode (automatically re-runs when changes are detected)
13
+ - `npm run test:coverage` - Runs tests and generates a coverage report
14
+
15
+ ### Code Quality
16
+
17
+ - `npm run format` - Formats all project files using Biome
18
+ - `npm run lint` - Runs linting on all project files using Biome
19
+
20
+ ## Technologies Used
21
+
22
+ - [TypeScript](https://www.typescriptlang.org/)
23
+ - [Vitest](https://vitest.dev/) for testing
24
+ - [Biome](https://biomejs.dev/) for formatting and linting
25
+ - [tsup](https://tsup.egoist.dev/) for building
@@ -0,0 +1,12 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
3
+ "organizeImports": {
4
+ "enabled": true
5
+ },
6
+ "linter": {
7
+ "enabled": true,
8
+ "rules": {
9
+ "recommended": true
10
+ }
11
+ }
12
+ }
@@ -1,16 +1,27 @@
1
1
  {
2
- "name": "minimal-jsx-app",
3
- "version": "1.0.2",
2
+ "name": "template-minimal-jsx-app",
3
+ "version": "0.1.0",
4
4
  "type": "module",
5
5
  "scripts": {
6
- "build": "tsup"
6
+ "dev": "concurrently -k -n BUILD,SERVE -c blue,green \"tsup --sourcemap inline --watch\" \"serve dist -l 8080 --cors\"",
7
+ "build": "tsup",
8
+ "test": "vitest run",
9
+ "test:watch": "vitest watch",
10
+ "test:coverage": "vitest run --coverage",
11
+ "format": "biome check --write ./src",
12
+ "lint": "biome check ./src"
7
13
  },
8
14
  "author": "Tiendanube / Nuvemshop",
9
15
  "devDependencies": {
16
+ "@biomejs/biome": "^1.9.4",
10
17
  "@tiendanube/nube-sdk-ui": "0.2.0",
11
18
  "@tiendanube/nube-sdk-jsx": "0.2.1",
12
19
  "@tiendanube/nube-sdk-types": "0.4.0",
20
+ "@vitest/coverage-v8": "^3.0.9",
21
+ "concurrently": "^9.1.2",
22
+ "serve": "^14.2.4",
13
23
  "tsup": "^8.3.0",
14
- "typescript": "^5.6.2"
24
+ "typescript": "^5.6.2",
25
+ "vitest": "^3.0.9"
15
26
  }
16
27
  }
@@ -0,0 +1,61 @@
1
+ import type {
2
+ NubeComponent,
3
+ NubeComponentBox,
4
+ NubeComponentField,
5
+ NubeSDKState,
6
+ } from "@tiendanube/nube-sdk-types";
7
+ import { describe, expect, it, vi } from "vitest";
8
+ import { MyCustomField } from "./MyCustomField";
9
+
10
+ describe("MyCustomField", () => {
11
+ it("should render a Box with correct dimensions", () => {
12
+ const result = MyCustomField() as NubeComponentBox;
13
+
14
+ expect(result).toEqual({
15
+ type: "box",
16
+ width: 100,
17
+ height: 200,
18
+ children: expect.any(Array),
19
+ });
20
+ });
21
+
22
+ it("should render a Text component with correct content", () => {
23
+ const result = MyCustomField() as NubeComponentBox;
24
+ const children = result.children as NubeComponent[];
25
+
26
+ expect(children[0]).toEqual({
27
+ type: "txt",
28
+ children: "Hello!!",
29
+ });
30
+ });
31
+
32
+ it("should render a Field component with correct props", () => {
33
+ const result = MyCustomField() as NubeComponentBox;
34
+ const children = result.children as NubeComponent[];
35
+ const field = children[1] as NubeComponentField;
36
+
37
+ expect(field).toEqual({
38
+ type: "field",
39
+ id: "my-custom-field",
40
+ label: "Name",
41
+ name: "Name",
42
+ onChange: expect.any(Function),
43
+ });
44
+ });
45
+
46
+ it("should log user input when field changes", () => {
47
+ const consoleSpy = vi.spyOn(console, "log");
48
+ const result = MyCustomField() as NubeComponentBox;
49
+ const children = result.children as NubeComponent[];
50
+ const field = children[1] as NubeComponentField;
51
+
52
+ // Simulate field change event
53
+ field.onChange?.({
54
+ type: "change",
55
+ state: {} as NubeSDKState,
56
+ value: "John Doe",
57
+ });
58
+
59
+ expect(consoleSpy).toHaveBeenCalledWith("User name: John Doe");
60
+ });
61
+ });
@@ -0,0 +1,17 @@
1
+ import { Box, Field, Txt } from "@tiendanube/nube-sdk-jsx";
2
+
3
+ export function MyCustomField() {
4
+ return (
5
+ <Box width={100} height={200}>
6
+ <Txt>Hello!!</Txt>
7
+ <Field
8
+ id="my-custom-field"
9
+ label="Name"
10
+ name="Name"
11
+ onChange={(e) => {
12
+ console.log(`User name: ${e.value}`);
13
+ }}
14
+ />
15
+ </Box>
16
+ );
17
+ }
@@ -0,0 +1,52 @@
1
+ import type { NubeSDK, NubeSDKState } from "@tiendanube/nube-sdk-types";
2
+ import { describe, expect, it, vi } from "vitest";
3
+ import { App } from "./main";
4
+
5
+ // Mock do componente MyCustomField
6
+ vi.mock("./components/MyCustomField", () => ({
7
+ MyCustomField: vi.fn(() => ({
8
+ type: "box",
9
+ width: 100,
10
+ height: 100,
11
+ })),
12
+ }));
13
+
14
+ describe("App", () => {
15
+ it("should set MyCustomField component in after_line_items slot", () => {
16
+ // Mock NubeSDK
17
+ const mockNube: Partial<NubeSDK> = {
18
+ send: vi.fn(),
19
+ };
20
+
21
+ // Execute App function with mock
22
+ App(mockNube as NubeSDK);
23
+
24
+ // Verify if send was called with correct parameters
25
+ expect(mockNube.send).toHaveBeenCalledWith(
26
+ "ui:slot:set",
27
+ expect.any(Function),
28
+ );
29
+
30
+ // Get the slot setter function
31
+ const slotSetter = (mockNube.send as ReturnType<typeof vi.fn>).mock
32
+ .calls[0][1] as (state: NubeSDKState) => {
33
+ ui: { slots: { after_line_items: unknown } };
34
+ };
35
+
36
+ // Execute the slot setter function
37
+ const result = slotSetter({} as NubeSDKState);
38
+
39
+ // Verify if the slot was set with MyCustomField component
40
+ expect(result).toEqual({
41
+ ui: {
42
+ slots: {
43
+ after_line_items: expect.objectContaining({
44
+ type: "box",
45
+ width: 100,
46
+ height: 100,
47
+ }),
48
+ },
49
+ },
50
+ });
51
+ });
52
+ });
@@ -1,28 +1,12 @@
1
1
  import type { NubeSDK } from "@tiendanube/nube-sdk-types";
2
- import { Box, Field, Txt } from "@tiendanube/nube-sdk-jsx";
3
-
4
- function MyComponent() {
5
- return (
6
- <Box width={100} height={200}>
7
- <Txt>Hello!!</Txt>
8
- <Field
9
- id="myField"
10
- label="Name"
11
- name="Name"
12
- onChange={(e) => {
13
- console.log(`User name: ${e.value}`);
14
- }}
15
- />
16
- </Box>
17
- );
18
- }
2
+ import { MyCustomField } from "./components/MyCustomField";
19
3
 
20
4
  export function App(nube: NubeSDK) {
21
- nube.send("ui:slot:set", () => ({
22
- ui: {
23
- slots: {
24
- after_line_items: <MyComponent />,
25
- },
26
- },
27
- }));
5
+ nube.send("ui:slot:set", () => ({
6
+ ui: {
7
+ slots: {
8
+ after_line_items: <MyCustomField />,
9
+ },
10
+ },
11
+ }));
28
12
  }
@@ -0,0 +1,5 @@
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {},
5
+ });