card 1.93.3 → 1.93.4

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 (160) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/db/migrate/20170908114452_increase_text_size_for_delayed_jobs.rb +9 -0
  4. data/db/migrate_core_cards/data/cards/*header +2 -2
  5. data/lib/card/format/nest.rb +12 -5
  6. data/lib/card/format/nest/fetch.rb +1 -2
  7. data/lib/card/format/render.rb +2 -2
  8. data/lib/card/model/save_helper.rb +1 -1
  9. data/lib/card/set/format/haml_views.rb +7 -3
  10. data/lib/card/subcards.rb +27 -228
  11. data/lib/card/subcards/add.rb +121 -0
  12. data/lib/card/subcards/relate.rb +27 -0
  13. data/lib/card/subcards/remove.rb +42 -0
  14. data/lib/card/tasks/card/create.rake +35 -132
  15. data/lib/card/tasks/card/file_card_creator.rb +25 -0
  16. data/lib/card/tasks/card/file_card_creator/abstract_file_card.rb +44 -0
  17. data/lib/card/tasks/card/file_card_creator/abstract_file_card/migration_file.rb +49 -0
  18. data/lib/card/tasks/card/file_card_creator/abstract_file_card/ruby_file.rb +30 -0
  19. data/lib/card/tasks/card/file_card_creator/abstract_file_card/source_file.rb +36 -0
  20. data/lib/card/tasks/card/file_card_creator/haml_card.rb +42 -0
  21. data/lib/card/tasks/card/file_card_creator/output_helper.rb +50 -0
  22. data/lib/card/tasks/card/file_card_creator/script_card.rb +33 -0
  23. data/lib/card/tasks/card/file_card_creator/style_card.rb +25 -0
  24. data/lib/generators/card/template/template_generator.rb +1 -1
  25. data/mod/account/set/self/account_links.rb +1 -1
  26. data/mod/basic_formats/set/all/all_csv.rb +63 -0
  27. data/mod/basic_formats/set/all/json.rb +4 -1
  28. data/mod/bootstrap/db/migrate_cards/20170719163733_update_bootswatch_themes_to_4_beta.rb +5 -2
  29. data/mod/carrierwave/set/abstract/attachment.rb +1 -2
  30. data/mod/core/set/abstract/haml_file.rb +20 -0
  31. data/mod/core/set/all/chunk.rb +125 -0
  32. data/mod/core/set/all/collection.rb +2 -351
  33. data/mod/core/set/all/content.rb +26 -7
  34. data/mod/core/set/all/extended.rb +45 -0
  35. data/mod/core/set/all/haml.rb +3 -7
  36. data/mod/core/set/all/item.rb +92 -0
  37. data/mod/core/set/all/name.rb +36 -0
  38. data/mod/core/set/all/subcards.rb +21 -12
  39. data/mod/core/set/all/tabs.rb +50 -0
  40. data/mod/core/set/all/trash.rb +4 -0
  41. data/mod/core/spec/set/all/chunk_spec.rb +45 -0
  42. data/mod/core/spec/set/all/collection_spec.rb +6 -6
  43. data/mod/history/set/all/action_view.rb +1 -1
  44. data/mod/machines/lib/javascript/decko.js.coffee +3 -0
  45. data/mod/pointer/set/abstract/02_pointer/edit.rb +0 -2
  46. data/mod/search/set/abstract/search.rb +1 -1
  47. data/mod/search/set/all/filter.rb +0 -2
  48. data/mod/search/template/all/filter/_filter_input.haml +1 -1
  49. data/mod/search/template/all/filter/filter_form.haml +1 -1
  50. data/mod/standard/set/all/rich_html/editing.rb +1 -1
  51. data/mod/standard/set/all/rich_html/form.rb +6 -7
  52. data/mod/standard/set/all/rich_html/menu.rb +2 -3
  53. data/mod/standard/set/all/rich_html/toolbar.rb +3 -4
  54. data/mod/standard/set/type/cardtype.rb +1 -1
  55. data/mod/standard/spec/set/all/rich_html/editing_spec.rb +15 -4
  56. data/mod/tinymce_editor/db/migrate_cards/{20171113233150_update_tinymce_config.rb → 20171113233151_update_tinymce_config.rb} +1 -0
  57. metadata +25 -161
  58. data/.rspec +0 -4
  59. data/card.gemspec +0 -87
  60. data/db/seed/test/fixtures/.gitkeep +0 -0
  61. data/mod/bootstrap/vendor/bootstrap/.babelrc.js +0 -16
  62. data/mod/bootstrap/vendor/bootstrap/.editorconfig +0 -17
  63. data/mod/bootstrap/vendor/bootstrap/.eslintignore +0 -3
  64. data/mod/bootstrap/vendor/bootstrap/.gitattributes +0 -16
  65. data/mod/bootstrap/vendor/bootstrap/.github/CONTRIBUTING.md +0 -252
  66. data/mod/bootstrap/vendor/bootstrap/.github/ISSUE_TEMPLATE.md +0 -22
  67. data/mod/bootstrap/vendor/bootstrap/.gitignore +0 -46
  68. data/mod/bootstrap/vendor/bootstrap/.hound.yml +0 -19
  69. data/mod/bootstrap/vendor/bootstrap/.houndignore +0 -4
  70. data/mod/bootstrap/vendor/bootstrap/.travis.yml +0 -32
  71. data/mod/bootstrap/vendor/bootstrap/build/.htmllintrc +0 -19
  72. data/mod/bootstrap/vendor/bootstrap/build/.stylelintrc +0 -248
  73. data/mod/bootstrap/vendor/bootstrap/docs/4.0/examples/.stylelintrc +0 -12
  74. data/mod/bootstrap/vendor/bootstrap/js/.eslintrc.json +0 -240
  75. data/mod/bootstrap/vendor/bootstrap/js/tests/.eslintrc.json +0 -46
  76. data/mod/bootstrap/vendor/bootswatch/.gitignore +0 -7
  77. data/mod/bootstrap/vendor/bootswatch/.npmignore +0 -12
  78. data/mod/bootstrap/vendor/bootswatch/.travis.yml +0 -21
  79. data/mod/bootstrap/vendor/bootswatch/docs/.nojekyll +0 -0
  80. data/mod/bootstrap/vendor/bootswatch/docs/2/.travis.yml +0 -15
  81. data/mod/bootstrap/vendor/bootswatch/docs/2/bower_components/bootstrap/.bower.json +0 -20
  82. data/mod/bootstrap/vendor/bootswatch/docs/2/bower_components/bootstrap/.gitignore +0 -37
  83. data/mod/bootstrap/vendor/bootswatch/docs/2/bower_components/bootstrap/.travis.yml +0 -3
  84. data/mod/bootstrap/vendor/bootswatch/docs/2/bower_components/bootstrap/js/.jshintrc +0 -12
  85. data/mod/bootstrap/vendor/bootswatch/docs/2/bower_components/jquery/.bower.json +0 -20
  86. data/mod/bootstrap/vendor/bootswatch/docs/2/bower_components/jquery/.gitignore +0 -1
  87. data/mod/bootstrap/vendor/bootswatch/docs/2/swatchmaker/.gitignore +0 -1
  88. data/mod/bootstrap/vendor/bootswatch/docs/3/bower_components/bootstrap-sass-official/.bower.json +0 -45
  89. data/mod/bootstrap/vendor/bootswatch/docs/3/bower_components/bootstrap/.bower.json +0 -44
  90. data/mod/bootstrap/vendor/bootswatch/docs/3/bower_components/bootstrap/grunt/.jshintrc +0 -7
  91. data/mod/bootstrap/vendor/bootswatch/docs/3/bower_components/bootstrap/js/.jscsrc +0 -42
  92. data/mod/bootstrap/vendor/bootswatch/docs/3/bower_components/bootstrap/js/.jshintrc +0 -15
  93. data/mod/bootstrap/vendor/bootswatch/docs/3/bower_components/bootstrap/less/.csscomb.json +0 -304
  94. data/mod/bootstrap/vendor/bootswatch/docs/3/bower_components/bootstrap/less/.csslintrc +0 -19
  95. data/mod/bootstrap/vendor/bootswatch/docs/3/bower_components/font-awesome/.bower.json +0 -14
  96. data/mod/bootstrap/vendor/bootswatch/docs/3/bower_components/font-awesome/.gitignore +0 -32
  97. data/mod/bootstrap/vendor/bootswatch/docs/3/bower_components/html5shiv/.bower.json +0 -25
  98. data/mod/bootstrap/vendor/bootswatch/docs/3/bower_components/jquery/.bower.json +0 -38
  99. data/mod/bootstrap/vendor/bootswatch/docs/3/bower_components/respond/.bower.json +0 -20
  100. data/mod/bootstrap/vendor/select2/.editorconfig +0 -6
  101. data/mod/bootstrap/vendor/select2/.github/CONTRIBUTING.md +0 -204
  102. data/mod/bootstrap/vendor/select2/.github/ISSUE_TEMPLATE.md +0 -46
  103. data/mod/bootstrap/vendor/select2/.github/PULL_REQUEST_TEMPLATE.md +0 -13
  104. data/mod/bootstrap/vendor/select2/.gitignore +0 -3
  105. data/mod/bootstrap/vendor/select2/.jshintignore +0 -4
  106. data/mod/bootstrap/vendor/select2/.jshintrc +0 -25
  107. data/mod/bootstrap/vendor/select2/.travis.yml +0 -22
  108. data/script/fetch_bootswatch_themes.rb +0 -38
  109. data/spec/config/initializers/core_extensions_spec.rb +0 -47
  110. data/spec/config/initializers/patches/active_job_spec.rb +0 -7
  111. data/spec/lib/card/action_spec.rb +0 -15
  112. data/spec/lib/card/auth_spec.rb +0 -58
  113. data/spec/lib/card/cache_spec.rb +0 -116
  114. data/spec/lib/card/chunk_spec.rb +0 -18
  115. data/spec/lib/card/codename_spec.rb +0 -66
  116. data/spec/lib/card/content_spec.rb +0 -428
  117. data/spec/lib/card/diff_spec.rb +0 -208
  118. data/spec/lib/card/format/nest_spec.rb +0 -13
  119. data/spec/lib/card/format/render_spec.rb +0 -26
  120. data/spec/lib/card/format_spec.rb +0 -117
  121. data/spec/lib/card/i18n_spec.rb +0 -24
  122. data/spec/lib/card/loader/Modfile +0 -2
  123. data/spec/lib/card/loader_spec.rb +0 -98
  124. data/spec/lib/card/migration/import_spec.rb +0 -80
  125. data/spec/lib/card/mod/loader/mod_dirs.rb +0 -8
  126. data/spec/lib/card/mod/loader/set_loader_spec.rb +0 -19
  127. data/spec/lib/card/mod/loader/set_pattern_loader_spec.rb +0 -19
  128. data/spec/lib/card/name/fields_and_traits_spec.rb +0 -18
  129. data/spec/lib/card/name_spec.rb +0 -70
  130. data/spec/lib/card/query/sorting_spec.rb +0 -68
  131. data/spec/lib/card/query_spec.rb +0 -574
  132. data/spec/lib/card/reference_spec.rb +0 -212
  133. data/spec/lib/card/set/event_spec.rb +0 -22
  134. data/spec/lib/card/set/trait_spec.rb +0 -80
  135. data/spec/lib/card/set_pattern_spec.rb +0 -59
  136. data/spec/lib/card/set_spec.rb +0 -89
  137. data/spec/lib/card/stage_director_spec.rb +0 -482
  138. data/spec/lib/card/subcards_spec.rb +0 -177
  139. data/spec/lib/card/success_spec.rb +0 -148
  140. data/spec/lib/card/view_cache_spec.rb +0 -27
  141. data/spec/mailers/mailer_spec.rb +0 -62
  142. data/spec/models/card/create_spec.rb +0 -119
  143. data/spec/models/card/trash_spec.rb +0 -189
  144. data/spec/models/card_spec.rb +0 -136
  145. data/spec/spec_helper.rb +0 -45
  146. data/spec/support/card_spec_helper.rb +0 -74
  147. data/spec/support/card_spec_loader.rb +0 -112
  148. data/spec/support/helper/card_helper.rb +0 -58
  149. data/spec/support/helper/event_helper.rb +0 -94
  150. data/spec/support/helper/render_helper.rb +0 -44
  151. data/spec/support/helper/save_helper.rb +0 -30
  152. data/spec/support/helper/set_helper.rb +0 -80
  153. data/spec/support/matchers/card_matchers.rb +0 -160
  154. data/spec/support/matchers/expectations.rb +0 -5
  155. data/spec/support/matchers/file_matchers.rb +0 -71
  156. data/spec/support/matchers/html_matchers.rb +0 -29
  157. data/spec/support/matchers/negated_matchers.rb +0 -2
  158. data/spec/support/simplecov_helper.rb +0 -70
  159. data/spec/support/test_mods/mod1/set/all/test_set.rb +0 -3
  160. data/spec/support/test_mods/mod2/set_pattern/test_pattern.rb +0 -0
@@ -1,80 +0,0 @@
1
- # -*- encoding : utf-8 -*-
2
-
3
- describe Card::Migration::Import do
4
- let(:path) { Card::Migration.data_path }
5
- let(:importer) { Card::Migration::Import.new path }
6
-
7
- def card_meta_path
8
- Card::Migration::Import::ImportData.new(path).instance_variable_get("@path")
9
- end
10
-
11
- def card_content_dir
12
- Card::Migration::Import::ImportData.new(path).instance_variable_get("@card_content_dir")
13
- end
14
-
15
- def meta_data
16
- YAML.load_file(card_meta_path).deep_symbolize_keys
17
- end
18
-
19
- def content_path filename
20
- File.join(card_content_dir, filename)
21
- end
22
-
23
- def content_data_file filename
24
- File.read content_path filename
25
- end
26
-
27
- before(:each) do
28
- FileUtils.rm card_meta_path if File.exist? card_meta_path
29
- FileUtils.rm_rf card_content_dir if Dir.exist? card_content_dir
30
- end
31
-
32
- describe ".add_remote" do
33
- it "adds remote to yml file" do
34
- importer.add_remote "test", "url"
35
- remotes = meta_data[:remotes]
36
- expect(remotes[:test]).to eq "url"
37
- end
38
- end
39
-
40
- describe ".pull" do
41
- it "saves card attributes" do
42
- importer.pull "A"
43
- cards = meta_data[:cards]
44
- expect(cards).to be_instance_of(Array)
45
- expect(cards.first[:name]).to eq "A"
46
- expect(cards.first[:type]).to eq "Basic"
47
- end
48
-
49
- it "saves card content" do
50
- importer.pull "A"
51
- expect(content_data_file("a")).to eq "Alpha [[Z]]"
52
- end
53
-
54
- context "called with deep: true" do
55
- it "saves nested card" do
56
- importer.pull "B", deep: true
57
- expect(content_data_file("z")).to eq "I'm here to be referenced to"
58
- end
59
-
60
- it "does not save linked card" do
61
- importer.pull "A", deep: true
62
- expect(File.exist?(content_path("z"))).to be_falsey
63
- end
64
-
65
- it "saves pointer items" do
66
- importer.pull "Fruit+*type+*create", deep: true
67
- expect(File.exist?(content_path("anyone"))).to be_truthy
68
- end
69
- end
70
- end
71
-
72
- describe ".merge" do
73
- it "updates card content" do
74
- importer.pull "A"
75
- File.write content_path("a"), "test"
76
- importer.merge
77
- expect(Card["A"].content).to eq "test"
78
- end
79
- end
80
- end
@@ -1,8 +0,0 @@
1
-
2
- describe Card::Mod::Dirs do
3
- it 'loads mods from Modfile' do
4
- path = File.expand_path "..", __FILE__
5
- tg = Card::Mod::Dirs.new path
6
- expect(tg.mods).to eq %w(mod1 mod2)
7
- end
8
- end
@@ -1,19 +0,0 @@
1
- # -*- encoding : utf-8 -*-
2
-
3
- RSpec.describe Card::Mod::Loader::SetLoader do
4
- let(:mod_dirs) do
5
- path = File.expand_path "../../../../../support/test_mods", __FILE__
6
- Card::Mod::Dirs.new path
7
- end
8
-
9
- it 'initializes the load strategy' do
10
- expect(Card::Mod::LoadStrategy::Eval).to receive(:new).with(mod_dirs, instance_of(described_class))
11
- described_class.new(:eval, mod_dirs)
12
- end
13
-
14
- it "load mods" do
15
- described_class.new(:eval, mod_dirs).load
16
- expect(Card::Set.const_defined?("All::TestSet")).to be_truthy
17
- expect(Card.take.test_method).to eq "works"
18
- end
19
- end
@@ -1,19 +0,0 @@
1
- # -*- encoding : utf-8 -*-
2
-
3
- RSpec.describe Card::Mod::Loader::SetPatternLoader do
4
- let(:mod_dirs) do
5
- path = File.expand_path "../../../../../support/test_mods", __FILE__
6
- puts path
7
- Card::Mod::Dirs.new path
8
- end
9
-
10
- it 'initializes the load strategy' do
11
- expect(Card::Mod::LoadStrategy::Eval).to receive(:new).with(mod_dirs, instance_of(described_class))
12
- described_class.new :eval, mod_dirs
13
- end
14
-
15
- it "load mods" do
16
- described_class.new(:eval, mod_dirs).load
17
- expect(Card::Set.const_defined?("TestPattern")).to be_truthy
18
- end
19
- end
@@ -1,18 +0,0 @@
1
- # -*- encoding : utf-8 -*-
2
-
3
- describe Card::Name do
4
- describe "field_of?" do
5
- it "should identify fields" do
6
- expect("A+B" .to_name.field_of? "A" ).to be_truthy
7
- expect("A+B" .to_name.field_of? "B" ).to be_falsey
8
- expect("A+B" .to_name.field_of? "A+B").to be_falsey
9
- expect("A+B" .to_name.field_of? "A+C").to be_falsey
10
- expect("A+B+C".to_name.field_of? "A+B").to be_truthy
11
- expect("+B" .to_name.field_of? "A" ).to be_truthy
12
- expect("+B" .to_name.field_of? "A+B").to be_truthy
13
- expect("+B" .to_name.field_of? "" ).to be_truthy
14
- expect("+B" .to_name.field_of? nil ).to be_truthy
15
-
16
- end
17
- end
18
- end
@@ -1,70 +0,0 @@
1
- # -*- encoding : utf-8 -*-
2
-
3
- RSpec.describe Card::Name do
4
- describe "#valid" do
5
- it "rejects long names" do
6
- card = Card.new
7
- card.name = "1" * 256
8
- expect(card).not_to be_valid
9
- end
10
- end
11
-
12
- describe "Cardnames star handling" do
13
- it "recognizes star cards" do
14
- expect("*a".to_name.star?).to be_truthy
15
- end
16
-
17
- it "doesn't recognize star cards with plusses" do
18
- expect("*a+*b".to_name.star?).to be_falsey
19
- end
20
-
21
- it "recognizes rstar cards" do
22
- expect("a+*a".to_name.rstar?).to be_truthy
23
- end
24
-
25
- it "doesn't recognize star cards as rstar" do
26
- expect("*a".to_name.rstar?).to be_falsey
27
- end
28
-
29
- it "doesn't recognize non-star or star left" do
30
- expect("*a+a".to_name.rstar?).to be_falsey
31
- end
32
- end
33
-
34
- describe "trait_name?" do
35
- it "returns true for content codename" do
36
- expect("bazoinga+*right+*structure".to_name.trait_name?(:structure)).to(
37
- be_truthy
38
- )
39
- end
40
-
41
- it "handles arrays" do
42
- structure =
43
- "bazoinga+*right+*structure".to_name.trait_name?(:structure, :default)
44
- expect(structure).to be_truthy
45
- end
46
-
47
- it "returns false for non-template" do
48
- structure = "bazoinga+*right+nontent".to_name.trait_name?(:structure)
49
- expect(structure).to be_falsey
50
- end
51
- end
52
-
53
- describe "#absolute" do
54
- it "does session user substitution" do
55
- expect("_user".to_name.absolute("A")).to eq(Card::Auth.current.name)
56
- Card::Auth.as_bot do
57
- expect("_user".to_name.absolute("A")).to eq(Card::Auth.current.name)
58
- end
59
- end
60
- end
61
-
62
- describe "part creation" do
63
- it "creates parts" do
64
- Card::Auth.as_bot do
65
- Card.create name: "left+right"
66
- end
67
- expect(Card.fetch("right")).to be_truthy
68
- end
69
- end
70
- end
@@ -1,68 +0,0 @@
1
- describe Card::Query, "sorting" do
2
- subject do
3
- Card::Query.run @query.reverse_merge return: :name, sort: :name
4
- end
5
-
6
- it "sorts by create" do
7
- Card.create! name: "classic bootstrap skin head"
8
- # classic skin head is created more recently than classic skin,
9
- # which is in the seed data
10
- @query = { sort: "create", name: [:match, "classic bootstrap skin"] }
11
- is_expected.to eq(
12
- ["classic bootstrap skin", "classic bootstrap skin head"]
13
- )
14
- end
15
-
16
- it "sorts by name" do
17
- @query = { name: %w(in B Z A Y C X), sort: "name", dir: "desc" }
18
- is_expected.to eq(%w(Z Y X C B A))
19
- end
20
-
21
- it "sorts by content" do
22
- @query = { name: %w(in Z T A), sort: "content" }
23
- is_expected.to eq(%w(A Z T))
24
- end
25
-
26
- it "plays nice with match" do
27
- @query = { match: "Z", type: "Basic", sort: "content" }
28
- is_expected.to eq(%w(A B Z A+B+Y+Z))
29
- end
30
-
31
- it "sorts by plus card content" do
32
- Card::Auth.as_bot do
33
- c = Card.fetch("Setting+*self+*table of contents")
34
- c.content = "10"
35
- c.save
36
- Card.create! name: "Basic+*type+*table of contents", content: "3"
37
-
38
- @query = {
39
- right_plus: "*table of contents",
40
- sort: { right: "*table_of_contents" },
41
- sort_as: "integer"
42
- }
43
- is_expected.to eq(%w(*all Basic+*type Setting+*self))
44
- end
45
- end
46
-
47
- it "sorts by count" do
48
- Card::Auth.as_bot do
49
- @query = {
50
- name: [:in, "*always", "*never", "*edited"],
51
- sort: { right: "*follow", item: "referred_to", return: "count" }
52
- }
53
- is_expected.to eq(["*never", "*edited", "*always"])
54
- end
55
- end
56
-
57
- # it 'sorts by update' do
58
- # # do this on a restricted set so it won't change every time we
59
- # # add a card..
60
- # Card::Query.run(
61
- # match: 'two', sort: 'update', dir: 'desc'
62
- # ).map(&:name).should == ['One+Two+Three', 'One+Two','Two','Joe User']
63
- # Card['Two'].update_attributes! content: 'new bar'
64
- # Card::Query.run(
65
- # match: 'two', sort: 'update', dir: 'desc'
66
- # ).map(&:name).should == ['Two','One+Two+Three', 'One+Two','Joe User']
67
- # end
68
- end
@@ -1,574 +0,0 @@
1
- # -*- encoding : utf-8 -*-
2
-
3
- RSpec.describe Card::Query do
4
- A_JOINEES = %w(B C D E F).freeze
5
- CARDS_MATCHING_TWO = ["Joe User", "One+Two", "One+Two+Three", "Two"].freeze
6
-
7
- subject do
8
- Card::Query.run @query.reverse_merge return: :name, sort: :name
9
- end
10
-
11
- it "does not alter original statement" do
12
- @query = { right_plus: { name: %w(in tag source) } }
13
- query_clone = @query.deep_clone
14
- subject # runs query
15
- expect(query_clone).to eq(@query)
16
- end
17
-
18
- describe "append" do
19
- it "finds real cards" do
20
- @query = {
21
- name: [:in, "C", "D", "F"],
22
- append: "A"
23
- }
24
- is_expected.to eq(%w(C+A D+A F+A))
25
- end
26
-
27
- it "absolutizes names" do
28
- @query = {
29
- name: [:in, "C", "D", "F"],
30
- append: "_right",
31
- context: "B+A"
32
- }
33
- is_expected.to eq(%w(C+A D+A F+A))
34
- end
35
-
36
- it "finds virtual cards" do
37
- @query = {
38
- name: [:in, "C", "D"],
39
- append: "*plus cards"
40
- }
41
- is_expected.to eq(["C+*plus cards", "D+*plus cards"])
42
- end
43
- end
44
-
45
- describe "in" do
46
- example "content option" do
47
- @query = { in: %w(AlphaBeta Theta) }
48
- is_expected.to eq(%w(A+B T))
49
- end
50
-
51
- it "finds the same thing in full syntax" do
52
- @query = { content: [:in, "Theta", "AlphaBeta"] }
53
- is_expected.to eq(%w(A+B T))
54
- end
55
-
56
- example "type option" do
57
- @query = { type: [:in, "Cardtype E", "Cardtype F"] }
58
- is_expected.to eq(%w(type-e-card type-f-card))
59
- end
60
- end
61
-
62
- describe "member_of" do
63
- it "finds members" do
64
- @query = { member_of: "r1" }
65
- is_expected.to eq(%w(u1 u2 u3))
66
- end
67
- end
68
-
69
- describe "member" do
70
- it "finds roles" do
71
- @query = { member: { match: "u1" } }
72
- is_expected.to eq(%w(r1 r2 r3))
73
- end
74
- end
75
-
76
- describe "not" do
77
- it "excludes cards matching not criteria" do
78
- Card::Auth.as_bot
79
- @query = { plus: "A", not: { plus: "A+B" } }
80
- is_expected.to eq(%w(B D E F))
81
- end
82
- end
83
-
84
- describe "multiple values" do
85
- it "handles :all as the first element of an Array" do
86
- @query = { member_of: [:all, { name: "r1" }, { key: "r2" }] }
87
- is_expected.to eq(%w(u1 u2))
88
- end
89
-
90
- it "handles act like :all by default" do
91
- @query = { member_of: [{ name: "r1" }, { key: "r2" }] }
92
- is_expected.to eq(%w(u1 u2))
93
- end
94
-
95
- it "handles :any as the first element of an Array" do
96
- @query = { member_of: [:any, { name: "r1" }, { key: "r2" }] }
97
- is_expected.to eq(%w(u1 u2 u3))
98
- end
99
-
100
- it "handles :any as a relationship" do
101
- @query = { member_of: { any: [{ name: "r1" }, { key: "r2" }] } }
102
- is_expected.to eq(%w(u1 u2 u3))
103
- end
104
-
105
- it "handles explicit conjunctions in plus_relational keys" do
106
- @query = { right_plus: [:all, "e", "c"] }
107
- is_expected.to eq(%w(A))
108
- end
109
-
110
- it "handles multiple values for right_part in compound relations" do
111
- @query = { right_plus: [["e", {}], "c"] }
112
- is_expected.to eq(%w(A)) # first element is array
113
- end
114
-
115
- it "does not interpret simple arrays as multi values for plus" do
116
- @query = { right_plus: %w(e c) }
117
- is_expected.to eq([]) # NOT interpreted as multi-value
118
- end
119
-
120
- it "handles :and for references" do
121
- @query = { refer_to: [:and, "a", "b"] }
122
- is_expected.to eq(%w(Y))
123
- end
124
-
125
- it "handles :or for references" do
126
- @query = { refer_to: [:or, "b", "z"] }
127
- is_expected.to eq(%w(A B Y))
128
- end
129
-
130
- it "handles treat simple arrays like :all for references" do
131
- @query = { refer_to: %w(A T) }
132
- is_expected.to eq(%w(X Y))
133
- end
134
- end
135
-
136
- describe "edited_by/editor_of" do
137
- it "finds card edited by joe using subquery" do
138
- @query = { edited_by: { match: "Joe User" } }
139
- is_expected.to include("JoeLater", "JoeNow")
140
- end
141
-
142
- it "finds card edited by Wagn Bot" do
143
- # this is a weak test, since it gives the name, but different sorting
144
- # mechanisms in other db setups
145
- # was having it return *account in some cases and 'A' in others
146
- @query = { edited_by: "Wagn Bot", name: "A" }
147
- is_expected.to eq(%w(A))
148
- end
149
-
150
- it "fails gracefully if user isn't there" do
151
- @query = { edited_by: "Joe LUser" }
152
- is_expected.to eq([])
153
- end
154
-
155
- it "does not give duplicate results for multiple edits" do
156
- c = Card["JoeNow"]
157
- c.content = "testagagin"
158
- c.save
159
- c.content = "test3"
160
- c.save!
161
- @query = { edited_by: "Joe User" }
162
- is_expected.to include("JoeLater", "JoeNow")
163
- end
164
-
165
- it "finds joe user among card's editors" do
166
- @query = { editor_of: "JoeLater" }
167
- is_expected.to eq(["Joe User"])
168
- end
169
- end
170
-
171
- describe "updated_by/updater_of" do
172
- it "finds card updated by Narcissist" do
173
- @query = { updated_by: "Narcissist" }
174
- is_expected.to eq(%w(Magnifier+lens))
175
- end
176
-
177
- it "finds Narcississt as the card's updater" do
178
- @query = { updater_of: "Magnifier+lens" }
179
- is_expected.to eq(%w(Narcissist))
180
- end
181
-
182
- it "does not give duplicate results for multiple updates" do
183
- @query = { updater_of: "First" }
184
- is_expected.to eq(["Wagn Bot"])
185
- end
186
-
187
- it "does not give results if not updated" do
188
- @query = { updater_of: "Sunglasses+price" }
189
- is_expected.to be_empty
190
- end
191
-
192
- it "'or' doesn't mess up updated_by SQL" do
193
- @query = { or: { updated_by: "Narcissist" } }
194
- is_expected.to eq(%w(Magnifier+lens))
195
- end
196
-
197
- it "'or' doesn't mess up updater_of SQL" do
198
- @query = { or: { updater_of: "First" } }
199
- is_expected.to eq(["Wagn Bot"])
200
- end
201
- end
202
-
203
- describe "created_by/creator_of" do
204
- before do
205
- Card.create name: "Create Test", content: "sufficiently distinctive"
206
- end
207
-
208
- it "finds Joe User as the card's creator" do
209
- @query = { creator_of: "Create Test" }
210
- is_expected.to eq(["Joe User"])
211
- end
212
-
213
- it "finds card created by Joe User" do
214
- @query = { created_by: "Joe User", eq: "sufficiently distinctive" }
215
- is_expected.to eq(["Create Test"])
216
- end
217
- end
218
-
219
- describe "last_edited_by/last_editor_of" do
220
- before do
221
- c = Card.fetch("A")
222
- c.content = "peculicious"
223
- c.save!
224
- end
225
-
226
- it "finds Joe User as the card's last editor" do
227
- @query = { last_editor_of: "A" }
228
- is_expected.to eq(["Joe User"])
229
- end
230
-
231
- it "finds card created by Joe User" do
232
- @query = { last_edited_by: "Joe User", eq: "peculicious" }
233
- is_expected.to eq(["A"])
234
- end
235
- end
236
-
237
- describe "keyword" do
238
- it "escapes nonword characters" do
239
- @query = { match: "two :(!" }
240
- is_expected.to eq(CARDS_MATCHING_TWO)
241
- end
242
- end
243
-
244
- describe "search count" do
245
- it "returns integer" do
246
- search = Card.create!(
247
- name: "tmpsearch",
248
- type: "Search",
249
- content: '{"match":"two"}'
250
- )
251
- expect(search.count).to eq(CARDS_MATCHING_TWO.length + 1)
252
- end
253
- end
254
-
255
- describe "vars" do
256
- it "replace placeholders" do
257
- @query = { match: "$keyword", vars: { keyword: "two" } }
258
- is_expected.to eq(CARDS_MATCHING_TWO)
259
- end
260
-
261
- it "replace placeholders in nested queries" do
262
- @query = { and: { match: "$keyword" }, vars: { keyword: "two" } }
263
- is_expected.to eq(CARDS_MATCHING_TWO)
264
- end
265
- end
266
-
267
- describe "content equality" do
268
- it "matchs content explicitly" do
269
- @query = { content: ["=", "I'm number two"] }
270
- is_expected.to eq(["Joe User"])
271
- end
272
-
273
- it "matchs via shortcut" do
274
- @query = { "=" => "I'm number two" }
275
- is_expected.to eq(["Joe User"])
276
- end
277
- end
278
-
279
- describe "links" do
280
- it "handles refer_to" do
281
- @query = { refer_to: "Z" }
282
- is_expected.to eq(%w(A B))
283
- end
284
-
285
- it "handles link_to" do
286
- @query = { link_to: "Z" }
287
- is_expected.to eq(%w(A))
288
- end
289
-
290
- it "handles include" do
291
- @query = { include: "Z" }
292
- is_expected.to eq(%w(B))
293
- end
294
-
295
- it "handles linked_to_by" do
296
- @query = { linked_to_by: "A" }
297
- is_expected.to eq(%w(Z))
298
- end
299
-
300
- it "handles included_by" do
301
- @query = { included_by: "B" }
302
- is_expected.to eq(%w(Z))
303
- end
304
-
305
- it "handles referred_to_by" do
306
- @query = { referred_to_by: "X" }
307
- is_expected.to eq(%w(A A+B T))
308
- end
309
- end
310
-
311
- describe "compound relationships" do
312
- it "right_plus should handle subqueries" do
313
- @query = { right_plus: ["*create", refer_to: "Anyone"] }
314
- is_expected.to eq(["Fruit+*type", "Sign up+*type"])
315
- end
316
-
317
- it "plus should handle subqueries" do # albeit more slowly :)
318
- @query = { plus: ["*create", refer_to: "Anyone"] }
319
- is_expected.to eq(["Fruit+*type", "Sign up+*type"])
320
- end
321
- end
322
-
323
- describe "relative links" do
324
- it "handles relative refer_to" do
325
- @query = { refer_to: "_self", context: "Z" }
326
- is_expected.to eq(%w(A B))
327
- end
328
- end
329
-
330
- describe "permissions" do
331
- it "does not find cards not in group" do
332
- Card::Auth.as_bot do
333
- Card.create name: "C+*self+*read", type: "Pointer", content: "[[R1]]"
334
- end
335
- @query = { plus: "A" }
336
- is_expected.to eq(%w(B D E F))
337
- end
338
- end
339
-
340
- describe "basics" do
341
- it "is case insensitive for name" do
342
- @query = { name: "a" }
343
- is_expected.to eq(["A"])
344
- end
345
-
346
- it "finds plus cards" do
347
- @query = { plus: "A" }
348
- is_expected.to eq(A_JOINEES)
349
- end
350
-
351
- it "finds connection cards" do
352
- @query = { part: "A" }
353
- is_expected.to eq(%w(A+B A+C A+D A+E C+A D+A F+A))
354
- end
355
-
356
- it "finds left connection cards" do
357
- @query = { left: "A" }
358
- is_expected.to eq(%w(A+B A+C A+D A+E))
359
- end
360
-
361
- it "finds right connection cards based on name" do
362
- @query = { right: "A" }
363
- is_expected.to eq(%w(C+A D+A F+A))
364
- end
365
-
366
- it "finds right connection cards based on content" do
367
- @query = { right: { content: "Alpha [[Z]]" } }
368
- is_expected.to eq(%w(C+A D+A F+A))
369
- end
370
-
371
- it "returns count" do
372
- expect(Card.count_by_wql part: "A").to eq(7)
373
- end
374
- end
375
-
376
- describe "limit and offset" do
377
- it "returns limit" do
378
- @query = { part: "A", limit: 5 }
379
- expect(subject.size).to eq(5)
380
- end
381
-
382
- it "does not break if offset but no limit" do
383
- @query = { part: "A", offset: 5 }
384
- expect(subject.size).not_to eq(0)
385
- end
386
-
387
- it "does not break count" do
388
- query = { match: "two", offset: 1 }
389
- expect(Card.count_by_wql(query)).to eq(CARDS_MATCHING_TWO.length)
390
- end
391
- end
392
-
393
- describe "type" do
394
- user_cards = [
395
- "Big Brother", "Joe Admin", "Joe Camel", "Joe User", "John",
396
- "Narcissist", "No Count", "Optic fan", "Sample User", "Sara",
397
- "Sunglasses fan", "u1", "u2", "u3"
398
- ].sort
399
-
400
- it "finds cards of this type" do
401
- @query = { type: "_self", context: "User" }
402
- is_expected.to eq(user_cards)
403
- end
404
-
405
- it "finds User cards " do
406
- @query = { type: "User" }
407
- is_expected.to eq(user_cards)
408
- end
409
-
410
- it "handles casespace variants" do
411
- @query = { type: "users" }
412
- is_expected.to eq(user_cards)
413
- end
414
- end
415
-
416
- describe "trash handling" do
417
- it "does not find cards in the trash" do
418
- Card["A+B"].delete!
419
- @query = { left: "A" }
420
- is_expected.to eq(["A+C", "A+D", "A+E"])
421
- end
422
- end
423
-
424
- describe "match" do
425
- it "reachs content and name via shortcut" do
426
- @query = { match: "two" }
427
- is_expected.to eq(CARDS_MATCHING_TWO)
428
- end
429
-
430
- it "gets only content when content is explicit" do
431
- @query = { content: [:match, "two"] }
432
- is_expected.to eq(["Joe User"])
433
- end
434
-
435
- it "gets only name when name is explicit" do
436
- @query = { name: [:match, "two"] }
437
- is_expected.to eq(["One+Two", "One+Two+Three", "Two"])
438
- end
439
- end
440
-
441
- describe "and" do
442
- it "acts as a simple passthrough with operators" do
443
- @query = { and: { match: "two" } }
444
- is_expected.to eq(CARDS_MATCHING_TWO)
445
- end
446
-
447
- it "acts as a simple passthrough with relationships" do
448
- @query = { and: {}, type: "Cardtype E" }
449
- is_expected.to eq(["type-e-card"])
450
- end
451
-
452
- it 'works within "or"' do
453
- @query = { or: { name: "Z", and: { left: "A", right: "C" } } }
454
- is_expected.to eq(["A+C", "Z"])
455
- end
456
- end
457
-
458
- describe "any" do
459
- it "works with :plus" do
460
- @query = { plus: "A", any: { name: "B", match: "K" } }
461
- is_expected.to eq(["B"])
462
- end
463
-
464
- it "works with multiple plusses" do
465
- @query = { or: { right_plus: "A", plus: "B" } }
466
- is_expected.to eq(%w(A C D F))
467
- end
468
- end
469
-
470
- describe "found_by" do
471
- before do
472
- Card::Auth.as_bot
473
- Card.create(
474
- name: "Simple Search", type: "Search", content: '{"name":"A"}'
475
- )
476
- end
477
-
478
- it "finds cards returned by search of given name" do
479
- @query = { found_by: "Simple Search" }
480
- is_expected.to eq(["A"])
481
- end
482
-
483
- it "finds cards returned by virtual cards" do
484
- image_cards = Card.search type: "Image", return: :name, sort: :name
485
- @query = { found_by: "Image+*type+by name" }
486
- is_expected.to eq(image_cards)
487
- end
488
-
489
- it "plays nicely with other properties and relationships" do
490
- explicit_query = { plus: { name: "A" }, return: :name, sort: :name }
491
- @query = { plus: { found_by: "Simple Search" } }
492
- is_expected.to eq(Card::Query.run(explicit_query))
493
- end
494
-
495
- it "plays work with virtual cards" do
496
- @query = { found_by: "A+*self", plus: "C" }
497
- is_expected.to eq(["A"])
498
- end
499
-
500
- it "is able to handle _self" do
501
- @query = {
502
- context: "Simple Search",
503
- left: { found_by: "_self" },
504
- right: "B",
505
- return: :name
506
- }
507
- is_expected.to eq(["A+B"])
508
- end
509
- end
510
-
511
- describe "relative" do
512
- it "cleans wql" do
513
- query = Card::Query.new(part: "_self", context: "A")
514
- expect(query.statement[:part]).to eq("A")
515
- end
516
-
517
- it "finds connection cards" do
518
- @query = { part: "_self", context: "A" }
519
- is_expected.to eq(%w(A+B A+C A+D A+E C+A D+A F+A))
520
- end
521
-
522
- it "is able to use parts of nonexistent cards in search" do
523
- expect(Card["B+A"]).to be_nil
524
- @query = { left: "_right", right: "_left", context: "B+A" }
525
- is_expected.to eq(["A+B"])
526
- end
527
-
528
- it "finds plus cards for _self" do
529
- @query = { plus: "_self", context: "A" }
530
- is_expected.to eq(A_JOINEES)
531
- end
532
-
533
- it "finds plus cards for _left" do
534
- @query = { plus: "_left", context: "A+B" }
535
- is_expected.to eq(A_JOINEES)
536
- end
537
-
538
- it "finds plus cards for _right" do
539
- @query = { plus: "_right", context: "C+A" }
540
- is_expected.to eq(A_JOINEES)
541
- end
542
- end
543
-
544
- describe "nested permissions" do
545
- it "are generated by default" do
546
- perm_count = 0
547
- sql = Card::Query.new(left: { name: "X" }).sql
548
- sql.scan(/read_rule_id IN \([\d\,]+\)/) do
549
- perm_count += 1
550
- end
551
- expect(perm_count).to eq(2)
552
- end
553
- end
554
-
555
- describe "return part of name" do
556
- subject do
557
- Card::Query.run right: "C", return: @return, sort: :name
558
- end
559
- it "handles _left" do
560
- @return = "_left"
561
- is_expected.to eq %w(A+B A)
562
- end
563
-
564
- it "handles _right" do
565
- @return = "_right"
566
- is_expected.to eq %w(C C)
567
- end
568
-
569
- it "handles _LL" do
570
- @return = "_LL"
571
- is_expected.to eq ["A", "A+C"]
572
- end
573
- end
574
- end