Airlock
view release on metacpan or search on metacpan
docs/superpowers/plans/2026-10-02-airlock-phase-1.md view on Meta::CPAN
sub request {
my ( $self, $method, $url, $args ) = @_;
my $body = $args->{content} // '';
my ( $path ) = $url =~ m{\Ahttps?://[^/]+(/[^?]*)};
push @{ $self->seen }, { method => $method, url => $url, body => $body, headers => $args->{headers} };
CORE::open( my $input, '<', \$body ) or die $!;
my $psgi = $self->app->( {
REQUEST_METHOD => $method,
PATH_INFO => $path,
CONTENT_TYPE => $args->{headers}{'content-type'},
CONTENT_LENGTH => length $body,
REMOTE_ADDR => '127.0.0.1',
HTTP_USER_AGENT => 'local-ua',
'psgi.input' => $input
} );
return {
success => $psgi->[0] < 400 ? 1 : '',
status => $psgi->[0],
reason => 'local',
content => join( '', @{ $psgi->[2] } ),
docs/superpowers/plans/2026-10-02-airlock-phase-1.md view on Meta::CPAN
return ( $t, $client, \@slept, $ua );
}
subtest 'start' => sub {
my ( $t, $client, undef, $ua ) = fixture();
my $start = $client->start;
like( $start->{device_code}, qr/\A[0-9a-f]{64}\z/, 'device_code' );
like( $start->{user_code}, qr/\A\w{4}-\w{4}\z/, 'user_code' );
is( $t->row( $start->{device_code} )->{scope}, 'read write', 'the scope arrived' );
is( $ua->seen->[0]{headers}{accept}, 'application/json', 'asks for JSON' );
like( $ua->seen->[0]{headers}{'content-type'}, qr{\Aapplication/x-www-form-urlencoded}, 'sends a form' );
my ( undef, $unknown ) = fixture( client_id => 'nope' );
ok( !eval { $unknown->start; 1 }, 'an unknown client croaks' );
like( $@, qr/start failed: invalid_client/, 'with the server error' );
};
subtest 'login: approved while polling' => sub {
my ( $t, $client, $slept ) = fixture(
after_sleep => sub {
my ( $t, $polls ) = @_;
t/70-client.t view on Meta::CPAN
sub request {
my ( $self, $method, $url, $args ) = @_;
my $body = $args->{content} // '';
my ( $path ) = $url =~ m{\Ahttps?://[^/]+(/[^?]*)};
push @{ $self->seen }, { method => $method, url => $url, body => $body, headers => $args->{headers} };
CORE::open( my $input, '<', \$body ) or die $!;
my $psgi = $self->app->( {
REQUEST_METHOD => $method,
PATH_INFO => $path,
CONTENT_TYPE => $args->{headers}{'content-type'},
CONTENT_LENGTH => length $body,
REMOTE_ADDR => '127.0.0.1',
HTTP_USER_AGENT => 'local-ua',
'psgi.input' => $input
} );
return {
success => $psgi->[0] < 400 ? 1 : '',
status => $psgi->[0],
reason => 'local',
content => join( '', @{ $psgi->[2] } ),
t/70-client.t view on Meta::CPAN
return ( $t, $client, \@slept, $ua );
}
subtest 'start' => sub {
my ( $t, $client, undef, $ua ) = fixture();
my $start = $client->start;
like( $start->{device_code}, qr/\A[0-9a-f]{64}\z/, 'device_code' );
like( $start->{user_code}, qr/\A\w{4}-\w{4}\z/, 'user_code' );
is( $t->row( $start->{device_code} )->{scope}, 'read write', 'the scope arrived' );
is( $ua->seen->[0]{headers}{accept}, 'application/json', 'asks for JSON' );
like( $ua->seen->[0]{headers}{'content-type'}, qr{\Aapplication/x-www-form-urlencoded}, 'sends a form' );
my ( undef, $unknown ) = fixture( client_id => 'nope' );
ok( !eval { $unknown->start; 1 }, 'an unknown client croaks' );
like( $@, qr/start failed: invalid_client/, 'with the server error' );
};
subtest 'login: approved while polling' => sub {
my ( $t, $client, $slept ) = fixture(
after_sleep => sub {
my ( $t, $polls ) = @_;
( run in 1.407 second using v1.01-cache-2.11-cpan-03fa5a55a2b )