puter-cli 1.8.6 → 2.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/.github/workflows/npm-build.yml +4 -3
- package/CHANGELOG.md +29 -0
- package/README.md +10 -2
- package/bin/index.js +184 -30
- package/package.json +12 -12
- package/src/commands/apps.js +53 -139
- package/src/commands/auth.js +113 -115
- package/src/commands/deploy.js +29 -27
- package/src/commands/files.js +151 -512
- package/src/commands/shell.js +13 -25
- package/src/commands/sites.js +25 -83
- package/src/commands/subdomains.js +46 -55
- package/src/commons.js +2 -2
- package/src/executor.js +26 -26
- package/src/modules/ErrorModule.js +18 -31
- package/src/modules/ProfileModule.js +183 -123
- package/src/modules/PuterModule.js +30 -0
- package/tests/ErrorModule.test.js +42 -0
- package/tests/ProfileModule.test.js +274 -0
- package/tests/PuterModule.test.js +56 -0
- package/tests/apps.test.js +194 -0
- package/tests/commons.test.js +380 -0
- package/tests/deploy.test.js +84 -0
- package/tests/executor.test.js +52 -0
- package/tests/files.test.js +640 -0
- package/tests/login.test.js +69 -51
- package/tests/shell.test.js +184 -0
- package/tests/sites.test.js +67 -0
- package/tests/subdomains.test.js +90 -0
- package/src/modules/SetContextModule.js +0 -5
- package/src/temporary/context_helpers.js +0 -17
package/tests/login.test.js
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import {
|
|
3
|
+
login, logout, getUserInfo, isAuthenticated, getAuthToken, getCurrentUserName,
|
|
4
|
+
getUsageInfo
|
|
5
|
+
} from '../src/commands/auth.js';
|
|
6
6
|
import chalk from 'chalk';
|
|
7
|
-
import fetch from 'node-fetch';
|
|
8
7
|
import Conf from 'conf';
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
11
|
-
import * as contextHelpers from '../src/temporary/context_helpers.js';
|
|
8
|
+
import { PROJECT_NAME } from '../src/commons.js';
|
|
9
|
+
import * as PuterModule from '../src/modules/PuterModule.js';
|
|
12
10
|
|
|
13
11
|
// Mock console to prevent actual logging
|
|
14
|
-
vi.spyOn(console, 'log').mockImplementation(() => {});
|
|
15
|
-
vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
12
|
+
vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
13
|
+
vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
16
14
|
|
|
17
15
|
// Mock dependencies
|
|
18
16
|
vi.mock('inquirer');
|
|
@@ -25,7 +23,19 @@ vi.mock('chalk', () => ({
|
|
|
25
23
|
cyan: vi.fn(text => text),
|
|
26
24
|
}
|
|
27
25
|
}));
|
|
28
|
-
vi.mock('
|
|
26
|
+
vi.mock('../src/modules/PuterModule.js');
|
|
27
|
+
|
|
28
|
+
// Mock ProfileModule
|
|
29
|
+
const mockProfileModule = {
|
|
30
|
+
switchProfileWizard: vi.fn(),
|
|
31
|
+
getAuthToken: vi.fn(),
|
|
32
|
+
getCurrentProfile: vi.fn(),
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
vi.mock('../src/modules/ProfileModule.js', () => ({
|
|
36
|
+
getProfileModule: vi.fn(() => mockProfileModule),
|
|
37
|
+
initProfileModule: vi.fn(),
|
|
38
|
+
}));
|
|
29
39
|
|
|
30
40
|
// Create a mock spinner object
|
|
31
41
|
const mockSpinner = {
|
|
@@ -51,19 +61,6 @@ vi.mock('conf', () => {
|
|
|
51
61
|
};
|
|
52
62
|
});
|
|
53
63
|
|
|
54
|
-
const mockProfileModule = {
|
|
55
|
-
switchProfileWizard: vi.fn(),
|
|
56
|
-
getAuthToken: vi.fn(),
|
|
57
|
-
getCurrentProfile: vi.fn(),
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
const mockContext = {
|
|
61
|
-
[ProfileAPI]: mockProfileModule,
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
vi.spyOn(contextHelpers, 'get_context').mockReturnValue(mockContext);
|
|
65
|
-
|
|
66
|
-
|
|
67
64
|
describe('auth.js', () => {
|
|
68
65
|
beforeEach(() => {
|
|
69
66
|
vi.clearAllMocks();
|
|
@@ -71,13 +68,13 @@ describe('auth.js', () => {
|
|
|
71
68
|
|
|
72
69
|
describe('login', () => {
|
|
73
70
|
it('should login successfully with valid credentials', async () => {
|
|
74
|
-
await login({}
|
|
71
|
+
await login({});
|
|
75
72
|
expect(mockProfileModule.switchProfileWizard).toHaveBeenCalled();
|
|
76
73
|
});
|
|
77
74
|
|
|
78
75
|
it('should fail login with invalid credentials', async () => {
|
|
79
76
|
mockProfileModule.switchProfileWizard.mockRejectedValue(new Error('Invalid credentials'));
|
|
80
|
-
await expect(login({}
|
|
77
|
+
await expect(login({})).rejects.toThrow('Invalid credentials');
|
|
81
78
|
expect(mockProfileModule.switchProfileWizard).toHaveBeenCalled();
|
|
82
79
|
});
|
|
83
80
|
|
|
@@ -108,31 +105,40 @@ describe('auth.js', () => {
|
|
|
108
105
|
it.skip('should handle logout error', async () => {
|
|
109
106
|
// This test needs to be updated to reflect the new login flow
|
|
110
107
|
});
|
|
111
|
-
|
|
108
|
+
|
|
112
109
|
});
|
|
113
|
-
|
|
110
|
+
|
|
114
111
|
|
|
115
112
|
describe('getUserInfo', () => {
|
|
113
|
+
const mockPuter = {
|
|
114
|
+
auth: {
|
|
115
|
+
getUser: vi.fn(),
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
beforeEach(() => {
|
|
120
|
+
vi.spyOn(PuterModule, 'getPuter').mockReturnValue(mockPuter);
|
|
121
|
+
});
|
|
122
|
+
|
|
116
123
|
it('should fetch user info successfully', async () => {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
124
|
+
mockPuter.auth.getUser.mockResolvedValue({
|
|
125
|
+
username: 'testuser',
|
|
126
|
+
uuid: 'testuuid',
|
|
127
|
+
email: 'test@puter.com',
|
|
128
|
+
email_confirmed: true,
|
|
129
|
+
is_temp: false,
|
|
130
|
+
human_readable_age: '1 day',
|
|
131
|
+
feature_flags: {},
|
|
123
132
|
});
|
|
124
133
|
|
|
125
134
|
await getUserInfo();
|
|
126
135
|
|
|
127
|
-
expect(
|
|
128
|
-
|
|
129
|
-
headers: expect.any(Object),
|
|
130
|
-
});
|
|
136
|
+
expect(mockPuter.auth.getUser).toHaveBeenCalled();
|
|
137
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('User Information:'));
|
|
131
138
|
});
|
|
132
139
|
|
|
133
140
|
it('should handle fetch user info error', async () => {
|
|
134
|
-
|
|
135
|
-
fetch.mockRejectedValue(new Error('Network error'));
|
|
141
|
+
mockPuter.auth.getUser.mockRejectedValue(new Error('Network error'));
|
|
136
142
|
await getUserInfo();
|
|
137
143
|
expect(console.error).toHaveBeenCalledWith(expect.stringContaining('Failed to get user info.'));
|
|
138
144
|
});
|
|
@@ -161,28 +167,40 @@ describe('auth.js', () => {
|
|
|
161
167
|
});
|
|
162
168
|
|
|
163
169
|
describe('getUsageInfo', () => {
|
|
170
|
+
const mockPuter = {
|
|
171
|
+
auth: {
|
|
172
|
+
getMonthlyUsage: vi.fn(),
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
beforeEach(() => {
|
|
177
|
+
vi.spyOn(PuterModule, 'getPuter').mockReturnValue(mockPuter);
|
|
178
|
+
});
|
|
179
|
+
|
|
164
180
|
it('should fetch usage info successfully', async () => {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
181
|
+
mockPuter.auth.getMonthlyUsage.mockResolvedValue({
|
|
182
|
+
allowanceInfo: {
|
|
183
|
+
monthUsageAllowance: 1000,
|
|
184
|
+
remaining: 500,
|
|
185
|
+
},
|
|
186
|
+
usage: {
|
|
187
|
+
total: 500,
|
|
188
|
+
},
|
|
189
|
+
appTotals: {},
|
|
169
190
|
});
|
|
170
191
|
|
|
171
192
|
await getUsageInfo();
|
|
172
193
|
|
|
173
|
-
expect(
|
|
174
|
-
|
|
175
|
-
headers: expect.any(Object),
|
|
176
|
-
});
|
|
194
|
+
expect(mockPuter.auth.getMonthlyUsage).toHaveBeenCalled();
|
|
195
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('Allowance Information:'));
|
|
177
196
|
});
|
|
178
197
|
|
|
179
198
|
it('should handle fetch usage info error', async () => {
|
|
180
|
-
|
|
181
|
-
fetch.mockRejectedValue(new Error('Network error'));
|
|
199
|
+
mockPuter.auth.getMonthlyUsage.mockRejectedValue(new Error('Network error'));
|
|
182
200
|
await getUsageInfo();
|
|
183
201
|
expect(console.error).toHaveBeenCalledWith(expect.stringContaining('Failed to fetch usage information.'));
|
|
184
202
|
});
|
|
185
203
|
});
|
|
186
|
-
|
|
204
|
+
|
|
187
205
|
|
|
188
206
|
});
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { execCommand, getPrompt } from '../src/executor.js';
|
|
3
|
+
import { getProfileModule } from '../src/modules/ProfileModule.js';
|
|
4
|
+
import readline from 'node:readline';
|
|
5
|
+
|
|
6
|
+
vi.mock('../src/executor.js');
|
|
7
|
+
vi.mock('../src/modules/ProfileModule.js');
|
|
8
|
+
vi.mock('node:readline');
|
|
9
|
+
vi.mock('conf', () => {
|
|
10
|
+
const Conf = vi.fn(() => ({
|
|
11
|
+
get: vi.fn(),
|
|
12
|
+
set: vi.fn(),
|
|
13
|
+
}));
|
|
14
|
+
return { default: Conf };
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
18
|
+
vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
19
|
+
|
|
20
|
+
let updatePrompt;
|
|
21
|
+
let startShell;
|
|
22
|
+
|
|
23
|
+
beforeEach(async () => {
|
|
24
|
+
vi.resetModules();
|
|
25
|
+
vi.clearAllMocks();
|
|
26
|
+
|
|
27
|
+
vi.mocked(getPrompt).mockReturnValue('puter@/> ');
|
|
28
|
+
vi.mocked(getProfileModule).mockReturnValue({
|
|
29
|
+
checkLogin: vi.fn(),
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const mockOn = vi.fn().mockReturnThis();
|
|
33
|
+
vi.mocked(readline.createInterface).mockReturnValue({
|
|
34
|
+
setPrompt: vi.fn(),
|
|
35
|
+
prompt: vi.fn(),
|
|
36
|
+
on: mockOn,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const module = await import('../src/commands/shell.js');
|
|
40
|
+
updatePrompt = module.updatePrompt;
|
|
41
|
+
startShell = module.startShell;
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe('updatePrompt', () => {
|
|
45
|
+
it('should call rl.setPrompt with getPrompt result', async () => {
|
|
46
|
+
await startShell();
|
|
47
|
+
const rl = readline.createInterface.mock.results[0].value;
|
|
48
|
+
rl.setPrompt.mockClear();
|
|
49
|
+
|
|
50
|
+
updatePrompt('/test/path');
|
|
51
|
+
|
|
52
|
+
expect(rl.setPrompt).toHaveBeenCalledWith('puter@/> ');
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe('startShell', () => {
|
|
57
|
+
it('should call checkLogin', async () => {
|
|
58
|
+
await startShell();
|
|
59
|
+
expect(getProfileModule().checkLogin).toHaveBeenCalled();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe('with command argument', () => {
|
|
63
|
+
let mockExit;
|
|
64
|
+
|
|
65
|
+
beforeEach(() => {
|
|
66
|
+
mockExit = vi.spyOn(process, 'exit').mockImplementation(() => {
|
|
67
|
+
throw new Error('process.exit called');
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
afterEach(() => {
|
|
72
|
+
mockExit.mockRestore();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should execute command and exit when command is provided', async () => {
|
|
76
|
+
await expect(startShell('help')).rejects.toThrow('process.exit called');
|
|
77
|
+
expect(execCommand).toHaveBeenCalledWith('help');
|
|
78
|
+
expect(mockExit).toHaveBeenCalledWith(0);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('should not create readline interface when command is provided', async () => {
|
|
82
|
+
vi.mocked(readline.createInterface).mockClear();
|
|
83
|
+
await expect(startShell('help')).rejects.toThrow('process.exit called');
|
|
84
|
+
expect(readline.createInterface).not.toHaveBeenCalled();
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe('without command argument (interactive mode)', () => {
|
|
89
|
+
it('should create readline interface', async () => {
|
|
90
|
+
await startShell();
|
|
91
|
+
expect(readline.createInterface).toHaveBeenCalledWith({
|
|
92
|
+
input: process.stdin,
|
|
93
|
+
output: process.stdout,
|
|
94
|
+
prompt: null,
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('should display welcome message', async () => {
|
|
99
|
+
await startShell();
|
|
100
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('Welcome to Puter-CLI'));
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('should set prompt and call prompt()', async () => {
|
|
104
|
+
await startShell();
|
|
105
|
+
const rl = readline.createInterface.mock.results[0].value;
|
|
106
|
+
expect(rl.setPrompt).toHaveBeenCalledWith('puter@/> ');
|
|
107
|
+
expect(rl.prompt).toHaveBeenCalled();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should register line and close event handlers', async () => {
|
|
111
|
+
await startShell();
|
|
112
|
+
const rl = readline.createInterface.mock.results[0].value;
|
|
113
|
+
expect(rl.on).toHaveBeenCalledWith('line', expect.any(Function));
|
|
114
|
+
expect(rl.on).toHaveBeenCalledWith('close', expect.any(Function));
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
describe('line event handler', () => {
|
|
119
|
+
let lineHandler;
|
|
120
|
+
let rl;
|
|
121
|
+
|
|
122
|
+
beforeEach(async () => {
|
|
123
|
+
await startShell();
|
|
124
|
+
rl = readline.createInterface.mock.results[0].value;
|
|
125
|
+
lineHandler = rl.on.mock.calls.find(call => call[0] === 'line')[1];
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('should execute trimmed command', async () => {
|
|
129
|
+
await lineHandler(' ls ');
|
|
130
|
+
expect(execCommand).toHaveBeenCalledWith('ls');
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('should not execute empty line', async () => {
|
|
134
|
+
vi.mocked(execCommand).mockClear();
|
|
135
|
+
await lineHandler(' ');
|
|
136
|
+
expect(execCommand).not.toHaveBeenCalled();
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('should call prompt after executing command', async () => {
|
|
140
|
+
rl.prompt.mockClear();
|
|
141
|
+
await lineHandler('ls');
|
|
142
|
+
expect(rl.prompt).toHaveBeenCalled();
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('should log error message when execCommand throws', async () => {
|
|
146
|
+
vi.mocked(execCommand).mockRejectedValueOnce(new Error('Command failed'));
|
|
147
|
+
await lineHandler('badcmd');
|
|
148
|
+
expect(console.error).toHaveBeenCalledWith(expect.stringContaining('Command failed'));
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('should still call prompt after error', async () => {
|
|
152
|
+
vi.mocked(execCommand).mockRejectedValueOnce(new Error('Command failed'));
|
|
153
|
+
rl.prompt.mockClear();
|
|
154
|
+
await lineHandler('badcmd');
|
|
155
|
+
expect(rl.prompt).toHaveBeenCalled();
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
describe('close event handler', () => {
|
|
160
|
+
let closeHandler;
|
|
161
|
+
let mockExit;
|
|
162
|
+
|
|
163
|
+
beforeEach(async () => {
|
|
164
|
+
mockExit = vi.spyOn(process, 'exit').mockImplementation(() => { });
|
|
165
|
+
await startShell();
|
|
166
|
+
const rl = readline.createInterface.mock.results[0].value;
|
|
167
|
+
closeHandler = rl.on.mock.calls.find(call => call[0] === 'close')[1];
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
afterEach(() => {
|
|
171
|
+
mockExit.mockRestore();
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('should display goodbye message', () => {
|
|
175
|
+
closeHandler();
|
|
176
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('Goodbye'));
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('should exit with code 0', () => {
|
|
180
|
+
closeHandler();
|
|
181
|
+
expect(mockExit).toHaveBeenCalledWith(0);
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { describe, vi, expect, it } from "vitest";
|
|
2
|
+
import { createSite, deleteSite, infoSite, listSites } from "../src/commands/sites";
|
|
3
|
+
import { createSubdomain, deleteSubdomain, getSubdomains } from "../src/commands/subdomains";
|
|
4
|
+
import { getPuter } from "../src/modules/PuterModule.js";
|
|
5
|
+
import { getCurrentDirectory } from "../src/commands/auth.js";
|
|
6
|
+
|
|
7
|
+
vi.mock("../src/commands/subdomains")
|
|
8
|
+
vi.mock("../src/modules/PuterModule")
|
|
9
|
+
vi.mock('../src/commands/auth.js');
|
|
10
|
+
|
|
11
|
+
vi.spyOn(console, "log").mockImplementation(() => { });
|
|
12
|
+
|
|
13
|
+
describe("listSites", () => {
|
|
14
|
+
it("should list sites successfully", async () => {
|
|
15
|
+
vi.mocked(getSubdomains).mockResolvedValue([{
|
|
16
|
+
uid: "123",
|
|
17
|
+
subdomain: "hehe.puter.site",
|
|
18
|
+
root_dir: { path: "/some/path" },
|
|
19
|
+
}])
|
|
20
|
+
await listSites();
|
|
21
|
+
expect(getSubdomains).toHaveBeenCalled();
|
|
22
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining("Total Sites: 1"))
|
|
23
|
+
})
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
describe("infoSite", () => {
|
|
27
|
+
it("should get site info successfully", async () => {
|
|
28
|
+
const mockHostingGet = vi.fn().mockResolvedValue({
|
|
29
|
+
uid: "123",
|
|
30
|
+
subdomain: "hehe.puter.site",
|
|
31
|
+
root_dir: { path: "/some/path" },
|
|
32
|
+
});
|
|
33
|
+
vi.mocked(getPuter).mockReturnValue({
|
|
34
|
+
hosting: {
|
|
35
|
+
get: mockHostingGet
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
await infoSite(["hehe.puter.site"])
|
|
40
|
+
expect(getPuter).toHaveBeenCalled();
|
|
41
|
+
expect(mockHostingGet).toHaveBeenCalled();
|
|
42
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining("hehe.puter.site"))
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
describe("deleteSite", () => {
|
|
47
|
+
it("should delete site successfully", async () => {
|
|
48
|
+
vi.mocked(deleteSubdomain)
|
|
49
|
+
const result = await deleteSite(["hehe.puter.site"]);
|
|
50
|
+
expect(result).toBe(true);
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
describe("createSite", () => {
|
|
55
|
+
it("should create site successfully", async () => {
|
|
56
|
+
vi.mocked(createSubdomain).mockResolvedValue({
|
|
57
|
+
uid: "123",
|
|
58
|
+
subdomain: "hehe.puter.site",
|
|
59
|
+
root_dir: { path: "/some/path" },
|
|
60
|
+
})
|
|
61
|
+
vi.mocked(getCurrentDirectory).mockReturnValue('/testuser');
|
|
62
|
+
const result = await createSite(["hehe hehe --subdomain=hehe"]);
|
|
63
|
+
expect(result).toMatchObject({
|
|
64
|
+
subdomain: "hehe.puter.site"
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
})
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { vi } from "vitest";
|
|
2
|
+
import { it } from "vitest";
|
|
3
|
+
import { describe } from "vitest";
|
|
4
|
+
import { createSubdomain, deleteSubdomain, getSubdomains, updateSubdomain } from "../src/commands/subdomains";
|
|
5
|
+
import { expect } from "vitest";
|
|
6
|
+
import { getPuter } from "../src/modules/PuterModule";
|
|
7
|
+
|
|
8
|
+
vi.mock("../src/modules/PuterModule")
|
|
9
|
+
vi.mock("conf", () => {
|
|
10
|
+
const Conf = vi.fn(() => ({
|
|
11
|
+
get: vi.fn(),
|
|
12
|
+
set: vi.fn(),
|
|
13
|
+
clear: vi.fn(),
|
|
14
|
+
}));
|
|
15
|
+
return { default: Conf };
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
vi.spyOn(console, "log").mockImplementation(() => { });
|
|
19
|
+
|
|
20
|
+
describe("getSubdomains", () => {
|
|
21
|
+
it("should get subdomains successfully", async () => {
|
|
22
|
+
const mockHostingList = vi.fn().mockResolvedValue([{
|
|
23
|
+
uid: "123",
|
|
24
|
+
subdomain: "hehe.puter.site",
|
|
25
|
+
root_dir: { path: "/some/path" },
|
|
26
|
+
}]);
|
|
27
|
+
vi.mocked(getPuter).mockReturnValue({
|
|
28
|
+
hosting: {
|
|
29
|
+
list: mockHostingList
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
const result = await getSubdomains();
|
|
33
|
+
expect(getPuter).toHaveBeenCalled();
|
|
34
|
+
expect(result).toHaveLength(1)
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
describe("deleteSubdomain", () => {
|
|
39
|
+
it("should delete subdomain successfully", async () => {
|
|
40
|
+
const mockHostingDelete = vi.fn().mockResolvedValue(true);
|
|
41
|
+
vi.mocked(getPuter).mockReturnValue({
|
|
42
|
+
hosting: {
|
|
43
|
+
delete: mockHostingDelete
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
const result = await deleteSubdomain(["hehe.puter.site"]);
|
|
47
|
+
expect(result).toBe(true);
|
|
48
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining("Subdomain deleted successfully"));
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
describe("createSubdomain", () => {
|
|
53
|
+
it("should create subdomain successfully", async () => {
|
|
54
|
+
const mockHostingCreate = vi.fn().mockResolvedValue({
|
|
55
|
+
uid: "123",
|
|
56
|
+
subdomain: "hehe.puter.site",
|
|
57
|
+
root_dir: { path: "/some/path" },
|
|
58
|
+
});
|
|
59
|
+
vi.mocked(getPuter).mockReturnValue({
|
|
60
|
+
hosting: {
|
|
61
|
+
create: mockHostingCreate
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
const result = await createSubdomain("hehe", "/mydir")
|
|
65
|
+
expect(result).toMatchObject({
|
|
66
|
+
subdomain: "hehe.puter.site"
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
describe("updateSubdomain", () => {
|
|
72
|
+
it("should update subdomain successfully", async () => {
|
|
73
|
+
const mockHostingUpdate = vi.fn().mockResolvedValue({
|
|
74
|
+
uid: "123",
|
|
75
|
+
subdomain: "hehe.puter.site",
|
|
76
|
+
root_dir: { path: "/newdir" },
|
|
77
|
+
});
|
|
78
|
+
vi.mocked(getPuter).mockReturnValue({
|
|
79
|
+
hosting: {
|
|
80
|
+
update: mockHostingUpdate
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
const result = await updateSubdomain("hehe", "/newdir")
|
|
84
|
+
expect(result).toMatchObject({
|
|
85
|
+
root_dir: {
|
|
86
|
+
path: "/newdir"
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
})
|
|
90
|
+
})
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Ideally we would always get a context from the caller, but in some places
|
|
3
|
-
* this is not possible without creating a large number of changes
|
|
4
|
-
* (and therefore also a large number of new bugs). This temporary file
|
|
5
|
-
* provides a way to get the context that modules get.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
let context;
|
|
9
|
-
|
|
10
|
-
// This is called by (list all callers so we can keep track):
|
|
11
|
-
// - auth.js:getAuthToken
|
|
12
|
-
export const get_context = () => {
|
|
13
|
-
return context;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
// This is called by SetContextModule
|
|
17
|
-
export const set_context = ctx => context = ctx;
|