View | Details | Raw Unified | Return to bug 16155
Collapse All | Expand All

(-)a/t/db_dependent/TestBuilder.t (-220 / +262 lines)
Lines 19-25 Link Here
19
19
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use Test::More tests => 41;
22
use Test::More tests => 9;
23
use Test::Warn;
24
use Data::Dumper qw(Dumper);
23
25
24
use Koha::Database;
26
use Koha::Database;
25
27
Lines 27-260 BEGIN { Link Here
27
    use_ok('t::lib::TestBuilder');
29
    use_ok('t::lib::TestBuilder');
28
}
30
}
29
31
30
my $schema  = Koha::Database->new->schema;
32
my $schema = Koha::Database->new->schema;
31
$schema->storage->txn_begin;
33
$schema->storage->txn_begin;
34
my $builder;
32
35
33
my $builder = t::lib::TestBuilder->new();
34
36
35
is( $builder->build(), undef, 'build without arguments returns undef' );
37
subtest 'Start with some trivial tests' => sub {
38
    plan tests => 6;
36
39
37
my @sources    = $builder->schema->sources;
40
    $builder = t::lib::TestBuilder->new;
38
my @source_in_failure;
41
    isnt( $builder, undef, 'We got a builder' );
39
for my $source (@sources) {
42
40
    eval { $builder->build( { source => $source } ); };
43
    is( $builder->build, undef, 'build without arguments returns undef' );
41
    push @source_in_failure, $source if $@;
44
    is( ref( $builder->schema ), 'Koha::Schema', 'check schema' );
42
}
45
    is( ref( $builder->can('delete') ), 'CODE', 'found delete method' );
43
is( @source_in_failure, 0, 'TestBuilder should be able to create an object for every sources' );
44
if ( @source_in_failure ) {
45
    diag ("The following sources have not been generated correctly: " . join ', ', @source_in_failure)
46
}
47
46
48
my $my_overduerules_transport_type = {
47
    # invalid argument
49
    message_transport_type => {
48
    warning_like { $builder->build({
50
        message_transport_type => 'my msg_t_t',
49
            source => 'Borrower',
51
    },
50
            value  => { surname => { invalid_hash => 1 } },
52
    overduerules_id => {
51
        }) } qr/^Hash not allowed for surname/,
53
        branchcode   => 'codeB',
52
        'Build should not accept a hash for this column';
54
        categorycode => 'codeC',
53
55
    },
54
    # return undef if a record exists
56
    categorycode => undef,
55
    my $param = { source => 'Branch', value => { branchcode => 'MPL' } };
56
    $builder->build( $param ); # at least it should exist now
57
    is( $builder->build( $param ), undef, 'Return undef when exists' );
57
};
58
};
58
$my_overduerules_transport_type->{categorycode} = $my_overduerules_transport_type->{branchcode};
59
my $overduerules_transport_type = $builder->build({
60
    source => 'OverduerulesTransportType',
61
    value  => $my_overduerules_transport_type,
62
});
63
is(
64
    $overduerules_transport_type->{message_transport_type},
65
    $my_overduerules_transport_type->{message_transport_type}->{message_transport_type},
66
    'build stores the message_transport_type correctly'
67
);
68
is(
69
    $overduerules_transport_type->{branchcode},
70
    $my_overduerules_transport_type->{branchcode}->{branchcode},
71
    'build stores the branchcode correctly'
72
);
73
is(
74
    $overduerules_transport_type->{categorycode},
75
    $my_overduerules_transport_type->{categorycode}->{categorycode},
76
    'build stores the categorycode correctly'
77
);
78
is(
79
    $overduerules_transport_type->{_fk}->{message_transport_type}->{message_transport_type},
80
    $my_overduerules_transport_type->{message_transport_type}->{message_transport_type},
81
    'build stores the foreign key message_transport_type correctly'
82
);
83
is(
84
    $overduerules_transport_type->{_fk}->{branchcode}->{branchcode},
85
    $my_overduerules_transport_type->{branchcode}->{branchcode},
86
    'build stores the foreign key branchcode correctly'
87
);
88
is(
89
    $overduerules_transport_type->{_fk}->{categorycode}->{categorycode},
90
    $my_overduerules_transport_type->{categorycode}->{categorycode},
91
    'build stores the foreign key categorycode correctly'
92
);
93
is_deeply(
94
    $overduerules_transport_type->{_fk}->{branchcode},
95
    $overduerules_transport_type->{_fk}->{categorycode},
96
    'build links the branchcode and the categorycode correctly'
97
);
98
isnt(
99
    $overduerules_transport_type->{_fk}->{overduerules_id}->{letter2},
100
    undef,
101
    'build generates values if they are not given'
102
);
103
104
my $my_user_permission = $t::lib::TestBuilder::default_value->{UserPermission};
105
my $user_permission = $builder->build({
106
    source => 'UserPermission',
107
});
108
isnt(
109
    $user_permission->{borrowernumber},
110
    undef,
111
    'build generates a borrowernumber correctly'
112
);
113
is(
114
    $user_permission->{module_bit},
115
    $my_user_permission->{module_bit}->{module_bit}->{bit},
116
    'build stores the default value correctly'
117
);
118
is(
119
    $user_permission->{code},
120
    $my_user_permission->{module_bit}->{code},
121
    'build stores the default value correctly'
122
);
123
is(
124
    $user_permission->{borrowernumber},
125
    $user_permission->{_fk}->{borrowernumber}->{borrowernumber},
126
    'build links the foreign key correctly'
127
);
128
is(
129
    $user_permission->{_fk}->{borrowernumber}->{surname},
130
    $my_user_permission->{borrowernumber}->{surname},
131
    'build stores the foreign key value correctly'
132
);
133
is(
134
    $user_permission->{_fk}->{borrowernumber}->{address},
135
    $my_user_permission->{borrowernumber}->{address},
136
    'build stores the foreign key value correctly'
137
);
138
is(
139
    $user_permission->{_fk}->{borrowernumber}->{city},
140
    $my_user_permission->{borrowernumber}->{city},
141
    'build stores the foreign key value correctly'
142
);
143
is(
144
    $user_permission->{_fk}->{borrowernumber}->{_fk}->{branchcode}->{branchcode},
145
    $my_user_permission->{borrowernumber}->{branchcode}->{branchcode},
146
    'build stores the foreign key value correctly'
147
);
148
is(
149
    $user_permission->{_fk}->{borrowernumber}->{_fk}->{branchcode}->{branchname},
150
    $my_user_permission->{borrowernumber}->{branchcode}->{branchname},
151
    'build stores the foreign key value correctly'
152
);
153
is(
154
    $user_permission->{_fk}->{borrowernumber}->{_fk}->{categorycode}->{categorycode},
155
    $my_user_permission->{borrowernumber}->{categorycode}->{categorycode},
156
    'build stores the foreign key value correctly'
157
);
158
is(
159
    $user_permission->{_fk}->{borrowernumber}->{_fk}->{categorycode}->{hidelostitems},
160
    $my_user_permission->{borrowernumber}->{categorycode}->{hidelostitems},
161
    'build stores the foreign key value correctly'
162
);
163
is(
164
    $user_permission->{_fk}->{borrowernumber}->{_fk}->{categorycode}->{category_type},
165
    $my_user_permission->{borrowernumber}->{categorycode}->{category_type},
166
    'build stores the foreign key value correctly'
167
);
168
is(
169
    $user_permission->{_fk}->{borrowernumber}->{_fk}->{categorycode}->{defaultprivacy},
170
    $my_user_permission->{borrowernumber}->{categorycode}->{defaultprivacy},
171
    'build stores the foreign key value correctly'
172
);
173
is(
174
    $user_permission->{_fk}->{borrowernumber}->{privacy},
175
    $my_user_permission->{borrowernumber}->{privacy},
176
    'build stores the foreign key value correctly'
177
);
178
is(
179
    $user_permission->{_fk}->{module_bit}->{_fk}->{module_bit}->{bit},
180
    $my_user_permission->{module_bit}->{module_bit}->{bit},
181
    'build stores the foreign key value correctly'
182
);
183
is(
184
    $user_permission->{_fk}->{module_bit}->{code},
185
    $my_user_permission->{module_bit}->{code},
186
    'build stores the foreign key value correctly'
187
);
188
is_deeply(
189
    $user_permission->{_fk}->{module_bit},
190
    $user_permission->{_fk}->{code},
191
    'build links the codes correctly'
192
);
193
isnt(
194
    $user_permission->{_fk}->{borrowernumber}->{cardnumber},
195
    undef,
196
    'build generates values if they are not given'
197
);
198
isnt(
199
    $user_permission->{_fk}->{borrowernumber}->{_fk}->{branchcode}->{branchaddress1},
200
    undef,
201
    'build generates values if they are not given'
202
);
203
isnt(
204
    $user_permission->{_fk}->{borrowernumber}->{_fk}->{categorycode}->{description},
205
    undef,
206
    'build generates values if they are not given'
207
);
208
isnt(
209
    $user_permission->{_fk}->{module_bit}->{description},
210
    undef,
211
    'build generates values if they are not given'
212
);
213
isnt(
214
    $user_permission->{_fk}->{module_bit}->{_fk}->{module_bit}->{flag},
215
    undef,
216
    'build generates values if they are not given'
217
);
218
219
220
my $nb_basket = $builder->schema->resultset('Aqbasket')->search();
221
isnt( $nb_basket, 0, 'add stores the generated entries correctly' );
222
$builder->clear( { source => 'Aqbasket' } );
223
$nb_basket = $builder->schema->resultset('Aqbasket')->search();
224
is( $nb_basket, 0, 'clear removes all the entries correctly' );
225
226
227
my $rs_aqbookseller = $builder->schema->resultset('Aqbookseller');
228
my $bookseller = $builder->build({
229
    source  => 'Aqbookseller',
230
    only_fk => 1,
231
});
232
delete $bookseller->{_fk};
233
my $bookseller_from_db = $rs_aqbookseller->find($bookseller);
234
is( $bookseller_from_db, undef, 'build with only_fk = 1 does not store the entry' );
235
my $bookseller_result = $rs_aqbookseller->create($bookseller);
236
is( $bookseller_result->in_storage, 1, 'build with only_fk = 1 creates the foreign keys correctly' );
237
238
$bookseller = $builder->build({
239
    source  => 'Aqbookseller',
240
});
241
ok( length( $bookseller->{phone} ) <= 30, 'The length for a generated string should not be longer than the size of the DB field' );
242
delete $bookseller->{_fk};
243
$bookseller_from_db = $rs_aqbookseller->find($bookseller);
244
is( $bookseller_from_db->in_storage, 1, 'build without the parameter only_sk stores the entry correctly' );
245
246
$bookseller = $builder->build({
247
    source  => 'Aqbookseller',
248
    only_fk => 0,
249
});
250
delete $bookseller->{_fk};
251
$bookseller_from_db = $rs_aqbookseller->find($bookseller);
252
is( $bookseller_from_db->in_storage, 1, 'build with only_fk = 0 stores the entry correctly' );
253
59
254
subtest 'Auto-increment values tests' => sub {
255
60
61
subtest 'Build all sources' => sub {
62
    plan tests => 1;
63
64
    my @sources = $builder->schema->sources;
65
    my @source_in_failure;
66
    for my $source ( @sources ) {
67
        my $res;
68
        eval { $res = $builder->build( { source => $source } ); };
69
        push @source_in_failure, $source if $@ || !defined( $res );
70
    }
71
    is( @source_in_failure, 0,
72
        'TestBuilder should be able to create an object for every source' );
73
    if ( @source_in_failure ) {
74
        diag( "The following sources have not been generated correctly: " .
75
        join ', ', @source_in_failure );
76
    }
77
};
78
79
80
subtest 'Test length of some generated fields' => sub {
256
    plan tests => 2;
81
    plan tests => 2;
257
82
83
    # Test the length of a returned character field
84
    my $bookseller = $builder->build({ source  => 'Aqbookseller' });
85
    my $max = $schema->source('Aqbookseller')->column_info('phone')->{size};
86
    is( length( $bookseller->{phone} ) > 0, 1,
87
        'The length for a generated string (phone) should not be zero' );
88
    is( length( $bookseller->{phone} ) <= $max, 1,
89
        'Check maximum length for a generated string (phone)' );
90
};
91
92
93
subtest 'Test FKs in overduerules_transport_type' => sub {
94
    plan tests => 5;
95
96
    my $my_overduerules_transport_type = {
97
        message_transport_type => {
98
            message_transport_type => 'my msg_t_t',
99
        },
100
        overduerules_id => {
101
            branchcode   => 'codeB',
102
            categorycode => 'codeC',
103
        },
104
    };
105
106
    my $overduerules_transport_type = $builder->build({
107
        source => 'OverduerulesTransportType',
108
        value  => $my_overduerules_transport_type,
109
    });
110
    is(
111
        $overduerules_transport_type->{message_transport_type},
112
        $my_overduerules_transport_type->{message_transport_type}->{message_transport_type},
113
        'build stores the message_transport_type correctly'
114
    );
115
    is(
116
        $schema->resultset('Overduerule')->find( $overduerules_transport_type->{overduerules_id} )->branchcode,
117
        $my_overduerules_transport_type->{overduerules_id}->{branchcode},
118
        'build stores the branchcode correctly'
119
    );
120
    is(
121
        $schema->resultset('Overduerule')->find( $overduerules_transport_type->{overduerules_id} )->categorycode,
122
        $my_overduerules_transport_type->{overduerules_id}->{categorycode},
123
        'build stores the categorycode correctly'
124
    );
125
    is(
126
        $schema->resultset('MessageTransportType')->find( $overduerules_transport_type->{message_transport_type} )->message_transport_type,
127
        $overduerules_transport_type->{message_transport_type},
128
        'build stores the foreign key message_transport_type correctly'
129
    );
130
    isnt(
131
        $schema->resultset('Overduerule')->find( $my_overduerules_transport_type->{overduerules_id} )->letter2,
132
        undef,
133
        'build generates values if they are not given'
134
    );
135
};
136
137
138
subtest 'Tests with composite FK in userpermission' => sub {
139
    plan tests => 9;
140
141
    my $my_user_permission = default_userpermission();
142
    my $user_permission = $builder->build({
143
        source => 'UserPermission',
144
        value  => $my_user_permission,
145
    });
146
147
    # Checks on top level of userpermission
148
    isnt(
149
        $user_permission->{borrowernumber},
150
        undef,
151
        'build generates a borrowernumber correctly'
152
    );
153
    is(
154
        $user_permission->{code},
155
        $my_user_permission->{code}->{code},
156
        'build stores code correctly'
157
    );
158
159
    # Checks one level deeper userpermission -> borrower
160
    my $patron = $schema->resultset('Borrower')->find({ borrowernumber => $user_permission->{borrowernumber} });
161
    is(
162
        $patron->surname,
163
        $my_user_permission->{borrowernumber}->{surname},
164
        'build stores surname correctly'
165
    );
166
    isnt(
167
        $patron->cardnumber,
168
        undef,
169
        'build generated cardnumber'
170
    );
171
172
    # Checks two levels deeper userpermission -> borrower -> branch
173
    my $branch = $schema->resultset('Branch')->find({ branchcode => $patron->branchcode->branchcode });
174
    is(
175
        $branch->branchname,
176
        $my_user_permission->{borrowernumber}->{branchcode}->{branchname},
177
        'build stores branchname correctly'
178
    );
179
    isnt(
180
        $branch->branchaddress1,
181
        undef,
182
        'build generated branch address'
183
    );
184
185
    # Checks with composite FK: userpermission -> permission
186
    my $perm = $schema->resultset('Permission')->find({ module_bit => $user_permission->{module_bit}, code => $my_user_permission->{code}->{code} });
187
    isnt( $perm, undef, 'build generated record for composite FK' );
188
    is(
189
        $perm->code,
190
        $my_user_permission->{code}->{code},
191
        'build stored code correctly'
192
    );
193
    is(
194
        $perm->description,
195
        $my_user_permission->{code}->{description},
196
        'build stored description correctly'
197
    );
198
};
199
200
sub default_userpermission {
201
    return {
202
        borrowernumber => {
203
            surname => 'my surname',
204
            address => 'my adress',
205
            city    => 'my city',
206
            branchcode => {
207
                branchname => 'my branchname',
208
            },
209
            categorycode => {
210
                hidelostitems   => 0,
211
                category_type   => 'A',
212
                default_privacy => 'default',
213
            },
214
            privacy => 1,
215
        },
216
        module_bit => {
217
            flag        => 'my flag',
218
        },
219
        code => {
220
            code        => 'my code',
221
            description => 'my desc',
222
        },
223
    };
224
}
225
226
227
subtest 'Test build with NULL values' => sub {
228
    plan tests => 3;
229
230
    # PK should not be null
231
    my $params = { source => 'Branch', value => { branchcode => undef }};
232
    is( $builder->build( $params ), undef, 'PK should not be null' );
233
    # Nullable column
234
    my $info = $schema->source( 'Item' )->column_info( 'barcode' );
235
    $params = { source => 'Item', value  => { barcode => undef }};
236
    my $item = $builder->build( $params );
237
    is( $info->{is_nullable} && $item && !defined( $item->{barcode} ), 1,
238
        'Barcode can be NULL' );
239
    # Nullable FK
240
    $params = { source => 'Reserve', value  => { itemnumber => undef }};
241
    my $reserve = $builder->build( $params );
242
    $info = $schema->source( 'Reserve' )->column_info( 'itemnumber' );
243
    is( $reserve && $info->{is_nullable} && $info->{is_foreign_key} &&
244
        !defined( $reserve->{itemnumber} ), 1, 'Nullable FK' );
245
};
246
247
248
subtest 'Tests for delete method' => sub {
249
    plan tests => 12;
250
251
    # Test delete with single and multiple records
252
    my $basket1 = $builder->build({ source => 'Aqbasket' });
253
    my $basket2 = $builder->build({ source => 'Aqbasket' });
254
    my $basket3 = $builder->build({ source => 'Aqbasket' });
255
    my ( $id1, $id2 ) = ( $basket1->{basketno}, $basket2->{basketno} );
256
    $builder->delete({ source => 'Aqbasket', records => $basket1 });
257
    isnt( exists $basket1->{basketno}, 1, 'Delete cleared PK hash value' );
258
259
    is( $builder->schema->resultset('Aqbasket')->search({ basketno => $id1 })->count, 0, 'Basket1 is no longer found' );
260
    is( $builder->schema->resultset('Aqbasket')->search({ basketno => $id2 })->count, 1, 'Basket2 is still found' );
261
    is( $builder->delete({ source => 'Aqbasket', records => [ $basket2, $basket3 ] }), 2, "Returned two delete attempts" );
262
    is( $builder->schema->resultset('Aqbasket')->search({ basketno => $id2 })->count, 0, 'Basket2 is no longer found' );
263
264
265
    # Test delete in table without primary key (..)
266
    is( $schema->source('TmpHoldsqueue')->primary_columns, 0,
267
        'Table without primary key detected' );
268
    my $bibno = 123; # just a number
269
    my $cnt1 = $schema->resultset('TmpHoldsqueue')->count;
270
    # Insert a new record in TmpHoldsqueue with that biblionumber
271
    my $val = { biblionumber => $bibno };
272
    my $rec = $builder->build({ source => 'TmpHoldsqueue', value => $val });
273
    my $cnt2 = $schema->resultset('TmpHoldsqueue')->count;
274
    is( defined($rec) && $cnt2 == $cnt1 + 1 , 1, 'Created a record' );
275
    is( $builder->delete({ source => 'TmpHoldsqueue', records => $rec }),
276
        undef, 'delete returns undef' );
277
    is( $rec->{biblionumber}, $bibno, 'Hash value untouched' );
278
    is( $schema->resultset('TmpHoldsqueue')->count, $cnt2,
279
        "Method did not delete record in table without PK" );
280
281
    # Test delete with NULL values
282
    $val = { branchcode => undef };
283
    is( $builder->delete({ source => 'Branch', records => $val }), 0,
284
        'delete returns zero for an undef search with one key' );
285
    $val = { module_bit => 1, #catalogue
286
             code       => undef };
287
    is( $builder->delete({ source => 'Permission', records => $val }), 0,
288
        'delete returns zero for an undef search with a composite PK' );
289
};
290
291
292
subtest 'Auto-increment values tests' => sub {
293
    plan tests => 3;
294
258
    # Pick a table with AI PK
295
    # Pick a table with AI PK
259
    my $source  = 'Biblio'; # table
296
    my $source  = 'Biblio'; # table
260
    my $column  = 'biblionumber'; # ai column
297
    my $column  = 'biblionumber'; # ai column
Lines 272-277 subtest 'Auto-increment values tests' => sub { Link Here
272
    my $next_ai_value = $biblio_2->{ biblionumber };
309
    my $next_ai_value = $biblio_2->{ biblionumber };
273
    is( $ai_value + 1, $next_ai_value, "AI values are consecutive");
310
    is( $ai_value + 1, $next_ai_value, "AI values are consecutive");
274
311
312
    # respect autoincr column
313
    warning_like { $builder->build({
314
            source => $source,
315
            value  => { biblionumber => 123 },
316
        }) } qr/^Value not allowed for auto_incr/,
317
        'Build should not overwrite an auto_incr column';
275
};
318
};
276
319
277
$schema->storage->txn_rollback;
320
$schema->storage->txn_rollback;
278
- 

Return to bug 16155