Repository: teleporthq/teleport-code-generators
Pull request #220 (2019-05-14 10:29:59)

Tests
Integration tests on teleport-component-generator-react/vue with a focus on
- conditional node
- repeat node
- dependencies

 + other tests for different parts of the code


Patch:
diff --git a/packages/teleport-generator-shared/src/builders/uidl-builders.ts b/packages/teleport-generator-shared/src/builders/uidl-builders.ts
index 17d6b6a8..b74e7380 100644
--- a/packages/teleport-generator-shared/src/builders/uidl-builders.ts
+++ b/packages/teleport-generator-shared/src/builders/uidl-builders.ts
@@ -1,19 +1,41 @@
 import {
+  ComponentUIDL,
+  ReferenceType,
+  ComponentDependency,
   UIDLNode,
-  UIDLAttributeValue,
+  UIDLSlotNode,
+  UIDLStyleValue,
+  UIDLRepeatNode,
   UIDLElementNode,
   UIDLStaticValue,
+  UIDLAttributeValue,
+  UIDLPropDefinition,
+  UIDLStateDefinition,
+  UIDLConditionalNode,
   UIDLDynamicReference,
-  ReferenceType,
-  ComponentUIDL,
-  UIDLSlotNode,
-  UIDLStyleValue,
 } from '../typings/uidl'
 
-export const component = (name: string, node: UIDLNode): ComponentUIDL => {
+export const component = (
+  name: string,
+  node: UIDLNode,
+  propDefinitions?: Record<string, UIDLPropDefinition>,
+  stateDefinitions?: Record<string, UIDLStateDefinition>
+): ComponentUIDL => {
   return {
     name,
     node,
+    stateDefinitions,
+    propDefinitions,
+  }
+}
+
+export const definition = (
+  type: string,
+  defaultValue: string | number | boolean | any[] | object
+) => {
+  return {
+    type,
+    defaultValue,
   }
 }
 
@@ -21,13 +43,14 @@ export const elementNode = (
   elementType: string,
   attrs?: Record<string, UIDLAttributeValue>,
   children?: UIDLNode[],
+  dependency?: ComponentDependency,
   style?: Record<string, UIDLStyleValue>
 ): UIDLElementNode => {
   return {
     type: 'element',
     content: style
-      ? element(elementType, attrs, children, style)
-      : element(elementType, attrs, children),
+      ? element(elementType, attrs, children, dependency, style)
+      : element(elementType, attrs, children, dependency),
   }
 }
 
@@ -35,17 +58,33 @@ export const element = (
   elementType: string,
   attrs?: Record<string, UIDLAttributeValue>,
   children?: UIDLNode[],
+  dependency?: ComponentDependency,
   style?: Record<string, UIDLStyleValue>
 ) => {
   return {
     elementType,
     name: elementType,
+    dependency,
     attrs,
     style,
     children,
   }
 }
 
+export const componentDependency = (
+  type?: string,
+  path?: string,
+  version?: string,
+  meta?: Record<string, string | boolean>
+): ComponentDependency => {
+  return {
+    type,
+    path,
+    version,
+    meta,
+  }
+}
+
 export const staticNode = (content: string): UIDLStaticValue => {
   return {
     type: 'static',
@@ -72,3 +111,33 @@ export const slotNode = (fallback?: UIDLNode, name?: string): UIDLSlotNode => {
     },
   }
 }
+
+export const conditionalNode = (
+  reference: UIDLDynamicReference,
+  node: UIDLNode,
+  value: string | number | boolean
+): UIDLConditionalNode => {
+  return {
+    type: 'conditional',
+    content: {
+      reference,
+      node,
+      value,
+    },
+  }
+}
+
+export const repeatNode = (
+  node: UIDLNode,
+  dataSource: UIDLAttributeValue,
+  meta?: Record<string, any>
+): UIDLRepeatNode => {
+  return {
+    type: 'repeat',
+    content: {
+      node,
+      dataSource,
+      meta,
+    },
+  }
+}
diff --git a/packages/teleport-generator-shared/src/utils/project-utils.ts b/packages/teleport-generator-shared/src/utils/project-utils.ts
index 9eba7d7d..ace1cb67 100644
--- a/packages/teleport-generator-shared/src/utils/project-utils.ts
+++ b/packages/teleport-generator-shared/src/utils/project-utils.ts
@@ -146,7 +146,6 @@ export const createHtmlIndexFile = (
 export const createManifestJSONFile = (uidl: ProjectUIDL, assetsPrefix?: string): GeneratedFile => {
   const manifest = uidl.globals.manifest
   const projectName = uidl.name
-
   const defaultManifest: WebManifest = {
     short_name: projectName,
     name: projectName,
@@ -155,7 +154,7 @@ export const createManifestJSONFile = (uidl: ProjectUIDL, assetsPrefix?: string)
   }
 
   const icons = manifest.icons.map((icon) => {
-    const src = prefixPlaygroundAssetsURL(assetsPrefix, icon.src)
+    const src = prefixPlaygroundAssetsURL(assetsPrefix || '', icon.src)
     return { ...icon, src }
   })
 
diff --git a/packages/teleport-generator-shared/src/utils/uidl-utils.ts b/packages/teleport-generator-shared/src/utils/uidl-utils.ts
index 246b5bec..75463008 100644
--- a/packages/teleport-generator-shared/src/utils/uidl-utils.ts
+++ b/packages/teleport-generator-shared/src/utils/uidl-utils.ts
@@ -19,7 +19,10 @@ import {
 export const extractPageMetadata = (
   routeDefinitions: UIDLStateDefinition,
   stateName: string,
-  options: { usePathAsFileName?: boolean; convertDefaultToIndex?: boolean } = {
+  options: {
+    usePathAsFileName?: boolean
+    convertDefaultToIndex?: boolean
+  } = {
     usePathAsFileName: false,
     convertDefaultToIndex: false,
   }


Test patch:
diff --git a/packages/teleport-component-generator-react/__tests__/integration/component-attrs.ts b/packages/teleport-component-generator-react/__tests__/integration/component-attrs.ts
index 956cbcf5..768b45f3 100644
--- a/packages/teleport-component-generator-react/__tests__/integration/component-attrs.ts
+++ b/packages/teleport-component-generator-react/__tests__/integration/component-attrs.ts
@@ -1,16 +1,45 @@
 // @ts-ignore-next-line
-import ComponentWithValidPropsJSON from './component-with-valid-attr-prop.json'
-// @ts-ignore-next-line
-import ComponentWithRepeatPropsJSON from './component-with-repeat.json'
-// @ts-ignore-next-line
 import ComponentWithOldFormatAttributesJSON from './component-with-old-format-attributes.json'
 
 import { createReactComponentGenerator } from '../../src'
-import { ComponentUIDL } from '@teleporthq/teleport-generator-shared/lib/typings/uidl'
 import { GeneratedFile } from '@teleporthq/teleport-generator-shared/lib/typings/generators'
 
-const ComponentWithValidProps = ComponentWithValidPropsJSON as ComponentUIDL
-const ComponentWithRepeatProps = ComponentWithRepeatPropsJSON as ComponentUIDL
+import {
+  component,
+  definition,
+  repeatNode,
+  dynamicNode,
+  elementNode,
+} from '@teleporthq/teleport-generator-shared/lib/builders/uidl-builders'
+
+const uidl = component(
+  'ComponentWithAttrProp',
+  elementNode('container', {}, [
+    repeatNode(
+      elementNode('div', {}, [
+        elementNode(
+          'div',
+          {
+            test: dynamicNode('local', 'index'),
+            'data-test': dynamicNode('prop', 'test'),
+            'data-inner-value': dynamicNode('prop', 'content.heading'),
+          },
+          [dynamicNode('local', 'item')]
+        ),
+      ]),
+      dynamicNode('prop', 'items'),
+      {
+        useIndex: true,
+      }
+    ),
+  ]),
+  {
+    items: definition('object', { test: '123' }),
+    test: definition('string', '123'),
+    content: definition('object', { heading: 'Hello World' }),
+  },
+  {}
+)
 
 const JS_FILE = 'js'
 const findFileByType = (files: GeneratedFile[], type: string = JS_FILE) =>
@@ -21,7 +50,7 @@ describe('React Props in Component', () => {
     const generator = createReactComponentGenerator()
 
     it('should add attributes on component', async () => {
-      const result = await generator.generateComponent(ComponentWithValidProps)
+      const result = await generator.generateComponent(uidl)
       const jsFile = findFileByType(result.files, JS_FILE)
 
       expect(jsFile).toBeDefined()
@@ -39,12 +68,12 @@ describe('React Props in Component', () => {
     })
 
     it('should run repeat attributes and data source', async () => {
-      const result = await generator.generateComponent(ComponentWithRepeatProps)
+      const result = await generator.generateComponent(uidl)
       const jsFile = findFileByType(result.files, JS_FILE)
 
       expect(jsFile).toBeDefined()
       expect(jsFile.content).toContain('key={index}>')
-      expect(jsFile.content).toContain('test={index}>')
+      expect(jsFile.content).toContain('test={index}')
     })
   })
 })
diff --git a/packages/teleport-component-generator-react/__tests__/integration/component-conditional.ts b/packages/teleport-component-generator-react/__tests__/integration/component-conditional.ts
new file mode 100644
index 00000000..5548f15b
--- /dev/null
+++ b/packages/teleport-component-generator-react/__tests__/integration/component-conditional.ts
@@ -0,0 +1,52 @@
+import { createReactComponentGenerator } from '../../src'
+import { GeneratedFile } from '@teleporthq/teleport-generator-shared/lib/typings/generators'
+
+import {
+  component,
+  definition,
+  staticNode,
+  dynamicNode,
+  elementNode,
+  conditionalNode,
+} from '@teleporthq/teleport-generator-shared/lib/builders/uidl-builders'
+
+const generator = createReactComponentGenerator()
+
+const JS_FILE = 'js'
+const findFileByType = (files: GeneratedFile[], type: string = JS_FILE) =>
+  files.find((file) => file.fileType === type)
+
+const uidl = component(
+  'Conditional Component',
+  elementNode('container', {}, [
+    conditionalNode(
+      dynamicNode('state', 'isVisible'),
+      elementNode('text', {}, [staticNode('Now you see me!')]),
+      true
+    ),
+    conditionalNode(
+      dynamicNode('state', 'isShareable'),
+      elementNode('text', {}, [staticNode('I am not shareable!')]),
+      false
+    ),
+  ]),
+  {},
+  { isVisible: definition('boolean', true), isShareable: definition('boolean', false) }
+)
+
+describe('Component with conditional node type', () => {
+  it('renders code with condition if value on state is true', async () => {
+    const result = await generator.generateComponent(uidl)
+    const jsFile = findFileByType(result.files, JS_FILE)
+
+    expect(jsFile).toBeDefined()
+    expect(jsFile.content).toContain('{isVisible && <span>Now you see me!</span>}')
+  })
+  it('renders code with !condition if value on state is false', async () => {
+    const result = await generator.generateComponent(uidl)
+    const jsFile = findFileByType(result.files, JS_FILE)
+
+    expect(jsFile).toBeDefined()
+    expect(jsFile.content).toContain('{!isShareable && <span>I am not shareable!</span>}')
+  })
+})
diff --git a/packages/teleport-component-generator-react/__tests__/integration/component-dependency.ts b/packages/teleport-component-generator-react/__tests__/integration/component-dependency.ts
new file mode 100644
index 00000000..87406d34
--- /dev/null
+++ b/packages/teleport-component-generator-react/__tests__/integration/component-dependency.ts
@@ -0,0 +1,170 @@
+import { createReactComponentGenerator } from '../../src'
+import { GeneratedFile } from '@teleporthq/teleport-generator-shared/lib/typings/generators'
+
+import {
+  component,
+  definition,
+  elementNode,
+  componentDependency,
+} from '@teleporthq/teleport-generator-shared/lib/builders/uidl-builders'
+
+const generator = createReactComponentGenerator()
+
+const JS_FILE = 'js'
+const findFileByType = (files: GeneratedFile[], type: string = JS_FILE) =>
+  files.find((file) => file.fileType === type)
+
+const dependencySample = (
+  name: string,
+  type: string,
+  path: string,
+  version: string,
+  option: object
+) => {
+  return { name, type, path, version, option }
+}
+
+const uidl = (dependency) => {
+  return component(
+    'Component with dependencies',
+    elementNode(
+      dependency.name,
+      {},
+      [],
+      componentDependency(dependency.type, dependency.path, dependency.version, dependency.option)
+    ),
+    {},
+    { title: definition('boolean', true) }
+  )
+}
+
+describe('Component with dependency ', () => {
+  describe('from package.json', () => {
+    it('renders code with imported package', async () => {
+      const result = await generator.generateComponent(
+        uidl(
+          dependencySample('ReactDatepicker', 'package', 'react-datepicker', '', {
+            namedImport: false,
+          })
+        )
+      )
+      const jsFile = findFileByType(result.files, JS_FILE)
+
+      expect(jsFile).toBeDefined()
+      expect(jsFile.content).toContain("import ReactDatepicker from 'react-datepicker'")
+    })
+
+    it('renders code with named import ', async () => {
+      const result = await generator.generateComponent(
+        uidl(
+          dependencySample('ReactDatepicker', 'package', 'react-datepicker', '', {
+            namedImport: true,
+          })
+        )
+      )
+      const jsFile = findFileByType(result.files, JS_FILE)
+      expect(jsFile).toBeDefined()
+      expect(jsFile.content).toContain("import { ReactDatepicker } from 'react-datepicker'")
+    })
+
+    it('fails to render if dependency option is not known', async () => {
+      const result = await generator.generateComponent(
+        uidl(
+          dependencySample('ReactDatepicker', 'package', 'react-datepicker', '', {
+            test: true,
+          })
+        )
+      )
+      const jsFile = findFileByType(result.files, JS_FILE)
+      expect(jsFile).toBeDefined()
+      expect(jsFile.content).not.toContain("import { ReactDatepicker } from 'react-datepicker'")
+    })
+
+    it('fails to render code if dependency path is not valid', async () => {
+      const result = await generator.generateComponent(
+        uidl(
+          dependencySample('ReactDatepicker', 'test', 'react-datepicker', '', {
+            namedImport: true,
+          })
+        )
+      )
+      const jsFile = findFileByType(result.files, JS_FILE)
+      expect(jsFile).toBeDefined()
+      expect(jsFile.content).not.toContain("import { ReactDatepicker } from 'react-datepicker'")
+    })
+
+    it('renders code with original name', async () => {
+      const result = await generator.generateComponent(
+        uidl(
+          dependencySample('Router', 'package', 'react-router', '', {
+            namedImport: true,
+            originalName: 'BrowserRouter',
+          })
+        )
+      )
+      const jsFile = findFileByType(result.files, JS_FILE)
+
+      expect(jsFile).toBeDefined()
+      expect(jsFile.content).toContain("import { BrowserRouter as Router } from 'react-router'")
+    })
+  })
+
+  describe('from local', () => {
+    it('renders code with imported package', async () => {
+      const result = await generator.generateComponent(
+        uidl(
+          dependencySample('ReactDatepicker', 'local', '../react-datepicker', '', {
+            namedImport: false,
+          })
+        )
+      )
+      const jsFile = findFileByType(result.files, JS_FILE)
+
+      expect(jsFile).toBeDefined()
+      expect(jsFile.content).toContain("import ReactDatepicker from '../react-datepicker'")
+    })
+
+    it('renders code with named import ', async () => {
+      const result = await generator.generateComponent(
+        uidl(
+          dependencySample('ReactDatepicker', 'local', '../react-datepicker', '', {
+            namedImport: true,
+          })
+        )
+      )
+      const jsFile = findFileByType(result.files, JS_FILE)
+      expect(jsFile).toBeDefined()
+      expect(jsFile.content).toContain("import { ReactDatepicker } from '../react-datepicker'")
+    })
+
+    it('renders code with original name', async () => {
+      const result = await generator.generateComponent(
+        uidl(
+          dependencySample('Router', 'local', 'react-router', '', {
+            namedImport: true,
+            originalName: 'BrowserRouter',
+          })
+        )
+      )
+      const jsFile = findFileByType(result.files, JS_FILE)
+
+      expect(jsFile).toBeDefined()
+      expect(jsFile.content).toContain("import { BrowserRouter as Router } from 'react-router'")
+    })
+  })
+
+  describe('from library', () => {
+    it('renders code with named import ', async () => {
+      const result = await generator.generateComponent(
+        uidl(
+          dependencySample('write', 'library', 'fs', '', {
+            namedImport: true,
+          })
+        )
+      )
+      const jsFile = findFileByType(result.files, JS_FILE)
+      expect(jsFile).toBeDefined()
+      expect(jsFile.content).toContain("import { write } from 'fs'")
+    })
+  })
+})
diff --git a/packages/teleport-component-generator-react/__tests__/integration/component-repeat.ts b/packages/teleport-component-generator-react/__tests__/integration/component-repeat.ts
new file mode 100644
index 00000000..f4751dc5
--- /dev/null
+++ b/packages/teleport-component-generator-react/__tests__/integration/component-repeat.ts
@@ -0,0 +1,48 @@
+import { createReactComponentGenerator } from '../../src'
+import { GeneratedFile } from '@teleporthq/teleport-generator-shared/lib/typings/generators'
+
+import {
+  component,
+  definition,
+  repeatNode,
+  dynamicNode,
+  elementNode,
+} from '@teleporthq/teleport-generator-shared/lib/builders/uidl-builders'
+
+const JS_FILE = 'js'
+const findFileByType = (files: GeneratedFile[], type: string = JS_FILE) =>
+  files.find((file) => file.fileType === type)
+
+const generator = createReactComponentGenerator()
+
+const uidl = component(
+  'Repeat Component',
+  elementNode('container', {}, [
+    repeatNode(
+      elementNode('div', {}, [dynamicNode('local', 'item')]),
+      dynamicNode('prop', 'items'),
+      {
+        useIndex: true,
+      }
+    ),
+  ]),
+  { items: definition('array', ['hello', 'world']) },
+  {}
+)
+
+describe('Component with repeat node type', () => {
+  it('renders code that contains map method', async () => {
+    const result = await generator.generateComponent(uidl)
+    const jsFile = findFileByType(result.files, JS_FILE)
+
+    expect(jsFile).toBeDefined()
+    expect(jsFile.content).toContain('props.items.map((item, index)')
+  })
+  it('renders code with map method that iterates using index', async () => {
+    const result = await generator.generateComponent(uidl)
+    const jsFile = findFileByType(result.files, JS_FILE)
+
+    expect(jsFile).toBeDefined()
+    expect(jsFile.content).toContain('key={index}')
+  })
+})
diff --git a/packages/teleport-component-generator-react/__tests__/integration/component-with-repeat.json b/packages/teleport-component-generator-react/__tests__/integration/component-with-repeat.json
deleted file mode 100644
index 1a23950d..00000000
--- a/packages/teleport-component-generator-react/__tests__/integration/component-with-repeat.json
+++ /dev/null
@@ -1,51 +0,0 @@
-{
-  "$schema": "https://raw.githubusercontent.com/teleporthq/teleport-code-generators/master/packages/teleport-generator-core/src/uidl-schemas/component.json",
-  "name": "ComponentWithAttrProp",
-  "propDefinitions": {
-    "test": {
-      "type": "string",
-      "defaultValue": "123"
-    }
-  },
-  "node": {
-    "type": "element",
-    "content": {
-      "elementType": "container",
-      "children": [{
-        "type": "repeat",
-        "content": {
-          "node": {
-            "type": "element",
-            "content": {
-              "elementType": "container",
-              "children": [{
-                "type": "element",
-                "content": {
-                  "elementType": "container",
-                  "name": "card",
-                  "attrs": {
-                    "test": {
-                      "type": "dynamic",
-                      "content": {
-                        "referenceType": "local",
-                        "id": "index"
-                      }
-                    }
-                  },
-                  "children": [{"type": "dynamic", "content": { "referenceType": "local", "id": "item" }}]
-                }
-              }]
-            }
-          },
-          "dataSource":  { 
-            "type": "dynamic",
-            "content": { "referenceType": "prop", "id": "items" }
-          },
-          "meta": {
-            "useIndex": true
-          }
-        }
-      }]
-    }
-  }
-}
\ No newline at end of file
diff --git a/packages/teleport-component-generator-react/__tests__/integration/component-with-valid-attr-prop.json b/packages/teleport-component-generator-react/__tests__/integration/component-with-valid-attr-prop.json
deleted file mode 100644
index 46afe765..00000000
--- a/packages/teleport-component-generator-react/__tests__/integration/component-with-valid-attr-prop.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
-  "$schema": "https://raw.githubusercontent.com/teleporthq/teleport-code-generators/master/packages/teleport-generator-core/src/uidl-schemas/component.json",
-  "name": "ComponentWithAttrProp",
-  "propDefinitions": {
-    "test": {
-      "type": "string",
-      "defaultValue": "123"
-    },
-    "content": {
-      "type": "object",
-      "defaultValue": {
-        "heading": "Hello World"
-      }
-    }
-  },
-  "node": {
-    "type": "element",
-    "content": {
-      "elementType": "container",
-      "attrs": {
-        "data-test": {
-          "type": "dynamic",
-          "content": {
-            "referenceType":"prop",
-            "id": "test"
-          }
-        },
-        "data-static": {
-          "type": "static",
-          "content": "I am just a static string"
-        },
-        "data-inner-value": {
-          "type": "dynamic",
-          "content": {
-            "referenceType":"prop",
-            "id": "content.heading"
-          }
-        }
-      }
-    }
-  }
-}
\ No newline at end of file
diff --git a/packages/teleport-component-generator-vue/__tests__/integration/component-attrs.ts b/packages/teleport-component-generator-vue/__tests__/integration/component-attrs.ts
index fa2fc56f..f2a96441 100644
--- a/packages/teleport-component-generator-vue/__tests__/integration/component-attrs.ts
+++ b/packages/teleport-component-generator-vue/__tests__/integration/component-attrs.ts
@@ -1,27 +1,57 @@
 // @ts-ignore-next-line
-import ComponentWithValidPropsJSON from './component-with-valid-attr-prop.json'
-// @ts-ignore-next-line
-import ComponentWithRepeatPropsJSON from './component-with-repeat.json'
-// @ts-ignore-next-line
 import ComponentWithOldFormatAttributesJSON from './component-with-old-format-attributes.json'
 
 import { createVueComponentGenerator } from '../../src'
-import { ComponentUIDL } from '@teleporthq/teleport-generator-shared/lib/typings/uidl'
 import { GeneratedFile } from '@teleporthq/teleport-generator-shared/lib/typings/generators'
-
-const ComponentWithValidProps = ComponentWithValidPropsJSON as ComponentUIDL
-const ComponentWithRepeatProps = ComponentWithRepeatPropsJSON as ComponentUIDL
+import {
+  component,
+  definition,
+  repeatNode,
+  dynamicNode,
+  elementNode,
+  staticNode,
+} from '@teleporthq/teleport-generator-shared/lib/builders/uidl-builders'
 
 const VUE_FILE = 'vue'
 const findFileByType = (files: GeneratedFile[], type: string = VUE_FILE) =>
   files.find((file) => file.fileType === type)
 
+const uidl = component(
+  'ComponentWithAttrProp',
+  elementNode('container', {}, [
+    repeatNode(
+      elementNode('div', {}, [
+        elementNode(
+          'div',
+          {
+            test: dynamicNode('local', 'index'),
+            'data-test': dynamicNode('prop', 'test'),
+            'data-static': staticNode('test'),
+            'data-inner-value': dynamicNode('prop', 'content.heading'),
+          },
+          [dynamicNode('local', 'item')]
+        ),
+      ]),
+      dynamicNode('prop', 'items'),
+      {
+        useIndex: true,
+      }
+    ),
+  ]),
+  {
+    items: definition('object', { test: '123' }),
+    test: definition('string', '123'),
+    content: definition('object', { heading: 'Hello World' }),
+  },
+  {}
+)
+
 describe('Vue Props in Component Generator', () => {
   describe('supports props json declaration in attributes', () => {
     const generator = createVueComponentGenerator()
 
     it('should add attributes on component', async () => {
-      const result = await generator.generateComponent(ComponentWithValidProps)
+      const result = await generator.generateComponent(uidl)
       const vueFile = findFileByType(result.files, VUE_FILE)
 
       expect(vueFile.content).toContain(':data-test')
@@ -45,7 +75,7 @@ describe('Vue Props in Component Generator', () => {
     })
 
     it('should run repeat attributes and data source', async () => {
-      const result = await generator.generateComponent(ComponentWithRepeatProps)
+      const result = await generator.generateComponent(uidl)
       const vueFile = findFileByType(result.files, VUE_FILE)
 
       expect(vueFile.content).toContain(':key="index"')
diff --git a/packages/teleport-component-generator-vue/__tests__/integration/component-conditional.ts b/packages/teleport-component-generator-vue/__tests__/integration/component-conditional.ts
new file mode 100644
index 00000000..a687a791
--- /dev/null
+++ b/packages/teleport-component-generator-vue/__tests__/integration/component-conditional.ts
@@ -0,0 +1,45 @@
+import {
+  component,
+  definition,
+  staticNode,
+  dynamicNode,
+  elementNode,
+  conditionalNode,
+} from '@teleporthq/teleport-generator-shared/lib/builders/uidl-builders'
+
+import { createVueComponentGenerator } from '../../src'
+
+const vueGenerator = createVueComponentGenerator()
+
+const uidl = component(
+  'Conditional Component',
+  elementNode('container', {}, [
+    conditionalNode(
+      dynamicNode('state', 'isVisible'),
+      elementNode('text', {}, [staticNode('Now you see me!')]),
+      true
+    ),
+    conditionalNode(
+      dynamicNode('state', 'isShareable'),
+      elementNode('text', {}, [staticNode('I am not shareable!')]),
+      false
+    ),
+  ]),
+  {},
+  { isVisible: definition('boolean', true), isShareable: definition('boolean', false) }
+)
+
+describe('Component with conditional node type', () => {
+  it('renders code with condition if value on state is true', async () => {
+    const result = await vueGenerator.generateComponent(uidl)
+    const code = result.files[0].content
+
+    expect(code).toContain('<span v-if="isVisible">Now you see me!</span>')
+  })
+  it('renders code with !condition if value on state is false', async () => {
+    const result = await vueGenerator.generateComponent(uidl)
+    const code = result.files[0].content
+
+    expect(code).toContain('<span v-if="!isShareable">I am not shareable!</span>')
+  })
+})
diff --git a/packages/teleport-component-generator-vue/__tests__/integration/component-dependency.ts b/packages/teleport-component-generator-vue/__tests__/integration/component-dependency.ts
new file mode 100644
index 00000000..70b058ad
--- /dev/null
+++ b/packages/teleport-component-generator-vue/__tests__/integration/component-dependency.ts
@@ -0,0 +1,130 @@
+import {
+  component,
+  definition,
+  elementNode,
+  componentDependency,
+} from '@teleporthq/teleport-generator-shared/lib/builders/uidl-builders'
+
+import { createVueComponentGenerator } from '../../src'
+
+const vueGenerator = createVueComponentGenerator()
+
+const dependencySample = (
+  name: string,
+  type: string,
+  path: string,
+  version: string,
+  option: object
+) => {
+  return { name, type, path, version, option }
+}
+
+const uidl = (dependency) => {
+  return component(
+    'Component With Dependencies',
+    elementNode(
+      dependency.name,
+      {},
+      [],
+      componentDependency(dependency.type, dependency.path, dependency.version, dependency.option)
+    ),
+    {},
+    { title: definition('boolean', true) }
+  )
+}
+
+describe('Component with dependency ', () => {
+  describe('from package.json', () => {
+    it('renders code with imported package', async () => {
+      const result = await vueGenerator.generateComponent(
+        uidl(
+          dependencySample('ReactDatepicker', 'package', 'react-datepicker', '', {
+            namedImport: false,
+          })
+        )
+      )
+      const code = result.files[0].content
+
+      expect(code).toContain("import ReactDatepicker from 'react-datepicker'")
+    })
+
+    it('renders code with named import ', async () => {
+      const result = await vueGenerator.generateComponent(
+        uidl(
+          dependencySample('ReactDatepicker', 'package', 'react-datepicker', '', {
+            namedImport: true,
+          })
+        )
+      )
+      const code = result.files[0].content
+      expect(code).toContain("import { ReactDatepicker } from 'react-datepicker'")
+    })
+
+    it('renders code with original name', async () => {
+      const result = await vueGenerator.generateComponent(
+        uidl(
+          dependencySample('Router', 'package', 'react-router', '', {
+            namedImport: true,
+            originalName: 'BrowserRouter',
+          })
+        )
+      )
+      const code = result.files[0].content
+      expect(code).toContain("import { BrowserRouter as Router } from 'react-router'")
+    })
+  })
+
+  describe('from local', () => {
+    it('renders code with imported package', async () => {
+      const result = await vueGenerator.generateComponent(
+        uidl(
+          dependencySample('ReactDatepicker', 'local', '../react-datepicker', '', {
+            namedImport: false,
+          })
+        )
+      )
+      const code = result.files[0].content
+
+      expect(code).toContain("import ReactDatepicker from '../react-datepicker'")
+    })
+
+    it('renders code with named import ', async () => {
+      const result = await vueGenerator.generateComponent(
+        uidl(
+          dependencySample('ReactDatepicker', 'local', '../react-datepicker', '', {
+            namedImport: true,
+          })
+        )
+      )
+      const code = result.files[0].content
+      expect(code).toContain("import { ReactDatepicker } from '../react-datepicker'")
+    })
+
+    it('renders code with original name', async () => {
+      const result = await vueGenerator.generateComponent(
+        uidl(
+          dependencySample('Router', 'local', 'react-router', '', {
+            namedImport: true,
+            originalName: 'BrowserRouter',
+          })
+        )
+      )
+      const code = result.files[0].content
+      expect(code).toContain("import { BrowserRouter as Router } from 'react-router'")
+    })
+  })
+
+  describe('from library', () => {
+    it('renders code with named import ', async () => {
+      const result = await vueGenerator.generateComponent(
+        uidl(
+          dependencySample('write', 'local', 'fs', '', {
+            namedImport: true,
+          })
+        )
+      )
+      const code = result.files[0].content
+      expect(code).toContain("import { write } from 'fs'")
+    })
+  })
+})
diff --git a/packages/teleport-component-generator-vue/__tests__/integration/component-repeat.ts b/packages/teleport-component-generator-vue/__tests__/integration/component-repeat.ts
new file mode 100644
index 00000000..52188c71
--- /dev/null
+++ b/packages/teleport-component-generator-vue/__tests__/integration/component-repeat.ts
@@ -0,0 +1,42 @@
+import {
+  component,
+  definition,
+  repeatNode,
+  dynamicNode,
+  elementNode,
+} from '@teleporthq/teleport-generator-shared/lib/builders/uidl-builders'
+
+import { createVueComponentGenerator } from '../../src'
+
+const vueGenerator = createVueComponentGenerator()
+
+const uidl = component(
+  'Repeat Component',
+  elementNode('container', {}, [
+    repeatNode(
+      elementNode('div', {}, [dynamicNode('local', 'item')]),
+      dynamicNode('prop', 'items'),
+      {
+        useIndex: true,
+      }
+    ),
+  ]),
+  { items: definition('array', ['hello', 'world']) },
+  {}
+)
+
+describe('Component Repeat Node', () => {
+  it('renders code that contains map method', async () => {
+    const result = await vueGenerator.generateComponent(uidl)
+    const code = result.files[0].content
+
+    expect(code).toContain('v-for="(item, index) in items"')
+  })
+
+  it('renders code with map method that iterates using index', async () => {
+    const result = await vueGenerator.generateComponent(uidl)
+    const code = result.files[0].content
+
+    expect(code).toContain(':key="index"')
+  })
+})
diff --git a/packages/teleport-component-generator-vue/__tests__/integration/component-with-repeat.json b/packages/teleport-component-generator-vue/__tests__/integration/component-with-repeat.json
deleted file mode 100644
index 1a23950d..00000000
--- a/packages/teleport-component-generator-vue/__tests__/integration/component-with-repeat.json
+++ /dev/null
@@ -1,51 +0,0 @@
-{
-  "$schema": "https://raw.githubusercontent.com/teleporthq/teleport-code-generators/master/packages/teleport-generator-core/src/uidl-schemas/component.json",
-  "name": "ComponentWithAttrProp",
-  "propDefinitions": {
-    "test": {
-      "type": "string",
-      "defaultValue": "123"
-    }
-  },
-  "node": {
-    "type": "element",
-    "content": {
-      "elementType": "container",
-      "children": [{
-        "type": "repeat",
-        "content": {
-          "node": {
-            "type": "element",
-            "content": {
-              "elementType": "container",
-              "children": [{
-                "type": "element",
-                "content": {
-                  "elementType": "container",
-                  "name": "card",
-                  "attrs": {
-                    "test": {
-                      "type": "dynamic",
-                      "content": {
-                        "referenceType": "local",
-                        "id": "index"
-                      }
-                    }
-                  },
-                  "children": [{"type": "dynamic", "content": { "referenceType": "local", "id": "item" }}]
-                }
-              }]
-            }
-          },
-          "dataSource":  { 
-            "type": "dynamic",
-            "content": { "referenceType": "prop", "id": "items" }
-          },
-          "meta": {
-            "useIndex": true
-          }
-        }
-      }]
-    }
-  }
-}
\ No newline at end of file
diff --git a/packages/teleport-component-generator-vue/__tests__/integration/component-with-valid-attr-prop.json b/packages/teleport-component-generator-vue/__tests__/integration/component-with-valid-attr-prop.json
deleted file mode 100644
index 46afe765..00000000
--- a/packages/teleport-component-generator-vue/__tests__/integration/component-with-valid-attr-prop.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
-  "$schema": "https://raw.githubusercontent.com/teleporthq/teleport-code-generators/master/packages/teleport-generator-core/src/uidl-schemas/component.json",
-  "name": "ComponentWithAttrProp",
-  "propDefinitions": {
-    "test": {
-      "type": "string",
-      "defaultValue": "123"
-    },
-    "content": {
-      "type": "object",
-      "defaultValue": {
-        "heading": "Hello World"
-      }
-    }
-  },
-  "node": {
-    "type": "element",
-    "content": {
-      "elementType": "container",
-      "attrs": {
-        "data-test": {
-          "type": "dynamic",
-          "content": {
-            "referenceType":"prop",
-            "id": "test"
-          }
-        },
-        "data-static": {
-          "type": "static",
-          "content": "I am just a static string"
-        },
-        "data-inner-value": {
-          "type": "dynamic",
-          "content": {
-            "referenceType":"prop",
-            "id": "content.heading"
-          }
-        }
-      }
-    }
-  }
-}
\ No newline at end of file
diff --git a/packages/teleport-generator-core/__tests__/resolver/index.ts b/packages/teleport-generator-core/__tests__/resolver/index.ts
index 29e5aac9..577505e0 100644
--- a/packages/teleport-generator-core/__tests__/resolver/index.ts
+++ b/packages/teleport-generator-core/__tests__/resolver/index.ts
@@ -1,11 +1,17 @@
 import { Resolver } from '../../src/'
 // @ts-ignore
 import mappingJSON from './mapping.json'
+import { Mapping } from '@teleporthq/teleport-generator-shared/lib/typings/uidl'
+
 import {
   element,
+  component,
+  definition,
   staticNode,
+  dynamicNode,
+  elementNode,
+  conditionalNode,
 } from '@teleporthq/teleport-generator-shared/lib/builders/uidl-builders'
-import { Mapping } from '@teleporthq/teleport-generator-shared/lib/typings/uidl'
 
 const mapping = mappingJSON as Mapping
 
@@ -29,3 +35,33 @@ describe('resolveElement', () => {
     expect(resolvedElement.attrs.dummy.content).toBe('remains here')
   })
 })
+
+describe('resolveUIDL', () => {
+  const uidl = component(
+    'Conditional Component',
+    elementNode('container', {}, [
+      conditionalNode(
+        dynamicNode('state', 'isVisible'),
+        elementNode('div', {}, [staticNode('Now you see me!')]),
+        true
+      ),
+    ]),
+    {},
+    { isVisible: definition('boolean', true), isShareable: definition('boolean', false) }
+  )
+
+  const extraMapping = {
+    elements: {
+      container: {
+        elementType: 'div',
+      },
+    },
+  }
+
+  const resolver = new Resolver()
+  resolver.addMapping(mapping)
+  const resolvedUIDL = resolver.resolveUIDL(uidl, { mapping: extraMapping })
+  expect(resolvedUIDL.name).toBe('ConditionalComponent')
+  expect(resolvedUIDL.node.type).toBe('element')
+  expect(resolvedUIDL.stateDefinitions.isVisible.type).toBe('boolean')
+})
diff --git a/packages/teleport-generator-core/__tests__/resolver/utils.ts b/packages/teleport-generator-core/__tests__/resolver/utils.ts
index eeb9b711..5e5d0303 100644
--- a/packages/teleport-generator-core/__tests__/resolver/utils.ts
+++ b/packages/teleport-generator-core/__tests__/resolver/utils.ts
@@ -1,6 +1,7 @@
 import {
-  elementNode,
   staticNode,
+  repeatNode,
+  elementNode,
   dynamicNode,
 } from '@teleporthq/teleport-generator-shared/lib/builders/uidl-builders'
 import { generateUniqueKeys, createNodesLookup, resolveChildren } from '../../src/resolver/utils'
@@ -75,6 +76,25 @@ describe('createNodesLookup', () => {
   })
 })
 
+describe('resolveNode', () => {
+  it('elementNode', () => {
+    const elementNodeSample = elementNode('container')
+    expect(elementNodeSample.content.name).toBe('container')
+  })
+  it('repeatNode', () => {
+    const repeatNodeSample = repeatNode(
+      elementNode('div', {}, [dynamicNode('local', 'item')]),
+      dynamicNode('prop', 'items'),
+      {
+        useIndex: true,
+      }
+    )
+    expect(repeatNodeSample.content.node.type).toBe('element')
+    expect(repeatNodeSample.content.node.content).toHaveProperty('name', 'div')
+    expect(repeatNodeSample.content.node.content).toHaveProperty('children')
+  })
+})
+
 describe('resolveChildren', () => {
   it('merges the children when no placeholder is found', () => {
     const mappedChildren = [staticNode('from-mapping')]
diff --git a/packages/teleport-generator-shared/__tests__/utils/ast-jsx-utils.ts b/packages/teleport-generator-shared/__tests__/utils/ast-jsx-utils.ts
index 81389071..d078eef2 100644
--- a/packages/teleport-generator-shared/__tests__/utils/ast-jsx-utils.ts
+++ b/packages/teleport-generator-shared/__tests__/utils/ast-jsx-utils.ts
@@ -1,4 +1,10 @@
-import { createBinaryExpression } from '../../src/utils/ast-jsx-utils'
+import {
+  generateStyledJSXTag,
+  createBinaryExpression,
+  stringAsTemplateLiteral,
+  createJSXSpreadAttribute,
+  generateASTDefinitionForJSXTag,
+} from '../../src/utils/ast-jsx-utils'
 
 describe('createBinaryExpression', () => {
   it('varName === true -> varName', () => {
@@ -28,4 +34,114 @@ describe('createBinaryExpression', () => {
       prefix: true,
     })
   })
+
+  it('varName === text -> varName === text', () => {
+    const condition = { operation: '===', operand: 'text' }
+    const conditionIdentifier = {
+      key: 'isVisible',
+      type: 'string',
+    }
+
+    const result = createBinaryExpression(condition, conditionIdentifier)
+
+    expect(result).toEqual({
+      type: 'BinaryExpression',
+      operator: '===',
+      left: { type: 'Identifier', name: 'isVisible' },
+      right: { type: 'StringLiteral', value: 'text' },
+    })
+  })
+
+  it('varName === undefined -> !varName', () => {
+    const condition = { operation: '===' }
+    const conditionIdentifier = {
+      key: 'isVisible',
+      type: 'string',
+    }
+
+    const result = createBinaryExpression(condition, conditionIdentifier)
+
+    expect(result).toEqual({
+      type: 'UnaryExpression',
+      operator: '!',
+      argument: { type: 'Identifier', name: 'isVisible' },
+      prefix: true,
+    })
+  })
+
+  it('varName == text -> varName === text', () => {
+    const condition = { operation: '==,', operand: 'text' }
+    const conditionIdentifier = {
+      key: 'isVisible',
+      type: 'string',
+    }
+
+    const result = createBinaryExpression(condition, conditionIdentifier)
+
+    expect(result).toEqual({
+      type: 'BinaryExpression',
+      operator: '===',
+      left: { type: 'Identifier', name: 'isVisible' },
+      right: { type: 'StringLiteral', value: 'text' },
+    })
+  })
+
+  it('varName === undefined -> !varName', () => {
+    const condition = { operation: '!' }
+    const conditionIdentifier = {
+      key: 'isVisible',
+      type: 'string',
+    }
+
+    const result = createBinaryExpression(condition, conditionIdentifier)
+
+    expect(result).toEqual({
+      type: 'UnaryExpression',
+      operator: '!',
+      argument: { type: 'Identifier', name: 'isVisible' },
+      prefix: true,
+    })
+  })
+})
+
+describe('stringAsTemplateLiteral', () => {
+  it('returns TemplateLiteral', () => {
+    const result = stringAsTemplateLiteral('randomString')
+
+    expect(result.type).toBe('TemplateLiteral')
+    expect(result.quasis[0].type).toBe('TemplateElement')
+  })
+})
+
+describe('generateStyledJSXTag', () => {
+  it('returns JSXTag', () => {
+    const result = generateStyledJSXTag('randomString')
+
+    expect(result.type).toBe('JSXElement')
+    expect(result.openingElement.type).toBe('JSXOpeningElement')
+    expect(result.openingElement.name).toHaveProperty('name', 'style')
+    expect(result.closingElement.type).toBe('JSXClosingElement')
+    expect(result.closingElement.name).toHaveProperty('name', 'style')
+  })
+})
+
+describe('generateASTDefinitionForJSXTag', () => {
+  it('returns ASTDefinitionForJSXTag', () => {
+    const result = generateASTDefinitionForJSXTag('randomString')
+
+    expect(result.type).toBe('JSXElement')
+    expect(result.openingElement.type).toBe('JSXOpeningElement')
+    expect(result.openingElement.name).toHaveProperty('name', 'randomString')
+    expect(result.closingElement.type).toBe('JSXClosingElement')
+    expect(result.closingElement.name).toHaveProperty('name', 'randomString')
+  })
+})
+
+describe('createJSXSpreadAttribute', () => {
+  it('runs with success', () => {
+    const result = createJSXSpreadAttribute('randomString')
+
+    expect(result.type).toBe('JSXSpreadAttribute')
+    expect(result.argument).toHaveProperty('name', 'randomString')
+  })
 })
diff --git a/packages/teleport-generator-shared/__tests__/utils/project-utils.ts b/packages/teleport-generator-shared/__tests__/utils/project-utils.ts
new file mode 100644
index 00000000..8e7d94d1
--- /dev/null
+++ b/packages/teleport-generator-shared/__tests__/utils/project-utils.ts
@@ -0,0 +1,78 @@
+import {
+  createHtmlIndexFile,
+  createPackageJSONFile,
+  createManifestJSONFile,
+} from '../../src/utils/project-utils'
+
+// @ts-ignore
+import uidlSample from '../../../../examples/test-samples/project-sample.json'
+
+describe('createHtmlIndexFile', () => {
+  it('returns index file with prefixed assets and app file', () => {
+    const HtmlIndexFileOptions = {
+      assetsPrefix: 'playground',
+      fileName: 'app',
+      appRootOverride: 'SomeRandomText?',
+    }
+    const result = createHtmlIndexFile(uidlSample, HtmlIndexFileOptions)
+
+    expect(result.name).toBe('app')
+    expect(result.fileType).toBe('html')
+    expect(result.content).toContain('<!DOCTYPE html>')
+    expect(result.content).toContain('content="playground/playground_assets')
+    expect(result.content).toContain('<body>SomeRandomText?')
+  })
+
+  it('returns index file with no prefixed assets and index file', () => {
+    const HtmlIndexFileOptions = {}
+    const result = createHtmlIndexFile(uidlSample, HtmlIndexFileOptions)
+
+    expect(result.name).toBe('index')
+    expect(result.fileType).toBe('html')
+    expect(result.content).toContain('<!DOCTYPE html>')
+    expect(result.content).toContain('content="/playground_assets')
+  })
+})
+
+describe('createManifestJSONFile', () => {
+  it('returns manifest file with prefixed assets', () => {
+    const assetsPrefix = 'playground'
+    const result = createManifestJSONFile(uidlSample, assetsPrefix)
+
+    expect(result.name).toBe('manifest')
+    expect(result.fileType).toBe('json')
+    expect(result.content).toContain('"src": "playground/playground_assets/')
+  })
+
+  it('returns manifest file with no prefixed assets', () => {
+    const result = createManifestJSONFile(uidlSample)
+
+    expect(result.name).toBe('manifest')
+    expect(result.fileType).toBe('json')
+    expect(result.content).toContain('"src": "/playground_assets/')
+  })
+})
+
+describe('createPackageJSONFile', () => {
+  it('returns package JSON file', () => {
+    const packageJSONTemplate = {
+      name: 'template',
+      description: 'test template',
+      version: '1',
+      main: 'index.js',
+      author: 'teleportHQ',
+      license: 'MIT',
+      dependencies: {},
+    }
+    const options = {
+      dependencies: { test: '1.0.0' },
+      projectName: 'testProject',
+    }
+    const result = createPackageJSONFile(packageJSONTemplate, options)
+
+    expect(result.name).toBe('package')
+    expect(result.fileType).toBe('json')
+    expect(result.content).toContain('"name": "testproject')
+    expect(result.content).toContain('"dependencies": {\n    "test": "1.0.0"\n  }')
+  })
+})
diff --git a/packages/teleport-plugin-react-styled-components/__tests__/index.ts b/packages/teleport-plugin-react-styled-components/__tests__/index.ts
index dbb226f4..c990e460 100644
--- a/packages/teleport-plugin-react-styled-components/__tests__/index.ts
+++ b/packages/teleport-plugin-react-styled-components/__tests__/index.ts
@@ -46,7 +46,7 @@ describe('Testing the functionality for StyledComponents', () => {
     const style = {
       height: staticNode('100px'),
     }
-    const element = elementNode('container', {}, [], style)
+    const element = elementNode('container', {}, [], { type: 'package' }, style)
     const elementWithKey = {
       ...element,
       content: {