From a9def876e86f3e1776f253062cdfe1ece3efd0a0 Mon Sep 17 00:00:00 2001 From: Cooldude2606 <25043174+Cooldude2606@users.noreply.github.com> Date: Tue, 15 Apr 2025 19:09:25 +0100 Subject: [PATCH] Remove `phin` without introducing new dependencies (#755) --- packages/create/create.js | 12 +- packages/create/package.json | 1 - plugins/player_auth/package.json | 1 - plugins/player_auth/test/plugin.js | 238 ++++++++++----------------- test/controller/routes.js | 253 ++++++++++++++--------------- test/integration/create.js | 1 - test/lib/ModStore.test.js | 11 +- 7 files changed, 220 insertions(+), 297 deletions(-) diff --git a/packages/create/create.js b/packages/create/create.js index 7a7eaaad..8699ca3f 100755 --- a/packages/create/create.js +++ b/packages/create/create.js @@ -6,7 +6,6 @@ const fs = require("fs-extra"); const inquirer = require("inquirer"); const os = require("os"); const path = require("path"); -const phin = require("phin"); const stream = require("stream"); const util = require("util"); const yargs = require("yargs"); @@ -624,7 +623,7 @@ async function inquirerMissingArgs(args) { answers.publicAddress = args.publicAddress; } else { try { - let result = await phin("https://api.ipify.org/"); + let result = await fetch("https://api.ipify.org/"); myIp = result.body.toString(); } catch (err) { /* ignore */ } } @@ -741,7 +740,7 @@ async function inquirerMissingArgs(args) { } async function downloadLinuxServer() { - let res = await phin("https://factorio.com/get-download/stable/headless/linux64"); + let res = await fetch("https://factorio.com/get-download/stable/headless/linux64"); const url = new URL(res.headers.location); // get the filename of the latest factorio archive from redirected url @@ -764,14 +763,11 @@ async function downloadLinuxServer() { await fs.ensureDir(tmpDir); // follow the redirect - res = await phin({ - url: url.href, - stream: true, - }); + res = await fetch(url.href); logger.info("Downloading latest Factorio server release. This may take a while."); const writeStream = fs.createWriteStream(tmpArchivePath); - res.pipe(writeStream); + stream.Readable.fromWeb(res.body).pipe(writeStream); await finished(writeStream); diff --git a/packages/create/package.json b/packages/create/package.json index 5104b19b..e1e7035c 100644 --- a/packages/create/package.json +++ b/packages/create/package.json @@ -19,7 +19,6 @@ "chalk": "^4.1.2", "fs-extra": "^11.3.0", "inquirer": "^8.2.4", - "phin": "^3.7.0", "yargs": "^17.7.2" }, "publishConfig": { diff --git a/plugins/player_auth/package.json b/plugins/player_auth/package.json index ac33f74c..25a360f5 100644 --- a/plugins/player_auth/package.json +++ b/plugins/player_auth/package.json @@ -38,7 +38,6 @@ "@types/node": "^20.17.19", "@types/react": "^18.3.18", "antd": "^5.24.2", - "phin": "^3.7.0", "react": "^18.2.0", "react-dom": "^18.2.0", "typescript": "^5.7.3", diff --git a/plugins/player_auth/test/plugin.js b/plugins/player_auth/test/plugin.js index 3865fcdb..6502bcc2 100644 --- a/plugins/player_auth/test/plugin.js +++ b/plugins/player_auth/test/plugin.js @@ -1,6 +1,5 @@ "use strict"; const assert = require("assert").strict; -const phin = require("phin"); const jwt = require("jsonwebtoken"); const mock = require("../../../test/mock"); @@ -11,6 +10,13 @@ const info = require("../dist/node/index").plugin; const { FetchPlayerCodeRequest, SetVerifyCodeRequest } = require("../dist/node/messages"); const lib = require("@clusterio/lib"); +function postJSON(url, body) { + return fetch(url, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(body), + }); +} describe("player_auth", function() { describe("controller.js", function() { @@ -39,6 +45,7 @@ describe("player_auth", function() { describe("ControllerPlugin", function() { let controllerPlugin; let controllerUrl; + let endpoint; before(async function() { controllerPlugin = await mock.createControllerPlugin(controller.ControllerPlugin, info); controllerPlugin.controller.mockConfigEntries.set("player_auth.code_length", 10); @@ -75,11 +82,8 @@ describe("player_auth", function() { addInstance(3, "running", false, "running unloaded"); addInstance(4, "stopped", false, "stopped unloaded"); addInstance(5, "running", true, undefined); - let result = await phin({ - url: `${controllerUrl}/api/player_auth/servers`, - parse: "json", - }); - assert.deepEqual(result.body, ["running loaded", "unnamed server"]); + const result = await fetch(`${controllerUrl}/api/player_auth/servers`); + assert.deepEqual(await result.json(), ["running loaded", "unnamed server"]); for (let id of [1, 2, 3, 4, 5]) { controllerPlugin.controller.instances.delete(id); } @@ -87,128 +91,81 @@ describe("player_auth", function() { }); describe("/api/player_auth/player_code", function() { + before(function() { + endpoint = `${controllerUrl}/api/player_auth/player_code`; + }); it("should return 400 on invalid json", async function() { - let result = await phin({ - url: `${controllerUrl}/api/player_auth/player_code`, - method: "POST", - headers: { - "Content-Type": "application/json", - }, - data: "invalid", - }); - assert.equal(result.statusCode, 400); + const result = await postJSON(endpoint, "invalid"); + assert.equal(result.status, 400); }); it("should return 400 on valid json which is not an object", async function() { for (let obj of [true, false, null, "string", 123, ["an", "array"]]) { - let result = await phin({ - url: `${controllerUrl}/api/player_auth/player_code`, - method: "POST", - headers: { - "Content-Type": "application/json", - }, - data: JSON.stringify(obj), - }); - assert.equal(result.statusCode, 400); + const result = await postJSON(endpoint, obj); + assert.equal(result.status, 400); } }); it("should return 400 if player_code is not a string", async function() { for (let obj of [true, false, null, 123, [], {}]) { - let result = await phin({ - url: `${controllerUrl}/api/player_auth/player_code`, - method: "POST", - headers: { - "Content-Type": "application/json", - }, - data: JSON.stringify({ player_code: obj }), - }); - assert.equal(result.statusCode, 400); + const result = await postJSON(endpoint, { player_code: obj }); + assert.equal(result.status, 400); } }); it("should return invalid player_code if the code is expired", async function() { let expiresMs = Date.now() - 1000; controllerPlugin.players.set("expired", { playerCode: "expired", verifyCode: null, expiresMs }); - let result = await phin({ - url: `${controllerUrl}/api/player_auth/player_code`, - method: "POST", - data: { player_code: "expired" }, - parse: "json", - }); - assert.deepEqual(result.body, { error: true, message: "invalid player_code" }); + const result = await postJSON(endpoint, { player_code: "expired" }); + assert.deepEqual(await result.json(), { error: true, message: "invalid player_code" }); }); it("should return a verify code and token if code is valid", async function() { let expiresMs = Date.now() + 1000; controllerPlugin.players.set("valid", { playerCode: "valid", verifyCode: null, expiresMs }); - let result = await phin({ - url: `${controllerUrl}/api/player_auth/player_code`, - method: "POST", - data: { player_code: "valid" }, - parse: "json", - }); - assert.equal(typeof result.body.verify_code, "string"); - assert.equal(typeof result.body.verify_token, "string"); + const result = await postJSON(endpoint, { player_code: "valid" }); + const body = await result.json(); + assert.equal(typeof body.verify_code, "string"); + assert.equal(typeof body.verify_token, "string"); }); }); describe("/api/player_auth/verify", function() { + before(function() { + endpoint = `${controllerUrl}/api/player_auth/verify`; + }); it("should return 400 on invalid json", async function() { - let result = await phin({ - url: `${controllerUrl}/api/player_auth/verify`, - method: "POST", - headers: { - "Content-Type": "application/json", - }, - data: "invalid", - }); - assert.equal(result.statusCode, 400); + const result = await postJSON(endpoint, "invalid"); + assert.equal(result.status, 400); }); it("should return 400 on valid json which is not an object", async function() { for (let obj of [true, false, null, "string", 123, ["an", "array"]]) { - let result = await phin({ - url: `${controllerUrl}/api/player_auth/verify`, - method: "POST", - headers: { - "Content-Type": "application/json", - }, - data: JSON.stringify(obj), - }); - assert.equal(result.statusCode, 400); + const result = await postJSON(endpoint, obj); + assert.equal(result.status, 400); } }); it("should return 400 if player_code, verify_code or verify_token are not strings", async function() { for (let obj of [true, false, null, 123, [], {}]) { for (let field of ["player_code", "verify_code", "verify_token"]) { - let result = await phin({ - url: `${controllerUrl}/api/player_auth/verify`, - method: "POST", - data: { - player_code: "str", - verify_code: "str", - verify_token: "str", - [field]: obj, - }, + const result = await postJSON(endpoint, { + player_code: "str", + verify_code: "str", + verify_token: "str", + [field]: obj, }); - assert.equal(result.statusCode, 400); + assert.equal(result.status, 400); } } }); it("should return error if verify_token is not valid", async function() { async function verify(tokenParams, error) { - let result = await phin({ - url: `${controllerUrl}/api/player_auth/verify`, - method: "POST", - data: { + const result = await postJSON(endpoint, { + player_code: "player", + verify_code: "verify", + verify_token: jwt.sign({ + aud: "player_auth.verify_code", player_code: "player", verify_code: "verify", - verify_token: jwt.sign({ - aud: "player_auth.verify_code", - player_code: "player", - verify_code: "verify", - ...tokenParams, - }, Buffer.from(tokenParams.secret || "TestSecretDoNotUse", "base64")), - }, - parse: "json", + ...tokenParams, + }, Buffer.from(tokenParams.secret || "TestSecretDoNotUse", "base64")), }); - assert.deepEqual(result.body.error, true); + assert.deepEqual((await result.json()).error, true); } await verify({ secret: "InvalidSecret" }); await verify({ verify_code: "bad" }); @@ -218,21 +175,16 @@ describe("player_auth", function() { it("should return invalid player_code if the code is expired", async function() { let expiresMs = Date.now() - 1000; controllerPlugin.players.set("expired", { playerCode: "expired", verifyCode: "verify", expiresMs }); - let result = await phin({ - url: `${controllerUrl}/api/player_auth/verify`, - method: "POST", - data: { + const result = await postJSON(endpoint, { + player_code: "expired", + verify_code: "verify", + verify_token: jwt.sign({ + aud: "player_auth.verify_code", player_code: "expired", verify_code: "verify", - verify_token: jwt.sign({ - aud: "player_auth.verify_code", - player_code: "expired", - verify_code: "verify", - }, Buffer.from("TestSecretDoNotUse", "base64")), - }, - parse: "json", + }, Buffer.from("TestSecretDoNotUse", "base64")), }); - assert.deepEqual(result.body, { error: true, message: "invalid player_code" }); + assert.deepEqual(await result.json(), { error: true, message: "invalid player_code" }); }); it("should return verified false if verify code has not yet been set", async function() { let expiresMs = Date.now() + 1000; @@ -240,60 +192,46 @@ describe("player_auth", function() { "unverified", { playerCode: "unverified", verifyCode: null, expiresMs }, ); - let result = await phin({ - url: `${controllerUrl}/api/player_auth/verify`, - method: "POST", - data: { + const result = await postJSON(endpoint, { + player_code: "unverified", + verify_code: "verify", + verify_token: jwt.sign({ + aud: "player_auth.verify_code", player_code: "unverified", verify_code: "verify", - verify_token: jwt.sign({ - aud: "player_auth.verify_code", - player_code: "unverified", - verify_code: "verify", - }, Buffer.from("TestSecretDoNotUse", "base64")), - }, - parse: "json", + }, Buffer.from("TestSecretDoNotUse", "base64")), }); - assert.deepEqual(result.body, { verified: false }); + assert.deepEqual(await result.json(), { verified: false }); }); it("should return error if user is missing", async function() { let expiresMs = Date.now() + 1000; controllerPlugin.players.set("missing", { playerCode: "missing", verifyCode: "verify", expiresMs }); - let result = await phin({ - url: `${controllerUrl}/api/player_auth/verify`, - method: "POST", - data: { + const result = await postJSON(endpoint, { + player_code: "missing", + verify_code: "verify", + verify_token: jwt.sign({ + aud: "player_auth.verify_code", player_code: "missing", verify_code: "verify", - verify_token: jwt.sign({ - aud: "player_auth.verify_code", - player_code: "missing", - verify_code: "verify", - }, Buffer.from("TestSecretDoNotUse", "base64")), - }, - parse: "json", + }, Buffer.from("TestSecretDoNotUse", "base64")), }); - assert.deepEqual(result.body, { error: true, message: "invalid user" }); + assert.deepEqual(await result.json(), { error: true, message: "invalid user" }); }); it("should return verified true with token if valid verification", async function() { let expiresMs = Date.now() + 1000; controllerPlugin.players.set("player", { playerCode: "player", verifyCode: "verify", expiresMs }); - let result = await phin({ - url: `${controllerUrl}/api/player_auth/verify`, - method: "POST", - data: { + const result = await postJSON(endpoint, { + player_code: "player", + verify_code: "verify", + verify_token: jwt.sign({ + aud: "player_auth.verify_code", player_code: "player", verify_code: "verify", - verify_token: jwt.sign({ - aud: "player_auth.verify_code", - player_code: "player", - verify_code: "verify", - }, Buffer.from("TestSecretDoNotUse", "base64")), - }, - parse: "json", + }, Buffer.from("TestSecretDoNotUse", "base64")), }); - assert.equal(result.body.verified, true); - assert.deepEqual(typeof result.body.token, "string", "missing token"); + const body = await result.json(); + assert.equal(body.verified, true); + assert.deepEqual(typeof body.token, "string", "missing token"); }); }); @@ -338,25 +276,21 @@ describe("player_auth", function() { new FetchPlayerCodeRequest("test") ); - let playerCodeResult = await phin({ - url: `${controllerUrl}/api/player_auth/player_code`, - method: "POST", - data: { player_code: playerCode }, - parse: "json", - }); + const playerCodeResult = await postJSON( + `${controllerUrl}/api/player_auth/player_code`, + { player_code: playerCode } + ); - let { verify_code, verify_token } = playerCodeResult.body; + let { verify_code, verify_token } = await playerCodeResult.json(); await controllerPlugin.handleSetVerifyCodeRequest( new SetVerifyCodeRequest("test", verify_code) ); - let verifyResult = await phin({ - url: `${controllerUrl}/api/player_auth/verify`, - method: "POST", - data: { player_code: playerCode, verify_code, verify_token }, - parse: "json", - }); - assert.equal(verifyResult.body.verified, true); + const verifyResult = await postJSON( + `${controllerUrl}/api/player_auth/verify`, + { player_code: playerCode, verify_code, verify_token } + ); + assert.equal((await verifyResult.json()).verified, true); }); }); }); diff --git a/test/controller/routes.js b/test/controller/routes.js index b2d5d07d..06d605e6 100644 --- a/test/controller/routes.js +++ b/test/controller/routes.js @@ -4,13 +4,11 @@ const events = require("events"); const FormData = require("form-data"); const jwt = require("jsonwebtoken"); const http = require("http"); -const phin = require("phin"); const { wait } = require("@clusterio/lib"); const routes = require("@clusterio/controller/dist/node/src/routes"); const mock = require("../mock"); - describe("controller/src/routes", function() { let controller; let server; @@ -27,20 +25,23 @@ describe("controller/src/routes", function() { server.close(); }); describe("/api/stream/:id", function() { + let endpoint; + beforeEach(function() { + endpoint = `http://localhost:${port}/api/stream`; + }); it("should respond with 404 if stream doesn't exist", async function() { let response; - response = await phin(`http://localhost:${port}/api/stream/01020304`); - assert.equal(response.statusCode, 404); - response = await phin({ - url: `http://localhost:${port}/api/stream/01020304`, method: "PUT", - data: "test stream", + response = await fetch(`${endpoint}/01020304`); + assert.equal(response.status, 404); + response = await fetch(`${endpoint}/01020304`, { + method: "PUT", body: "test stream", }); - assert.equal(response.statusCode, 404); + assert.equal(response.status, 404); }); it("should respond with 500 if stream times out", async function() { let stream = await routes.createProxyStream(controller.app); - let response = await phin(`http://localhost:${port}/api/stream/${stream.id}`); - assert.equal(response.statusCode, 500); + let response = await fetch(`${endpoint}/${stream.id}`); + assert.equal(response.status, 500); }); it("should passthrough a stream", async function() { let stream; @@ -49,121 +50,123 @@ describe("controller/src/routes", function() { responses = await Promise.all([ (async function() { await wait(100); - return await phin({ - url: `http://localhost:${port}/api/stream/${stream.id}`, method: "PUT", - data: "test content", + return await fetch(`${endpoint}/${stream.id}`, { + method: "PUT", body: "test content", }); }()), - phin(`http://localhost:${port}/api/stream/${stream.id}`), + fetch(`${endpoint}/${stream.id}`), ]); - assert.equal(responses[0].statusCode, 200); - assert.equal(responses[1].statusCode, 200); - assert.equal(responses[1].body.toString(), "test content"); + assert.equal(responses[0].status, 200); + assert.equal(responses[1].status, 200); + assert.equal(await responses[1].text(), "test content"); stream = await routes.createProxyStream(controller.app); responses = await Promise.all([ - phin({ - url: `http://localhost:${port}/api/stream/${stream.id}`, method: "PUT", - data: "test content", + fetch(`${endpoint}/${stream.id}`, { + method: "PUT", body: "test content", }), (async function() { await wait(100); - return await phin(`http://localhost:${port}/api/stream/${stream.id}`); + return await fetch(`${endpoint}/${stream.id}`); }()), ]); - assert.equal(responses[0].statusCode, 200); - assert.equal(responses[1].statusCode, 200); - assert.equal(responses[1].body.toString(), "test content"); + assert.equal(responses[0].status, 200); + assert.equal(responses[1].status, 200); + assert.equal(await responses[1].text(), "test content"); }); }); describe("/api/upload-save", function() { + let endpoint; + beforeEach(function() { + endpoint = `http://localhost:${port}/api/upload-save`; + }); it("should respond with 401 with invalid token", async function() { let response; - response = await phin({ - url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=file.zip`, method: "POST", + response = await fetch(`${endpoint}?instance_id=123&filename=file.zip`, { + method: "POST", headers: { "Content-Type": "application/zip" }, - data: "totally a zip file", + body: "totally a zip file", }); - assert.equal(response.statusCode, 401); - response = await phin({ - url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=file.zip`, method: "POST", + assert.equal(response.status, 401); + response = await fetch(`${endpoint}?instance_id=123&filename=file.zip`, { + method: "POST", headers: { "Content-Type": "application/zip", "X-Access-Token": "invalid", }, - data: "totally a zip file", + body: "totally a zip file", }); - assert.equal(response.statusCode, 401); - response = await phin({ - url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=file.zip`, method: "POST", + assert.equal(response.status, 401); + response = await fetch(`${endpoint}?instance_id=123&filename=file.zip`, { + method: "POST", headers: { "Content-Type": "application/zip", "X-Access-Token": jwt.sign( { aud: "user", user: "invalid" }, Buffer.from("TestSecretDoNotUse", "base64") ), }, - data: "totally a zip file", + body: "totally a zip file", }); - assert.equal(response.statusCode, 401); + assert.equal(response.status, 401); controller.userManager.getByName("test").tokenValidAfter = Math.floor((Date.now() + 60e3) / 1000); - response = await phin({ - url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=file.zip`, method: "POST", + response = await fetch(`${endpoint}?instance_id=123&filename=file.zip`, { + method: "POST", headers: { "Content-Type": "application/zip", "X-Access-Token": jwt.sign( { aud: "user", user: "test" }, Buffer.from("TestSecretDoNotUse", "base64") ), }, - data: "totally a zip file", + body: "totally a zip file", }); - assert.equal(response.statusCode, 401); + assert.equal(response.status, 401); }); it("should respond with 403 when user has insufficient permission", async function() { - let response = await phin({ - url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=file.zip`, method: "POST", + let response = await fetch(`${endpoint}?instance_id=123&filename=file.zip`, { + method: "POST", headers: { "Content-Type": "application/zip", "X-Access-Token": jwt.sign( { aud: "user", user: "player" }, Buffer.from("TestSecretDoNotUse", "base64") ), }, - data: "totally a zip file", + body: "totally a zip file", }); - assert.equal(response.statusCode, 403); + assert.equal(response.status, 403); }); let testToken = jwt.sign({ aud: "user", user: "test" }, Buffer.from("TestSecretDoNotUse", "base64")); it("should respond with 415 if content type is missing or invalid", async function() { let response; - response = await phin({ - url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=file.zip`, method: "POST", + response = await fetch(`${endpoint}?instance_id=123&filename=file.zip`, { + method: "POST", headers: { "X-Access-Token": testToken, }, - data: "totally a zip file", + body: "totally a zip file", }); - assert.equal(response.statusCode, 415); - assert.deepEqual(JSON.parse(response.body), { request_errors: ["invalid Content-Type"] }); - response = await phin({ - url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=file.zip`, method: "POST", + assert.equal(response.status, 415); + assert.deepEqual(await response.json(), { request_errors: ["invalid Content-Type"] }); + response = await fetch(`${endpoint}?instance_id=123&filename=file.zip`, { + method: "POST", headers: { "X-Access-Token": testToken, "Content-Type": "invalid", }, - data: "totally a zip file", + body: "totally a zip file", }); - assert.equal(response.statusCode, 415); - assert.deepEqual(JSON.parse(response.body), { request_errors: ["invalid Content-Type"] }); - response = await phin({ - url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=file.zip`, method: "POST", + assert.equal(response.status, 415); + assert.deepEqual(await response.json(), { request_errors: ["invalid Content-Type"] }); + response = await fetch(`${endpoint}?instance_id=123&filename=file.zip`, { + method: "POST", headers: { "X-Access-Token": testToken, "Content-Type": "text/plain", }, - data: "totally a zip file", + body: "totally a zip file", }); - assert.equal(response.statusCode, 415); - assert.deepEqual(JSON.parse(response.body), { request_errors: ["invalid Content-Type"] }); + assert.equal(response.status, 415); + assert.deepEqual(await response.json(), { request_errors: ["invalid Content-Type"] }); }); it("should respond with 400 if invalid multipart request", async function() { @@ -172,96 +175,96 @@ describe("controller/src/routes", function() { form = new FormData(); form.append("instance_id", "123"); form.append("file", "totally a zip file", { filename: "test.zip", contentType: "text/plain" }); - response = await phin({ - url: `http://localhost:${port}/api/upload-save`, method: "POST", + response = await fetch(endpoint, { + method: "POST", headers: { "X-Access-Token": testToken, ...form.getHeaders(), }, - data: form.getBuffer(), + body: form.getBuffer(), }); - assert.equal(response.statusCode, 400); - assert.deepEqual(JSON.parse(response.body), { request_errors: ["invalid file Content-Type"] }); + assert.equal(response.status, 400); + assert.deepEqual(await response.json(), { request_errors: ["invalid file Content-Type"] }); form = new FormData(); form.append("file", "totally a zip file", { filename: "test.zip", contentType: "application/zip" }); form.append("instance_id", "123"); - response = await phin({ - url: `http://localhost:${port}/api/upload-save`, method: "POST", + response = await fetch(endpoint, { + method: "POST", headers: { "X-Access-Token": testToken, ...form.getHeaders(), }, - data: form.getBuffer(), + body: form.getBuffer(), }); - assert.equal(response.statusCode, 400); + assert.equal(response.status, 400); assert.deepEqual( - JSON.parse(response.body), { request_errors: ["instance_id must come before files uploaded"] } + await response.json(), { request_errors: ["instance_id must come before files uploaded"] } ); form = new FormData(); form.append("instance_id", "123"); form.append("file", "totally a zip file", { filename: "test.txt", contentType: "application/zip" }); - response = await phin({ - url: `http://localhost:${port}/api/upload-save`, method: "POST", + response = await fetch(endpoint, { + method: "POST", headers: { "X-Access-Token": testToken, ...form.getHeaders(), }, - data: form.getBuffer(), + body: form.getBuffer(), }); - assert.equal(response.statusCode, 400); + assert.equal(response.status, 400); assert.deepEqual( - JSON.parse(response.body), { request_errors: ["filename must end with .zip"] } + await response.json(), { request_errors: ["filename must end with .zip"] } ); form = new FormData(); form.append("instance_id", "invalid"); form.append("file", "totally a zip file", { filename: "test.zip", contentType: "application/zip" }); - response = await phin({ - url: `http://localhost:${port}/api/upload-save`, method: "POST", + response = await fetch(endpoint, { + method: "POST", headers: { "X-Access-Token": testToken, ...form.getHeaders(), }, - data: form.getBuffer(), + body: form.getBuffer(), }); - assert.equal(response.statusCode, 400); + assert.equal(response.status, 400); assert.deepEqual( - JSON.parse(response.body), { request_errors: ["invalid instance_id"] } + await response.json(), { request_errors: ["invalid instance_id"] } ); }); it("should respond with 400 if invalid file request", async function() { let response; - response = await phin({ - url: `http://localhost:${port}/api/upload-save?instance_id=123`, method: "POST", + response = await fetch(`${endpoint}?instance_id=123`, { + method: "POST", headers: { "X-Access-Token": testToken, "Content-Type": "application/zip", }, - data: "totally a zip file", + body: "totally a zip file", }); - assert.equal(response.statusCode, 400); - assert.deepEqual(JSON.parse(response.body), { request_errors: ["Missing or invalid filename parameter"] }); - response = await phin({ - url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=test.txt`, method: "POST", + assert.equal(response.status, 400); + assert.deepEqual(await response.json(), { request_errors: ["Missing or invalid filename parameter"] }); + response = await fetch(`${endpoint}?instance_id=123&filename=test.txt`, { + method: "POST", headers: { "X-Access-Token": testToken, "Content-Type": "application/zip", }, - data: "totally a zip file", + body: "totally a zip file", }); - assert.equal(response.statusCode, 400); - assert.deepEqual(JSON.parse(response.body), { request_errors: ["filename must end with .zip"] }); - response = await phin({ - url: `http://localhost:${port}/api/upload-save?filename=test.zip`, method: "POST", + assert.equal(response.status, 400); + assert.deepEqual(await response.json(), { request_errors: ["filename must end with .zip"] }); + response = await fetch(`${endpoint}?filename=test.zip`, { + method: "POST", headers: { "X-Access-Token": testToken, "Content-Type": "application/zip", }, - data: "totally a zip file", + body: "totally a zip file", }); - assert.equal(response.statusCode, 400); + assert.equal(response.status, 400); assert.deepEqual( - JSON.parse(response.body), { request_errors: ["Missing or invalid instance_id parameter"] } + await response.json(), { request_errors: ["Missing or invalid instance_id parameter"] } ); }); @@ -274,82 +277,78 @@ describe("controller/src/routes", function() { form = new FormData(); form.append("instance_id", "123"); form.append("file", "totally a zip file", { filename: "test.zip", contentType: "application/zip" }); - response = await phin({ - url: `http://localhost:${port}/api/upload-save`, method: "POST", + response = await fetch(endpoint, { + method: "POST", headers: { "X-Access-Token": testToken, ...form.getHeaders(), }, - data: form.getBuffer(), + body: form.getBuffer(), }); - assert.equal(response.statusCode, 500); - assert.deepEqual(JSON.parse(response.body), { errors: ["Something went wrong"], request_errors: [] }); - response = await phin({ - url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=test.zip`, method: "POST", + assert.equal(response.status, 500); + assert.deepEqual(await response.json(), { errors: ["Something went wrong"], request_errors: [] }); + response = await fetch(`${endpoint}?instance_id=123&filename=test.zip`, { + method: "POST", headers: { "X-Access-Token": testToken, "Content-Type": "application/zip", }, - data: "totally a zip file", + body: "totally a zip file", }); - assert.equal(response.statusCode, 500); - assert.deepEqual(JSON.parse(response.body), { errors: ["Something went wrong"], request_errors: [] }); + assert.equal(response.status, 500); + assert.deepEqual(await response.json(), { errors: ["Something went wrong"], request_errors: [] }); controller.sendToHostByInstanceId = async (request) => { await new Promise(() => {}); }; - response = await phin({ - url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=test.zip`, method: "POST", + response = await fetch(`${endpoint}?instance_id=123&filename=test.zip`, { + method: "POST", headers: { "X-Access-Token": testToken, "Content-Type": "application/zip", }, - data: "totally a zip file", + body: "totally a zip file", }); - assert.equal(response.statusCode, 500); + assert.equal(response.status, 500); assert.deepEqual( - JSON.parse(response.body), { errors: ["Timed out establishing stream to host"], request_errors: [] } + await response.json(), { errors: ["Timed out establishing stream to host"], request_errors: [] } ); }); it("should complete a valid transfer", async function() { controller.sendToHostByInstanceId = async (request) => { - let stream = await phin({ - url: `http://localhost:${port}/api/stream/${request.streamId}`, - }); - assert.equal(stream.body.toString(), "totally a zip file"); + const stream = await fetch(`http://localhost:${port}/api/stream/${request.streamId}`); + assert.equal(await stream.text(), "totally a zip file"); return request.name; }; let response; - response = await phin({ - url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=test.zip`, method: "POST", + response = await fetch(`${endpoint}?instance_id=123&filename=test.zip`, { + method: "POST", headers: { "X-Access-Token": testToken, "Content-Type": "application/zip", }, - data: "totally a zip file", + body: "totally a zip file", }); - assert.deepEqual(JSON.parse(response.body), { saves: ["test.zip"] }); - assert.equal(response.statusCode, 200); + assert.deepEqual(await response.json(), { saves: ["test.zip"] }); + assert.equal(response.status, 200); }); it("should complete a valid transfer with non-standerd mime type", async function() { controller.sendToHostByInstanceId = async (request) => { - let stream = await phin({ - url: `http://localhost:${port}/api/stream/${request.streamId}`, - }); - assert.equal(stream.body.toString(), "totally a zip file"); + const stream = await fetch(`http://localhost:${port}/api/stream/${request.streamId}`); + assert.equal(await stream.text(), "totally a zip file"); return request.name; }; let response; - response = await phin({ - url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=test.zip`, method: "POST", + response = await fetch(`${endpoint}?instance_id=123&filename=test.zip`, { + method: "POST", headers: { "X-Access-Token": testToken, "Content-Type": "application/x-zip-compressed", }, - data: "totally a zip file", + body: "totally a zip file", }); - assert.deepEqual(JSON.parse(response.body), { saves: ["test.zip"] }); - assert.equal(response.statusCode, 200); + assert.deepEqual(await response.json(), { saves: ["test.zip"] }); + assert.equal(response.status, 200); }); }); }); diff --git a/test/integration/create.js b/test/integration/create.js index fc6a7535..c1dfcd9e 100644 --- a/test/integration/create.js +++ b/test/integration/create.js @@ -4,7 +4,6 @@ const fs = require("fs-extra"); const jwt = require("jsonwebtoken"); const path = require("path"); const events = require("events"); -const phin = require("phin"); const child_process = require("child_process"); const util = require("util"); diff --git a/test/lib/ModStore.test.js b/test/lib/ModStore.test.js index 9f081164..7730eadd 100644 --- a/test/lib/ModStore.test.js +++ b/test/lib/ModStore.test.js @@ -7,15 +7,8 @@ const JSZip = require("jszip"); // Added for creating mock zips // Capture native fetch before any potential mocks are applied const nativeFetch = global.fetch; -// Removed logger mocking setup - const { ModStore, ModInfo } = require("@clusterio/lib"); // Adjust path based on compiled output -// Mock fetch function -global.fetch = async (url, options) => { - throw new Error(`fetch mock not implemented for ${url}`); -}; - const MODS_DIR = path.join("temp", "test", "mod_store", "mods"); const CACHE_FILE = path.join(MODS_DIR, "mod-info-cache.json"); @@ -49,6 +42,10 @@ describe("lib/ModStore", function () { await fs.ensureDir(MODS_DIR); }); + after(function() { + global.fetch = nativeFetch; + }); + beforeEach(function () { // Reset mocks before each test global.fetch = async (url, options) => {