@@ -9,39 +9,136 @@ import R2Error from '../../../../../../src/model/errors/R2Error';
99import Profile from '../../../../../../src/model/Profile' ;
1010import ProfileInstallerProvider from '../../../../../../src/providers/ror2/installing/ProfileInstallerProvider' ;
1111import GenericProfileInstaller from '../../../../../../src/r2mm/installing/profile_installers/GenericProfileInstaller' ;
12+ import InstallationRules , { RuleSubtype } from '../../../../../../src/r2mm/installing/InstallationRules' ;
13+ import { TrackingMethod } from '../../../../../../src/model/schema/ThunderstoreSchema' ;
1214import { describe , beforeEach , test , expect } from 'vitest' ;
1315
16+ function getShimloaderRules ( includePakExtension : boolean ) : RuleSubtype [ ] {
17+ return [
18+ {
19+ route : 'shimloader/mod' ,
20+ isDefaultLocation : true ,
21+ defaultFileExtensions : [ ] ,
22+ trackingMethod : TrackingMethod . SUBDIR ,
23+ subRoutes : [ ] ,
24+ } ,
25+ {
26+ route : 'shimloader/pak' ,
27+ defaultFileExtensions : includePakExtension ? [ 'pak' ] : [ ] ,
28+ trackingMethod : TrackingMethod . SUBDIR ,
29+ subRoutes : [ ] ,
30+ } ,
31+ {
32+ route : 'shimloader/cfg' ,
33+ defaultFileExtensions : [ ] ,
34+ trackingMethod : TrackingMethod . NONE ,
35+ subRoutes : [ ] ,
36+ } ,
37+ ] ;
38+ }
39+
40+ function setPalworldInstallRules ( rules : RuleSubtype [ ] ) {
41+ const existingRules = InstallationRules . RULES ;
42+ const palworldIdx = existingRules . findIndex ( ( rule ) => rule . gameName === 'Palworld' ) ;
43+
44+ if ( palworldIdx === - 1 ) {
45+ throw new Error ( 'Palworld install rules not found' ) ;
46+ }
47+
48+ existingRules [ palworldIdx ] = {
49+ ...existingRules [ palworldIdx ] ,
50+ rules,
51+ } ;
52+ InstallationRules . RULES = existingRules ;
53+ }
54+
1455describe ( 'Shimloader Installer Tests' , ( ) => {
56+ describe ( 'Schema-defined installRules' , ( ) => {
57+
58+ beforeEach ( async ( ) => {
59+ await installLogicBeforeEach ( 'Palworld' ) ;
60+ setPalworldInstallRules ( getShimloaderRules ( false ) ) ;
61+ } ) ;
62+
63+ test ( 'Installs and uninstalls a package' , async ( ) => {
64+ const pkg = createManifest ( "test_mod" , "auth" ) ;
65+ const name = pkg . getName ( ) ;
66+ const sourceToExpectedDestination = {
67+ "README.md" : `shimloader/mod/${ name } /README.md` ,
68+ "manifest.json" : `shimloader/mod/${ name } /manifest.json` ,
69+ "icon.png" : `shimloader/mod/${ name } /icon.png` ,
70+ "pak/blueprint.pak" : `shimloader/pak/${ name } /blueprint.pak` ,
71+ "mod/scripts/main.lua" : `shimloader/mod/${ name } /scripts/main.lua` ,
72+ "mod/scripts/other.lua" : `shimloader/mod/${ name } /scripts/other.lua` ,
73+ "mod/dll/mod.dll" : `shimloader/mod/${ name } /dll/mod.dll` ,
74+ "cfg/package.cfg" : `shimloader/cfg/package.cfg` ,
75+ } ;
76+ const expectedAfterUninstall = [
77+ "shimloader/cfg/package.cfg" ,
78+ ] ;
79+ await createPackageFilesIntoCache ( pkg , Object . keys ( sourceToExpectedDestination ) ) ;
80+
81+ ProfileInstallerProvider . provide ( ( ) => new GenericProfileInstaller ( ) ) ;
82+ await ProfileInstallerProvider . instance . installMod ( pkg , Profile . getActiveProfile ( ) . asImmutableProfile ( ) ) ;
83+ await expectFilesToBeCopied ( sourceToExpectedDestination ) ;
84+
85+ const result = await ProfileInstallerProvider . instance . uninstallMod ( pkg , Profile . getActiveProfile ( ) . asImmutableProfile ( ) ) ;
86+ expect ( result instanceof R2Error ) . toBeFalsy ( ) ;
87+ await expectFilesToBeRemoved ( sourceToExpectedDestination , expectedAfterUninstall ) ;
88+ } ) ;
89+
90+ test ( 'Loose .pak files route to schema default location when no extension rule exists' , async ( ) => {
91+ const pkg = createManifest ( "pak_mod" , "auth" ) ;
92+ const name = pkg . getName ( ) ;
93+ const sourceToExpectedDestination = {
94+ "manifest.json" : `shimloader/mod/${ name } /manifest.json` ,
95+ "icon.png" : `shimloader/mod/${ name } /icon.png` ,
96+ "loose_mod.pak" : `shimloader/mod/${ name } /loose_mod.pak` ,
97+ } ;
98+ await createPackageFilesIntoCache ( pkg , Object . keys ( sourceToExpectedDestination ) ) ;
99+
100+ ProfileInstallerProvider . provide ( ( ) => new GenericProfileInstaller ( ) ) ;
101+ await ProfileInstallerProvider . instance . installMod ( pkg , Profile . getActiveProfile ( ) . asImmutableProfile ( ) ) ;
102+ await expectFilesToBeCopied ( sourceToExpectedDestination ) ;
103+ } ) ;
104+ } ) ;
105+
106+ describe ( 'Schema-defined installRules with pak extension rule' , ( ) => {
107+
108+ beforeEach ( async ( ) => {
109+ await installLogicBeforeEach ( 'Palworld' ) ;
110+ setPalworldInstallRules ( getShimloaderRules ( true ) ) ;
111+ } ) ;
112+
113+ test ( 'Loose .pak files route to shimloader/pak when schema defines .pak extension' , async ( ) => {
114+ const pkg = createManifest ( "pak_mod" , "auth" ) ;
115+ const name = pkg . getName ( ) ;
116+ const sourceToExpectedDestination = {
117+ "manifest.json" : `shimloader/mod/${ name } /manifest.json` ,
118+ "icon.png" : `shimloader/mod/${ name } /icon.png` ,
119+ "loose_mod.pak" : `shimloader/pak/${ name } /loose_mod.pak` ,
120+ } ;
121+ await createPackageFilesIntoCache ( pkg , Object . keys ( sourceToExpectedDestination ) ) ;
122+
123+ ProfileInstallerProvider . provide ( ( ) => new GenericProfileInstaller ( ) ) ;
124+ await ProfileInstallerProvider . instance . installMod ( pkg , Profile . getActiveProfile ( ) . asImmutableProfile ( ) ) ;
125+ await expectFilesToBeCopied ( sourceToExpectedDestination ) ;
126+ } ) ;
127+
128+ test ( 'Subdirectory pak files still route to shimloader/pak' , async ( ) => {
129+ const pkg = createManifest ( "pak_subdir_mod" , "auth" ) ;
130+ const name = pkg . getName ( ) ;
131+ const sourceToExpectedDestination = {
132+ "manifest.json" : `shimloader/mod/${ name } /manifest.json` ,
133+ "pak/blueprint.pak" : `shimloader/pak/${ name } /blueprint.pak` ,
134+ "mod/scripts/main.lua" : `shimloader/mod/${ name } /scripts/main.lua` ,
135+ "cfg/package.cfg" : `shimloader/cfg/package.cfg` ,
136+ } ;
137+ await createPackageFilesIntoCache ( pkg , Object . keys ( sourceToExpectedDestination ) ) ;
15138
16- beforeEach ( ( ) => {
17- installLogicBeforeEach ( 'Palworld' ) ;
18- }
19- ) ;
20-
21- test ( 'Installs and uninstalls a package' , async ( ) => {
22- const pkg = createManifest ( "test_mod" , "auth" ) ;
23- const name = pkg . getName ( ) ;
24- const sourceToExpectedDestination = {
25- "README.md" : `shimloader/mod/${ name } /README.md` ,
26- "manifest.json" : `shimloader/mod/${ name } /manifest.json` ,
27- "icon.png" : `shimloader/mod/${ name } /icon.png` ,
28- "pak/blueprint.pak" : `shimloader/pak/${ name } /blueprint.pak` ,
29- "mod/scripts/main.lua" : `shimloader/mod/${ name } /scripts/main.lua` ,
30- "mod/scripts/other.lua" : `shimloader/mod/${ name } /scripts/other.lua` ,
31- "mod/dll/mod.dll" : `shimloader/mod/${ name } /dll/mod.dll` ,
32- "cfg/package.cfg" : `shimloader/cfg/package.cfg` ,
33- } ;
34- const expectedAfterUninstall = [
35- "shimloader/cfg/package.cfg" ,
36- ] ;
37- await createPackageFilesIntoCache ( pkg , Object . keys ( sourceToExpectedDestination ) ) ;
38-
39- ProfileInstallerProvider . provide ( ( ) => new GenericProfileInstaller ( ) ) ;
40- await ProfileInstallerProvider . instance . installMod ( pkg , Profile . getActiveProfile ( ) . asImmutableProfile ( ) ) ;
41- await expectFilesToBeCopied ( sourceToExpectedDestination ) ;
42-
43- const result = await ProfileInstallerProvider . instance . uninstallMod ( pkg , Profile . getActiveProfile ( ) . asImmutableProfile ( ) ) ;
44- expect ( result instanceof R2Error ) . toBeFalsy ( ) ;
45- expectFilesToBeRemoved ( sourceToExpectedDestination , expectedAfterUninstall )
139+ ProfileInstallerProvider . provide ( ( ) => new GenericProfileInstaller ( ) ) ;
140+ await ProfileInstallerProvider . instance . installMod ( pkg , Profile . getActiveProfile ( ) . asImmutableProfile ( ) ) ;
141+ await expectFilesToBeCopied ( sourceToExpectedDestination ) ;
142+ } ) ;
46143 } ) ;
47144} ) ;
0 commit comments