@takaro/modules 0.0.10 → 0.0.13
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/dto/takaroEvents.d.ts +0 -3
- package/dist/dto/takaroEvents.js +1 -13
- package/dist/dto/takaroEvents.js.map +1 -1
- package/dist/main.js +2 -0
- package/dist/main.js.map +1 -1
- package/dist/modules/economyUtils/commands/shop.d.ts +1 -0
- package/dist/modules/economyUtils/commands/shop.js +69 -0
- package/dist/modules/economyUtils/commands/shop.js.map +1 -0
- package/dist/modules/economyUtils/commands/transfer.js +1 -1
- package/dist/modules/economyUtils/commands/transfer.js.map +1 -1
- package/dist/modules/economyUtils/index.js +29 -0
- package/dist/modules/economyUtils/index.js.map +1 -1
- package/dist/modules/serverMessages/cronJobs/Automated message.js +35 -3
- package/dist/modules/serverMessages/cronJobs/Automated message.js.map +1 -1
- package/dist/modules/timedShutdown/cronJobs/Shutdown.d.ts +1 -0
- package/dist/modules/timedShutdown/cronJobs/Shutdown.js +7 -0
- package/dist/modules/timedShutdown/cronJobs/Shutdown.js.map +1 -0
- package/dist/modules/timedShutdown/cronJobs/warning.d.ts +1 -0
- package/dist/modules/timedShutdown/cronJobs/warning.js +10 -0
- package/dist/modules/timedShutdown/cronJobs/warning.js.map +1 -0
- package/dist/modules/timedShutdown/index.d.ts +4 -0
- package/dist/modules/timedShutdown/index.js +33 -0
- package/dist/modules/timedShutdown/index.js.map +1 -0
- package/dist/modules.json +53 -2
- package/package.json +1 -1
- package/scripts/buildBuiltinJson.ts +0 -1
- package/src/__tests__/aliases.integration.test.ts +40 -0
- package/src/__tests__/bugRepros.integration.test.ts +163 -1
- package/src/__tests__/{economyUtils.shop.integration.test.ts → economy/claim.integration.test.ts} +10 -120
- package/src/__tests__/{economyUtils.integration.test.ts → economy/economyUtils.integration.test.ts} +2 -2
- package/src/__tests__/economy/shop.integration.test.ts +153 -0
- package/src/__tests__/serverMessages.integration.test.ts +32 -18
- package/src/dto/takaroEvents.ts +0 -10
- package/src/main.ts +2 -0
- package/src/modules/economyUtils/commands/shop.js +87 -0
- package/src/modules/economyUtils/commands/transfer.js +1 -1
- package/src/modules/economyUtils/index.ts +29 -0
- package/src/modules/serverMessages/cronJobs/Automated message.js +39 -4
- package/src/modules/timedShutdown/cronJobs/Shutdown.js +8 -0
- package/src/modules/timedShutdown/cronJobs/warning.js +13 -0
- package/src/modules/timedShutdown/index.ts +38 -0
|
@@ -40,6 +40,46 @@ const tests = [
|
|
|
40
40
|
playerId: this.setupData.players[0].id,
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
+
expect((await events).length).to.be.eq(1);
|
|
44
|
+
expect((await events)[0].data.meta.msg).to.be.eq('Teleported to test.');
|
|
45
|
+
},
|
|
46
|
+
}),
|
|
47
|
+
new IntegrationTest<IModuleTestsSetupData>({
|
|
48
|
+
group,
|
|
49
|
+
snapshot: false,
|
|
50
|
+
setup: modulesTestSetup,
|
|
51
|
+
name: 'Aliases are case insensitive',
|
|
52
|
+
test: async function () {
|
|
53
|
+
await this.client.gameserver.gameServerControllerInstallModule(
|
|
54
|
+
this.setupData.gameserver.id,
|
|
55
|
+
this.setupData.teleportsModule.id,
|
|
56
|
+
{
|
|
57
|
+
systemConfig: JSON.stringify({
|
|
58
|
+
commands: {
|
|
59
|
+
teleport: {
|
|
60
|
+
delay: 0,
|
|
61
|
+
aliases: ['tp', 'tellyport'],
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
}),
|
|
65
|
+
},
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const setEvents = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 1);
|
|
69
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
70
|
+
msg: '/settp test',
|
|
71
|
+
playerId: this.setupData.players[0].id,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
expect((await setEvents).length).to.be.eq(1);
|
|
75
|
+
expect((await setEvents)[0].data.meta.msg).to.be.eq('Teleport test set.');
|
|
76
|
+
|
|
77
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 1);
|
|
78
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
79
|
+
msg: '/TelLyPoRt test',
|
|
80
|
+
playerId: this.setupData.players[0].id,
|
|
81
|
+
});
|
|
82
|
+
|
|
43
83
|
expect((await events).length).to.be.eq(1);
|
|
44
84
|
expect((await events)[0].data.meta.msg).to.be.eq('Teleported to test.');
|
|
45
85
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IntegrationTest, expect, IModuleTestsSetupData, modulesTestSetup, EventsAwaiter } from '@takaro/test';
|
|
2
|
-
import { GameEvents } from '../dto/index.js';
|
|
2
|
+
import { GameEvents, HookEvents } from '../dto/index.js';
|
|
3
3
|
import { EventChatMessageChannelEnum } from '@takaro/apiclient';
|
|
4
4
|
|
|
5
5
|
const group = 'Bug repros';
|
|
@@ -63,6 +63,168 @@ const tests = [
|
|
|
63
63
|
expect((await events).map((e) => e.data.meta.msg)).to.include.members(['First hook', 'Second hook']);
|
|
64
64
|
},
|
|
65
65
|
}),
|
|
66
|
+
// Before, the event "hook-executed" would not have the correct result logs saved
|
|
67
|
+
// The TakaroDTO validation was rejecting it because "not a string"
|
|
68
|
+
// `An instance of TakaroEventHookExecuted has failed the validation:\n - property result.logs[1].msg has failed the following constraints: isString \n - property result.logs[2].msg has failed the following constraints: isString \n"`
|
|
69
|
+
new IntegrationTest<IModuleTestsSetupData>({
|
|
70
|
+
group,
|
|
71
|
+
snapshot: false,
|
|
72
|
+
name: 'Bug repro: console.log in a function works with objects',
|
|
73
|
+
setup: modulesTestSetup,
|
|
74
|
+
test: async function () {
|
|
75
|
+
const mod = (
|
|
76
|
+
await this.client.module.moduleControllerCreate({
|
|
77
|
+
name: 'Test module',
|
|
78
|
+
})
|
|
79
|
+
).data.data;
|
|
80
|
+
await this.client.hook.hookControllerCreate({
|
|
81
|
+
name: 'Test hook 1',
|
|
82
|
+
moduleId: mod.id,
|
|
83
|
+
regex: 'test msg',
|
|
84
|
+
eventType: 'chat-message',
|
|
85
|
+
function: `import { data, takaro } from '@takaro/helpers';
|
|
86
|
+
async function main() {
|
|
87
|
+
console.log("foo");
|
|
88
|
+
console.log({ foo: "bar" });
|
|
89
|
+
console.log(["baz", 1]);
|
|
90
|
+
}
|
|
91
|
+
await main();`,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
await this.client.gameserver.gameServerControllerInstallModule(this.setupData.gameserver.id, mod.id);
|
|
95
|
+
|
|
96
|
+
const listener = (await new EventsAwaiter().connect(this.client)).waitForEvents(HookEvents.HOOK_EXECUTED, 1);
|
|
97
|
+
|
|
98
|
+
await this.client.hook.hookControllerTrigger({
|
|
99
|
+
eventType: 'chat-message',
|
|
100
|
+
gameServerId: this.setupData.gameserver.id,
|
|
101
|
+
moduleId: mod.id,
|
|
102
|
+
playerId: this.setupData.players[0].id,
|
|
103
|
+
eventMeta: {
|
|
104
|
+
msg: 'test msg',
|
|
105
|
+
channel: EventChatMessageChannelEnum.Global,
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const result = (await listener)[0].data.meta.result;
|
|
110
|
+
expect(result.success).to.be.true;
|
|
111
|
+
const logs = result.logs;
|
|
112
|
+
const msgs = logs.map((l: any) => l.msg);
|
|
113
|
+
expect(msgs).to.include.members(['foo', JSON.stringify({ foo: 'bar' }), JSON.stringify(['baz', 1])]);
|
|
114
|
+
},
|
|
115
|
+
}),
|
|
116
|
+
/**
|
|
117
|
+
* Repro for https://github.com/gettakaro/takaro/issues/1047
|
|
118
|
+
* System config uses the names of functions to create structure
|
|
119
|
+
* If a module is installed, and you then rename the function, the system config will be broken
|
|
120
|
+
*/
|
|
121
|
+
new IntegrationTest<IModuleTestsSetupData>({
|
|
122
|
+
group,
|
|
123
|
+
snapshot: false,
|
|
124
|
+
name: 'Bug repro: renaming functions breaks system config #1047',
|
|
125
|
+
setup: modulesTestSetup,
|
|
126
|
+
test: async function () {
|
|
127
|
+
const mod = (
|
|
128
|
+
await this.client.module.moduleControllerCreate({
|
|
129
|
+
name: 'Test module',
|
|
130
|
+
})
|
|
131
|
+
).data.data;
|
|
132
|
+
const createdCommand = await this.client.command.commandControllerCreate({
|
|
133
|
+
name: 'testcmd',
|
|
134
|
+
moduleId: mod.id,
|
|
135
|
+
trigger: 'testpong',
|
|
136
|
+
function: `import { data, takaro } from '@takaro/helpers';
|
|
137
|
+
async function main() {
|
|
138
|
+
const { player } = data;
|
|
139
|
+
await takaro.gameserver.gameServerControllerSendMessage(data.gameServerId, {
|
|
140
|
+
message: 'pong',
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
await main();`,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
await this.client.gameserver.gameServerControllerInstallModule(this.setupData.gameserver.id, mod.id, {
|
|
147
|
+
userConfig: JSON.stringify({}),
|
|
148
|
+
systemConfig: JSON.stringify({ commands: { testcmd: { aliases: ['foobar'] } } }),
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 1);
|
|
152
|
+
|
|
153
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
154
|
+
msg: '/foobar',
|
|
155
|
+
playerId: this.setupData.players[0].id,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
expect((await events).length).to.be.eq(1);
|
|
159
|
+
expect((await events)[0].data.meta.msg).to.be.eq('pong');
|
|
160
|
+
|
|
161
|
+
// Rename the function
|
|
162
|
+
await this.client.command.commandControllerUpdate(createdCommand.data.data.id, { name: 'testcmd2' });
|
|
163
|
+
|
|
164
|
+
const eventsAfter = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 1);
|
|
165
|
+
|
|
166
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
167
|
+
msg: '/foobar',
|
|
168
|
+
playerId: this.setupData.players[0].id,
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
expect((await eventsAfter).length).to.be.eq(1);
|
|
172
|
+
expect((await eventsAfter)[0].data.meta.msg).to.be.eq('pong');
|
|
173
|
+
},
|
|
174
|
+
}),
|
|
175
|
+
/**
|
|
176
|
+
* Repro for https://github.com/gettakaro/takaro/issues/1405
|
|
177
|
+
* When providing invalid code, Takaro trips over itself and throws a nasty error
|
|
178
|
+
* Instead, it should catch it properly and return an actionable message for the user
|
|
179
|
+
*/
|
|
180
|
+
new IntegrationTest<IModuleTestsSetupData>({
|
|
181
|
+
group,
|
|
182
|
+
snapshot: false,
|
|
183
|
+
name: 'Bug repro: invalid module code throws bad error #1405',
|
|
184
|
+
setup: modulesTestSetup,
|
|
185
|
+
test: async function () {
|
|
186
|
+
const mod = (
|
|
187
|
+
await this.client.module.moduleControllerCreate({
|
|
188
|
+
name: 'Test module',
|
|
189
|
+
})
|
|
190
|
+
).data.data;
|
|
191
|
+
await this.client.command.commandControllerCreate({
|
|
192
|
+
name: 'testcmd',
|
|
193
|
+
moduleId: mod.id,
|
|
194
|
+
trigger: 'test',
|
|
195
|
+
// Yes, very bad code! This is what a user might accidentally do
|
|
196
|
+
function: `import { data, takaro } from '@takaro/helpers';
|
|
197
|
+
|
|
198
|
+
const messed = (await takaro.variable.variableControllerSearch({ search: { key: [\`object Object\`] } })).data.data
|
|
199
|
+
for (const thisVar of messed) {
|
|
200
|
+
let originalString = thisVar.key;
|
|
201
|
+
let newString = originalString.replace("[object Object]", "2024-09-20");
|
|
202
|
+
|
|
203
|
+
await takaro.variable.variableControllerUpdate(thisVar.id, { key: newString, value: thisVar.value });
|
|
204
|
+
|
|
205
|
+
}
|
|
206
|
+
data.player.pm(\`done\`).
|
|
207
|
+
`,
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
await this.client.gameserver.gameServerControllerInstallModule(this.setupData.gameserver.id, mod.id, {
|
|
211
|
+
userConfig: JSON.stringify({}),
|
|
212
|
+
systemConfig: JSON.stringify({}),
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(HookEvents.COMMAND_EXECUTED, 1);
|
|
216
|
+
|
|
217
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
218
|
+
msg: '/test',
|
|
219
|
+
playerId: this.setupData.players[0].id,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
console.log(JSON.stringify((await events)[0].data.meta.result, null, 2));
|
|
223
|
+
const result = (await events)[0].data.meta.result;
|
|
224
|
+
expect(result.success).to.be.false;
|
|
225
|
+
expect(result.reason).to.include('SyntaxError: Unexpected end of input.');
|
|
226
|
+
},
|
|
227
|
+
}),
|
|
66
228
|
];
|
|
67
229
|
|
|
68
230
|
describe(group, function () {
|
package/src/__tests__/{economyUtils.shop.integration.test.ts → economy/claim.integration.test.ts}
RENAMED
|
@@ -1,123 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { EventsAwaiter, expect, IntegrationTest, IShopSetup, shopSetup } from '@takaro/test';
|
|
2
|
+
import { HookEvents } from '../../dto/index.js';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
EventsAwaiter,
|
|
6
|
-
integrationConfig,
|
|
7
|
-
expect,
|
|
8
|
-
modulesTestSetup,
|
|
9
|
-
IModuleTestsSetupData,
|
|
10
|
-
IntegrationTest,
|
|
11
|
-
} from '@takaro/test';
|
|
12
|
-
import { HookEvents } from '../dto/index.js';
|
|
13
|
-
|
|
14
|
-
const group = 'EconomyUtils:Shop';
|
|
15
|
-
|
|
16
|
-
interface IShopSetup extends IModuleTestsSetupData {
|
|
17
|
-
userClient: Client;
|
|
18
|
-
listing100: ShopListingOutputDTO;
|
|
19
|
-
listing33: ShopListingOutputDTO;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
async function createUserForPlayer(client: Client, playerId: string, gameServerId: string) {
|
|
23
|
-
const password = 'shop-tester-password-very-safe';
|
|
24
|
-
|
|
25
|
-
let user: UserOutputDTO | null = null;
|
|
26
|
-
|
|
27
|
-
user = (
|
|
28
|
-
await client.user.userControllerCreate({
|
|
29
|
-
name: 'test',
|
|
30
|
-
email: `test-${faker.internet.email()}`,
|
|
31
|
-
password,
|
|
32
|
-
})
|
|
33
|
-
).data.data;
|
|
34
|
-
|
|
35
|
-
const userClient = new Client({ auth: { username: user.email, password }, url: integrationConfig.get('host') });
|
|
36
|
-
await userClient.login();
|
|
37
|
-
|
|
38
|
-
const eventsAwaiter = new EventsAwaiter();
|
|
39
|
-
await eventsAwaiter.connect(client);
|
|
40
|
-
const chatEventWaiter = eventsAwaiter.waitForEvents(HookEvents.CHAT_MESSAGE);
|
|
41
|
-
await client.command.commandControllerTrigger(gameServerId, {
|
|
42
|
-
msg: '/link',
|
|
43
|
-
playerId,
|
|
44
|
-
});
|
|
45
|
-
const chatEvents = await chatEventWaiter;
|
|
46
|
-
expect(chatEvents).to.have.length(1);
|
|
47
|
-
const code = chatEvents[0].data.meta.msg.match(/code=(\w+-\w+-\w+)/)[1];
|
|
48
|
-
await userClient.user.userControllerLinkPlayerProfile({ email: user.email, code });
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
user,
|
|
52
|
-
client: userClient,
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async function setupShop(client: Client, gameServerId: string) {
|
|
57
|
-
const items = (await client.item.itemControllerSearch()).data.data;
|
|
58
|
-
|
|
59
|
-
const listing100Res = await client.shopListing.shopListingControllerCreate({
|
|
60
|
-
gameServerId: gameServerId,
|
|
61
|
-
items: [{ itemId: items[0].id, amount: 1 }],
|
|
62
|
-
price: 100,
|
|
63
|
-
name: 'Test item',
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
const listing33Res = await client.shopListing.shopListingControllerCreate({
|
|
67
|
-
gameServerId: gameServerId,
|
|
68
|
-
items: [{ itemId: items[1].id, amount: 1 }],
|
|
69
|
-
price: 33,
|
|
70
|
-
name: 'Test item 2',
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
return {
|
|
74
|
-
listing100: listing100Res.data.data,
|
|
75
|
-
listing33: listing33Res.data.data,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const customSetup = async function (this: IntegrationTest<IShopSetup>): Promise<IShopSetup> {
|
|
80
|
-
const setupData = await modulesTestSetup.bind(this as unknown as IntegrationTest<IModuleTestsSetupData>)();
|
|
81
|
-
|
|
82
|
-
await this.client.settings.settingsControllerSet('economyEnabled', {
|
|
83
|
-
value: 'true',
|
|
84
|
-
gameServerId: setupData.gameserver.id,
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
await this.client.settings.settingsControllerSet('economyEnabled', {
|
|
88
|
-
value: 'true',
|
|
89
|
-
});
|
|
90
|
-
await this.client.settings.settingsControllerSet('currencyName', {
|
|
91
|
-
gameServerId: setupData.gameserver.id,
|
|
92
|
-
value: 'test coin',
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
await this.client.gameserver.gameServerControllerInstallModule(
|
|
96
|
-
setupData.gameserver.id,
|
|
97
|
-
setupData.economyUtilsModule.id,
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
const { client: userClient } = await createUserForPlayer(
|
|
101
|
-
this.client,
|
|
102
|
-
setupData.players[0].id,
|
|
103
|
-
setupData.gameserver.id,
|
|
104
|
-
);
|
|
105
|
-
const { listing100, listing33 } = await setupShop(this.client, setupData.gameserver.id);
|
|
106
|
-
|
|
107
|
-
await this.client.playerOnGameserver.playerOnGameServerControllerAddCurrency(
|
|
108
|
-
setupData.gameserver.id,
|
|
109
|
-
setupData.players[0].id,
|
|
110
|
-
{ currency: 250 },
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
return { ...setupData, userClient, listing100, listing33 };
|
|
114
|
-
};
|
|
4
|
+
const group = 'EconomyUtils:Shop:Claim';
|
|
115
5
|
|
|
116
6
|
const tests = [
|
|
117
7
|
new IntegrationTest<IShopSetup>({
|
|
118
8
|
group,
|
|
119
9
|
snapshot: false,
|
|
120
|
-
setup:
|
|
10
|
+
setup: shopSetup,
|
|
121
11
|
name: 'Can claim an order happy path',
|
|
122
12
|
test: async function () {
|
|
123
13
|
await this.setupData.userClient.shopOrder.shopOrderControllerCreate({
|
|
@@ -137,7 +27,7 @@ const tests = [
|
|
|
137
27
|
new IntegrationTest<IShopSetup>({
|
|
138
28
|
group,
|
|
139
29
|
snapshot: false,
|
|
140
|
-
setup:
|
|
30
|
+
setup: shopSetup,
|
|
141
31
|
name: 'Shows a friendly error when there are no pending orders',
|
|
142
32
|
test: async function () {
|
|
143
33
|
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(HookEvents.CHAT_MESSAGE, 1);
|
|
@@ -153,7 +43,7 @@ const tests = [
|
|
|
153
43
|
new IntegrationTest<IShopSetup>({
|
|
154
44
|
group,
|
|
155
45
|
snapshot: false,
|
|
156
|
-
setup:
|
|
46
|
+
setup: shopSetup,
|
|
157
47
|
name: 'Handles double-claiming an order',
|
|
158
48
|
test: async function () {
|
|
159
49
|
await this.setupData.userClient.shopOrder.shopOrderControllerCreate({
|
|
@@ -182,7 +72,7 @@ const tests = [
|
|
|
182
72
|
new IntegrationTest<IShopSetup>({
|
|
183
73
|
group,
|
|
184
74
|
snapshot: false,
|
|
185
|
-
setup:
|
|
75
|
+
setup: shopSetup,
|
|
186
76
|
name: 'Only claims the first order by default',
|
|
187
77
|
test: async function () {
|
|
188
78
|
await this.setupData.userClient.shopOrder.shopOrderControllerCreate({
|
|
@@ -217,7 +107,7 @@ const tests = [
|
|
|
217
107
|
new IntegrationTest<IShopSetup>({
|
|
218
108
|
group,
|
|
219
109
|
snapshot: false,
|
|
220
|
-
setup:
|
|
110
|
+
setup: shopSetup,
|
|
221
111
|
name: 'Can claim all orders in one go',
|
|
222
112
|
test: async function () {
|
|
223
113
|
await this.setupData.userClient.shopOrder.shopOrderControllerCreate({
|
|
@@ -237,9 +127,9 @@ const tests = [
|
|
|
237
127
|
|
|
238
128
|
expect(await events).to.have.length(4);
|
|
239
129
|
expect((await events)[0].data.meta.msg).to.equal('You have received items from a shop order.');
|
|
240
|
-
expect((await events)[1].data.meta.msg).to.equal('1x
|
|
130
|
+
expect((await events)[1].data.meta.msg).to.equal('1x Stone');
|
|
241
131
|
expect((await events)[2].data.meta.msg).to.equal('You have received items from a shop order.');
|
|
242
|
-
expect((await events)[3].data.meta.msg).to.equal('1x
|
|
132
|
+
expect((await events)[3].data.meta.msg).to.equal('1x Wood');
|
|
243
133
|
},
|
|
244
134
|
}),
|
|
245
135
|
];
|
package/src/__tests__/{economyUtils.integration.test.ts → economy/economyUtils.integration.test.ts}
RENAMED
|
@@ -6,9 +6,9 @@ import {
|
|
|
6
6
|
chatMessageSorter,
|
|
7
7
|
EventsAwaiter,
|
|
8
8
|
} from '@takaro/test';
|
|
9
|
-
import { GameEvents } from '
|
|
9
|
+
import { GameEvents } from '../../dto/index.js';
|
|
10
10
|
|
|
11
|
-
const group = '
|
|
11
|
+
const group = 'EconomyUtils';
|
|
12
12
|
|
|
13
13
|
const customSetup = async function (this: IntegrationTest<IModuleTestsSetupData>): Promise<IModuleTestsSetupData> {
|
|
14
14
|
const setupData = await modulesTestSetup.bind(this)();
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { EventsAwaiter, expect, IntegrationTest, IShopSetup, shopSetup } from '@takaro/test';
|
|
2
|
+
import { HookEvents } from '../../dto/index.js';
|
|
3
|
+
|
|
4
|
+
const group = 'EconomyUtils:Shop:Browse';
|
|
5
|
+
|
|
6
|
+
const tests = [
|
|
7
|
+
new IntegrationTest<IShopSetup>({
|
|
8
|
+
group,
|
|
9
|
+
snapshot: false,
|
|
10
|
+
setup: shopSetup,
|
|
11
|
+
name: 'Calling /shop without arguments displays help information',
|
|
12
|
+
test: async function () {
|
|
13
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(HookEvents.CHAT_MESSAGE, 5);
|
|
14
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
15
|
+
msg: '/shop',
|
|
16
|
+
playerId: this.setupData.players[0].id,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
expect(await events).to.have.length(5);
|
|
20
|
+
expect((await events)[0].data.meta.msg).to.eq(
|
|
21
|
+
'This command allows you to browse the shop and view available items.',
|
|
22
|
+
);
|
|
23
|
+
expect((await events)[1].data.meta.msg).to.eq('Usage: /shop [page] [item] [action]');
|
|
24
|
+
expect((await events)[2].data.meta.msg).to.eq('/shop 2 - View the second page of shop items');
|
|
25
|
+
expect((await events)[3].data.meta.msg).to.eq('/shop 1 3 - View details about the third item on the first page');
|
|
26
|
+
expect((await events)[4].data.meta.msg).to.eq('/shop 1 3 buy - Purchase the third item on the first page');
|
|
27
|
+
},
|
|
28
|
+
}),
|
|
29
|
+
new IntegrationTest<IShopSetup>({
|
|
30
|
+
group,
|
|
31
|
+
snapshot: false,
|
|
32
|
+
setup: shopSetup,
|
|
33
|
+
name: 'First page shows the first 5 items',
|
|
34
|
+
test: async function () {
|
|
35
|
+
await this.setupData.createListings(this.client, { gameServerId: this.setupData.gameserver.id, amount: 5 });
|
|
36
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(HookEvents.CHAT_MESSAGE, 5);
|
|
37
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
38
|
+
msg: '/shop 1',
|
|
39
|
+
playerId: this.setupData.players[0].id,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
console.log(JSON.stringify((await events)[0].data.meta.msg, null, 2));
|
|
43
|
+
expect(await events).to.have.length(5);
|
|
44
|
+
},
|
|
45
|
+
}),
|
|
46
|
+
new IntegrationTest<IShopSetup>({
|
|
47
|
+
group,
|
|
48
|
+
snapshot: false,
|
|
49
|
+
setup: shopSetup,
|
|
50
|
+
name: 'Can view the second page of shop items',
|
|
51
|
+
test: async function () {
|
|
52
|
+
await this.client.gameserver.gameServerControllerInstallModule(
|
|
53
|
+
this.setupData.gameserver.id,
|
|
54
|
+
this.setupData.utilsModule.id,
|
|
55
|
+
);
|
|
56
|
+
await this.setupData.createListings(this.client, { gameServerId: this.setupData.gameserver.id, amount: 5 });
|
|
57
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(HookEvents.CHAT_MESSAGE, 3);
|
|
58
|
+
const commandExecutedEvent = (await new EventsAwaiter().connect(this.client)).waitForEvents(
|
|
59
|
+
HookEvents.COMMAND_EXECUTED,
|
|
60
|
+
1,
|
|
61
|
+
);
|
|
62
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
63
|
+
msg: '/shop 2',
|
|
64
|
+
playerId: this.setupData.players[0].id,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
await commandExecutedEvent;
|
|
68
|
+
|
|
69
|
+
// We trigger the ping command to make sure we can see the FULL output of the previous command
|
|
70
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
71
|
+
msg: '/ping',
|
|
72
|
+
playerId: this.setupData.players[0].id,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
expect(await events).to.have.length(3);
|
|
76
|
+
expect((await events)[(await events).length - 1].data.meta.msg).to.eq('Pong!');
|
|
77
|
+
},
|
|
78
|
+
}),
|
|
79
|
+
new IntegrationTest<IShopSetup>({
|
|
80
|
+
group,
|
|
81
|
+
snapshot: false,
|
|
82
|
+
setup: shopSetup,
|
|
83
|
+
name: 'When no items are available, shows a message',
|
|
84
|
+
test: async function () {
|
|
85
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(HookEvents.CHAT_MESSAGE, 1);
|
|
86
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
87
|
+
msg: '/shop 5',
|
|
88
|
+
playerId: this.setupData.players[0].id,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
expect(await events).to.have.length(1);
|
|
92
|
+
expect((await events)[0].data.meta.msg).to.equal('No items found.');
|
|
93
|
+
},
|
|
94
|
+
}),
|
|
95
|
+
new IntegrationTest<IShopSetup>({
|
|
96
|
+
group,
|
|
97
|
+
snapshot: false,
|
|
98
|
+
setup: shopSetup,
|
|
99
|
+
name: 'Can show details about an item',
|
|
100
|
+
test: async function () {
|
|
101
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(HookEvents.CHAT_MESSAGE, 2);
|
|
102
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
103
|
+
msg: '/shop 1 1',
|
|
104
|
+
playerId: this.setupData.players[0].id,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
expect(await events).to.have.length(2);
|
|
108
|
+
expect((await events)[0].data.meta.msg).to.equal('Listing Test item - 100 test coin');
|
|
109
|
+
expect((await events)[1].data.meta.msg).to.equal('- 1x Stone. Description: Stone can get you stoned');
|
|
110
|
+
},
|
|
111
|
+
}),
|
|
112
|
+
new IntegrationTest<IShopSetup>({
|
|
113
|
+
group,
|
|
114
|
+
snapshot: false,
|
|
115
|
+
setup: shopSetup,
|
|
116
|
+
name: 'Shows an error when requesting details for an invalid item',
|
|
117
|
+
test: async function () {
|
|
118
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(HookEvents.CHAT_MESSAGE, 1);
|
|
119
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
120
|
+
msg: '/shop 1 5',
|
|
121
|
+
playerId: this.setupData.players[0].id,
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
expect(await events).to.have.length(1);
|
|
125
|
+
expect((await events)[0].data.meta.msg).to.equal(
|
|
126
|
+
'Item not found. Please select an item from the list, valid options are 1-2.',
|
|
127
|
+
);
|
|
128
|
+
},
|
|
129
|
+
}),
|
|
130
|
+
new IntegrationTest<IShopSetup>({
|
|
131
|
+
group,
|
|
132
|
+
snapshot: false,
|
|
133
|
+
setup: shopSetup,
|
|
134
|
+
name: 'Can buy an item',
|
|
135
|
+
test: async function () {
|
|
136
|
+
const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(HookEvents.CHAT_MESSAGE, 2);
|
|
137
|
+
await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
|
|
138
|
+
msg: '/shop 1 1 buy',
|
|
139
|
+
playerId: this.setupData.players[0].id,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
expect(await events).to.have.length(2);
|
|
143
|
+
expect((await events)[0].data.meta.msg).to.equal('You have purchased Test item for 100 test coin.');
|
|
144
|
+
expect((await events)[1].data.meta.msg).to.equal('You have received items from a shop order.');
|
|
145
|
+
},
|
|
146
|
+
}),
|
|
147
|
+
];
|
|
148
|
+
|
|
149
|
+
describe(group, function () {
|
|
150
|
+
tests.forEach((test) => {
|
|
151
|
+
test.run();
|
|
152
|
+
});
|
|
153
|
+
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { IntegrationTest, expect, IModuleTestsSetupData, modulesTestSetup, EventsAwaiter } from '@takaro/test';
|
|
2
2
|
import { GameEvents } from '../dto/index.js';
|
|
3
|
-
import { sleep } from '@takaro/util';
|
|
4
3
|
|
|
5
4
|
const group = 'Server messages';
|
|
6
5
|
|
|
@@ -77,24 +76,39 @@ const tests = [
|
|
|
77
76
|
|
|
78
77
|
// We should see each of our test messages at least once
|
|
79
78
|
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
79
|
+
const firstEvents = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 1);
|
|
80
|
+
|
|
81
|
+
await this.client.cronjob.cronJobControllerTrigger({
|
|
82
|
+
cronjobId: this.setupData.serverMessagesModule.cronJobs[0].id,
|
|
83
|
+
gameServerId: this.setupData.gameserver.id,
|
|
84
|
+
moduleId: this.setupData.serverMessagesModule.id,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
expect((await firstEvents).length).to.be.eq(1);
|
|
88
|
+
expect((await firstEvents)[0].data.meta.msg).to.be.eq('Test message 1');
|
|
89
|
+
|
|
90
|
+
const secondEvents = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 1);
|
|
91
|
+
|
|
92
|
+
await this.client.cronjob.cronJobControllerTrigger({
|
|
93
|
+
cronjobId: this.setupData.serverMessagesModule.cronJobs[0].id,
|
|
94
|
+
gameServerId: this.setupData.gameserver.id,
|
|
95
|
+
moduleId: this.setupData.serverMessagesModule.id,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
expect((await secondEvents).length).to.be.eq(1);
|
|
99
|
+
expect((await secondEvents)[0].data.meta.msg).to.be.eq('Test message 2');
|
|
100
|
+
|
|
101
|
+
// After this, it should loop back to the first message
|
|
102
|
+
const thirdEvents = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 1);
|
|
103
|
+
|
|
104
|
+
await this.client.cronjob.cronJobControllerTrigger({
|
|
105
|
+
cronjobId: this.setupData.serverMessagesModule.cronJobs[0].id,
|
|
106
|
+
gameServerId: this.setupData.gameserver.id,
|
|
107
|
+
moduleId: this.setupData.serverMessagesModule.id,
|
|
108
|
+
});
|
|
85
109
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
await this.client.cronjob.cronJobControllerTrigger({
|
|
89
|
-
cronjobId: this.setupData.serverMessagesModule.cronJobs[0].id,
|
|
90
|
-
gameServerId: this.setupData.gameserver.id,
|
|
91
|
-
moduleId: this.setupData.serverMessagesModule.id,
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const messages = (await events).map((e) => e.data.meta.msg);
|
|
96
|
-
expect(messages).to.include('Test message 1');
|
|
97
|
-
expect(messages).to.include('Test message 2');
|
|
110
|
+
expect((await thirdEvents).length).to.be.eq(1);
|
|
111
|
+
expect((await thirdEvents)[0].data.meta.msg).to.be.eq('Test message 1');
|
|
98
112
|
},
|
|
99
113
|
}),
|
|
100
114
|
];
|
package/src/dto/takaroEvents.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
IsBoolean,
|
|
3
|
-
IsDefined,
|
|
4
3
|
IsEnum,
|
|
5
4
|
IsIP,
|
|
6
5
|
IsISO31661Alpha2,
|
|
@@ -141,9 +140,6 @@ export class TakaroEventCommandExecuted extends BaseEvent<TakaroEventCommandExec
|
|
|
141
140
|
@IsString()
|
|
142
141
|
type = TakaroEvents.COMMAND_EXECUTED;
|
|
143
142
|
|
|
144
|
-
@IsDefined()
|
|
145
|
-
data: Record<string, unknown>;
|
|
146
|
-
|
|
147
143
|
@ValidateNested()
|
|
148
144
|
@Type(() => TakaroEventFunctionResult)
|
|
149
145
|
result: TakaroEventFunctionResult;
|
|
@@ -158,9 +154,6 @@ export class TakaroEventHookExecuted extends BaseEvent<TakaroEventHookExecuted>
|
|
|
158
154
|
@IsString()
|
|
159
155
|
type = TakaroEvents.HOOK_EXECUTED;
|
|
160
156
|
|
|
161
|
-
@IsDefined()
|
|
162
|
-
data: Record<string, unknown>;
|
|
163
|
-
|
|
164
157
|
@ValidateNested()
|
|
165
158
|
@Type(() => TakaroEventFunctionResult)
|
|
166
159
|
result: TakaroEventFunctionResult;
|
|
@@ -175,9 +168,6 @@ export class TakaroEventCronjobExecuted extends BaseEvent<TakaroEventCronjobExec
|
|
|
175
168
|
@IsString()
|
|
176
169
|
type = TakaroEvents.CRONJOB_EXECUTED;
|
|
177
170
|
|
|
178
|
-
@IsDefined()
|
|
179
|
-
data: Record<string, unknown>;
|
|
180
|
-
|
|
181
171
|
@ValidateNested()
|
|
182
172
|
@Type(() => TakaroEventFunctionResult)
|
|
183
173
|
result: TakaroEventFunctionResult;
|
package/src/main.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { Lottery } from './modules/lottery/index.js';
|
|
|
8
8
|
import { PlayerOnboarding } from './modules/playerOnboarding/index.js';
|
|
9
9
|
import { ServerMessages } from './modules/serverMessages/index.js';
|
|
10
10
|
import { Teleports } from './modules/teleports/index.js';
|
|
11
|
+
import { TimedShutdown } from './modules/timedShutdown/index.js';
|
|
11
12
|
import { Utils } from './modules/utils/index.js';
|
|
12
13
|
|
|
13
14
|
export { BuiltinModule, ICommand, ICommandArgument, ICronJob, IHook, IFunction } from './BuiltinModule.js';
|
|
@@ -28,6 +29,7 @@ export function getModules(): Array<BuiltinModule<unknown>> {
|
|
|
28
29
|
new EconomyUtils(),
|
|
29
30
|
new Lottery(),
|
|
30
31
|
new GeoBlock(),
|
|
32
|
+
new TimedShutdown(),
|
|
31
33
|
];
|
|
32
34
|
}
|
|
33
35
|
|