nucleo-client 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. checksums.yaml +7 -0
  2. data/.env.sample +2 -0
  3. data/.gitignore +16 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +31 -0
  7. data/Rakefile +37 -0
  8. data/lib/nucleo/client.rb +172 -0
  9. data/lib/nucleo/client/version.rb +5 -0
  10. data/lib/nucleo/configuration.rb +83 -0
  11. data/lib/nucleo/configurations.rb +6 -0
  12. data/lib/nucleo/configurations/default.rb +100 -0
  13. data/lib/nucleo/connection.rb +44 -0
  14. data/lib/nucleo/errors.rb +7 -0
  15. data/lib/nucleo/errors/invalid_uri_error.rb +6 -0
  16. data/lib/nucleo/errors/record_not_found.rb +6 -0
  17. data/lib/nucleo/logger.rb +36 -0
  18. data/lib/nucleo/models.rb +50 -0
  19. data/lib/nucleo/models/change_types.rb +10 -0
  20. data/lib/nucleo/models/change_types/base.rb +81 -0
  21. data/lib/nucleo/models/change_types/seo.rb +13 -0
  22. data/lib/nucleo/models/change_types/seo/base.rb +50 -0
  23. data/lib/nucleo/models/change_types/seo/meta_description.rb +10 -0
  24. data/lib/nucleo/models/change_types/seo/page_title.rb +10 -0
  25. data/lib/nucleo/models/changes.rb +50 -0
  26. data/lib/nucleo/models/check_js.rb +41 -0
  27. data/lib/nucleo/models/check_types.rb +11 -0
  28. data/lib/nucleo/models/check_types/base.rb +25 -0
  29. data/lib/nucleo/models/check_types/count.rb +26 -0
  30. data/lib/nucleo/models/check_types/length.rb +26 -0
  31. data/lib/nucleo/models/check_types/not_exists.rb +8 -0
  32. data/lib/nucleo/models/checks.rb +56 -0
  33. data/lib/nucleo/models/concerns.rb +7 -0
  34. data/lib/nucleo/models/concerns/count.rb +57 -0
  35. data/lib/nucleo/models/concerns/length.rb +57 -0
  36. data/lib/nucleo/models/date_range.rb +66 -0
  37. data/lib/nucleo/models/element.rb +40 -0
  38. data/lib/nucleo/models/elements.rb +47 -0
  39. data/lib/nucleo/models/feed.rb +141 -0
  40. data/lib/nucleo/models/feed_types.rb +11 -0
  41. data/lib/nucleo/models/feed_types/analytics.rb +18 -0
  42. data/lib/nucleo/models/feed_types/analytics/base.rb +12 -0
  43. data/lib/nucleo/models/feed_types/analytics/page/channels.rb +61 -0
  44. data/lib/nucleo/models/feed_types/analytics/page/pages.rb +58 -0
  45. data/lib/nucleo/models/feed_types/analytics/page/referrers.rb +61 -0
  46. data/lib/nucleo/models/feed_types/analytics/page/social.rb +61 -0
  47. data/lib/nucleo/models/feed_types/analytics/site/channels.rb +61 -0
  48. data/lib/nucleo/models/feed_types/analytics/site/pages.rb +61 -0
  49. data/lib/nucleo/models/feed_types/analytics/site/referrers.rb +61 -0
  50. data/lib/nucleo/models/feed_types/analytics/site/social.rb +61 -0
  51. data/lib/nucleo/models/feed_types/base.rb +182 -0
  52. data/lib/nucleo/models/feed_types/seo.rb +22 -0
  53. data/lib/nucleo/models/feed_types/seo/page/base.rb +47 -0
  54. data/lib/nucleo/models/feed_types/seo/page/img_alt.rb +90 -0
  55. data/lib/nucleo/models/feed_types/seo/page/meta_description.rb +49 -0
  56. data/lib/nucleo/models/feed_types/seo/page/meta_robots.rb +48 -0
  57. data/lib/nucleo/models/feed_types/seo/page/page_title.rb +48 -0
  58. data/lib/nucleo/models/feed_types/seo/page/seo_summary.rb +53 -0
  59. data/lib/nucleo/models/feed_types/seo/page/summary.rb +52 -0
  60. data/lib/nucleo/models/feed_types/seo/site/base.rb +22 -0
  61. data/lib/nucleo/models/feed_types/seo/site/img_alt.rb +14 -0
  62. data/lib/nucleo/models/feed_types/seo/site/meta_description.rb +14 -0
  63. data/lib/nucleo/models/feed_types/seo/site/meta_robots.rb +14 -0
  64. data/lib/nucleo/models/feed_types/seo/site/page_title.rb +14 -0
  65. data/lib/nucleo/models/feeds.rb +126 -0
  66. data/lib/nucleo/models/metric.rb +54 -0
  67. data/lib/nucleo/models/metric_period.rb +97 -0
  68. data/lib/nucleo/models/metric_period_row.rb +125 -0
  69. data/lib/nucleo/models/metric_period_rows.rb +34 -0
  70. data/lib/nucleo/models/metric_period_totals.rb +121 -0
  71. data/lib/nucleo/models/metric_periods.rb +78 -0
  72. data/lib/nucleo/models/metric_periods_comparison.rb +80 -0
  73. data/lib/nucleo/models/metric_periods_comparisons.rb +73 -0
  74. data/lib/nucleo/models/metric_periods_totals.rb +58 -0
  75. data/lib/nucleo/models/page.rb +147 -0
  76. data/lib/nucleo/models/page_alerts.rb +27 -0
  77. data/lib/nucleo/models/page_metric.rb +58 -0
  78. data/lib/nucleo/models/page_rank.rb +28 -0
  79. data/lib/nucleo/models/pages.rb +40 -0
  80. data/lib/nucleo/models/seo_score.rb +28 -0
  81. data/lib/nucleo/models/site_feed.rb +82 -0
  82. data/lib/nucleo/models/tag.rb +48 -0
  83. data/lib/nucleo/models/tags.rb +35 -0
  84. data/lib/nucleo/requests.rb +14 -0
  85. data/lib/nucleo/requests/analyzer.rb +35 -0
  86. data/lib/nucleo/requests/check_js.rb +56 -0
  87. data/lib/nucleo/requests/feed.rb +58 -0
  88. data/lib/nucleo/requests/page.rb +113 -0
  89. data/lib/nucleo/requests/page_alerts.rb +36 -0
  90. data/lib/nucleo/requests/page_changes.rb +44 -0
  91. data/lib/nucleo/requests/site.rb +26 -0
  92. data/lib/nucleo/requests/site_changes.rb +56 -0
  93. data/lib/nucleo/requests/site_feed.rb +41 -0
  94. data/lib/nucleo/response.rb +52 -0
  95. data/lib/nucleo/utilities.rb +7 -0
  96. data/lib/nucleo/utilities/status_code_mapper.rb +53 -0
  97. data/lib/nucleo/webhook.rb +26 -0
  98. data/nucleo-client.gemspec +35 -0
  99. data/spec/data/models/feed_types/seo/heading_tag_length.json +55 -0
  100. data/spec/data/models/feed_types/seo/internal_link_count.json +149 -0
  101. data/spec/data/models/feed_types/seo/no_follow_link_count.json +142 -0
  102. data/spec/spec_helper.rb +15 -0
  103. data/spec/unit/nucleo/models/concerns/count_spec.rb +103 -0
  104. data/spec/unit/nucleo/models/concerns/length_spec.rb +79 -0
  105. data/spec/unit/nucleo/models/feed_types/analytics/site/pages_no_data_spec.rb +39 -0
  106. data/spec/unit/nucleo/models/metric_periods_comparison_spec.rb +50 -0
  107. data/spec/unit/nucleo/models/metric_periods_comparisons_spec.rb +58 -0
  108. metadata +341 -0
@@ -0,0 +1,142 @@
1
+ {
2
+ "category": "seo",
3
+ "data": {
4
+ "count": 735,
5
+ "points": 1,
6
+ "identified_at": "2016-10-11T04:06:02.183396",
7
+ "last_checked_at": "2016-10-11T04:06:02.183441",
8
+ "tags": [
9
+ {
10
+ "content_length": 5,
11
+ "full_tag": "<a rel=\"nofollow\" class=\"comment-reply-link\" href=\"https://www.quicksprout.com/2012/11/19/the-science-of-instagram-how-to-get-more-followers-and-likes/?replytocom=137898#respond\" onclick=\"return addComment.moveForm( &quot;comment-137898&quot;, &quot;137898&quot;, &quot;respond&quot;, &quot;6201&quot; )\" aria-label=\"Reply to Leith\">Reply</a>\t\t",
12
+ "tag_content": "Reply"
13
+ },
14
+ {
15
+ "content_length": 10,
16
+ "full_tag": "<a href=\"http://www.quicksprout.com\" rel=\"external nofollow\" class=\"url\">Neil Patel</a>",
17
+ "tag_content": "Neil Patel"
18
+ },
19
+ {
20
+ "content_length": 5,
21
+ "full_tag": "<a rel=\"nofollow\" class=\"comment-reply-link\" href=\"https://www.quicksprout.com/2012/11/19/the-science-of-instagram-how-to-get-more-followers-and-likes/?replytocom=137942#respond\" onclick=\"return addComment.moveForm( &quot;comment-137942&quot;, &quot;137942&quot;, &quot;respond&quot;, &quot;6201&quot; )\" aria-label=\"Reply to Neil Patel\">Reply</a>\t\t",
22
+ "tag_content": "Reply"
23
+ },
24
+ {
25
+ "content_length": 5,
26
+ "full_tag": "<a rel=\"nofollow\" class=\"comment-reply-link\" href=\"https://www.quicksprout.com/2012/11/19/the-science-of-instagram-how-to-get-more-followers-and-likes/?replytocom=137991#respond\" onclick=\"return addComment.moveForm( &quot;comment-137991&quot;, &quot;137991&quot;, &quot;respond&quot;, &quot;6201&quot; )\" aria-label=\"Reply to Lorna\">Reply</a>\t\t",
27
+ "tag_content": "Reply"
28
+ },
29
+ {
30
+ "content_length": 10,
31
+ "full_tag": "<a href=\"http://www.quicksprout.com\" rel=\"external nofollow\" class=\"url\">Neil Patel</a>",
32
+ "tag_content": "Neil Patel"
33
+ },
34
+ {
35
+ "content_length": 5,
36
+ "full_tag": "<a rel=\"nofollow\" class=\"comment-reply-link\" href=\"https://www.quicksprout.com/2012/11/19/the-science-of-instagram-how-to-get-more-followers-and-likes/?replytocom=137998#respond\" onclick=\"return addComment.moveForm( &quot;comment-137998&quot;, &quot;137998&quot;, &quot;respond&quot;, &quot;6201&quot; )\" aria-label=\"Reply to Neil Patel\">Reply</a>\t\t",
37
+ "tag_content": "Reply"
38
+ },
39
+ {
40
+ "content_length": 10,
41
+ "full_tag": "<a href=\"http://www.quicksprout.com\" rel=\"external nofollow\" class=\"url\">Neil Patel</a>",
42
+ "tag_content": "Neil Patel"
43
+ },
44
+ {
45
+ "content_length": 5,
46
+ "full_tag": "<a rel=\"nofollow\" class=\"comment-reply-link\" href=\"https://www.quicksprout.com/2012/11/19/the-science-of-instagram-how-to-get-more-followers-and-likes/?replytocom=214516#respond\" onclick=\"return addComment.moveForm( &quot;comment-214516&quot;, &quot;214516&quot;, &quot;respond&quot;, &quot;6201&quot; )\" aria-label=\"Reply to Neil Patel\">Reply</a>\t\t",
47
+ "tag_content": "Reply"
48
+ },
49
+ {
50
+ "content_length": 5,
51
+ "full_tag": "<a rel=\"nofollow\" class=\"comment-reply-link\" href=\"https://www.quicksprout.com/2012/11/19/the-science-of-instagram-how-to-get-more-followers-and-likes/?replytocom=2461656#respond\" onclick=\"return addComment.moveForm( &quot;comment-2461656&quot;, &quot;2461656&quot;, &quot;respond&quot;, &quot;6201&quot; )\" aria-label=\"Reply to Annamonnika\">Reply</a>\t\t",
52
+ "tag_content": "Reply"
53
+ },
54
+ {
55
+ "content_length": 10,
56
+ "full_tag": "<a href=\"http://www.quicksprout.com\" rel=\"external nofollow\" class=\"url\">Neil Patel</a>",
57
+ "tag_content": "Neil Patel"
58
+ },
59
+ {
60
+ "content_length": 5,
61
+ "full_tag": "<a rel=\"nofollow\" class=\"comment-reply-link\" href=\"https://www.quicksprout.com/2012/11/19/the-science-of-instagram-how-to-get-more-followers-and-likes/?replytocom=2462237#respond\" onclick=\"return addComment.moveForm( &quot;comment-2462237&quot;, &quot;2462237&quot;, &quot;respond&quot;, &quot;6201&quot; )\" aria-label=\"Reply to Neil Patel\">Reply</a>\t\t",
62
+ "tag_content": "Reply"
63
+ },
64
+ {
65
+ "content_length": 5,
66
+ "full_tag": "<a rel=\"nofollow\" class=\"comment-reply-link\" href=\"https://www.quicksprout.com/2012/11/19/the-science-of-instagram-how-to-get-more-followers-and-likes/?replytocom=2708226#respond\" onclick=\"return addComment.moveForm( &quot;comment-2708226&quot;, &quot;2708226&quot;, &quot;respond&quot;, &quot;6201&quot; )\" aria-label=\"Reply to Leonardo &quot;List Legend&quot; LaVito\">Reply</a>\t\t",
67
+ "tag_content": "Reply"
68
+ },
69
+ {
70
+ "content_length": 10,
71
+ "full_tag": "<a href=\"http://www.quicksprout.com\" rel=\"external nofollow\" class=\"url\">Neil Patel</a>",
72
+ "tag_content": "Neil Patel"
73
+ },
74
+ {
75
+ "content_length": 5,
76
+ "full_tag": "<a rel=\"nofollow\" class=\"comment-reply-link\" href=\"https://www.quicksprout.com/2012/11/19/the-science-of-instagram-how-to-get-more-followers-and-likes/?replytocom=2709204#respond\" onclick=\"return addComment.moveForm( &quot;comment-2709204&quot;, &quot;2709204&quot;, &quot;respond&quot;, &quot;6201&quot; )\" aria-label=\"Reply to Neil Patel\">Reply</a>\t\t",
77
+ "tag_content": "Reply"
78
+ },
79
+ {
80
+ "content_length": 5,
81
+ "full_tag": "<a rel=\"nofollow\" class=\"comment-reply-link\" href=\"https://www.quicksprout.com/2012/11/19/the-science-of-instagram-how-to-get-more-followers-and-likes/?replytocom=236927#respond\" onclick=\"return addComment.moveForm( &quot;comment-236927&quot;, &quot;236927&quot;, &quot;respond&quot;, &quot;6201&quot; )\" aria-label=\"Reply to Alexis\">Reply</a>\t\t",
82
+ "tag_content": "Reply"
83
+ },
84
+ {
85
+ "content_length": 5,
86
+ "full_tag": "<a rel=\"nofollow\" class=\"comment-reply-link\" href=\"https://www.quicksprout.com/2012/11/19/the-science-of-instagram-how-to-get-more-followers-and-likes/?replytocom=908860#respond\" onclick=\"return addComment.moveForm( &quot;comment-908860&quot;, &quot;908860&quot;, &quot;respond&quot;, &quot;6201&quot; )\" aria-label=\"Reply to lavonta\">Reply</a>\t\t",
87
+ "tag_content": "Reply"
88
+ },
89
+ {
90
+ "content_length": 5,
91
+ "full_tag": "<a rel=\"nofollow\" class=\"comment-reply-link\" href=\"https://www.quicksprout.com/2012/11/19/the-science-of-instagram-how-to-get-more-followers-and-likes/?replytocom=1910570#respond\" onclick=\"return addComment.moveForm( &quot;comment-1910570&quot;, &quot;1910570&quot;, &quot;respond&quot;, &quot;6201&quot; )\" aria-label=\"Reply to Taylor\">Reply</a>\t\t",
92
+ "tag_content": "Reply"
93
+ },
94
+ {
95
+ "content_length": 5,
96
+ "full_tag": "<a rel=\"nofollow\" class=\"comment-reply-link\" href=\"https://www.quicksprout.com/2012/11/19/the-science-of-instagram-how-to-get-more-followers-and-likes/?replytocom=2241637#respond\" onclick=\"return addComment.moveForm( &quot;comment-2241637&quot;, &quot;2241637&quot;, &quot;respond&quot;, &quot;6201&quot; )\" aria-label=\"Reply to Laura Salvaggio\">Reply</a>\t\t",
97
+ "tag_content": "Reply"
98
+ },
99
+ {
100
+ "content_length": 5,
101
+ "full_tag": "<a rel=\"nofollow\" class=\"comment-reply-link\" href=\"https://www.quicksprout.com/2012/11/19/the-science-of-instagram-how-to-get-more-followers-and-likes/?replytocom=157019#respond\" onclick=\"return addComment.moveForm( &quot;comment-157019&quot;, &quot;157019&quot;, &quot;respond&quot;, &quot;6201&quot; )\" aria-label=\"Reply to lexie\">Reply</a>\t\t",
102
+ "tag_content": "Reply"
103
+ },
104
+ {
105
+ "content_length": 5,
106
+ "full_tag": "<a rel=\"nofollow\" class=\"comment-reply-link\" href=\"https://www.quicksprout.com/2012/11/19/the-science-of-instagram-how-to-get-more-followers-and-likes/?replytocom=246234#respond\" onclick=\"return addComment.moveForm( &quot;comment-246234&quot;, &quot;246234&quot;, &quot;respond&quot;, &quot;6201&quot; )\" aria-label=\"Reply to RBIproductions\">Reply</a>\t\t",
107
+ "tag_content": "Reply"
108
+ },
109
+ {
110
+ "content_length": 5,
111
+ "full_tag": "<a rel=\"nofollow\" class=\"comment-reply-link\" href=\"https://www.quicksprout.com/2012/11/19/the-science-of-instagram-how-to-get-more-followers-and-likes/?replytocom=2353146#respond\" onclick=\"return addComment.moveForm( &quot;comment-2353146&quot;, &quot;2353146&quot;, &quot;respond&quot;, &quot;6201&quot; )\" aria-label=\"Reply to Mallory\">Reply</a>\t\t",
112
+ "tag_content": "Reply"
113
+ },
114
+ {
115
+ "content_length": 5,
116
+ "full_tag": "<a rel=\"nofollow\" class=\"comment-reply-link\" href=\"https://www.quicksprout.com/2012/11/19/the-science-of-instagram-how-to-get-more-followers-and-likes/?replytocom=221256#respond\" onclick=\"return addComment.moveForm( &quot;comment-221256&quot;, &quot;221256&quot;, &quot;respond&quot;, &quot;6201&quot; )\" aria-label=\"Reply to Paul\">Reply</a>\t\t",
117
+ "tag_content": "Reply"
118
+ },
119
+ {
120
+ "content_length": 5,
121
+ "full_tag": "<a rel=\"nofollow\" class=\"comment-reply-link\" href=\"https://www.quicksprout.com/2012/11/19/the-science-of-instagram-how-to-get-more-followers-and-likes/?replytocom=876854#respond\" onclick=\"return addComment.moveForm( &quot;comment-876854&quot;, &quot;876854&quot;, &quot;respond&quot;, &quot;6201&quot; )\" aria-label=\"Reply to instakip\">Reply</a>\t\t",
122
+ "tag_content": "Reply"
123
+ },
124
+ {
125
+ "content_length": 5,
126
+ "full_tag": "<a rel=\"nofollow\" class=\"comment-reply-link\" href=\"https://www.quicksprout.com/2012/11/19/the-science-of-instagram-how-to-get-more-followers-and-likes/?replytocom=230670#respond\" onclick=\"return addComment.moveForm( &quot;comment-230670&quot;, &quot;230670&quot;, &quot;respond&quot;, &quot;6201&quot; )\" aria-label=\"Reply to Keith Whitman\">Reply</a>\t\t",
127
+ "tag_content": "Reply"
128
+ },
129
+ {
130
+ "content_length": 5,
131
+ "full_tag": "<a rel=\"nofollow\" class=\"comment-reply-link\" href=\"https://www.quicksprout.com/2012/11/19/the-science-of-instagram-how-to-get-more-followers-and-likes/?replytocom=253129#respond\" onclick=\"return addComment.moveForm( &quot;comment-253129&quot;, &quot;253129&quot;, &quot;respond&quot;, &quot;6201&quot; )\" aria-label=\"Reply to Saryna Galvan\">Reply</a>\t\t",
132
+ "tag_content": "Reply"
133
+ }
134
+ ]
135
+ },
136
+ "site_id": 292,
137
+ "executed_at": "2016-10-11T04:06:02.183489",
138
+ "id": "0bb012ccda13c710a8a7309bd657368665f1ca06546b32d03eb544d4dc4b8a50",
139
+ "status": "unresolved",
140
+ "context": "page",
141
+ "type": "no_follow_link_count"
142
+ }
@@ -0,0 +1,15 @@
1
+ # http://www.relaxdiego.com/2013/06/mocking-web-services-with-vcr.html
2
+
3
+ require 'webmock/rspec'
4
+
5
+ # Load support files
6
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
7
+
8
+ require 'nucleo/client'
9
+
10
+ RSpec.configure do |config|
11
+ config.after(:suite) do
12
+ WebMock.disable!
13
+ end
14
+ end
15
+
@@ -0,0 +1,103 @@
1
+ require File.expand_path('../../../../../../lib/nucleo/models/concerns/count', __FILE__)
2
+
3
+ RSpec.describe(Nucleo::Models::Concerns::Count) do
4
+ let(:count) { 25 }
5
+ let(:min) { 5 }
6
+ let(:max) { 100 }
7
+
8
+ subject { described_class.new(count, min, max) }
9
+
10
+ context "within range" do
11
+ it "returns false for #missing?" do
12
+ expect(subject.missing?).to be(false)
13
+ end
14
+
15
+ it "returns true for #multiple?" do
16
+ expect(subject.multiple?).to be(true)
17
+ end
18
+
19
+ it "returns false for #too_few?" do
20
+ expect(subject.too_few?).to be(false)
21
+ end
22
+
23
+ it "returns true for #max?" do
24
+ expect(subject.max?).to be(true)
25
+ end
26
+
27
+ it "returns false for #too_many?" do
28
+ expect(subject.too_many?).to be(false)
29
+ end
30
+ end
31
+
32
+ context "missing" do
33
+ let(:count) { 0 }
34
+
35
+ it "returns true for #missing?" do
36
+ expect(subject.missing?).to be(true)
37
+ end
38
+
39
+ it "returns false for #multiple?" do
40
+ expect(subject.multiple?).to be(false)
41
+ end
42
+
43
+ it "returns true for #too_few?" do
44
+ expect(subject.too_few?).to be(true)
45
+ end
46
+
47
+ it "returns true for #max?" do
48
+ expect(subject.max?).to be(true)
49
+ end
50
+
51
+ it "returns false for #too_many?" do
52
+ expect(subject.too_many?).to be(false)
53
+ end
54
+ end
55
+
56
+ context "too many" do
57
+ let(:count) { 101 }
58
+
59
+ it "returns false for #missing?" do
60
+ expect(subject.missing?).to be(false)
61
+ end
62
+
63
+ it "returns true for #multiple?" do
64
+ expect(subject.multiple?).to be(true)
65
+ end
66
+
67
+ it "returns false for #too_few?" do
68
+ expect(subject.too_few?).to be(false)
69
+ end
70
+
71
+ it "returns true for #max?" do
72
+ expect(subject.max?).to be(true)
73
+ end
74
+
75
+ it "returns true for #too_many?" do
76
+ expect(subject.too_many?).to be(true)
77
+ end
78
+ end
79
+
80
+ context "without max" do
81
+ let(:max) { 0 }
82
+
83
+ it "returns false for #missing?" do
84
+ expect(subject.missing?).to be(false)
85
+ end
86
+
87
+ it "returns true for #multiple?" do
88
+ expect(subject.multiple?).to be(true)
89
+ end
90
+
91
+ it "returns false for #too_few?" do
92
+ expect(subject.too_few?).to be(false)
93
+ end
94
+
95
+ it "returns false for #max?" do
96
+ expect(subject.max?).to be(false)
97
+ end
98
+
99
+ it "returns false for #too_many?" do
100
+ expect(subject.too_many?).to be(false)
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,79 @@
1
+ require File.expand_path('../../../../../../lib/nucleo/models/concerns/length', __FILE__)
2
+
3
+ RSpec.describe(Nucleo::Models::Concerns::Length) do
4
+ let(:total) { 25 }
5
+ let(:min) { 5 }
6
+ let(:max) { 50 }
7
+
8
+ subject { described_class.new(total, min, max) }
9
+
10
+ context "within range" do
11
+ it "returns true for #max?" do
12
+ expect(subject.max?).to be(true)
13
+ end
14
+
15
+ it "returns false for #too_short?" do
16
+ expect(subject.too_short?).to be(false)
17
+ end
18
+
19
+ it "returns -20 for #too_short_length" do
20
+ expect(subject.too_short_length).to eq(-20)
21
+ end
22
+
23
+ it "returns false for #too_long?" do
24
+ expect(subject.too_long?).to be(false)
25
+ end
26
+
27
+ it "returns -25 for #too_long_length" do
28
+ expect(subject.too_long_length).to eq(-25)
29
+ end
30
+ end
31
+
32
+ context "too short" do
33
+ let(:total) { 4 }
34
+
35
+ it "returns true for #max?" do
36
+ expect(subject.max?).to be(true)
37
+ end
38
+
39
+ it "returns true for #too_short?" do
40
+ expect(subject.too_short?).to be(true)
41
+ end
42
+
43
+ it "returns 1 for #too_short_length" do
44
+ expect(subject.too_short_length).to eq(1)
45
+ end
46
+
47
+ it "returns false for #too_long?" do
48
+ expect(subject.too_long?).to be(false)
49
+ end
50
+
51
+ it "returns -46 for #too_long_length" do
52
+ expect(subject.too_long_length).to eq(-46)
53
+ end
54
+ end
55
+
56
+ context "too long" do
57
+ let(:total) { 51 }
58
+
59
+ it "returns true for #max?" do
60
+ expect(subject.max?).to be(true)
61
+ end
62
+
63
+ it "returns false for #too_short?" do
64
+ expect(subject.too_short?).to be(false)
65
+ end
66
+
67
+ it "returns -46 for #too_short_length" do
68
+ expect(subject.too_short_length).to eq(-46)
69
+ end
70
+
71
+ it "returns true for #too_long?" do
72
+ expect(subject.too_long?).to be(true)
73
+ end
74
+
75
+ it "returns 1 for #too_long_length" do
76
+ expect(subject.too_long_length).to eq(1)
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,39 @@
1
+ require 'multi_json'
2
+
3
+ require File.expand_path('../../../../../../../../lib/nucleo/models/feed_types/analytics/site/pages', __FILE__)
4
+
5
+ RSpec.describe(Nucleo::Models::FeedTypes::Analytics::Site::Pages, 'Pages with no data') do
6
+ let(:model_attributes) do
7
+ {
8
+ "metrics" => [],
9
+ "alerts" => [],
10
+ "changes" => [],
11
+ "pages" => []
12
+ }
13
+ end
14
+
15
+ subject { described_class.new(model_attributes) }
16
+
17
+ context "with empty values" do
18
+ it "returns an empty Metric model for metric" do
19
+ expect(subject.metric).to be_a(Nucleo::Models::Metric)
20
+ end
21
+
22
+ it "returns an empty MetricPeriodsTotals model for totals" do
23
+ expect(subject.totals).to be_a(Nucleo::Models::MetricPeriodsTotals)
24
+ end
25
+
26
+ it "returns an empty MetricPeriod model for current_period" do
27
+ expect(subject.current_period).to be_a(Nucleo::Models::MetricPeriod)
28
+ end
29
+
30
+ it "returns an empty MetricPeriod model for prior_period" do
31
+ expect(subject.prior_period).to be_a(Nucleo::Models::MetricPeriod)
32
+ end
33
+
34
+ it "returns false for #any?" do
35
+ expect(subject.any?).to be(false)
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,50 @@
1
+ require 'multi_json'
2
+
3
+ require File.expand_path('../../../../../lib/nucleo/models/metric_periods_comparisons', __FILE__)
4
+
5
+ RSpec.describe(Nucleo::Models::MetricPeriodsComparison) do
6
+ let(:model_attributes) do
7
+ {
8
+ 'dimension' => 'Google',
9
+ 'current_value' => 3445,
10
+ 'prior_value' => 2340,
11
+ 'change' => 23
12
+ }
13
+ end
14
+
15
+ subject { described_class.new(model_attributes) }
16
+
17
+ context "with valid values" do
18
+ it "returns the #dimension" do
19
+ expect(subject.dimension).to eq('Google')
20
+ end
21
+
22
+ it "returns the #current_value" do
23
+ expect(subject.current_value).to eq(3445)
24
+ end
25
+
26
+ it "returns the #prior_value" do
27
+ expect(subject.prior_value).to eq(2340)
28
+ end
29
+
30
+ it "returns the percent #change" do
31
+ expect(subject.change).to eq(23)
32
+ end
33
+
34
+ describe "#direction" do
35
+ it "returns 'up' with a positive change" do
36
+ expect(subject.direction).to eq('up')
37
+ end
38
+
39
+ it "returns 'same' with a no change" do
40
+ model_attributes['change'] = 0
41
+ expect(subject.direction).to eq('same')
42
+ end
43
+
44
+ it "returns 'down' with a negative change" do
45
+ model_attributes['change'] = -23
46
+ expect(subject.direction).to eq('down')
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,58 @@
1
+
2
+ require 'multi_json'
3
+
4
+ require File.expand_path('../../../../../lib/nucleo/models/metric_periods_comparisons', __FILE__)
5
+
6
+ RSpec.describe(Nucleo::Models::MetricPeriodsComparisons) do
7
+ let(:first_period_rows) do
8
+ MultiJson.load('[{
9
+ "ga:pageviews_rank": 1,
10
+ "ga:source": "google",
11
+ "ga:pageviews_pct_total": "0.743499",
12
+ "ga:pageviews_rank_change": 0,
13
+ "ga:pageviews": 3374,
14
+ "ga:pageviews_change": "0.139597"
15
+ },
16
+ {
17
+ "ga:pageviews_rank": 2,
18
+ "ga:source": "forbes.com",
19
+ "ga:pageviews_pct_total": "0.125606",
20
+ "ga:pageviews_rank_change": 7,
21
+ "ga:pageviews": 570,
22
+ "ga:pageviews_change": "0.994737"
23
+ }]')
24
+ end
25
+
26
+ let(:second_period_rows) do
27
+ MultiJson.load('[{
28
+ "ga:pageviews_rank": 1,
29
+ "ga:pageviews": 2903,
30
+ "ga:source": "google",
31
+ "ga:pageviews_pct_total": "0.748775"
32
+ },
33
+ {
34
+ "ga:pageviews_rank": 2,
35
+ "ga:pageviews": 100,
36
+ "ga:source": "bing",
37
+ "ga:pageviews_pct_total": "0.025793"
38
+ }]')
39
+ end
40
+
41
+ let(:first_period) do
42
+ Nucleo::Models::MetricPeriod.new('metric' => 'ga:pageviews', 'dimension' => 'ga:source', 'period_name' => 'current', 'rows' => first_period_rows)
43
+ end
44
+
45
+ let(:second_period) do
46
+ Nucleo::Models::MetricPeriod.new('metric' => 'ga:pageviews', 'dimension' => 'ga:source', 'period_name' => 'prior', 'rows' => second_period_rows)
47
+ end
48
+
49
+ subject { described_class.new(first_period, second_period) }
50
+
51
+ context "with valid values" do
52
+ it "returns a unique set of comparisons" do
53
+ expected = 3
54
+ expect(subject.count).to eq(expected)
55
+ end
56
+
57
+ end
58
+ end