safeword 0.2.4 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/check-3NGQ4NR5.js +129 -0
- package/dist/check-3NGQ4NR5.js.map +1 -0
- package/dist/chunk-2XWIUEQK.js +190 -0
- package/dist/chunk-2XWIUEQK.js.map +1 -0
- package/dist/chunk-GZRQL3SX.js +146 -0
- package/dist/chunk-GZRQL3SX.js.map +1 -0
- package/dist/chunk-ORQHKDT2.js +10 -0
- package/dist/chunk-ORQHKDT2.js.map +1 -0
- package/dist/chunk-W66Z3C5H.js +21 -0
- package/dist/chunk-W66Z3C5H.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +34 -0
- package/dist/cli.js.map +1 -0
- package/dist/diff-Y6QTAW4O.js +166 -0
- package/dist/diff-Y6QTAW4O.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/reset-3ACTIYYE.js +143 -0
- package/dist/reset-3ACTIYYE.js.map +1 -0
- package/dist/setup-RR4M334C.js +266 -0
- package/dist/setup-RR4M334C.js.map +1 -0
- package/dist/upgrade-6AR3DHUV.js +134 -0
- package/dist/upgrade-6AR3DHUV.js.map +1 -0
- package/package.json +44 -19
- package/{.safeword → templates}/hooks/agents-md-check.sh +0 -0
- package/{.safeword → templates}/hooks/post-tool.sh +0 -0
- package/{.safeword → templates}/hooks/pre-commit.sh +0 -0
- package/.claude/commands/arch-review.md +0 -32
- package/.claude/commands/lint.md +0 -6
- package/.claude/commands/quality-review.md +0 -13
- package/.claude/commands/setup-linting.md +0 -6
- package/.claude/hooks/auto-lint.sh +0 -6
- package/.claude/hooks/auto-quality-review.sh +0 -170
- package/.claude/hooks/check-linting-sync.sh +0 -17
- package/.claude/hooks/inject-timestamp.sh +0 -6
- package/.claude/hooks/question-protocol.sh +0 -12
- package/.claude/hooks/run-linters.sh +0 -8
- package/.claude/hooks/run-quality-review.sh +0 -76
- package/.claude/hooks/version-check.sh +0 -10
- package/.claude/mcp/README.md +0 -96
- package/.claude/mcp/arcade.sample.json +0 -9
- package/.claude/mcp/context7.sample.json +0 -7
- package/.claude/mcp/playwright.sample.json +0 -7
- package/.claude/settings.json +0 -62
- package/.claude/skills/quality-reviewer/SKILL.md +0 -190
- package/.claude/skills/safeword-quality-reviewer/SKILL.md +0 -13
- package/.env.arcade.example +0 -4
- package/.env.example +0 -11
- package/.gitmodules +0 -4
- package/.safeword/SAFEWORD.md +0 -33
- package/.safeword/eslint/eslint-base.mjs +0 -101
- package/.safeword/guides/architecture-guide.md +0 -404
- package/.safeword/guides/code-philosophy.md +0 -174
- package/.safeword/guides/context-files-guide.md +0 -405
- package/.safeword/guides/data-architecture-guide.md +0 -183
- package/.safeword/guides/design-doc-guide.md +0 -165
- package/.safeword/guides/learning-extraction.md +0 -515
- package/.safeword/guides/llm-instruction-design.md +0 -239
- package/.safeword/guides/llm-prompting.md +0 -95
- package/.safeword/guides/tdd-best-practices.md +0 -570
- package/.safeword/guides/test-definitions-guide.md +0 -243
- package/.safeword/guides/testing-methodology.md +0 -573
- package/.safeword/guides/user-story-guide.md +0 -237
- package/.safeword/guides/zombie-process-cleanup.md +0 -214
- package/.safeword/planning/002-user-story-quality-evaluation.md +0 -1840
- package/.safeword/planning/003-langsmith-eval-setup-prompt.md +0 -363
- package/.safeword/planning/004-llm-eval-test-cases.md +0 -3226
- package/.safeword/planning/005-architecture-enforcement-system.md +0 -169
- package/.safeword/planning/006-reactive-fix-prevention-research.md +0 -135
- package/.safeword/planning/011-cli-ux-vision.md +0 -330
- package/.safeword/planning/012-project-structure-cleanup.md +0 -154
- package/.safeword/planning/README.md +0 -39
- package/.safeword/planning/automation-plan-v2.md +0 -1225
- package/.safeword/planning/automation-plan-v3.md +0 -1291
- package/.safeword/planning/automation-plan.md +0 -3058
- package/.safeword/planning/design/005-cli-implementation.md +0 -343
- package/.safeword/planning/design/013-cli-self-contained-templates.md +0 -596
- package/.safeword/planning/design/013a-eslint-plugin-suite.md +0 -256
- package/.safeword/planning/design/013b-implementation-snippets.md +0 -385
- package/.safeword/planning/design/013c-config-isolation-strategy.md +0 -242
- package/.safeword/planning/design/code-philosophy-improvements.md +0 -60
- package/.safeword/planning/mcp-analysis.md +0 -545
- package/.safeword/planning/phase2-subagents-vs-skills-analysis.md +0 -451
- package/.safeword/planning/settings-improvements.md +0 -970
- package/.safeword/planning/test-definitions/005-cli-implementation.md +0 -1301
- package/.safeword/planning/test-definitions/cli-self-contained-templates.md +0 -205
- package/.safeword/planning/user-stories/001-guides-review-user-stories.md +0 -1381
- package/.safeword/planning/user-stories/003-reactive-fix-prevention.md +0 -132
- package/.safeword/planning/user-stories/004-technical-constraints.md +0 -86
- package/.safeword/planning/user-stories/005-cli-implementation.md +0 -311
- package/.safeword/planning/user-stories/cli-self-contained-templates.md +0 -172
- package/.safeword/planning/versioned-distribution.md +0 -740
- package/.safeword/prompts/arch-review.md +0 -43
- package/.safeword/prompts/quality-review.md +0 -11
- package/.safeword/scripts/arch-review.sh +0 -235
- package/.safeword/scripts/check-linting-sync.sh +0 -58
- package/.safeword/scripts/setup-linting.sh +0 -559
- package/.safeword/templates/architecture-template.md +0 -136
- package/.safeword/templates/ci/architecture-check.yml +0 -79
- package/.safeword/templates/design-doc-template.md +0 -127
- package/.safeword/templates/test-definitions-feature.md +0 -100
- package/.safeword/templates/ticket-template.md +0 -74
- package/.safeword/templates/user-stories-template.md +0 -82
- package/.safeword/tickets/001-guides-review-user-stories.md +0 -83
- package/.safeword/tickets/002-architecture-enforcement.md +0 -211
- package/.safeword/tickets/003-reactive-fix-prevention.md +0 -57
- package/.safeword/tickets/004-technical-constraints-in-user-stories.md +0 -39
- package/.safeword/tickets/005-cli-implementation.md +0 -248
- package/.safeword/tickets/006-flesh-out-skills.md +0 -43
- package/.safeword/tickets/007-flesh-out-questioning.md +0 -44
- package/.safeword/tickets/008-upgrade-questioning.md +0 -58
- package/.safeword/tickets/009-naming-conventions.md +0 -41
- package/.safeword/tickets/010-safeword-md-cleanup.md +0 -34
- package/.safeword/tickets/011-cursor-setup.md +0 -86
- package/.safeword/tickets/README.md +0 -73
- package/.safeword/version +0 -1
- package/AGENTS.md +0 -59
- package/CLAUDE.md +0 -12
- package/README.md +0 -347
- package/docs/001-cli-implementation-plan.md +0 -856
- package/docs/elite-dx-implementation-plan.md +0 -1034
- package/framework/README.md +0 -131
- package/framework/mcp/README.md +0 -96
- package/framework/mcp/arcade.sample.json +0 -8
- package/framework/mcp/context7.sample.json +0 -6
- package/framework/mcp/playwright.sample.json +0 -6
- package/framework/scripts/arch-review.sh +0 -235
- package/framework/scripts/check-linting-sync.sh +0 -58
- package/framework/scripts/load-env.sh +0 -49
- package/framework/scripts/setup-claude.sh +0 -223
- package/framework/scripts/setup-linting.sh +0 -559
- package/framework/scripts/setup-quality.sh +0 -477
- package/framework/scripts/setup-safeword.sh +0 -550
- package/framework/templates/ci/architecture-check.yml +0 -78
- package/learnings/ai-sdk-v5-breaking-changes.md +0 -178
- package/learnings/e2e-test-zombie-processes.md +0 -231
- package/learnings/milkdown-crepe-editor-property.md +0 -96
- package/learnings/prosemirror-fragment-traversal.md +0 -119
- package/packages/cli/AGENTS.md +0 -1
- package/packages/cli/ARCHITECTURE.md +0 -279
- package/packages/cli/package.json +0 -51
- package/packages/cli/src/cli.ts +0 -63
- package/packages/cli/src/commands/check.ts +0 -166
- package/packages/cli/src/commands/diff.ts +0 -209
- package/packages/cli/src/commands/reset.ts +0 -190
- package/packages/cli/src/commands/setup.ts +0 -325
- package/packages/cli/src/commands/upgrade.ts +0 -163
- package/packages/cli/src/index.ts +0 -3
- package/packages/cli/src/templates/config.ts +0 -58
- package/packages/cli/src/templates/content.ts +0 -18
- package/packages/cli/src/templates/index.ts +0 -12
- package/packages/cli/src/utils/agents-md.ts +0 -66
- package/packages/cli/src/utils/fs.ts +0 -179
- package/packages/cli/src/utils/git.ts +0 -124
- package/packages/cli/src/utils/hooks.ts +0 -29
- package/packages/cli/src/utils/output.ts +0 -60
- package/packages/cli/src/utils/project-detector.test.ts +0 -185
- package/packages/cli/src/utils/project-detector.ts +0 -44
- package/packages/cli/src/utils/version.ts +0 -28
- package/packages/cli/src/version.ts +0 -6
- package/packages/cli/templates/SAFEWORD.md +0 -776
- package/packages/cli/templates/doc-templates/architecture-template.md +0 -136
- package/packages/cli/templates/doc-templates/design-doc-template.md +0 -134
- package/packages/cli/templates/doc-templates/test-definitions-feature.md +0 -131
- package/packages/cli/templates/doc-templates/ticket-template.md +0 -82
- package/packages/cli/templates/doc-templates/user-stories-template.md +0 -92
- package/packages/cli/templates/guides/architecture-guide.md +0 -423
- package/packages/cli/templates/guides/code-philosophy.md +0 -195
- package/packages/cli/templates/guides/context-files-guide.md +0 -457
- package/packages/cli/templates/guides/data-architecture-guide.md +0 -200
- package/packages/cli/templates/guides/design-doc-guide.md +0 -171
- package/packages/cli/templates/guides/learning-extraction.md +0 -552
- package/packages/cli/templates/guides/llm-instruction-design.md +0 -248
- package/packages/cli/templates/guides/llm-prompting.md +0 -102
- package/packages/cli/templates/guides/tdd-best-practices.md +0 -615
- package/packages/cli/templates/guides/test-definitions-guide.md +0 -334
- package/packages/cli/templates/guides/testing-methodology.md +0 -618
- package/packages/cli/templates/guides/user-story-guide.md +0 -256
- package/packages/cli/templates/guides/zombie-process-cleanup.md +0 -219
- package/packages/cli/templates/hooks/agents-md-check.sh +0 -27
- package/packages/cli/templates/hooks/post-tool.sh +0 -4
- package/packages/cli/templates/hooks/pre-commit.sh +0 -10
- package/packages/cli/templates/prompts/arch-review.md +0 -43
- package/packages/cli/templates/prompts/quality-review.md +0 -10
- package/packages/cli/templates/skills/safeword-quality-reviewer/SKILL.md +0 -207
- package/packages/cli/tests/commands/check.test.ts +0 -129
- package/packages/cli/tests/commands/cli.test.ts +0 -89
- package/packages/cli/tests/commands/diff.test.ts +0 -115
- package/packages/cli/tests/commands/reset.test.ts +0 -310
- package/packages/cli/tests/commands/self-healing.test.ts +0 -170
- package/packages/cli/tests/commands/setup-blocking.test.ts +0 -71
- package/packages/cli/tests/commands/setup-core.test.ts +0 -135
- package/packages/cli/tests/commands/setup-git.test.ts +0 -139
- package/packages/cli/tests/commands/setup-hooks.test.ts +0 -334
- package/packages/cli/tests/commands/setup-linting.test.ts +0 -189
- package/packages/cli/tests/commands/setup-noninteractive.test.ts +0 -80
- package/packages/cli/tests/commands/setup-templates.test.ts +0 -181
- package/packages/cli/tests/commands/upgrade.test.ts +0 -215
- package/packages/cli/tests/helpers.ts +0 -243
- package/packages/cli/tests/npm-package.test.ts +0 -83
- package/packages/cli/tests/technical-constraints.test.ts +0 -96
- package/packages/cli/tsconfig.json +0 -25
- package/packages/cli/tsup.config.ts +0 -11
- package/packages/cli/vitest.config.ts +0 -23
- package/promptfoo.yaml +0 -3270
- /package/{framework → templates}/SAFEWORD.md +0 -0
- /package/{packages/cli/templates → templates}/commands/arch-review.md +0 -0
- /package/{packages/cli/templates → templates}/commands/lint.md +0 -0
- /package/{packages/cli/templates → templates}/commands/quality-review.md +0 -0
- /package/{framework/templates → templates/doc-templates}/architecture-template.md +0 -0
- /package/{framework/templates → templates/doc-templates}/design-doc-template.md +0 -0
- /package/{framework/templates → templates/doc-templates}/test-definitions-feature.md +0 -0
- /package/{framework/templates → templates/doc-templates}/ticket-template.md +0 -0
- /package/{framework/templates → templates/doc-templates}/user-stories-template.md +0 -0
- /package/{framework → templates}/guides/architecture-guide.md +0 -0
- /package/{framework → templates}/guides/code-philosophy.md +0 -0
- /package/{framework → templates}/guides/context-files-guide.md +0 -0
- /package/{framework → templates}/guides/data-architecture-guide.md +0 -0
- /package/{framework → templates}/guides/design-doc-guide.md +0 -0
- /package/{framework → templates}/guides/learning-extraction.md +0 -0
- /package/{framework → templates}/guides/llm-instruction-design.md +0 -0
- /package/{framework → templates}/guides/llm-prompting.md +0 -0
- /package/{framework → templates}/guides/tdd-best-practices.md +0 -0
- /package/{framework → templates}/guides/test-definitions-guide.md +0 -0
- /package/{framework → templates}/guides/testing-methodology.md +0 -0
- /package/{framework → templates}/guides/user-story-guide.md +0 -0
- /package/{framework → templates}/guides/zombie-process-cleanup.md +0 -0
- /package/{packages/cli/templates → templates}/hooks/inject-timestamp.sh +0 -0
- /package/{packages/cli/templates → templates}/lib/common.sh +0 -0
- /package/{packages/cli/templates → templates}/lib/jq-fallback.sh +0 -0
- /package/{packages/cli/templates → templates}/markdownlint.jsonc +0 -0
- /package/{framework → templates}/prompts/arch-review.md +0 -0
- /package/{framework → templates}/prompts/quality-review.md +0 -0
- /package/{framework/skills/quality-reviewer → templates/skills/safeword-quality-reviewer}/SKILL.md +0 -0
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Test Suite 7: Git Repository Handling
|
|
3
|
-
*
|
|
4
|
-
* Tests for git detection and hook installation.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
8
|
-
import {
|
|
9
|
-
createTempDir,
|
|
10
|
-
removeTempDir,
|
|
11
|
-
createTypeScriptPackageJson,
|
|
12
|
-
runCli,
|
|
13
|
-
readTestFile,
|
|
14
|
-
writeTestFile,
|
|
15
|
-
fileExists,
|
|
16
|
-
initGitRepo,
|
|
17
|
-
} from '../helpers';
|
|
18
|
-
|
|
19
|
-
describe('Test Suite 7: Git Repository Handling', () => {
|
|
20
|
-
let tempDir: string;
|
|
21
|
-
|
|
22
|
-
beforeEach(() => {
|
|
23
|
-
tempDir = createTempDir();
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
afterEach(() => {
|
|
27
|
-
removeTempDir(tempDir);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
describe('Test 7.1: Prompts for git init when no .git', () => {
|
|
31
|
-
it('should mention git initialization in output', async () => {
|
|
32
|
-
createTypeScriptPackageJson(tempDir);
|
|
33
|
-
// No git init
|
|
34
|
-
|
|
35
|
-
// In non-interactive mode with --yes, we expect it to skip
|
|
36
|
-
// The prompt behavior is tested via TTY simulation
|
|
37
|
-
const result = await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
38
|
-
|
|
39
|
-
// Output should mention git
|
|
40
|
-
const output = result.stdout + result.stderr;
|
|
41
|
-
expect(output.toLowerCase()).toMatch(/git/i);
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
describe('Test 7.2: Runs git init when user confirms', () => {
|
|
46
|
-
// This test would require TTY simulation for interactive input
|
|
47
|
-
// For now, we test that git hooks work when .git exists
|
|
48
|
-
it('should work with existing git repository', async () => {
|
|
49
|
-
createTypeScriptPackageJson(tempDir);
|
|
50
|
-
initGitRepo(tempDir);
|
|
51
|
-
|
|
52
|
-
const result = await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
53
|
-
|
|
54
|
-
expect(result.exitCode).toBe(0);
|
|
55
|
-
expect(fileExists(tempDir, '.git')).toBe(true);
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
describe('Test 7.3: Skips git init when user declines', () => {
|
|
60
|
-
// In --yes mode, git init is skipped by default
|
|
61
|
-
it('should skip git init in non-interactive mode', async () => {
|
|
62
|
-
createTypeScriptPackageJson(tempDir);
|
|
63
|
-
// No git init
|
|
64
|
-
|
|
65
|
-
const result = await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
66
|
-
|
|
67
|
-
expect(result.exitCode).toBe(0);
|
|
68
|
-
// Git should NOT be initialized
|
|
69
|
-
expect(fileExists(tempDir, '.git')).toBe(false);
|
|
70
|
-
|
|
71
|
-
// Should warn about skipped git hooks
|
|
72
|
-
const output = result.stdout + result.stderr;
|
|
73
|
-
expect(output.toLowerCase()).toMatch(/skip|warning|git/i);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
describe('Test 7.4: Installs git hooks when .git present', () => {
|
|
78
|
-
it('should create pre-commit hook with safeword markers', async () => {
|
|
79
|
-
createTypeScriptPackageJson(tempDir);
|
|
80
|
-
initGitRepo(tempDir);
|
|
81
|
-
|
|
82
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
83
|
-
|
|
84
|
-
expect(fileExists(tempDir, '.git/hooks/pre-commit')).toBe(true);
|
|
85
|
-
|
|
86
|
-
const content = readTestFile(tempDir, '.git/hooks/pre-commit');
|
|
87
|
-
expect(content).toContain('SAFEWORD_ARCH_CHECK_START');
|
|
88
|
-
expect(content).toContain('SAFEWORD_ARCH_CHECK_END');
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
describe('Test 7.5: Preserves existing pre-commit hooks', () => {
|
|
93
|
-
it('should preserve custom hook content', async () => {
|
|
94
|
-
createTypeScriptPackageJson(tempDir);
|
|
95
|
-
initGitRepo(tempDir);
|
|
96
|
-
|
|
97
|
-
// Create existing pre-commit hook
|
|
98
|
-
const customHook = `#!/bin/bash
|
|
99
|
-
# Custom hook for running tests
|
|
100
|
-
echo "Running custom tests..."
|
|
101
|
-
npm test
|
|
102
|
-
`;
|
|
103
|
-
writeTestFile(tempDir, '.git/hooks/pre-commit', customHook);
|
|
104
|
-
|
|
105
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
106
|
-
|
|
107
|
-
const content = readTestFile(tempDir, '.git/hooks/pre-commit');
|
|
108
|
-
|
|
109
|
-
// Original content preserved
|
|
110
|
-
expect(content).toContain('Running custom tests');
|
|
111
|
-
expect(content).toContain('npm test');
|
|
112
|
-
|
|
113
|
-
// Safeword markers added
|
|
114
|
-
expect(content).toContain('SAFEWORD_ARCH_CHECK_START');
|
|
115
|
-
expect(content).toContain('SAFEWORD_ARCH_CHECK_END');
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it('should not duplicate markers on repeated setup', async () => {
|
|
119
|
-
createTypeScriptPackageJson(tempDir);
|
|
120
|
-
initGitRepo(tempDir);
|
|
121
|
-
|
|
122
|
-
// Run setup twice
|
|
123
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
124
|
-
|
|
125
|
-
// For second run, we need to remove .safeword to allow setup
|
|
126
|
-
// Or use upgrade. Let's test via upgrade path
|
|
127
|
-
await runCli(['upgrade'], { cwd: tempDir });
|
|
128
|
-
|
|
129
|
-
const content = readTestFile(tempDir, '.git/hooks/pre-commit');
|
|
130
|
-
|
|
131
|
-
// Markers should appear exactly once
|
|
132
|
-
const startCount = (content.match(/SAFEWORD_ARCH_CHECK_START/g) || []).length;
|
|
133
|
-
const endCount = (content.match(/SAFEWORD_ARCH_CHECK_END/g) || []).length;
|
|
134
|
-
|
|
135
|
-
expect(startCount).toBe(1);
|
|
136
|
-
expect(endCount).toBe(1);
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
});
|
|
@@ -1,334 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Test Suite 3: Setup - Hooks and Skills
|
|
3
|
-
*
|
|
4
|
-
* Tests for Claude Code hook registration and skill copying.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
8
|
-
import { chmodSync, readdirSync } from 'node:fs';
|
|
9
|
-
import { join } from 'node:path';
|
|
10
|
-
import {
|
|
11
|
-
createTempDir,
|
|
12
|
-
removeTempDir,
|
|
13
|
-
createTypeScriptPackageJson,
|
|
14
|
-
runCli,
|
|
15
|
-
readTestFile,
|
|
16
|
-
writeTestFile,
|
|
17
|
-
fileExists,
|
|
18
|
-
initGitRepo,
|
|
19
|
-
} from '../helpers';
|
|
20
|
-
|
|
21
|
-
describe('Test Suite 3: Setup - Hooks and Skills', () => {
|
|
22
|
-
let tempDir: string;
|
|
23
|
-
|
|
24
|
-
beforeEach(() => {
|
|
25
|
-
tempDir = createTempDir();
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
afterEach(() => {
|
|
29
|
-
removeTempDir(tempDir);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
describe('Test 3.1: Registers hooks in settings.json', () => {
|
|
33
|
-
it('should create .claude/settings.json with hooks', async () => {
|
|
34
|
-
createTypeScriptPackageJson(tempDir);
|
|
35
|
-
initGitRepo(tempDir);
|
|
36
|
-
|
|
37
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
38
|
-
|
|
39
|
-
expect(fileExists(tempDir, '.claude/settings.json')).toBe(true);
|
|
40
|
-
|
|
41
|
-
const settings = JSON.parse(readTestFile(tempDir, '.claude/settings.json'));
|
|
42
|
-
|
|
43
|
-
expect(settings.hooks).toBeDefined();
|
|
44
|
-
expect(settings.hooks.SessionStart).toBeDefined();
|
|
45
|
-
expect(Array.isArray(settings.hooks.SessionStart)).toBe(true);
|
|
46
|
-
expect(settings.hooks.UserPromptSubmit).toBeDefined();
|
|
47
|
-
expect(Array.isArray(settings.hooks.UserPromptSubmit)).toBe(true);
|
|
48
|
-
expect(settings.hooks.PostToolUse).toBeDefined();
|
|
49
|
-
expect(Array.isArray(settings.hooks.PostToolUse)).toBe(true);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('should reference .safeword/hooks paths', async () => {
|
|
53
|
-
createTypeScriptPackageJson(tempDir);
|
|
54
|
-
initGitRepo(tempDir);
|
|
55
|
-
|
|
56
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
57
|
-
|
|
58
|
-
const settings = JSON.parse(readTestFile(tempDir, '.claude/settings.json'));
|
|
59
|
-
const settingsStr = JSON.stringify(settings);
|
|
60
|
-
|
|
61
|
-
// At least one hook should reference .safeword/hooks
|
|
62
|
-
expect(settingsStr).toContain('.safeword/hooks');
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
describe('Test 3.2: Copies skills to .claude/skills', () => {
|
|
67
|
-
it('should create skills directory with safeword skills', async () => {
|
|
68
|
-
createTypeScriptPackageJson(tempDir);
|
|
69
|
-
initGitRepo(tempDir);
|
|
70
|
-
|
|
71
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
72
|
-
|
|
73
|
-
expect(fileExists(tempDir, '.claude/skills')).toBe(true);
|
|
74
|
-
|
|
75
|
-
// Check for safeword skill directory
|
|
76
|
-
// Should match pattern safeword-* (e.g., safeword-quality-reviewer)
|
|
77
|
-
expect(fileExists(tempDir, '.claude/skills/safeword-quality-reviewer')).toBe(true);
|
|
78
|
-
|
|
79
|
-
// The skill should contain a SKILL.md file
|
|
80
|
-
expect(fileExists(tempDir, '.claude/skills/safeword-quality-reviewer/SKILL.md')).toBe(true);
|
|
81
|
-
|
|
82
|
-
const skillContent = readTestFile(
|
|
83
|
-
tempDir,
|
|
84
|
-
'.claude/skills/safeword-quality-reviewer/SKILL.md',
|
|
85
|
-
);
|
|
86
|
-
expect(skillContent).toContain('Quality Reviewer');
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
describe('Test 3.3: Preserves existing hooks', () => {
|
|
91
|
-
it('should append to existing hooks without replacing', async () => {
|
|
92
|
-
createTypeScriptPackageJson(tempDir);
|
|
93
|
-
initGitRepo(tempDir);
|
|
94
|
-
|
|
95
|
-
// Create existing settings with custom hook
|
|
96
|
-
const existingSettings = {
|
|
97
|
-
hooks: {
|
|
98
|
-
SessionStart: [
|
|
99
|
-
{
|
|
100
|
-
command: 'echo "My custom hook"',
|
|
101
|
-
description: 'Custom SessionStart hook',
|
|
102
|
-
},
|
|
103
|
-
],
|
|
104
|
-
},
|
|
105
|
-
};
|
|
106
|
-
writeTestFile(tempDir, '.claude/settings.json', JSON.stringify(existingSettings, null, 2));
|
|
107
|
-
|
|
108
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
109
|
-
|
|
110
|
-
const settings = JSON.parse(readTestFile(tempDir, '.claude/settings.json'));
|
|
111
|
-
|
|
112
|
-
// Custom hook should still be present
|
|
113
|
-
const hasCustomHook = settings.hooks.SessionStart.some(
|
|
114
|
-
(hook: { command?: string }) => hook.command === 'echo "My custom hook"',
|
|
115
|
-
);
|
|
116
|
-
expect(hasCustomHook).toBe(true);
|
|
117
|
-
|
|
118
|
-
// Safeword hooks should be added
|
|
119
|
-
expect(settings.hooks.SessionStart.length).toBeGreaterThan(1);
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
describe('Test 3.4: Includes SessionStart hook for AGENTS.md', () => {
|
|
124
|
-
it('should include AGENTS.md verification hook', async () => {
|
|
125
|
-
createTypeScriptPackageJson(tempDir);
|
|
126
|
-
initGitRepo(tempDir);
|
|
127
|
-
|
|
128
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
129
|
-
|
|
130
|
-
const settings = JSON.parse(readTestFile(tempDir, '.claude/settings.json'));
|
|
131
|
-
|
|
132
|
-
// Find hook that references AGENTS.md check
|
|
133
|
-
const agentsHook = settings.hooks.SessionStart.find(
|
|
134
|
-
(hook: { command?: string }) =>
|
|
135
|
-
hook.command && (hook.command.includes('AGENTS') || hook.command.includes('agents')),
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
expect(agentsHook).toBeDefined();
|
|
139
|
-
|
|
140
|
-
// Hook script should exist
|
|
141
|
-
if (agentsHook?.command) {
|
|
142
|
-
// Extract script path from command if it's a bash script
|
|
143
|
-
const scriptMatch = agentsHook.command.match(/bash\s+([^\s]+)/);
|
|
144
|
-
if (scriptMatch) {
|
|
145
|
-
expect(fileExists(tempDir, scriptMatch[1])).toBe(true);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
describe('Test 3.6: Includes UserPromptSubmit hook for timestamp injection', () => {
|
|
152
|
-
it('should include timestamp injection hook', async () => {
|
|
153
|
-
createTypeScriptPackageJson(tempDir);
|
|
154
|
-
initGitRepo(tempDir);
|
|
155
|
-
|
|
156
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
157
|
-
|
|
158
|
-
const settings = JSON.parse(readTestFile(tempDir, '.claude/settings.json'));
|
|
159
|
-
|
|
160
|
-
// Find hook that references timestamp injection
|
|
161
|
-
const timestampHook = settings.hooks.UserPromptSubmit.find(
|
|
162
|
-
(hook: { command?: string }) =>
|
|
163
|
-
hook.command && hook.command.includes('inject-timestamp'),
|
|
164
|
-
);
|
|
165
|
-
|
|
166
|
-
expect(timestampHook).toBeDefined();
|
|
167
|
-
|
|
168
|
-
// Hook script should exist
|
|
169
|
-
expect(fileExists(tempDir, '.safeword/hooks/inject-timestamp.sh')).toBe(true);
|
|
170
|
-
|
|
171
|
-
// Script should contain timestamp output
|
|
172
|
-
const scriptContent = readTestFile(tempDir, '.safeword/hooks/inject-timestamp.sh');
|
|
173
|
-
expect(scriptContent).toContain('date');
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
describe('Test 3.5: Exit 1 if hook registration fails', () => {
|
|
178
|
-
it('should fail with exit 1 when settings.json is not writable', async () => {
|
|
179
|
-
createTypeScriptPackageJson(tempDir);
|
|
180
|
-
initGitRepo(tempDir);
|
|
181
|
-
|
|
182
|
-
// Create .claude directory with read-only settings.json
|
|
183
|
-
writeTestFile(tempDir, '.claude/settings.json', '{}');
|
|
184
|
-
chmodSync(join(tempDir, '.claude/settings.json'), 0o444);
|
|
185
|
-
|
|
186
|
-
const result = await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
187
|
-
|
|
188
|
-
// Restore permissions for cleanup
|
|
189
|
-
chmodSync(join(tempDir, '.claude/settings.json'), 0o644);
|
|
190
|
-
|
|
191
|
-
expect(result.exitCode).toBe(1);
|
|
192
|
-
expect(result.stderr.toLowerCase()).toMatch(/hook|permission|write|failed/i);
|
|
193
|
-
});
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
describe('Test 3.7: Installs lib scripts', () => {
|
|
197
|
-
it('should install shared library scripts to .safeword/lib/', async () => {
|
|
198
|
-
createTypeScriptPackageJson(tempDir);
|
|
199
|
-
initGitRepo(tempDir);
|
|
200
|
-
|
|
201
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
202
|
-
|
|
203
|
-
// Lib directory should exist with shell scripts
|
|
204
|
-
expect(fileExists(tempDir, '.safeword/lib')).toBe(true);
|
|
205
|
-
|
|
206
|
-
const libDir = join(tempDir, '.safeword/lib');
|
|
207
|
-
const shFiles = readdirSync(libDir).filter((f) => f.endsWith('.sh'));
|
|
208
|
-
expect(shFiles.length).toBeGreaterThan(0);
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
describe('Test 3.8: Sets up MCP servers', () => {
|
|
213
|
-
it('should create .mcp.json with context7 and playwright', async () => {
|
|
214
|
-
createTypeScriptPackageJson(tempDir);
|
|
215
|
-
initGitRepo(tempDir);
|
|
216
|
-
|
|
217
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
218
|
-
|
|
219
|
-
expect(fileExists(tempDir, '.mcp.json')).toBe(true);
|
|
220
|
-
|
|
221
|
-
const mcpConfig = JSON.parse(readTestFile(tempDir, '.mcp.json'));
|
|
222
|
-
expect(mcpConfig.mcpServers).toBeDefined();
|
|
223
|
-
expect(mcpConfig.mcpServers.context7).toBeDefined();
|
|
224
|
-
expect(mcpConfig.mcpServers.playwright).toBeDefined();
|
|
225
|
-
});
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
describe('Test 3.9: Preserves existing MCP servers', () => {
|
|
229
|
-
it('should preserve user MCP servers when adding safeword servers', async () => {
|
|
230
|
-
createTypeScriptPackageJson(tempDir);
|
|
231
|
-
initGitRepo(tempDir);
|
|
232
|
-
|
|
233
|
-
// Create existing .mcp.json with custom server
|
|
234
|
-
const existingMcp = {
|
|
235
|
-
mcpServers: {
|
|
236
|
-
'my-custom-server': {
|
|
237
|
-
command: 'my-server',
|
|
238
|
-
args: ['--port', '3000'],
|
|
239
|
-
},
|
|
240
|
-
},
|
|
241
|
-
};
|
|
242
|
-
writeTestFile(tempDir, '.mcp.json', JSON.stringify(existingMcp, null, 2));
|
|
243
|
-
|
|
244
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
245
|
-
|
|
246
|
-
const mcpConfig = JSON.parse(readTestFile(tempDir, '.mcp.json'));
|
|
247
|
-
|
|
248
|
-
// Custom server should be preserved
|
|
249
|
-
expect(mcpConfig.mcpServers['my-custom-server']).toBeDefined();
|
|
250
|
-
expect(mcpConfig.mcpServers['my-custom-server'].command).toBe('my-server');
|
|
251
|
-
|
|
252
|
-
// Safeword servers should be added
|
|
253
|
-
expect(mcpConfig.mcpServers.context7).toBeDefined();
|
|
254
|
-
expect(mcpConfig.mcpServers.playwright).toBeDefined();
|
|
255
|
-
});
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
describe('Test 3.10: Installs slash commands', () => {
|
|
259
|
-
it('should install slash commands to .claude/commands/', async () => {
|
|
260
|
-
createTypeScriptPackageJson(tempDir);
|
|
261
|
-
initGitRepo(tempDir);
|
|
262
|
-
|
|
263
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
264
|
-
|
|
265
|
-
// Commands directory should exist
|
|
266
|
-
expect(fileExists(tempDir, '.claude/commands')).toBe(true);
|
|
267
|
-
|
|
268
|
-
// Should contain markdown command files
|
|
269
|
-
const commandsDir = join(tempDir, '.claude/commands');
|
|
270
|
-
const mdFiles = readdirSync(commandsDir).filter((f) => f.endsWith('.md'));
|
|
271
|
-
expect(mdFiles.length).toBeGreaterThan(0);
|
|
272
|
-
});
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
describe('Test 3.11: MCP servers work out of the box', () => {
|
|
276
|
-
it('should configure context7 with correct npx command', async () => {
|
|
277
|
-
createTypeScriptPackageJson(tempDir);
|
|
278
|
-
initGitRepo(tempDir);
|
|
279
|
-
|
|
280
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
281
|
-
|
|
282
|
-
expect(fileExists(tempDir, '.mcp.json')).toBe(true);
|
|
283
|
-
|
|
284
|
-
const mcpConfig = JSON.parse(readTestFile(tempDir, '.mcp.json'));
|
|
285
|
-
|
|
286
|
-
// Context7 should use npx with the correct package
|
|
287
|
-
expect(mcpConfig.mcpServers.context7).toBeDefined();
|
|
288
|
-
expect(mcpConfig.mcpServers.context7.command).toBe('npx');
|
|
289
|
-
expect(mcpConfig.mcpServers.context7.args).toContain('@upstash/context7-mcp@latest');
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
it('should configure playwright with correct npx command', async () => {
|
|
293
|
-
createTypeScriptPackageJson(tempDir);
|
|
294
|
-
initGitRepo(tempDir);
|
|
295
|
-
|
|
296
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
297
|
-
|
|
298
|
-
const mcpConfig = JSON.parse(readTestFile(tempDir, '.mcp.json'));
|
|
299
|
-
|
|
300
|
-
// Playwright should use npx with the correct package
|
|
301
|
-
expect(mcpConfig.mcpServers.playwright).toBeDefined();
|
|
302
|
-
expect(mcpConfig.mcpServers.playwright.command).toBe('npx');
|
|
303
|
-
expect(mcpConfig.mcpServers.playwright.args).toEqual(
|
|
304
|
-
expect.arrayContaining([expect.stringContaining('@playwright/mcp')]),
|
|
305
|
-
);
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
it('should have MCP packages that can be resolved by npx', async () => {
|
|
309
|
-
// Verify the packages exist on npm (can be resolved)
|
|
310
|
-
// This is a lightweight check - just verify npm can find the packages
|
|
311
|
-
const { execSync } = await import('node:child_process');
|
|
312
|
-
|
|
313
|
-
// Check context7 package exists
|
|
314
|
-
try {
|
|
315
|
-
execSync('npm view @upstash/context7-mcp version', {
|
|
316
|
-
encoding: 'utf-8',
|
|
317
|
-
timeout: 10000,
|
|
318
|
-
});
|
|
319
|
-
} catch {
|
|
320
|
-
expect.fail('@upstash/context7-mcp package not found on npm');
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// Check playwright package exists
|
|
324
|
-
try {
|
|
325
|
-
execSync('npm view @playwright/mcp version', {
|
|
326
|
-
encoding: 'utf-8',
|
|
327
|
-
timeout: 10000,
|
|
328
|
-
});
|
|
329
|
-
} catch {
|
|
330
|
-
expect.fail('@playwright/mcp package not found on npm');
|
|
331
|
-
}
|
|
332
|
-
});
|
|
333
|
-
});
|
|
334
|
-
});
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Test Suite 4: Setup - Linting (Integration Tests)
|
|
3
|
-
*
|
|
4
|
-
* Tests for ESLint + Prettier configuration.
|
|
5
|
-
*
|
|
6
|
-
* Note: Unit tests for project type detection (Tests 4.1-4.3) are in
|
|
7
|
-
* src/utils/project-detector.test.ts. This file contains only the
|
|
8
|
-
* integration tests (Tests 4.4-4.8).
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
12
|
-
import { chmodSync } from 'node:fs';
|
|
13
|
-
import { join } from 'node:path';
|
|
14
|
-
import {
|
|
15
|
-
createTempDir,
|
|
16
|
-
removeTempDir,
|
|
17
|
-
createTypeScriptPackageJson,
|
|
18
|
-
runCli,
|
|
19
|
-
readTestFile,
|
|
20
|
-
fileExists,
|
|
21
|
-
initGitRepo,
|
|
22
|
-
} from '../helpers';
|
|
23
|
-
|
|
24
|
-
describe('Test Suite 4: Setup - Linting (Integration)', () => {
|
|
25
|
-
let tempDir: string;
|
|
26
|
-
|
|
27
|
-
beforeEach(() => {
|
|
28
|
-
tempDir = createTempDir();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
afterEach(() => {
|
|
32
|
-
removeTempDir(tempDir);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
describe('Test 4.4: Creates eslint.config.mjs', () => {
|
|
36
|
-
it('should create ESLint flat config', async () => {
|
|
37
|
-
createTypeScriptPackageJson(tempDir);
|
|
38
|
-
initGitRepo(tempDir);
|
|
39
|
-
|
|
40
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
41
|
-
|
|
42
|
-
expect(fileExists(tempDir, 'eslint.config.mjs')).toBe(true);
|
|
43
|
-
|
|
44
|
-
const content = readTestFile(tempDir, 'eslint.config.mjs');
|
|
45
|
-
// Should be a valid ESLint flat config
|
|
46
|
-
expect(content).toContain('export');
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('should include TypeScript config when detected', async () => {
|
|
50
|
-
createTypeScriptPackageJson(tempDir);
|
|
51
|
-
initGitRepo(tempDir);
|
|
52
|
-
|
|
53
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
54
|
-
|
|
55
|
-
const content = readTestFile(tempDir, 'eslint.config.mjs');
|
|
56
|
-
expect(content).toMatch(/typescript|@typescript-eslint/i);
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
describe('Test 4.5: Creates .prettierrc', () => {
|
|
61
|
-
it('should create Prettier config', async () => {
|
|
62
|
-
createTypeScriptPackageJson(tempDir);
|
|
63
|
-
initGitRepo(tempDir);
|
|
64
|
-
|
|
65
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
66
|
-
|
|
67
|
-
expect(fileExists(tempDir, '.prettierrc')).toBe(true);
|
|
68
|
-
|
|
69
|
-
const content = readTestFile(tempDir, '.prettierrc');
|
|
70
|
-
// Should be valid JSON
|
|
71
|
-
expect(() => JSON.parse(content)).not.toThrow();
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
describe('Test 4.6: Adds lint script to package.json', () => {
|
|
76
|
-
it('should add lint script', async () => {
|
|
77
|
-
createTypeScriptPackageJson(tempDir);
|
|
78
|
-
initGitRepo(tempDir);
|
|
79
|
-
|
|
80
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
81
|
-
|
|
82
|
-
const packageJson = JSON.parse(readTestFile(tempDir, 'package.json'));
|
|
83
|
-
expect(packageJson.scripts?.lint).toBe('eslint .');
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('should not overwrite existing lint script', async () => {
|
|
87
|
-
createTypeScriptPackageJson(tempDir, {
|
|
88
|
-
scripts: {
|
|
89
|
-
lint: 'eslint src/',
|
|
90
|
-
},
|
|
91
|
-
});
|
|
92
|
-
initGitRepo(tempDir);
|
|
93
|
-
|
|
94
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
95
|
-
|
|
96
|
-
const packageJson = JSON.parse(readTestFile(tempDir, 'package.json'));
|
|
97
|
-
// Original script should be preserved
|
|
98
|
-
expect(packageJson.scripts?.lint).toBe('eslint src/');
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
describe('Test 4.7: Adds format script to package.json', () => {
|
|
103
|
-
it('should add format script', async () => {
|
|
104
|
-
createTypeScriptPackageJson(tempDir);
|
|
105
|
-
initGitRepo(tempDir);
|
|
106
|
-
|
|
107
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
108
|
-
|
|
109
|
-
const packageJson = JSON.parse(readTestFile(tempDir, 'package.json'));
|
|
110
|
-
expect(packageJson.scripts?.format).toBe('prettier --write .');
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it('should not overwrite existing format script', async () => {
|
|
114
|
-
createTypeScriptPackageJson(tempDir, {
|
|
115
|
-
scripts: {
|
|
116
|
-
format: 'prettier --write src/',
|
|
117
|
-
},
|
|
118
|
-
});
|
|
119
|
-
initGitRepo(tempDir);
|
|
120
|
-
|
|
121
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
122
|
-
|
|
123
|
-
const packageJson = JSON.parse(readTestFile(tempDir, 'package.json'));
|
|
124
|
-
// Original script should be preserved
|
|
125
|
-
expect(packageJson.scripts?.format).toBe('prettier --write src/');
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
describe('Test 4.8: Exit 1 if linting setup fails', () => {
|
|
130
|
-
it('should fail with exit 1 when package.json is not writable', async () => {
|
|
131
|
-
createTypeScriptPackageJson(tempDir);
|
|
132
|
-
initGitRepo(tempDir);
|
|
133
|
-
|
|
134
|
-
// Make package.json read-only
|
|
135
|
-
chmodSync(join(tempDir, 'package.json'), 0o444);
|
|
136
|
-
|
|
137
|
-
const result = await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
138
|
-
|
|
139
|
-
// Restore permissions for cleanup
|
|
140
|
-
chmodSync(join(tempDir, 'package.json'), 0o644);
|
|
141
|
-
|
|
142
|
-
expect(result.exitCode).toBe(1);
|
|
143
|
-
expect(result.stderr.toLowerCase()).toMatch(/lint|permission|write|failed|package/i);
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
describe('Test 4.9: Creates markdownlint config', () => {
|
|
148
|
-
it('should create .markdownlint.jsonc', async () => {
|
|
149
|
-
createTypeScriptPackageJson(tempDir);
|
|
150
|
-
initGitRepo(tempDir);
|
|
151
|
-
|
|
152
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
153
|
-
|
|
154
|
-
// Implementation may place in .safeword/ or root
|
|
155
|
-
const hasMarkdownlintConfig =
|
|
156
|
-
fileExists(tempDir, '.markdownlint.jsonc') ||
|
|
157
|
-
fileExists(tempDir, '.safeword/.markdownlint.jsonc');
|
|
158
|
-
|
|
159
|
-
expect(hasMarkdownlintConfig).toBe(true);
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
describe('Test 4.10: Adds lint:md script', () => {
|
|
164
|
-
it('should add lint:md script to package.json', async () => {
|
|
165
|
-
createTypeScriptPackageJson(tempDir);
|
|
166
|
-
initGitRepo(tempDir);
|
|
167
|
-
|
|
168
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
169
|
-
|
|
170
|
-
const packageJson = JSON.parse(readTestFile(tempDir, 'package.json'));
|
|
171
|
-
expect(packageJson.scripts?.['lint:md']).toBeDefined();
|
|
172
|
-
expect(packageJson.scripts?.['lint:md']).toContain('markdownlint');
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
describe('Test 4.11: Adds format:check script', () => {
|
|
177
|
-
it('should add format:check script to package.json', async () => {
|
|
178
|
-
createTypeScriptPackageJson(tempDir);
|
|
179
|
-
initGitRepo(tempDir);
|
|
180
|
-
|
|
181
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
182
|
-
|
|
183
|
-
const packageJson = JSON.parse(readTestFile(tempDir, 'package.json'));
|
|
184
|
-
expect(packageJson.scripts?.['format:check']).toBeDefined();
|
|
185
|
-
expect(packageJson.scripts?.['format:check']).toContain('prettier');
|
|
186
|
-
expect(packageJson.scripts?.['format:check']).toContain('--check');
|
|
187
|
-
});
|
|
188
|
-
});
|
|
189
|
-
});
|