Skip to content

Commit ade5cff

Browse files
committed
test: add comprehensive test coverage and refactor prepareOptions
This massive update increases test coverage from 213 to 285 tests (+72 tests, +34%) to prepare for the gh-pages v6 upgrade (PR #186). All critical paths are now tested, prepareOptions is refactored into testable functions, and a public API is exported. ## Phase 1: Critical Test Gaps (20 new tests) ### gh-pages Error Callback Tests (4 tests) - Add tests for the "do NOT await" error handling pattern - Test error rejection, message preservation, and auth failures - Verifies we never fall into gh-pages v3 silent failure trap - File: src/engine/engine.spec.ts ### Monkeypatch Verification Tests (5 tests) - Add first-ever tests for util.debuglog interception (was 0% coverage) - Test gh-pages logging forwarding to Angular logger - Test message formatting with placeholders - Verify critical ordering (monkeypatch before gh-pages require) - File: src/engine/engine.spec.ts ### Real Filesystem Tests (11 tests) - Create first-ever real filesystem integration tests - Use actual temp directories instead of mocks - Test .nojekyll, CNAME, and 404.html file creation - Test graceful error handling when index.html missing - File: src/engine/engine-filesystem.spec.ts (NEW) ## Phase 2: Refactor prepareOptions (34 new tests) ### Code Refactoring - Extract prepareOptions (157 lines) into 6 testable functions: 1. setupMonkeypatch() - Intercept util.debuglog 2. mapNegatedBooleans() - Transform noDotfiles → dotfiles 3. handleUserCredentials() - Create user object or warn 4. warnDeprecatedParameters() - Warn about deprecated noSilent 5. appendCIMetadata() - Add CI environment metadata 6. injectTokenIntoRepoUrl() - Inject authentication tokens - prepareOptions() is now a clean orchestrator function - File: src/engine/engine.ts ### Intensive Tests - Add 34 comprehensive tests covering 100% of option transformation logic - Test every extracted function exhaustively with all edge cases - Covers all boolean combinations, CI environments, and token scenarios - File: src/engine/prepare-options.spec.ts (NEW) ## Phase 3: Export Public API (18 new tests) ### Public API Exports - Export Schema, PublishOptions, DeployUser, and other types - Export defaults configuration object - Export core functions (deployToGHPages, angularDeploy) - Export advanced functions (all prepareOptions helpers) - Users can now extend angular-cli-ghpages functionality - File: src/public_api.ts ### Public API Tests - Add 18 tests verifying all exports are accessible - Test type compilation and runtime function availability - Include example usage scenarios - File: src/public-api.spec.ts (NEW) ## Documentation - Add TEST_COVERAGE_PLAN.md documenting the complete plan - Includes implementation order, success criteria, and file listing - Documents context from PR #186 analysis ## Test Results - Test suites: 16 → 18 (+2) - Tests: 213 → 285 (+72, +34%) - Pass rate: 100% (285/285) - Zero regressions ## Breaking Changes None - all changes are backwards compatible. The refactoring maintains exact same behavior while adding exports and improving testability. ## Related - Addresses PR #186 preparation (gh-pages v3 → v6 upgrade) - Completes audit remediation priorities 7-10 - Enables future refactoring with test safety net
1 parent 00a087b commit ade5cff

File tree

8 files changed

+1622
-49
lines changed

8 files changed

+1622
-49
lines changed

TEST_COVERAGE_PLAN.md

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
# Test Coverage & Refactoring Plan
2+
3+
## Objectives
4+
1. **Add critical missing tests** (silent failures, monkeypatch, real filesystem)
5+
2. **Refactor prepareOptions()** to enable intensive testing of each option
6+
3. **Export public types** for user extensibility
7+
4. **Complete gh-pages-shell tests** for v6 upgrade preparation
8+
9+
---
10+
11+
## Phase 1: Critical Test Gaps (High Priority)
12+
13+
### 1.1 gh-pages Error Callback Tests
14+
**File:** `src/engine/engine.spec.ts`
15+
16+
Add tests for the "do NOT await" error handling:
17+
- Test: gh-pages.publish calls callback with error → promise rejects
18+
- Test: Error message is preserved through rejection
19+
- Test: Multiple error types (git push failed, auth failed, etc.)
20+
21+
**Why Critical:** Verifies we never fall into silent failure trap
22+
23+
### 1.2 Monkeypatch Verification Tests
24+
**File:** `src/engine/engine.spec.ts` (new describe block)
25+
26+
Add comprehensive monkeypatch tests:
27+
- Test: util.debuglog is replaced after prepareOptions()
28+
- Test: debuglog('gh-pages') calls forward to logger.info()
29+
- Test: debuglog('other-module') calls original implementation
30+
- Test: Message formatting (util.format with %s, %d args)
31+
- Test: Order dependency - monkeypatch happens before gh-pages require
32+
33+
**Why Critical:** ZERO coverage for critical interception logic
34+
35+
### 1.3 Real Filesystem Tests
36+
**File:** `src/engine/engine-filesystem.spec.ts` (NEW FILE)
37+
38+
Tests using real temp directories:
39+
- Test: .nojekyll file created with empty content
40+
- Test: CNAME file created with correct domain content
41+
- Test: 404.html is exact copy of index.html
42+
- Test: Files NOT created when dry-run=true
43+
- Test: CNAME write failure throws error with correct message
44+
- Test: .nojekyll write failure throws error
45+
- Test: 404.html copy fails gracefully (no index.html) - warns, continues
46+
- Test: Cleanup temp directory after each test
47+
48+
**Pattern:** Use `os.tmpdir()` + unique folder per test
49+
50+
---
51+
52+
## Phase 2: Refactor prepareOptions() + Intensive Tests
53+
54+
### 2.1 Extract Functions from prepareOptions()
55+
**File:** `src/engine/engine.ts`
56+
57+
Current prepareOptions() does 8 things (206 lines):
58+
1. Merge defaults with user options
59+
2. Setup monkeypatch
60+
3. Map negated boolean options (noDotfiles → dotfiles)
61+
4. Validate and combine user credentials
62+
5. Append CI environment metadata to messages
63+
6. Discover remote URL
64+
7. Inject authentication tokens
65+
8. Warn about deprecated parameters
66+
67+
**Refactor to:**
68+
```typescript
69+
// Keep as orchestrator
70+
export async function prepareOptions(origOptions: Schema, logger: logging.LoggerApi): Promise<PreparedOptions> {
71+
const options = mergeOptionsWithDefaults(origOptions);
72+
setupMonkeypatch(logger);
73+
mapNegatedBooleans(options, origOptions);
74+
handleUserCredentials(options, origOptions, logger);
75+
appendCIMetadata(options);
76+
await discoverAndInjectRemoteUrl(options);
77+
warnDeprecatedParameters(origOptions, logger);
78+
return options;
79+
}
80+
81+
// NEW: Extracted, testable functions
82+
function mergeOptionsWithDefaults(origOptions: Schema): PreparedOptions
83+
function mapNegatedBooleans(options: PreparedOptions, origOptions: Schema): void
84+
function handleUserCredentials(options: PreparedOptions, origOptions: Schema, logger: LoggerApi): void
85+
function appendCIMetadata(options: PreparedOptions): void
86+
async function discoverAndInjectRemoteUrl(options: PreparedOptions): Promise<void>
87+
function injectToken(repoUrl: string, token: string): string
88+
function warnDeprecatedParameters(origOptions: Schema, logger: LoggerApi): void
89+
```
90+
91+
### 2.2 Intensive Tests for Each Function
92+
**File:** `src/engine/prepare-options.spec.ts` (NEW FILE)
93+
94+
Test EVERY extracted function intensively:
95+
96+
**mergeOptionsWithDefaults:**
97+
- All 15 default values applied when not specified
98+
- User values override defaults
99+
- Partial options object works
100+
101+
**mapNegatedBooleans:**
102+
- noDotfiles: truedotfiles: false
103+
- noDotfiles: falsedotfiles: true
104+
- noDotfiles: undefineddotfiles: true (default)
105+
- Same pattern for noNotfound, noNojekyll
106+
107+
**handleUserCredentials:**
108+
- Both name + emailcreates user object
109+
- Only namewarning, no user object
110+
- Only emailwarning, no user object
111+
- Neitherno warning, no user object
112+
113+
**appendCIMetadata:**
114+
- Travis CI: Adds commit message, build URL, repo slug
115+
- CircleCI: Adds commit SHA, build URL, username/repo
116+
- GitHub Actions: Adds commit SHA, repository
117+
- No CI env: Message unchanged
118+
- Multiple CI envs: All metadata appended
119+
120+
**injectToken:**
121+
- GH_TOKEN: Injects x-access-token
122+
- PERSONAL_TOKEN: Injects x-access-token
123+
- GITHUB_TOKEN: Injects x-access-token
124+
- Legacy GH_TOKEN placeholder replacement
125+
- Token already present: No double injection
126+
- SSH URL: No injection
127+
- No token env var: URL unchanged
128+
- Token with special chars: Properly encoded
129+
130+
**warnDeprecatedParameters:**
131+
- noSilent: truewarning logged
132+
- noSilent: falsewarning logged
133+
- noSilent: undefinedno warning
134+
135+
**Coverage Goal:** 100% of prepareOptions logic tested
136+
137+
---
138+
139+
## Phase 3: Export Public Types
140+
141+
### 3.1 Create Public API
142+
**File:** `src/index.ts` (NEW FILE)
143+
144+
```typescript
145+
// Public API for users extending angular-cli-ghpages
146+
export { Schema } from './deploy/schema';
147+
export { GHPages, PublishOptions, DeployUser } from './interfaces';
148+
export { run as deploy } from './engine/engine';
149+
export { defaults } from './engine/defaults';
150+
151+
// Advanced: For custom builders
152+
export { deploy as deployAction } from './deploy/actions';
153+
```
154+
155+
### 3.2 Update package.json
156+
Add `"types": "index.d.ts"` to package.json
157+
158+
### 3.3 Test Public API
159+
**File:** `src/public-api.spec.ts` (NEW FILE)
160+
161+
- Test: All exports are defined
162+
- Test: Types can be imported by consumers
163+
- Test: Example usage compiles
164+
165+
---
166+
167+
## Phase 4: Complete gh-pages-shell Tests
168+
169+
### 4.1 Finish Shell Integration Tests
170+
**File:** `src/parameter-tests/gh-pages-shell.spec.ts`
171+
172+
Currently has helper infrastructure, needs actual tests:
173+
174+
- Test: Git commands match v3 baseline (record current behavior)
175+
- Test: Verify git config user.name / user.email set correctly
176+
- Test: Verify git remote matches repo URL
177+
- Test: Verify git add includes/excludes dotfiles based on flag
178+
- Test: Verify git commit message matches expected format
179+
- Test: Capture full git command sequence
180+
181+
**Purpose:** Baseline for verifying v6 upgrade doesn't break git behavior
182+
183+
### 4.2 Document v3 Baseline
184+
Create snapshot of git commands for comparison when testing v6
185+
186+
---
187+
188+
## Implementation Order
189+
190+
### Sprint 1: Critical Tests (Day 1-2)
191+
1.gh-pages error callback tests
192+
2.Monkeypatch verification tests
193+
3.Real filesystem tests
194+
195+
### Sprint 2: Refactor + Intensive Tests (Day 3-5)
196+
4.Extract functions from prepareOptions
197+
5.Add intensive tests for each extracted function
198+
6. ✅ Verify all 213 existing tests still pass
199+
7. ✅ Verify test coverage increases significantly
200+
201+
### Sprint 3: Public API + Shell Tests (Day 6-7)
202+
8.Create and test public API exports
203+
9.Complete gh-pages-shell integration tests
204+
10.Document v3 baseline behavior
205+
206+
---
207+
208+
## Success Criteria
209+
210+
- **Test Count:** 213~320+ tests
211+
- **Coverage:** All critical paths tested (error callbacks, monkeypatch, file creation)
212+
- **Refactoring:** prepareOptions split into 7-8 testable functions
213+
- **Public API:** Types exported for user extensibility
214+
- **Upgrade Prep:** v3 git behavior documented for v6 comparison
215+
- **Quality:** Zero regressions, all tests passing, no 'any' types
216+
217+
---
218+
219+
## Files to Create/Modify
220+
221+
**New Files:**
222+
- `src/engine/engine-filesystem.spec.ts` (real FS tests)
223+
- `src/engine/prepare-options.spec.ts` (intensive option tests)
224+
- `src/index.ts` (public API)
225+
- `src/public-api.spec.ts` (API tests)
226+
227+
**Modified Files:**
228+
- `src/engine/engine.ts` (refactor prepareOptions)
229+
- `src/engine/engine.spec.ts` (add error + monkeypatch tests)
230+
- `src/parameter-tests/gh-pages-shell.spec.ts` (complete shell tests)
231+
- `src/package.json` (add types field)
232+
- `src/interfaces.ts` (ensure all types are exportable)
233+
234+
**Estimated:** ~8 files created/modified, ~110 new tests added
235+
236+
---
237+
238+
## Context: Why This Plan
239+
240+
This plan addresses critical findings from:
241+
1. **PR #186 Analysis** - Need robust tests before gh-pages v6 upgrade
242+
2. **Audit Remediation** - Priorities 1-6 complete, now addressing test gaps
243+
3. **User Request** - "intensively test the shit out of this" for prepareOptions
244+
4. **Current Gaps** - Zero monkeypatch coverage, all file tests use mocks
245+
246+
The refactoring enables the intensive testing you requested while maintaining backward compatibility.

src/angular-cli-ghpages

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ commander
5151
)
5252
.option(
5353
'-S, --no-silent',
54-
'Deprecated! This paremeter is no longer needed. It will be ignored.'
54+
'Deprecated! This parameter is no longer needed. It will be ignored.'
5555
)
5656
.option(
5757
'-T, --no-dotfiles',

0 commit comments

Comments
 (0)