runoff 0.3.3 → 1.0.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.
- checksums.yaml +4 -4
- data/.gitignore +18 -17
- data/Gemfile +4 -4
- data/LICENSE.txt +21 -21
- data/README.md +41 -40
- data/Rakefile +7 -7
- data/bin/runoff +58 -34
- data/lib/runoff/commands/all.rb +22 -36
- data/lib/runoff/commands/command.rb +18 -84
- data/lib/runoff/commands/some.rb +38 -0
- data/lib/runoff/file_writer.rb +84 -53
- data/lib/runoff/location.rb +118 -79
- data/lib/runoff/skype_data_format.rb +128 -104
- data/lib/runoff/version.rb +3 -3
- data/lib/runoff.rb +7 -10
- data/runoff.gemspec +27 -26
- data/test/skype_data_format_test.rb +57 -70
- metadata +29 -28
- data/lib/runoff/commands/chat.rb +0 -37
- data/lib/runoff/composition.rb +0 -105
- data/test/all_test.rb +0 -37
- data/test/chat_test.rb +0 -11
- data/test/command_test.rb +0 -41
- data/test/composition_test.rb +0 -58
- data/test/file_writer_test.rb +0 -90
- data/test/location_test.rb +0 -29
data/lib/runoff/location.rb
CHANGED
@@ -1,79 +1,118 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
# Public:
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
# # =>
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
# Returns a
|
70
|
-
def self.
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
end
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Runoff
|
4
|
+
# Contains class methods for finding out the appropriate file paths.
|
5
|
+
#
|
6
|
+
# Examples
|
7
|
+
#
|
8
|
+
# Location::default_skype_data_location skype_username
|
9
|
+
# # => /home/user/.Skype/skype_username/main.db
|
10
|
+
class Location
|
11
|
+
# Public: Gets a path to the Skype's main.db file.
|
12
|
+
#
|
13
|
+
# username - A String containing Skype username
|
14
|
+
# options - A hash containing command-line options passed to the command.
|
15
|
+
# If the username is empty, then the hash must contain :from key.
|
16
|
+
#
|
17
|
+
# Examples
|
18
|
+
#
|
19
|
+
# get_database_path('john_doe', {})
|
20
|
+
# # => Path to the default Skype database location depending on the operating system.
|
21
|
+
#
|
22
|
+
# get_database_path('', { from: '~/Desktop/main.db' })
|
23
|
+
# # => '~/Desktop/main.db'
|
24
|
+
#
|
25
|
+
# Returns a String
|
26
|
+
def self.get_database_path(username, options)
|
27
|
+
if options.from
|
28
|
+
options.from
|
29
|
+
else
|
30
|
+
self.default_skype_data_location username
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Public: Composes the default Skype database location depending on the operating system.
|
35
|
+
#
|
36
|
+
# skype_username - A String that contains a username of the Skype account,
|
37
|
+
# which database we want to access.
|
38
|
+
#
|
39
|
+
# Examples
|
40
|
+
#
|
41
|
+
# On Linux:
|
42
|
+
# default_skype_data_location skype_username
|
43
|
+
# # => /home/user/.Skype/skype_username/mai.db
|
44
|
+
#
|
45
|
+
# On Windows:
|
46
|
+
# default_skype_data_location skype_username
|
47
|
+
# # => /Users/user/AppData/Roaming/Skype/skype_username/main.db
|
48
|
+
#
|
49
|
+
# Returns a String that contains the path to the Skype database file.
|
50
|
+
def self.default_skype_data_location(skype_username)
|
51
|
+
case RbConfig::CONFIG['host_os']
|
52
|
+
when /mingw/
|
53
|
+
if File.exist?("#{ENV['APPDATA']}\\Skype")
|
54
|
+
format_windows_path "#{ENV['APPDATA']}\\Skype\\#{skype_username}\\main.db"
|
55
|
+
else
|
56
|
+
format_windows_path self.get_default_skype_data_location_on_windows_8(skype_username)
|
57
|
+
end
|
58
|
+
when /linux/
|
59
|
+
"#{ENV['HOME']}/.Skype/#{skype_username}/main.db"
|
60
|
+
else
|
61
|
+
"#{ENV['HOME']}/Library/Application Support/Skype/#{skype_username}/main.db"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Public: Composes a path where the exported files must be saved.
|
66
|
+
#
|
67
|
+
# options - an object with command line options passed to the runoff executable.
|
68
|
+
#
|
69
|
+
# Returns a string with a directory path.
|
70
|
+
def self.get_export_path(options)
|
71
|
+
path = options.destination || "#{ENV['HOME']}"
|
72
|
+
path = "#{path}/skype_chat_history"
|
73
|
+
|
74
|
+
unless File.exist?(path)
|
75
|
+
FileUtils::mkdir_p path
|
76
|
+
end
|
77
|
+
|
78
|
+
path
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
# Internal: Replaces backslashes with forward slashes and removes drive letter.
|
84
|
+
#
|
85
|
+
# path - String containing a directory path.
|
86
|
+
#
|
87
|
+
# Examples
|
88
|
+
#
|
89
|
+
# format_windows_path 'C:\Users\username\AppData\Roaming\Skype\skype_username\main.db'
|
90
|
+
# # => /Users/username/AppData/ROaming/Skype/skype_username/main.db
|
91
|
+
#
|
92
|
+
# Returns a String with modified directory path.
|
93
|
+
def self.format_windows_path(path)
|
94
|
+
path = path.gsub(/\\/, '/')
|
95
|
+
path.gsub(/^[a-zA-Z]:/, '')
|
96
|
+
end
|
97
|
+
|
98
|
+
# Internal: Composes the default Skype database location for the Windows 8 operating system.
|
99
|
+
#
|
100
|
+
# skype_username - A String that contains a username of the Skype account,
|
101
|
+
# which database we want to access.
|
102
|
+
#
|
103
|
+
# Examples
|
104
|
+
#
|
105
|
+
# get_default_skype_data_location_on_windows_8 skype_username
|
106
|
+
# # => C:/Users/user/AppData/Local/Packages/Microsoft.SkypeApp_sakjhds8asd/LocalState/skype_username/main.db
|
107
|
+
#
|
108
|
+
# Returns a String that contains the path to the Skype database file.
|
109
|
+
def self.get_default_skype_data_location_on_windows_8(skype_username)
|
110
|
+
location = "#{ENV['HOME']}/AppData/Local/Packages"
|
111
|
+
skype_folder = Dir["#{location}/Microsoft.SkypeApp*"].first
|
112
|
+
|
113
|
+
raise IOError.new "The default Skype directory doesn't exist." unless skype_folder
|
114
|
+
|
115
|
+
"#{skype_folder}/LocalState/#{skype_username}/main.db"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -1,104 +1,128 @@
|
|
1
|
-
module Runoff
|
2
|
-
#
|
3
|
-
class SkypeDataFormat
|
4
|
-
#Public:
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
#
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
#
|
90
|
-
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
94
|
-
#
|
95
|
-
#
|
96
|
-
# # =>
|
97
|
-
#
|
98
|
-
# Returns a string
|
99
|
-
def
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
1
|
+
module Runoff
|
2
|
+
# Defines methods to hide the specific format that is used in the Skype database.
|
3
|
+
class SkypeDataFormat
|
4
|
+
# Public: Defines what kind of information can be queried from the database.
|
5
|
+
#
|
6
|
+
# Example
|
7
|
+
#
|
8
|
+
# get_schema do |table, columns|
|
9
|
+
# # SELSECT *columns FROM table
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# get_schema
|
13
|
+
# # => { table: :Messages, columns: [:chatname, :timestamp, :from_dispname, :body_xml] }
|
14
|
+
#
|
15
|
+
# Returns a hash with keys "table" and "columns" if no block is given.
|
16
|
+
def get_schema
|
17
|
+
if block_given?
|
18
|
+
yield :Messages, [:chatname, :timestamp, :from_dispname, :body_xml]
|
19
|
+
else
|
20
|
+
return {
|
21
|
+
table: :Messages,
|
22
|
+
columns: [:chatname, :timestamp, :from_dispname, :body_xml]
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Public: Provides a filename and the data that should be written to the file.
|
28
|
+
#
|
29
|
+
# fields - an array representing a single entry in the database.
|
30
|
+
#
|
31
|
+
# Examples
|
32
|
+
#
|
33
|
+
# build_entry {
|
34
|
+
# chatname: "#john/$doe;1243435",
|
35
|
+
# from_dispname: "John",
|
36
|
+
# body_xml: "Lorem ipsum",
|
37
|
+
# timestamp: 12435463
|
38
|
+
# } # => { filename: john-doe.txt, content: "[2013-12-27 12:23:43] John: Lorem ipsum" }
|
39
|
+
#
|
40
|
+
# Returns a hash with "filename" and "content" keys.
|
41
|
+
def build_entry(fields)
|
42
|
+
chatname = fields[:chatname]
|
43
|
+
username = fields[:from_dispname]
|
44
|
+
message = parse_xml fields[:body_xml]
|
45
|
+
datetime = Time.at(fields[:timestamp]).strftime "%Y-%m-%d %H:%M:%S"
|
46
|
+
|
47
|
+
{
|
48
|
+
filename: get_filename(chatname),
|
49
|
+
content: "[#{datetime}] #{username}: #{message}\n"
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
# Public: Parse a into a human readable format.
|
54
|
+
#
|
55
|
+
# chatname - a string that must be normalized.
|
56
|
+
#
|
57
|
+
# Examples
|
58
|
+
#
|
59
|
+
# normalize "#john/$doe;2354657"
|
60
|
+
# # => john-doe
|
61
|
+
#
|
62
|
+
# Returns a string without unnecessary characters.
|
63
|
+
def normalize(chatname)
|
64
|
+
pattern = /^#(.+)\/\$(.+)?;.*$/
|
65
|
+
initiator, respondent = chatname.match(pattern).captures
|
66
|
+
|
67
|
+
"#{initiator}-#{respondent}".gsub(/(^-+|-+$)/, '')
|
68
|
+
end
|
69
|
+
|
70
|
+
# Public: Converts a string that is similar to the chat title stored
|
71
|
+
# in the Skype database.
|
72
|
+
#
|
73
|
+
# dispname - a string that is displayed to the user as a chat title.
|
74
|
+
#
|
75
|
+
# Examples
|
76
|
+
#
|
77
|
+
# denormalize "john-doe"
|
78
|
+
# # => "#john/$doe;"
|
79
|
+
#
|
80
|
+
# Returns a string that can be used to query Skype database.
|
81
|
+
def denormalize(dispname)
|
82
|
+
parts = dispname.split '-'
|
83
|
+
|
84
|
+
parts.count == 2 ? "##{parts[0]}/$#{parts[1]};" : "##{parts[0]}/$;"
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
# Internal: Parses a string into a valid file name.
|
90
|
+
#
|
91
|
+
# chatname - a string that must be converted into a valid filename.
|
92
|
+
#
|
93
|
+
# Examples
|
94
|
+
#
|
95
|
+
# get_filename "#john/$doe;2354657"
|
96
|
+
# # => john-doe.txt
|
97
|
+
#
|
98
|
+
# Returns a string that can be used as a file name.
|
99
|
+
def get_filename(chatname)
|
100
|
+
normalize(chatname) + ".txt"
|
101
|
+
end
|
102
|
+
|
103
|
+
# Internal: removes unnecessary XML code from the message.
|
104
|
+
#
|
105
|
+
# message - a string to parse
|
106
|
+
#
|
107
|
+
# Examples
|
108
|
+
#
|
109
|
+
# parse_xml "<ss type="smile">:)</ss>"
|
110
|
+
# # => ":)"
|
111
|
+
#
|
112
|
+
# Returns an XML-free string.
|
113
|
+
def parse_xml(message)
|
114
|
+
if message
|
115
|
+
message = message.gsub /<ss type=".*">/, ''
|
116
|
+
message = message.gsub /<\/ss>/, ''
|
117
|
+
message = message.gsub /<a href=".*">/, ''
|
118
|
+
message = message.gsub /<\/a>/, ''
|
119
|
+
message = message.gsub /'/, "'"
|
120
|
+
message = message.gsub /</, '<'
|
121
|
+
message = message.gsub />/, '>'
|
122
|
+
message = message.gsub /"/, '"'
|
123
|
+
end
|
124
|
+
|
125
|
+
message
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/lib/runoff/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module Runoff
|
2
|
-
VERSION = '0.
|
3
|
-
end
|
1
|
+
module Runoff
|
2
|
+
VERSION = '1.0.0'
|
3
|
+
end
|
data/lib/runoff.rb
CHANGED
@@ -1,10 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require "runoff/commands/command"
|
9
|
-
require "runoff/commands/all"
|
10
|
-
require "runoff/commands/chat"
|
1
|
+
require 'runoff/version'
|
2
|
+
require 'runoff/location'
|
3
|
+
require 'runoff/skype_data_format'
|
4
|
+
require 'runoff/file_writer'
|
5
|
+
require 'runoff/commands/command'
|
6
|
+
require 'runoff/commands/all'
|
7
|
+
require 'runoff/commands/some'
|
data/runoff.gemspec
CHANGED
@@ -1,26 +1,27 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
|
5
|
-
require 'runoff/version'
|
6
|
-
|
7
|
-
Gem::Specification.new do |gem|
|
8
|
-
gem.name = "runoff"
|
9
|
-
gem.version = Runoff::VERSION
|
10
|
-
gem.authors = ["Aigars Dzerviniks"]
|
11
|
-
gem.email = ["dzerviniks.aigars@outlook.com"]
|
12
|
-
gem.description = %q{runoff provides functionality to export all the Skype chat history or only specified chats from the Skype SQLite database file to text files}
|
13
|
-
gem.summary = %q{Tool to export Skype chat history from the SQLite database to text files}
|
14
|
-
gem.homepage = 'https://github.com/
|
15
|
-
gem.license = 'MIT'
|
16
|
-
|
17
|
-
gem.files = `git ls-files`.split($/)
|
18
|
-
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
19
|
-
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
20
|
-
gem.require_paths = ["lib"]
|
21
|
-
|
22
|
-
gem.add_dependency 'commander'
|
23
|
-
gem.add_dependency 'sequel'
|
24
|
-
gem.add_dependency 'rubyzip'
|
25
|
-
gem.add_dependency 'sqlite3'
|
26
|
-
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
require 'runoff/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |gem|
|
8
|
+
gem.name = "runoff"
|
9
|
+
gem.version = Runoff::VERSION
|
10
|
+
gem.authors = ["Aigars Dzerviniks"]
|
11
|
+
gem.email = ["dzerviniks.aigars@outlook.com"]
|
12
|
+
gem.description = %q{runoff provides functionality to export all the Skype chat history or only specified chats from the Skype SQLite database file to text files}
|
13
|
+
gem.summary = %q{Tool to export Skype chat history from the SQLite database to text files}
|
14
|
+
gem.homepage = 'https://github.com/aigarsdz/runoff'
|
15
|
+
gem.license = 'MIT'
|
16
|
+
|
17
|
+
gem.files = `git ls-files`.split($/)
|
18
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
19
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
20
|
+
gem.require_paths = ["lib"]
|
21
|
+
|
22
|
+
gem.add_dependency 'commander'
|
23
|
+
gem.add_dependency 'sequel'
|
24
|
+
gem.add_dependency 'rubyzip'
|
25
|
+
gem.add_dependency 'sqlite3'
|
26
|
+
gem.add_dependency 'colorize'
|
27
|
+
end
|
@@ -1,71 +1,58 @@
|
|
1
|
-
require 'minitest/autorun'
|
2
|
-
require '
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
def test_must_return_a_string_without_skype_emotion_xml_tags
|
59
|
-
string = 'Some text <ss type="laugh">:D</ss>'
|
60
|
-
clean_string = @format.send :parse_body_xml, string
|
61
|
-
|
62
|
-
assert_equal 'Some text :D', clean_string
|
63
|
-
end
|
64
|
-
|
65
|
-
def test_must_remove_all_starting_and_ending_dashes_from_a_string
|
66
|
-
string = '---example--'
|
67
|
-
valid_name = @format.send :trim_dashes, string
|
68
|
-
|
69
|
-
assert_equal 'example', valid_name
|
70
|
-
end
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'runoff'
|
3
|
+
|
4
|
+
describe Runoff::SkypeDataFormat do
|
5
|
+
before do
|
6
|
+
@format = Runoff::SkypeDataFormat.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it "must return a schema of the necessary data" do
|
10
|
+
expected = { table: :Messages, columns: [:chatname, :timestamp, :from_dispname, :body_xml] }
|
11
|
+
|
12
|
+
@format.get_schema.must_equal expected
|
13
|
+
end
|
14
|
+
|
15
|
+
it "must yield a schema of the necessary data to a block" do
|
16
|
+
@format.get_schema do |table, columns|
|
17
|
+
table.must_equal :Messages
|
18
|
+
columns.must_equal [:chatname, :timestamp, :from_dispname, :body_xml]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "must return a hash with 'filename' and 'content' keys based on the input data" do
|
23
|
+
fields = {
|
24
|
+
chatname: "#john/$doe;1243435",
|
25
|
+
from_dispname: "John",
|
26
|
+
body_xml: "Lorem ipsum",
|
27
|
+
timestamp: 1387756800
|
28
|
+
}
|
29
|
+
|
30
|
+
expected = { filename: "john-doe.txt", content: "[2013-12-23 02:00:00] John: Lorem ipsum\n" }
|
31
|
+
|
32
|
+
@format.build_entry(fields).must_equal expected
|
33
|
+
end
|
34
|
+
|
35
|
+
it "must normalize a Skype specific chat title into a human readable string" do
|
36
|
+
@format.normalize('#john/$doe;2354657').must_equal 'john-doe'
|
37
|
+
end
|
38
|
+
|
39
|
+
it "must normalize a Skype specific chat title into a human readable string even in case of invalid title" do
|
40
|
+
@format.normalize('#john/$;2354657').must_equal 'john'
|
41
|
+
end
|
42
|
+
|
43
|
+
it "must parse a Skype specific chat title into a valid file name" do
|
44
|
+
@format.send(:get_filename, '#john/$doe;2354657').must_equal 'john-doe.txt'
|
45
|
+
end
|
46
|
+
|
47
|
+
it "must parse a Skype specific chat title into a valid file name even in case of invalid title" do
|
48
|
+
@format.send(:get_filename, '#john/$;2354657').must_equal 'john.txt'
|
49
|
+
end
|
50
|
+
|
51
|
+
it "must denormalize a human readable chat title into a string that can be used in a database query" do
|
52
|
+
@format.denormalize('john-doe').must_equal '#john/$doe;'
|
53
|
+
end
|
54
|
+
|
55
|
+
it "must denormalize a human readable, invalid chat title into a string that can be used in a database query" do
|
56
|
+
@format.denormalize('john').must_equal '#john/$;'
|
57
|
+
end
|
71
58
|
end
|