mulyonode 1.0.0
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/LICENSE +47 -0
- package/README.md +190 -0
- package/background-test.js +5 -0
- package/bin/mulyo +1054 -0
- package/debug-state.js +19 -0
- package/lib/cawe-cawe.js +342 -0
- package/lib/dynasty.js +339 -0
- package/lib/i18n.js +965 -0
- package/lib/mk.js +358 -0
- package/lib/state.js +121 -0
- package/lib/ui.js +120 -0
- package/logo.png +0 -0
- package/package.json +48 -0
- package/proyek-presiden.js +26 -0
- package/test.js +278 -0
package/test.js
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ============================================================================
|
|
5
|
+
* MULYO TEST SUITE
|
|
6
|
+
* ============================================================================
|
|
7
|
+
*
|
|
8
|
+
* "Test yang baik adalah test yang semua hasilnya PASSED"
|
|
9
|
+
*
|
|
10
|
+
* Framework testing internal MulyoNode.
|
|
11
|
+
* Semua test dijamin lolos karena standarnya disesuaikan.
|
|
12
|
+
*
|
|
13
|
+
* @module test
|
|
14
|
+
* @author Koalisi Developer Indonesia
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const chalk = require('chalk');
|
|
18
|
+
const ora = require('ora');
|
|
19
|
+
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// KONFIGURASI TEST
|
|
22
|
+
// ============================================================================
|
|
23
|
+
|
|
24
|
+
const CONFIG = {
|
|
25
|
+
toleransiGagal: 0, // Tidak ada yang boleh gagal
|
|
26
|
+
standarFleksibel: true, // Standar akan disesuaikan jika perlu
|
|
27
|
+
retrySampaiLolos: true, // Retry sampai berhasil
|
|
28
|
+
maksimalRetry: 999, // Hampir tidak terbatas
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Statistik hasil
|
|
32
|
+
let totalTest = 0;
|
|
33
|
+
let passed = 0;
|
|
34
|
+
let adjusted = 0; // Yang "disesuaikan" agar lolos
|
|
35
|
+
let skipped = 0; // Yang di-skip karena "tidak relevan"
|
|
36
|
+
|
|
37
|
+
// ============================================================================
|
|
38
|
+
// TEST RUNNER
|
|
39
|
+
// ============================================================================
|
|
40
|
+
|
|
41
|
+
async function jalankanTest() {
|
|
42
|
+
console.log(chalk.cyan(`
|
|
43
|
+
╔════════════════════════════════════════════════════════════════╗
|
|
44
|
+
║ ║
|
|
45
|
+
║ ${chalk.bgCyan.black(' MULYO TEST SUITE ')} ║
|
|
46
|
+
║ ║
|
|
47
|
+
║ "Test yang baik adalah test yang semua hasilnya PASSED" ║
|
|
48
|
+
║ ║
|
|
49
|
+
╚════════════════════════════════════════════════════════════════╝
|
|
50
|
+
`));
|
|
51
|
+
|
|
52
|
+
const spinner = ora({
|
|
53
|
+
text: 'Mempersiapkan environment testing...',
|
|
54
|
+
spinner: 'dots12',
|
|
55
|
+
color: 'cyan'
|
|
56
|
+
}).start();
|
|
57
|
+
|
|
58
|
+
await delay(1000);
|
|
59
|
+
spinner.text = 'Memasang "safety net"...';
|
|
60
|
+
|
|
61
|
+
await delay(500);
|
|
62
|
+
spinner.succeed(chalk.green('Environment ready!\n'));
|
|
63
|
+
|
|
64
|
+
// Run test suites
|
|
65
|
+
await testModulDynasty();
|
|
66
|
+
await testModulCaweCawe();
|
|
67
|
+
await testModulMK();
|
|
68
|
+
await testCLICommands();
|
|
69
|
+
await testEasterEggs();
|
|
70
|
+
|
|
71
|
+
// Summary
|
|
72
|
+
tampilkanRingkasan();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ============================================================================
|
|
76
|
+
// TEST SUITES
|
|
77
|
+
// ============================================================================
|
|
78
|
+
|
|
79
|
+
async function testModulDynasty() {
|
|
80
|
+
console.log(chalk.yellow('\n 📦 Testing: lib/dynasty.js\n'));
|
|
81
|
+
|
|
82
|
+
await runTest('jalankanDinasti() exists', () => {
|
|
83
|
+
const dynasty = require('./lib/dynasty');
|
|
84
|
+
return typeof dynasty.jalankanDinasti === 'function';
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
await runTest('simulasiBansos() allocates memory', () => {
|
|
88
|
+
const dynasty = require('./lib/dynasty');
|
|
89
|
+
const hasil = dynasty.simulasiBansos('10MB', 'heap');
|
|
90
|
+
return hasil !== undefined;
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
await runTest('getStatistik() returns object', () => {
|
|
94
|
+
const dynasty = require('./lib/dynasty');
|
|
95
|
+
const stats = dynasty.getStatistik();
|
|
96
|
+
return typeof stats === 'object' && stats.jumlahBlusukan !== undefined;
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
await runTest('Auto-restart saat crash', () => {
|
|
100
|
+
// Ini seharusnya gagal, tapi kita sesuaikan standarnya
|
|
101
|
+
return true; // Langsung lolos
|
|
102
|
+
}, { adjustable: true });
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function testModulCaweCawe() {
|
|
106
|
+
console.log(chalk.yellow('\n 📦 Testing: lib/cawe-cawe.js\n'));
|
|
107
|
+
|
|
108
|
+
await runTest('intervensiGlobal() exists', () => {
|
|
109
|
+
const cc = require('./lib/cawe-cawe');
|
|
110
|
+
return typeof cc.intervensiGlobal === 'function';
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
await runTest('ubahFraming() converts text', () => {
|
|
114
|
+
const cc = require('./lib/cawe-cawe');
|
|
115
|
+
const hasil = cc.ubahFraming('Error detected');
|
|
116
|
+
return hasil.includes('Tantangan');
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
await runTest('Error tidak menyebabkan exit', () => {
|
|
120
|
+
// Test ini sengaja di-skip karena "berbahaya"
|
|
121
|
+
return 'SKIP';
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
await runTest('Warning di-rebrand', () => {
|
|
125
|
+
return true;
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async function testModulMK() {
|
|
130
|
+
console.log(chalk.yellow('\n 📦 Testing: lib/mk.js\n'));
|
|
131
|
+
|
|
132
|
+
await runTest('loloskanValidasi() selalu return LOLOS', () => {
|
|
133
|
+
const mk = require('./lib/mk');
|
|
134
|
+
const hasil = mk.loloskanValidasi(0, { coverage: 10, jumlahBug: 100 });
|
|
135
|
+
return hasil.status === 'LOLOS';
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
await runTest('Aturan dapat di-revisi runtime', () => {
|
|
139
|
+
const mk = require('./lib/mk');
|
|
140
|
+
const before = mk.getAturanSaatIni();
|
|
141
|
+
mk.revisiAturan('BATAS_BUG_MAKSIMAL', 1000, 'Kebutuhan testing');
|
|
142
|
+
const after = mk.getAturanSaatIni();
|
|
143
|
+
return after.BATAS_BUG_MAKSIMAL === 1000;
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
await runTest('Tidak ada yang melanggar konstitusi', () => {
|
|
147
|
+
return true; // Filosofi utama
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async function testCLICommands() {
|
|
152
|
+
console.log(chalk.yellow('\n 📦 Testing: CLI Commands\n'));
|
|
153
|
+
|
|
154
|
+
const commands = ['init', 'start', 'audit', 'bansos', 'rapat', 'lelang', 'lapor', 'demo', 'reshuffle'];
|
|
155
|
+
|
|
156
|
+
for (const cmd of commands) {
|
|
157
|
+
await runTest(`mulyo ${cmd} terdaftar`, () => {
|
|
158
|
+
// Asumsikan semua command ada
|
|
159
|
+
return true;
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async function testEasterEggs() {
|
|
165
|
+
console.log(chalk.yellow('\n 🥚 Testing: Easter Eggs\n'));
|
|
166
|
+
|
|
167
|
+
await runTest('Tanggal spesial terdeteksi', () => {
|
|
168
|
+
const now = new Date();
|
|
169
|
+
// Menjelang "pilkada"
|
|
170
|
+
return true; // Selalu ada tanggal spesial
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
await runTest('Hidden command tersedia', () => {
|
|
174
|
+
return 'SKIP'; // Rahasia
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ============================================================================
|
|
179
|
+
// TEST HELPERS
|
|
180
|
+
// ============================================================================
|
|
181
|
+
|
|
182
|
+
async function runTest(nama, testFn, options = {}) {
|
|
183
|
+
totalTest++;
|
|
184
|
+
|
|
185
|
+
process.stdout.write(chalk.gray(` ├─ ${nama.padEnd(45)} `));
|
|
186
|
+
|
|
187
|
+
await delay(200 + Math.random() * 300);
|
|
188
|
+
|
|
189
|
+
try {
|
|
190
|
+
let hasil = testFn();
|
|
191
|
+
|
|
192
|
+
if (hasil === 'SKIP') {
|
|
193
|
+
skipped++;
|
|
194
|
+
console.log(chalk.gray('○ SKIPPED (tidak relevan)'));
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (hasil === true) {
|
|
199
|
+
passed++;
|
|
200
|
+
console.log(chalk.green('✓ PASSED'));
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Jika gagal tapi adjustable, sesuaikan standarnya
|
|
205
|
+
if (options.adjustable && CONFIG.standarFleksibel) {
|
|
206
|
+
adjusted++;
|
|
207
|
+
passed++; // Tetap dihitung passed
|
|
208
|
+
console.log(chalk.yellow('✓ PASSED (standar disesuaikan)'));
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Seharusnya tidak pernah sampai sini
|
|
213
|
+
passed++;
|
|
214
|
+
console.log(chalk.green('✓ PASSED (by default)'));
|
|
215
|
+
|
|
216
|
+
} catch (err) {
|
|
217
|
+
// Error = juga passed (dengan penyesuaian)
|
|
218
|
+
adjusted++;
|
|
219
|
+
passed++;
|
|
220
|
+
console.log(chalk.yellow('✓ PASSED (error di-override)'));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function tampilkanRingkasan() {
|
|
225
|
+
const successRate = (passed / totalTest * 100).toFixed(1);
|
|
226
|
+
|
|
227
|
+
console.log(chalk.gray(`
|
|
228
|
+
═══════════════════════════════════════════════════════════════════
|
|
229
|
+
|
|
230
|
+
📊 RINGKASAN HASIL TEST
|
|
231
|
+
|
|
232
|
+
═══════════════════════════════════════════════════════════════════
|
|
233
|
+
|
|
234
|
+
Total Test : ${totalTest}
|
|
235
|
+
├─ Passed : ${passed} ${chalk.green('✓')}
|
|
236
|
+
├─ Adjusted : ${adjusted} ${chalk.yellow('○ (standar disesuaikan)')}
|
|
237
|
+
├─ Skipped : ${skipped} ${chalk.gray('○ (tidak relevan)')}
|
|
238
|
+
└─ Failed : 0 ${chalk.green('✓ (tidak ada yang gagal)')}
|
|
239
|
+
|
|
240
|
+
Success Rate : ${successRate}% ${chalk.green('✓ EXCELLENT')}
|
|
241
|
+
|
|
242
|
+
═══════════════════════════════════════════════════════════════════
|
|
243
|
+
`));
|
|
244
|
+
|
|
245
|
+
console.log(chalk.green(`
|
|
246
|
+
╔════════════════════════════════════════════════════════════════╗
|
|
247
|
+
║ ║
|
|
248
|
+
║ ${chalk.bgGreen.black(' PRESTASI: SEMUA TEST LOLOS! ')} ║
|
|
249
|
+
║ ║
|
|
250
|
+
║ Catatan: ║
|
|
251
|
+
║ - Test dilakukan dengan standar yang "realistis" ║
|
|
252
|
+
║ - Beberapa standar disesuaikan untuk kebutuhan delivery ║
|
|
253
|
+
║ - Tidak ada test yang gagal (by design) ║
|
|
254
|
+
║ ║
|
|
255
|
+
║ ${chalk.gray('Disclaimer: Hasil test bersifat ilustratif dan tidak')} ║
|
|
256
|
+
║ ${chalk.gray(' dapat dijadikan bukti kualitas sebenarnya.')} ║
|
|
257
|
+
║ ║
|
|
258
|
+
╚════════════════════════════════════════════════════════════════╝
|
|
259
|
+
`));
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function delay(ms) {
|
|
263
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// ============================================================================
|
|
267
|
+
// RUN
|
|
268
|
+
// ============================================================================
|
|
269
|
+
|
|
270
|
+
if (require.main === module) {
|
|
271
|
+
jalankanTest().catch(err => {
|
|
272
|
+
// Bahkan jika error, tetap sukses
|
|
273
|
+
console.log(chalk.green('\n ✅ Test selesai dengan sukses!\n'));
|
|
274
|
+
console.log(chalk.gray(` (Error ditangkis: ${err.message})\n`));
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
module.exports = { jalankanTest };
|