meetup-generator 0.0.20210128 → 1.2.84

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,9 @@
1
+ require_relative 'version'
2
+
3
+ def gem_version
4
+ format('%s.%s', BASE_VERSION, build_number)
5
+ end
6
+
7
+ def build_number
8
+ ENV['TRAVIS_BUILD_NUMBER'] || 0
9
+ end
@@ -0,0 +1,63 @@
1
+ require 'json'
2
+ require 'yaml'
3
+
4
+ # Everything needed for a meetup generator
5
+ #
6
+ class MeetupGenerator
7
+ attr_reader :words, :lib, :unused_templates
8
+
9
+ def initialize
10
+ grep, dict = find_unix_stuff
11
+ @words = `#{grep} "^[a-z]*$" #{dict}`.split("\n")
12
+ @lib = YAML.load_file(ROOT + 'lib' + 'all_the_things.yaml')
13
+ end
14
+
15
+ def find_unix_stuff
16
+ case RUBY_PLATFORM
17
+ when /solaris/
18
+ %w[/bin/grep /usr/share/lib/dict/words]
19
+ when /linux/
20
+ %w[/bin/grep /usr/share/dict/words]
21
+ when /darwin/
22
+ %w[/usr/bin/grep /usr/share/dict/words]
23
+ else
24
+ abort "unsupported platform: #{RUBY_PLATFORM}"
25
+ end
26
+ end
27
+
28
+ def title
29
+ @unused_templates ||= lib[:template].dup
30
+ t = unused_templates.sample
31
+ unused_templates.delete(t)
32
+ t.scan(/%\w+%/).each { |k| t = t.sub(k, lib[k[1..-2].to_sym].sample) }
33
+ t.scan(/RAND\d+/).each do |i|
34
+ t = t.sub(i, rand(2..(i.sub(/RAND/, '').to_i)).to_s)
35
+ end
36
+ t
37
+ end
38
+
39
+ def talks(count = 5)
40
+ @unused_templates = lib[:template].dup
41
+ count.times.with_object([]) { |_i, a| a.<< title }
42
+ end
43
+
44
+ def talker
45
+ lib[:first_name].sample + ' ' + lib[:last_name].sample
46
+ end
47
+
48
+ def role
49
+ lib[:job_role].sample + ' ' + lib[:job_title].sample
50
+ end
51
+
52
+ def company
53
+ words.sample.sub(/([^aeiou])er$/, '\\1r').downcase + '.io'
54
+ end
55
+
56
+ def refreshment
57
+ lib[:food_style].sample + ' ' + lib[:food].sample
58
+ end
59
+
60
+ def talk
61
+ { talk: talks(1)[0], talker: talker, role: role, company: company }
62
+ end
63
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,4 @@
1
+ # We define the major and minor here. The patch version comes from
2
+ # the Travis build number
3
+ #
4
+ BASE_VERSION = '1.2'.freeze
@@ -1,13 +1,11 @@
1
- # frozen_string_literal: true
2
-
1
+ require 'pathname'
3
2
  require 'date'
4
-
5
- # Github actions sets the RELEASE_VERSION environment variable
3
+ require 'English'
4
+ require_relative 'lib/build_helpers'
6
5
 
7
6
  Gem::Specification.new do |gem|
8
7
  gem.name = 'meetup-generator'
9
- gem.version = ENV['RELEASE_VERSION'] ||
10
- "0.0.#{Time.now.strftime('%Y%m%d')}"
8
+ gem.version = gem_version
11
9
  gem.date = Date.today.to_s
12
10
 
13
11
  gem.summary = 'Stupid fatuous random string generatpr'
@@ -15,29 +13,23 @@ Gem::Specification.new do |gem|
15
13
  'DevOps meetup, using all the latest buzzwords, ' \
16
14
  'new-shiny, and clichés'
17
15
  gem.authors = ['Robert Fisher']
18
- gem.email = 'rob@sysdef.xyz'
16
+ gem.email = 'slackboy@gmail.com'
19
17
  gem.homepage = 'https://github.com/snltd/meetup-generator'
20
18
  gem.license = 'BSD-2-Clause'
21
19
 
22
- gem.bindir = 'bin'
23
- gem.executables = ['meetup-generator.rb', 'locate_meetup-generator']
24
- gem.files = IO.readlines('package/runtime_files', chomp: true)
20
+ gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
25
21
  gem.test_files = gem.files.grep(%r{^spec/})
26
- gem.require_paths = %w[lib]
27
22
 
28
- gem.add_runtime_dependency 'puma', '~> 5.1'
29
- gem.add_runtime_dependency 'sinatra', '~>2.1'
30
- gem.add_runtime_dependency 'slim', '~> 4.1'
23
+ gem.add_runtime_dependency 'sinatra', '~>2.0', '>= 2.0.1'
24
+ gem.add_runtime_dependency 'slim', '~> 3.0', '>= 3.0.0'
25
+ gem.add_runtime_dependency 'puma', '~> 3.11', '>= 3.11.0'
31
26
 
32
- gem.add_development_dependency 'bundler', '~> 2.0'
33
- gem.add_development_dependency 'minitest', '~> 5.14'
34
- gem.add_development_dependency 'nokogiri', '~> 1.10'
35
- gem.add_development_dependency 'rack-test', '~> 1.1'
36
- gem.add_development_dependency 'rake', '~> 13.0'
37
- gem.add_development_dependency 'rubocop', '~> 1.9'
38
- gem.add_development_dependency 'rubocop-minitest', '~> 0.10'
39
- gem.add_development_dependency 'rubocop-performance', '~> 1.3'
40
- gem.add_development_dependency 'rubocop-rake', '~> 0.5'
27
+ gem.add_development_dependency 'bundler', '~> 1.3'
28
+ gem.add_development_dependency 'minitest', '~> 5.11', '>= 5.11.0'
29
+ gem.add_development_dependency 'nokogiri', '~> 1.8', '>= 1.8.0'
30
+ gem.add_development_dependency 'rack-test', '~> 0.8', '>= 0.8.0'
31
+ gem.add_development_dependency 'rake', '~> 12.3', '>= 12.3.0'
32
+ gem.add_development_dependency 'rubocop', '~> 0.52', '>= 0.52.0'
41
33
 
42
- gem.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
34
+ gem.required_ruby_version = Gem::Requirement.new('>= 2.2.0')
43
35
  end
data/public/css/main.css CHANGED
@@ -11,15 +11,11 @@ body {
11
11
  line-height: 120%;
12
12
  }
13
13
 
14
- .indent {
14
+ .tperson {
15
15
  font-size: small;
16
16
  margin-left: 12em;
17
17
  }
18
18
 
19
- .indent a {
20
- color: #0f0;
21
- }
22
-
23
19
  ul {
24
20
  list-style: none;
25
21
  }
@@ -31,6 +27,7 @@ li {
31
27
  }
32
28
 
33
29
  .ttitle {
30
+ /*font-style: italic;*/
34
31
  font-weight: bold;
35
32
  background-color: #0ff;
36
33
  color: #000;
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
2
+ #
3
+ # Acceptance tests for the meetup generator. Yeah, I know.
4
+ #
4
5
  %w[minitest minitest/unit minitest/autorun rack/test pathname json
5
6
  yaml cgi nokogiri].each { |f| require f }
6
7
 
@@ -8,25 +9,21 @@ MGROOT = Pathname.new(__FILE__).realpath.dirname.parent
8
9
 
9
10
  OUTER_APP = Rack::Builder.parse_file((MGROOT + 'config.ru').to_s).first
10
11
 
11
- # Acceptance tests for the meetup generator. Yeah, I know.
12
- #
13
12
  class TestApp < MiniTest::Test
14
13
  attr_reader :things
15
-
16
14
  include Rack::Test::Methods
17
15
 
18
16
  def initialize(args)
19
17
  super(args)
20
- @things = YAML.safe_load(IO.read(MGROOT + 'lib' + 'all_the_things.yaml'),
21
- symbolize_names: true)
18
+ @things = YAML.load_file(MGROOT + 'lib' + 'all_the_things.yaml')
22
19
  end
23
20
 
24
21
  def app
25
22
  OUTER_APP
26
23
  end
27
24
 
28
- # Load the page a thousand times and make sure no talk titles
29
- # occur twice
25
+ # Load the page 1000 times and make sure no talk titles occur
26
+ # twice
30
27
  #
31
28
  def test_no_repeats
32
29
  1000.times do
@@ -36,80 +33,54 @@ class TestApp < MiniTest::Test
36
33
  end
37
34
  end
38
35
 
39
- # Get all of the templates used to generate talk titles, and
40
- # re-run the test until we've seen them all. Then we know no
41
- # template causes a crash. That's good enough.
42
- #
43
36
  def test_default
37
+ #
38
+ # Get all of the templates used to generate talk titles, and re-run
39
+ # the test until we've seen them all. Then we know no template
40
+ # causes a crash. That's good enough.
41
+ #
44
42
  templates = things[:template].map do |t|
45
43
  escaped = Regexp.escape(CGI.escapeHTML(t))
46
- matcher = escaped.gsub(/%\w+%/, '[\w\-]+').gsub(/RAND\d+/, '\d+')
47
- .gsub(/FNOPS/, '\w+')
44
+ matcher = escaped.gsub(/%\w+%/, '\w+').gsub(/RAND\d+/, '\d+')
48
45
  Regexp.new('^.*ttitle">' + matcher + '</span>.*$')
49
46
  end
50
47
 
51
48
  until templates.empty?
52
49
  get '/'
53
- assert_equal('text/html;charset=utf-8',
54
- last_response.header['Content-Type'])
55
- last_response.ok?
56
- resp = last_response.body
57
- assert_match(/The code./, resp)
58
- assert_match(/DevOps Meetup/, resp)
59
- templates.each { |t| templates.delete(t) if resp.match?(t) }
50
+ assert last_response.ok?
51
+ assert last_response.header['Content-Type'] == 'text/html;charset=utf-8'
52
+ x = last_response.body
53
+ assert_match(/The code./, x)
54
+ assert_match(/DevOps Meetup/, x)
55
+ templates.each { |t| templates.delete(t) if x.match(t) }
60
56
  end
61
57
  end
62
58
 
63
- def test_api_talker
64
- get format('/api/talker')
65
- assert last_response.ok?
66
- assert_instance_of(String, last_response.body)
67
- assert_match(/^"\w+ \w+"$/, last_response.body)
68
- assert last_response.header['Content-Type'] == 'application/json'
69
- end
70
-
71
- def test_api_company
72
- get format('/api/company')
59
+ def test_api_talk
60
+ get '/api/talk'
73
61
  assert last_response.ok?
74
- assert_instance_of(String, last_response.body)
75
- assert_match(/^"\w+.io"$/, last_response.body)
76
62
  assert last_response.header['Content-Type'] == 'application/json'
63
+ resp = last_response.body
64
+ refute_empty resp
65
+ j = JSON.parse(resp)
66
+ fields = %w[talk talker role company]
67
+ assert_equal(j.keys, fields)
68
+ fields.each { |f| refute_empty j[f] }
69
+ name = j['talker'].split
70
+ assert_includes(things[:first_name], name.first)
71
+ assert_includes(things[:last_name], name.last)
72
+ assert j['company'].end_with?('.io')
77
73
  end
78
74
 
79
75
  def test_api_misc
80
- %w[title role refreshment location date].each do |word|
81
- get format('/api/%<word>s', word: word)
76
+ %w[title talker company role refreshment].each do |word|
77
+ get format('/api/%s', word)
82
78
  assert last_response.ok?
83
- assert_instance_of(String, last_response.body)
84
79
  assert last_response.header['Content-Type'] == 'application/json'
85
80
  end
86
81
  end
87
82
 
88
- def test_api_talk
89
- get format('/api/talk')
90
- assert last_response.ok?
91
- assert_instance_of(String, last_response.body)
92
- as_obj = JSON.parse(last_response.body, symbolize_names: true)
93
- assert_equal(%i[title talker role company], as_obj.keys)
94
- end
95
-
96
- def test_api_agenda
97
- get format('/api/agenda')
98
- assert last_response.ok?
99
- assert_instance_of(String, last_response.body)
100
- agenda = JSON.parse(last_response.body, symbolize_names: true)
101
- assert_equal(%i[date location refreshment talks], agenda.keys.sort)
102
-
103
- agenda[:talks].each do |t|
104
- assert_equal(%i[title talker role company], t.keys)
105
- end
106
-
107
- assert_instance_of(String, agenda[:refreshment])
108
- assert_instance_of(String, agenda[:date])
109
- assert_instance_of(String, agenda[:location])
110
- end
111
-
112
- def test_api_not_found
83
+ def test_api_404
113
84
  get '/api/no_such_thing'
114
85
  assert_equal(last_response.status, 404)
115
86
  end
data/spec/unit_spec.rb ADDED
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'minitest/autorun'
4
+ require_relative '../lib/meetup-generator'
5
+
6
+ THINGS = { food_style: %w[artisan],
7
+ food: %w[flatbread],
8
+ first_name: %w[John],
9
+ last_name: %w[Smith],
10
+ job_role: %w[Neckbeard],
11
+ job_title: ['Without Portfolio'],
12
+ tech: %w[Ruby],
13
+ template: ['RAND20 %tech% things'] }.freeze
14
+
15
+ class Giblets < MeetupGenerator
16
+ def initialize; end
17
+ end
18
+
19
+ class GibletsTest < MiniTest::Test
20
+ attr_reader :m
21
+
22
+ def setup
23
+ @m = Giblets.new
24
+ m.instance_variable_set(:@lib, THINGS)
25
+ end
26
+
27
+ def test_title
28
+ x = m.title
29
+ assert_instance_of(String, x)
30
+ assert !x.empty?
31
+ refute_match(/%\w+%/, x)
32
+ refute_match(/RAND/, x)
33
+ end
34
+
35
+ def test_talk
36
+ x = m.talks(1)
37
+ assert_instance_of(Array, x)
38
+ assert_instance_of(String, x.first)
39
+ toks = x.first.split
40
+ number = toks.first.to_i
41
+ assert number > 0
42
+ assert number <= 20
43
+ assert_equal('Ruby', toks[1])
44
+ assert_equal('things', toks[2])
45
+ end
46
+
47
+ def test_talker
48
+ assert_equal(m.talker, 'John Smith')
49
+ end
50
+
51
+ def test_role
52
+ assert_equal(m.role, 'Neckbeard Without Portfolio')
53
+ end
54
+
55
+ def test_company_no_e
56
+ m.instance_variable_set(:@words, %w[leadswinger])
57
+ assert_equal(m.company, 'leadswingr.io')
58
+ end
59
+
60
+ def test_company
61
+ m.instance_variable_set(:@words, %w[Cabbage])
62
+ assert_equal(m.company, 'cabbage.io')
63
+ end
64
+
65
+ def test_refreshment
66
+ assert_equal(m.refreshment, 'artisan flatbread')
67
+ end
68
+ end
data/views/default.slim CHANGED
@@ -7,42 +7,42 @@ html
7
7
 
8
8
  body
9
9
  #container
10
- h1
11
- ' #DevOps Meetup //
12
- => @agenda[:location]
13
- ' //
14
- == @agenda[:date]
10
+ h1 #DevOps Meetup // Shoreditch, probably // #{(Date.today + 1).strftime("%d/%m/%Y")}
15
11
 
16
12
  ul
17
13
  li 18:00 // Introduction
18
14
 
19
15
  li
20
16
  ' 18:10 // Lightning talk //
21
- == slim :partial_talk
17
+ span.ttitle=@talks.pop
18
+ .tperson=@jobs.pop
22
19
 
23
20
  li
24
21
  ' 18:20 //
25
- == slim :partial_talk
22
+ span.ttitle=@talks.pop
23
+ .tperson=@jobs.pop
26
24
 
27
- li
28
- ' 18:50 // break
29
- .indent=@agenda[:refreshment]
25
+ li 18:50 // break
26
+ .tperson=@food
30
27
 
31
28
  li
32
29
  ' 19:20 //
33
- == slim :partial_talk
30
+ span.ttitle=@talks.pop
31
+ .tperson=@jobs.pop
34
32
 
35
33
  li
36
34
  ' 19:40 // Ignite //
37
- == slim :partial_talk
35
+ span.ttitle=@talks.pop
36
+ .tperson=@jobs.pop
38
37
 
39
38
  li
40
39
  ' 20:00 //
41
- == slim :partial_talk
40
+ span.ttitle=@talks.pop
41
+ .tperson=@jobs.pop
42
42
 
43
43
  li
44
44
  ' 20:30 // Close
45
- .indent Everyone is hiring, but no one's paying
45
+ .tperson Everyone is hiring, but no one's paying
46
46
 
47
47
  #footer
48
48
  a href='https://github.com/snltd/meetup-generator' The code.
@@ -5,7 +5,7 @@
5
5
  <service_bundle type='manifest' name='snltd:sinatra:meetup-generator'>
6
6
 
7
7
  <service
8
- name='sysdef/meetup-generator'
8
+ name='application/sinatra/meetup-generator'
9
9
  type='service'
10
10
  version='1'>
11
11
 
@@ -90,7 +90,7 @@
90
90
  </common_name>
91
91
 
92
92
  <documentation>
93
- <doc_link name='meetup.sysdef.xyz' uri='http://meetup.sysdef.xyz' />
93
+ <doc_link name='meetup.rfisher.co.uk' uri='http://meetup.rdfisher.co.uk' />
94
94
  </documentation>
95
95
 
96
96
  </template>