1+ import { describe , expect , it } from "vitest" ;
2+ import { Node } from "@dafthunk/types" ;
3+
4+ import { JsonToGeojsonNode } from "./json-to-geojson-node" ;
5+ import { NodeContext } from "../types" ;
6+
7+ describe ( "JsonToGeojsonNode" , ( ) => {
8+ const createMockContext = ( inputs : Record < string , any > ) : NodeContext => ( {
9+ nodeId : "test-node" ,
10+ workflowId : "test-workflow" ,
11+ organizationId : "test-org" ,
12+ inputs,
13+ env : { } as any ,
14+ } ) ;
15+
16+ const createNode = ( ) : JsonToGeojsonNode => {
17+ const node : Node = {
18+ id : "test-node" ,
19+ name : "Test JSON to GeoJSON Node" ,
20+ type : "json-to-geojson" ,
21+ position : { x : 0 , y : 0 } ,
22+ inputs : [ ] ,
23+ outputs : [ ] ,
24+ } ;
25+ return new JsonToGeojsonNode ( node ) ;
26+ } ;
27+
28+ describe ( "valid GeoJSON inputs" , ( ) => {
29+ it ( "should convert valid Point geometry" , async ( ) => {
30+ const node = createNode ( ) ;
31+ const point = {
32+ type : "Point" ,
33+ coordinates : [ 10 , 20 ] ,
34+ } ;
35+
36+ const context = createMockContext ( { json : point } ) ;
37+ const result = await node . execute ( context ) ;
38+
39+ expect ( result . status ) . toBe ( "completed" ) ;
40+ expect ( result . outputs ?. geojson ) . toEqual ( point ) ;
41+ } ) ;
42+
43+ it ( "should convert valid LineString geometry" , async ( ) => {
44+ const node = createNode ( ) ;
45+ const lineString = {
46+ type : "LineString" ,
47+ coordinates : [ [ 0 , 0 ] , [ 10 , 10 ] , [ 20 , 0 ] ] ,
48+ } ;
49+
50+ const context = createMockContext ( { json : lineString } ) ;
51+ const result = await node . execute ( context ) ;
52+
53+ expect ( result . status ) . toBe ( "completed" ) ;
54+ expect ( result . outputs ?. geojson ) . toEqual ( lineString ) ;
55+ } ) ;
56+
57+ it ( "should convert valid Polygon geometry" , async ( ) => {
58+ const node = createNode ( ) ;
59+ const polygon = {
60+ type : "Polygon" ,
61+ coordinates : [ [ [ 0 , 0 ] , [ 10 , 0 ] , [ 10 , 10 ] , [ 0 , 10 ] , [ 0 , 0 ] ] ] ,
62+ } ;
63+
64+ const context = createMockContext ( { json : polygon } ) ;
65+ const result = await node . execute ( context ) ;
66+
67+ expect ( result . status ) . toBe ( "completed" ) ;
68+ expect ( result . outputs ?. geojson ) . toEqual ( polygon ) ;
69+ } ) ;
70+
71+ it ( "should convert valid Feature" , async ( ) => {
72+ const node = createNode ( ) ;
73+ const feature = {
74+ type : "Feature" ,
75+ geometry : {
76+ type : "Point" ,
77+ coordinates : [ 5 , 5 ] ,
78+ } ,
79+ properties : {
80+ name : "Test Point" ,
81+ } ,
82+ } ;
83+
84+ const context = createMockContext ( { json : feature } ) ;
85+ const result = await node . execute ( context ) ;
86+
87+ expect ( result . status ) . toBe ( "completed" ) ;
88+ expect ( result . outputs ?. geojson ) . toEqual ( feature ) ;
89+ } ) ;
90+
91+ it ( "should convert valid FeatureCollection" , async ( ) => {
92+ const node = createNode ( ) ;
93+ const featureCollection = {
94+ type : "FeatureCollection" ,
95+ features : [
96+ {
97+ type : "Feature" ,
98+ geometry : {
99+ type : "Point" ,
100+ coordinates : [ 5 , 5 ] ,
101+ } ,
102+ properties : {
103+ name : "Test Point" ,
104+ } ,
105+ } ,
106+ ] ,
107+ } ;
108+
109+ const context = createMockContext ( { json : featureCollection } ) ;
110+ const result = await node . execute ( context ) ;
111+
112+ expect ( result . status ) . toBe ( "completed" ) ;
113+ expect ( result . outputs ?. geojson ) . toEqual ( featureCollection ) ;
114+ } ) ;
115+ } ) ;
116+
117+ describe ( "JSON string inputs" , ( ) => {
118+ it ( "should parse and convert JSON string to GeoJSON" , async ( ) => {
119+ const node = createNode ( ) ;
120+ const geojsonString = JSON . stringify ( {
121+ type : "Point" ,
122+ coordinates : [ 10 , 20 ] ,
123+ } ) ;
124+
125+ const context = createMockContext ( { json : geojsonString } ) ;
126+ const result = await node . execute ( context ) ;
127+
128+ expect ( result . status ) . toBe ( "completed" ) ;
129+ expect ( result . outputs ?. geojson ) . toEqual ( {
130+ type : "Point" ,
131+ coordinates : [ 10 , 20 ] ,
132+ } ) ;
133+ } ) ;
134+
135+ it ( "should parse and convert Feature JSON string" , async ( ) => {
136+ const node = createNode ( ) ;
137+ const featureString = JSON . stringify ( {
138+ type : "Feature" ,
139+ geometry : {
140+ type : "Point" ,
141+ coordinates : [ 5 , 5 ] ,
142+ } ,
143+ properties : {
144+ fill : "#ff0000" ,
145+ } ,
146+ } ) ;
147+
148+ const context = createMockContext ( { json : featureString } ) ;
149+ const result = await node . execute ( context ) ;
150+
151+ expect ( result . status ) . toBe ( "completed" ) ;
152+ expect ( result . outputs ?. geojson ) . toEqual ( {
153+ type : "Feature" ,
154+ geometry : {
155+ type : "Point" ,
156+ coordinates : [ 5 , 5 ] ,
157+ } ,
158+ properties : {
159+ fill : "#ff0000" ,
160+ } ,
161+ } ) ;
162+ } ) ;
163+ } ) ;
164+
165+ describe ( "error handling" , ( ) => {
166+ it ( "should return error for missing input" , async ( ) => {
167+ const node = createNode ( ) ;
168+ const context = createMockContext ( { } ) ;
169+
170+ const result = await node . execute ( context ) ;
171+
172+ expect ( result . status ) . toBe ( "error" ) ;
173+ expect ( result . error ) . toContain ( "JSON input is required" ) ;
174+ } ) ;
175+
176+ it ( "should return error for null input" , async ( ) => {
177+ const node = createNode ( ) ;
178+ const context = createMockContext ( { json : null } ) ;
179+
180+ const result = await node . execute ( context ) ;
181+
182+ expect ( result . status ) . toBe ( "error" ) ;
183+ expect ( result . error ) . toContain ( "JSON input is required" ) ;
184+ } ) ;
185+
186+ it ( "should return error for undefined input" , async ( ) => {
187+ const node = createNode ( ) ;
188+ const context = createMockContext ( { json : undefined } ) ;
189+
190+ const result = await node . execute ( context ) ;
191+
192+ expect ( result . status ) . toBe ( "error" ) ;
193+ expect ( result . error ) . toContain ( "JSON input is required" ) ;
194+ } ) ;
195+
196+ it ( "should return error for invalid JSON string" , async ( ) => {
197+ const node = createNode ( ) ;
198+ const context = createMockContext ( { json : "{ invalid json }" } ) ;
199+
200+ const result = await node . execute ( context ) ;
201+
202+ expect ( result . status ) . toBe ( "error" ) ;
203+ expect ( result . error ) . toContain ( "Invalid JSON string" ) ;
204+ } ) ;
205+
206+ it ( "should return error for unsupported input type" , async ( ) => {
207+ const node = createNode ( ) ;
208+ const context = createMockContext ( { json : 123 } ) ;
209+
210+ const result = await node . execute ( context ) ;
211+
212+ expect ( result . status ) . toBe ( "error" ) ;
213+ expect ( result . error ) . toContain ( "Unsupported input type" ) ;
214+ } ) ;
215+
216+ it ( "should return error for non-object input" , async ( ) => {
217+ const node = createNode ( ) ;
218+ const context = createMockContext ( { json : "123" } ) ; // Valid JSON but not an object
219+
220+ const result = await node . execute ( context ) ;
221+
222+ expect ( result . status ) . toBe ( "error" ) ;
223+ expect ( result . error ) . toContain ( "Input must be an object" ) ;
224+ } ) ;
225+
226+ it ( "should return error for missing type property" , async ( ) => {
227+ const node = createNode ( ) ;
228+ const context = createMockContext ( {
229+ json : { coordinates : [ 10 , 20 ] }
230+ } ) ;
231+
232+ const result = await node . execute ( context ) ;
233+
234+ expect ( result . status ) . toBe ( "error" ) ;
235+ expect ( result . error ) . toContain ( "Input must have a 'type' property" ) ;
236+ } ) ;
237+
238+ it ( "should return error for invalid GeoJSON type" , async ( ) => {
239+ const node = createNode ( ) ;
240+ const context = createMockContext ( {
241+ json : { type : "InvalidType" , coordinates : [ 10 , 20 ] }
242+ } ) ;
243+
244+ const result = await node . execute ( context ) ;
245+
246+ expect ( result . status ) . toBe ( "error" ) ;
247+ expect ( result . error ) . toContain ( "Invalid GeoJSON format" ) ;
248+ } ) ;
249+
250+ it ( "should return error for invalid geometry structure" , async ( ) => {
251+ const node = createNode ( ) ;
252+ const context = createMockContext ( {
253+ json : { type : "Point" , coordinates : "not an array" }
254+ } ) ;
255+
256+ const result = await node . execute ( context ) ;
257+
258+ expect ( result . status ) . toBe ( "error" ) ;
259+ expect ( result . error ) . toContain ( "Invalid GeoJSON format" ) ;
260+ } ) ;
261+ } ) ;
262+ } ) ;
0 commit comments