You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@whimsical.apache.org by ru...@apache.org on 2017/09/18 17:48:21 UTC

[whimsy] branch agenda_on_vue updated: convert tests from react to vue

This is an automated email from the ASF dual-hosted git repository.

rubys pushed a commit to branch agenda_on_vue
in repository https://gitbox.apache.org/repos/asf/whimsy.git


The following commit(s) were added to refs/heads/agenda_on_vue by this push:
     new f9b06c6  convert tests from react to vue
f9b06c6 is described below

commit f9b06c66859816770ff939f4eb383b42214a20c8
Author: Sam Ruby <ru...@intertwingly.net>
AuthorDate: Mon Sep 18 13:47:36 2017 -0400

    convert tests from react to vue
    
    two additional tests now passing
---
 www/board/agenda/package.json                      |  4 +-
 www/board/agenda/spec/client_spec.rb               | 20 +++--
 www/board/agenda/spec/filters_spec.rb              | 43 +++++++----
 www/board/agenda/spec/forms_spec.rb                | 80 ++++++++++++--------
 .../agenda/spec/{react_server.rb => vue_server.rb} | 85 +++++++++++++++++-----
 www/board/agenda/views/buttons/add-comment.js.rb   |  2 +-
 6 files changed, 162 insertions(+), 72 deletions(-)

diff --git a/www/board/agenda/package.json b/www/board/agenda/package.json
index 6ea8762..f29dbac 100644
--- a/www/board/agenda/package.json
+++ b/www/board/agenda/package.json
@@ -7,7 +7,9 @@
   },
   "devDependencies": {
     "jsdom": "^11.1.0",
+    "jsdom-global": "^3.0.2",
     "jquery": "^3.2.1",
-    "vue": "^2.4.4"
+    "vue": "^2.4.4",
+    "vue-server-renderer": "^2.4.4"
   }
 }
diff --git a/www/board/agenda/spec/client_spec.rb b/www/board/agenda/spec/client_spec.rb
index 35e4b14..2ef240a 100644
--- a/www/board/agenda/spec/client_spec.rb
+++ b/www/board/agenda/spec/client_spec.rb
@@ -5,9 +5,9 @@
 #
 
 require_relative 'spec_helper'
-require_relative 'react_server'
+require_relative 'vue_server'
 
-describe "client", type: :feature, server: :react do
+describe "client", type: :feature, server: :vue do
   #
   # Agenda model
   #
@@ -15,15 +15,21 @@ describe "client", type: :feature, server: :react do
     it "should link pages in agenda traversal order" do
       @parsed = Agenda.parse 'board_agenda_2015_02_18.txt', :quick
 
-      on_react_server do
+      on_vue_server do
+
         agenda = Agenda.load(@parsed)
+        container = document.createElement('div')
 
-        output = _div agenda do |item|
-          _item.next item.next.href, class: item.href if item.next
-          _item.prev item.prev.href, class: item.href if item.prev
+        class TestClient < Vue
+          def render
+            _div agenda do |item|
+              _item.next item.next.href, class: item.href if item.next
+              _item.prev item.prev.href, class: item.href if item.prev
+            end
+          end
         end
 
-        response.end ReactDOMServer.renderToStaticMarkup(output)
+        Vue.renderResponse(TestClient, response)
       end
 
       expect(page).not_to have_selector '.Call-to-order.prev'
diff --git a/www/board/agenda/spec/filters_spec.rb b/www/board/agenda/spec/filters_spec.rb
index 6d97a80..31bf6a1 100644
--- a/www/board/agenda/spec/filters_spec.rb
+++ b/www/board/agenda/spec/filters_spec.rb
@@ -1,7 +1,7 @@
 require_relative 'spec_helper'
-require_relative 'react_server'
+require_relative 'vue_server'
 
-describe "filters", type: :feature, server: :react do
+describe "filters", type: :feature, server: :vue do
   before :all do
     @parsed = Agenda.parse 'board_agenda_2015_02_18.txt', :quick
   end
@@ -13,11 +13,16 @@ describe "filters", type: :feature, server: :react do
     it "should convert http addresses to links" do
       @item = @parsed.find {|item| item['title'] == 'Clerezza'}
 
-      on_react_server do
-        container = document.createElement('div')
-        ReactDOM.render _Report(item: Agenda.new(@item)), container do
-          response.end container.innerHTML
+      on_vue_server do
+        agenda_item = Agenda.new(@item)
+
+        class TestReport < Vue
+          def render
+            _Report item: agenda_item
+          end
         end
+
+        Vue.renderResponse TestReport, response
       end
 
       expect(page).to have_selector 'a[href="http://s.apache.org/EjO"]'
@@ -31,11 +36,16 @@ describe "filters", type: :feature, server: :react do
     it "should convert start time to local time on call to order" do
       @item = @parsed.find {|item| item['title'] == 'Call to order'}
 
-      on_react_server do
-        container = document.createElement('div')
-        ReactDOM.render _Report(item: Agenda.new(@item)), container do
-          response.end container.innerHTML
+      on_vue_server do
+        agenda_item = Agenda.new(@item)
+
+        class TestReport < Vue
+          def render
+            _Report item: agenda_item
+          end
         end
+
+        Vue.renderResponse TestReport, response
       end
 
       expect(page).to have_selector 'span.hilite', text: /Local Time:/
@@ -52,11 +62,16 @@ describe "filters", type: :feature, server: :react do
         rubys: {name: "Sam Ruby", member: true, attending: true}
       })
 
-      on_react_server do
-        container = document.createElement('div')
-        ReactDOM.render _Report(item: Agenda.new(@item)), container do
-          response.end container.innerHTML
+      on_vue_server do
+        agenda_item = Agenda.new(@item)
+
+        class TestReport < Vue
+          def render
+            _Report item: agenda_item
+          end
         end
+
+        Vue.renderResponse TestReport, response
       end
 
       expect(page).to have_selector \
diff --git a/www/board/agenda/spec/forms_spec.rb b/www/board/agenda/spec/forms_spec.rb
index 8783a7f..1d66132 100644
--- a/www/board/agenda/spec/forms_spec.rb
+++ b/www/board/agenda/spec/forms_spec.rb
@@ -3,20 +3,22 @@
 #
 
 require_relative 'spec_helper'
-require_relative 'react_server'
+require_relative 'vue_server'
 
-describe "forms", type: :feature, server: :react do
+describe "forms", type: :feature, server: :vue do
   #
   # Comment form
   #
   describe "comment form" do
     it "has an add-comment form with a disabled Save button" do
-      on_react_server do
-        server = {pending: {}, initials: 'sr'}
-        container = document.createElement('div')
-        ReactDOM.render _AddComment(item: {}, server: server), container do
-          response.end container.innerHTML
+      on_vue_server do
+        class TestCommentForm < Vue
+          def render
+            _AddComment(item: {}, server: {pending: {}, initials: 'sr'})
+          end
         end
+
+        Vue.renderResponse(TestCommentForm, response)
       end
 
       expect(page).to have_selector '.modal#comment-form'
@@ -30,17 +32,23 @@ describe "forms", type: :feature, server: :react do
     end
 
     it "should enable Save button after input" do
-      on_react_server do
+      on_vue_server do
         server = {pending: {}, initials: 'sr'}
-        container = document.createElement('div')
-        ReactDOM.render _AddComment(item: {}, server: server), container do
-          node = container.querySelector('#comment-text')
-          node.textContent = 'Good job!'
-          Simulate.change node, target: {value: 'Good job!'}
-          response.end container.innerHTML
+
+        class TestCommentForm < Vue
+          def render
+            _AddComment(item: {}, server: {pending: {}, initials: 'sr'})
+          end
         end
+
+        app = Vue.renderApp(TestCommentForm)
+        node = app.querySelector('#comment-text')
+        node.textContent = 'Good job!'
+        app.dispatchEvent(Event.new('input'))
+        response.end app.innerHTML
       end
 
+      puts page.body
       expect(page).to have_selector '.modal-footer .btn-warning', text: 'Delete'
       expect(page).to have_selector \
         '.modal-footer .btn-primary:not([disabled])', text: 'Save'
@@ -54,12 +62,16 @@ describe "forms", type: :feature, server: :react do
     it "should indicate when a reflow is needed" do
       parsed = Agenda.parse 'board_agenda_2015_02_18.txt', :quick
       @item = parsed.find {|item| item['title'] == 'Executive Vice President'}
-      on_react_server do
+      on_vue_server do
         item = Agenda.new(@item)
-        container = document.createElement('div')
-        ReactDOM.render _Post(item: item, button: 'edit report'), container do
-          response.end container.innerHTML
+
+        class TestPostForm < Vue
+          def render
+            _Post(item: item, button: 'edit report')
+          end
         end
+
+        Vue.renderResponse(TestPostForm, response)
       end
 
       expect(find('#post-report-text').value).to match(/to answer\nquestions/)
@@ -70,15 +82,21 @@ describe "forms", type: :feature, server: :react do
     it "should perform a reflow" do
       parsed = Agenda.parse 'board_agenda_2015_02_18.txt', :quick
       @item = parsed.find {|item| item['title'] == 'Executive Vice President'}
-      on_react_server do
+      on_vue_server do
         item = Agenda.new(@item)
-        container = document.createElement('div')
-        ReactDOM.render _Post(item: item, button: 'edit report'), container do
-          Simulate.click container.querySelector('.btn-danger')
-          post_report = container.querySelector('#post-report-text')
-          post_report.textContent = this.state.report
-          response.end container.innerHTML
+
+        class TestPost < Vue
+          def render
+            _Post(item: item, button: 'edit report')
+          end
         end
+
+        app = Vue.renderApp(TestPost)
+        button = app.querySelector('.btn-danger')
+        app.dispatchEvent(new Event('click'), button)
+        post_report = app.querySelector('#post-report-text')
+        post_report.textContent = this.state.report
+        response.end app.innerHTML
       end
 
       expect(find('#post-report-text').value).to match(/to\nanswer questions/)
@@ -93,13 +111,17 @@ describe "forms", type: :feature, server: :react do
   describe "commit form" do
     it "should generate a default commit message" do
       @parsed = Agenda.parse 'board_agenda_2015_02_18.txt', :quick
-      on_react_server do
+      on_vue_server do
         Agenda.load(@parsed)
         server = {pending: {approved: ['7'], comments: {I: 'Nice report!'}}}
-        container = document.createElement('div')
-        ReactDOM.render _Commit(item: {}, server: server), container do
-          response.end container.innerHTML
+
+        class TestCommit < Vue
+          def render
+            _Commit(item: {}, server: server)
+          end
         end
+
+        Vue.renderResponse TestCommit, response
       end
 
       expect(page).to have_selector '#commit-text',
diff --git a/www/board/agenda/spec/react_server.rb b/www/board/agenda/spec/vue_server.rb
similarity index 56%
rename from www/board/agenda/spec/react_server.rb
rename to www/board/agenda/spec/vue_server.rb
index d628c4e..16acdf4 100644
--- a/www/board/agenda/spec/react_server.rb
+++ b/www/board/agenda/spec/vue_server.rb
@@ -1,6 +1,6 @@
 #
 # This class spawns a io.js process to run a HTTP server which accepts
-# POST requests containing React TestUtils scripts and responds with 
+# POST requests containing Vue/jsdom scripts and responds with 
 # HTML results.  It provides a Rack interface, enabling this server to
 # be run with Capybara/RackTest.
 #
@@ -10,9 +10,9 @@ require 'net/http'
 require 'stringio'
 
 require 'capybara/rspec'
-require 'ruby2js/filter/react'
+require 'ruby2js/filter/vue'
 
-class ReactServer
+class VueServer
   @@pid = nil
   @@port = nil
 
@@ -36,7 +36,7 @@ class ReactServer
         response = new.call('rack.input' => StringIO.new("response.end('hi')"))
         return if response.first == '200' and response.last == 'hi'
         STDERR.puts response
-        raise RuntimeError('Invalid ReactServer response received')
+        raise RuntimeError('Invalid VueServer response received')
       rescue Errno::ECONNREFUSED
         sleep i * 0.1
       end
@@ -71,16 +71,61 @@ class ReactServer
 
   # the server itself
   @@server = proc do
-    JSDOM = require("jsdom").JSDOM
-    global.window = JSDOM.new('<html><body></body></html>').window
-    global.document = global.window.document
-    global.navigator = global.window.navigator
+    cleanup = require("jsdom-global/register")
 
-    React = require('react')
-    ReactDOM = require('react-dom')
-    ReactDOMServer = require('react-dom/server');
-    TestUtils = require('react-dom/test-utils')
-    Simulate = TestUtils.Simulate
+    process.env.VUE_ENV = 'server'
+
+    Vue = require('vue')
+    Vue.config.productionTip = false
+
+    # render a response, using server side rendering
+    def Vue.renderResponse(component, response)
+      renderer = require('vue-server-renderer').createRenderer()
+      app = Vue.new(render: proc {|h| return h(component)})
+
+      renderer.renderToString(app) do |err, html|
+        if err
+          response.end(err.toString() + "\n" + err.stack)
+        else
+          response.end(html)
+        end
+      end
+    end
+
+    # render a element, using client side rendering
+    def Vue.renderElement(component)
+      outer = document.createElement('div')
+      inner = document.createElement('span')
+      outer.appendChild(inner);
+      Vue.new(el: inner, render: proc {|h| return h(component)})
+      return outer.firstChild
+    end
+
+    # render an app, using client side rendering.  Convenience methods are
+    # provided to querySelector, extract outerHTML and to dispatch events.
+    def Vue.renderApp(component)
+      outer = document.createElement('div')
+      inner = document.createElement('span')
+      outer.appendChild(inner);
+      app = Vue.new(el: inner, render: proc {|h| return h(component)})
+      inner = outer.firstChild
+
+      def app.outerHTML
+        return inner.outerHTML
+      end
+
+      def app.querySelector(selector)
+        return outer.querySelector(selector)
+      end
+
+      def app.dispatchEvent(event, element=nil)
+        element ||= inner
+        element.dispatchEvent(event)
+        app._watcher.run()
+      end
+
+      return app
+    end
 
     jQuery = require('jquery')
 
@@ -92,7 +137,7 @@ class ReactServer
       end
 
       request.on 'error' do |error|
-        console.log "ReactServer error: #{error.message}"
+        console.log "VueServer error: #{error.message}"
       end
 
       request.on 'end' do
@@ -110,22 +155,22 @@ class ReactServer
   end
 end
 
-shared_context "react_server", server: :react do
+shared_context "vue_server", server: :vue do
   #
   # administrivia
   #
   before :all do
-    ReactServer.start
+    VueServer.start
     Dir.chdir File.expand_path('../../views', __FILE__) do
       @_script = Ruby2JS.convert(File.read('app.js.rb'), file: 'app.js.rb')
     end
   end
 
   before :each do
-    @_app, Capybara.app = Capybara.app, ReactServer.new
+    @_app, Capybara.app = Capybara.app, VueServer.new
   end
 
-  def on_react_server(&block)
+  def on_vue_server(&block)
     locals = {}
     instance_variables.each do |ivar|
       next if ivar.to_s.start_with? '@_'
@@ -133,7 +178,7 @@ shared_context "react_server", server: :react do
     end
 
     page.driver.post('/', @_script + ';' +
-      Ruby2JS.convert(block, react: true, ivars: locals))
+      Ruby2JS.convert(block, vue: true, vue_h: '$h', ivars: locals).to_s)
   end
 
   after :each do
@@ -141,6 +186,6 @@ shared_context "react_server", server: :react do
   end
 
   at_exit do
-    ReactServer.stop
+    VueServer.stop
   end
 end
diff --git a/www/board/agenda/views/buttons/add-comment.js.rb b/www/board/agenda/views/buttons/add-comment.js.rb
index 5632f01..7c2ad93 100644
--- a/www/board/agenda/views/buttons/add-comment.js.rb
+++ b/www/board/agenda/views/buttons/add-comment.js.rb
@@ -37,7 +37,7 @@ class AddComment < Vue
       #input field: initials
       _input.comment_initials! label: 'Initials',
         placeholder: 'initials', disabled: @disabled,
-        defaultValue: @@server.pending.initials || @@server.initials
+        value: @@server.pending.initials || @@server.initials
 
       #input field: comment text
       _textarea.comment_text!  value: @comment, label: 'Comment',

-- 
To stop receiving notification emails like this one, please contact
['"commits@whimsical.apache.org" <co...@whimsical.apache.org>'].