weft-qda 0.9.6 → 0.9.8

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 (86) hide show
  1. data/lib/weft.rb +16 -1
  2. data/lib/weft/WEFT-VERSION-STRING.rb +1 -1
  3. data/lib/weft/application.rb +17 -74
  4. data/lib/weft/backend.rb +6 -32
  5. data/lib/weft/backend/sqlite.rb +222 -164
  6. data/lib/weft/backend/sqlite/category_tree.rb +52 -48
  7. data/lib/weft/backend/sqlite/database.rb +57 -0
  8. data/lib/weft/backend/sqlite/upgradeable.rb +7 -0
  9. data/lib/weft/broadcaster.rb +90 -0
  10. data/lib/weft/category.rb +139 -47
  11. data/lib/weft/codereview.rb +160 -0
  12. data/lib/weft/coding.rb +74 -23
  13. data/lib/weft/document.rb +23 -10
  14. data/lib/weft/exceptions.rb +10 -0
  15. data/lib/weft/filters.rb +47 -224
  16. data/lib/weft/filters/indexers.rb +137 -0
  17. data/lib/weft/filters/input.rb +118 -0
  18. data/lib/weft/filters/output.rb +101 -0
  19. data/lib/weft/filters/templates.rb +80 -0
  20. data/lib/weft/filters/win32backtick.rb +246 -0
  21. data/lib/weft/query.rb +169 -0
  22. data/lib/weft/wxgui.rb +349 -294
  23. data/lib/weft/wxgui/constants.rb +43 -0
  24. data/lib/weft/wxgui/controls.rb +6 -0
  25. data/lib/weft/wxgui/controls/category_dropdown.rb +192 -0
  26. data/lib/weft/wxgui/controls/category_tree.rb +314 -0
  27. data/lib/weft/wxgui/controls/document_list.rb +97 -0
  28. data/lib/weft/wxgui/controls/multitype_control.rb +37 -0
  29. data/lib/weft/wxgui/{inspectors → controls}/textcontrols.rb +235 -64
  30. data/lib/weft/wxgui/dialogs.rb +144 -41
  31. data/lib/weft/wxgui/error_handler.rb +116 -36
  32. data/lib/weft/wxgui/exceptions.rb +7 -0
  33. data/lib/weft/wxgui/inspectors.rb +61 -208
  34. data/lib/weft/wxgui/inspectors/category.rb +19 -16
  35. data/lib/weft/wxgui/inspectors/codereview.rb +90 -132
  36. data/lib/weft/wxgui/inspectors/document.rb +12 -8
  37. data/lib/weft/wxgui/inspectors/imagedocument.rb +56 -56
  38. data/lib/weft/wxgui/inspectors/query.rb +284 -0
  39. data/lib/weft/wxgui/inspectors/script.rb +147 -23
  40. data/lib/weft/wxgui/lang/en.rb +69 -0
  41. data/lib/weft/wxgui/sidebar.rb +90 -432
  42. data/lib/weft/wxgui/utilities.rb +70 -91
  43. data/lib/weft/wxgui/workarea.rb +150 -43
  44. data/share/icons/category.ico +0 -0
  45. data/share/icons/category.xpm +109 -0
  46. data/share/icons/codereview.ico +0 -0
  47. data/share/icons/codereview.xpm +54 -0
  48. data/share/icons/d_and_c.xpm +126 -0
  49. data/share/icons/document.ico +0 -0
  50. data/share/icons/document.xpm +70 -0
  51. data/share/icons/project.ico +0 -0
  52. data/share/icons/query.ico +0 -0
  53. data/share/icons/query.xpm +56 -0
  54. data/{lib/weft/wxgui → share/icons}/search.xpm +0 -0
  55. data/share/icons/weft.ico +0 -0
  56. data/share/icons/weft.xpm +62 -0
  57. data/share/icons/weft16.ico +0 -0
  58. data/share/icons/weft32.ico +0 -0
  59. data/share/templates/category_plain.html +18 -0
  60. data/share/templates/codereview_plain.html +18 -0
  61. data/share/templates/document_plain.html +13 -0
  62. data/share/templates/document_plain.txt +7 -0
  63. data/test/001-document.rb +55 -36
  64. data/test/002-category.rb +81 -6
  65. data/test/003-code.rb +8 -4
  66. data/test/004-application.rb +13 -34
  67. data/test/005-query_review.rb +139 -0
  68. data/test/006-filters.rb +54 -42
  69. data/test/007-output_filters.rb +113 -0
  70. data/test/009a-backend_sqlite_basic.rb +95 -24
  71. data/test/009b-backend_sqlite_complex.rb +43 -62
  72. data/test/009c_backend_sqlite_bench.rb +5 -10
  73. data/test/053-doc_inspector.rb +46 -0
  74. data/test/055-query_window.rb +50 -0
  75. data/test/all-tests.rb +1 -0
  76. data/test/test-common.rb +19 -0
  77. data/test/testdata/empty.qdp +0 -0
  78. data/test/testdata/simple with space.pdf +0 -0
  79. data/test/testdata/simple.pdf +0 -0
  80. data/weft-qda.rb +40 -7
  81. metadata +74 -14
  82. data/lib/weft/wxgui/category.xpm +0 -26
  83. data/lib/weft/wxgui/document.xpm +0 -25
  84. data/lib/weft/wxgui/inspectors/search.rb +0 -265
  85. data/lib/weft/wxgui/mondrian.xpm +0 -44
  86. data/lib/weft/wxgui/weft16.xpm +0 -31
@@ -0,0 +1,139 @@
1
+ require 'test-common'
2
+
3
+ require 'weft'
4
+ require 'test/unit'
5
+
6
+ class TestCodeReview < Test::Unit::TestCase
7
+ include QDA
8
+ def test_to_query()
9
+ cr = CodeReview.new()
10
+ assert_equal(0, cr.number_rows)
11
+ assert_equal(0, cr.number_cols)
12
+
13
+ cat1 = Category.new('foo')
14
+ cat1.code(1, 10, 40)
15
+ cat2 = Category.new('bar')
16
+ cat2.code(1, 70, 20)
17
+ cat3 = Category.new('baz')
18
+ cat3.code(1, 40, 40)
19
+ cat4 = Category.new('qux')
20
+ cat4.code(1, 100, 15)
21
+
22
+ cr.add_col( cat1 )
23
+ cr.add_col( cat2 )
24
+ cr.add_row( cat3 )
25
+ cr.add_row( cat4 )
26
+ # invalid
27
+ assert_nil( cr.to_query(nil, 2,2) )
28
+ # valid
29
+ assert_kind_of( Query, cr.to_query(nil, 0, 1) )
30
+ end
31
+
32
+ def test_basic
33
+ cr = CodeReview.new()
34
+ assert_equal(0, cr.number_rows)
35
+ assert_equal(0, cr.number_cols)
36
+
37
+ cat1 = Category.new('foo')
38
+ cat1.code(1, 10, 40)
39
+ cat2 = Category.new('bar')
40
+ cat2.code(1, 70, 20)
41
+ cat3 = Category.new('baz')
42
+ cat3.code(1, 40, 40)
43
+ cat4 = Category.new('qux')
44
+ cat4.code(1, 100, 15)
45
+
46
+ cr.add_col( cat1 )
47
+ cr.add_col( cat2 )
48
+ assert_equal(0, cr.number_rows)
49
+ assert_equal(2, cr.number_cols)
50
+
51
+ cr.add_row( cat3 )
52
+ cr.add_row( cat4 )
53
+ assert_equal(2, cr.number_rows)
54
+ assert_equal(2, cr.number_cols)
55
+
56
+
57
+ end
58
+ end
59
+
60
+
61
+ # for testing
62
+ class NullFunction < QDA::Query::Function
63
+ def initialize(token)
64
+ @token = token
65
+ end
66
+ def calculate()
67
+ QDA::CodingTable.new()
68
+ end
69
+ def to_s()
70
+ "(NULL-#{@token})"
71
+ end
72
+ end
73
+
74
+ class TestQuery < Test::Unit::TestCase
75
+ include QDA
76
+
77
+ def test_query
78
+ q = Query.new( NullFunction.new('FOO') )
79
+ assert_equal(1, q.num_functions)
80
+ assert_equal(0, q.num_expressions)
81
+ assert_equal(QDA::CodingTable.new(), q.calculate)
82
+ assert_kind_of(NullFunction, q.root)
83
+
84
+ q.add_expression( 'AND', NullFunction.new('BAR') )
85
+ assert_equal(2, q.num_functions)
86
+ assert_equal(1, q.num_expressions)
87
+ assert_equal(QDA::CodingTable.new(), q.calculate)
88
+ assert_kind_of(Query::AND, q.root)
89
+
90
+ q.add_expression( 'OR', NullFunction.new('BAZ') )
91
+ assert_equal(3, q.num_functions)
92
+ assert_equal(2, q.num_expressions)
93
+ assert_equal(QDA::CodingTable.new(), q.calculate)
94
+ assert_kind_of(Query::OR, q.root)
95
+ # a bad logical operator
96
+ assert_raises(ArgumentError) do
97
+ q.add_expression('UG', NullFunction.new('QUX'))
98
+ end
99
+
100
+ end
101
+
102
+
103
+
104
+ def test_or
105
+ cs_1 = CodingTable.new()
106
+ cs_2 = CodingTable.new()
107
+ cs_1.add( Code.new(3, 0, 4) )
108
+ cs_2.add( Code.new(3, 3, 5) )
109
+ expr = Query::AND.new(cs_1, cs_2)
110
+ result = expr.calculate()
111
+ assert_equal(1, result.num_of_docs)
112
+ assert_equal(1, result.num_of_chars)
113
+ assert_equal(1, result.num_of_passages)
114
+ end
115
+
116
+ def test_and_not
117
+ cs_1 = CodingTable.new()
118
+ cs_2 = CodingTable.new()
119
+ cs_1.add( Code.new(3, 0, 4) )
120
+ cs_2.add( Code.new(3, 3, 5) )
121
+ expr = Query::AND_NOT.new(cs_1, cs_2)
122
+ result = expr.calculate()
123
+ assert_equal(1, result.num_of_docs)
124
+ assert_equal(3, result.num_of_chars)
125
+ assert_equal(1, result.num_of_passages)
126
+ end
127
+
128
+ def test_or
129
+ cs_1 = CodingTable.new()
130
+ cs_2 = CodingTable.new()
131
+ cs_1.add( Code.new(3, 0, 4) )
132
+ cs_2.add( Code.new(3, 3, 5) )
133
+ expr = Query::OR.new(cs_1, cs_2)
134
+ result = expr.calculate()
135
+ assert_equal(1, result.num_of_docs)
136
+ assert_equal(8, result.num_of_chars)
137
+ assert_equal(1, result.num_of_passages)
138
+ end
139
+ end
@@ -1,31 +1,33 @@
1
- require 'english'
1
+ require 'test-common'
2
2
 
3
- $:.push('../lib/')
4
-
5
- require 'weft/application'
6
- require 'weft/backend'
7
- require 'weft/document'
8
- require 'weft/filters'
3
+ require 'weft'
9
4
 
10
5
  require 'test/unit'
11
6
 
12
7
  class TestFilter < Test::Unit::TestCase
13
- def sample_file(filename)
14
- File.join( File.dirname( __FILE__), 'testdata', filename)
8
+ include QDA
9
+ def test_filter_types()
10
+ import_filters = Filters::import_filters
11
+ assert_kind_of(Hash, import_filters)
12
+ assert_kind_of(Array, import_filters[QDA::Document])
13
+ assert(import_filters[Document].length > 0)
14
+
15
+ export_filters = Filters::export_filters
16
+ assert_kind_of(Hash, export_filters)
17
+ assert_kind_of(Array, export_filters[Document])
15
18
  end
16
-
19
+
17
20
  def test_unix_utf8()
18
- filter = QDA::TextFilter.new()
19
- doc = filter.read(sample_file('text1-unix-utf8.txt'), 'test-unix-utf8')
20
-
21
- str = "This is a text document\nin unix unicode.\n"
22
- assert_equal(str, doc.text, "Document text read in")
21
+ textfile = sample_file('text1-unix-utf8.txt')
22
+ doc = Filters.import_file(Document, textfile) do | doc, filter |
23
+ str = "This is a text document\nin unix unicode.\n"
24
+ assert_equal(str, doc.text, "Document text read in")
25
+ doc.title = 'utf-8'
26
+ end
27
+ assert_equal('utf-8', doc.title)
23
28
  end
24
29
 
25
30
  def test_indexer
26
- idx = QDA::Indexer.new()
27
- idx.index('foo')
28
-
29
31
  widx = QDA::WordIndexer.new()
30
32
  my_word = 'SOMETHING'
31
33
  widx.index(my_word)
@@ -34,34 +36,33 @@ class TestFilter < Test::Unit::TestCase
34
36
  end
35
37
 
36
38
  def test_dos_ascii()
37
- filter = QDA::TextFilter.new()
38
- doc = filter.read(sample_file('text1-dos-ascii.txt'), 'test-ascii')
39
+ text_filter = QDA::Filters.find_import_filter(QDA::Document, 'txt')
40
+ filter = text_filter.new()
41
+ doc = filter.run(sample_file('text1-dos-ascii.txt'))
39
42
 
40
43
  str = "This is a text document\nin dos ascii.\n"
41
44
  assert_equal(str, doc.text, "Document text read in")
42
45
  end
43
46
 
44
47
  def test_pdf
45
- filter = QDA::PDFFilter.new()
46
- windxr = QDA::WordIndexer.new()
47
- filter.add_indexer(windxr)
48
- doc = filter.read('testdata/emacs-refcard-a4.pdf', 'i')
49
-
50
- doc.title = 'Acknowledgments'
51
- word = 'moving'
52
- windxr.words.each do | word, offsets |
53
- offsets.each do | offset |
54
- assert_equal( word, doc[offset, word.length] )
55
- end
56
- end
48
+ doc = Filters.import_file(Document, sample_file('simple.pdf') )
49
+ txt = "This is a simple unlocked PDF document. " <<
50
+ "It should import without problem into Weft QDA.\n\n"
51
+ assert_equal(txt, doc.text)
52
+
53
+ doc = Filters.import_file(Document, sample_file('simple with space.pdf') )
54
+ txt = "This is a simple unlocked PDF document. " <<
55
+ "It should import without problem into Weft QDA.\n\n"
56
+ assert_equal(txt, doc.text, 'OK importing file with space in name')
57
57
  end
58
58
 
59
59
  def test_word_indexing()
60
- filter = QDA::TextFilter.new()
60
+ text_filter = Filters.find_import_filter(Document, 'txt')
61
+ filter = text_filter.new()
62
+
61
63
  windxr = QDA::WordIndexer.new()
62
64
  filter.add_indexer(windxr)
63
- doc = filter.read(sample_file('autocoding-test.txt'),
64
- 'word_indexing')
65
+ doc = filter.run( sample_file('autocoding-test.txt') )
65
66
  # ordinary, capitalised, short, apostrophe, longer
66
67
  test_words = [ 'the', 'Before', 'I', 'It\'s', 'opinions' ]
67
68
  test_words.each do | test_word |
@@ -71,25 +72,36 @@ class TestFilter < Test::Unit::TestCase
71
72
  end
72
73
  end
73
74
 
74
- def test_indexing_iso_8859_1
75
- filter = QDA::TextFilter.new()
76
- windxr = QDA::WordIndexer.new()
75
+ def test_indexing_iso_8859_1()
76
+ text_filter = Filters.find_import_filter(Document, 'txt')
77
+ filter = text_filter.new()
78
+
79
+ windxr = WordIndexer.new()
77
80
  filter.add_indexer(windxr)
78
- doc = filter.read(sample_file('iso-8859-1.txt'), 'iso-8859-1')
81
+
82
+ doc = filter.run( sample_file('iso-8859-1.txt') )
79
83
  word_rx = /[\w\xC0-\xD6\xD8-\xF6\xF8-\xFF][\w\xC0-\xD6\xD8-\xF6\xF8-\xFF\']+/
80
84
  windxr.words.each_key do | word |
81
85
  assert_match(word_rx, word)
82
86
  end
87
+
88
+ windxr2 = WordIndexer.new()
89
+ windxr2.feed(doc)
90
+ windxr.words.each do | word, offsets|
91
+ assert_equal(offsets, windxr2.words[word])
92
+ end
93
+
83
94
  end
84
95
 
85
96
  def test_autocoding
86
- filter = QDA::TextFilter.new()
97
+ text_filter = QDA::Filters.find_import_filter(QDA::Document, 'txt')
98
+ filter = text_filter.new()
99
+
87
100
  autocoder = QDA::AutoCoder.new(/^\*\*(.*)\*\*\s*$/ => 'Heading',
88
101
  /^(.*)\:\s*$/ => 'Speaker')
89
102
  filter.add_indexer(autocoder)
90
103
 
91
- doc = filter.read(sample_file('autocoding-test.txt'),
92
- 'autocoding')
104
+ doc = filter.run( sample_file('autocoding-test.txt') )
93
105
 
94
106
  str = "Before any autocoding\n\nSpeakerA:\nI am the first speaker.\nThis is what I say.\n\n**A TEXT HEADER**\n\nSpeakerB:\nI am the second speaker.\n\nThis is what I say. It's my opinions.\n\nSpeakerA:\nMe again.\n"
95
107
  assert_equal(str, doc.text)
@@ -0,0 +1,113 @@
1
+ require 'test-common'
2
+
3
+ require 'weft'
4
+ require 'tempfile' # so we can test output
5
+
6
+ require 'test/unit'
7
+
8
+ class TestFilter < Test::Unit::TestCase
9
+ include QDA
10
+
11
+ def run_filter(obj, filter)
12
+ tmp = Tempfile.new('output')
13
+ filter.write(obj, tmp)
14
+ tmp.rewind()
15
+ tmp.read()
16
+ end
17
+
18
+ def test_filter_types()
19
+ import_filters = Filters::import_filters
20
+ assert_kind_of(Hash, import_filters)
21
+ assert_kind_of(Array, import_filters[QDA::Document])
22
+ assert(import_filters[Document].length > 0)
23
+
24
+ export_filters = Filters::export_filters
25
+ assert_kind_of(Hash, export_filters)
26
+ assert_kind_of(Array, export_filters[Category])
27
+ assert(export_filters[Category].length > 0)
28
+ assert(export_filters[Document].length > 0)
29
+ assert(export_filters[CodeReview].length > 0)
30
+
31
+ assert( Filters.can_export?(Category) )
32
+ assert( Filters.can_export?(Document) )
33
+ assert( Filters.can_export?(CodeReview) )
34
+ assert( ! Filters.can_export?(Query) )
35
+
36
+ end
37
+
38
+ def test_export_document()
39
+ doc = Document.new('foo')
40
+ doc.append('blah blah blah')
41
+ filter = Filters::DocumentTextOutput.new()
42
+
43
+ tmp = Tempfile.new('doc_text')
44
+ filter.write(doc, tmp)
45
+ tmp.rewind()
46
+ contents = tmp.read()
47
+ # Proper template not written yet
48
+ # assert_match(/blah/m, contents, 'Looks a bit like the document')
49
+ end
50
+
51
+ def test_export_category()
52
+ @app = QDA::Application.new()
53
+ @app.extend(QDA::Backend::SQLite)
54
+ @app.start(:memory => true)
55
+ @app.install_clean()
56
+
57
+ doc = Document.new('My Document')
58
+ doc.append('This is some text in the document')
59
+ @app.save_doc(doc)
60
+
61
+ cat = Category.new('foo & bar')
62
+ cat.code(doc.dbid, 13, 7)
63
+ @app.save_category(cat)
64
+
65
+ contents = run_filter( cat, Filters::CategoryHTMLOutput.new(@app) )
66
+ assert_match(/<html>.*<\/html>/m, contents, "Sort of looks like HTML")
67
+ assert_match(/foo &amp; bar/, contents, "Title's mentioned somewhere")
68
+ assert_match(/foo/, contents, "Category name's mentioned somewhere")
69
+ assert_match(/text in/, contents, "Document text is included")
70
+ end
71
+
72
+ def test_export_codereview_csv()
73
+ @app = QDA::Application.new()
74
+ @app.extend(QDA::Backend::SQLite)
75
+ @app.start(:memory => true)
76
+ @app.install_clean()
77
+ cr = mock_codereview()
78
+ tmp = Tempfile.new('codereview_csv')
79
+
80
+ filter = Filters::CodeReviewCSVOutput.new(@app)
81
+ filter.write(cr, tmp)
82
+ tmp.rewind()
83
+ lines = tmp.read().split("\n")
84
+ assert_match(/foo,bar/, lines[0])
85
+ assert_equal('baz,10,10', lines[1])
86
+ end
87
+
88
+ def mock_codereview()
89
+ cr = CodeReview.new()
90
+ cr.count_method = :num_of_chars
91
+ cat1 = Category.new('foo')
92
+ cat1.code(1, 10, 40)
93
+ cat2 = Category.new('bar')
94
+ cat2.code(1, 70, 20)
95
+ cat3 = Category.new('baz')
96
+ cat3.code(1, 40, 40)
97
+ cat4 = Category.new('qux')
98
+ cat4.code(1, 85, 15)
99
+
100
+ cr.add_col( cat1 )
101
+ cr.add_col( cat2 )
102
+
103
+ cr.add_row( cat3 )
104
+ cr.add_row( cat4 )
105
+ cr
106
+ end
107
+
108
+ def test_export_codereview_html
109
+ cr = mock_codereview()
110
+ contents = run_filter(cr, Filters::CodeReviewHTMLOutput.new() )
111
+ assert_match(/<table/, contents, "There's a table in there somewhere")
112
+ end
113
+ end
@@ -1,8 +1,23 @@
1
- require 'english'
2
- $:.push('../lib/')
3
-
1
+ require 'test-common'
4
2
  require 'weft'
5
- require 'test/unit'
3
+
4
+ class DummyClient
5
+ attr_reader :event_log
6
+ include QDA::Subscriber
7
+
8
+ def initialize(app = nil)
9
+ @event_log = []
10
+ subscribe(app, :all)
11
+ end
12
+
13
+ def reset_log()
14
+ @event_log = []
15
+ end
16
+
17
+ def notify(evt, data)
18
+ event_log.push( :evt => evt, :data => data )
19
+ end
20
+ end
6
21
 
7
22
  class TestSQLiteBasic < Test::Unit::TestCase
8
23
  def sample_file(filename)
@@ -13,17 +28,15 @@ class TestSQLiteBasic < Test::Unit::TestCase
13
28
  @dbfile = nil
14
29
  @app = QDA::Application.new()
15
30
  @app.extend(QDA::Backend::SQLite)
31
+ @client = DummyClient.new(@app)
16
32
  end
17
33
 
18
34
  # delete any files hanging around
19
35
  def teardown()
20
- if @app.started?
21
- # p @app
22
- # @app.end()
23
- if @app.dbfile and File.exist?(@app.dbfile)
24
- File.delete(@app.dbfile)
25
- end
26
- end
36
+ @app.end
37
+ if @app.dbfile and File.exist?(@app.dbfile)
38
+ File.delete(@app.dbfile)
39
+ end
27
40
  end
28
41
 
29
42
  # test save & revert
@@ -33,7 +46,7 @@ class TestSQLiteBasic < Test::Unit::TestCase
33
46
  doc = QDA::Document.new('Doc-1')
34
47
  @app.save_document(doc)
35
48
 
36
- assert_raises(RuntimeError, "Cannot save without a filename") do
49
+ assert_raises(QDA::Backend::BackendError, "Cannot save without filename") do
37
50
  doc = @app.save()
38
51
  end
39
52
 
@@ -78,9 +91,14 @@ class TestSQLiteBasic < Test::Unit::TestCase
78
91
  @app.install_clean()
79
92
  doc = QDA::Document.new('About Something')
80
93
  assert_nil(doc.dbid, "No DBID set")
94
+ assert_nil( @app.doc_exists(doc.title) )
95
+
96
+ # test saving
81
97
  @app.save_document(doc)
82
98
  assert(doc.dbid, 'Got a DBID set')
83
-
99
+ assert_equal( doc.dbid, @app.doc_exists(doc.title) )
100
+
101
+ # test fetching by document identifier
84
102
  fetch_doc = @app.get_doc(doc.dbid)
85
103
  assert(fetch_doc, "Got something back")
86
104
 
@@ -89,6 +107,7 @@ class TestSQLiteBasic < Test::Unit::TestCase
89
107
  assert_equal(doc.title, fetch_doc.title,
90
108
  "Fetched back thing has the same dbid")
91
109
 
110
+ # test fetching by document title
92
111
  fetch_doc = @app.get_doc(doc.title)
93
112
  assert(fetch_doc, "Got something back")
94
113
 
@@ -96,8 +115,25 @@ class TestSQLiteBasic < Test::Unit::TestCase
96
115
  "Fetched back thing has the same dbid")
97
116
  assert_equal(doc.title, fetch_doc.title,
98
117
  "Fetched back thing has the same dbid")
99
- end
100
118
 
119
+ end
120
+ def test_magic_renaming_document()
121
+ @app.start(:dbfile => @dbfile)
122
+ @app.install_clean()
123
+
124
+ @app.save_document(QDA::Document.new('Foo'))
125
+ doc = QDA::Document.new('Foo')
126
+ assert_raises(QDA::NotUniqueNameError) { @app.save_doc(doc) }
127
+ # test duplicate magic renaming
128
+ @app.save_document(doc, true)
129
+ assert(doc.dbid)
130
+ assert_equal('Foo (1)', doc.title)
131
+ doc_1 = QDA::Document.new('Foo')
132
+ @app.save_document(doc_1, true)
133
+ assert(doc_1.dbid)
134
+ assert_equal('Foo (2)', doc_1.title)
135
+ end
136
+
101
137
  def test_save_and_get_document_content()
102
138
  @app.start(:dbfile => @dbfile)
103
139
  @app.install_clean()
@@ -165,6 +201,24 @@ class TestSQLiteBasic < Test::Unit::TestCase
165
201
 
166
202
  end
167
203
 
204
+
205
+ def test_root_category()
206
+ @app.start(:dbfile => @dbfile)
207
+ @app.install_clean()
208
+ root = QDA::Category.new("ROOT", nil, 'the "memo"')
209
+ @app.save_category(root)
210
+ f_root = @app.get_root_category('ROOT')
211
+ assert_equal(nil, f_root.parent)
212
+ assert_equal('ROOT', f_root.name)
213
+ f_root.name = 'RENAMED'
214
+ @app.save_category(f_root)
215
+
216
+ assert_raises(QDA::NotFoundError) { @app.get_root_category('ROOT') }
217
+ f_root = @app.get_root_category('RENAMED')
218
+ assert_equal(nil, f_root.parent)
219
+ assert_equal('RENAMED', f_root.name)
220
+ end
221
+
168
222
  def test_basic_save_category
169
223
  @app.start(:dbfile => @dbfile)
170
224
  @app.install_clean()
@@ -178,19 +232,29 @@ class TestSQLiteBasic < Test::Unit::TestCase
178
232
  "Name retrieved successfully")
179
233
  assert_equal(cat1.memo, f_cat1.memo,
180
234
  "Memo retrieved successfully")
181
-
235
+
236
+ f_cat1 = @app.get_category("/About 'Something'")
237
+ assert_equal(cat1, f_cat1)
238
+
182
239
  # test some parent-child stuff
183
240
  cat2 = QDA::Category.new('Something "Specific"', cat1)
184
241
  @app.save_category(cat2)
185
242
  assert(cat2.dbid, 'Category was assigned a database id')
243
+ assert_equal(cat1, cat2.parent)
244
+
245
+ f_cat1 = @app.get_category(cat1.dbid, true)
246
+ assert_equal(1, f_cat1.children.length)
186
247
 
248
+ f_cat2 = @app.get_category("/About 'Something'/Something")
249
+ assert_equal(cat2, f_cat2)
250
+
251
+
187
252
  cat2a = QDA::Category.new('Something "Specific" & Detailed', cat2)
188
253
  @app.save_category(cat2a)
189
254
 
190
255
  cat3 = QDA::Category.new('Something "Else"', cat1)
191
256
  @app.save_category(cat3)
192
257
 
193
- # @app.dbh.execute("SELECT * FROM category") { | r | p r }
194
258
  f_cat2 = @app.get_category(cat2.dbid)
195
259
  assert_equal(cat2.name, f_cat2.name,
196
260
  "Name retrieved successfully")
@@ -225,8 +289,7 @@ class TestSQLiteBasic < Test::Unit::TestCase
225
289
  assert_equal(QDA::Category, new_root.class)
226
290
  assert_equal("NEw root node", new_root.name)
227
291
  assert_equal(nil, new_root.parent)
228
- assert_raises(RuntimeError) { @app.get_root_category("Doesn't exist") }
229
-
292
+ assert_raises(QDA::NotFoundError) { @app.get_root_category("Doesn't exist") }
230
293
 
231
294
  finds = @app.get_categories_by_path('Something')
232
295
  assert_equal(3, finds.length, 'Normal name/path search')
@@ -244,7 +307,7 @@ class TestSQLiteBasic < Test::Unit::TestCase
244
307
  def test_cut_paste_category
245
308
  @app.start(:dbfile => @dbfile)
246
309
  @app.install_clean()
247
- cat1 = QDA::Category.new("About 'Something'", nil)
310
+ cat1 = QDA::Category.new("Root", nil)
248
311
  @app.save_category(cat1)
249
312
 
250
313
  cat2 = QDA::Category.new('Something "Specific"', cat1)
@@ -256,20 +319,28 @@ class TestSQLiteBasic < Test::Unit::TestCase
256
319
  cat4 = QDA::Category.new('Something "Again"', cat1)
257
320
  @app.save_category(cat4)
258
321
 
259
-
260
322
  cat2.parent = cat3
261
323
  @app.save_category(cat2)
324
+ assert_equal("/Root/Something \"Else\"/Something \"Specific\"",
325
+ cat2.path)
262
326
 
263
-
264
327
  cat4.parent = cat3
265
328
  @app.save_category(cat4)
329
+
266
330
 
331
+ cat4_x = @app.get_category(cat4.dbid)
332
+ assert_equal(cat3, cat4_x.parent)
333
+
267
334
  cat2.parent = cat1
268
335
  @app.save_category(cat2)
269
336
 
270
- deletions = @app.delete_category(cat3)
271
- assert_kind_of(Array, deletions)
272
- assert_equal(2, deletions.length)
337
+ @client.reset_log
338
+ deletion = @app.delete_category(cat3)
339
+ assert_kind_of(QDA::Category, deletion)
340
+ assert_equal(cat3, deletion)
341
+ assert_raises(QDA::NotFoundError) { @app.get_category(cat4.dbid) }
342
+ assert_raises(QDA::NotFoundError) { @app.get_category(cat3.dbid) }
343
+ assert_equal(2, @client.event_log.length)
273
344
  end
274
345
 
275
346
  def test_install()