Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
4a2e7c4
🔖 Auto bump patch version to v1.16.1
hyesngy Oct 31, 2025
f7992cb
feat: 테스트 코드 작성 완료
yeonjin719 Nov 3, 2025
01bd06c
feat: gitignore 수정
yeonjin719 Nov 3, 2025
08836fc
fix: lock 파일 오류 해결
yeonjin719 Nov 3, 2025
507bb24
🔥delete: playwright 결과 삭제
yeonjin719 Nov 3, 2025
1166960
feat: 가독성 좋게 설명 추가
yeonjin719 Nov 3, 2025
481cd81
style: test 화면 색상 변경 및 디자인 변경
yeonjin719 Nov 3, 2025
887decd
style: 반응형 수정
yeonjin719 Nov 3, 2025
2183d7d
Merge pull request #87 from 2025-OSDC/feature/#86
yeonjin719 Nov 5, 2025
0da94f0
🔖 Auto bump minor version to v1.17.0
hyesngy Nov 5, 2025
275b66f
Merge pull request #90 from 2025-OSDC/develop
yeonjin719 Feb 19, 2026
560c794
🔖 Auto bump minor version to v1.18.0
hyesngy Feb 19, 2026
e42506d
🔖 bump version to v1.18.1
yeonjin719 Feb 19, 2026
70faf1e
🔖 Auto bump minor version to v1.19.0
hyesngy Feb 19, 2026
4529d1d
🔖 bump version to v1.19.1
yeonjin719 Feb 19, 2026
e6afd7e
🔖 Auto bump minor version to v1.20.0
hyesngy Feb 19, 2026
86bfd01
chore(deps-dev): bump vite from 6.4.1 to 6.4.2 in /e2e/site
dependabot[bot] Apr 7, 2026
e2093ae
Merge pull request #91 from 2025-OSDC/dependabot/npm_and_yarn/e2e/sit…
yeonjin719 Apr 8, 2026
9e62bb3
🔖 Auto bump minor version to v1.21.0
hyesngy Apr 8, 2026
bd21ea3
chore(deps): bump brace-expansion from 1.1.12 to 5.0.6 (via audit fix)
dependabot[bot] May 18, 2026
979b339
ci: pin pnpm and use node 22
yeonjin719 May 19, 2026
2005dd4
Merge pull request #92 from 2025-OSDC/dependabot/npm_and_yarn/brace-e…
yeonjin719 May 19, 2026
6285a3b
🔖 Auto bump patch version to v1.21.1
hyesngy May 19, 2026
b578f39
chore(deps): bump postcss from 8.5.6 to 8.5.10
dependabot[bot] May 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ jobs:
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: latest
version: 10.23.0

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
node-version: "22"
cache: "pnpm"
registry-url: "https://registry.npmjs.org"

Expand Down
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
node_modules/
dist/
tmp/
test-results/
playwright-report/
e2e/site/playwright-report/
.env
# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,macos,windows
# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,macos,windows
Expand Down Expand Up @@ -85,4 +89,4 @@ $RECYCLE.BIN/
# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,macos,windows

*.tgz
colbrush-*.tgz
colbrush-*.tgz
12 changes: 12 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Exclude development and test assets from published packages
e2e/
scripts/
test-results/
tmp/

# Ignore repository-specific artifacts
*.tgz
*.log
.DS_Store
.vscode/
node_modules/
8 changes: 8 additions & 0 deletions e2e/cli/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "colbrush-cli-e2e",
"private": true,
"type": "module",
"scripts": {
"test": "node --test tests/*.test.mjs"
}
}
152 changes: 152 additions & 0 deletions e2e/cli/tests/cli.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import { before, after, test } from 'node:test';
import assert from 'node:assert/strict';
import path from 'node:path';
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { spawn } from 'node:child_process';
import { mkdtemp, readFile, cp, rm } from 'node:fs/promises';
import { tmpdir } from 'node:os';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(__dirname, '../../..');
const cliEntry = path.join(repoRoot, 'dist/cli.cjs');
const fixtureCss = path.join(repoRoot, 'e2e/site/src/index.css');
const packageVersion = JSON.parse(
readFileSync(path.join(repoRoot, 'package.json'), 'utf8')
).version;

const sandboxes = [];

const runProcess = (command, args, options = {}) =>
new Promise((resolve, reject) => {
const child = spawn(command, args, {
cwd: options.cwd ?? repoRoot,
env: { ...process.env, ...options.env },
stdio: options.inheritStdio ? 'inherit' : 'pipe',
});

if (options.inheritStdio) {
child.on('exit', (code) => {
resolve({ code, stdout: '', stderr: '' });
});
child.on('error', reject);
return;
}

let stdout = '';
let stderr = '';

child.stdout?.on('data', (chunk) => {
stdout += chunk.toString();
});
child.stderr?.on('data', (chunk) => {
stderr += chunk.toString();
});

child.on('exit', (code) => {
resolve({ code, stdout, stderr });
});
child.on('error', reject);
});

before(async () => {
console.log('🛠️ 라이브러리 빌드를 준비 중입니다...\n');
const buildResult = await runProcess('pnpm', ['build'], {
inheritStdio: true,
});
if (buildResult.code !== 0) {
throw new Error('Failed to build library before CLI tests');
}
console.log('\n✅ 라이브러리 빌드 완료\n');
});

after(async () => {
await Promise.all(
sandboxes.map((dir) => rm(dir, { recursive: true, force: true }))
);
});

async function createSandbox() {
const sandboxRoot = await mkdtemp(path.join(tmpdir(), 'colbrush-cli-'));
const targetCssPath = path.join(sandboxRoot, 'input.css');
await cp(fixtureCss, targetCssPath);
sandboxes.push(sandboxRoot);
return { sandboxRoot, cssPath: targetCssPath };
}

async function runCli(args, options) {
return runProcess(process.execPath, [cliEntry, ...args], options);
}

test('prints version information with --version flag', async () => {
const result = await runCli(['--version']);

assert.equal(result.code, 0);
assert.ok(
result.stdout.includes(`Colbrush v${packageVersion}`),
`CLI stdout should contain version banner, got: ${result.stdout}`
);
});

test('displays usage instructions with --help', async () => {
const result = await runCli(['--help']);

assert.equal(result.code, 0);
const normalized = result.stdout.replace(/\u001B\[[0-9;]*m/g, '');
assert.ok(
normalized.includes('USAGE'),
'도움말에는 "USAGE" 섹션이 포함되어야 합니다'
);
assert.ok(
normalized.includes('Generate color-blind accessible themes'),
'도움말에는 generate 명령 설명이 포함되어야 합니다'
);
});

test('generates themed CSS and report for a valid input file', async () => {
const { sandboxRoot, cssPath } = await createSandbox();
const reportPath = path.join(sandboxRoot, 'report.json');

const result = await runCli(
['generate', `--css=${cssPath}`, `--json=${reportPath}`],
{ cwd: sandboxRoot }
);

assert.equal(
result.code,
0,
`CLI exited with non-zero code: ${result.stderr}`
);
assert.ok(
result.stdout.includes('All themes generated successfully'),
'CLI는 성공적으로 완료되었다는 메시지를 출력해야 합니다'
);

const cssOutput = await readFile(cssPath, 'utf8');
assert.match(
cssOutput,
/\[data-theme='protanopia']\s*{[\s\S]+--color-primary-500:/,
'CSS file should contain the protanopia theme block'
);
assert.match(
cssOutput,
/\[data-theme='deuteranopia']\s*{[\s\S]+--color-primary-500:/,
'CSS file should contain the deuteranopia theme block'
);
assert.match(
cssOutput,
/\[data-theme='tritanopia']\s*{[\s\S]+--color-primary-500:/,
'CSS file should contain the tritanopia theme block'
);

const jsonReportRaw = await readFile(reportPath, 'utf8');
const jsonReport = JSON.parse(jsonReportRaw);

assert.equal(jsonReport.input, cssPath);
assert.equal(jsonReport.exitCode, 0);
assert.equal(jsonReport.themes.length, 3);
assert.ok(
jsonReport.variables.processed >= 4,
`Expected at least 4 processed variables, got ${jsonReport.variables.processed}`
);
});
12 changes: 12 additions & 0 deletions e2e/site/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Colbrush E2E Playground</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
28 changes: 28 additions & 0 deletions e2e/site/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "colbrush-e2e-site",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"test:e2e": "node ../../scripts/run-site-e2e.mjs"
},
"dependencies": {
"@tailwindcss/vite": "^4.1.16",
"colbrush": "link:../../",
"playwright": "^1.56.1",
"playwright-core": "^1.56.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"tailwindcss": "^4.1.16"
},
"devDependencies": {
"@playwright/test": "1.56.1",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
"@vitejs/plugin-react": "^5.1.0",
"typescript": "^5.8.0",
"vite": "^6.4.2"
}
}
31 changes: 31 additions & 0 deletions e2e/site/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { defineConfig, devices } from '@playwright/test';

const useExternalServer =
process.env.PLAYWRIGHT_EXTERNAL_SERVER === '1' ||
process.env.PLAYWRIGHT_SKIP_WEB_SERVER === '1';

export default defineConfig({
testDir: './tests',
fullyParallel: false,
retries: process.env.CI ? 2 : 0,
reporter: [['list'], ['html', { outputFolder: 'playwright-report', open: 'never' }]],
use: {
baseURL: 'http://127.0.0.1:4173',
trace: 'retain-on-failure',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
webServer: useExternalServer
? undefined
: {
command: 'pnpm dev -- --host 127.0.0.1 --port 4173',
url: 'http://127.0.0.1:4173',
reuseExistingServer: !process.env.CI,
stdout: 'pipe',
stderr: 'pipe',
},
});
Loading
Loading