guard-jest 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 12086254600f743764afab326f8cd7d944139982
4
+ data.tar.gz: 754a8c45c368998d810518e74dd4968f9baa0733
5
+ SHA512:
6
+ metadata.gz: f8d72ca3d8057279249bfafe8709925b4f058ea484180c72a46764ea3e2b52f0e2f178c83ada98a12f3df29d6ea619951b11b2f5f2c0decd27779a0ae9567036
7
+ data.tar.gz: 02c4369e5df3c54de3088e940638baa79fdd81163b87b095d43a7fefd301198d0901446d0f3e030443d31c88c53776fc6fdf72308bd3e5ad305956e2333cb38c
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
@@ -0,0 +1,13 @@
1
+ Metrics/LineLength:
2
+ Max: 100
3
+
4
+ StringLiterals:
5
+ Enabled: false
6
+
7
+ Style/IndentationWidth:
8
+ Width: 4
9
+
10
+
11
+ Style/MultilineMethodCallIndentation:
12
+ EnforcedStyle: indented_relative_to_receiver
13
+ IndentationWidth: 4
@@ -0,0 +1,9 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - "2.2.5"
5
+ - "2.4.0"
6
+ cache: bundler
7
+ bundler_args: --without production --retry=6
8
+ script:
9
+ - bundle exec rake spec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in guard-jest.gemspec
4
+ gemspec
@@ -0,0 +1,5 @@
1
+ guard :rspec, cmd: 'rspec' do
2
+ watch('spec/spec_helper.rb') { 'spec' }
3
+ watch(%r{spec/.+_spec.rb})
4
+ watch(%r{lib/(.+).rb}) { |m| "spec/#{m[1]}_spec.rb" }
5
+ end
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Nathan Stitt
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,70 @@
1
+ [![Build Status](https://travis-ci.org/nathanstitt/guard-jest.svg?branch=master)](https://travis-ci.org/nathanstitt/guard-jest)
2
+
3
+ # Guard::Jest automatically tests your Jest specs when files are modified.
4
+
5
+ It runs the Jest server in watch mode, so that it can run specs more efficiently when instructed.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ Add Guard::Jest to your `Gemfile`:
12
+
13
+ ```ruby
14
+ group :development, :test do
15
+ gem 'guard-jest'
16
+ end
17
+ ```
18
+
19
+ Add the default Guard::Jest template to your `Guardfile` by running:
20
+
21
+ ```bash
22
+ $ guard init jest
23
+ ```
24
+ ## Usage
25
+
26
+ Please read the [Guard usage documentation](https://github.com/guard/guard#readme).
27
+
28
+ ## Guardfile
29
+
30
+ Guard::Jest can be adapted to all kind of projects. Please read the
31
+ [Guard documentation](https://github.com/guard/guard#readme) for more information about the Guardfile DSL.
32
+
33
+ ```ruby
34
+ guard 'jest' do
35
+ watch(%r{spec/javascripts/spec\.(js\.coffee|js|coffee)$}) { "spec/javascripts" }
36
+ watch(%r{spec/javascripts/.+_spec\.(js\.coffee|js|coffee)$})
37
+ watch(%r{app/assets/javascripts/(.+?)\.(js\.coffee|js|coffee)$}) { |m| "spec/javascripts/#{m[1]}_spec.#{m[2]}" }
38
+ end
39
+ ```
40
+
41
+ ## Options
42
+
43
+ There are many options that can customize Guard::Jest to your needs. Options are simply supplied as hash when
44
+ defining the Guard in your `Guardfile`:
45
+
46
+ ```ruby
47
+ guard 'jest', jest_cmd: './node_modules/jest-cli/bin/jest.js' do
48
+ ...
49
+ end
50
+ ```
51
+
52
+ ### Server options
53
+
54
+ The server options configures the server environment that is needed to run Guard::Jest:
55
+
56
+ ```ruby
57
+ directory: <cwd> # Directory that should be used for running Jest
58
+ config_file: nil # Path to a [Jest configuration file](https://facebook.github.io/jest/docs/configuration.html)
59
+
60
+ jest_cmd: jest # Command to execute in order to start the Jest server
61
+ ```
62
+
63
+ ## Contributing
64
+
65
+ Bug reports and pull requests are welcome on GitHub at https://github.com/nathanstitt/guard-jest.
66
+
67
+
68
+ ## License
69
+
70
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ begin
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new(:spec)
5
+ rescue LoadError
6
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "guard/jest"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,38 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'guard/jest/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "guard-jest"
8
+ spec.version = Guard::Jest::VERSION
9
+ spec.authors = ["Nathan Stitt"]
10
+ spec.email = ["nathan@stitt.org"]
11
+
12
+ spec.summary = 'Guard plugin for auto-running Jest specs'
13
+ spec.description = 'Guard plugin for testing Javascript using the Jest test runner'
14
+ spec.homepage = "https://github.com/nathanstitt/guard-jest"
15
+ spec.license = "MIT"
16
+
17
+ if spec.respond_to?(:metadata)
18
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
19
+ else
20
+ raise "RubyGems 2.0 or newer is required to protect against " \
21
+ "public gem pushes."
22
+ end
23
+
24
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
25
+ f.match(%r{^(test|spec|features)/})
26
+ end
27
+ spec.bindir = "exe"
28
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
29
+ spec.require_paths = ["lib"]
30
+
31
+ spec.add_dependency 'guard-compat', '~> 1.2'
32
+ spec.add_dependency 'concurrent-ruby', '~> 1.0.4'
33
+
34
+ spec.add_development_dependency 'rake', '~> 10.0'
35
+ spec.add_development_dependency 'bundler', '~> 1.13'
36
+ spec.add_development_dependency 'rspec', '~> 3.5'
37
+ spec.add_development_dependency 'guard-rspec', '~> 4.7'
38
+ end
@@ -0,0 +1,16 @@
1
+ require 'rails/generators'
2
+
3
+ module GuardJest
4
+ class InstallGenerator < Rails::Generators::Base
5
+ desc 'Install a sample Guardfile for running Jest specs via GuardJest'
6
+
7
+ def self.source_root
8
+ @source_root ||= File.join(File.dirname(__FILE__), 'templates')
9
+ end
10
+
11
+ # Generator Code. Remember this is just suped-up Thor so methods are executed in order
12
+ def install
13
+ template 'Guardfile'
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :jest do
5
+ watch(%r{^spec/javascripts/.*(?:_s|S)pec\.(coffee|js)$})
6
+ watch(%r{app/assets/javascripts/(.+?)\.(js\.coffee|js|coffee)(?:\.\w+)*$}) do |m|
7
+ "spec/javascripts/#{m[1]}_spec.#{m[2]}"
8
+ end
9
+ end
@@ -0,0 +1,113 @@
1
+ require 'logger'
2
+ require 'guard/compat/plugin'
3
+
4
+ require_relative 'jest/version'
5
+ require_relative 'jest/formatter'
6
+ require_relative 'jest/run_request'
7
+ require_relative 'jest/runner'
8
+ require_relative 'jest/server'
9
+
10
+ module Guard
11
+ # The Jest guard that gets notifications about the following
12
+ # Guard events: `start`, `stop`, `reload`, `run_all` and `run_on_modifications`.
13
+ class Jest < Plugin
14
+ class << self
15
+ attr_writer :logger
16
+ def logger
17
+ @logger ||= ( l = Logger.new(STDOUT); l.level = Logger::INFO; l )
18
+ end
19
+ end
20
+
21
+ DEFAULT_OPTIONS = {
22
+ jest_cmd: 'jest'
23
+ }.freeze
24
+
25
+ attr_reader :runner, :server
26
+
27
+ # Initialize Guard::Jest
28
+ #
29
+ # @param [Hash] options the options for the Guard
30
+ # @option options [String] :config_file the location of a Jest configuration file
31
+ # @option options [String] :jest_cmd path to jest application that should be executed
32
+ #
33
+ def initialize(options = {})
34
+ options = DEFAULT_OPTIONS.merge(options)
35
+ options[:server] = @server = options[:server] || Server.new(options)
36
+ @runner = options[:runner] || Runner.new(options)
37
+ super(options)
38
+ end
39
+
40
+ # Called once when Guard starts. Please override initialize method to init stuff.
41
+ #
42
+ # @raise [:task_has_failed] when start has failed
43
+ # @return [Object] the task result
44
+ #
45
+ def start
46
+ throw :task_has_failed unless server.start
47
+ run_all if options[:all_on_start]
48
+ end
49
+
50
+ # Called when `stop|quit|exit|s|q|e + enter` is pressed (when Guard quits).
51
+ #
52
+ # @raise [:task_has_failed] when stop has failed
53
+ # @return [Object] the task result
54
+ #
55
+ def stop
56
+ throw :task_has_failed unless server.stop
57
+ end
58
+
59
+ # Called when `reload|r|z + enter` is pressed.
60
+ # This method should be mainly used for "reload" (really!) actions like reloading passenger/spork/bundler/...
61
+ #
62
+ # @raise [:task_has_failed] when reload has failed
63
+ # @return [Object] the task result
64
+ #
65
+ def reload
66
+ server_success = server.reload(options)
67
+ runner_success = runner.reload(options)
68
+ throw :task_has_failed unless server_success && runner_success
69
+ end
70
+
71
+ # Called when just `enter` is pressed
72
+ # This method should be principally used for long action like running all specs/tests/...
73
+ #
74
+ # @raise [:task_has_failed] when run_all has failed
75
+ # @return [Object] the task result
76
+ #
77
+ def run_all
78
+ results = runner.test_all
79
+ throw :task_has_failed if results.failed?
80
+ end
81
+
82
+ # Called on file(s) additions that the Guard plugin watches.
83
+ #
84
+ # @param [Array<String>] paths the changes files or paths
85
+ # @raise [:task_has_failed] when run_on_additions has failed
86
+ # @return [Object] the task result
87
+ #
88
+ def run_on_additions(paths)
89
+ run_on_modifications(paths)
90
+ end
91
+
92
+ # Called on file(s) modifications that the Guard plugin watches.
93
+ #
94
+ # @param [Array<String>] paths the changes files or paths
95
+ # @raise [:task_has_failed] when run_on_modifications has failed
96
+ # @return [Object] the task result
97
+ #
98
+ def run_on_modifications(paths)
99
+ results = runner.test_paths(paths)
100
+ throw :task_has_failed if results.failed?
101
+ end
102
+
103
+ # Called on file(s) removals that the Guard plugin watches.
104
+ #
105
+ # @param [Array<String>] paths the changes files or paths
106
+ # @raise [:task_has_failed] when run_on_removals has failed
107
+ # @return [Object] the task result
108
+ #
109
+ def run_on_removals(paths)
110
+ runner.remove_paths(paths)
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,103 @@
1
+ require 'guard/compat/plugin'
2
+
3
+ module Guard
4
+ class Jest < Plugin
5
+ # The Guard::Jasmine formatter collects console and
6
+ # system notification methods and enhances them with
7
+ # some color information.
8
+ #
9
+ module Formatter
10
+ class << self
11
+ # Print an info message to the console.
12
+ #
13
+ # @param [String] message the message to print
14
+ # @param [Hash] options the output options
15
+ # @option options [Boolean] :reset reset the UI
16
+ #
17
+ def info(message, options = {})
18
+ Compat::UI.info(message, options)
19
+ end
20
+
21
+ # Print a debug message to the console.
22
+ #
23
+ # @param [String] message the message to print
24
+ # @param [Hash] options the output options
25
+ # @option options [Boolean] :reset reset the UI
26
+ #
27
+ def debug(message, options = {})
28
+ Compat::UI.debug(message, options)
29
+ end
30
+
31
+ # Print a red error message to the console.
32
+ #
33
+ # @param [String] message the message to print
34
+ # @param [Hash] options the output options
35
+ # @option options [Boolean] :reset reset the UI
36
+ #
37
+ def error(message, options = {})
38
+ Compat::UI.error(color(message, ';31'), options)
39
+ end
40
+
41
+ # Print a green success message to the console.
42
+ #
43
+ # @param [String] message the message to print
44
+ # @param [Hash] options the output options
45
+ # @option options [Boolean] :reset reset the UI
46
+ #
47
+ def success(message, options = {})
48
+ Compat::UI.info(color(message, ';32'), options)
49
+ end
50
+
51
+ # Print a yellow pending message to the console.
52
+ #
53
+ # @param [String] message the message to print
54
+ # @param [Hash] options the output options
55
+ # @option options [Boolean] :reset reset the UI
56
+ #
57
+ def spec_pending(message, options = {})
58
+ Compat::UI.info(color(message, ';33'), options)
59
+ end
60
+
61
+ # Print a red spec failed message to the console.
62
+ #
63
+ # @param [String] message the message to print
64
+ # @param [Hash] options the output options
65
+ #
66
+ def spec_failed(message, options = {})
67
+ Compat::UI.info(color(message, ';31'), options)
68
+ end
69
+
70
+ # Print a red spec failed message to the console.
71
+ #
72
+ # @param [String] message the message to print
73
+ # @param [Hash] options the output options
74
+ #
75
+ def suite_name(message, options = {})
76
+ Compat::UI.info(color(message, ';33'), options)
77
+ end
78
+
79
+ # Outputs a system notification.
80
+ #
81
+ # @param [String] message the message to print
82
+ # @param [Hash] options the output options
83
+ # @option options [Symbol, String] :image the image to use, either :failed, :pending or :success, or an image path
84
+ # @option options [String] :title the title of the system notification
85
+ #
86
+ def notify(message, options = {})
87
+ Compat::UI.notify(message, options)
88
+ end
89
+
90
+ private
91
+
92
+ # Print a info message to the console.
93
+ #
94
+ # @param [String] text the text to colorize
95
+ # @param [String] color_code the color code
96
+ #
97
+ def color(text, color_code)
98
+ Compat::UI.color_enabled? ? "\e[0#{color_code}m#{text}\e[0m" : text
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,41 @@
1
+ require 'concurrent/atomic/atomic_boolean'
2
+
3
+ module Guard
4
+ class Jest < Plugin
5
+ class RunRequest
6
+
7
+ attr_reader :paths, :runner, :result
8
+
9
+ def initialize(runner, paths)
10
+ @runner = runner
11
+ @paths = paths
12
+ @end_time = Time.now
13
+ @start_time = Time.now
14
+ @is_complete = Concurrent::AtomicBoolean.new(false)
15
+ end
16
+
17
+ def all?
18
+ :all == paths
19
+ end
20
+
21
+ def elapsed_seconds
22
+ if satisfied?
23
+ @end_time - @start_time
24
+ else
25
+ Time.now - @start_time
26
+ end
27
+ end
28
+
29
+ def satisfied?
30
+ @is_complete.true?
31
+ end
32
+
33
+ def satisfy(json)
34
+ @end_time = Time.now
35
+ @is_complete.make_true
36
+ @result = json
37
+ runner.notify(self)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,78 @@
1
+ require 'guard/ui'
2
+ require 'guard/compat/plugin'
3
+
4
+ module Guard
5
+ class Jest < Plugin
6
+
7
+ class Runner
8
+ attr_reader :server, :options
9
+
10
+ attr_accessor :last_failed_paths, :last_result
11
+
12
+ def initialize(options)
13
+ reload(options)
14
+ end
15
+
16
+ def reload(options)
17
+ @options = options
18
+ @server = options[:server]
19
+ self.last_failed_paths = []
20
+ end
21
+
22
+ def test_all
23
+ server.run(RunRequest.new(self, :all))
24
+ end
25
+
26
+ def test_paths(paths)
27
+ paths = paths.concat(last_failed_paths) if options[:keep_failed]
28
+
29
+ server.run(RunRequest.new(self, paths.uniq.compact))
30
+ end
31
+
32
+ def remove_paths(paths)
33
+ self.last_failed_paths -= paths
34
+ end
35
+
36
+ def notify(request)
37
+ @last_result = r = request.result
38
+
39
+ specs = r['numTotalTests'] - r['numPendingTests']
40
+ failed = r['numFailedTests']
41
+ specs_plural = specs == 1 ? '' : 's'
42
+ failed_plural = failed == 1 ? '' : 's'
43
+
44
+ Formatter.info("Finished in #{request.elapsed_seconds} seconds")
45
+
46
+ pending = r['numPendingTests'] > 0 ? " #{r['numPendingTests']} pending," : ''
47
+ message = "#{specs} spec#{specs_plural}," \
48
+ "#{pending} #{failed} failure#{failed_plural}"
49
+ full_message = "#{message}\nin #{request.elapsed_seconds} seconds"
50
+
51
+ if failed.zero?
52
+ Formatter.success(message)
53
+ Formatter.notify(full_message, title: 'Jest suite passed')
54
+ else
55
+ Formatter.error(
56
+ collect_spec_error_messages(r['testResults']).join("\n")
57
+ )
58
+ error_title = collect_spec_error_titles(r['testResults']).join("\n")
59
+ Formatter.notify("#{error_title}\n#{full_message}",
60
+ title: 'Jest test run failed', image: :failed, priority: 2)
61
+ end
62
+ end
63
+
64
+ def collect_spec_error_titles(specs)
65
+ specs.select { |s| s['status'] == 'failed' }.map do |s|
66
+ result = s['assertionResults'].detect { |res| res['status'] == 'failed' }
67
+ result ? result['title'] : 'Unknown failure'
68
+ end
69
+ end
70
+
71
+ def collect_spec_error_messages(specs)
72
+ specs.select { |s| s['status'] == 'failed' }.map do |s|
73
+ s['message']
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,132 @@
1
+ require 'concurrent/array'
2
+ require 'concurrent/atomic/atomic_boolean'
3
+ require 'pty'
4
+ require 'json'
5
+
6
+ module Guard
7
+ class Jest < Plugin
8
+
9
+ class Server
10
+ CR = 13.chr
11
+
12
+ attr_reader :stdout, :stdin, :pid, :last_result, :options, :cmd, :pending
13
+
14
+ def initialize(options = {})
15
+ reload(options)
16
+ @work_in_progress = Concurrent::AtomicBoolean.new(false)
17
+ @pending = Concurrent::Array.new
18
+ end
19
+
20
+ def run(request)
21
+ start unless alive?
22
+ pending << request
23
+ work_fifo_queue
24
+ self
25
+ end
26
+
27
+ def failed?
28
+ @pid && !alive?
29
+ end
30
+
31
+ def busy?
32
+ @work_in_progress.true?
33
+ end
34
+
35
+ def wait_until_not_busy
36
+ sleep(0.1) while busy?
37
+ end
38
+
39
+ def start
40
+ @threads = []
41
+ @work_in_progress.make_true
42
+ @directory ? Dir.chdir(@directory) { spawn } : spawn
43
+ @threads << Thread.new do
44
+ @stdout.each { |line| record_result(line) }
45
+ end
46
+ self
47
+ end
48
+
49
+ def alive?
50
+ return false unless pid
51
+ Process.kill(0, pid)
52
+ return true
53
+ rescue Errno::ESRCH # "No such process"
54
+ return false
55
+ rescue Errno::EPERM # "Operation not permitted, but it at least exists
56
+ return true
57
+ else
58
+ return true
59
+ end
60
+
61
+ def stop
62
+ stdin.write('q')
63
+ sleep(0.1)
64
+ return unless alive?
65
+ Process.kill("TERM", pid)
66
+ sleep(0.1)
67
+ Process.kill("KILL", pid) if alive?
68
+ @pid = nil
69
+ end
70
+
71
+ def reload(options)
72
+ @options = options
73
+ @directory = options[:directory]
74
+ @cmd = options[:jest_cmd] + ' --json --silent true --watch'
75
+ @cmd << " --config #{options[:config_file]}" if options[:config_file]
76
+ if alive?
77
+ stop
78
+ start
79
+ end
80
+ self
81
+ end
82
+
83
+ private
84
+
85
+ def work_fifo_queue
86
+ return if busy? || pending.none?
87
+ request = pending.first
88
+ if request.all?
89
+ run_all
90
+ else
91
+ run_paths(request.paths)
92
+ end
93
+ end
94
+
95
+ def run_all
96
+ @work_in_progress.make_true
97
+ stdin.write('a')
98
+ end
99
+
100
+ def run_paths(paths)
101
+ @work_in_progress.make_true
102
+ stdin.write('p')
103
+ # the sleep values simply "seem to work ok" and may need refinement
104
+ sleep(0.1)
105
+ stdin.write(paths.join('|'))
106
+ sleep(0.1)
107
+ stdin.write(CR)
108
+ end
109
+
110
+ def record_result(line)
111
+ # looks vaguely jsonish if it starts with {"
112
+ return unless line.start_with?('{"')
113
+ begin
114
+ json = JSON.parse(line)
115
+ result = @pending.pop
116
+ result.satisfy(json) if result
117
+ @work_in_progress.make_false
118
+ work_fifo_queue
119
+ rescue => e
120
+ Jest.logger.warn e
121
+ end
122
+ end
123
+
124
+ def spawn
125
+ Jest.logger.debug "starting jest with #{cmd}"
126
+ @stdout, @stdin, @pid = PTY.spawn(cmd)
127
+ end
128
+
129
+ end
130
+
131
+ end
132
+ end
@@ -0,0 +1,7 @@
1
+ require 'guard/compat/plugin'
2
+
3
+ module Guard
4
+ class Jest < Plugin
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: guard-jest
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Nathan Stitt
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-01-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: guard-compat
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: concurrent-ruby
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.0.4
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.0.4
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.13'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.13'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.5'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.5'
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard-rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '4.7'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '4.7'
97
+ description: Guard plugin for testing Javascript using the Jest test runner
98
+ email:
99
+ - nathan@stitt.org
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - ".rubocop.yml"
106
+ - ".travis.yml"
107
+ - Gemfile
108
+ - Guardfile
109
+ - LICENSE.txt
110
+ - README.md
111
+ - Rakefile
112
+ - bin/console
113
+ - bin/setup
114
+ - guard-jest.gemspec
115
+ - lib/generators/guard_jest/install_generator.rb
116
+ - lib/generators/guard_jest/templates/Guardfile
117
+ - lib/guard/jest.rb
118
+ - lib/guard/jest/formatter.rb
119
+ - lib/guard/jest/run_request.rb
120
+ - lib/guard/jest/runner.rb
121
+ - lib/guard/jest/server.rb
122
+ - lib/guard/jest/version.rb
123
+ homepage: https://github.com/nathanstitt/guard-jest
124
+ licenses:
125
+ - MIT
126
+ metadata:
127
+ allowed_push_host: https://rubygems.org
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ requirements: []
143
+ rubyforge_project:
144
+ rubygems_version: 2.6.8
145
+ signing_key:
146
+ specification_version: 4
147
+ summary: Guard plugin for auto-running Jest specs
148
+ test_files: []