repo-cloak-cli 1.3.2 → 1.3.4

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/src/ui/prompts.js CHANGED
@@ -5,53 +5,158 @@
5
5
 
6
6
  import inquirer from 'inquirer';
7
7
  import chalk from 'chalk';
8
- import { existsSync } from 'fs';
8
+ import { existsSync, mkdirSync } from 'fs';
9
9
  import { resolve, isAbsolute } from 'path';
10
+ import { getSourcePaths, getDestPaths, addSourcePath, addDestPath } from '../core/path-cache.js';
11
+
12
+ const ENTER_DIFFERENT = '__ENTER_DIFFERENT__';
13
+ import { checkboxTreeSelectSingleDir } from './treeCheckboxSelector.js';
10
14
 
11
15
  /**
12
- * Prompt for source directory
16
+ * Build a list prompt with cached paths + "Enter a different path" option.
17
+ * Falls back to a plain input prompt when there are no cached paths.
18
+ * @param {object} opts
19
+ * @param {string} opts.message - Question shown to the user
20
+ * @param {string} opts.inputMessage - Follow-up message when they pick "Enter a different path"
21
+ * @param {string[]} opts.cachedPaths - Decrypted cached paths to show
22
+ * @param {(path: string) => string|true} opts.validate - Validator for final resolved path
23
+ * @param {string} [opts.defaultValue] - Default path
24
+ * @param {boolean} [opts.allowNewSubfolder] - Ask to append a subfolder after selection
25
+ * @returns {Promise<string>} Resolved absolute path
13
26
  */
14
- export async function promptSourceDirectory(defaultPath = process.cwd()) {
15
- const { sourcePath } = await inquirer.prompt([
16
- {
17
- type: 'input',
18
- name: 'sourcePath',
19
- message: 'Source directory:',
20
- default: defaultPath,
21
- validate: (input) => {
22
- const path = resolve(input);
23
- if (!existsSync(path)) {
24
- return 'Directory does not exist. Please enter a valid path.';
27
+ async function promptWithCache({ message, cachedPaths, validate, defaultValue, allowNewSubfolder }) {
28
+ // Build the displayed message append a dim default hint if one is provided
29
+ const displayMessage = defaultValue
30
+ ? `${message} ${chalk.dim(`(press Enter to use current folder: ${defaultValue})`)}`
31
+ : message;
32
+
33
+ // With cached paths → show a quick-pick list with the question as its header
34
+ if (cachedPaths.length > 0) {
35
+ const { selected } = await inquirer.prompt([
36
+ {
37
+ type: 'list',
38
+ name: 'selected',
39
+ message: displayMessage,
40
+ choices: [
41
+ ...cachedPaths.map(p => ({ name: p, value: p })),
42
+ new inquirer.Separator(),
43
+ { name: chalk.cyan('↵ Enter a different path'), value: ENTER_DIFFERENT }
44
+ ]
45
+ }
46
+ ]);
47
+
48
+ if (selected !== ENTER_DIFFERENT) {
49
+ let resolved = resolve(selected);
50
+
51
+ if (allowNewSubfolder) {
52
+ const { subfolder } = await inquirer.prompt([{
53
+ type: 'input',
54
+ name: 'subfolder',
55
+ message: `Subfolder to create inside ${chalk.cyan(resolved)}? (press Enter to use current folder)`
56
+ }]);
57
+ if (subfolder.trim()) {
58
+ resolved = resolve(resolved, subfolder.trim());
25
59
  }
26
- return true;
60
+ }
61
+
62
+ const result = validate(resolved);
63
+ if (result !== true) {
64
+ console.log(chalk.yellow(` ⚠ ${result}`));
65
+ } else {
66
+ return resolved;
27
67
  }
28
68
  }
29
- ]);
69
+ }
70
+
71
+ // No cache (or user chose "Enter a different path") → use hierarchical tree selector
72
+ console.log(chalk.dim(' (Use arrow keys to navigate, Space to expand/collapse, Enter to select)'));
73
+ let basePath = await checkboxTreeSelectSingleDir({
74
+ message: displayMessage,
75
+ root: process.cwd()
76
+ });
77
+
78
+ if (allowNewSubfolder) {
79
+ const { subfolder } = await inquirer.prompt([{
80
+ type: 'input',
81
+ name: 'subfolder',
82
+ message: `Subfolder to create inside ${chalk.cyan(basePath)}? (press Enter to use current folder)`
83
+ }]);
84
+ if (subfolder.trim()) {
85
+ basePath = resolve(basePath, subfolder.trim());
86
+ }
87
+ }
30
88
 
31
- return resolve(sourcePath);
89
+ let finalPath = resolve(basePath);
90
+ // Loop until we get a path that passes validation
91
+ while (true) {
92
+ const result = validate(finalPath);
93
+ if (result === true) break;
94
+ console.log(chalk.yellow(` ⚠ ${result}`));
95
+
96
+ const { retry } = await inquirer.prompt([{
97
+ type: 'input',
98
+ name: 'retry',
99
+ message: 'Please type a valid absolute path:'
100
+ }]);
101
+ finalPath = resolve(retry.trim());
102
+ }
103
+
104
+ return finalPath;
32
105
  }
33
106
 
34
107
  /**
35
- * Prompt for destination directory
108
+ * Prompt for source directory (the repo to extract files from).
109
+ * Shows cached paths; validates that the directory exists.
110
+ * Saves the chosen path to the cache after selection.
36
111
  */
37
- export async function promptDestinationDirectory() {
38
- const { destPath } = await inquirer.prompt([
39
- {
40
- type: 'input',
41
- name: 'destPath',
42
- message: 'Destination directory (will be created if not exists):',
43
- validate: (input) => {
44
- if (!input.trim()) {
45
- return 'Please enter a destination path.';
46
- }
47
- return true;
112
+ export async function promptSourceDirectory() {
113
+ const cachedPaths = getSourcePaths();
114
+
115
+ const path = await promptWithCache({
116
+ message: 'Which repo do you want to extract files from?',
117
+ cachedPaths,
118
+ validate: (resolved) => {
119
+ if (!existsSync(resolved)) {
120
+ return `Directory not found: ${resolved}`;
48
121
  }
122
+ return true;
49
123
  }
50
- ]);
124
+ });
51
125
 
52
- return resolve(destPath);
126
+ addSourcePath(path);
127
+ return path;
53
128
  }
54
129
 
130
+ /**
131
+ * Prompt for destination directory (where cloaked files will be saved).
132
+ * Shows cached paths; creates the folder automatically if it doesn't exist.
133
+ * Saves the chosen path to the cache after selection.
134
+ */
135
+ export async function promptDestinationDirectory() {
136
+ const cachedPaths = getDestPaths();
137
+
138
+ const path = await promptWithCache({
139
+ message: 'Where should the cloaked (anonymized) files be saved?',
140
+ defaultValue: process.cwd(),
141
+ allowNewSubfolder: true,
142
+ cachedPaths,
143
+ validate: (resolved) => {
144
+ if (!resolved.trim()) return 'Please enter a destination path.';
145
+ return true; // Destination may not exist yet – we will create it
146
+ }
147
+ });
148
+
149
+ // Auto-create the destination if it doesn't exist
150
+ if (!existsSync(path)) {
151
+ mkdirSync(path, { recursive: true });
152
+ console.log(chalk.dim(` Created directory: ${path}`));
153
+ }
154
+
155
+ addDestPath(path);
156
+ return path;
157
+ }
158
+
159
+
55
160
  /**
56
161
  * Prompt for keyword replacements
57
162
  */
@@ -68,12 +173,12 @@ export async function promptKeywordReplacements() {
68
173
  {
69
174
  type: 'input',
70
175
  name: 'original',
71
- message: 'Text to find (leave empty to finish):',
176
+ message: 'What do you want to replace? (leave empty to skip / finish):',
72
177
  },
73
178
  {
74
179
  type: 'input',
75
180
  name: 'replacement',
76
- message: 'Replace with:',
181
+ message: 'Replace it with:',
77
182
  when: (answers) => answers.original.trim() !== '',
78
183
  validate: (input) => {
79
184
  if (!input.trim()) {
@@ -139,7 +244,7 @@ export async function showSummaryAndConfirm(fileCount, destination, replacements
139
244
 
140
245
  console.log(chalk.cyan('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'));
141
246
 
142
- return confirmAction('Proceed with extraction?');
247
+ return confirmAction('Everything looks good — go ahead?');
143
248
  }
144
249
 
145
250
  /**
@@ -150,7 +255,7 @@ export async function promptBackupFolder() {
150
255
  {
151
256
  type: 'input',
152
257
  name: 'folderPath',
153
- message: 'Path to cloaked backup folder:',
258
+ message: 'Where is the cloaked folder you want to restore from?',
154
259
  validate: (input) => {
155
260
  const path = resolve(input);
156
261
  if (!existsSync(path)) {
@@ -0,0 +1,253 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import inquirer from 'inquirer';
4
+ import checkbox from '@inquirer/checkbox';
5
+
6
+ function buildTree(root, options) {
7
+ const { maxDepth, ignore } = options;
8
+ const nodes = new Map();
9
+ const checked = new Set();
10
+
11
+ function walk(currentPath, depth, parentId) {
12
+ if (depth > maxDepth) return;
13
+ try {
14
+ const entries = fs.readdirSync(currentPath, { withFileTypes: true });
15
+
16
+ for (const entry of entries) {
17
+ const fullPath = path.join(currentPath, entry.name);
18
+ if (ignore(fullPath, entry.name)) continue;
19
+
20
+ const id = fullPath;
21
+ const node = {
22
+ id,
23
+ name: entry.name,
24
+ fullPath,
25
+ parentId,
26
+ children: [],
27
+ isDirectory: entry.isDirectory(),
28
+ };
29
+ nodes.set(id, node);
30
+
31
+ if (parentId) {
32
+ const parent = nodes.get(parentId);
33
+ if (parent) parent.children.push(id);
34
+ }
35
+
36
+ if (entry.isDirectory()) {
37
+ walk(fullPath, depth + 1, id);
38
+ }
39
+ }
40
+ } catch (e) {
41
+ // ignore read errors
42
+ }
43
+ }
44
+
45
+ walk(root, 0, undefined);
46
+ return { nodes, checked };
47
+ }
48
+
49
+ function setSubtreeChecked(state, nodeId, checkedStatus) {
50
+ const queue = [nodeId];
51
+ while (queue.length) {
52
+ const id = queue.pop();
53
+ if (checkedStatus) state.checked.add(id);
54
+ else state.checked.delete(id);
55
+ const node = state.nodes.get(id);
56
+ if (node) queue.push(...node.children);
57
+ }
58
+ }
59
+
60
+ function recomputeParentFromChildren(state, nodeId) {
61
+ let current = state.nodes.get(nodeId);
62
+ while (current?.parentId) {
63
+ const parent = state.nodes.get(current.parentId);
64
+ if (!parent) break;
65
+ const allChildrenChecked = parent.children.length
66
+ ? parent.children.every((cid) => state.checked.has(cid))
67
+ : false;
68
+
69
+ if (allChildrenChecked) state.checked.add(parent.id);
70
+ else state.checked.delete(parent.id);
71
+
72
+ current = parent;
73
+ }
74
+ }
75
+
76
+ function applyExplicitNodeState(state, nodeId, targetState) {
77
+ setSubtreeChecked(state, nodeId, targetState);
78
+ recomputeParentFromChildren(state, nodeId);
79
+ }
80
+
81
+ function flattenNodesHierarchically(nodes) {
82
+ const roots = Array.from(nodes.values()).filter((n) => !n.parentId);
83
+ roots.sort((a, b) => a.name.localeCompare(b.name));
84
+
85
+ const flatList = [];
86
+
87
+ function visit(node, prefix, isLast) {
88
+ const connector = prefix ? (isLast ? '└─ ' : '├─ ') : '';
89
+ const icon = node.isDirectory ? '[d] ' : ' ';
90
+
91
+ flatList.push({
92
+ node,
93
+ displayName: `${prefix}${connector}${icon}${node.name}`
94
+ });
95
+
96
+ const childPrefix = prefix + (isLast ? ' ' : '| ');
97
+ const children = node.children
98
+ .map((id) => nodes.get(id))
99
+ .sort((a, b) => a.name.localeCompare(b.name));
100
+
101
+ children.forEach((child, index) => {
102
+ const last = index === children.length - 1;
103
+ visit(child, childPrefix, last);
104
+ });
105
+ }
106
+
107
+ roots.forEach((root, index) => {
108
+ const last = index === roots.length - 1;
109
+ visit(root, '', last);
110
+ });
111
+
112
+ return flatList;
113
+ }
114
+
115
+ function printSelectionSummary(root, state, hierarchicalNodes) {
116
+ const selectedFiles = hierarchicalNodes.filter(n => !n.node.isDirectory && state.checked.has(n.node.id));
117
+ if (selectedFiles.length === 0) {
118
+ console.log('\x1b[90m (no files selected yet)\x1b[0m\n');
119
+ } else {
120
+ console.log(`\x1b[32m ${selectedFiles.length} file(s) selected:\x1b[0m`);
121
+ const maxDisplay = 10;
122
+ selectedFiles.slice(0, maxDisplay).forEach(n => {
123
+ const rel = path.relative(root, n.node.id);
124
+ console.log(` \x1b[32m+\x1b[0m ${rel}`);
125
+ });
126
+ if (selectedFiles.length > maxDisplay) {
127
+ console.log(`\x1b[90m ... and ${selectedFiles.length - maxDisplay} more\x1b[0m`);
128
+ }
129
+ console.log('');
130
+ }
131
+ }
132
+
133
+ export async function checkboxTreeSelect(options = {}) {
134
+ const {
135
+ root = process.cwd(),
136
+ maxDepth = 5,
137
+ ignore = (fullPath, name) => name === 'node_modules' || name.startsWith('.git'),
138
+ message = 'Select files',
139
+ pageSize = 15,
140
+ precheck = [],
141
+ } = options;
142
+
143
+ const state = buildTree(root, { maxDepth, ignore });
144
+
145
+ if (precheck && precheck.length > 0) {
146
+ for (const p of precheck) {
147
+ if (state.nodes.has(p)) applyExplicitNodeState(state, p, true);
148
+ }
149
+ }
150
+
151
+ const hierarchicalNodes = flattenNodesHierarchically(state.nodes);
152
+ const allNodes = hierarchicalNodes.map(item => item.node);
153
+
154
+ if (hierarchicalNodes.length === 0) {
155
+ console.log(`No items found in ${root}`);
156
+ return [];
157
+ }
158
+
159
+ // Search loop: user types a query, sees filtered results, selects with space.
160
+ // Empty search + Enter = done.
161
+ while (true) {
162
+ console.clear();
163
+ console.log(`\nRoot: \x1b[1m${root}\x1b[0m`);
164
+ console.log('\x1b[90mType a filename to search. Space to select, Enter to confirm. Empty search + Enter to finish.\x1b[0m\n');
165
+ printSelectionSummary(root, state, hierarchicalNodes);
166
+
167
+ const { query } = await inquirer.prompt([{
168
+ type: 'input',
169
+ name: 'query',
170
+ message: `${message} — search:`,
171
+ }]);
172
+
173
+ const trimmed = query.trim().toLowerCase();
174
+
175
+ // Empty query = user is done selecting
176
+ if (!trimmed) break;
177
+
178
+ // Filter nodes whose relative path matches the query
179
+ const matched = hierarchicalNodes.filter(({ node }) => {
180
+ const rel = path.relative(root, node.id).toLowerCase();
181
+ return rel.includes(trimmed);
182
+ });
183
+
184
+ if (matched.length === 0) {
185
+ console.log(`\x1b[33m No results for "${query}". Try a different term.\x1b[0m`);
186
+ await new Promise(r => setTimeout(r, 1200));
187
+ continue;
188
+ }
189
+
190
+ // Build choices for the checkbox prompt from search results
191
+ const choices = matched.map(({ node }) => {
192
+ const rel = path.relative(root, node.id);
193
+ const icon = node.isDirectory ? '[dir] ' : '';
194
+ return {
195
+ name: `${icon}${rel}`,
196
+ value: node.id,
197
+ checked: state.checked.has(node.id),
198
+ };
199
+ });
200
+
201
+ const prevChecked = new Set(state.checked);
202
+
203
+ let selected;
204
+ try {
205
+ selected = await checkbox({
206
+ message: `Results for "${query}" — Space to toggle, Enter to go back to search`,
207
+ choices,
208
+ pageSize,
209
+ loop: false,
210
+ });
211
+ } catch {
212
+ // User force-quit (ctrl+c) — treat as done
213
+ break;
214
+ }
215
+
216
+ // Apply changes: determine what was toggled from the matched set
217
+ const nextChecked = new Set(selected);
218
+ for (const { node } of matched) {
219
+ const was = prevChecked.has(node.id);
220
+ const now = nextChecked.has(node.id);
221
+ if (was !== now) {
222
+ applyExplicitNodeState(state, node.id, now);
223
+ }
224
+ }
225
+ }
226
+
227
+ return Array.from(state.checked);
228
+ }
229
+
230
+ export async function checkboxTreeSelectFilesOnly(options = {}) {
231
+ const paths = await checkboxTreeSelect(options);
232
+ return paths.filter((p) => {
233
+ try {
234
+ return fs.statSync(p).isFile();
235
+ } catch {
236
+ return false;
237
+ }
238
+ });
239
+ }
240
+
241
+ export async function checkboxTreeSelectSingleDir(options = {}) {
242
+ while (true) {
243
+ const paths = await checkboxTreeSelect({ ...options, message: options.message + ' (Select MAXIMUM ONE directory)' });
244
+ const dirs = paths.filter(p => {
245
+ try { return fs.statSync(p).isDirectory(); } catch { return false; }
246
+ });
247
+ if (dirs.length > 1) {
248
+ console.log('\nPlease select ONLY ONE directory.\n');
249
+ continue;
250
+ }
251
+ return dirs[0] || '';
252
+ }
253
+ }
package/test-tree.js ADDED
@@ -0,0 +1,2 @@
1
+ import { checkboxTreeSelect } from './src/ui/treeCheckboxSelector.js';
2
+ checkboxTreeSelect({ root: process.cwd(), maxDepth: 1 }).then(res => console.log(res));
@@ -9,37 +9,37 @@ describe('Anonymizer', () => {
9
9
  describe('createAnonymizer', () => {
10
10
  it('should replace exact matches', () => {
11
11
  const anonymizer = createAnonymizer([
12
- { original: 'Cuviva', replacement: 'ABCCompany' }
12
+ { original: 'Microsoft', replacement: 'ABCCompany' }
13
13
  ]);
14
14
 
15
15
  // Title case input -> Title case output (first letter upper, rest lower)
16
- expect(anonymizer('Hello Cuviva world')).toBe('Hello Abccompany world');
16
+ expect(anonymizer('Hello Microsoft world')).toBe('Hello Abccompany world');
17
17
  });
18
18
 
19
19
  it('should handle all uppercase', () => {
20
20
  const anonymizer = createAnonymizer([
21
- { original: 'Cuviva', replacement: 'ABCCompany' }
21
+ { original: 'Microsoft', replacement: 'ABCCompany' }
22
22
  ]);
23
23
 
24
- expect(anonymizer('CUVIVA is great')).toBe('ABCCOMPANY is great');
24
+ expect(anonymizer('MICROSOFT is great')).toBe('ABCCOMPANY is great');
25
25
  });
26
26
 
27
27
  it('should handle all lowercase', () => {
28
28
  const anonymizer = createAnonymizer([
29
- { original: 'Cuviva', replacement: 'ABCCompany' }
29
+ { original: 'Microsoft', replacement: 'ABCCompany' }
30
30
  ]);
31
31
 
32
- expect(anonymizer('cuviva is lower')).toBe('abccompany is lower');
32
+ expect(anonymizer('microsoft is lower')).toBe('abccompany is lower');
33
33
  });
34
34
 
35
35
  it('should handle multiple replacements', () => {
36
36
  const anonymizer = createAnonymizer([
37
- { original: 'Cuviva', replacement: 'ABCCompany' },
37
+ { original: 'Microsoft', replacement: 'ABCCompany' },
38
38
  { original: 'Frontend', replacement: 'Client' }
39
39
  ]);
40
40
 
41
41
  // Both are Title case -> first upper + rest lower
42
- expect(anonymizer('Cuviva Frontend API')).toBe('Abccompany Client API');
42
+ expect(anonymizer('Microsoft Frontend API')).toBe('Abccompany Client API');
43
43
  });
44
44
 
45
45
  it('should handle empty replacements', () => {
@@ -65,45 +65,45 @@ describe('Anonymizer', () => {
65
65
  describe('createDeanonymizer', () => {
66
66
  it('should reverse the anonymization', () => {
67
67
  const replacements = [
68
- { original: 'Cuviva', replacement: 'ABCCompany' }
68
+ { original: 'Microsoft', replacement: 'ABCCompany' }
69
69
  ];
70
70
 
71
71
  const deanonymizer = createDeanonymizer(replacements);
72
72
 
73
- // ABCCompany (Title case) -> Cuviva (Title case: first upper + rest lower)
74
- expect(deanonymizer('Hello ABCCompany world')).toBe('Hello Cuviva world');
73
+ // ABCCompany (Title case) -> Microsoft (Title case: first upper + rest lower)
74
+ expect(deanonymizer('Hello ABCCompany world')).toBe('Hello Microsoft world');
75
75
  });
76
76
 
77
77
  it('should handle multiple replacements in reverse', () => {
78
78
  const replacements = [
79
- { original: 'Cuviva', replacement: 'ABCCompany' },
79
+ { original: 'Microsoft', replacement: 'ABCCompany' },
80
80
  { original: 'API', replacement: 'Service' }
81
81
  ];
82
82
 
83
83
  const deanonymizer = createDeanonymizer(replacements);
84
84
 
85
85
  // Title case -> Title case for both
86
- expect(deanonymizer('ABCCompany Service')).toBe('Cuviva Api');
86
+ expect(deanonymizer('ABCCompany Service')).toBe('Microsoft Api');
87
87
  });
88
88
 
89
89
  it('should handle uppercase in reverse', () => {
90
90
  const replacements = [
91
- { original: 'Cuviva', replacement: 'ABCCompany' }
91
+ { original: 'Microsoft', replacement: 'ABCCompany' }
92
92
  ];
93
93
 
94
94
  const deanonymizer = createDeanonymizer(replacements);
95
95
 
96
- expect(deanonymizer('ABCCOMPANY')).toBe('CUVIVA');
96
+ expect(deanonymizer('ABCCOMPANY')).toBe('MICROSOFT');
97
97
  });
98
98
 
99
99
  it('should handle lowercase in reverse', () => {
100
100
  const replacements = [
101
- { original: 'Cuviva', replacement: 'ABCCompany' }
101
+ { original: 'Microsoft', replacement: 'ABCCompany' }
102
102
  ];
103
103
 
104
104
  const deanonymizer = createDeanonymizer(replacements);
105
105
 
106
- expect(deanonymizer('abccompany')).toBe('cuviva');
106
+ expect(deanonymizer('abccompany')).toBe('microsoft');
107
107
  });
108
108
  });
109
109
  });
@@ -55,9 +55,9 @@ describe('Copier Module', () => {
55
55
  const sourceFile = join(sourceDir, 'code.js');
56
56
  const destFile = join(destDir, 'code.js');
57
57
 
58
- writeFileSync(sourceFile, 'const company = "Cuviva";');
58
+ writeFileSync(sourceFile, 'const company = "Microsoft";');
59
59
 
60
- const transform = (content) => content.replace(/Cuviva/g, 'ABCCompany');
60
+ const transform = (content) => content.replace(/Microsoft/g, 'ABCCompany');
61
61
  const result = copyFileWithTransform(sourceFile, destFile, transform);
62
62
 
63
63
  expect(result.transformed).toBe(true);
@@ -70,7 +70,7 @@ describe('Copier Module', () => {
70
70
 
71
71
  writeFileSync(sourceFile, 'const x = 1;');
72
72
 
73
- const transform = (content) => content.replace(/Cuviva/g, 'ABCCompany');
73
+ const transform = (content) => content.replace(/Microsoft/g, 'ABCCompany');
74
74
  const result = copyFileWithTransform(sourceFile, destFile, transform);
75
75
 
76
76
  expect(result.transformed).toBe(false);
@@ -65,7 +65,7 @@ describe('Crypto Module', () => {
65
65
  describe('encryptReplacements/decryptReplacements', () => {
66
66
  it('should encrypt only the original field', () => {
67
67
  const replacements = [
68
- { original: 'Cuviva', replacement: 'ABCCompany' },
68
+ { original: 'Microsoft', replacement: 'ABCCompany' },
69
69
  { original: 'Secret', replacement: 'Public' }
70
70
  ];
71
71
 
@@ -82,13 +82,13 @@ describe('Crypto Module', () => {
82
82
 
83
83
  it('should decrypt back to original', () => {
84
84
  const replacements = [
85
- { original: 'Cuviva', replacement: 'ABCCompany' }
85
+ { original: 'Microsoft', replacement: 'ABCCompany' }
86
86
  ];
87
87
 
88
88
  const encrypted = encryptReplacements(replacements, testSecret);
89
89
  const decrypted = decryptReplacements(encrypted, testSecret);
90
90
 
91
- expect(decrypted[0].original).toBe('Cuviva');
91
+ expect(decrypted[0].original).toBe('Microsoft');
92
92
  expect(decrypted[0].replacement).toBe('ABCCompany');
93
93
  });
94
94