diff options
Diffstat (limited to '')
-rw-r--r-- | test/t/salsa.pm | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/test/t/salsa.pm b/test/t/salsa.pm new file mode 100644 index 0000000..800d1e5 --- /dev/null +++ b/test/t/salsa.pm @@ -0,0 +1,226 @@ +{ + + package MockRESTClient; + use URI; + use Moo; + extends 'GitLab::API::v4::RESTClient'; + + has _mocks => ( + is => 'ro', + default => sub { [] }, + init_arg => undef, + ); + + sub mock_endpoints { + my $self = shift; + + while (@_) { + my $method = shift; + my $path_re = shift; + my $sub = shift; + + push @{ $self->_mocks() }, [$method, $path_re, $sub]; + } + + return; + } + + sub _http_tiny_request { + my ($self, $req_method, $req) = @_; + + die "req_method may only be 'request' at this time" + if $req_method ne 'request'; + + my ($method, $url, $options) = @$req; + + my $path = URI->new($url)->path(); + $path =~ s{^.*api/v4/}{}; + + foreach my $mock (@{ $self->_mocks() }) { + my ($handler_method, $path_re, $sub) = @$mock; + + next if $method ne $handler_method; + + my @captures = ($path =~ $path_re); + next if !@captures; # No captures still returns a 1. + + my ($status, $content) + = $sub->([$method, $url, $options], @captures); + $content = JSON::to_json($content) if ref $content; + + return { + status => $status, + success => ($status =~ m{^2\d\d$}) ? 1 : 0, + defined($content) ? (content => $content) : (), + }; + } + + die "No mock endpoint matched the $method '$path' endpoint"; + } +} + +sub api { + my ($gitdir) = @_; + my @users = ({ + id => 11, + username => 'me', + name => 'Me', + email => 'me@debian.org', + state => 'active' + }); + my @teams = ({ + id => 2099, + name => 'Debian JavaScript Maintainers', + full_name => 'Debian JavaScript Maintainers', + full_path => 'js-team', + }); + my @projects; + my $next_id = 1; + + my $api = GitLab::API::v4->new( + url => 'https://example.com/api/v4', + rest_client_class => 'MockRESTClient', + ); + + $api->rest_client->mock_endpoints( + GET => qr{^user$} => sub { 200, $users[0] }, + GET => qr{^users$} => sub { 200, \@users }, + POST => qr{^users$} => sub { + my ($req) = @_; + my $user = decode_json($req->[2]->{content}); + $user->{id} = $next_id; + $next_id++; + push @users, $user; + return 204; + }, + GET => qr{^users?/(\d+)$} => sub { + my ($req, $id) = @_; + foreach my $user (@users) { + next if $user->{id} != $id; + return 200, $user; + } + return 404; + }, + GET => qr{^users/(\D+)$} => sub { + my ($req, $id) = @_; + foreach my $user (@users) { + next if $user->{username} != $id; + return 200, $user; + } + return 404; + }, + GET => qr{^groups$} => sub { + 200, \@teams; + }, + GET => qr{^groups/([^/]+)$} => sub { + my ($req, $name) = @_; + foreach my $team (@teams) { + next if $team->{full_path} ne $name; + return 200, $team; + } + return 404; + }, + PUT => qr{^users/(\d+)$} => sub { + my ($req, $id) = @_; + my $data = decode_json($req->[2]->{content}); + foreach my $user (@users) { + next if $user->{id} != $id; + %$user = (%$user, %$data,); + return 204; + } + return 404; + }, + DELETE => qr{^users/(\d+)$} => sub { + my ($req, $id) = @_; + my @new; + foreach my $user (@users) { + next if $user->{id} == $id; + push @new, $user; + } + return 404 if @new == @users; + @users = @new; + return 204; + }, + # Projects + POST => qr{^projects$} => sub { + my $content = JSON::from_json($_[0]->[2]->{content}); + mkdir "$gitdir/me/$content->{path}"; + $ENV{"GIT_CONFIG_NOGLOBAL"} = 1; + print +`cd $gitdir/me/$content->{path};git init;git config receive.denyCurrentBranch ignore;cd -`; + $content->{id} = scalar @projects + 1; + $content->{hooks} = []; + $content->{namespace} = { + kind => 'user', + id => 11, + name => 'me', + }; + $content->{path_with_namespace} = 'me/' . $content->{path}; + $content->{web_url} = 'http://no.org/me/' . $content->{path}; + push @projects, $content; + return 200, $content; + }, + GET => qr{^projects/(\d+)/hooks} => sub { + my ($req, $id) = @_; + my $res = eval { $projects[$id - 1]->{hooks} }; + return ($res ? (200, $res) : (404)); + }, + GET => qr{^projects/(\d+)/services/(\w+)} => sub { + my ($req, $id, $service) = @_; + return 404; + }, + GET => qr{^projects$} => sub { + my ($req) = @_; + return (200, \@projects) unless ($req->[1] =~ /search=([^&]+)/); + my $str = $1; + my @res; + foreach (@projects) { + if ($_->{name} =~ /\Q$str\E/) { + push @res, $_; + } + } + return 200, \@res; + }, + GET => qr{^projects/([a-z]+)(?:%2F(\w+))*$} => sub { + my ($req, @path) = @_; + my $repo = pop @path; + my $path = join '/', @path; + foreach (@projects) { + if ($_->{namespace}->{name} eq $path and $_->{path} eq $repo) { + return 200, $_; + } + } + return 404; + }, + GET => qr{^projects/(\d+)$} => sub { + my ($req, $id) = @_; + return 404 unless ($_ = $projects[$id - 1]); + return 200, $_; + }, + PUT => qr{^projects/(\d+)} => sub { + my ($req, $id) = @_; + return 404 unless ($_ = $projects[$id - 1]); + my $content = JSON::from_json($req->[2]->{content}); + foreach my $k (keys %$content) { + $_->{$k} = $content->{$k}; + } + return 200, {}; + }, + POST => qr{^projects/(\d+)/hooks} => sub { + my ($req, $id) = @_; + return 404 unless ($_ = $projects[$id - 1]); + my $content = JSON::from_json($req->[2]->{content}); + push @{ $_->{hooks} }, $content; + return 200, {}; + }, + POST => qr{^projects/(\d+)/repository/branches} => sub { + return 200, {}; + }, + DELETE => qr{^projects/(\d+)/repository/branches/([\w\-\.]+)$} => sub { + return 200, {}; + }, + ); + return $api; +} + +1; |