@takaro/modules 0.2.0 → 0.3.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/dist/BuiltinModule.d.ts +3 -0
- package/dist/BuiltinModule.d.ts.map +1 -1
- package/dist/BuiltinModule.js +17 -0
- package/dist/BuiltinModule.js.map +1 -1
- package/dist/dto/index.d.ts +1 -0
- package/dist/dto/index.d.ts.map +1 -1
- package/dist/dto/takaroEvents.d.ts +7 -0
- package/dist/dto/takaroEvents.d.ts.map +1 -1
- package/dist/dto/takaroEvents.js +23 -1
- package/dist/dto/takaroEvents.js.map +1 -1
- package/dist/modules/chatBridge/index.d.ts.map +1 -1
- package/dist/modules/chatBridge/index.js +2 -0
- package/dist/modules/chatBridge/index.js.map +1 -1
- package/dist/modules/dailyRewards/commands/daily.js +1 -4
- package/dist/modules/dailyRewards/commands/daily.js.map +1 -1
- package/dist/modules/dailyRewards/index.d.ts.map +1 -1
- package/dist/modules/dailyRewards/index.js +4 -1
- package/dist/modules/dailyRewards/index.js.map +1 -1
- package/dist/modules/economyUtils/commands/confirmTransfer.js +4 -4
- package/dist/modules/economyUtils/commands/confirmTransfer.js.map +1 -1
- package/dist/modules/economyUtils/commands/grantCurrency.js +1 -4
- package/dist/modules/economyUtils/commands/grantCurrency.js.map +1 -1
- package/dist/modules/economyUtils/commands/revokeCurrency.js +1 -4
- package/dist/modules/economyUtils/commands/revokeCurrency.js.map +1 -1
- package/dist/modules/economyUtils/index.d.ts.map +1 -1
- package/dist/modules/economyUtils/index.js +5 -1
- package/dist/modules/economyUtils/index.js.map +1 -1
- package/dist/modules/geoBlock/index.d.ts.map +1 -1
- package/dist/modules/geoBlock/index.js +2 -0
- package/dist/modules/geoBlock/index.js.map +1 -1
- package/dist/modules/gimme/index.d.ts.map +1 -1
- package/dist/modules/gimme/index.js +2 -0
- package/dist/modules/gimme/index.js.map +1 -1
- package/dist/modules/highPingKicker/index.d.ts.map +1 -1
- package/dist/modules/highPingKicker/index.js +2 -0
- package/dist/modules/highPingKicker/index.js.map +1 -1
- package/dist/modules/lottery/commands/buyTicket.js +1 -4
- package/dist/modules/lottery/commands/buyTicket.js.map +1 -1
- package/dist/modules/lottery/commands/viewTickets.js +5 -8
- package/dist/modules/lottery/commands/viewTickets.js.map +1 -1
- package/dist/modules/lottery/index.d.ts.map +1 -1
- package/dist/modules/lottery/index.js +5 -1
- package/dist/modules/lottery/index.js.map +1 -1
- package/dist/modules/playerOnboarding/index.d.ts.map +1 -1
- package/dist/modules/playerOnboarding/index.js +2 -0
- package/dist/modules/playerOnboarding/index.js.map +1 -1
- package/dist/modules/serverMessages/index.d.ts.map +1 -1
- package/dist/modules/serverMessages/index.js +2 -0
- package/dist/modules/serverMessages/index.js.map +1 -1
- package/dist/modules/teleports/commands/deletewaypoint.js +1 -4
- package/dist/modules/teleports/commands/deletewaypoint.js.map +1 -1
- package/dist/modules/teleports/commands/setpublic.js +0 -3
- package/dist/modules/teleports/commands/setpublic.js.map +1 -1
- package/dist/modules/teleports/commands/settp.js +1 -4
- package/dist/modules/teleports/commands/settp.js.map +1 -1
- package/dist/modules/teleports/commands/setwaypoint.js +1 -4
- package/dist/modules/teleports/commands/setwaypoint.js.map +1 -1
- package/dist/modules/teleports/commands/teleport.js +1 -4
- package/dist/modules/teleports/commands/teleport.js.map +1 -1
- package/dist/modules/teleports/index.d.ts.map +1 -1
- package/dist/modules/teleports/index.js +9 -1
- package/dist/modules/teleports/index.js.map +1 -1
- package/dist/modules/timedShutdown/index.d.ts.map +1 -1
- package/dist/modules/timedShutdown/index.js +2 -0
- package/dist/modules/timedShutdown/index.js.map +1 -1
- package/dist/modules/utils/commands/help.js +60 -6
- package/dist/modules/utils/commands/help.js.map +1 -1
- package/dist/modules/utils/index.d.ts.map +1 -1
- package/dist/modules/utils/index.js +11 -2
- package/dist/modules/utils/index.js.map +1 -1
- package/dist/modules.json +112 -18
- package/package.json +1 -1
- package/src/BuiltinModule.ts +11 -0
- package/src/__tests__/economy/economyUtils.integration.test.ts +6 -2
- package/src/__tests__/help.integration.test.ts +230 -62
- package/src/__tests__/lottery.integration.test.ts +5 -1
- package/src/__tests__/modulePermission.integration.test.ts +197 -11
- package/src/__tests__/roleExpiry.integration.test.ts +6 -2
- package/src/__tests__/teleports/publicteleports.integration.test.ts +1 -1
- package/src/__tests__/teleports/waypoints.integration.test.ts +6 -2
- package/src/dto/takaroEvents.ts +16 -0
- package/src/modules/chatBridge/index.ts +2 -0
- package/src/modules/dailyRewards/commands/daily.js +1 -5
- package/src/modules/dailyRewards/index.ts +4 -1
- package/src/modules/economyUtils/commands/confirmTransfer.js +6 -6
- package/src/modules/economyUtils/commands/grantCurrency.js +1 -5
- package/src/modules/economyUtils/commands/revokeCurrency.js +1 -5
- package/src/modules/economyUtils/index.ts +5 -1
- package/src/modules/geoBlock/index.ts +2 -0
- package/src/modules/gimme/index.ts +2 -0
- package/src/modules/highPingKicker/index.ts +2 -0
- package/src/modules/lottery/commands/buyTicket.js +1 -5
- package/src/modules/lottery/commands/viewTickets.js +5 -9
- package/src/modules/lottery/index.ts +5 -1
- package/src/modules/playerOnboarding/index.ts +2 -0
- package/src/modules/serverMessages/index.ts +2 -0
- package/src/modules/teleports/commands/deletewaypoint.js +1 -5
- package/src/modules/teleports/commands/setpublic.js +1 -5
- package/src/modules/teleports/commands/settp.js +1 -6
- package/src/modules/teleports/commands/setwaypoint.js +1 -5
- package/src/modules/teleports/commands/teleport.js +1 -5
- package/src/modules/teleports/index.ts +9 -1
- package/src/modules/timedShutdown/index.ts +2 -0
- package/src/modules/utils/commands/help.js +70 -8
- package/src/modules/utils/index.ts +11 -2
|
@@ -1,140 +1,308 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
expect,
|
|
4
|
-
IModuleTestsSetupData,
|
|
5
|
-
modulesTestSetup,
|
|
6
|
-
chatMessageSorter,
|
|
7
|
-
EventsAwaiter,
|
|
8
|
-
} from '@takaro/test';
|
|
9
|
-
import { GameEvents } from '../dto/gameEvents.js';
|
|
1
|
+
import { IntegrationTest, expect, IModuleTestsSetupData, modulesTestSetup, EventsAwaiter } from '@takaro/test';
|
|
2
|
+
import { GameEvents } from '../dto/index.js';
|
|
10
3
|
import { describe } from 'node:test';
|
|
11
4
|
|
|
12
|
-
const group = '
|
|
5
|
+
const group = 'help command suite';
|
|
13
6
|
|
|
14
7
|
const tests = [
|
|
15
8
|
new IntegrationTest<IModuleTestsSetupData>({
|
|
16
9
|
group,
|
|
17
10
|
snapshot: false,
|
|
18
11
|
setup: modulesTestSetup,
|
|
19
|
-
name: '
|
|
12
|
+
name: 'Shows all available commands when no argument provided',
|
|
20
13
|
test: async function () {
|
|
21
14
|
await this.client.module.moduleInstallationsControllerInstallModule({
|
|
22
15
|
gameServerId: this.setupData.gameserver.id,
|
|
23
16
|
versionId: this.setupData.utilsModule.latestVersion.id,
|
|
24
17
|
});
|
|
18
|
+
|
|
25
19
|
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 3);
|
|
20
|
+
|
|
26
21
|
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
27
22
|
msg: '/help',
|
|
28
23
|
playerId: this.setupData.players[0].id,
|
|
29
24
|
});
|
|
30
25
|
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
const messages = await events;
|
|
27
|
+
expect(messages.length).to.be.greaterThan(0);
|
|
28
|
+
expect(messages[0].data.meta.msg).to.include('Available commands:');
|
|
29
|
+
// Should show help and ping commands from utils module
|
|
30
|
+
expect(messages.some((m) => m.data.meta.msg.includes('help:'))).to.be.true;
|
|
31
|
+
expect(messages.some((m) => m.data.meta.msg.includes('ping:'))).to.be.true;
|
|
32
|
+
},
|
|
33
|
+
}),
|
|
34
|
+
new IntegrationTest<IModuleTestsSetupData>({
|
|
35
|
+
group,
|
|
36
|
+
snapshot: false,
|
|
37
|
+
setup: modulesTestSetup,
|
|
38
|
+
name: 'Shows specific command help when command name provided',
|
|
39
|
+
test: async function () {
|
|
40
|
+
await this.client.module.moduleInstallationsControllerInstallModule({
|
|
41
|
+
gameServerId: this.setupData.gameserver.id,
|
|
42
|
+
versionId: this.setupData.utilsModule.latestVersion.id,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE);
|
|
33
46
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
);
|
|
47
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
48
|
+
msg: '/help ping',
|
|
49
|
+
playerId: this.setupData.players[0].id,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const messages = await events;
|
|
53
|
+
expect(messages.length).to.be.eq(1);
|
|
54
|
+
expect(messages[0].data.meta.msg).to.include('ping:');
|
|
55
|
+
expect(messages[0].data.meta.msg).to.include('pong');
|
|
41
56
|
},
|
|
42
57
|
}),
|
|
43
58
|
new IntegrationTest<IModuleTestsSetupData>({
|
|
44
59
|
group,
|
|
45
60
|
snapshot: false,
|
|
46
61
|
setup: modulesTestSetup,
|
|
47
|
-
name: '
|
|
62
|
+
name: 'Search returns commands with matching names',
|
|
48
63
|
test: async function () {
|
|
49
64
|
await this.client.module.moduleInstallationsControllerInstallModule({
|
|
50
65
|
gameServerId: this.setupData.gameserver.id,
|
|
51
66
|
versionId: this.setupData.utilsModule.latestVersion.id,
|
|
52
67
|
});
|
|
68
|
+
|
|
69
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 2);
|
|
70
|
+
|
|
71
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
72
|
+
msg: '/help search ping',
|
|
73
|
+
playerId: this.setupData.players[0].id,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const messages = await events;
|
|
77
|
+
expect(messages.length).to.be.greaterThan(0);
|
|
78
|
+
expect(messages[0].data.meta.msg).to.include('Commands matching "ping":');
|
|
79
|
+
expect(messages.some((m) => m.data.meta.msg.includes('ping:'))).to.be.true;
|
|
80
|
+
},
|
|
81
|
+
}),
|
|
82
|
+
new IntegrationTest<IModuleTestsSetupData>({
|
|
83
|
+
group,
|
|
84
|
+
snapshot: false,
|
|
85
|
+
setup: modulesTestSetup,
|
|
86
|
+
name: 'Search returns commands with matching help text',
|
|
87
|
+
test: async function () {
|
|
53
88
|
await this.client.module.moduleInstallationsControllerInstallModule({
|
|
54
89
|
gameServerId: this.setupData.gameserver.id,
|
|
55
|
-
versionId: this.setupData.
|
|
90
|
+
versionId: this.setupData.utilsModule.latestVersion.id,
|
|
56
91
|
});
|
|
57
|
-
|
|
92
|
+
|
|
93
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 2);
|
|
94
|
+
|
|
58
95
|
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
59
|
-
msg: '/help',
|
|
96
|
+
msg: '/help search pong',
|
|
60
97
|
playerId: this.setupData.players[0].id,
|
|
61
98
|
});
|
|
62
99
|
|
|
63
|
-
const
|
|
100
|
+
const messages = await events;
|
|
101
|
+
expect(messages.length).to.be.greaterThan(0);
|
|
102
|
+
expect(messages[0].data.meta.msg).to.include('Commands matching "pong":');
|
|
103
|
+
expect(messages.some((m) => m.data.meta.msg.includes('ping:'))).to.be.true;
|
|
104
|
+
},
|
|
105
|
+
}),
|
|
106
|
+
new IntegrationTest<IModuleTestsSetupData>({
|
|
107
|
+
group,
|
|
108
|
+
snapshot: false,
|
|
109
|
+
setup: modulesTestSetup,
|
|
110
|
+
name: 'Search is case-insensitive',
|
|
111
|
+
test: async function () {
|
|
112
|
+
await this.client.module.moduleInstallationsControllerInstallModule({
|
|
113
|
+
gameServerId: this.setupData.gameserver.id,
|
|
114
|
+
versionId: this.setupData.utilsModule.latestVersion.id,
|
|
115
|
+
});
|
|
64
116
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
);
|
|
75
|
-
expect(
|
|
76
|
-
'setprivate: Sets a teleport to be private, only the teleport owner can teleport to it.',
|
|
77
|
-
);
|
|
78
|
-
expect(sortedEvents[7].data.meta.msg).to.be.eq(
|
|
79
|
-
'setpublic: Sets a teleport to be public, allowing other players to teleport to it.',
|
|
80
|
-
);
|
|
81
|
-
expect(sortedEvents[8].data.meta.msg).to.be.eq('settp: Sets a location to teleport to.');
|
|
82
|
-
expect(sortedEvents[9].data.meta.msg).to.be.eq('setwaypoint: Creates a new waypoint.');
|
|
83
|
-
expect(sortedEvents[10].data.meta.msg).to.be.eq('teleport: Teleports to one of your set locations.');
|
|
84
|
-
expect(sortedEvents[11].data.meta.msg).to.be.eq(
|
|
85
|
-
'teleportwaypoint: Placeholder command, this will not be used directly. The module will install aliases for this command corresponding to the waypoint names.',
|
|
86
|
-
);
|
|
87
|
-
expect(sortedEvents[12].data.meta.msg).to.be.eq('tplist: Lists all your set locations.');
|
|
117
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 2);
|
|
118
|
+
|
|
119
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
120
|
+
msg: '/help search PING',
|
|
121
|
+
playerId: this.setupData.players[0].id,
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const messages = await events;
|
|
125
|
+
expect(messages.length).to.be.greaterThan(0);
|
|
126
|
+
expect(messages[0].data.meta.msg).to.include('Commands matching "PING":');
|
|
127
|
+
expect(messages.some((m) => m.data.meta.msg.includes('ping:'))).to.be.true;
|
|
88
128
|
},
|
|
89
129
|
}),
|
|
90
130
|
new IntegrationTest<IModuleTestsSetupData>({
|
|
91
131
|
group,
|
|
92
132
|
snapshot: false,
|
|
93
133
|
setup: modulesTestSetup,
|
|
94
|
-
name: '
|
|
134
|
+
name: 'Search supports partial matches',
|
|
95
135
|
test: async function () {
|
|
96
136
|
await this.client.module.moduleInstallationsControllerInstallModule({
|
|
97
137
|
gameServerId: this.setupData.gameserver.id,
|
|
98
138
|
versionId: this.setupData.utilsModule.latestVersion.id,
|
|
99
139
|
});
|
|
100
140
|
|
|
101
|
-
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE,
|
|
141
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 2);
|
|
102
142
|
|
|
103
143
|
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
104
|
-
msg: '/help
|
|
144
|
+
msg: '/help search hel',
|
|
105
145
|
playerId: this.setupData.players[0].id,
|
|
106
146
|
});
|
|
107
147
|
|
|
108
|
-
|
|
109
|
-
|
|
148
|
+
const messages = await events;
|
|
149
|
+
expect(messages.length).to.be.greaterThan(0);
|
|
150
|
+
expect(messages[0].data.meta.msg).to.include('Commands matching "hel":');
|
|
151
|
+
expect(messages.some((m) => m.data.meta.msg.includes('help:'))).to.be.true;
|
|
152
|
+
},
|
|
153
|
+
}),
|
|
154
|
+
new IntegrationTest<IModuleTestsSetupData>({
|
|
155
|
+
group,
|
|
156
|
+
snapshot: false,
|
|
157
|
+
setup: modulesTestSetup,
|
|
158
|
+
name: 'Search returns appropriate message when no matches found',
|
|
159
|
+
test: async function () {
|
|
160
|
+
await this.client.module.moduleInstallationsControllerInstallModule({
|
|
161
|
+
gameServerId: this.setupData.gameserver.id,
|
|
162
|
+
versionId: this.setupData.utilsModule.latestVersion.id,
|
|
163
|
+
});
|
|
110
164
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
165
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE);
|
|
166
|
+
|
|
167
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
168
|
+
msg: '/help search nonexistentcommand',
|
|
169
|
+
playerId: this.setupData.players[0].id,
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
const messages = await events;
|
|
173
|
+
expect(messages.length).to.be.eq(1);
|
|
174
|
+
expect(messages[0].data.meta.msg).to.include('No commands found matching "nonexistentcommand"');
|
|
175
|
+
},
|
|
176
|
+
}),
|
|
177
|
+
new IntegrationTest<IModuleTestsSetupData>({
|
|
178
|
+
group,
|
|
179
|
+
snapshot: false,
|
|
180
|
+
setup: modulesTestSetup,
|
|
181
|
+
name: 'Search works across multiple modules',
|
|
182
|
+
test: async function () {
|
|
183
|
+
// Install utils module
|
|
184
|
+
await this.client.module.moduleInstallationsControllerInstallModule({
|
|
185
|
+
gameServerId: this.setupData.gameserver.id,
|
|
186
|
+
versionId: this.setupData.utilsModule.latestVersion.id,
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// Install another module (gimme) to have more commands
|
|
190
|
+
await this.client.module.moduleInstallationsControllerInstallModule({
|
|
191
|
+
gameServerId: this.setupData.gameserver.id,
|
|
192
|
+
versionId: this.setupData.gimmeModule.latestVersion.id,
|
|
193
|
+
userConfig: JSON.stringify({
|
|
194
|
+
items: [],
|
|
195
|
+
commands: ['say test'],
|
|
196
|
+
}),
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 2);
|
|
200
|
+
|
|
201
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
202
|
+
msg: '/help search command',
|
|
203
|
+
playerId: this.setupData.players[0].id,
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const messages = await events;
|
|
207
|
+
expect(messages.length).to.be.greaterThan(0);
|
|
208
|
+
expect(messages[0].data.meta.msg).to.include('Commands matching "command":');
|
|
209
|
+
// Should find help command which has "command" in its help text
|
|
210
|
+
expect(messages.some((m) => m.data.meta.msg.includes('help:'))).to.be.true;
|
|
114
211
|
},
|
|
115
212
|
}),
|
|
116
213
|
new IntegrationTest<IModuleTestsSetupData>({
|
|
117
214
|
group,
|
|
118
215
|
snapshot: false,
|
|
119
216
|
setup: modulesTestSetup,
|
|
120
|
-
name: '
|
|
217
|
+
name: 'Does not show commands from disabled modules',
|
|
121
218
|
test: async function () {
|
|
219
|
+
// First install utils module normally so help command is available
|
|
122
220
|
await this.client.module.moduleInstallationsControllerInstallModule({
|
|
123
221
|
gameServerId: this.setupData.gameserver.id,
|
|
124
222
|
versionId: this.setupData.utilsModule.latestVersion.id,
|
|
125
223
|
});
|
|
126
224
|
|
|
127
|
-
|
|
225
|
+
// Install teleports module but disabled
|
|
226
|
+
const teleportsInstallation = await this.client.module.moduleInstallationsControllerInstallModule({
|
|
227
|
+
gameServerId: this.setupData.gameserver.id,
|
|
228
|
+
versionId: this.setupData.teleportsModule.latestVersion.id,
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// Get the current system config and disable the teleports module
|
|
232
|
+
const systemConfig = teleportsInstallation.data.data.systemConfig as any;
|
|
233
|
+
systemConfig.enabled = false;
|
|
234
|
+
|
|
235
|
+
// Uninstall and reinstall teleports module with disabled config
|
|
236
|
+
await this.client.module.moduleInstallationsControllerUninstallModule(
|
|
237
|
+
teleportsInstallation.data.data.moduleId,
|
|
238
|
+
this.setupData.gameserver.id,
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
await this.client.module.moduleInstallationsControllerInstallModule({
|
|
242
|
+
gameServerId: this.setupData.gameserver.id,
|
|
243
|
+
versionId: this.setupData.teleportsModule.latestVersion.id,
|
|
244
|
+
systemConfig: JSON.stringify(systemConfig),
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 3);
|
|
128
248
|
|
|
129
249
|
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
130
|
-
msg: '/help
|
|
250
|
+
msg: '/help',
|
|
131
251
|
playerId: this.setupData.players[0].id,
|
|
132
252
|
});
|
|
133
253
|
|
|
134
|
-
|
|
135
|
-
expect(
|
|
136
|
-
|
|
254
|
+
const messages = await events;
|
|
255
|
+
expect(messages.length).to.be.greaterThan(0);
|
|
256
|
+
expect(messages[0].data.meta.msg).to.include('Available commands:');
|
|
257
|
+
// Should show commands from utils module but NOT from disabled teleports module
|
|
258
|
+
expect(messages.some((m) => m.data.meta.msg.includes('help:'))).to.be.true;
|
|
259
|
+
expect(messages.some((m) => m.data.meta.msg.includes('ping:'))).to.be.true;
|
|
260
|
+
// Should NOT show teleports commands
|
|
261
|
+
expect(messages.some((m) => m.data.meta.msg.includes('settp:'))).to.be.false;
|
|
262
|
+
expect(messages.some((m) => m.data.meta.msg.includes('teleport:'))).to.be.false;
|
|
263
|
+
},
|
|
264
|
+
}),
|
|
265
|
+
new IntegrationTest<IModuleTestsSetupData>({
|
|
266
|
+
group,
|
|
267
|
+
snapshot: false,
|
|
268
|
+
setup: modulesTestSetup,
|
|
269
|
+
name: 'Does not show individually disabled commands',
|
|
270
|
+
test: async function () {
|
|
271
|
+
// Install utils module
|
|
272
|
+
const moduleInstallation = await this.client.module.moduleInstallationsControllerInstallModule({
|
|
273
|
+
gameServerId: this.setupData.gameserver.id,
|
|
274
|
+
versionId: this.setupData.utilsModule.latestVersion.id,
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// Disable only the ping command
|
|
278
|
+
const systemConfig = moduleInstallation.data.data.systemConfig as any;
|
|
279
|
+
systemConfig.commands.ping.enabled = false;
|
|
280
|
+
|
|
281
|
+
// Uninstall and reinstall with new config
|
|
282
|
+
await this.client.module.moduleInstallationsControllerUninstallModule(
|
|
283
|
+
moduleInstallation.data.data.moduleId,
|
|
284
|
+
this.setupData.gameserver.id,
|
|
137
285
|
);
|
|
286
|
+
|
|
287
|
+
await this.client.module.moduleInstallationsControllerInstallModule({
|
|
288
|
+
gameServerId: this.setupData.gameserver.id,
|
|
289
|
+
versionId: this.setupData.utilsModule.latestVersion.id,
|
|
290
|
+
systemConfig: JSON.stringify(systemConfig),
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 2);
|
|
294
|
+
|
|
295
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
296
|
+
msg: '/help',
|
|
297
|
+
playerId: this.setupData.players[0].id,
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
const messages = await events;
|
|
301
|
+
expect(messages.length).to.be.greaterThan(0);
|
|
302
|
+
expect(messages[0].data.meta.msg).to.include('Available commands:');
|
|
303
|
+
// Should show help command but NOT ping command
|
|
304
|
+
expect(messages.some((m) => m.data.meta.msg.includes('help:'))).to.be.true;
|
|
305
|
+
expect(messages.some((m) => m.data.meta.msg.includes('ping:'))).to.be.false;
|
|
138
306
|
},
|
|
139
307
|
}),
|
|
140
308
|
];
|
|
@@ -171,7 +171,11 @@ const tests = [
|
|
|
171
171
|
playerId: this.setupData.players[0].id,
|
|
172
172
|
});
|
|
173
173
|
|
|
174
|
-
await waitForBuyEvents;
|
|
174
|
+
const buyEvents = await waitForBuyEvents;
|
|
175
|
+
expect(buyEvents.length).to.be.eq(1);
|
|
176
|
+
expect(buyEvents[0].data.meta.msg).to.be.eq(
|
|
177
|
+
`You have successfully bought ${wantAmount} tickets for ${wantAmount * ticketCost} Takaro coins. Good luck!`,
|
|
178
|
+
);
|
|
175
179
|
|
|
176
180
|
const waitForViewEvent = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE);
|
|
177
181
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IntegrationTest, expect, IModuleTestsSetupData, modulesTestSetup, EventsAwaiter } from '@takaro/test';
|
|
2
|
-
import {
|
|
2
|
+
import { IHookEventTypeEnum } from '@takaro/apiclient';
|
|
3
3
|
import { describe } from 'node:test';
|
|
4
4
|
import { randomUUID } from 'crypto';
|
|
5
5
|
import { getMockServer } from '@takaro/mock-gameserver';
|
|
@@ -55,7 +55,10 @@ const tests = [
|
|
|
55
55
|
});
|
|
56
56
|
await this.client.player.playerControllerAssignRole(this.setupData.players[0].id, this.setupData.role.id);
|
|
57
57
|
|
|
58
|
-
const setEvents = (await new EventsAwaiter().connect(this.client)).waitForEvents(
|
|
58
|
+
const setEvents = (await new EventsAwaiter().connect(this.client)).waitForEvents(
|
|
59
|
+
IHookEventTypeEnum.ChatMessage,
|
|
60
|
+
1,
|
|
61
|
+
);
|
|
59
62
|
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
60
63
|
msg: '/settp test',
|
|
61
64
|
playerId: this.setupData.players[0].id,
|
|
@@ -87,14 +90,19 @@ const tests = [
|
|
|
87
90
|
gameServerId: newGameServer.id,
|
|
88
91
|
});
|
|
89
92
|
|
|
90
|
-
const setEvents = (await new EventsAwaiter().connect(this.client)).waitForEvents(
|
|
93
|
+
const setEvents = (await new EventsAwaiter().connect(this.client)).waitForEvents(
|
|
94
|
+
IHookEventTypeEnum.ChatMessage,
|
|
95
|
+
1,
|
|
96
|
+
);
|
|
91
97
|
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
92
98
|
msg: '/settp test',
|
|
93
99
|
playerId: this.setupData.players[0].id,
|
|
94
100
|
});
|
|
95
101
|
|
|
96
102
|
expect((await setEvents).length).to.be.eq(1);
|
|
97
|
-
expect((await setEvents)[0].data.meta.msg).to.be.eq(
|
|
103
|
+
expect((await setEvents)[0].data.meta.msg).to.be.eq(
|
|
104
|
+
"⚠️ You need the 'Teleports Use' permission to use this command. Please contact an admin if you need access.",
|
|
105
|
+
);
|
|
98
106
|
},
|
|
99
107
|
}),
|
|
100
108
|
new IntegrationTest<IModuleTestsSetupData>({
|
|
@@ -117,7 +125,10 @@ const tests = [
|
|
|
117
125
|
gameServerId: this.setupData.gameserver.id,
|
|
118
126
|
});
|
|
119
127
|
|
|
120
|
-
const setEvents = (await new EventsAwaiter().connect(this.client)).waitForEvents(
|
|
128
|
+
const setEvents = (await new EventsAwaiter().connect(this.client)).waitForEvents(
|
|
129
|
+
IHookEventTypeEnum.ChatMessage,
|
|
130
|
+
1,
|
|
131
|
+
);
|
|
121
132
|
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
122
133
|
msg: '/settp test',
|
|
123
134
|
playerId: this.setupData.players[0].id,
|
|
@@ -148,6 +159,7 @@ const tests = [
|
|
|
148
159
|
);
|
|
149
160
|
|
|
150
161
|
const playerRoleRes = await this.client.role.roleControllerSearch({ filters: { name: ['Player'] } });
|
|
162
|
+
|
|
151
163
|
const useTeleportsRole = await this.client.permissionCodesToInputs(['TELEPORTS_USE']);
|
|
152
164
|
await this.client.role.roleControllerUpdate(playerRoleRes.data.data[0].id, {
|
|
153
165
|
permissions: [
|
|
@@ -158,17 +170,22 @@ const tests = [
|
|
|
158
170
|
],
|
|
159
171
|
});
|
|
160
172
|
|
|
161
|
-
const setTpEvent = (await new EventsAwaiter().connect(this.client)).waitForEvents(
|
|
173
|
+
const setTpEvent = (await new EventsAwaiter().connect(this.client)).waitForEvents(
|
|
174
|
+
IHookEventTypeEnum.ChatMessage,
|
|
175
|
+
1,
|
|
176
|
+
);
|
|
162
177
|
|
|
163
178
|
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
164
179
|
msg: '/settp test',
|
|
165
180
|
playerId: this.setupData.players[0].id,
|
|
166
181
|
});
|
|
167
182
|
|
|
168
|
-
|
|
169
|
-
|
|
183
|
+
const setTpEventResult = await setTpEvent;
|
|
184
|
+
|
|
185
|
+
expect(setTpEventResult.length).to.be.eq(1);
|
|
186
|
+
expect(setTpEventResult[0].data.meta.msg).to.be.eq('Teleport test set.');
|
|
170
187
|
|
|
171
|
-
const tpEvent = (await new EventsAwaiter().connect(this.client)).waitForEvents(
|
|
188
|
+
const tpEvent = (await new EventsAwaiter().connect(this.client)).waitForEvents(IHookEventTypeEnum.ChatMessage, 1);
|
|
172
189
|
|
|
173
190
|
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
174
191
|
msg: '/tp test',
|
|
@@ -182,14 +199,183 @@ const tests = [
|
|
|
182
199
|
permissions: [],
|
|
183
200
|
});
|
|
184
201
|
|
|
185
|
-
const tpEventNoPerm = (await new EventsAwaiter().connect(this.client)).waitForEvents(
|
|
202
|
+
const tpEventNoPerm = (await new EventsAwaiter().connect(this.client)).waitForEvents(
|
|
203
|
+
IHookEventTypeEnum.ChatMessage,
|
|
204
|
+
1,
|
|
205
|
+
);
|
|
186
206
|
|
|
187
207
|
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
188
208
|
msg: '/tp test',
|
|
189
209
|
playerId: this.setupData.players[0].id,
|
|
190
210
|
});
|
|
191
211
|
|
|
192
|
-
expect((await tpEventNoPerm)[0].data.meta.msg).to.
|
|
212
|
+
expect((await tpEventNoPerm)[0].data.meta.msg).to.include("You need the 'Teleports Use' permission");
|
|
213
|
+
},
|
|
214
|
+
}),
|
|
215
|
+
new IntegrationTest<IModuleTestsSetupData>({
|
|
216
|
+
group,
|
|
217
|
+
snapshot: false,
|
|
218
|
+
setup: async function () {
|
|
219
|
+
const defaultSetup = await modulesTestSetup.bind(this)();
|
|
220
|
+
|
|
221
|
+
// Remove all permissions from the default role
|
|
222
|
+
await this.client.role.roleControllerUpdate(defaultSetup.role.id, {
|
|
223
|
+
name: defaultSetup.role.name,
|
|
224
|
+
permissions: [],
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
return defaultSetup;
|
|
228
|
+
},
|
|
229
|
+
name: 'Command execution denied when player lacks requiredPermissions',
|
|
230
|
+
test: async function () {
|
|
231
|
+
// Install economyUtils module which has commands with requiredPermissions
|
|
232
|
+
const installRes = await this.client.module.moduleInstallationsControllerInstallModule({
|
|
233
|
+
gameServerId: this.setupData.gameserver.id,
|
|
234
|
+
versionId: this.setupData.economyUtilsModule.latestVersion.id,
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// Verify installation succeeded
|
|
238
|
+
expect(installRes.data.data).to.exist;
|
|
239
|
+
|
|
240
|
+
// Ensure we have at least 1 player
|
|
241
|
+
expect(this.setupData.players.length).to.be.at.least(1);
|
|
242
|
+
const executingPlayer = this.setupData.players[0];
|
|
243
|
+
|
|
244
|
+
// Remove any existing roles from the player to ensure they have no special permissions
|
|
245
|
+
await this.client.player.playerControllerRemoveRole(executingPlayer.id, this.setupData.role.id);
|
|
246
|
+
|
|
247
|
+
// Check player's roles after removal
|
|
248
|
+
const playerAfter = await this.client.player.playerControllerGetOne(executingPlayer.id);
|
|
249
|
+
|
|
250
|
+
// If player still has system roles, we need to handle the Player role specially
|
|
251
|
+
if (playerAfter.data.data.roleAssignments && playerAfter.data.data.roleAssignments.length > 0) {
|
|
252
|
+
// Find the Player role
|
|
253
|
+
const playerRole = playerAfter.data.data.roleAssignments.find((ra) => ra.role.name === 'Player');
|
|
254
|
+
if (!playerRole) throw new Error('Player role not found after removing roles');
|
|
255
|
+
// Update the Player role to have no permissions
|
|
256
|
+
await this.client.role.roleControllerUpdate(playerRole.role.id, {
|
|
257
|
+
name: 'Player',
|
|
258
|
+
permissions: [],
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Enable economy for this test
|
|
263
|
+
await this.client.settings.settingsControllerSet('economyEnabled', {
|
|
264
|
+
value: 'true',
|
|
265
|
+
gameServerId: this.setupData.gameserver.id,
|
|
266
|
+
});
|
|
267
|
+
await this.client.settings.settingsControllerSet('currencyName', {
|
|
268
|
+
gameServerId: this.setupData.gameserver.id,
|
|
269
|
+
value: 'test coin',
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
// Set up event listener - just listen for the chat message
|
|
273
|
+
const eventsAwaiter = await new EventsAwaiter().connect(this.client);
|
|
274
|
+
const chatEvents = eventsAwaiter.waitForEvents(IHookEventTypeEnum.ChatMessage, 1);
|
|
275
|
+
|
|
276
|
+
// Try to execute grantCurrency command without permission
|
|
277
|
+
const targetPlayer = this.setupData.players.length > 1 ? this.setupData.players[1] : executingPlayer;
|
|
278
|
+
const commandMsg = `/grantcurrency ${targetPlayer.name} 100`;
|
|
279
|
+
|
|
280
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
281
|
+
msg: commandMsg,
|
|
282
|
+
playerId: executingPlayer.id,
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// Check if we got a permission denied message
|
|
286
|
+
const chatEventResults = await chatEvents;
|
|
287
|
+
expect(chatEventResults).to.have.length(1);
|
|
288
|
+
expect(chatEventResults[0].data.meta.msg).to.match(/do not have permission|need.*permission/i);
|
|
289
|
+
},
|
|
290
|
+
}),
|
|
291
|
+
new IntegrationTest<IModuleTestsSetupData>({
|
|
292
|
+
group,
|
|
293
|
+
snapshot: false,
|
|
294
|
+
setup: modulesTestSetup,
|
|
295
|
+
name: 'Command execution allowed when player has requiredPermissions',
|
|
296
|
+
test: async function () {
|
|
297
|
+
// Install economyUtils module
|
|
298
|
+
await this.client.module.moduleInstallationsControllerInstallModule({
|
|
299
|
+
gameServerId: this.setupData.gameserver.id,
|
|
300
|
+
versionId: this.setupData.economyUtilsModule.latestVersion.id,
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
// Create a role with ECONOMY_UTILS_MANAGE_CURRENCY permission
|
|
304
|
+
const permissions = await this.client.permissionCodesToInputs(['ECONOMY_UTILS_MANAGE_CURRENCY']);
|
|
305
|
+
const roleRes = await this.client.role.roleControllerCreate({
|
|
306
|
+
name: 'Currency Manager',
|
|
307
|
+
permissions,
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// Assign the role to the player
|
|
311
|
+
await this.client.player.playerControllerAssignRole(this.setupData.players[0].id, roleRes.data.data.id);
|
|
312
|
+
|
|
313
|
+
// Set up event listener for COMMAND_EXECUTED event
|
|
314
|
+
const eventsAwaiter = await new EventsAwaiter().connect(this.client);
|
|
315
|
+
const executedEvents = eventsAwaiter.waitForEvents(IHookEventTypeEnum.CommandExecuted, 1);
|
|
316
|
+
|
|
317
|
+
// Execute grantCurrency command with permission
|
|
318
|
+
const targetPlayer = this.setupData.players.length > 1 ? this.setupData.players[1] : this.setupData.players[0];
|
|
319
|
+
|
|
320
|
+
const commandMsg = `/grantcurrency ${targetPlayer.name} 100`;
|
|
321
|
+
|
|
322
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
323
|
+
msg: commandMsg,
|
|
324
|
+
playerId: this.setupData.players[0].id,
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
// Verify COMMAND_EXECUTED event was logged (not COMMAND_EXECUTION_DENIED)
|
|
328
|
+
const executedEventResults = await executedEvents;
|
|
329
|
+
expect(executedEventResults).to.have.length(1);
|
|
330
|
+
expect(executedEventResults[0].data.eventName).to.equal('command-executed');
|
|
331
|
+
// Command might fail during execution, but the important thing is that it was allowed to execute
|
|
332
|
+
// expect(executedEventResults[0].data.command.name).to.equal('grantcurrency');
|
|
333
|
+
// expect(executedEventResults[0].data.player.id).to.equal(this.setupData.players[0].id);
|
|
334
|
+
},
|
|
335
|
+
}),
|
|
336
|
+
new IntegrationTest<IModuleTestsSetupData>({
|
|
337
|
+
group,
|
|
338
|
+
snapshot: false,
|
|
339
|
+
setup: modulesTestSetup,
|
|
340
|
+
name: 'ROOT permission bypasses command permission checks',
|
|
341
|
+
test: async function () {
|
|
342
|
+
// Install economyUtils module
|
|
343
|
+
await this.client.module.moduleInstallationsControllerInstallModule({
|
|
344
|
+
gameServerId: this.setupData.gameserver.id,
|
|
345
|
+
versionId: this.setupData.economyUtilsModule.latestVersion.id,
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
// Create a role with ROOT permission
|
|
349
|
+
const permissions = await this.client.permissionCodesToInputs(['ROOT']);
|
|
350
|
+
const roleRes = await this.client.role.roleControllerCreate({
|
|
351
|
+
name: 'Root Admin Test',
|
|
352
|
+
permissions,
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
// Remove existing roles and assign ROOT role
|
|
356
|
+
await this.client.player.playerControllerRemoveRole(this.setupData.players[0].id, this.setupData.role.id);
|
|
357
|
+
await this.client.player.playerControllerAssignRole(this.setupData.players[0].id, roleRes.data.data.id);
|
|
358
|
+
|
|
359
|
+
// Set up event listener for COMMAND_EXECUTED event
|
|
360
|
+
const eventsAwaiter = await new EventsAwaiter().connect(this.client);
|
|
361
|
+
const executedEvents = eventsAwaiter.waitForEvents(IHookEventTypeEnum.CommandExecuted, 1);
|
|
362
|
+
|
|
363
|
+
// Execute grantCurrency command with ROOT permission (should bypass permission check)
|
|
364
|
+
const targetPlayer = this.setupData.players.length > 1 ? this.setupData.players[1] : this.setupData.players[0];
|
|
365
|
+
|
|
366
|
+
const commandMsg = `/grantcurrency ${targetPlayer.name} 100`;
|
|
367
|
+
|
|
368
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
369
|
+
msg: commandMsg,
|
|
370
|
+
playerId: this.setupData.players[0].id,
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
// Verify command was executed successfully
|
|
374
|
+
const executedEventResults = await executedEvents;
|
|
375
|
+
expect(executedEventResults).to.have.length(1);
|
|
376
|
+
expect(executedEventResults[0].data.eventName).to.equal('command-executed');
|
|
377
|
+
// Command might fail during execution, but the important thing is that ROOT bypassed the permission check
|
|
378
|
+
// expect(executedEventResults[0].data.command.name).to.equal('grantcurrency');
|
|
193
379
|
},
|
|
194
380
|
}),
|
|
195
381
|
];
|