CtrlK
BlogDocsLog inGet started
Tessl Logo

ai-ecoverse/advanced-skills

Quarantined high-risk skills (browser session capture, WebSocket interception) for Slack and Microsoft Teams. Install only after reviewing the security implications.

76

Quality

96%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide
SecuritybySnyk

Low

Low-risk findings worth noting

Overview
Quality
Evals
Security
Files

argv.test.jsskills/slack/tests/

// argv.test.js — tst suite for skills/slack/scripts/argv.js
//
// Run from skills/slack/:
//   tst tests/argv.test.js
//
// This file imports `tst` and a single relative module; no node:test, no fs,
// no path, no sliccy:* — it runs in the SLICC test realm as-is (CLAUDE.md §16).

import test, { is, ok, throws } from 'tst';
import * as argvMod from '../scripts/argv.js';

const { BOOL_FLAGS, parseArgv, parseList } = argvMod.default || argvMod;

// ─── parseArgv: bare boolean flags ───────────────────────────────────────────

test('bare --confirm is boolean true', () => {
  const r = parseArgv(['set-single', 'U1', '--confirm']);
  is(r.flags.confirm, true);
});

test('absent --confirm is undefined (not false)', () => {
  const r = parseArgv(['set-single', 'U1']);
  is(r.flags.confirm, undefined);
});

test('bare --json is boolean true', () => {
  is(parseArgv(['status', '--json']).flags.json, true);
});

// ─── parseArgv: --name=value bool normalisation ───────────────────────────────

test('--confirm=false stores boolean false', () => {
  is(parseArgv(['x', '--confirm=false']).flags.confirm, false);
});

test('--confirm=0 stores boolean false', () => {
  is(parseArgv(['x', '--confirm=0']).flags.confirm, false);
});

test('--confirm=no stores boolean false', () => {
  is(parseArgv(['x', '--confirm=no']).flags.confirm, false);
});

test('--confirm=off stores boolean false', () => {
  is(parseArgv(['x', '--confirm=off']).flags.confirm, false);
});

test('--confirm=FALSE stores boolean false (case-insensitive)', () => {
  is(parseArgv(['x', '--confirm=FALSE']).flags.confirm, false);
});

test('--confirm= (empty string) stores boolean false', () => {
  is(parseArgv(['x', '--confirm=']).flags.confirm, false);
});

test('--confirm=true stores boolean true', () => {
  is(parseArgv(['x', '--confirm=true']).flags.confirm, true);
});

test('--confirm=1 stores boolean true', () => {
  is(parseArgv(['x', '--confirm=1']).flags.confirm, true);
});

test('--confirm=yes stores boolean true', () => {
  is(parseArgv(['x', '--confirm=yes']).flags.confirm, true);
});

test('--confirm=on stores boolean true', () => {
  is(parseArgv(['x', '--confirm=on']).flags.confirm, true);
});

test('--confirm=TRUE stores boolean true (case-insensitive)', () => {
  is(parseArgv(['x', '--confirm=TRUE']).flags.confirm, true);
});

// ─── parseArgv: typo is fatal ─────────────────────────────────────────────────

test('--confirm=fasle (typo) is a fatal error', () => {
  // process.exit(1) throws in the SLICC sandbox; throws() catches it.
  throws(() => parseArgv(['x', '--confirm=fasle']));
});

test('--confirm=maybe (unrecognised value) is a fatal error', () => {
  throws(() => parseArgv(['x', '--confirm=maybe']));
});

// ─── parseArgv: non-boolean flags keep string values ─────────────────────────

test('--channel=false keeps the string "false" (not a bool flag)', () => {
  is(parseArgv(['x', '--channel=false']).flags.channel, 'false');
});

test('--ws=T06DUTYDQ keeps the string', () => {
  is(parseArgv(['x', '--ws=T06DUTYDQ']).flags.ws, 'T06DUTYDQ');
});

// ─── parseArgv: -- stops flag parsing ────────────────────────────────────────

test('-- stops flag parsing', () => {
  const r = parseArgv(['set-single', '--', '--confirm']);
  is(r.flags.confirm, undefined);
  ok(r.positional.includes('--confirm'));
});

test('-- passes remaining tokens as positionals', () => {
  const r = parseArgv(['cmd', '--ws=T1', '--', 'a', 'b']);
  is(r.positional[1], 'a');
  is(r.positional[2], 'b');
});

// ─── parseArgv: positionals and mixed ordering ───────────────────────────────

test('positional words are collected in order', () => {
  const r = parseArgv(['set-single', 'U12345', '--ws=T1', '--channel=C2']);
  is(r.positional[0], 'set-single');
  is(r.positional[1], 'U12345');
});

test('BOOL_FLAGS set contains confirm, json, help, h, allow-deletions', () => {
  ok(BOOL_FLAGS.has('confirm'));
  ok(BOOL_FLAGS.has('json'));
  ok(BOOL_FLAGS.has('help'));
  ok(BOOL_FLAGS.has('h'));
  ok(BOOL_FLAGS.has('allow-deletions'));
});

test('--session and --no-session are booleans and never swallow the app id', () => {
  ok(BOOL_FLAGS.has('session'));
  ok(BOOL_FLAGS.has('no-session'));
  const r = parseArgv(['app', 'show', '--session', 'A0123456789']);
  is(r.flags.session, true);
  is(r.positional, ['app', 'show', 'A0123456789']);
  const n = parseArgv(['app', 'show', '--no-session', 'A0123456789']);
  is(n.flags['no-session'], true);
  is(n.positional[2], 'A0123456789');
});

// ─── parseList ────────────────────────────────────────────────────────────────

test('parseList splits on commas', () => {
  const r = parseList('channels:read,chat:write', 'scopes');
  is(r.length, 2);
  is(r[0], 'channels:read');
  is(r[1], 'chat:write');
});

test('parseList splits on whitespace', () => {
  const r = parseList('channels:read chat:write', 'scopes');
  is(r.length, 2);
  is(r[0], 'channels:read');
});

test('parseList splits on comma-and-space', () => {
  const r = parseList('a, b, c', 'items');
  is(r.length, 3);
  is(r[2], 'c');
});

test('parseList deduplicates', () => {
  is(parseList('a,a,b', 'x').length, 2);
});

test('parseList returns [] for undefined', () => {
  is(parseList(undefined, 'x').length, 0);
});

test('parseList with valueless flag (true) is fatal', () => {
  // raw === true means the flag was passed without a value; process.exit(1) throws.
  throws(() => parseList(true, 'scopes'));
});

test('--allow-shared is boolean and never swallows the next positional', () => {
  const r = parseArgv(['channel-archive', '--allow-shared', 'C04633RSEDU']);
  is(r.flags['allow-shared'], true);
  is(r.positional.join(','), 'channel-archive,C04633RSEDU');
  is(parseArgv(['x', '--allow-shared=false']).flags['allow-shared'], false);
});

// ─── jsonInvocation (JSON-mode detection when parseArgv itself throws) ───────

const { jsonInvocation } = argvMod.default || argvMod;
const ARCH = ['channel-archive', 'channel-unarchive'];

test('jsonInvocation: finds a --json channel-archive call and its channel id', () => {
  const r = jsonInvocation(['channel-archive', 'C04633RSEDU', '--allow-shared=maybe', '--json'], ARCH);
  is(r.command, 'channel-archive');
  is(r.channelId, 'C04633RSEDU');
});

test('jsonInvocation: --json=true counts, globals before the command are skipped', () => {
  const r = jsonInvocation(['--ws', 'T0385CHDU9E', 'channel-unarchive', 'C0634KMGW2G', '--json=true'], ARCH);
  is(r.command, 'channel-unarchive');
  is(r.channelId, 'C0634KMGW2G');
});

test('jsonInvocation: null without --json, for other commands, or for --json=garbage', () => {
  is(jsonInvocation(['channel-archive', 'C1', '--allow-shared=maybe'], ARCH), null);
  is(jsonInvocation(['eg-status', 'U1', '--json'], ARCH), null);
  is(jsonInvocation(['channel-archive', 'C04633RSEDU', '--json=maybe'], ARCH), null);
  is(jsonInvocation(['channel-archive', '--json'], ARCH).channelId, null);
});

tile.json