Developer-Dashboard
view release on metacpan or search on metacpan
t/24-api-dashboard-tabs-playwright.t view on Meta::CPAN
my ( $method, $target ) = split /\s+/, $request_line;
my %headers;
while ( my $line = <$client> ) {
$line =~ s/\r?\n\z//;
last if $line eq '';
my ( $key, $value ) = split /:\s*/, $line, 2;
$headers{ lc($key) } = defined $value ? $value : '';
}
my $content_length = $headers{'content-length'} || 0;
my $body = '';
read( $client, $body, $content_length ) if $content_length > 0;
my $uri = URI->new( 'http://127.0.0.1' . ( $target || '/' ) );
my ( $status, $reason, $content_type, $payload ) = ( 404, 'Not Found', 'application/json', json_encode( { error => 'not found' } ) );
if ( $uri->path eq '/json' ) {
my $name = defined scalar $uri->query_param('name') ? scalar $uri->query_param('name') : '';
$status = 200;
$reason = 'OK';
$content_type = 'application/json';
$payload = json_encode(
{
ok => 1,
method => $method || 'GET',
name => $name,
path => $uri->path,
}
);
}
elsif ( $uri->path eq '/image' ) {
$status = 200;
$reason = 'OK';
$content_type = 'image/png';
$payload = $png;
}
my $response = join(
"\r\n",
"HTTP/1.1 $status $reason",
"Content-Type: $content_type",
'Connection: close',
'Content-Length: ' . length($payload),
'',
''
);
print {$client} $response;
print {$client} $payload;
close $client;
}
exit 0;
}
return $pid;
}
# _playwright_script()
# Purpose: return the embedded Node.js Playwright tab-layout flow used by this Perl test.
# Input: none.
# Output: JavaScript source text string.
sub _playwright_script {
return <<'JAVASCRIPT';
const { chromium } = require(process.env.PLAYWRIGHT_DIR);
async function main() {
const browser = await chromium.launch({
executablePath: process.env.CHROMIUM_BIN,
headless: true,
args: ['--no-sandbox', '--disable-dev-shm-usage'],
});
const consoleErrors = [];
try {
const context = await browser.newContext({
viewport: { width: 960, height: 900 },
});
const page = await context.newPage();
page.on('console', (message) => {
if (message.type() !== 'error') return;
const text = message.text();
if (/favicon\.ico/i.test(text)) return;
if (text === 'Failed to load resource: the server responded with a status of 404 (Not Found)') return;
consoleErrors.push(text);
});
page.on('pageerror', (error) => {
consoleErrors.push(error && error.stack ? error.stack : String(error));
});
await page.goto(process.env.DASHBOARD_URL, { waitUntil: 'domcontentloaded' });
await page.getByRole('tab', { name: 'Collections' }).waitFor();
await page.getByRole('tab', { name: 'Workspace' }).waitFor();
await page.getByRole('tab', { name: 'Collections' }).click();
await page.waitForFunction(() => {
const collections = document.querySelector('[role="tabpanel"][data-api-shell-panel="collections"]');
const workspace = document.querySelector('[role="tabpanel"][data-api-shell-panel="workspace"]');
if (!collections || !workspace) return false;
return !collections.hidden && workspace.hidden;
});
await page.getByRole('tab', { name: 'Workspace' }).click();
await page.waitForFunction(() => {
const collections = document.querySelector('[role="tabpanel"][data-api-shell-panel="collections"]');
const workspace = document.querySelector('[role="tabpanel"][data-api-shell-panel="workspace"]');
const requestName = document.querySelector('#api-request-name');
if (!collections || !workspace || !requestName) return false;
return collections.hidden && !workspace.hidden && requestName.offsetParent !== null;
});
await page.waitForFunction(() => {
const tabs = Array.from(document.querySelectorAll('.api-collection-tab')).map((node) => node.textContent.trim());
return tabs.includes('Tabbed Collection') && tabs.includes('Second Tabbed Collection');
});
const shellTabStyle = await page.$eval('#api-shell-tab-workspace', (node) => {
const style = window.getComputedStyle(node);
return {
radius: style.borderTopLeftRadius,
bottomWidth: style.borderBottomWidth,
};
});
( run in 0.680 second using v1.01-cache-2.11-cpan-39bf76dae61 )