icalendar 1.5.4 → 2.0.0.beta.1
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.
- checksums.yaml +7 -0
- data/.gitignore +1 -1
- data/.rspec +2 -0
- data/.travis.yml +1 -2
- data/History.txt +2 -7
- data/README.md +82 -107
- data/Rakefile +6 -7
- data/icalendar.gemspec +10 -9
- data/lib/icalendar.rb +17 -33
- data/lib/icalendar/alarm.rb +35 -0
- data/lib/icalendar/calendar.rb +17 -100
- data/lib/icalendar/component.rb +41 -403
- data/lib/icalendar/event.rb +51 -0
- data/lib/icalendar/freebusy.rb +27 -0
- data/lib/icalendar/has_components.rb +83 -0
- data/lib/icalendar/has_properties.rb +156 -0
- data/lib/icalendar/journal.rb +39 -0
- data/lib/icalendar/parser.rb +75 -403
- data/lib/icalendar/timezone.rb +53 -0
- data/lib/icalendar/todo.rb +52 -0
- data/lib/icalendar/tzinfo.rb +30 -30
- data/lib/icalendar/value.rb +80 -0
- data/lib/icalendar/values/array.rb +43 -0
- data/lib/icalendar/values/binary.rb +31 -0
- data/lib/icalendar/values/boolean.rb +17 -0
- data/lib/icalendar/values/cal_address.rb +8 -0
- data/lib/icalendar/values/date.rb +26 -0
- data/lib/icalendar/values/date_time.rb +34 -0
- data/lib/icalendar/values/duration.rb +48 -0
- data/lib/icalendar/values/float.rb +17 -0
- data/lib/icalendar/values/integer.rb +17 -0
- data/lib/icalendar/values/period.rb +46 -0
- data/lib/icalendar/values/recur.rb +63 -0
- data/lib/icalendar/values/text.rb +26 -0
- data/lib/icalendar/values/time.rb +34 -0
- data/lib/icalendar/values/time_with_zone.rb +31 -0
- data/lib/icalendar/values/uri.rb +19 -0
- data/lib/icalendar/values/utc_offset.rb +39 -0
- data/lib/icalendar/version.rb +5 -0
- data/spec/alarm_spec.rb +108 -0
- data/spec/calendar_spec.rb +167 -0
- data/spec/event_spec.rb +108 -0
- data/{test/fixtures/folding.ics → spec/fixtures/nondefault_values.ics} +2 -2
- data/{test → spec}/fixtures/single_event.ics +11 -14
- data/spec/fixtures/timezone.ics +35 -0
- data/spec/freebusy_spec.rb +7 -0
- data/spec/journal_spec.rb +7 -0
- data/spec/parser_spec.rb +26 -0
- data/spec/roundtrip_spec.rb +40 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/timezone_spec.rb +31 -0
- data/spec/todo_spec.rb +24 -0
- data/spec/tzinfo_spec.rb +85 -0
- data/spec/values/date_time_spec.rb +80 -0
- data/spec/values/duration_spec.rb +67 -0
- data/spec/values/period_spec.rb +47 -0
- data/spec/values/recur_spec.rb +47 -0
- data/spec/values/text_spec.rb +72 -0
- data/spec/values/utc_offset_spec.rb +41 -0
- metadata +129 -88
- data/GPL +0 -340
- data/examples/create_cal.rb +0 -45
- data/examples/parse_cal.rb +0 -20
- data/examples/single_event.ics +0 -18
- data/lib/hash_attrs.rb +0 -34
- data/lib/icalendar/base.rb +0 -47
- data/lib/icalendar/component/alarm.rb +0 -47
- data/lib/icalendar/component/event.rb +0 -131
- data/lib/icalendar/component/freebusy.rb +0 -38
- data/lib/icalendar/component/journal.rb +0 -60
- data/lib/icalendar/component/timezone.rb +0 -91
- data/lib/icalendar/component/todo.rb +0 -64
- data/lib/icalendar/conversions.rb +0 -107
- data/lib/icalendar/helpers.rb +0 -109
- data/lib/icalendar/parameter.rb +0 -33
- data/lib/icalendar/rrule.rb +0 -133
- data/lib/meta.rb +0 -32
- data/script/console +0 -10
- data/script/recur1.ics +0 -38
- data/script/tryit.rb +0 -13
- data/test/component/test_event.rb +0 -253
- data/test/component/test_timezone.rb +0 -74
- data/test/component/test_todo.rb +0 -31
- data/test/fixtures/life.ics +0 -46
- data/test/fixtures/nonstandard.ics +0 -25
- data/test/fixtures/simplecal.ics +0 -119
- data/test/interactive.rb +0 -17
- data/test/read_write.rb +0 -23
- data/test/test_calendar.rb +0 -167
- data/test/test_component.rb +0 -102
- data/test/test_conversions.rb +0 -104
- data/test/test_helper.rb +0 -7
- data/test/test_parameter.rb +0 -91
- data/test/test_parser.rb +0 -100
- data/test/test_tzinfo.rb +0 -83
- data/website/index.html +0 -70
- data/website/index.txt +0 -38
- data/website/javascripts/rounded_corners_lite.inc.js +0 -285
- data/website/stylesheets/screen.css +0 -159
- data/website/template.html.erb +0 -50
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start do
|
3
|
+
add_filter '/spec/'
|
4
|
+
end
|
5
|
+
|
6
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
7
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
8
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
9
|
+
# loaded once.
|
10
|
+
#
|
11
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
12
|
+
require 'timecop'
|
13
|
+
require 'icalendar'
|
14
|
+
|
15
|
+
RSpec.configure do |config|
|
16
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
17
|
+
config.run_all_when_everything_filtered = true
|
18
|
+
config.filter_run :focus
|
19
|
+
|
20
|
+
# Run specs in random order to surface order dependencies. If you find an
|
21
|
+
# order dependency and want to debug it, you can fix the order by providing
|
22
|
+
# the seed, which is printed after each run.
|
23
|
+
# --seed 1234
|
24
|
+
config.order = 'random'
|
25
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Icalendar::Timezone do
|
4
|
+
|
5
|
+
describe "valid?" do
|
6
|
+
subject { described_class.new.tap { |t| t.tzid = 'Eastern' } }
|
7
|
+
|
8
|
+
context 'with both standard and daylight components' do
|
9
|
+
before(:each) do
|
10
|
+
subject.daylight { |d| d.should_receive(:valid?).and_return true }
|
11
|
+
subject.standard { |s| s.should_receive(:valid?).and_return true }
|
12
|
+
end
|
13
|
+
|
14
|
+
it { should be_valid }
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'with only standard' do
|
18
|
+
before(:each) { subject.standard { |s| s.stub(:valid?).and_return true } }
|
19
|
+
it { should be_valid }
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'with only daylight' do
|
23
|
+
before(:each) { subject.daylight { |d| d.stub(:valid?).and_return true } }
|
24
|
+
it { should be_valid }
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'with neither standard or daylight' do
|
28
|
+
it { should_not be_valid }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/spec/todo_spec.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Icalendar::Todo do
|
4
|
+
|
5
|
+
describe '#dtstart' do
|
6
|
+
it 'is not normally required' do
|
7
|
+
subject.dtstart = nil
|
8
|
+
subject.should be_valid
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'with duration set' do
|
12
|
+
before(:each) { subject.duration = 'PT15M' }
|
13
|
+
|
14
|
+
it 'is invalid if not set' do
|
15
|
+
subject.should_not be_valid
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'is valid when set' do
|
19
|
+
subject.dtstart = Date.today
|
20
|
+
subject.should be_valid
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/spec/tzinfo_spec.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require_relative '../lib/icalendar/tzinfo'
|
3
|
+
|
4
|
+
describe 'TZInfo::Timezone' do
|
5
|
+
|
6
|
+
let(:tz) { TZInfo::Timezone.get 'Europe/Copenhagen' }
|
7
|
+
let(:date) { DateTime.new 1970 }
|
8
|
+
subject { tz.ical_timezone date }
|
9
|
+
|
10
|
+
describe 'daylight offset' do
|
11
|
+
specify { expect(subject.daylights.first.tzoffsetto.value_ical).to eq "+0200" }
|
12
|
+
specify { expect(subject.daylights.first.tzoffsetfrom.value_ical).to eq "+0100" }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'standard offset' do
|
16
|
+
specify { expect(subject.standards.first.tzoffsetto.value_ical).to eq "+0100" }
|
17
|
+
specify { expect(subject.standards.first.tzoffsetfrom.value_ical).to eq "+0200" }
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'no end transition' do
|
21
|
+
let(:tz) { TZInfo::Timezone.get 'America/Cayman' }
|
22
|
+
let(:date) { DateTime.now }
|
23
|
+
|
24
|
+
it 'only creates a standard component' do
|
25
|
+
expect(subject.to_ical).to eq <<-EXPECTED.gsub "\n", "\r\n"
|
26
|
+
BEGIN:VTIMEZONE
|
27
|
+
TZID:America/Cayman
|
28
|
+
BEGIN:STANDARD
|
29
|
+
DTSTART:19120201T000711
|
30
|
+
TZOFFSETFROM:-0652
|
31
|
+
TZOFFSETTO:-0500
|
32
|
+
TZNAME:EST
|
33
|
+
END:STANDARD
|
34
|
+
END:VTIMEZONE
|
35
|
+
EXPECTED
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'no transition' do
|
40
|
+
let(:tz) { TZInfo::Timezone.get 'UTC' }
|
41
|
+
let(:date) { DateTime.now }
|
42
|
+
|
43
|
+
it 'creates a standard component with equal offsets' do
|
44
|
+
expect(subject.to_ical).to eq <<-EXPECTED.gsub "\n", "\r\n"
|
45
|
+
BEGIN:VTIMEZONE
|
46
|
+
TZID:UTC
|
47
|
+
BEGIN:STANDARD
|
48
|
+
DTSTART:19700101T000000
|
49
|
+
TZOFFSETFROM:+0000
|
50
|
+
TZOFFSETTO:+0000
|
51
|
+
TZNAME:UTC
|
52
|
+
END:STANDARD
|
53
|
+
END:VTIMEZONE
|
54
|
+
EXPECTED
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe 'dst transition' do
|
59
|
+
subject { TZInfo::Timezone.get 'America/Los_Angeles' }
|
60
|
+
let(:now) { subject.now }
|
61
|
+
# freeze in DST transition in America/Los_Angeles
|
62
|
+
before(:each) { Timecop.freeze DateTime.new(2013, 11, 03, 1, 30, 0, '-08:00') }
|
63
|
+
after(:each) { Timecop.return }
|
64
|
+
|
65
|
+
specify { expect { subject.ical_timezone now, nil }.to raise_error TZInfo::AmbiguousTime }
|
66
|
+
specify { expect { subject.ical_timezone now, true }.not_to raise_error }
|
67
|
+
specify { expect { subject.ical_timezone now, false }.not_to raise_error }
|
68
|
+
|
69
|
+
context 'TZInfo::Timezone.default_dst = nil' do
|
70
|
+
before(:each) { TZInfo::Timezone.default_dst = nil }
|
71
|
+
specify { expect { subject.ical_timezone now }.to raise_error TZInfo::AmbiguousTime }
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'TZInfo::Timezone.default_dst = true' do
|
75
|
+
before(:each) { TZInfo::Timezone.default_dst = true }
|
76
|
+
specify { expect { subject.ical_timezone now }.not_to raise_error }
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'TZInfo::Timezone.default_dst = false' do
|
80
|
+
before(:each) { TZInfo::Timezone.default_dst = false }
|
81
|
+
specify { expect { subject.ical_timezone now }.not_to raise_error }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Icalendar::Values::DateTime do
|
4
|
+
|
5
|
+
subject { described_class.new value, params }
|
6
|
+
let(:value) { '20140209T194355Z' }
|
7
|
+
let(:params) { {} }
|
8
|
+
|
9
|
+
# not sure how to automatically test both sides of this.
|
10
|
+
# For now - relying on commenting out dev dependency in gemspec
|
11
|
+
# AND uninstalling gem manually
|
12
|
+
if defined? ActiveSupport
|
13
|
+
|
14
|
+
context 'with ActiveSupport' do
|
15
|
+
it 'parses a string to a ActiveSupport::TimeWithZone instance' do
|
16
|
+
expect(subject.value).to be_a_kind_of ActiveSupport::TimeWithZone
|
17
|
+
expect(subject.value_ical).to eq value
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'local time' do
|
21
|
+
let(:value) { '20140209T160652' }
|
22
|
+
let(:params) { {'tzid' => 'America/Denver'} }
|
23
|
+
|
24
|
+
it 'parses the value as local time' do
|
25
|
+
expect(subject.value.hour).to eq 16
|
26
|
+
expect(subject.value.utc_offset).to eq -25200
|
27
|
+
expect(subject.value.utc.hour).to eq 23
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
else
|
33
|
+
|
34
|
+
context 'without ActiveSupport' do
|
35
|
+
it 'parses a string to a DateTime instance' do
|
36
|
+
expect(subject.value).to be_a_kind_of ::DateTime
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'local time' do
|
40
|
+
let(:value) { '20140209T160652' }
|
41
|
+
let(:params) { {'tzid' => 'America/Denver'} }
|
42
|
+
|
43
|
+
it 'parses the value as local time' do
|
44
|
+
expect(subject.value.hour).to eq 16
|
45
|
+
# TODO better offset support without ActiveSupport
|
46
|
+
#expect(subject.offset).to eq Rational(-7, 24)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
context 'common tests' do
|
55
|
+
it 'does not add any tzid parameter to output' do
|
56
|
+
expect(subject.to_ical described_class).to eq ":#{value}"
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'local time' do
|
60
|
+
let(:value) { '20140209T160652' }
|
61
|
+
let(:params) { {'tzid' => 'America/Denver'} }
|
62
|
+
|
63
|
+
it 'keeps value and tzid as localtime on output' do
|
64
|
+
expect(subject.to_ical described_class).to eq ";TZID=America/Denver:#{value}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'floating local time' do
|
69
|
+
let(:value) { '20140209T162845' }
|
70
|
+
|
71
|
+
it 'keeps the value as a DateTime' do
|
72
|
+
expect(subject.value).to be_a_kind_of ::DateTime
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'does not append a Z on output' do
|
76
|
+
expect(subject.to_ical described_class).to eq ":#{value}"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Icalendar::Values::Duration do
|
4
|
+
|
5
|
+
subject { described_class.new value }
|
6
|
+
|
7
|
+
describe '#past?' do
|
8
|
+
context 'positive explicit' do
|
9
|
+
let(:value) { '+P15M' }
|
10
|
+
specify { expect(subject.past?).to be_false }
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'positive implicit' do
|
14
|
+
let(:value) { 'P15M' }
|
15
|
+
specify { expect(subject.past?).to be_false }
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'negative' do
|
19
|
+
let(:value) { '-P15M' }
|
20
|
+
specify { expect(subject.past?).to be_true }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#days' do
|
25
|
+
context 'days given' do
|
26
|
+
let(:value) { 'P5DT3H' }
|
27
|
+
specify { expect(subject.days).to eq 5 }
|
28
|
+
end
|
29
|
+
context 'no days given' do
|
30
|
+
let(:value) { 'P5W' }
|
31
|
+
specify { expect(subject.days).to eq 0 }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#weeks' do
|
36
|
+
let(:value) { 'P3W' }
|
37
|
+
specify { expect(subject.weeks).to eq 3 }
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#hours' do
|
41
|
+
let(:value) { 'PT6H' }
|
42
|
+
specify { expect(subject.hours).to eq 6 }
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#minutes' do
|
46
|
+
let(:value) { 'P2DT5H45M12S' }
|
47
|
+
specify { expect(subject.minutes).to eq 45 }
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#seconds' do
|
51
|
+
let(:value) { '-PT5M30S' }
|
52
|
+
specify { expect(subject.seconds).to eq 30 }
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#value_ical' do
|
56
|
+
let(:value) { 'P2DT4H' }
|
57
|
+
specify { expect(subject.value_ical).to eq value }
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#days=' do
|
61
|
+
let(:value) { 'P3D' }
|
62
|
+
it 'can set the number of days' do
|
63
|
+
subject.days = 4
|
64
|
+
expect(subject.value_ical).to eq 'P4D'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
describe Icalendar::Values::Period do
|
5
|
+
|
6
|
+
subject { described_class.new value }
|
7
|
+
|
8
|
+
context 'date-time/date-time' do
|
9
|
+
let(:value) { '19830507T000600Z/20140128T201400Z' }
|
10
|
+
|
11
|
+
describe '#value_ical' do
|
12
|
+
specify { expect(subject.value_ical).to eq value }
|
13
|
+
end
|
14
|
+
describe '#period_start' do
|
15
|
+
specify { expect(subject.period_start).to eq DateTime.new(1983, 5, 7, 0, 6) }
|
16
|
+
end
|
17
|
+
describe '#duration' do
|
18
|
+
specify { expect(subject.duration).to be_nil }
|
19
|
+
end
|
20
|
+
describe '#explicit_end' do
|
21
|
+
specify { expect(subject.explicit_end).to eq DateTime.new(2014, 01, 28, 20, 14) }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'date-time/duration' do
|
26
|
+
let(:value) { '19830507T000600Z/P1604W' }
|
27
|
+
let(:expected_duration) { OpenStruct.new past: false, weeks: 1604, days: 0, hours: 0, minutes: 0, seconds: 0 }
|
28
|
+
|
29
|
+
describe '#value_ical' do
|
30
|
+
specify { expect(subject.value_ical).to eq value }
|
31
|
+
|
32
|
+
it 'allows updating duration' do
|
33
|
+
subject.duration = 'PT30M'
|
34
|
+
expect(subject.value_ical).to eq '19830507T000600Z/PT30M'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
describe '#period_start' do
|
38
|
+
specify { expect(subject.period_start).to eq DateTime.new(1983, 5, 7, 0, 6) }
|
39
|
+
end
|
40
|
+
describe '#duration' do
|
41
|
+
specify { expect(subject.duration).to eq expected_duration }
|
42
|
+
end
|
43
|
+
describe '#explicit_end' do
|
44
|
+
specify { expect(subject.explicit_end).to eq nil }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Icalendar::Values::Recur do
|
4
|
+
|
5
|
+
subject { described_class.new value }
|
6
|
+
let(:value) { 'FREQ=DAILY' }
|
7
|
+
|
8
|
+
describe 'parsing' do
|
9
|
+
context 'multiple bydays' do
|
10
|
+
let(:value) { 'FREQ=WEEKLY;COUNT=4;BYDAY=MO,WE,FR' }
|
11
|
+
|
12
|
+
specify { expect(subject.frequency).to eq 'WEEKLY' }
|
13
|
+
specify { expect(subject.count).to eq 4 }
|
14
|
+
specify { expect(subject.by_day).to eq %w(MO WE FR) }
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'single byday' do
|
18
|
+
let(:value) { 'FREQ=YEARLY;BYDAY=2SU;BYMONTH=3' }
|
19
|
+
|
20
|
+
specify { expect(subject.frequency).to eq 'YEARLY' }
|
21
|
+
specify { expect(subject.by_day).to eq %w(2SU) }
|
22
|
+
specify { expect(subject.by_month).to eq [3] }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#valid?' do
|
27
|
+
it 'requires frequency' do
|
28
|
+
expect(subject.valid?).to be_true
|
29
|
+
subject.frequency = nil
|
30
|
+
expect(subject.valid?).to be_false
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'cannot have both until and count' do
|
34
|
+
subject.until = '20140201'
|
35
|
+
subject.count = 4
|
36
|
+
expect(subject.valid?).to be_false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#value_ical' do
|
41
|
+
let(:value) { 'FREQ=DAILY;BYYEARDAY=1,34,56,240;BYDAY=SU,SA' }
|
42
|
+
|
43
|
+
it 'outputs in spec order' do
|
44
|
+
expect(subject.value_ical).to eq 'FREQ=DAILY;BYDAY=SU,SA;BYYEARDAY=1,34,56,240'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Icalendar::Values::Text do
|
4
|
+
|
5
|
+
subject { described_class.new value }
|
6
|
+
let(:unescaped) { "This \\ that, semi; colons\r\nAnother line: \"why not?\"" }
|
7
|
+
let(:escaped) { 'This \\\\ that\, semi\; colons\nAnother line: "why not?"' }
|
8
|
+
|
9
|
+
describe '#value_ical' do
|
10
|
+
let(:value) { unescaped }
|
11
|
+
it 'escapes \ , ; NL' do
|
12
|
+
expect(subject.value_ical).to eq escaped
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'unescapes in initializer' do
|
17
|
+
context 'given escaped version' do
|
18
|
+
let(:unescaped_no_cr) { unescaped.gsub "\r", '' }
|
19
|
+
let(:value) { escaped }
|
20
|
+
it 'removes escaping' do
|
21
|
+
expect(subject.value).to eq unescaped_no_cr
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'given unescaped version' do
|
26
|
+
let(:value) { unescaped }
|
27
|
+
it 'does not try to double unescape' do
|
28
|
+
expect(subject.value).to eq unescaped
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'escapes parameter text properly' do
|
34
|
+
subject { described_class.new escaped, {'param' => param_value} }
|
35
|
+
context 'single value, no special characters' do
|
36
|
+
let(:param_value) { 'HelloWorld' }
|
37
|
+
it 'does not wrap param in double quotes' do
|
38
|
+
expect(subject.params_ical).to eq %(;PARAM=HelloWorld)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
context 'single value, special characters' do
|
42
|
+
let(:param_value) { 'Hello:World' }
|
43
|
+
it 'wraps param value in double quotes' do
|
44
|
+
expect(subject.params_ical).to eq %(;PARAM="Hello:World")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
context 'single value, double quotes' do
|
48
|
+
let(:param_value) { 'Hello "World"' }
|
49
|
+
it 'replaces double quotes with single' do
|
50
|
+
expect(subject.params_ical).to eq %(;PARAM=Hello 'World')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
context 'multiple values, no special characters' do
|
54
|
+
let(:param_value) { ['HelloWorld', 'GoodbyeMoon'] }
|
55
|
+
it 'joins with comma' do
|
56
|
+
expect(subject.params_ical).to eq %(;PARAM=HelloWorld,GoodbyeMoon)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
context 'multiple values, with special characters' do
|
60
|
+
let(:param_value) { ['Hello, World', 'GoodbyeMoon'] }
|
61
|
+
it 'quotes values with special characters, joins with comma' do
|
62
|
+
expect(subject.params_ical).to eq %(;PARAM="Hello, World",GoodbyeMoon)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
context 'multiple values, double quotes' do
|
66
|
+
let(:param_value) { ['Hello, "World"', 'GoodbyeMoon'] }
|
67
|
+
it 'replaces double quotes with single' do
|
68
|
+
expect(subject.params_ical).to eq %(;PARAM="Hello, 'World'",GoodbyeMoon)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|