@devscholar/node-ps1-dotnet 0.0.1 → 0.0.2

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.
@@ -0,0 +1,136 @@
1
+ import { jest } from '@jest/globals';
2
+
3
+ const isWindows = process.platform === 'win32';
4
+
5
+ (isWindows ? describe : describe.skip)('WinForms GUI Tests', () => {
6
+ let dotnet: any;
7
+ let System: any;
8
+ let Forms: any;
9
+ let Drawing: any;
10
+
11
+ beforeAll(async () => {
12
+ try {
13
+ dotnet = await import('../src/index.js');
14
+ dotnet.default.load('System.Windows.Forms');
15
+ dotnet.default.load('System.Drawing');
16
+ System = dotnet.System;
17
+ Forms = System.Windows.Forms;
18
+ Drawing = System.Drawing;
19
+ } catch (e) {
20
+ console.log('Skipping WinForms tests - load failed:', e);
21
+ }
22
+ });
23
+
24
+ afterAll(() => {
25
+ try {
26
+ dotnet?.node_ps1_dotnet?._close();
27
+ } catch {}
28
+ });
29
+
30
+ it('should load System.Windows.Forms assembly', () => {
31
+ expect(Forms).toBeDefined();
32
+ expect(Forms.Form).toBeDefined();
33
+ });
34
+
35
+ it('should load System.Drawing assembly', () => {
36
+ expect(Drawing).toBeDefined();
37
+ expect(Drawing.Color).toBeDefined();
38
+ expect(Drawing.Font).toBeDefined();
39
+ expect(Drawing.Point).toBeDefined();
40
+ });
41
+
42
+ it('should create a Form instance', () => {
43
+ const form = new Forms.Form();
44
+ expect(form).toBeDefined();
45
+ expect(form.__ref).toBeDefined();
46
+ });
47
+
48
+ it('should set Form properties', () => {
49
+ const form = new Forms.Form();
50
+ form.Text = 'Test Form';
51
+ form.Width = 800;
52
+ form.Height = 600;
53
+ form.StartPosition = 1;
54
+
55
+ expect(form.Text).toBe('Test Form');
56
+ expect(form.Width).toBe(800);
57
+ expect(form.Height).toBe(600);
58
+ });
59
+
60
+ it('should create a Label control', () => {
61
+ const label = new Forms.Label();
62
+ expect(label).toBeDefined();
63
+
64
+ label.Text = 'Test Label';
65
+ label.Font = new Drawing.Font('Arial', 14);
66
+ label.AutoSize = true;
67
+
68
+ expect(label.Text).toBe('Test Label');
69
+ expect(label.AutoSize).toBe(true);
70
+ });
71
+
72
+ it('should create a Button control', () => {
73
+ const button = new Forms.Button();
74
+ expect(button).toBeDefined();
75
+
76
+ button.Text = 'Click Me';
77
+ button.AutoSize = true;
78
+
79
+ expect(button.Text).toBe('Click Me');
80
+ });
81
+
82
+ it('should create a Panel control', () => {
83
+ const panel = new Forms.Panel();
84
+ expect(panel).toBeDefined();
85
+
86
+ panel.Width = 100;
87
+ panel.Height = 100;
88
+ panel.BackColor = Drawing.Color.Red;
89
+
90
+ expect(panel.Width).toBe(100);
91
+ expect(panel.Height).toBe(100);
92
+ });
93
+
94
+ it('should create a Point for location', () => {
95
+ const point = new Drawing.Point(100, 200);
96
+ expect(point).toBeDefined();
97
+ expect(point.X).toBe(100);
98
+ expect(point.Y).toBe(200);
99
+ });
100
+
101
+ it('should create a Font', () => {
102
+ const font = new Drawing.Font('Arial', 12);
103
+ expect(font).toBeDefined();
104
+ expect(font.Name).toContain('Arial');
105
+ });
106
+
107
+ it('should add controls to form', () => {
108
+ const form = new Forms.Form();
109
+ const label = new Forms.Label();
110
+ const button = new Forms.Button();
111
+
112
+ form.Controls.Add(label);
113
+ form.Controls.Add(button);
114
+
115
+ expect(form.Controls.Count).toBeGreaterThanOrEqual(2);
116
+ });
117
+
118
+ it('should register click event handler', () => {
119
+ const button = new Forms.Button();
120
+ let clicked = false;
121
+
122
+ button.add_Click(() => {
123
+ clicked = true;
124
+ });
125
+
126
+ expect(button).toBeDefined();
127
+ });
128
+
129
+ it('should create Color constants', () => {
130
+ expect(Drawing.Color.Red).toBeDefined();
131
+ expect(Drawing.Color.Green).toBeDefined();
132
+ expect(Drawing.Color.Blue).toBeDefined();
133
+ expect(Drawing.Color.Black).toBeDefined();
134
+ expect(Drawing.Color.White).toBeDefined();
135
+ });
136
+ });
@@ -0,0 +1,135 @@
1
+ import { jest } from '@jest/globals';
2
+
3
+ const isWindows = process.platform === 'win32';
4
+
5
+ (isWindows ? describe : describe.skip)('WPF GUI Tests', () => {
6
+ let dotnet: any;
7
+ let System: any;
8
+ let Windows: any;
9
+ let Controls: any;
10
+ let Media: any;
11
+
12
+ beforeAll(async () => {
13
+ try {
14
+ dotnet = await import('../src/index.js');
15
+ dotnet.default.load('PresentationFramework');
16
+ dotnet.default.load('PresentationCore');
17
+ dotnet.default.load('WindowsBase');
18
+ System = dotnet.System;
19
+ Windows = System.Windows;
20
+ Controls = Windows.Controls;
21
+ Media = Windows.Media;
22
+ } catch (e) {
23
+ console.log('Skipping WPF tests - load failed:', e);
24
+ }
25
+ });
26
+
27
+ afterAll(() => {
28
+ try {
29
+ dotnet?.node_ps1_dotnet?._close();
30
+ } catch {}
31
+ });
32
+
33
+ it('should load PresentationFramework assembly', () => {
34
+ expect(Controls).toBeDefined();
35
+ expect(Windows).toBeDefined();
36
+ });
37
+
38
+ it('should load PresentationCore assembly', () => {
39
+ expect(Media).toBeDefined();
40
+ expect(Media.FontFamily).toBeDefined();
41
+ });
42
+
43
+ it('should create a Window instance', () => {
44
+ const window = new Windows.Window();
45
+ expect(window).toBeDefined();
46
+ expect(window.__ref).toBeDefined();
47
+ });
48
+
49
+ it('should set Window properties', () => {
50
+ const window = new Windows.Window();
51
+ window.Title = 'Test Window';
52
+ window.Width = 400;
53
+ window.Height = 300;
54
+ window.WindowStartupLocation = Windows.WindowStartupLocation.CenterScreen;
55
+
56
+ expect(window.Title).toBe('Test Window');
57
+ expect(window.Width).toBe(400);
58
+ expect(window.Height).toBe(300);
59
+ });
60
+
61
+ it('should create a StackPanel', () => {
62
+ const stackPanel = new Controls.StackPanel();
63
+ expect(stackPanel).toBeDefined();
64
+
65
+ stackPanel.HorizontalAlignment = Windows.HorizontalAlignment.Center;
66
+ stackPanel.VerticalAlignment = Windows.VerticalAlignment.Center;
67
+
68
+ expect(stackPanel.HorizontalAlignment).toBeDefined();
69
+ });
70
+
71
+ it('should create a Label control', () => {
72
+ const label = new Controls.Label();
73
+ expect(label).toBeDefined();
74
+ label.Content = 'Test Label';
75
+ label.FontSize = 24;
76
+ label.Margin = new Windows.Thickness(10);
77
+
78
+ expect(label.Content).toBe('Test Label');
79
+ expect(label.FontSize).toBe(24);
80
+ });
81
+
82
+ it('should create a Button control', () => {
83
+ const button = new Controls.Button();
84
+ expect(button).toBeDefined();
85
+
86
+ button.Content = 'Click Me';
87
+ button.FontSize = 14;
88
+ button.Padding = new Windows.Thickness(5);
89
+
90
+ expect(button.Content).toBe('Click Me');
91
+ });
92
+
93
+ it('should add children to StackPanel', () => {
94
+ const stackPanel = new Controls.StackPanel();
95
+ const label = new Controls.Label();
96
+ const button = new Controls.Button();
97
+
98
+ stackPanel.Children.Add(label);
99
+ stackPanel.Children.Add(button);
100
+
101
+ expect(stackPanel.Children.Count).toBeGreaterThanOrEqual(2);
102
+ });
103
+
104
+ it('should set Window Content to StackPanel', () => {
105
+ const window = new Windows.Window();
106
+ const stackPanel = new Controls.StackPanel();
107
+
108
+ window.Content = stackPanel;
109
+
110
+ expect(window.Content).toBeDefined();
111
+ });
112
+
113
+ it('should register button click event handler', () => {
114
+ const button = new Controls.Button();
115
+
116
+ button.add_Click((sender: any, e: any) => {
117
+ console.log('Button clicked');
118
+ });
119
+
120
+ expect(button).toBeDefined();
121
+ });
122
+
123
+ it('should create FontFamily', () => {
124
+ const fontFamily = new Media.FontFamily('Arial');
125
+ expect(fontFamily).toBeDefined();
126
+ });
127
+
128
+ it('should create Thickness', () => {
129
+ const thickness = new Windows.Thickness(10);
130
+ expect(thickness).toBeDefined();
131
+
132
+ const thickness2 = new Windows.Thickness(5, 10, 15, 20);
133
+ expect(thickness2).toBeDefined();
134
+ });
135
+ });
@@ -0,0 +1,30 @@
1
+ # Testing
2
+ Run all tests:
3
+
4
+ ```bash
5
+ npm test
6
+ ```
7
+
8
+ Run specific test files:
9
+
10
+ ```bash
11
+ npm test -- --testPathPatterns=winforms
12
+ npm test -- --testPathPatterns=wpf
13
+ npm test -- --testPathPatterns=dotnet
14
+ ```
15
+
16
+ Test files are located in the `__tests__` directory:
17
+
18
+ - `basic.test.ts` - Basic module functionality tests
19
+ - `ipc.test.ts` - IPC communication tests
20
+ - `winforms.test.ts` - WinForms GUI component tests
21
+ - `wpf.test.ts` - WPF GUI component tests
22
+ - `gui-events.test.ts` - GUI event handling tests
23
+ - `dotnet-enums.test.ts` - .NET enum tests
24
+ - `dotnet-console.test.ts` - Console class tests
25
+ - `dotnet-io.test.ts` - System.IO tests
26
+ - `dotnet-task.test.ts` - Task asynchronous tests
27
+ - `dotnet-misc.test.ts` - String, Array, Environment tests
28
+ - `dotnet-runtime.test.ts` - Runtime info and type loading tests
29
+
30
+ Note: GUI tests will not display windows - they only create objects in memory for verification.
package/jest.config.js ADDED
@@ -0,0 +1,31 @@
1
+ export default {
2
+ preset: 'ts-jest/presets/default-esm',
3
+ testEnvironment: 'node',
4
+ extensionsToTreatAsEsm: ['.ts'],
5
+ moduleNameMapper: {
6
+ '^(\\.{1,2}/.*)\\.js$': '$1',
7
+ },
8
+ transform: {
9
+ '^.+\\.ts$': [
10
+ 'ts-jest',
11
+ {
12
+ useESM: true,
13
+ tsconfig: {
14
+ module: 'ESNext',
15
+ moduleResolution: 'bundler',
16
+ },
17
+ },
18
+ ],
19
+ },
20
+ testMatch: [
21
+ '**/__tests__/**/*.ts',
22
+ '**/?(*.)+(spec|test).ts',
23
+ ],
24
+ collectCoverageFrom: [
25
+ 'src/**/*.ts',
26
+ '!src/**/*.d.ts',
27
+ ],
28
+ coverageDirectory: 'coverage',
29
+ coverageReporters: ['text', 'lcov', 'html'],
30
+ testTimeout: 30000,
31
+ };
package/package.json CHANGED
@@ -1,21 +1,32 @@
1
1
  {
2
2
  "name": "@devscholar/node-ps1-dotnet",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Node.js to .NET interop via IPC",
5
- "main": "./src/index.ts",
5
+ "main": "./dist/index.js",
6
6
  "type": "module",
7
7
  "exports": {
8
- ".": "./src/index.ts"
8
+ ".": "./dist/index.js"
9
9
  },
10
10
  "scripts": {
11
- "test": "echo \"Error: no test specified\" && exit 1",
11
+ "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
12
+ "test:watch": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watch",
13
+ "test:coverage": "node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage",
12
14
  "build": "tsc"
13
15
  },
14
- "keywords": ["dotnet", "winforms", "interop", "bridge", "ipc"],
16
+ "keywords": [
17
+ "dotnet",
18
+ "winforms",
19
+ "interop",
20
+ "bridge",
21
+ "ipc"
22
+ ],
15
23
  "author": "",
16
24
  "license": "ISC",
17
25
  "devDependencies": {
26
+ "@types/jest": "^30.0.0",
18
27
  "@types/node": "^25.0.10",
28
+ "jest": "^30.2.0",
29
+ "ts-jest": "^29.4.6",
19
30
  "typescript": "^5.9.3"
20
31
  }
21
32
  }
@@ -380,6 +380,20 @@ public static class Reflection
380
380
  var intValue = value is long ? (int)(long)value : (int)value;
381
381
  value = Enum.ToObject(prop.PropertyType, intValue);
382
382
  }
383
+ else if (prop.PropertyType.IsValueType && !prop.PropertyType.IsPrimitive)
384
+ {
385
+ // Handle structs like FontWeight - try to create from integer
386
+ var intValue = value is long ? (int)(long)value : (int)value;
387
+ var ctor = prop.PropertyType.GetConstructor(new[] { typeof(int) });
388
+ if (ctor != null)
389
+ {
390
+ value = ctor.Invoke(new object[] { intValue });
391
+ }
392
+ else if (value is IConvertible)
393
+ {
394
+ value = Convert.ChangeType(value, prop.PropertyType);
395
+ }
396
+ }
383
397
  else if (value is IConvertible)
384
398
  {
385
399
  value = Convert.ChangeType(value, prop.PropertyType);