cubism 0.1.0.pre10 → 0.1.0.pre13

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.
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