diff --git a/core/cli/run_safety_test.go b/core/cli/run_safety_test.go
index 21bcd3d87a94..1155e23e0167 100644
--- a/core/cli/run_safety_test.go
+++ b/core/cli/run_safety_test.go
@@ -88,7 +88,7 @@ var _ = Describe("requireAuthOrTrustedBind", func() {
})
It("rejects public IPv6", func() {
- Expect(requireAuthOrTrustedBind("[2001:db8::1]:8080", false, false)).To(HaveOccurred())
+ Expect(requireAuthOrTrustedBind("[2606:4700:4700::1111]:8080", false, false)).To(HaveOccurred())
})
})
diff --git a/core/http/react-ui/e2e/diarization-profiles.spec.js b/core/http/react-ui/e2e/diarization-profiles.spec.js
index 2bb00ea4950f..3adc70fba027 100644
--- a/core/http/react-ui/e2e/diarization-profiles.spec.js
+++ b/core/http/react-ui/e2e/diarization-profiles.spec.js
@@ -27,8 +27,9 @@ async function setup(page, permission = true, diarizationPermission = true) {
return route.fulfill({ json: data })
})
await page.route('**/v1/audio/diarization', route => route.fulfill({ json: result }))
- // Studio is an add-on. Installed after the catch-all above, so its routes win.
- await installStudioAddons(page, { ids: ['studio'] })
+ // Studio and Voice are add-ons. Installed after the catch-all above, so their routes win.
+ // The remembered-voices link opens the Voice add-on page.
+ await installStudioAddons(page, { ids: ['studio', 'voice'] })
await page.goto('/app/diarization')
if (!diarizationPermission) return
await expect(page.getByRole('button', { name: 'diarizer', exact: true })).toBeVisible()
diff --git a/core/http/react-ui/e2e/studio-addon.js b/core/http/react-ui/e2e/studio-addon.js
index e2efd995ab89..3565355e9896 100644
--- a/core/http/react-ui/e2e/studio-addon.js
+++ b/core/http/react-ui/e2e/studio-addon.js
@@ -24,9 +24,9 @@ export async function buildAddonBundles(ids) {
for (const id of ids) await import(path.join(addons, id, 'ui/build.mjs')).then(m => m.build())
}
-// The add-ons the specs serve from their build output: Studio and Talk through
-// installStudioAddons, Face and Fine-tuning through their own routes.
-export async function buildStudioAddons(ids = ['studio', 'talk', 'face', 'fine-tuning']) {
+// The add-ons the specs serve from their build output: Studio, Talk and Voice
+// through installStudioAddons, Face and Fine-tuning through their own routes.
+export async function buildStudioAddons(ids = ['studio', 'talk', 'voice', 'face', 'fine-tuning']) {
await buildAddonBundles(ids)
process.env[BUILT] = '1'
}
@@ -55,7 +55,7 @@ export function packagedApp(id, over = {}) {
// Returns the state of mockAddons.
export async function installStudioAddons(page, { ids = ['studio', 'talk'], ...options } = {}) {
const dirs = await Promise.all(ids.map(build))
- await page.route(/\/api\/addons\/(studio|talk)\/assets\//, route => {
+ await page.route(/\/api\/addons\/(studio|talk|voice)\/assets\//, route => {
const parts = new URL(route.request().url()).pathname.split('/')
const id = parts[3]
const file = parts.slice(6).join('/')
diff --git a/core/http/react-ui/src/addons/AddonRoute.jsx b/core/http/react-ui/src/addons/AddonRoute.jsx
index d005b95c6202..5bf1979ae825 100644
--- a/core/http/react-ui/src/addons/AddonRoute.jsx
+++ b/core/http/react-ui/src/addons/AddonRoute.jsx
@@ -181,6 +181,7 @@ export default function AddonRoute() {
{t('apps.start')}
)}
+ {extra}
{outcome && outcome.outcome && describeOutcome(outcome.outcome, t, outcome.error) && (
{describeOutcome(outcome.outcome, t, outcome.error)}
)}
diff --git a/core/http/react-ui/src/components/addons/installFlow.js b/core/http/react-ui/src/components/addons/installAndTurnOn.js
similarity index 100%
rename from core/http/react-ui/src/components/addons/installFlow.js
rename to core/http/react-ui/src/components/addons/installAndTurnOn.js
diff --git a/core/http/react-ui/src/components/addons/useAddonActions.js b/core/http/react-ui/src/components/addons/useAddonActions.js
index cfdc8d18a06b..e94d0fbd5606 100644
--- a/core/http/react-ui/src/components/addons/useAddonActions.js
+++ b/core/http/react-ui/src/components/addons/useAddonActions.js
@@ -1,7 +1,7 @@
import { useCallback, useEffect, useRef, useState } from 'react'
import { createActionBook, effectOutcome } from './actionBook'
import { runLifecycle, settleOperation } from './lifecycleFlow'
-import { runInstallAndTurnOn } from './installFlow'
+import { runInstallAndTurnOn } from './installAndTurnOn'
// Runs user actions that change an add-on, one operation identity per action.
//
diff --git a/core/http/react-ui/tests/unit/addons.test.mjs b/core/http/react-ui/tests/unit/addons.test.mjs
index 9a572a350f54..10dc708c4f78 100644
--- a/core/http/react-ui/tests/unit/addons.test.mjs
+++ b/core/http/react-ui/tests/unit/addons.test.mjs
@@ -17,7 +17,7 @@ import { runLifecycle, settleOperation } from '../../src/components/addons/lifec
import { createActionBook, effectOutcome } from '../../src/components/addons/actionBook.js'
import { describeError, describeOutcome } from '../../src/components/addons/errors.js'
import { backendState, libraryOrigin, shortDigest as shortBackendDigest } from '../../src/utils/backendRows.js'
-import { runInstallAndTurnOn } from '../../src/components/addons/installFlow.js'
+import { runInstallAndTurnOn } from '../../src/components/addons/installAndTurnOn.js'
import { installSteps, STEP_ORDER } from '../../src/components/addons/installSteps.js'
const json = (status, body) => ({ ok: status >= 200 && status < 300, status, json: async () => body })