Skip to content
Permalink
Browse files

Add spec_defaults()

This adds spec_defaults which allows you to specify default attributes
for blocks of a given type for any given build scope.

Fixes #6
Fixes #7
  • Loading branch information...
exodist committed Jul 27, 2016
1 parent f8c61bb commit c6d1442dd7040935b5db7ca27731baadc3addeeb
Showing with 99 additions and 7 deletions.
  1. +2 −0 Changes
  2. +91 −4 lib/Test2/Tools/Spec.pm
  3. +4 −2 lib/Test2/Workflow.pm
  4. +2 −1 lib/Test2/Workflow/Build.pm
@@ -1,5 +1,7 @@
{{$NEXT}}

- Add spec_defaults()

0.000014 2016-07-02 22:11:29-07:00 America/Los_Angeles

- No Changes from last trial
@@ -3,7 +3,7 @@ use strict;
use warnings;

use Carp qw/croak/;
use Test2::Workflow qw/parse_args build current_build root_build init_root/;
use Test2::Workflow qw/parse_args build current_build root_build init_root build_stack/;

use Test2::Workflow::Runner();
use Test2::Workflow::Task::Action();
@@ -13,7 +13,7 @@ use Importer();

use vars qw/@EXPORT @EXPORT_OK/;
push @EXPORT => qw{describe cases};
push @EXPORT_OK => qw{include_workflow include_workflows};
push @EXPORT_OK => qw{include_workflow include_workflows spec_defaults};

my %HANDLED;
sub import {
@@ -116,9 +116,12 @@ sub import {

sub describe {
my @caller = caller(0);
my $build = build(args => \@_, caller => \@caller);

return $build if defined wantarray;
my $want = wantarray;

my $build = build(args => \@_, caller => \@caller, stack_stop => defined $want ? 1 : 0);

return $build if defined $want;

my $current = current_build() || root_build($caller[0])
or croak "No current workflow build!";
@@ -140,6 +143,25 @@ sub include_workflow {
}
}

sub defaults {
my %params = @_;

my ($package, $tool) = @params{qw/package tool/};

my @stack = (root_build($package), build_stack());
return unless @stack;

my %out;
for my $build (@stack) {
%out = () if $build->stack_stop;
my $new = $build->defaults->{$tool} or next;
%out = (%out, %$new);
}

return \%out;
}


# Generate a bunch of subs that only have minor differences between them.
BEGIN {
@EXPORT = qw{
@@ -208,6 +230,20 @@ BEGIN {
around_each => [scaffold => 1, around => 1],
);

sub spec_defaults {
my ($tool, %params) = @_;
my @caller = caller(0);

croak "'$tool' is not a spec tool"
unless exists $props{$tool} || exists $stages{$tool};

my $build = current_build() || root_build($caller[0])
or croak "No current workflow build!";

my $old = $build->defaults->{$tool} ||= {};
$build->defaults->{$tool} = { %$old, %params };
}

my $run = "";
for my $func (@EXPORT, @EXPORT_OK) {
$run .= <<" EOT";
@@ -222,6 +258,14 @@ sub $func {
my \$build = current_build() || root_build(\$caller[0])
or croak "No current workflow build!";
if (my \$defaults = defaults(package => \$caller[0], tool => '$func')) {
for my \$attr (keys \%\$defaults) {
next if defined \$action->\$attr;
my \$sub = "set_\$attr";
\$action->\$sub(\$defaults->{\$attr});
}
}
\$build->\$_(\$action) for \@{\$stages{$func}};
}
EOT
@@ -524,6 +568,49 @@ Same as:
=back
=head2 CUSTOM ATTRIBUTE DEFAULTS
Sometimes you want to apply default attributes to all C<tests()> or C<case()>
blocks. This can be done, and is lexical to your describe or package root!
use Test2::Bundle::Extended;
use Test2::Tools::Spec ':ALL';
# All 'tests' blocks after this declaration will have C<<iso => 1>> by default
spec_defaults tests => (iso => 1);
tests foo => sub { ... }; # isolated
tests foo, {iso => 0}, sub { ... }; # Not isolated
spec_defaults tests => (iso => 0); # Turn it off again
Defaults are inherited by nested describe blocks. You can also override the
defaults for the scope of the describe:
spec_defaults tests => (iso => 1);
describe foo => sub {
spec_defaults tests => (async => 1); # Scoped to this describe and any child describes
tests bar => sub { ... }; # both iso and async
};
tests baz => sub { ... }; # Just iso, no async.
You can apply defaults to any type of blocks:
spec_defaults case => (iso => 1); # All cases are 'iso';
Defaults are not inherited when a builder's return is captured.
spec_defaults tests => (iso => 1);
# Note we are not calling this in void context, that is the key here.
my $d = describe foo => {
tests bar => sub { ... }; # Not iso
};
=head1 EXECUTION ORDER
As each function is encountered it executes, just like any other function. The
@@ -4,7 +4,7 @@ use warnings;

our $VERSION = "0.000014";

our @EXPORT_OK = qw/parse_args current_build build root_build init_root/;
our @EXPORT_OK = qw/parse_args current_build build root_build init_root build_stack/;
use base 'Exporter';

use Test2::Workflow::Build;
@@ -19,6 +19,7 @@ sub parse_args {
my %props;

my $caller = $out{frame} = $input{caller} || caller(defined $input{level} ? $input{level} : 1);
delete @input{qw/caller level/};

for my $arg (@$args) {
if (my $r = ref($arg)) {
@@ -54,7 +55,7 @@ sub parse_args {
die "a codeblock must be provided at $caller->[1] line $caller->[2].\n"
unless $out{code};

return { %props, %out };
return { %props, %out, %input };
}

{
@@ -63,6 +64,7 @@ sub parse_args {

sub root_build { $ROOT_BUILDS{$_[0]} }
sub current_build { @BUILD_STACK ? $BUILD_STACK[-1] : undef }
sub build_stack { @BUILD_STACK }

sub init_root {
my ($pkg, %args) = @_;
@@ -17,7 +17,7 @@ BEGIN {
}

use base 'Test2::Workflow::Task';
use Test2::Util::HashBase @BUILD_FIELDS, qw/events/;
use Test2::Util::HashBase @BUILD_FIELDS, qw/events defaults stack_stop/;

sub init {
my $self = shift;
@@ -28,6 +28,7 @@ sub init {
}

$self->{$_} ||= [] for @BUILD_FIELDS;
$self->{+DEFAULTS} ||= {};
}

for my $field (@BUILD_FIELDS) {

0 comments on commit c6d1442

Please sign in to comment.
You can’t perform that action at this time.