cubism 0.1.0.pre10 → 0.1.0.pre13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +16 -0
  3. data/Appraisals~ +16 -0
  4. data/CHANGELOG.md +87 -0
  5. data/Gemfile +7 -0
  6. data/Gemfile.lock +220 -0
  7. data/Gemfile~ +9 -0
  8. data/README.md +35 -14
  9. data/README.md~ +191 -0
  10. data/app/assets/javascripts/cubism.js +141 -0
  11. data/app/assets/javascripts/cubism.min.js +2 -0
  12. data/app/assets/javascripts/cubism.min.js.map +1 -0
  13. data/app/assets/javascripts/cubism.umd.js +149 -0
  14. data/app/assets/javascripts/cubism.umd.min.js +2 -0
  15. data/app/assets/javascripts/cubism.umd.min.js.map +1 -0
  16. data/app/channels/cubism/presence_channel.rb +14 -5
  17. data/app/helpers/cubism_helper.rb +15 -17
  18. data/app/models/concerns/cubism/presence.rb +11 -3
  19. data/bin/rails +14 -0
  20. data/bin/standardize +4 -0
  21. data/bin/test +5 -0
  22. data/cubism.gemspec +36 -0
  23. data/cubism.gemspec~ +28 -0
  24. data/lib/cubism/broadcaster.rb +13 -6
  25. data/lib/cubism/cubicle_store.rb +141 -0
  26. data/lib/cubism/engine.rb +23 -2
  27. data/lib/cubism/importmap.rb +2 -0
  28. data/lib/cubism/preprocessor.rb +4 -1
  29. data/lib/cubism/version.rb +1 -1
  30. data/lib/cubism.rb +3 -2
  31. data/package.json +43 -0
  32. data/package.json~ +33 -0
  33. data/rollup.config.js +77 -0
  34. data/{lib/cubism/parser.rb~ → rollup.config.js~} +0 -0
  35. data/test/block_container_test.rb +105 -0
  36. data/test/block_source_test.rb +102 -0
  37. data/test/broadcaster_test.rb +66 -0
  38. data/test/channels/cubism/presence_channel_test.rb +72 -0
  39. data/test/cubicle_store_test.rb +34 -0
  40. data/test/cubism_test.rb +7 -0
  41. data/test/dummy/app/channels/application_cable/channel.rb +4 -0
  42. data/test/dummy/app/channels/application_cable/connection.rb +4 -0
  43. data/test/dummy/app/controllers/application_controller.rb +2 -0
  44. data/test/dummy/app/helpers/application_helper.rb +2 -0
  45. data/test/dummy/app/jobs/application_job.rb +7 -0
  46. data/test/dummy/app/mailers/application_mailer.rb +4 -0
  47. data/test/dummy/app/models/application_record.rb +3 -0
  48. data/test/dummy/app/models/post.rb +3 -0
  49. data/test/dummy/app/models/user.rb +3 -0
  50. data/test/dummy/config/application.rb +22 -0
  51. data/test/dummy/config/boot.rb +5 -0
  52. data/test/dummy/config/environment.rb +5 -0
  53. data/test/dummy/config/environments/development.rb +76 -0
  54. data/test/dummy/config/environments/production.rb +120 -0
  55. data/test/dummy/config/environments/test.rb +59 -0
  56. data/test/dummy/config/initializers/application_controller_renderer.rb +8 -0
  57. data/test/dummy/config/initializers/assets.rb +12 -0
  58. data/test/dummy/config/initializers/backtrace_silencers.rb +8 -0
  59. data/test/dummy/config/initializers/content_security_policy.rb +28 -0
  60. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  61. data/test/dummy/config/initializers/filter_parameter_logging.rb +6 -0
  62. data/test/dummy/config/initializers/inflections.rb +16 -0
  63. data/test/dummy/config/initializers/mime_types.rb +4 -0
  64. data/test/dummy/config/initializers/permissions_policy.rb +11 -0
  65. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  66. data/test/dummy/config/puma.rb +43 -0
  67. data/test/dummy/config/routes.rb +3 -0
  68. data/test/dummy/db/migrate/20220102072929_create_posts.rb +10 -0
  69. data/test/dummy/db/migrate/20220102073003_create_users.rb +9 -0
  70. data/test/dummy/db/schema.rb +26 -0
  71. data/test/dummy/test/models/post_test.rb +7 -0
  72. data/test/dummy/test/models/user_test.rb +7 -0
  73. data/test/helpers/cubism_helper_test.rb +39 -0
  74. data/test/integration/navigation_test.rb +7 -0
  75. data/test/models/concerns/presence_test.rb +25 -0
  76. data/test/models/concerns/user_test.rb +9 -0
  77. data/test/rendering/preprocessor_test.rb +61 -0
  78. data/test/test_helper.rb +16 -0
  79. data/yarn.lock +2814 -0
  80. metadata +118 -18
  81. data/app/channels/cubism/presence_channel.rb~ +0 -52
  82. data/app/helpers/cubism_helper.rb~ +0 -34
  83. data/app/models/concerns/cubism/presence.rb~ +0 -13
  84. data/config/routes.rb +0 -2
  85. data/lib/cubism/broadcaster.rb~ +0 -50
  86. data/lib/cubism/cubicle_block_store.rb +0 -56
  87. data/lib/cubism/cubicle_block_store.rb~ +0 -43
  88. data/lib/cubism/engine.rb~ +0 -4
  89. data/lib/cubism/preprocessor.rb~ +0 -26
  90. data/lib/cubism/version.rb~ +0 -3
  91. data/lib/cubism.rb~ +0 -18
  92. data/lib/tasks/cubism_tasks.rake +0 -4
@@ -0,0 +1,141 @@
1
+ module Cubism
2
+ class CubicleStore
3
+ delegate_missing_to :@blocks
4
+
5
+ def initialize(key)
6
+ @blocks = Kredis.hash key
7
+ end
8
+
9
+ def [](key)
10
+ Marshal.load(@blocks[key]) if @blocks[key]
11
+ end
12
+
13
+ def []=(key, value)
14
+ mutex.synchronize do
15
+ @blocks[key] = Marshal.dump value
16
+ end
17
+ end
18
+
19
+ def fetch(key, value = nil, &block)
20
+ if self[key].nil?
21
+ yield value if block
22
+ self[key] = value
23
+ end
24
+
25
+ self[key]
26
+ end
27
+
28
+ def clear
29
+ mutex.synchronize do
30
+ # kredis #remove
31
+ @blocks.remove
32
+ end
33
+ end
34
+
35
+ def size
36
+ @blocks.to_h.size
37
+ end
38
+
39
+ private
40
+
41
+ def mutex
42
+ @mutex ||= Mutex.new
43
+ end
44
+ end
45
+
46
+ # Container for cubicle blocks
47
+ BlockContainer = Struct.new(
48
+ :block_location,
49
+ :block_source,
50
+ :user_gid,
51
+ :resource_gid,
52
+ :scope,
53
+ keyword_init: true
54
+ ) do
55
+ def initialize(*args)
56
+ super
57
+
58
+ @filename, _lineno = block_location.split(":")
59
+ end
60
+
61
+ def user
62
+ GlobalID::Locator.locate self[:user_gid]
63
+ end
64
+
65
+ def resource
66
+ GlobalID::Locator.locate self[:resource_gid]
67
+ end
68
+
69
+ def scope
70
+ self[:scope] || ""
71
+ end
72
+
73
+ def digest
74
+ resource_user_key = [resource_gid, user_gid, scope].join(":")
75
+
76
+ ActiveSupport::Digest.hexdigest("#{block_location}:#{File.read(@filename)}:#{resource_user_key}")
77
+ end
78
+
79
+ def marshal_dump
80
+ to_h.merge(block_source: block_source.digest)
81
+ end
82
+
83
+ def marshal_load(serialized_item)
84
+ members.excluding(:block_source).each do |arg|
85
+ send("#{arg}=", serialized_item[arg])
86
+ end
87
+
88
+ self.block_source = Cubism.source_store[serialized_item[:block_source]]
89
+ end
90
+ end
91
+
92
+ # Container for cubicle block sources
93
+ BlockSource = Struct.new(
94
+ :location,
95
+ :source,
96
+ :variable_name,
97
+ :view_context,
98
+ keyword_init: true
99
+ ) do
100
+ def self.find_or_create(location:, view_context:)
101
+ instance = new(location: location, view_context: view_context)
102
+
103
+ Cubism.source_store.fetch(instance.digest, instance) do |instance|
104
+ instance.parse!
105
+ end
106
+
107
+ instance
108
+ end
109
+
110
+ def initialize(*args)
111
+ super
112
+
113
+ @filename, @lineno = location.split(":")
114
+ @lineno = @lineno.to_i
115
+ end
116
+
117
+ def parse!
118
+ return if location.start_with?("inline template")
119
+
120
+ lines = File.readlines(@filename)[@lineno - 1..]
121
+
122
+ preprocessor = Cubism::Preprocessor.new(source: lines.join.squish, view_context: view_context)
123
+ self.variable_name = preprocessor.block_variable_name
124
+ self.source = preprocessor.process
125
+ end
126
+
127
+ def digest
128
+ ActiveSupport::Digest.hexdigest("#{location}:#{File.read(@filename)}")
129
+ end
130
+
131
+ def marshal_dump
132
+ to_h.except(:view_context)
133
+ end
134
+
135
+ def marshal_load(serialized_item)
136
+ members.excluding(:view_context).each do |arg|
137
+ send("#{arg}=", serialized_item[arg])
138
+ end
139
+ end
140
+ end
141
+ end
data/lib/cubism/engine.rb CHANGED
@@ -1,7 +1,28 @@
1
1
  module Cubism
2
2
  class Engine < ::Rails::Engine
3
- initializer "cubism.store" do
4
- Cubism.store = Cubism::CubicleBlockStore.new
3
+ initializer "cubism.stores" do
4
+ Cubism.block_store = Cubism::CubicleStore.new("cubism-blocks")
5
+ Cubism.source_store = Cubism::CubicleStore.new("cubism-source")
6
+ end
7
+
8
+ initializer "cubism.assets" do |app|
9
+ if app.config.respond_to?(:assets)
10
+ app.config.assets.precompile += %w[
11
+ cubism.js
12
+ cubism.min.js
13
+ cubism.min.js.map
14
+ cubism.umd.js
15
+ cubism.umd.min.js
16
+ cubism.umd.min.js.map
17
+ ]
18
+ end
19
+ end
20
+
21
+ initializer "cubism.importmap", before: "importmap" do |app|
22
+ if app.config.respond_to?(:importmap)
23
+ app.config.importmap.paths << Engine.root.join("lib/cubism/importmap.rb")
24
+ app.config.importmap.cache_sweepers << Engine.root.join("app/assets/javascripts")
25
+ end
5
26
  end
6
27
  end
7
28
  end
@@ -0,0 +1,2 @@
1
+ pin "cable_ready", to: "cable_ready.min.js", preload: true
2
+ pin "cubism", to: "cubism.min.js", preload: true
@@ -1,8 +1,11 @@
1
1
  module Cubism
2
2
  class Preprocessor
3
+ attr_reader :block_variable_name
4
+
3
5
  def initialize(source:, view_context:)
4
- match_data = /<%=\s+cubicle_for.+\|.+\|\s+%>/.match(source)
6
+ match_data = /<%=\s+cubicle_for.+?\|(\w+)\|\s+%>/.match(source)
5
7
  start_pos = match_data&.end(0) || 0
8
+ @block_variable_name = match_data[1] if match_data
6
9
  @source = source[start_pos..]
7
10
  @view_context = view_context
8
11
  end
@@ -1,3 +1,3 @@
1
1
  module Cubism
2
- VERSION = "0.1.0.pre10"
2
+ VERSION = "0.1.0.pre13"
3
3
  end
data/lib/cubism.rb CHANGED
@@ -3,7 +3,7 @@ require "kredis"
3
3
  require "cubism/version"
4
4
  require "cubism/engine"
5
5
  require "cubism/broadcaster"
6
- require "cubism/cubicle_block_store"
6
+ require "cubism/cubicle_store"
7
7
  require "cubism/preprocessor"
8
8
 
9
9
  module Cubism
@@ -14,5 +14,6 @@ module Cubism
14
14
 
15
15
  mattr_accessor :user_class, instance_writer: false, instance_reader: false
16
16
 
17
- mattr_accessor :store, instance_reader: false
17
+ mattr_accessor :block_store, instance_reader: false
18
+ mattr_accessor :source_store, instance_reader: false
18
19
  end
data/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@minthesize/cubism",
3
+ "version": "0.1.0-pre13",
4
+ "description": "Lightweight Resource-Based Presence Solution with CableReady.",
5
+ "main": "./dist/cubism.umd.min.js",
6
+ "module": "./dist/cubism.min.js",
7
+ "files": [
8
+ "dist/*",
9
+ "javascript/*"
10
+ ],
11
+ "scripts": {
12
+ "lint": "yarn run prettier-standard:check",
13
+ "format": "yarn run prettier-standard:format",
14
+ "prettier-standard:check": "yarn run prettier-standard --check ./javascript/**/*.js rollup.config.js",
15
+ "prettier-standard:format": "yarn run prettier-standard ./javascript/**/*.js rollup.config.js",
16
+ "build": "yarn rollup -c",
17
+ "watch": "yarn rollup -wc"
18
+ },
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/julianrubisch/cubism.git"
22
+ },
23
+ "keywords": [
24
+ "presence"
25
+ ],
26
+ "author": "Julian Rubisch",
27
+ "license": "MIT",
28
+ "bugs": {
29
+ "url": "https://github.com/julianrubisch/cubism/issues"
30
+ },
31
+ "homepage": "https://github.com/julianrubisch/cubism#readme",
32
+ "devDependencies": {
33
+ "@rollup/plugin-commonjs": "^21.0.3",
34
+ "@rollup/plugin-json": "^4.1.0",
35
+ "@rollup/plugin-node-resolve": "^13.1.3",
36
+ "prettier-standard": "^16.4.1",
37
+ "rollup": "^2.70.1",
38
+ "rollup-plugin-terser": "^7.0.2"
39
+ },
40
+ "dependencies": {
41
+ "cable_ready": "^5.0.0-pre9"
42
+ }
43
+ }
data/package.json~ ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@minthesize/cubism",
3
+ "version": "0.1.0-pre12",
4
+ "description": "Lightweight Resource-Based Presence Solution with CableReady.",
5
+ "main": "./javascript/index.js",
6
+ "module": "./javascript/index.js",
7
+ "files": ["javascript/**/*.js"],
8
+ "scripts": {
9
+ "lint": "yarn run prettier-standard:check",
10
+ "format": "yarn run prettier-standard:format",
11
+ "prettier-standard:check": "yarn run prettier-standard --check ./javascript/**/*.js",
12
+ "prettier-standard:format": "yarn run prettier-standard ./javascript/**/*.js"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/julianrubisch/cubism.git"
17
+ },
18
+ "keywords": [
19
+ "presence"
20
+ ],
21
+ "author": "Julian Rubisch",
22
+ "license": "MIT",
23
+ "bugs": {
24
+ "url": "https://github.com/julianrubisch/cubism/issues"
25
+ },
26
+ "homepage": "https://github.com/julianrubisch/cubism#readme",
27
+ "devDependencies": {
28
+ "prettier-standard": "^16.4.1"
29
+ },
30
+ "dependencies": {
31
+ "cable_ready": "5.0.0-pre8"
32
+ }
33
+ }
data/rollup.config.js ADDED
@@ -0,0 +1,77 @@
1
+ import resolve from '@rollup/plugin-node-resolve'
2
+ import commonjs from '@rollup/plugin-commonjs'
3
+ import json from '@rollup/plugin-json'
4
+ import { terser } from 'rollup-plugin-terser'
5
+
6
+ const pretty = () => {
7
+ return terser({
8
+ mangle: false,
9
+ compress: false,
10
+ format: {
11
+ beautify: true,
12
+ indent_level: 2
13
+ }
14
+ })
15
+ }
16
+
17
+ const minify = () => {
18
+ return terser({
19
+ mangle: true,
20
+ compress: true
21
+ })
22
+ }
23
+
24
+ const esConfig = {
25
+ format: 'es',
26
+ inlineDynamicImports: true
27
+ }
28
+
29
+ const umdConfig = {
30
+ name: 'Cubism',
31
+ format: 'umd',
32
+ exports: 'named',
33
+ globals: {
34
+ cable_ready: 'CableReady'
35
+ }
36
+ }
37
+
38
+ const distFolders = ['dist/', 'app/assets/javascripts/']
39
+
40
+ const output = distFolders
41
+ .map(distFolder => [
42
+ {
43
+ ...esConfig,
44
+ file: `${distFolder}/cubism.js`,
45
+ plugins: [pretty()]
46
+ },
47
+ {
48
+ ...esConfig,
49
+ file: `${distFolder}/cubism.min.js`,
50
+ sourcemap: true,
51
+ plugins: [minify()]
52
+ },
53
+ {
54
+ ...umdConfig,
55
+ file: `${distFolder}/cubism.umd.js`,
56
+ plugins: [pretty()]
57
+ },
58
+ {
59
+ ...umdConfig,
60
+ file: `${distFolder}/cubism.umd.min.js`,
61
+ sourcemap: true,
62
+ plugins: [minify()]
63
+ }
64
+ ])
65
+ .flat()
66
+
67
+ export default [
68
+ {
69
+ external: ['cable_ready'],
70
+ input: 'javascript/index.js',
71
+ output,
72
+ plugins: [commonjs(), resolve(), json()],
73
+ watch: {
74
+ include: 'javascript/**'
75
+ }
76
+ }
77
+ ]
File without changes
@@ -0,0 +1,105 @@
1
+ require "test_helper"
2
+
3
+ class BlockContainerTest < ActiveSupport::TestCase
4
+ FIXTURES_DIR = File.expand_path("./fixtures", __dir__)
5
+
6
+ setup do
7
+ @cwd = Dir.pwd
8
+ @tmp_dir = Dir.mktmpdir
9
+
10
+ FileUtils.cp_r FIXTURES_DIR, @tmp_dir
11
+ Dir.chdir @tmp_dir
12
+
13
+ @post = posts(:one)
14
+ @user = users(:one)
15
+ end
16
+
17
+ teardown do
18
+ Dir.chdir @cwd
19
+ FileUtils.rm_r @tmp_dir
20
+ end
21
+
22
+ test "block container digest changes when file contents change" do
23
+ template = "fixtures/_cubicle_partial"
24
+
25
+ digest1 = Cubism::BlockContainer.new(
26
+ block_location: "#{template_tmp_path(template)}.html.erb:1",
27
+ resource_gid: @post.to_gid.to_s,
28
+ user_gid: @user.to_gid.to_s
29
+ ).digest
30
+
31
+ change_template(template)
32
+
33
+ digest2 = Cubism::BlockContainer.new(
34
+ block_location: "#{template_tmp_path(template)}.html.erb:1",
35
+ resource_gid: @post.to_gid.to_s,
36
+ user_gid: @user.to_gid.to_s
37
+ ).digest
38
+
39
+ refute_equal digest1, digest2
40
+ end
41
+
42
+ test "block container digest changes when user changes" do
43
+ template = "fixtures/_cubicle_partial"
44
+
45
+ digest1 = Cubism::BlockContainer.new(
46
+ block_location: "#{template_tmp_path(template)}.html.erb:1",
47
+ resource_gid: @post.to_gid.to_s,
48
+ user_gid: @user.to_gid.to_s
49
+ ).digest
50
+
51
+ digest2 = Cubism::BlockContainer.new(
52
+ block_location: "#{template_tmp_path(template)}.html.erb:1",
53
+ resource_gid: @post.to_gid.to_s,
54
+ user_gid: users(:two).to_gid.to_s
55
+ ).digest
56
+
57
+ refute_equal digest1, digest2
58
+ end
59
+
60
+ test "block container digest changes when resource changes" do
61
+ template = "fixtures/_cubicle_partial"
62
+
63
+ digest1 = Cubism::BlockContainer.new(
64
+ block_location: "#{template_tmp_path(template)}.html.erb:1",
65
+ resource_gid: @post.to_gid.to_s,
66
+ user_gid: @user.to_gid.to_s
67
+ ).digest
68
+
69
+ digest2 = Cubism::BlockContainer.new(
70
+ block_location: "#{template_tmp_path(template)}.html.erb:1",
71
+ resource_gid: posts(:two).to_gid.to_s,
72
+ user_gid: @user.to_gid.to_s
73
+ ).digest
74
+
75
+ refute_equal digest1, digest2
76
+ end
77
+
78
+ test "block container digest changes when block_location changes" do
79
+ template = "fixtures/_cubicle_partial"
80
+
81
+ digest1 = Cubism::BlockContainer.new(
82
+ block_location: "#{template_tmp_path(template)}.html.erb:1",
83
+ resource_gid: @post.to_gid.to_s,
84
+ user_gid: @user.to_gid.to_s
85
+ ).digest
86
+
87
+ digest2 = Cubism::BlockContainer.new(
88
+ block_location: "#{template_tmp_path(template)}.html.erb:2",
89
+ resource_gid: @post.to_gid.to_s,
90
+ user_gid: @user.to_gid.to_s
91
+ ).digest
92
+
93
+ refute_equal digest1, digest2
94
+ end
95
+
96
+ private
97
+
98
+ def template_tmp_path(template)
99
+ Pathname.new(@tmp_dir).join(template).to_path
100
+ end
101
+
102
+ def change_template(template)
103
+ File.write("#{template}.html.erb", "\nTHIS WAS CHANGED!")
104
+ end
105
+ end
@@ -0,0 +1,102 @@
1
+ require "test_helper"
2
+
3
+ class BlockSourceTest < ActionView::TestCase
4
+ FIXTURES_DIR = File.expand_path("./fixtures", __dir__)
5
+
6
+ setup do
7
+ @cwd = Dir.pwd
8
+ @tmp_dir = Dir.mktmpdir
9
+
10
+ FileUtils.cp_r FIXTURES_DIR, @tmp_dir
11
+ Dir.chdir @tmp_dir
12
+
13
+ @post = posts(:one)
14
+ @user = users(:one)
15
+ end
16
+
17
+ teardown do
18
+ Dir.chdir @cwd
19
+ FileUtils.rm_r @tmp_dir
20
+ end
21
+
22
+ test "block source digest changes when file contents change" do
23
+ template = "fixtures/_cubicle_partial"
24
+
25
+ digest1 = Cubism::BlockSource.new(
26
+ location: "#{template_tmp_path(template)}.html.erb:1",
27
+ view_context: self
28
+ ).digest
29
+
30
+ change_template(template)
31
+
32
+ digest2 = Cubism::BlockSource.new(
33
+ location: "#{template_tmp_path(template)}.html.erb:1",
34
+ view_context: self
35
+ ).digest
36
+
37
+ refute_equal digest1, digest2
38
+ end
39
+
40
+ test "block source digest changes when block_location changes" do
41
+ template = "fixtures/_cubicle_partial"
42
+
43
+ digest1 = Cubism::BlockSource.new(
44
+ location: "#{template_tmp_path(template)}.html.erb:1",
45
+ view_context: self
46
+ ).digest
47
+
48
+ digest2 = Cubism::BlockSource.new(
49
+ location: "#{template_tmp_path(template)}.html.erb:2",
50
+ view_context: self
51
+ ).digest
52
+
53
+ refute_equal digest1, digest2
54
+ end
55
+
56
+ test "can be created in the store by source location" do
57
+ template = "fixtures/_cubicle_partial"
58
+
59
+ assert_equal 0, Cubism.source_store.size
60
+
61
+ Cubism::BlockSource.any_instance.expects(:parse!).once
62
+
63
+ Cubism::BlockSource.find_or_create(
64
+ location: "#{template_tmp_path(template)}.html.erb:1",
65
+ view_context: self
66
+ )
67
+
68
+ assert_equal 1, Cubism.source_store.size
69
+ end
70
+
71
+ test "existing block source is returned and not parsed" do
72
+ template = "fixtures/_cubicle_partial"
73
+
74
+ instance = Cubism::BlockSource.new(
75
+ location: "#{template_tmp_path(template)}.html.erb:1",
76
+ view_context: self
77
+ )
78
+
79
+ Cubism.source_store[instance.digest] = instance
80
+
81
+ assert_equal 1, Cubism.source_store.size
82
+
83
+ Cubism::BlockSource.any_instance.expects(:parse!).never
84
+
85
+ Cubism::BlockSource.find_or_create(
86
+ location: "#{template_tmp_path(template)}.html.erb:1",
87
+ view_context: self
88
+ )
89
+
90
+ assert_equal 1, Cubism.source_store.size
91
+ end
92
+
93
+ private
94
+
95
+ def template_tmp_path(template)
96
+ Pathname.new(@tmp_dir).join(template).to_path
97
+ end
98
+
99
+ def change_template(template)
100
+ File.write("#{template}.html.erb", "\nTHIS WAS CHANGED!")
101
+ end
102
+ end
@@ -0,0 +1,66 @@
1
+ require "test_helper"
2
+
3
+ class BroadcasterTest < ActionView::TestCase
4
+ include CableReady::StreamIdentifier
5
+
6
+ setup do
7
+ @post = posts(:one)
8
+ @post.stubs(:cubicle_element_ids).returns(%w[foo bar])
9
+ @post.stubs(:present_users_for_element_id_and_scope).with("foo", "").returns([users(:one)])
10
+ @post.stubs(:present_users_for_element_id_and_scope).with("bar", "").returns([users(:two)])
11
+
12
+ @post_2 = posts(:two)
13
+ @post_2.stubs(:cubicle_element_ids).returns(%w[baz])
14
+ @post_2.stubs(:present_users_for_element_id_and_scope).with("baz", :edit).returns([users(:one)])
15
+ @post_2.stubs(:present_users_for_element_id_and_scope).with("baz", :show).returns([])
16
+
17
+ block_source_foo = Cubism::BlockSource.new(location: "test:1", variable_name: "users", source: "<div><%= users.map(&:username).to_sentence %></div>", view_context: self)
18
+ block_source_bar = Cubism::BlockSource.new(location: "test:1", variable_name: "present_users", source: "<div><%= present_users.map(&:username).to_sentence %></div>", view_context: self)
19
+
20
+ Cubism.stubs(:block_store).returns({
21
+ "foo" => Cubism::BlockContainer.new(block_location: "test:1", block_source: block_source_foo, user_gid: users(:one).to_gid.to_s, resource_gid: posts(:one).to_gid.to_s),
22
+ "bar" => Cubism::BlockContainer.new(block_location: "test:1", block_source: block_source_bar, user_gid: users(:two).to_gid.to_s, resource_gid: posts(:one).to_gid.to_s),
23
+ "baz" => Cubism::BlockContainer.new(block_location: "test:1", block_source: block_source_foo, user_gid: users(:one).to_gid.to_s, resource_gid: posts(:two).to_gid.to_s, scope: :edit)
24
+ })
25
+ end
26
+
27
+ test "it broadcasts to all registered element ids with default scopes" do
28
+ with_mocked_cable_ready({"foo" => {"" => users(:one)}, "bar" => {"" => users(:two)}}, @post) do |cable_ready_mock|
29
+ @broadcaster = Cubism::Broadcaster.new(resource: @post)
30
+
31
+ @broadcaster.expects(:cable_ready).returns(cable_ready_mock).times(3)
32
+
33
+ @broadcaster.broadcast
34
+ end
35
+ end
36
+
37
+ test "it broadcasts to all registered element ids and respects scopes" do
38
+ with_mocked_cable_ready({"baz" => {"edit" => users(:one)}}, @post_2) do |cable_ready_mock|
39
+ @broadcaster = Cubism::Broadcaster.new(resource: @post_2)
40
+
41
+ @broadcaster.expects(:cable_ready).returns(cable_ready_mock).twice
42
+
43
+ @broadcaster.broadcast
44
+ end
45
+ end
46
+ end
47
+
48
+ def with_mocked_cable_ready(elements_with_users_and_scopes, resource)
49
+ cable_ready_mock = mock
50
+ cable_ready_mock.expects(:broadcast).once
51
+
52
+ elements_with_users_and_scopes.each do |element_id, scoped_users|
53
+ cable_ready_channel = mock
54
+ scoped_users.each do |scope, user|
55
+ cable_ready_channel
56
+ .expects(:inner_html)
57
+ .with({
58
+ selector: "cubicle-element#cubicle-#{element_id}[identifier='#{signed_stream_identifier(resource.to_global_id.to_s)}']",
59
+ html: "<div>#{user.username}</div>"
60
+ })
61
+ end
62
+ cable_ready_mock.expects(:[]).with(element_id).returns(cable_ready_channel)
63
+ end
64
+
65
+ yield cable_ready_mock
66
+ end