Skip to content

Commit 75b8e0b

Browse files
committed
Task #207 Stage 4: 테스트 이전 + Firefox 특화 케이스 + build.mjs dereference
- rhwp-chrome/sw/download-interceptor.test.js 삭제 - rhwp-shared/sw/download-interceptor-common.test.js 신규 (기존 23건 + Firefox 특화 3건) · Firefox onCreated: url/mime/referrer 단독 감지 · Firefox onChanged: filename 확정 후 일반 파일 미감지 - rhwp-chrome/build.mjs, rhwp-firefox/build.mjs · sw/ 복사 시 dereference: true 추가 — 심링크를 실체 파일로 복사 · Firefox copy() 헬퍼에 options 인자 추가 + EXCLUDE_FROM_DIST 도입 - node --test: 26 pass / 0 fail closes #207
1 parent 5381ca8 commit 75b8e0b

3 files changed

Lines changed: 48 additions & 7 deletions

File tree

rhwp-chrome/build.mjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,11 @@ copy(resolve(__dirname, 'background.js'), resolve(DIST, 'background.js'));
6868
copy(resolve(__dirname, 'content-script.js'), resolve(DIST, 'content-script.js'));
6969
copy(resolve(__dirname, 'content-script.css'), resolve(DIST, 'content-script.css'));
7070
copy(resolve(__dirname, 'dev-tools-inject.js'), resolve(DIST, 'dev-tools-inject.js'));
71+
// sw/ 는 download-interceptor-common.js 심링크(→ rhwp-shared/sw/)를 포함하므로
72+
// dereference: true 로 실체 파일 복사 (패키징된 확장에서 상대 경로 의존성 제거).
7173
copy(resolve(__dirname, 'sw'), resolve(DIST, 'sw'), {
7274
filter: (src) => !EXCLUDE_FROM_DIST.test(src),
75+
dereference: true,
7376
});
7477
copy(resolve(__dirname, 'options.html'), resolve(DIST, 'options.html'));
7578
copy(resolve(__dirname, 'options.js'), resolve(DIST, 'options.js'));

rhwp-firefox/build.mjs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,18 @@ function run(cmd, cwd = __dirname) {
1818
execSync(cmd, { stdio: 'inherit', cwd });
1919
}
2020

21-
function copy(src, dest) {
21+
function copy(src, dest, options = {}) {
2222
if (!existsSync(src)) {
2323
console.warn(` SKIP (not found): ${src}`);
2424
return;
2525
}
26-
cpSync(src, dest, { recursive: true });
26+
cpSync(src, dest, { recursive: true, ...options });
2727
console.log(` COPY: ${src}${dest}`);
2828
}
2929

30+
/** 배포본에서 제외할 파일 패턴 (테스트 등). */
31+
const EXCLUDE_FROM_DIST = /\.(test|spec)\.[mc]?[jt]sx?$/i;
32+
3033
console.log('=== rhwp-firefox 빌드 시작 ===\n');
3134

3235
// 1. Vite 빌드 (rhwp-studio → dist/)
@@ -58,7 +61,12 @@ copy(resolve(__dirname, 'background.js'), resolve(DIST, 'background.js'));
5861
copy(resolve(__dirname, 'content-script.js'), resolve(DIST, 'content-script.js'));
5962
copy(resolve(__dirname, 'content-script.css'), resolve(DIST, 'content-script.css'));
6063
copy(resolve(__dirname, 'dev-tools-inject.js'), resolve(DIST, 'dev-tools-inject.js'));
61-
copy(resolve(__dirname, 'sw'), resolve(DIST, 'sw'));
64+
// sw/ 는 download-interceptor-common.js 심링크(→ rhwp-shared/sw/)를 포함하므로
65+
// dereference: true 로 실체 파일 복사 (패키징된 확장에서 상대 경로 의존성 제거).
66+
copy(resolve(__dirname, 'sw'), resolve(DIST, 'sw'), {
67+
filter: (src) => !EXCLUDE_FROM_DIST.test(src),
68+
dereference: true,
69+
});
6270
copy(resolve(__dirname, 'options.html'), resolve(DIST, 'options.html'));
6371
copy(resolve(__dirname, 'options.js'), resolve(DIST, 'options.js'));
6472

rhwp-chrome/sw/download-interceptor.test.js renamed to rhwp-shared/sw/download-interceptor-common.test.js

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
// #198: shouldInterceptDownload 단위 테스트
1+
// shouldInterceptDownload 단위 테스트 (#198 / #207)
22
//
3-
// 실행: node --test rhwp-chrome/sw/download-interceptor.test.js
3+
// 실행: node --test rhwp-shared/sw/download-interceptor-common.test.js
44
//
5-
// Chrome API 와 무관한 순수 함수만 테스트. 인터셉터 등록 / handleHwpDownload 자체는
6-
// 작업지시자 수동 검증 (Stage 3) 에서 통합 검증.
5+
// 브라우저 API 에 의존하지 않는 순수 함수만 테스트.
6+
// Chrome(onDeterminingFilename) / Firefox(onCreated+onChanged) 양쪽에서 동일하게 사용.
77

88
import { test } from 'node:test';
99
import { strict as assert } from 'node:assert';
@@ -182,3 +182,33 @@ test('DEXT5 변종 확장자 (.jsp/.do) 도 차단', () => {
182182
false,
183183
);
184184
});
185+
186+
// ─── Firefox 특화: onCreated / onChanged 단계별 시나리오 (#207) ─
187+
188+
test('Firefox onCreated: url만 있고 filename/mime 없어도 감지', () => {
189+
// browser.downloads.onCreated 시점에는 filename 이 아직 없을 수 있음
190+
assert.equal(
191+
shouldInterceptDownload({ id: 1, url: 'https://example.com/a.hwp' }),
192+
true,
193+
);
194+
});
195+
196+
test('Firefox onCreated: url/filename 없고 mime 만으로 감지', () => {
197+
// Content-Disposition 없이 MIME 으로만 HWP 알 수 있는 경우
198+
assert.equal(
199+
shouldInterceptDownload({ id: 2, mime: 'application/x-hwp' }),
200+
true,
201+
);
202+
});
203+
204+
test('Firefox onChanged: filename 확정 후 일반 파일은 미감지', () => {
205+
// onCreated 에서 판정 불가 → onChanged 에서 filename 확정 → 일반 zip 이면 인터셉트 포기
206+
assert.equal(
207+
shouldInterceptDownload({
208+
id: 3,
209+
filename: 'a.zip',
210+
url: 'https://example.com/download?id=123',
211+
}),
212+
false,
213+
);
214+
});

0 commit comments

Comments
 (0)