mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +00:00
BigBlueButton is WebRTC (SRTP/UDP with ICE/STUN) which Tor cannot carry. Guard the role's core include on the resolved Keycloak domain not being an onion (alongside the existing run_once guard), disable the co-installed cloud_bbb Nextcloud app on onion at runtime, and skip the BBB Playwright specs on onion targets. Relax the run_once schema test (test_service_core_first_task_run_once) to accept a when-list that contains the run_once guard, so a role can add extra include conditions while staying protected against duplicate execution. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
79 lines
3.4 KiB
JavaScript
79 lines
3.4 KiB
JavaScript
const { test, expect } = require("@playwright/test");
|
|
const { resolveTimeout, isOnionTarget } = require("../timeouts");
|
|
const { skipUnlessAddonEnabled } = require("../addon-gating");
|
|
const shared = require("../_shared");
|
|
const { gotoOnion } = require("../personas");
|
|
|
|
test.use({ ignoreHTTPSErrors: true });
|
|
|
|
test("bbb addon: cloud_bbb app route renders its own UI and is coupled to the partner server", async ({ browser }) => {
|
|
skipUnlessAddonEnabled("bbb");
|
|
test.skip(isOnionTarget(), "BigBlueButton is WebRTC (UDP/ICE); Tor carries only TCP, so the app is disabled on an onion node");
|
|
test.setTimeout(resolveTimeout(120_000));
|
|
|
|
const context = await browser.newContext({ ignoreHTTPSErrors: true });
|
|
const page = await context.newPage();
|
|
|
|
try {
|
|
await shared.loginToStandaloneNextcloud(page);
|
|
|
|
const appUrl = new URL("apps/bbb/", shared.env.nextcloudBaseUrl).toString();
|
|
await gotoOnion(page, appUrl, { waitUntil: "commit", timeout: resolveTimeout(60_000) });
|
|
await shared.dismissBlockingNextcloudModals(page, page);
|
|
|
|
const appContainer = page.locator(
|
|
"#app-content, #app-content-vue, #content, #content-vue"
|
|
);
|
|
await expect(
|
|
appContainer.first(),
|
|
"the cloud_bbb app shell must render at /apps/bbb/ (the app is installed and enabled)"
|
|
).toBeVisible({ timeout: resolveTimeout(60_000) });
|
|
|
|
const bbbAppSurface = page.locator(
|
|
"#bbb, .app-bbb, [id^='bbb'], a[href*='/apps/bbb']"
|
|
);
|
|
await expect(
|
|
bbbAppSurface.first(),
|
|
"the cloud_bbb app's own UI surface (its room-management view / active app menu entry) must render, so a disabled or broken bbb app fails"
|
|
).toBeVisible({ timeout: resolveTimeout(60_000) });
|
|
|
|
await gotoOnion(page,
|
|
new URL("settings/admin/additional", shared.env.nextcloudBaseUrl).toString(),
|
|
{ waitUntil: "domcontentloaded", timeout: resolveTimeout(60_000) }
|
|
);
|
|
await shared.dismissBlockingNextcloudModals(page, page);
|
|
|
|
const bbbSection = page.locator("#bbb-settings");
|
|
await expect(
|
|
bbbSection.first(),
|
|
"the cloud_bbb admin settings section (#bbb-settings) must render on the additional admin page, proving the bbb app is enabled"
|
|
).toBeVisible({ timeout: resolveTimeout(60_000) });
|
|
|
|
const apiUrlField = bbbSection.locator("#bbb-api input[name='api.url'], input[name='api.url']");
|
|
await expect(
|
|
apiUrlField.first(),
|
|
"the BigBlueButton (bbb) admin settings section must expose the api.url field"
|
|
).toBeVisible({ timeout: resolveTimeout(60_000) });
|
|
|
|
const configuredUrl = ((await apiUrlField.first().inputValue().catch(() => "")) || "").trim();
|
|
expect(
|
|
configuredUrl.length,
|
|
"the bbb api.url field must be populated from config:app:set so the BigBlueButton partner endpoint is wired"
|
|
).toBeGreaterThan(0);
|
|
|
|
expect(
|
|
configuredUrl,
|
|
"the bbb api.url must be a valid https URL pointing at the BigBlueButton API mount (the partner base URL + '/bigbluebutton/' API suffix)"
|
|
).toMatch(/^https:\/\/.+\/bigbluebutton\/?$/);
|
|
|
|
const apiSecretField = bbbSection.locator("#bbb-api input[name='api.secret'], input[name='api.secret']");
|
|
await expect(
|
|
apiSecretField.first(),
|
|
"the bbb settings must expose the api.secret field; together with api.url it forms the partner coupling written via config:app:set"
|
|
).toBeAttached({ timeout: resolveTimeout(30_000) });
|
|
} finally {
|
|
await page.close().catch(() => {});
|
|
await context.close().catch(() => {});
|
|
}
|
|
});
|