114 lines · 4.4 KB · TypeScript
RawDownload
import { describe, expect, it } from "@effect/vitest";import * as NodePath from "@effect/platform-node/NodePath";import { HostProcessEnvironment, HostProcessPlatform } from "@t3tools/shared/hostProcess";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer";import * as Path from "effect/Path";import * as FileSystem from "effect/FileSystem"; import * as LocalDeviceHost from "./LocalDeviceHost.ts";import * as NodeServices from "@effect/platform-node/NodeServices";import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner";import { HttpClient } from "effect/unstable/http";import * as NetService from "@t3tools/shared/Net";import * as ServerConfig from "../config.ts";import * as ProcessRunner from "../processRunner.ts"; const diagnose = (files: ReadonlyArray<string>, environment: NodeJS.ProcessEnv) =>  LocalDeviceHost.__testing.platformReason("android").pipe(    Effect.provideService(HostProcessEnvironment, environment),    Effect.provideService(HostProcessPlatform, "darwin"),    Effect.provideService(      FileSystem.FileSystem,      FileSystem.makeNoop({        exists: (file) => Effect.succeed(files.includes(file)),      }),    ),    Effect.provide(NodePath.layer),  ); describe("Android SDK availability", () => {  it.effect("explains that adb alone is insufficient to launch an emulator", () =>    Effect.gen(function* () {      const reason = yield* diagnose(["/sdk/platform-tools/adb"], { ANDROID_HOME: "/sdk" });      expect(reason).toContain("Android Emulator is missing");    }),  );   it.effect("identifies command-line tools required by the device hub", () =>    Effect.gen(function* () {      const reason = yield* diagnose(["/sdk/platform-tools/adb", "/sdk/emulator/emulator"], {        ANDROID_HOME: "/sdk",      });      expect(reason).toContain("Command-line Tools (latest)");    }),  );   it.effect("discovers the standard macOS SDK without ANDROID_HOME", () =>    Effect.gen(function* () {      const root = "/test/home/Library/Android/sdk";      const reason = yield* diagnose(        [          `${root}/platform-tools/adb`,          `${root}/emulator/emulator`,          `${root}/cmdline-tools/latest/bin/avdmanager`,        ],        { HOME: "/test/home" },      );      expect(reason).toBeNull();    }),  );   it.effect("reports an absent SDK without running or installing tools", () =>    Effect.gen(function* () {      expect(yield* diagnose([], { HOME: "/test/home" })).toContain("Android SDK was not found");    }),  );}); it.effect("puts detected Android tools on the helper PATH without losing existing commands", () =>  Effect.gen(function* () {    const path = yield* Path.Path;    const environment = LocalDeviceHost.__testing.deviceHostEnvironment(      { PATH: "/usr/bin", HOME: "/test/home" },      "/sdk",      "darwin",      path,    );    expect(environment.PATH).toBe("/sdk/platform-tools:/sdk/emulator:/usr/bin");    expect(environment.ANDROID_HOME).toBe("/sdk");    expect(environment.HOME).toBe("/test/home");  }).pipe(Effect.provide(NodePath.layer)),); it.effect(  "constructs and inspects an unconfigured host without installing or starting helpers",  () =>    Effect.gen(function* () {      const fs = yield* FileSystem.FileSystem;      const baseDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-device-consent-" });      const host = yield* LocalDeviceHost.make().pipe(        Effect.provide(Layer.mergeAll(ServerConfig.layerTest(baseDir, baseDir), NetService.layer)),        Effect.provideService(HostProcessEnvironment, { HOME: baseDir, PATH: "" }),        Effect.provideService(HostProcessPlatform, "linux"),        Effect.provideService(          ChildProcessSpawner.ChildProcessSpawner,          ChildProcessSpawner.make(() =>            Effect.die(new Error("Host construction must not spawn processes")),          ),        ),        Effect.provideService(ProcessRunner.ProcessRunner, {          run: () => Effect.die(new Error("Host construction must not run commands")),        }),        Effect.provideService(          HttpClient.HttpClient,          HttpClient.make(() =>            Effect.die(new Error("Host construction must not make network requests")),          ),        ),      );      expect(yield* host.current).toBeNull();      yield* host.stop;      expect(yield* fs.exists(`${baseDir}/tools`)).toBe(false);    }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),);