Files
bun.sh/test/js/bun/globals.test.js
2024-09-03 21:32:52 -07:00

199 lines
6.0 KiB
JavaScript

import { describe, expect, it } from "bun:test";
import { bunEnv, bunExe } from "harness";
import path from "path";
it("ERR_INVALID_THIS", () => {
try {
Request.prototype.formData.call(undefined);
expect.unreachable();
} catch (e) {
expect(e.code).toBe("ERR_INVALID_THIS");
expect(e.name).toBe("TypeError");
expect(e.message).toBe("Expected this to be instanceof Request");
}
try {
Request.prototype.formData.call(null);
expect.unreachable();
} catch (e) {
expect(e.code).toBe("ERR_INVALID_THIS");
expect(e.name).toBe("TypeError");
expect(e.message).toBe("Expected this to be instanceof Request, but received null");
}
try {
Request.prototype.formData.call(new (class Boop {})());
expect.unreachable();
} catch (e) {
expect(e.code).toBe("ERR_INVALID_THIS");
expect(e.name).toBe("TypeError");
expect(e.message).toBe("Expected this to be instanceof Request, but received Boop");
}
try {
Request.prototype.formData.call("hellooo");
expect.unreachable();
} catch (e) {
expect(e.code).toBe("ERR_INVALID_THIS");
expect(e.name).toBe("TypeError");
expect(e.message).toBe("Expected this to be instanceof Request, but received a string");
}
});
it("extendable", () => {
const classes = [Blob, TextDecoder, TextEncoder, Request, Response, Headers, HTMLRewriter, Bun.Transpiler, Buffer];
for (let Class of classes) {
var Foo = class extends Class {};
var bar = Class === Request ? new Request({ url: "https://example.com" }) : new Foo();
expect(bar instanceof Class).toBe(true);
expect(!!Class.prototype).toBe(true);
expect(typeof Class.prototype).toBe("object");
}
expect(true).toBe(true);
});
it("writable", () => {
const classes = [
["TextDecoder", TextDecoder],
["Request", Request],
["Response", Response],
["Headers", Headers],
["Buffer", Buffer],
["Event", Event],
["DOMException", DOMException],
["EventTarget", EventTarget],
["ErrorEvent", ErrorEvent],
["CustomEvent", CustomEvent],
["CloseEvent", CloseEvent],
["File", File],
];
for (let [name, Class] of classes) {
globalThis[name] = 123;
expect(globalThis[name]).toBe(123);
globalThis[name] = Class;
expect(globalThis[name]).toBe(Class);
}
});
it("name", () => {
const classes = [
["Blob", Blob],
["TextDecoder", TextDecoder],
["TextEncoder", TextEncoder],
["Request", Request],
["Response", Response],
["Headers", Headers],
["HTMLRewriter", HTMLRewriter],
["Transpiler", Bun.Transpiler],
["Buffer", Buffer],
["File", File],
];
for (let [name, Class] of classes) {
expect(Class.name).toBe(name);
}
});
describe("File", () => {
it("constructor", () => {
const file = new File(["foo"], "bar.txt", { type: "text/plain;charset=utf-8" });
expect(file.name).toBe("bar.txt");
expect(file.type).toBe("text/plain;charset=utf-8");
expect(file.size).toBe(3);
expect(file.lastModified).toBeGreaterThan(0);
});
it("constructor with lastModified", () => {
const file = new File(["foo"], "bar.txt", { type: "text/plain;charset=utf-8", lastModified: 123 });
expect(file.name).toBe("bar.txt");
expect(file.type).toBe("text/plain;charset=utf-8");
expect(file.size).toBe(3);
expect(file.lastModified).toBe(123);
});
it("constructor with undefined name", () => {
const file = new File(["foo"], undefined);
expect(file.name).toBe("undefined");
expect(file.type).toBe("");
expect(file.size).toBe(3);
expect(file.lastModified).toBeGreaterThan(0);
});
it("constructor throws invalid args", () => {
const invalid = [[], [undefined], [null], [Symbol(), "foo"], [Symbol(), Symbol(), Symbol()]];
for (let args of invalid) {
expect(() => new File(...args)).toThrow();
}
});
it("constructor without new", () => {
const result = () => File();
expect(result).toThrow({
name: "TypeError",
message: "Class constructor File cannot be invoked without 'new'",
});
});
it("instanceof", () => {
const file = new File(["foo"], "bar.txt", { type: "text/plain;charset=utf-8" });
expect(file instanceof File).toBe(true);
expect(file instanceof Blob).toBe(true);
expect(file instanceof Object).toBe(true);
expect(file instanceof Function).toBe(false);
const blob = new Blob(["foo"], { type: "text/plain;charset=utf-8" });
expect(blob instanceof File).toBe(false);
});
it("extendable", async () => {
class Foo extends File {
constructor(...args) {
super(...args);
}
bar() {
return true;
}
text() {
return super.text();
}
}
const foo = new Foo(["foo"], "bar.txt", { type: "text/plain;charset=utf-8" });
expect(foo instanceof File).toBe(true);
expect(foo instanceof Blob).toBe(true);
expect(foo instanceof Object).toBe(true);
expect(foo instanceof Function).toBe(false);
expect(foo instanceof Foo).toBe(true);
expect(foo.bar()).toBe(true);
expect(foo.name).toBe("bar.txt");
expect(foo.type).toBe("text/plain;charset=utf-8");
expect(foo.size).toBe(3);
expect(foo.lastModified).toBeGreaterThanOrEqual(0);
expect(await foo.text()).toBe("foo");
});
});
it("globals are deletable", () => {
const { stdout, exitCode } = Bun.spawnSync({
cmd: [bunExe(), "run", path.join(import.meta.dir, "deletable-globals-fixture.js")],
env: bunEnv,
stderr: "inherit",
});
expect(stdout.toString().trim().endsWith("--pass--")).toBe(true);
expect(exitCode).toBe(0);
});
it("self is a getter", () => {
const descriptor = Object.getOwnPropertyDescriptor(globalThis, "self");
expect(descriptor.get).toBeInstanceOf(Function);
expect(descriptor.set).toBeInstanceOf(Function);
expect(descriptor.enumerable).toBe(true);
expect(descriptor.configurable).toBe(true);
expect(globalThis.self).toBe(globalThis);
});
it("errors thrown by native code should be TypeError", async () => {
expect(() => Bun.dns.prefetch()).toThrowError(TypeError);
expect(async () => await fetch("http://localhost", { body: "123" })).toThrowError(TypeError);
});