moh: music-on-hold classes, uploads, pickers for users and queues
/api/moh-classes: create (slug, not "default"), delete (409 while an extension or queue uses it), add/play/remove files. Files are 8 kHz wav in MOH_DIR/<class>/ and sound_files rows of kind moh. Extensions and queues may only pick default or an existing class. Two things found with real calls, written back into 03 and 04: - An empty class plays silence on Asterisk 24. Only classes with music are rendered, so a channel asking for an empty one gets default. - The generator reloads only changed files, and a file upload changes no config (except a class's first/last). The route sends moh reload after every file change. Web: a Music on hold section on Sounds & music, and a select of sets in the user drawer's Phone tab and the queue form. load-golden makes the class folders like the api does. Golden case queue gains two classes. e2e m8-t5: set made in the UI, upload listed by Asterisk, a queue caller hears it, a user's moh_suggest, delete refused while used, an emptied set falls back to default. Task: M8-T5
This commit is contained in:
1 parent
e95271e694
commit
b8ff6e3386
34 files changed
+840
-21
No files matched your search
@@ -4,7 +4,15 @@
|
||||
// Needs Docker and a built image (ASTERISK_IMAGE, default "selfphoneng-asterisk").
|
||||
// Usage: pnpm test:asterisk [case ...]
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { cpSync, existsSync, mkdtempSync, readdirSync, readFileSync, rmSync } from 'node:fs';
|
||||
import {
|
||||
cpSync,
|
||||
existsSync,
|
||||
mkdirSync,
|
||||
mkdtempSync,
|
||||
readdirSync,
|
||||
readFileSync,
|
||||
rmSync,
|
||||
} from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
@@ -40,6 +48,11 @@ async function check(name) {
|
||||
const tmp = mkdtempSync(join(tmpdir(), `sp-golden-${name}-`));
|
||||
cpSync(join(GOLDEN, name, 'expected'), tmp, { recursive: true });
|
||||
const problems = [];
|
||||
// The api makes each MOH class's folder when the class is created (routes/moh.ts); do the same.
|
||||
const moh = mkdtempSync(join(tmpdir(), `sp-golden-moh-`));
|
||||
const mohConf = readFileSync(join(tmp, 'musiconhold_selfphoneng.conf'), 'utf8');
|
||||
for (const [, d] of mohConf.matchAll(/^directory = \/var\/lib\/asterisk\/moh\/(.+)$/gm))
|
||||
mkdirSync(join(moh, d));
|
||||
const run = docker(
|
||||
'run',
|
||||
'-d',
|
||||
@@ -50,6 +63,8 @@ async function check(name) {
|
||||
'AMI_SECRET=golden-test-secret',
|
||||
'-v',
|
||||
`${tmp}:/etc/asterisk/selfphoneng`,
|
||||
'-v',
|
||||
`${moh}:/var/lib/asterisk/moh`,
|
||||
IMAGE,
|
||||
);
|
||||
if (!run.ok) throw new Error(`docker run failed: ${run.out}`);
|
||||
@@ -90,6 +105,7 @@ async function check(name) {
|
||||
} finally {
|
||||
docker('rm', '-f', NAME);
|
||||
rmSync(tmp, { recursive: true, force: true });
|
||||
rmSync(moh, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user