From f4d584c27a886f29e4d2da088f8529dbd0eb7130 Mon Sep 17 00:00:00 2001 From: Campiotti Date: Mon, 8 May 2023 20:15:20 +0200 Subject: [PATCH 1/3] chore: add a test file for services: enb, instruction & modpack + 4 stub files --- .../unit/services/enb.service.test.ts | 136 +++++++++++ .../unit/services/instruction.service.test.ts | 225 ++++++++++++++++++ .../unit/services/launcher.service.test.ts | 1 + .../unit/services/modpack.service.test.ts | 81 +++++++ .../unit/services/resolution.service.test.ts | 1 + .../unit/services/update.service.test.ts | 1 + .../unit/services/window.service.test.ts | 1 + 7 files changed, 446 insertions(+) create mode 100644 src/__tests__/unit/services/enb.service.test.ts create mode 100644 src/__tests__/unit/services/instruction.service.test.ts create mode 100644 src/__tests__/unit/services/launcher.service.test.ts create mode 100644 src/__tests__/unit/services/modpack.service.test.ts create mode 100644 src/__tests__/unit/services/resolution.service.test.ts create mode 100644 src/__tests__/unit/services/update.service.test.ts create mode 100644 src/__tests__/unit/services/window.service.test.ts diff --git a/src/__tests__/unit/services/enb.service.test.ts b/src/__tests__/unit/services/enb.service.test.ts new file mode 100644 index 00000000..d17bb0fb --- /dev/null +++ b/src/__tests__/unit/services/enb.service.test.ts @@ -0,0 +1,136 @@ +import mockFs from "mock-fs"; +import { + createStubInstance, + expect, + StubbedInstanceWithSinonAccessor, +} from "@loopback/testlab"; +import { EnbService } from "@/main/services/enb.service"; +import { ConfigService, userPreferences } from "@/main/services/config.service"; +import { USER_PREFERENCE_KEYS } from "@/shared/enums/userPreferenceKeys"; +import { InstructionService } from "@/main/services/instruction.service"; +import fs from "fs"; +import { AdditionalInstructions } from "@/additional-instructions"; +import { DirectoryItems } from "mock-fs/lib/filesystem"; + +describe("ENB Service", () => { + let enbService: EnbService; + let configService: StubbedInstanceWithSinonAccessor; + let instructionService: StubbedInstanceWithSinonAccessor; + const modDir = "/mock/mods"; + const enbPresetDir = `${modDir}/launcher/ENB Presets`; + const baseFS = { + [`${modDir}/Stock Game`]: { "exampleB.json": "[]" }, + [`${modDir}/launcher`]: { + "namesENB.json": JSON.stringify([{ real: "A", friendly: "Letter A" }]), + }, + [`${enbPresetDir}/A`]: { "example.json": "{}" }, + [`${enbPresetDir}/B`]: { "exampleB.json": "{}" }, + } as DirectoryItems; + beforeEach(() => { + configService = createStubInstance(ConfigService); + instructionService = createStubInstance(InstructionService); + enbService = new EnbService(configService, instructionService); + mockFs(baseFS); + }); + + afterEach(() => { + mockFs.restore(); + }); + + it("should override unmapped with mapped ENB presets", async () => { + // setting the userPref in beforeEach doesn't work for some reason -> undefined + userPreferences.set(USER_PREFERENCE_KEYS.MOD_DIRECTORY, modDir); + expect(await enbService.getENBPresets()).to.eql([ + { + friendly: "Letter A", + real: "A", + }, + { + friendly: "B", + real: "B", + }, + { + friendly: "No Shaders", + real: "noEnb", + }, + ]); + }); + + it("should backup the entire ENB presets directory", async () => { + userPreferences.set(USER_PREFERENCE_KEYS.MOD_DIRECTORY, modDir); + const enbBackupDir = `${modDir}/launcher/_backups`; + configService.stubs.backupDirectory.returns(enbBackupDir); + const orig = fs.readdirSync(enbPresetDir); + + await enbService.backupOriginalENBs(); + const backup = fs.readdirSync(`${enbBackupDir}/ENB Presets`); + expect(orig).eql(backup); + }); + + it("should reset to the correct ENB preset", async () => { + const instructions = [ + { + action: "disable-plugin", + type: "enb", + target: ["21:9"], + plugin: "example.esp", + }, + { + action: "disable-ultra-widescreen", + type: "resolution-ratio", + }, + ] as AdditionalInstructions; + userPreferences.set(USER_PREFERENCE_KEYS.MOD_DIRECTORY, modDir); + userPreferences.set(USER_PREFERENCE_KEYS.ENB_PROFILE, "A"); + userPreferences.set(USER_PREFERENCE_KEYS.PREVIOUS_ENB_PROFILE, "B"); + configService.stubs.getPreference.returns("A"); + configService.stubs.skyrimDirectory.returns(`${modDir}/Stock Game`); + instructionService.stubs.getInstructions.returns(instructions); + instructionService.stubs.execute.resolves(true); + await enbService.resetCurrentEnb(true); + expect( + instructionService.stubs.execute.calledOnceWithExactly([instructions[0]]) + ); + expect( + configService.stubs.setPreference.calledWithExactly( + USER_PREFERENCE_KEYS.PREVIOUS_ENB_PROFILE, + "A" + ) + ).true(); + expect( + configService.stubs.setPreference.calledWithExactly( + USER_PREFERENCE_KEYS.ENB_PROFILE, + "A" + ) + ).true(); + }); + it("should restore ENB presets and overwrite existing ones", async () => { + const enbBackupDir = `${modDir}/launcher/_backups`; + mockFs({ + ...baseFS, + [`${enbBackupDir}/ENB Presets/Z`]: { "Z.json": "{}" }, + [`${enbBackupDir}/ENB Presets/A`]: { + "example.json": JSON.stringify({ different: true }), + }, + }); + userPreferences.set(USER_PREFERENCE_KEYS.MOD_DIRECTORY, modDir); + userPreferences.set(USER_PREFERENCE_KEYS.ENB_PROFILE, "A"); + configService.stubs.backupDirectory.returns(enbBackupDir); + configService.stubs.skyrimDirectory.returns(`${modDir}/Stock Game`); + // right now Z should not exist within the current presets + expect(fs.readdirSync(enbPresetDir).includes("Z")).false(); + const backup = fs.readdirSync(`${enbBackupDir}/ENB Presets`); + // verify A/example.json is overwritten + const presetAPrior = fs + .readFileSync(`${enbPresetDir}/A/example.json`) + .toJSON(); + await enbService.restoreENBPresets(); + const presetACurrent = fs + .readFileSync(`${enbPresetDir}/A/example.json`) + .toJSON(); + expect(presetAPrior).not.eql(presetACurrent); + // current Presets should now contain the previously missing Z + const current = fs.readdirSync(enbPresetDir); + expect(backup.every((value) => current.includes(value))).true(); + }); +}); diff --git a/src/__tests__/unit/services/instruction.service.test.ts b/src/__tests__/unit/services/instruction.service.test.ts new file mode 100644 index 00000000..2112fee8 --- /dev/null +++ b/src/__tests__/unit/services/instruction.service.test.ts @@ -0,0 +1,225 @@ +import mockFs from "mock-fs"; +import { InstructionService } from "@/main/services/instruction.service"; +import { AdditionalInstruction } from "@/additional-instructions"; +import { ConfigService } from "@/main/services/config.service"; +import { ProfileService } from "@/main/services/profile.service"; +import { WabbajackService } from "@/main/services/wabbajack.service"; +import modpackAdditionalInstructions from "@/additional-instructions.json"; +import { + expect, + StubbedInstanceWithSinonAccessor, + createStubInstance, +} from "@loopback/testlab"; +import * as os from "os"; +import fs from "fs"; + +describe("Instruction service", () => { + let instructionService: InstructionService; + let configService: StubbedInstanceWithSinonAccessor; + let wabbajackService: StubbedInstanceWithSinonAccessor; + let profileService: StubbedInstanceWithSinonAccessor; + + beforeEach(() => { + configService = createStubInstance(ConfigService); + wabbajackService = createStubInstance(WabbajackService); + profileService = createStubInstance(ProfileService); + instructionService = new InstructionService( + configService, + profileService, + wabbajackService + ); + }); + + afterEach(() => { + mockFs.restore(); + }); + + it("should match json imported instructions", () => { + // not mocked because mock-require doesn't seem to work here for some reason + expect(instructionService.getInstructions()).to.eql( + modpackAdditionalInstructions + ); + }); + + it("should ignore or compute instruction based on modpack version", async () => { + wabbajackService.stubs.getModpackVersion.resolves("1.1.0"); + const instruction = { + action: "disable-ultra-widescreen", + version: "1.0.0", + } as AdditionalInstruction; + // instruction is skipped if version mismatch -> undefined + expect(await instructionService.execute([instruction])).undefined(); + + // however having the same modpack version will result in a different result + wabbajackService.stubs.getModpackVersion.resolves("1.0.0"); + expect(await instructionService.execute([instruction])).not.undefined(); + }); + + describe("modlist.txt", () => { + const mockProfilesDir = "/mock/profiles"; + const mockModlistArr = ["+Mod1E", "-Mod2D", "+Mod3E", "-Mod4D"]; + const mockModlistStr = mockModlistArr.join(os.EOL); + const mockModlistFile = `${mockProfilesDir}/profileA/modlist.txt`; + beforeEach(async () => { + // this is a heavily simplified version of the FS compared to the real thing + // it does not represent how it actually looks whatsoever, only facilitates this test + mockFs({ + [mockModlistFile]: mockModlistStr, + }); + profileService.stubs.getPhysicalProfiles.resolves( + await fs.promises.readdir(mockProfilesDir, { withFileTypes: true }) + ); + profileService.stubs.profileDirectory.returns(mockProfilesDir); + }); + + it("Should not change anything if instruction matches state", async () => { + const instructionEnabledAlready = { + action: "enable-mod", + type: "resolution-ratio", + target: "21:9", + mod: "Mod1E", + } as AdditionalInstruction; + await instructionService.execute([instructionEnabledAlready], "21:9"); + const currentModlistContent = fs.readFileSync(mockModlistFile).toString(); + expect(currentModlistContent).to.eql(mockModlistStr); + }); + it("Should enable disabled mod", async () => { + const instructionEnableDisabled = { + action: "enable-mod", + type: "resolution-ratio", + target: "21:9", + mod: "Mod2D", + } as AdditionalInstruction; + await instructionService.execute([instructionEnableDisabled], "21:9"); + const currentModlistContent = fs.readFileSync(mockModlistFile).toString(); + expect(currentModlistContent.includes("+Mod2D")).true(); + }); + it("Should disable enabled mod", async () => { + const instructionDisableEnabled = { + action: "disable-mod", + type: "resolution-ratio", + target: "21:9", + mod: "Mod3E", + } as AdditionalInstruction; + await instructionService.execute([instructionDisableEnabled], "21:9"); + const currentModlistContent = fs.readFileSync(mockModlistFile).toString(); + expect(currentModlistContent.includes("-Mod3E")).true(); + }); + it("Should disable on enable instruction if target mismatch", async () => { + const instructionInverseEnableTargetMismatch = { + action: "enable-mod", + type: "resolution-ratio", + target: "not matching", + mod: "Mod1E", + } as AdditionalInstruction; + await instructionService.execute( + [instructionInverseEnableTargetMismatch], + "21:9" + ); + const currentModlistContent = fs.readFileSync(mockModlistFile).toString(); + expect(currentModlistContent.includes("-Mod1E")).true(); + }); + it("should enable on disable instruction if target mismatch", async () => { + const instructionInverseDisableTargetMismatch = { + action: "disable-mod", + type: "resolution-ratio", + target: "missing target in call", + mod: "Mod1E", + } as AdditionalInstruction; + await instructionService.execute([ + instructionInverseDisableTargetMismatch, + ]); + const currentModlistContent = fs.readFileSync(mockModlistFile).toString(); + expect(currentModlistContent.includes("+Mod1E")).true(); + }); + }); + + describe("plugins.txt", () => { + const mockProfilesDir = "/mock/profiles"; + const mockPluginList = [ + "*Plugin1E.esp", + "Plugin2D.esp", + "*Plugin3E.esp", + "Plugin4D.esp", + ]; + const mockPlugins = mockPluginList.join(os.EOL); + const mockPluginsFile = `${mockProfilesDir}/profileA/plugins.txt`; + beforeEach(async () => { + mockFs({ + [mockPluginsFile]: mockPlugins, + }); + profileService.stubs.getPhysicalProfiles.resolves( + await fs.promises.readdir(mockProfilesDir, { withFileTypes: true }) + ); + profileService.stubs.profileDirectory.returns(mockProfilesDir); + }); + it("should not change anything if instruction matches state", async () => { + const instructionEnabledAlready = { + action: "enable-plugin", + type: "resolution-ratio", + target: ["21:9", "32:9"], + plugin: "Plugin1E.esp", + } as AdditionalInstruction; + await instructionService.execute([instructionEnabledAlready], "21:9"); + const currentPluginsContent = fs.readFileSync(mockPluginsFile).toString(); + expect(currentPluginsContent).to.eql(mockPlugins); + }); + it("should enable disabled", async () => { + const instructionEnableDisabled = { + action: "enable-plugin", + type: "resolution-ratio", + target: ["21:9", "32:9"], + plugin: "Plugin2D.esp", + } as AdditionalInstruction; + await instructionService.execute([instructionEnableDisabled], "21:9"); + const currentPluginsContent = fs.readFileSync(mockPluginsFile).toString(); + expect( + currentPluginsContent.split(os.EOL).includes("*Plugin2D.esp") + ).true(); + }); + it("should disable enabled", async () => { + const instructionDisableEnabled = { + action: "disable-plugin", + type: "enb", + target: "21:9", + plugin: "Plugin3E.esp", + } as AdditionalInstruction; + await instructionService.execute([instructionDisableEnabled], "21:9"); + const currentPluginsContent = fs.readFileSync(mockPluginsFile).toString(); + expect( + currentPluginsContent.split(os.EOL).includes("Plugin3E.esp") + ).true(); + }); + it("should disable on enable instruction if target mismatch", async () => { + const instructionInverseEnableTargetMismatch = { + action: "enable-plugin", + type: "resolution-ratio", + target: ["21:9", "32:9"], + plugin: "Plugin1E.esp", + } as AdditionalInstruction; + await instructionService.execute( + [instructionInverseEnableTargetMismatch], + "enb" + ); + const currentPluginsContent = fs.readFileSync(mockPluginsFile).toString(); + expect( + currentPluginsContent.split(os.EOL).includes("Plugin1E.esp") + ).true(); + }); + it("should enable on disable instruction if target mismatch", async () => { + const instructionInverseDisableTargetMismatch = { + action: "disable-plugin", + type: "enb", + target: "noEnb", + plugin: "Plugin1E.esp", + } as AdditionalInstruction; + await instructionService.execute([ + instructionInverseDisableTargetMismatch, + ]); + const currentPluginsContent = fs.readFileSync(mockPluginsFile).toString(); + expect( + currentPluginsContent.split(os.EOL).includes("*Plugin1E.esp") + ).true(); + }); + }); +}); diff --git a/src/__tests__/unit/services/launcher.service.test.ts b/src/__tests__/unit/services/launcher.service.test.ts new file mode 100644 index 00000000..70b786d1 --- /dev/null +++ b/src/__tests__/unit/services/launcher.service.test.ts @@ -0,0 +1 @@ +// TODO diff --git a/src/__tests__/unit/services/modpack.service.test.ts b/src/__tests__/unit/services/modpack.service.test.ts new file mode 100644 index 00000000..911be082 --- /dev/null +++ b/src/__tests__/unit/services/modpack.service.test.ts @@ -0,0 +1,81 @@ +import mockFs from "mock-fs"; +import { + createStubInstance, + expect, + StubbedInstanceWithSinonAccessor, +} from "@loopback/testlab"; +import { ConfigService, UserPreferences } from "@/main/services/config.service"; +import { DirectoryItems } from "mock-fs/lib/filesystem"; +import { ModpackService } from "@/main/services/modpack.service"; +import { MO2Names } from "@/main/services/modOrganizer.service"; +import modpack from "@/modpack.json"; +import Store from "electron-store"; +import { USER_PREFERENCE_KEYS } from "@/shared/enums/userPreferenceKeys"; + +describe("Modpack Service", () => { + let modpackService: ModpackService; + let configService: StubbedInstanceWithSinonAccessor; + const mockUserConfig = "/mock/config"; + const modDir = "/mock/mods"; + const enbPresetDir = `${modDir}/launcher/ENB Presets`; + const baseFS = { + [mockUserConfig]: { "userPreferences.json": "{}" }, + [`${modDir}/Stock Game`]: { "exampleB.json": "[]" }, + [`${modDir}/launcher`]: { + "namesENB.json": JSON.stringify([{ real: "A", friendly: "Letter A" }]), + }, + [`${modDir}/${MO2Names.MO2EXE}`]: "binary exe data", + [`${modDir}/profiles`]: { "example.json": "{}" }, + [`${enbPresetDir}/A`]: { "example.json": "{}" }, + [`${enbPresetDir}/B`]: { "exampleB.json": "{}" }, + } as DirectoryItems; + beforeEach(() => { + configService = createStubInstance(ConfigService); + modpackService = new ModpackService(configService); + mockFs(baseFS); + }); + + afterEach(() => { + mockFs.restore(); + }); + + it("Should verify that modpack path is valid", () => { + const res = modpackService.checkModpackPathIsValid(modDir); + expect(res.ok).to.be.true(); + expect(res.missingPaths).to.eql([]); + }); + + it("Should verify current modpack path is valid & config is set", () => { + const mockStore = new Store({ + name: "userPreferences", + cwd: mockUserConfig, + }); + mockStore.set(USER_PREFERENCE_KEYS.MOD_DIRECTORY, modDir); + configService.stubs.getPreferences.returns(mockStore); + configService.stubs.getPreference.returns(modDir); + expect(modpackService.checkCurrentModpackPathIsValid()).to.be.true(); + }); + + it("Should detect missing files in modpack path", () => { + const baseFSCopy = baseFS; + delete baseFSCopy[`${modDir}/${MO2Names.MO2EXE}`]; + mockFs.restore(); + mockFs(baseFSCopy); + const res = modpackService.checkModpackPathIsValid(modDir); + expect(res.ok).to.be.false(); + expect(res.missingPaths).to.eql([MO2Names.MO2EXE]); + }); + + it("Should return modpack.json", () => { + expect(modpackService.getModpackMetadata()).to.eql(modpack); + }); + + it("Should delete modpack from configservice' userPreferences", () => { + modpackService.deleteModpackDirectory(); + expect( + configService.stubs.deletePreference.calledOnceWithExactly( + USER_PREFERENCE_KEYS.MOD_DIRECTORY + ) + ).to.be.true(); + }); +}); diff --git a/src/__tests__/unit/services/resolution.service.test.ts b/src/__tests__/unit/services/resolution.service.test.ts new file mode 100644 index 00000000..70b786d1 --- /dev/null +++ b/src/__tests__/unit/services/resolution.service.test.ts @@ -0,0 +1 @@ +// TODO diff --git a/src/__tests__/unit/services/update.service.test.ts b/src/__tests__/unit/services/update.service.test.ts new file mode 100644 index 00000000..70b786d1 --- /dev/null +++ b/src/__tests__/unit/services/update.service.test.ts @@ -0,0 +1 @@ +// TODO diff --git a/src/__tests__/unit/services/window.service.test.ts b/src/__tests__/unit/services/window.service.test.ts new file mode 100644 index 00000000..70b786d1 --- /dev/null +++ b/src/__tests__/unit/services/window.service.test.ts @@ -0,0 +1 @@ +// TODO From 224feaef2f9651dbe770c6adf47c0f4f6707b877 Mon Sep 17 00:00:00 2001 From: Campiotti Date: Mon, 8 May 2023 20:42:39 +0200 Subject: [PATCH 2/3] chore: add test stub for error service --- src/__tests__/unit/services/error.service.test.ts | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/__tests__/unit/services/error.service.test.ts diff --git a/src/__tests__/unit/services/error.service.test.ts b/src/__tests__/unit/services/error.service.test.ts new file mode 100644 index 00000000..70b786d1 --- /dev/null +++ b/src/__tests__/unit/services/error.service.test.ts @@ -0,0 +1 @@ +// TODO From dfaa941fcc28a2f8641965561028c1b0db45db86 Mon Sep 17 00:00:00 2001 From: Campiotti Date: Wed, 24 May 2023 21:07:52 +0200 Subject: [PATCH 3/3] chore: add a few tests for resolutionService --- .../unit/services/resolution.service.test.ts | 124 +++++++++++++++++- 1 file changed, 123 insertions(+), 1 deletion(-) diff --git a/src/__tests__/unit/services/resolution.service.test.ts b/src/__tests__/unit/services/resolution.service.test.ts index 70b786d1..29d9d89d 100644 --- a/src/__tests__/unit/services/resolution.service.test.ts +++ b/src/__tests__/unit/services/resolution.service.test.ts @@ -1 +1,123 @@ -// TODO +import mockFs from "mock-fs"; +import { + createStubInstance, + expect, + StubbedInstanceWithSinonAccessor, +} from "@loopback/testlab"; +import { Resolution } from "@/Resolution"; +import { ResolutionService } from "@/main/services/resolution.service"; +import { ConfigService, userPreferences } from "@/main/services/config.service"; +import { InstructionService } from "@/main/services/instruction.service"; +import { beforeEach } from "mocha"; +import { DirectoryItems } from "mock-fs/lib/filesystem"; +import { USER_PREFERENCE_KEYS } from "@/shared/enums/userPreferenceKeys"; +import { name as modpackName } from "@/modpack.json"; +import { parse } from "js-ini"; +import fs from "fs"; +import { IIniObjectSection } from "js-ini/src/interfaces/ini-object-section"; + +describe("Resolution Service", () => { + let mockConfigService: StubbedInstanceWithSinonAccessor; + let mockInstructionService: StubbedInstanceWithSinonAccessor; + let resolutionService: ResolutionService; + const modDirectory = "/mock/modDir"; + // needs to be generated like this as mocking process.cwd() was unsuccessful. + const fakeAssetDir = `${process.cwd()}/src/assets`; + const baseFS = { + [fakeAssetDir]: { "a.json": "{}" }, + [`${modDirectory}/mods/${modpackName}/SKSE/Plugins/`]: { + "SSEDisplayTweaks.ini": "[Render]\nResolution=3840x1080\n", + }, + } as DirectoryItems; + const resUltraWide: Resolution = { width: 3840, height: 1080 }; + const resMedWide: Resolution = { width: 2440, height: 1080 }; + const resNormal: Resolution = { width: 1920, height: 1080 }; + + beforeEach(() => { + mockFs(baseFS); + mockConfigService = createStubInstance(ConfigService); + mockInstructionService = createStubInstance(InstructionService); + resolutionService = new ResolutionService( + mockConfigService, + mockInstructionService + ); + }); + + afterEach(() => { + mockFs.restore(); + }); + + it("Should get correct resource path", () => { + const res = resolutionService.getResourcePath(); + expect(res).to.eql(fakeAssetDir); + }); + + it("Should check if a resolution is UltraWide", () => { + expect(resolutionService.isUltraWidescreen(resUltraWide)).to.be.true(); + expect(resolutionService.isUltraWidescreen(resNormal)).to.be.false(); + }); + + it("Should get correct closest supported ratio", () => { + expect(resolutionService.getClosestSupportedRatio(resUltraWide)).to.eql( + "32:9" + ); + expect(resolutionService.getClosestSupportedRatio(resMedWide)).to.eql( + "21:9" + ); + expect(resolutionService.getClosestSupportedRatio(resNormal)).to.eql( + "16:9" + ); + }); + + // unable to mock {screen} from electron thus skipped + it.skip("Should set & apply a new resolution correctly", async () => { + // can't figure out how to mock the userPreference so setting the real one + userPreferences.set(USER_PREFERENCE_KEYS.RESOLUTION, resNormal); + // for USER_PREFERENCE_KEYS.MOD_DIRECTORY/mods/${modpackName}/SKSE/Plugins/SSEDisplayTweaks.ini + mockConfigService.stubs.getPreference.returns(modDirectory); + // for postSetResolution->getResolutionInstructions + mockInstructionService.stubs.getInstructions.returns([ + { + action: "disable-ultra-widescreen", + type: "resolution-ratio", + }, + { + action: "enable-mod", + type: "enb", + target: "16:9", + mod: "target-mod", + }, + ]); + mockInstructionService.stubs.execute.resolves(true); + + const res = await resolutionService.setResolution(resNormal); + expect(res).to.be.true(); + expect( + mockConfigService.stubs.setPreference.calledWith( + USER_PREFERENCE_KEYS.RESOLUTION, + resNormal + ) + ); + expect( + mockInstructionService.stubs.execute.calledOnceWithExactly( + [ + { + action: "disable-ultra-widescreen", + type: "resolution-ratio", + }, + ], + "16:9" + ) + ); + const newGraphicSettings = parse( + fs.readFileSync(resolutionService.skyrimGraphicsSettingsPath(), "utf-8"), + { comment: "#" } + ) as IIniObjectSection; + expect( + (newGraphicSettings.Render as IIniObjectSection).BorderlessUpscale + ).to.be.true(); + expect((newGraphicSettings.Render as IIniObjectSection).Resolution).to.eql( + "1920x1080" + ); + }); +});