import expect from "expect"
import React from "react"
import SwaggerUi from "swagger-ui"
import insertPlugin from "src/standalone/topbar-insert"
import { fromJS } from "immutable"
import { configure, mount } from "enzyme"
import Adapter from "enzyme-adapter-react-15"

configure({ adapter: new Adapter() })

function getSystem(spec) {
  return new Promise((resolve) => {
    const system = SwaggerUi({
      spec,
      domNode: null,
      presets: [
        SwaggerUi.plugins.SpecIndex,
        SwaggerUi.plugins.ErrIndex,
        SwaggerUi.plugins.DownloadUrl,
        SwaggerUi.plugins.SwaggerJsIndex,
      ],
      initialState: {
        layout: undefined
      },
      plugins: [
        insertPlugin,
        () => ({
          statePlugins: {
            spec: {
              wrapSelectors: {
                isOAS3: () => () => true
              }
            }
          }
        }),
        () => ({
          statePlugins: {
            configs: {
              actions: {
                loaded: () => {
                  return {
                    type: "noop"
                  }
                }
              }
            }
          }
        })
      ]
    })
    
    resolve(system)
  })
}

describe("editor topbar insert menu plugin", function() {
  this.timeout(10 * 1000)

  it("should provide a `addToSpec` method as a spec action", async () => {
    const spec = {}
    const system = await getSystem(spec)
    expect(system.specActions.addToSpec).toBeA(Function)
  })

  it("should provide an <InsertMenu /> component to render a menu option", async function(){
    const spec = {}
    const system = await getSystem(spec)
    const InsertMenu = system.getSystem().getComponents("TopbarInsert")
    let wrapper = mount(<InsertMenu {...system} getComponent={(c) => system.getSystem().getComponents(c)} />)
    expect(wrapper.find(".menu-item").length).toEqual(1)
  })
  
  it("should correctly update the spec when addToSpec is called", async () => {
    const spec = {
      "openapi": "3.0.0",
      "info": {
        "version": "1.0.0",
        "title": "My New Service"
      },
      "paths": {
        "/test": {
          "get": {
            "summary": "Sample endpoint for my awesome service.",
            "responses": {
              "200": {
                "description": "OK"
              }
            }
          }
        }
      }
    }

    const toAdd = fromJS({
      "summary": "Sample endpoint for my awesome service.",
      "responses": {
        "200": {
          "description": "OK"
        }
      }
    })

    const expected = {
      "openapi": "3.0.0",
      "info": {
        "version": "1.0.0",
        "title": "My New Service"
      },
      "paths": {
        "/test": {
          "get": {
            "summary": "Sample endpoint for my awesome service.",
            "responses": {
              "200": {
                "description": "OK"
              }
            }
          },
          "post": {
            "summary": "Sample endpoint for my awesome service.",
            "responses": {
              "200": {
                "description": "OK"
              }
            }
          }
        }
      }
    }

    const system = await getSystem(spec)

    system.specActions.addToSpec(["paths", "/test"], toAdd, "post")
    expect(system.specSelectors.specJson().toJS()).toEqual(expected)
  })
})