| ... | @@ -4,6 +4,7 @@ import * as Effect from "effect/Effect"; | ... | @@ -4,6 +4,7 @@ import * as Effect from "effect/Effect"; |
| 4 | import * as FileSystem from "effect/FileSystem"; | 4 | import * as FileSystem from "effect/FileSystem"; |
| 5 | import * as Layer from "effect/Layer"; | 5 | import * as Layer from "effect/Layer"; |
| 6 | import * as Option from "effect/Option"; | 6 | import * as Option from "effect/Option"; |
| | 7 | import * as PlatformError from "effect/PlatformError"; |
| 7 | | 8 | |
| 8 | import type * as Electron from "electron"; | 9 | import type * as Electron from "electron"; |
| 9 | | 10 | |
| ... | @@ -105,6 +106,7 @@ const withIdentity = <A, E, R>( | ... | @@ -105,6 +106,7 @@ const withIdentity = <A, E, R>( |
| 105 | readonly calls?: ElectronAppCalls; | 106 | readonly calls?: ElectronAppCalls; |
| 106 | readonly environment?: TestEnvironmentInput; | 107 | readonly environment?: TestEnvironmentInput; |
| 107 | readonly legacyPathExists?: boolean; | 108 | readonly legacyPathExists?: boolean; |
| | 109 | readonly legacyPathProbeError?: PlatformError.PlatformError; |
| 108 | readonly packageJson?: string; | 110 | readonly packageJson?: string; |
| 109 | readonly pngIconPath?: Option.Option<string>; | 111 | readonly pngIconPath?: Option.Option<string>; |
| 110 | } = {}, | 112 | } = {}, |
| ... | @@ -121,7 +123,11 @@ const withIdentity = <A, E, R>( | ... | @@ -121,7 +123,11 @@ const withIdentity = <A, E, R>( |
| 121 | Layer.provideMerge( | 123 | Layer.provideMerge( |
| 122 | FileSystem.layerNoop({ | 124 | FileSystem.layerNoop({ |
| 123 | exists: (path) => | 125 | exists: (path) => |
| 124 | Effect.succeed(input.legacyPathExists === true && path.includes("T3 Code (Alpha)")), | 126 | input.legacyPathProbeError |
| | 127 | ? Effect.fail(input.legacyPathProbeError) |
| | 128 | : Effect.succeed( |
| | 129 | input.legacyPathExists === true && path.includes("T3 Code (Alpha)"), |
| | 130 | ), |
| 125 | readFileString: () => | 131 | readFileString: () => |
| 126 | Effect.succeed(input.packageJson ?? '{"t3codeCommitHash":"abcdef1234567890"}'), | 132 | Effect.succeed(input.packageJson ?? '{"t3codeCommitHash":"abcdef1234567890"}'), |
| 127 | }), | 133 | }), |
| ... | @@ -147,6 +153,33 @@ describe("DesktopAppIdentity", () => { | ... | @@ -147,6 +153,33 @@ describe("DesktopAppIdentity", () => { |
| 147 | ), | 153 | ), |
| 148 | ); | 154 | ); |
| 149 | | 155 | |
| | 156 | it.effect("preserves failures while inspecting the legacy userData path", () => { |
| | 157 | const legacyPath = "/Users/alice/Library/Application Support/T3 Code (Alpha)"; |
| | 158 | const cause = PlatformError.systemError({ |
| | 159 | _tag: "PermissionDenied", |
| | 160 | module: "FileSystem", |
| | 161 | method: "exists", |
| | 162 | description: "permission denied", |
| | 163 | pathOrDescriptor: legacyPath, |
| | 164 | }); |
| | 165 | |
| | 166 | return withIdentity( |
| | 167 | Effect.gen(function* () { |
| | 168 | const identity = yield* DesktopAppIdentity.DesktopAppIdentity; |
| | 169 | const error = yield* identity.resolveUserDataPath.pipe(Effect.flip); |
| | 170 | |
| | 171 | assert.instanceOf(error, DesktopAppIdentity.DesktopUserDataPathResolutionError); |
| | 172 | assert.equal(error.legacyPath, legacyPath); |
| | 173 | assert.strictEqual(error.cause, cause); |
| | 174 | assert.equal( |
| | 175 | error.message, |
| | 176 | `Failed to inspect legacy desktop user-data path at "${legacyPath}".`, |
| | 177 | ); |
| | 178 | }), |
| | 179 | { legacyPathProbeError: cause }, |
| | 180 | ); |
| | 181 | }); |
| | 182 | |
| 150 | it.effect("configures app identity from the environment commit override", () => { | 183 | it.effect("configures app identity from the environment commit override", () => { |
| 151 | const calls: ElectronAppCalls = { | 184 | const calls: ElectronAppCalls = { |
| 152 | setAboutPanelOptions: [], | 185 | setAboutPanelOptions: [], |