test(cms): partner-logo test uses unique names and only cleans its own files
CI Pipeline with Test Management / 🧪 Run Tests & Generate Reports (push) Waiting to run
CI Pipeline with Test Management / 🐳 Docker Integration Tests (push) Blocked by required conditions
CI Pipeline with Test Management / 🏗️ Build Docker Image (push) Blocked by required conditions
CI Pipeline with Test Management / 📊 Generate Test Summary (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🧪 Run Tests & Generate Reports (push) Waiting to run
Test Reporting & Gherkin Analysis / 📊 Analyze Test Coverage (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🔄 Sync with Linear (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / ⚡ Performance Monitoring (push) Blocked by required conditions
CI Pipeline with Test Management / 🧪 Run Tests & Generate Reports (push) Waiting to run
CI Pipeline with Test Management / 🐳 Docker Integration Tests (push) Blocked by required conditions
CI Pipeline with Test Management / 🏗️ Build Docker Image (push) Blocked by required conditions
CI Pipeline with Test Management / 📊 Generate Test Summary (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🧪 Run Tests & Generate Reports (push) Waiting to run
Test Reporting & Gherkin Analysis / 📊 Analyze Test Coverage (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🔄 Sync with Linear (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / ⚡ Performance Monitoring (push) Blocked by required conditions
The previous cleanup emptied proto/public/partners/ entirely, deleting real committed partner logos during the pre-deploy run. Now the test uploads to unique run-specific filenames and removes only those.
This commit is contained in:
@@ -134,9 +134,11 @@ async function main() {
|
|||||||
|
|
||||||
// 4. partner logo upload (MITHOME-83)
|
// 4. partner logo upload (MITHOME-83)
|
||||||
const partnerDir = path.join(ROOT, 'proto', 'public', 'partners');
|
const partnerDir = path.join(ROOT, 'proto', 'public', 'partners');
|
||||||
const partnerFile = path.join(partnerDir, 'acme.png');
|
// Unique names so the test never collides with real partner logos.
|
||||||
|
const runId = process.pid + '-' + Date.now();
|
||||||
|
const created = [];
|
||||||
try {
|
try {
|
||||||
const up = await fetch(`${BASE}/partner-logo?name=acme`, {
|
const up = await fetch(`${BASE}/partner-logo?name=acme-${runId}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'image/png', 'X-CSRF-Token': csrf, 'Cookie': cookie },
|
headers: { 'Content-Type': 'image/png', 'X-CSRF-Token': csrf, 'Cookie': cookie },
|
||||||
body: TINY_PNG,
|
body: TINY_PNG,
|
||||||
@@ -144,11 +146,12 @@ async function main() {
|
|||||||
assert.equal(up.status, 200);
|
assert.equal(up.status, 200);
|
||||||
const body = await up.json();
|
const body = await up.json();
|
||||||
assert.equal(body.ok, true);
|
assert.equal(body.ok, true);
|
||||||
assert.equal(body.path, '/partners/acme.png');
|
assert.equal(body.path, `/partners/acme-${runId}.png`);
|
||||||
assert.ok(fs.existsSync(partnerFile), 'partner logo file created');
|
created.push(path.join(partnerDir, `acme-${runId}.png`));
|
||||||
|
assert.ok(fs.existsSync(created[0]), 'partner logo file created');
|
||||||
|
|
||||||
// non-PNG → 415
|
// non-PNG → 415
|
||||||
const bad = await fetch(`${BASE}/partner-logo?name=x`, {
|
const bad = await fetch(`${BASE}/partner-logo?name=x-${runId}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'image/png', 'X-CSRF-Token': csrf, 'Cookie': cookie },
|
headers: { 'Content-Type': 'image/png', 'X-CSRF-Token': csrf, 'Cookie': cookie },
|
||||||
body: Buffer.from('not a png'),
|
body: Buffer.from('not a png'),
|
||||||
@@ -156,7 +159,7 @@ async function main() {
|
|||||||
assert.equal(bad.status, 415);
|
assert.equal(bad.status, 415);
|
||||||
|
|
||||||
// traversal name is sanitized (no path escape)
|
// traversal name is sanitized (no path escape)
|
||||||
const trav = await fetch(`${BASE}/partner-logo?name=../evil`, {
|
const trav = await fetch(`${BASE}/partner-logo?name=../evil-${runId}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'image/png', 'X-CSRF-Token': csrf, 'Cookie': cookie },
|
headers: { 'Content-Type': 'image/png', 'X-CSRF-Token': csrf, 'Cookie': cookie },
|
||||||
body: TINY_PNG,
|
body: TINY_PNG,
|
||||||
@@ -165,11 +168,10 @@ async function main() {
|
|||||||
const tBody = await trav.json();
|
const tBody = await trav.json();
|
||||||
assert.ok(tBody.path.startsWith('/partners/'), 'traversal name is sanitized to a safe slug');
|
assert.ok(tBody.path.startsWith('/partners/'), 'traversal name is sanitized to a safe slug');
|
||||||
assert.ok(!tBody.path.includes('..'), 'no traversal in the returned path');
|
assert.ok(!tBody.path.includes('..'), 'no traversal in the returned path');
|
||||||
|
created.push(path.join(ROOT, 'proto', 'public', tBody.path));
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
for (const f of created) { try { fs.unlinkSync(f); } catch { /* noop */ } }
|
||||||
for (const f of fs.readdirSync(partnerDir)) fs.unlinkSync(path.join(partnerDir, f));
|
try { fs.rmdirSync(partnerDir); } catch { /* only removes when empty */ }
|
||||||
fs.rmdirSync(partnerDir);
|
|
||||||
} catch { /* best effort */ }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Content Editor logo upload test: OK');
|
console.log('Content Editor logo upload test: OK');
|
||||||
|
|||||||
Reference in New Issue
Block a user