Fourth sub-pass of the S29 plugin-wide terminology scrub: the banned brand phrase
"thought leadership" (FORM A) removed from the remaining surfaces — skills, a config template,
shipped assets, and a test fixture. 8 edits across 6 files. Vocabulary consistent with
S29a-S29c: "thought leadership angle(s)" -> "content angle(s)"; the "Value Test" family ->
"Authority Value Test"; "Standard Thought Leadership Post" -> "Standard Post" (matches the
S29a/S29c "Standard Post Structure" equivalent).
Edits: skills/linkedin-content-creation (3) "Identify Thought Leadership Angles" -> "Content
Angles", "Standard Thought Leadership Post" -> "Standard Post", "The 8 Thought Leadership
Angles" -> "The 8 Content Angles"; skills/linkedin-strategy:176 phase-focus cell "Thought
leadership, cross-platform" -> "Signature content, ..." (avoids the Authority-phase column
echo); config/user-profile.template:35 "Build thought leadership & authority" -> "Build
authority & influence"; assets/checklists/quality-scorecard:136 "Passes thought leadership
test" -> "Passes Authority Value Test"; assets/case-studies/case-study-template:173 "Best for:
Thought leadership" -> "Authority content"; hooks/scripts/__tests__/clipboard-helper.test:61
unicode fixture "Thought leadership" -> "Authority" (emoji + arrow retained; coverage unchanged).
Scope (operator-locked, inherits S29a-S29c): FORM A only. FORM B = 8 untouched -- the 5
buzzword-denylist entries MUST list the banned word ("thought leader"), plus 3 role usages
(linkedin-networking x2, README "niche thought leaders"). The 21 thought-leadership-angles.md
filename pointers deferred to S29e. No anchor links to the changed headers anywhere in the
plugin. Forward-looking docs already clean.
Verify: FORM A in scope = NONE; FORM B unchanged (8); filename pointers unchanged (21);
clipboard-helper test 13/0; gate 81/0/0; counts 29/19/26/6 + v0.5.0 unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016qgzo6rxthw7KuxHjn5vyE
86 lines
2.8 KiB
JavaScript
86 lines
2.8 KiB
JavaScript
import { describe, test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { clipboardAvailable, copyToClipboard } from '../clipboard-helper.mjs';
|
|
|
|
describe('clipboardAvailable', () => {
|
|
test('returns object with available and platform fields', () => {
|
|
const result = clipboardAvailable();
|
|
assert.equal(typeof result.available, 'boolean');
|
|
assert.equal(typeof result.platform, 'string');
|
|
});
|
|
|
|
test('returns available: true on macOS (darwin)', () => {
|
|
if (process.platform !== 'darwin') return;
|
|
const result = clipboardAvailable();
|
|
assert.equal(result.available, true);
|
|
assert.equal(result.platform, 'darwin');
|
|
});
|
|
|
|
test('returns a recognized platform string', () => {
|
|
const result = clipboardAvailable();
|
|
assert.ok(
|
|
['darwin', 'win32', 'linux'].includes(result.platform),
|
|
`Unexpected platform: ${result.platform}`
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('copyToClipboard', () => {
|
|
test('returns object with success and platform fields', () => {
|
|
const result = copyToClipboard('test clipboard text');
|
|
assert.equal(typeof result.success, 'boolean');
|
|
assert.equal(typeof result.platform, 'string');
|
|
});
|
|
|
|
test('copies text successfully on macOS', () => {
|
|
if (process.platform !== 'darwin') return;
|
|
const result = copyToClipboard('clipboard-helper test 2026');
|
|
assert.equal(result.success, true);
|
|
assert.equal(result.platform, 'darwin');
|
|
});
|
|
|
|
test('handles empty string input gracefully', () => {
|
|
const result = copyToClipboard('');
|
|
assert.equal(result.success, true);
|
|
assert.equal(typeof result.platform, 'string');
|
|
});
|
|
|
|
test('handles multiline text', () => {
|
|
const multiline = 'Line 1\nLine 2\nLine 3';
|
|
const result = copyToClipboard(multiline);
|
|
assert.equal(result.success, true);
|
|
});
|
|
|
|
test('handles special characters (quotes, ampersands, backticks)', () => {
|
|
const special = 'He said "hello" & she said \'goodbye\' `code` $VAR';
|
|
const result = copyToClipboard(special);
|
|
assert.equal(result.success, true);
|
|
});
|
|
|
|
test('handles unicode/emoji text', () => {
|
|
const unicode = '🚀 Authority → impact';
|
|
const result = copyToClipboard(unicode);
|
|
assert.equal(result.success, true);
|
|
});
|
|
|
|
test('never throws — always returns a result object', () => {
|
|
assert.doesNotThrow(() => copyToClipboard(null));
|
|
assert.doesNotThrow(() => copyToClipboard(undefined));
|
|
assert.doesNotThrow(() => copyToClipboard(123));
|
|
});
|
|
|
|
test('returns success: false for non-string input', () => {
|
|
const result = copyToClipboard(null);
|
|
assert.equal(result.success, false);
|
|
});
|
|
});
|
|
|
|
describe('module exports', () => {
|
|
test('exports clipboardAvailable as a function', () => {
|
|
assert.equal(typeof clipboardAvailable, 'function');
|
|
});
|
|
|
|
test('exports copyToClipboard as a function', () => {
|
|
assert.equal(typeof copyToClipboard, 'function');
|
|
});
|
|
});
|