From f411c816aa1c87d5e6289719d3b10bbe39b22de1 Mon Sep 17 00:00:00 2001 From: Doc Ritezel Date: Fri, 19 Aug 2022 14:07:08 -0700 Subject: [PATCH] WIP - Run jasmine specs --- app/channels/application_cable/channel.rb | 2 +- .../hotwire/jasmine/suites_channel.rb | 29 ++++++++ .../hotwire/jasmine/application_controller.rb | 1 + .../hotwire/jasmine/suites_controller.rb | 11 +++ app/javascript/hotwire/jasmine/application.js | 3 + .../actioncable_reporter_controller.js | 17 +++++ .../jasmine/controllers/application.js | 9 +++ .../controllers/iframe_client_controller.js | 8 ++ .../controllers/iframe_host_controller.js | 8 ++ .../hotwire/jasmine/controllers/index.js | 7 ++ .../jasmine/controllers/suite_controller.js | 74 +++++++++++++++++++ .../hotwire/jasmine/suites/_suite.html.erb | 11 +++ .../hotwire/jasmine/suites/index.html.erb | 8 ++ .../hotwire/jasmine/suites/show.html.erb | 1 + .../hotwire/jasmine/application.html.erb | 20 +++++ config/application.rb | 1 + config/importmap.rb | 13 +++- config/initializers/assets.rb | 6 +- config/initializers/hotwire_jasmine.rb | 7 ++ config/routes.rb | 11 +++ lib/hotwire/jasmine.rb | 14 ++++ lib/hotwire/jasmine/configuration.rb | 13 ++++ lib/hotwire/jasmine/suite.rb | 69 +++++++++++++++++ lib/hotwire/jasmine/suite_finder.rb | 25 +++++++ .../hotwire/jasmine/suites_channel_spec.rb | 29 ++++++++ spec/fixtures/jasmine/example.spec.js | 5 ++ spec/javascript/example.spec.js | 13 ++++ .../hotwire/jasmine/suites_controller_spec.rb | 22 ++++++ spec/support/capybara.rb | 2 +- spec/system/running_a_jasmine_suite_spec.rb | 23 ++++++ 30 files changed, 451 insertions(+), 11 deletions(-) create mode 100644 app/channels/hotwire/jasmine/suites_channel.rb create mode 100644 app/controllers/hotwire/jasmine/application_controller.rb create mode 100644 app/controllers/hotwire/jasmine/suites_controller.rb create mode 100644 app/javascript/hotwire/jasmine/application.js create mode 100644 app/javascript/hotwire/jasmine/controllers/actioncable_reporter_controller.js create mode 100644 app/javascript/hotwire/jasmine/controllers/application.js create mode 100644 app/javascript/hotwire/jasmine/controllers/iframe_client_controller.js create mode 100644 app/javascript/hotwire/jasmine/controllers/iframe_host_controller.js create mode 100644 app/javascript/hotwire/jasmine/controllers/index.js create mode 100644 app/javascript/hotwire/jasmine/controllers/suite_controller.js create mode 100644 app/views/hotwire/jasmine/suites/_suite.html.erb create mode 100644 app/views/hotwire/jasmine/suites/index.html.erb create mode 100644 app/views/hotwire/jasmine/suites/show.html.erb create mode 100644 app/views/layouts/hotwire/jasmine/application.html.erb create mode 100644 config/initializers/hotwire_jasmine.rb create mode 100644 lib/hotwire/jasmine.rb create mode 100644 lib/hotwire/jasmine/configuration.rb create mode 100644 lib/hotwire/jasmine/suite.rb create mode 100644 lib/hotwire/jasmine/suite_finder.rb create mode 100644 spec/channels/hotwire/jasmine/suites_channel_spec.rb create mode 100644 spec/fixtures/jasmine/example.spec.js create mode 100644 spec/javascript/example.spec.js create mode 100644 spec/requests/hotwire/jasmine/suites_controller_spec.rb create mode 100644 spec/system/running_a_jasmine_suite_spec.rb diff --git a/app/channels/application_cable/channel.rb b/app/channels/application_cable/channel.rb index d672697..618cb9e 100644 --- a/app/channels/application_cable/channel.rb +++ b/app/channels/application_cable/channel.rb @@ -1,4 +1,4 @@ module ApplicationCable - class Channel < ActionCable::Channel::Base + class Channel end end diff --git a/app/channels/hotwire/jasmine/suites_channel.rb b/app/channels/hotwire/jasmine/suites_channel.rb new file mode 100644 index 0000000..1db1da9 --- /dev/null +++ b/app/channels/hotwire/jasmine/suites_channel.rb @@ -0,0 +1,29 @@ +module Hotwire + module Jasmine + class SuitesChannel < ActionCable::Channel::Base + def jasmine_started(data) + Hotwire::Jasmine::SuiteFinder.find(data['suiteId']).jasmine_started(data) + end + + def jasmine_suite_started(data) + Hotwire::Jasmine::SuiteFinder.find(data['suiteId']).jasmine_suite_started(data) + end + + def jasmine_spec_started(data) + Hotwire::Jasmine::SuiteFinder.find(data['suiteId']).jasmine_spec_started(data) + end + + def jasmine_spec_done(data) + Hotwire::Jasmine::SuiteFinder.find(data['suiteId']).jasmine_spec_done(data) + end + + def jasmine_suite_done(data) + Hotwire::Jasmine::SuiteFinder.find(data['suiteId']).jasmine_suite_done(data) + end + + def jasmine_done(data) + Hotwire::Jasmine::SuiteFinder.find(data['suiteId']).jasmine_done(data) + end + end + end +end diff --git a/app/controllers/hotwire/jasmine/application_controller.rb b/app/controllers/hotwire/jasmine/application_controller.rb new file mode 100644 index 0000000..c8850f0 --- /dev/null +++ b/app/controllers/hotwire/jasmine/application_controller.rb @@ -0,0 +1 @@ +class Hotwire::Jasmine::ApplicationController < ActionController::Base; end diff --git a/app/controllers/hotwire/jasmine/suites_controller.rb b/app/controllers/hotwire/jasmine/suites_controller.rb new file mode 100644 index 0000000..b2d94f1 --- /dev/null +++ b/app/controllers/hotwire/jasmine/suites_controller.rb @@ -0,0 +1,11 @@ +class Hotwire::Jasmine::SuitesController < Hotwire::Jasmine::ApplicationController + def index + @suites = Hotwire::Jasmine::SuiteFinder.resolve + end + + def show + @suite = Hotwire::Jasmine::SuiteFinder.find(params[:id]) + rescue KeyError + raise ActiveRecord::RecordNotFound, params[:id] + end +end diff --git a/app/javascript/hotwire/jasmine/application.js b/app/javascript/hotwire/jasmine/application.js new file mode 100644 index 0000000..3e5249f --- /dev/null +++ b/app/javascript/hotwire/jasmine/application.js @@ -0,0 +1,3 @@ +// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails +import "@hotwired/turbo-rails" +import "hotwire/jasmine/controllers" diff --git a/app/javascript/hotwire/jasmine/controllers/actioncable_reporter_controller.js b/app/javascript/hotwire/jasmine/controllers/actioncable_reporter_controller.js new file mode 100644 index 0000000..53f6008 --- /dev/null +++ b/app/javascript/hotwire/jasmine/controllers/actioncable_reporter_controller.js @@ -0,0 +1,17 @@ +import { Controller } from '@hotwired/stimulus' +import { createConsumer } from '@rails/actioncable' +const consumer = createConsumer() + +export default class extends Controller { + connect() { + this.channel = consumer.subscriptions.create({channel: 'Hotwire::Jasmine::SuitesChannel'}) + } + + disconnect() { + this.channel.disconnect() + } + + post({type, detail}) { + this.channel.perform(type.replaceAll(':', '_'), detail) + } +} diff --git a/app/javascript/hotwire/jasmine/controllers/application.js b/app/javascript/hotwire/jasmine/controllers/application.js new file mode 100644 index 0000000..28412f1 --- /dev/null +++ b/app/javascript/hotwire/jasmine/controllers/application.js @@ -0,0 +1,9 @@ +import { Application } from '@hotwired/stimulus' + +const application = Application.start() + +// Configure Stimulus development experience +application.debug = false +window.Stimulus = application + +export { application } diff --git a/app/javascript/hotwire/jasmine/controllers/iframe_client_controller.js b/app/javascript/hotwire/jasmine/controllers/iframe_client_controller.js new file mode 100644 index 0000000..9801da2 --- /dev/null +++ b/app/javascript/hotwire/jasmine/controllers/iframe_client_controller.js @@ -0,0 +1,8 @@ +import { Controller } from '@hotwired/stimulus' + +export default class extends Controller { + receive({data: {type, detail}}) { + const event = new CustomEvent(type, {detail, bubbles: true}) + this.element.dispatchEvent(event) + } +} diff --git a/app/javascript/hotwire/jasmine/controllers/iframe_host_controller.js b/app/javascript/hotwire/jasmine/controllers/iframe_host_controller.js new file mode 100644 index 0000000..23c0cc3 --- /dev/null +++ b/app/javascript/hotwire/jasmine/controllers/iframe_host_controller.js @@ -0,0 +1,8 @@ +import { Controller } from '@hotwired/stimulus' + +export default class extends Controller { + post(event) { + const {type, detail} = event + window.parent.postMessage({type, detail}, "*") + } +} diff --git a/app/javascript/hotwire/jasmine/controllers/index.js b/app/javascript/hotwire/jasmine/controllers/index.js new file mode 100644 index 0000000..76af283 --- /dev/null +++ b/app/javascript/hotwire/jasmine/controllers/index.js @@ -0,0 +1,7 @@ +// Import and register all your controllers from the importmap under controllers/* + +import { application } from "hotwire/jasmine/controllers/application" + +// Eager load all controllers defined in the import map under controllers/**/*_controller +import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading" +eagerLoadControllersFrom("hotwire/jasmine/controllers", application) diff --git a/app/javascript/hotwire/jasmine/controllers/suite_controller.js b/app/javascript/hotwire/jasmine/controllers/suite_controller.js new file mode 100644 index 0000000..974560e --- /dev/null +++ b/app/javascript/hotwire/jasmine/controllers/suite_controller.js @@ -0,0 +1,74 @@ +import { Controller } from '@hotwired/stimulus' +import jasmineRequire from 'jasmine-core/lib/jasmine-core/jasmine.js' + +export default class extends Controller { + static values = {id: String} + + initialize() { + this.jasmine = jasmineRequire.core(jasmineRequire); + } + + async connect() { + const { jasmine, idValue } = this; + const global = jasmine.getGlobal(); + global.jasmine = jasmine; + const env = jasmine.getEnv(); + const jasmineInterface = jasmineRequire.interface(jasmine, env); + + env.addReporter(this); + + for (const property in jasmineInterface) { + global[property] = jasmineInterface[property]; + } + + try { + await import(idValue); + await env.execute(); + } finally { + env.clearReporters(); + for (const property in jasmineInterface) { + delete global[property]; + } + } + } + + jasmineStarted({order, ...detail}) { + const { idValue } = this; + this.stack = []; + const event = new CustomEvent('jasmine:started', {detail: {suiteId: idValue, ...detail}, bubbles: true}); + this.element.dispatchEvent(event); + } + + suiteStarted({order, ...detail}) { + const { idValue, stack } = this; + stack.push(detail) + const event = new CustomEvent('jasmine:suite:started', {detail: {suiteId: idValue, ...detail}, bubbles: true}); + this.element.dispatchEvent(event); + } + + specStarted({order, ...detail}) { + const { idValue, stack } = this; + const event = new CustomEvent('jasmine:spec:started', {detail: {suiteId: idValue, stack, ...detail}, bubbles: true}); + this.element.dispatchEvent(event); + } + + specDone({order, ...detail}) { + const { idValue, stack } = this; + const event = new CustomEvent('jasmine:spec:done', {detail: {suiteId: idValue, stack, ...detail}, bubbles: true}); + this.element.dispatchEvent(event); + } + + suiteDone({order, ...detail}) { + const { idValue, stack } = this; + stack.pop(); + const event = new CustomEvent('jasmine:suite:done', {detail: {suiteId: idValue, ...detail}, bubbles: true}); + this.element.dispatchEvent(event); + } + + jasmineDone({order, ...detail}) { + const { idValue } = this; + this.stack = null; + const event = new CustomEvent('jasmine:done', {detail: {suiteId: idValue, ...detail}, bubbles: true}); + this.element.dispatchEvent(event); + } +} diff --git a/app/views/hotwire/jasmine/suites/_suite.html.erb b/app/views/hotwire/jasmine/suites/_suite.html.erb new file mode 100644 index 0000000..9cb597d --- /dev/null +++ b/app/views/hotwire/jasmine/suites/_suite.html.erb @@ -0,0 +1,11 @@ +
+
+ + +
+ +
+
+
+
+
diff --git a/app/views/hotwire/jasmine/suites/index.html.erb b/app/views/hotwire/jasmine/suites/index.html.erb new file mode 100644 index 0000000..66a0b8b --- /dev/null +++ b/app/views/hotwire/jasmine/suites/index.html.erb @@ -0,0 +1,8 @@ +<%= turbo_stream_from 'hotwire_jasmine' %> +<%= turbo_frame_tag 'hotwire_jasmine' do %> + <%= render partial: 'suite', locals: {suites: @suites} %> +<% end %> + +<% @suites.each do |suite| %> + <%= content_tag(:iframe, nil, id: suite.id.parameterize, style: 'display: none;', loading: :eager, src: hotwire_jasmine_suite_path(suite.id), data: {controller: 'actioncable-reporter iframe-client', action: 'message@window->iframe-client#receive jasmine:started->actioncable-reporter#post jasmine:suite:started->actioncable-reporter#post jasmine:spec:started->actioncable-reporter#post jasmine:spec:done->actioncable-reporter#post jasmine:suite:done->actioncable-reporter#post jasmine:done->actioncable-reporter#post'}) %> +<% end %> diff --git a/app/views/hotwire/jasmine/suites/show.html.erb b/app/views/hotwire/jasmine/suites/show.html.erb new file mode 100644 index 0000000..d57b638 --- /dev/null +++ b/app/views/hotwire/jasmine/suites/show.html.erb @@ -0,0 +1 @@ +<%= content_tag(:template, nil, data: {controller: 'suite iframe-host', suite_id_value: @suite.id, action: 'jasmine:started->iframe-host#post jasmine:suite:started->iframe-host#post jasmine:spec:started->iframe-host#post jasmine:spec:done->iframe-host#post jasmine:suite:done->iframe-host#post jasmine:done->iframe-host#post'}) %> diff --git a/app/views/layouts/hotwire/jasmine/application.html.erb b/app/views/layouts/hotwire/jasmine/application.html.erb new file mode 100644 index 0000000..d7d4b18 --- /dev/null +++ b/app/views/layouts/hotwire/jasmine/application.html.erb @@ -0,0 +1,20 @@ + + + + Jasmine + + <%= csrf_meta_tags %> + <%= csp_meta_tag %> + <%= javascript_inline_importmap_tag(JSON.pretty_generate(JSON.parse(Rails.application.importmap.to_json(resolver: self)).deep_merge('imports' => Hotwire::Jasmine::SuiteFinder.resolve.map(&:to_h).reduce(:+)))) %> + <%= javascript_importmap_module_preload_tags %> + <%= javascript_module_preload_tag(Hotwire::Jasmine::SuiteFinder.resolve.map(&:to_h).reduce(:+).values) %> + <%= javascript_importmap_shim_nonce_configuration_tag %> + <%= javascript_importmap_shim_tag %> + <%= javascript_import_module_tag('hotwire/jasmine/application') %> + <%= action_cable_meta_tag %> + <%= stylesheet_link_tag 'https://ga.jspm.io/npm:jasmine-core@4.3.0/lib/jasmine-core/jasmine.css' %> + + + <%= yield %> + + diff --git a/config/application.rb b/config/application.rb index adef089..454d16f 100644 --- a/config/application.rb +++ b/config/application.rb @@ -20,6 +20,7 @@ module Retrospectives class Application < Rails::Application config.load_defaults 7.0 + config.autoload_paths << config.root.join('lib') config.generators do |g| g.helper false g.assets false diff --git a/config/importmap.rb b/config/importmap.rb index 12ef44b..c887429 100644 --- a/config/importmap.rb +++ b/config/importmap.rb @@ -1,9 +1,10 @@ # Pin npm packages by running ./bin/importmap -pin '@hotwired/stimulus', to: 'https://ga.jspm.io/npm:@hotwired/stimulus@3.1.0/dist/stimulus.js' pin '@hotwired/stimulus', to: 'stimulus.min.js', preload: true pin '@hotwired/stimulus-loading', to: 'stimulus-loading.js', preload: true pin '@hotwired/turbo-rails', to: 'turbo.min.js', preload: true +pin 'application' +pin 'canvas-confetti', to: 'https://ga.jspm.io/npm:canvas-confetti@1.5.1/dist/confetti.module.mjs' pin 'hotkeys-js', to: 'https://ga.jspm.io/npm:hotkeys-js@3.9.4/dist/hotkeys.esm.js' pin 'stimulus-dropdown', to: 'https://ga.jspm.io/npm:stimulus-dropdown@2.0.0/dist/stimulus-dropdown.es.js' pin 'stimulus-clipboard', to: 'https://ga.jspm.io/npm:stimulus-clipboard@3.2.0/dist/stimulus-clipboard.es.js' @@ -13,7 +14,11 @@ pin 'stimulus-timeago', to: 'https://ga.jspm.io/npm:stimulus-timeago@4.0.0/dist/stimulus-timeago.es.js' pin 'stimulus-use', to: 'https://ga.jspm.io/npm:stimulus-use@0.50.0/dist/index.js' pin 'tailwindcss-stimulus-components', to: 'https://ga.jspm.io/npm:tailwindcss-stimulus-components@3.0.4/dist/tailwindcss-stimulus-components.modern.js' - -pin 'application', preload: true pin_all_from 'app/javascript/controllers', under: 'controllers' -pin 'canvas-confetti', to: 'https://ga.jspm.io/npm:canvas-confetti@1.5.1/dist/confetti.module.mjs' +pin_all_from 'spec/javascript', to: 'spec/javascript' + +pin_all_from 'app/javascript/hotwire/jasmine/controllers', under: 'hotwire/jasmine/controllers' +pin 'hotwire/jasmine/application', preload: true +pin 'jasmine-core/lib/jasmine-core/jasmine.js', to: 'https://ga.jspm.io/npm:jasmine-core@4.3.0/lib/jasmine-core/jasmine.js' +pin 'process', to: 'https://ga.jspm.io/npm:@jspm/core@2.0.0-beta.24/nodelibs/browser/process-production.js' +pin '@rails/actioncable', to: 'https://ga.jspm.io/npm:@rails/actioncable@7.0.3-1/app/assets/javascripts/actioncable.esm.js' diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index fe48fc3..a9eff7a 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -5,8 +5,4 @@ # Add additional assets to the asset load path. # Rails.application.config.assets.paths << Emoji.images_path - -# Precompile additional assets. -# application.js, application.css, and all non-JS/CSS in the app/assets -# folder are already added. -# Rails.application.config.assets.precompile += %w( admin.js admin.css ) +Rails.application.config.assets.paths << 'spec/javascript' diff --git a/config/initializers/hotwire_jasmine.rb b/config/initializers/hotwire_jasmine.rb new file mode 100644 index 0000000..a7f4ec1 --- /dev/null +++ b/config/initializers/hotwire_jasmine.rb @@ -0,0 +1,7 @@ +require 'hotwire/jasmine' + +Hotwire::Jasmine.configure do |config| + config.paths << Rails.root.join('spec/javascript') +end + +Rails.application.config.hotwire_jasmine_store = ActiveSupport::Cache.lookup_store(:file_store, Rails.root.join('tmp/hotwire/stimulus')) diff --git a/config/routes.rb b/config/routes.rb index 746898e..f86ab6c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,15 @@ Rails.application.routes.draw do + namespace :hotwire do + namespace :jasmine do + resources :suites, only: [:index, :show], id: /.+/ do + resources :specs, only: [:update] + end + end + end + + mount Rack::File.new(Rails.root.join('spec/javascript')) => '/spec/javascript' + mount Rack::File.new(Rails.root.join('spec/fixtures/jasmine')) => '/spec/fixtures/jasmine' + devise_for :users, controllers: {omniauth_callbacks: 'users/omniauth_callbacks'} resources :boards do diff --git a/lib/hotwire/jasmine.rb b/lib/hotwire/jasmine.rb new file mode 100644 index 0000000..32937e0 --- /dev/null +++ b/lib/hotwire/jasmine.rb @@ -0,0 +1,14 @@ +require 'hotwire/jasmine/configuration' +require 'hotwire/jasmine/suite' + +module Hotwire + module Jasmine + def self.configuration + Hotwire::Jasmine::Configuration.instance + end + + def self.configure(&block) + yield(configuration) if block + end + end +end diff --git a/lib/hotwire/jasmine/configuration.rb b/lib/hotwire/jasmine/configuration.rb new file mode 100644 index 0000000..6f2049b --- /dev/null +++ b/lib/hotwire/jasmine/configuration.rb @@ -0,0 +1,13 @@ +module Hotwire + module Jasmine + class Configuration + include Singleton + + attr_accessor :paths + + def initialize(paths: []) + @paths = Array(paths) + end + end + end +end diff --git a/lib/hotwire/jasmine/suite.rb b/lib/hotwire/jasmine/suite.rb new file mode 100644 index 0000000..903a7c5 --- /dev/null +++ b/lib/hotwire/jasmine/suite.rb @@ -0,0 +1,69 @@ +require 'hotwire/jasmine/suite_finder' + +module Hotwire + module Jasmine + class Suite + attr_reader :path + + def initialize(path:) + @path = path + end + + def id + path.dirname.join(basename).to_s + end + + def to_h + {id => "/#{path}"} + end + + def done? + data['done'] + end + + def data + Rails.application.config.hotwire_jasmine_store.fetch(id) { cache_defaults } + end + + def jasmine_started(result) + Rails.application.config.hotwire_jasmine_store.delete(id) + suite = data + suite['totalSpecsDefined'] = result['totalSpecsDefined'] + Rails.application.config.hotwire_jasmine_store.write(id, suite) + end + + def jasmine_suite_started(_) + end + + def jasmine_spec_started(_) + end + + def jasmine_spec_done(result, *args) + suite = data + suite[result['status']] ||= [] + suite[result['status']].push(result) + Rails.application.config.hotwire_jasmine_store.write(id, suite) + end + + def jasmine_suite_done(_) + end + + def jasmine_done(_) + suite = Rails.application.config.hotwire_jasmine_store.fetch(id) { {'done' => false} } + Rails.application.config.hotwire_jasmine_store.write(id, suite.merge('done' => true)) + end + + private + + def cache_defaults + {'done' => false, 'totalSpecsDefined' => 0} + end + + def basename + return path.basename('.js') if path.extname.eql?('.js') + + path.basename + end + end + end +end diff --git a/lib/hotwire/jasmine/suite_finder.rb b/lib/hotwire/jasmine/suite_finder.rb new file mode 100644 index 0000000..2cab68a --- /dev/null +++ b/lib/hotwire/jasmine/suite_finder.rb @@ -0,0 +1,25 @@ +module Hotwire + module Jasmine + class SuiteFinder + attr_reader :paths + + def initialize(paths: []) + @paths = Array(paths) + end + + def self.resolve(paths: Hotwire::Jasmine.configuration.paths) + new(paths: Array(paths)).resolve + end + + def self.find(id) + resolve.index_by { |suite| suite.id }.fetch(id) + end + + def resolve + paths + .flat_map { |path| path.glob('**/*spec.js') } + .map { |path| Suite.new(path: path.relative_path_from(Rails.root)) } + end + end + end +end diff --git a/spec/channels/hotwire/jasmine/suites_channel_spec.rb b/spec/channels/hotwire/jasmine/suites_channel_spec.rb new file mode 100644 index 0000000..deddd63 --- /dev/null +++ b/spec/channels/hotwire/jasmine/suites_channel_spec.rb @@ -0,0 +1,29 @@ +require 'rails_helper' + +RSpec.describe Hotwire::Jasmine::SuitesChannel, type: :channel do + around do |example| + old_paths = Hotwire::Jasmine.configuration.paths + Hotwire::Jasmine.configuration.paths = [Rails.root.join('spec/fixtures/jasmine')] + example.run + ensure + Hotwire::Jasmine.configuration.paths = old_paths + end + + before { subscribe } + + describe '#jasmine_started' do + it 'sets a value inside the jasmine suite' do + perform(:jasmine_started, suiteId: 'spec/fixtures/jasmine/example.spec', totalSpecsDefined: 5) + expect(Hotwire::Jasmine::SuiteFinder.find('spec/fixtures/jasmine/example.spec').data) + .to match(hash_including('totalSpecsDefined' => 5)) + end + end + + describe '#jasmine_done' do + it 'sets the done flag' do + perform(:jasmine_done, suiteId: 'spec/fixtures/jasmine/example.spec') + expect(Hotwire::Jasmine::SuiteFinder.find('spec/fixtures/jasmine/example.spec').data) + .to match(hash_including('done' => true)) + end + end +end diff --git a/spec/fixtures/jasmine/example.spec.js b/spec/fixtures/jasmine/example.spec.js new file mode 100644 index 0000000..8726e76 --- /dev/null +++ b/spec/fixtures/jasmine/example.spec.js @@ -0,0 +1,5 @@ +describe('Example', () => { + it('works', () => { + expect(true).toEqual(true) + }) +}) diff --git a/spec/javascript/example.spec.js b/spec/javascript/example.spec.js new file mode 100644 index 0000000..e64dd3c --- /dev/null +++ b/spec/javascript/example.spec.js @@ -0,0 +1,13 @@ +describe('Example', () => { + describe('when it works', () => { + it('works', () => { + expect(true).toBe(true) + }) + }); + + describe('when javascript does not work', () => { + it('fails', () => { + expect(NaN).toBe(NaN) + }) + }); +}) diff --git a/spec/requests/hotwire/jasmine/suites_controller_spec.rb b/spec/requests/hotwire/jasmine/suites_controller_spec.rb new file mode 100644 index 0000000..50c0e8c --- /dev/null +++ b/spec/requests/hotwire/jasmine/suites_controller_spec.rb @@ -0,0 +1,22 @@ +require 'rails_helper' + +RSpec.describe Hotwire::Jasmine::SuitesController, type: :request do + describe 'GET #index' do + def make_request + get hotwire_jasmine_suites_path + end + + context 'when the path has specs in it' do + before do + Hotwire::Jasmine.configure do |config| + config.paths = [Rails.root.join('spec/fixtures/jasmine')] + end + end + + it 'runs all specs' do + make_request + expect(page).to have_content('spec/fixtures/jasmine/example.spec.js') + end + end + end +end diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb index 136a8f8..812123d 100644 --- a/spec/support/capybara.rb +++ b/spec/support/capybara.rb @@ -10,7 +10,7 @@ Capybara::Cuprite::Driver.new( app, window_size: [1920, 1080], - headless: false + headless: true ) end diff --git a/spec/system/running_a_jasmine_suite_spec.rb b/spec/system/running_a_jasmine_suite_spec.rb new file mode 100644 index 0000000..8348588 --- /dev/null +++ b/spec/system/running_a_jasmine_suite_spec.rb @@ -0,0 +1,23 @@ +require 'rails_helper' + +RSpec.describe 'Running a Jasmine suite', type: :system do + around do |example| + old_paths = Hotwire::Jasmine.configuration.paths + Hotwire::Jasmine.configuration.paths = [Rails.root.join('spec/fixtures/jasmine')] + example.run + ensure + Hotwire::Jasmine.configuration.paths = old_paths + end + + it 'reports statuses', :js do + visit hotwire_jasmine_suites_path + + expect(page).to have_css('#spec-fixtures-jasmine-example-spec', visible: :all) + + timeout = 5.seconds.from_now + until timeout.past? + break if Hotwire::Jasmine::SuiteFinder.resolve.all?(&:done?) + end + expect(timeout).not_to be_past + end +end