import { describe, it, expect } from "bun:test";
import { gcTick } from "./gc";
var setTimeoutAsync = (fn, delay) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
try {
resolve(fn());
} catch (e) {
reject(e);
}
}, delay);
});
};
describe("HTMLRewriter", () => {
it("HTMLRewriter: async replacement", async () => {
await gcTick();
const res = new HTMLRewriter()
.on("div", {
async element(element) {
await setTimeoutAsync(() => {
element.setInnerContent("replace ", { html: true });
}, 5);
},
})
.transform(new Response("
example.com
"));
await gcTick();
expect(await res.text()).toBe("replace
");
await gcTick();
});
it("supports element handlers", async () => {
var rewriter = new HTMLRewriter();
rewriter.on("div", {
element(element) {
element.setInnerContent("it worked! ", { html: true });
},
});
var input = new Response("hello
");
var output = rewriter.transform(input);
expect(await output.text()).toBe("it worked!
");
});
it("(from file) supports element handlers", async () => {
var rewriter = new HTMLRewriter();
rewriter.on("div", {
element(element) {
element.setInnerContent("it worked! ", { html: true });
},
});
await Bun.write("/tmp/html-rewriter.txt.js", "hello
");
var input = new Response(Bun.file("/tmp/html-rewriter.txt.js"));
var output = rewriter.transform(input);
expect(await output.text()).toBe("it worked!
");
});
it("supports attribute iterator", async () => {
var rewriter = new HTMLRewriter();
var expected = [
["first", ""],
["second", "alrihgt"],
["third", "123"],
["fourth", "5"],
["fifth", "helloooo"],
];
rewriter.on("div", {
element(element2) {
for (let attr of element2.attributes) {
const stack = expected.shift();
expect(stack[0]).toBe(attr[0]);
expect(stack[1]).toBe(attr[1]);
}
},
});
var input = new Response(
'hello
'
);
var output = rewriter.transform(input);
expect(await output.text()).toBe(
'hello
'
);
expect(expected.length).toBe(0);
});
it("handles element specific mutations", async () => {
// prepend/append
let res = new HTMLRewriter()
.on("p", {
element(element) {
element.prepend("prepend ");
element.prepend("prepend html ", { html: true });
element.append("append ");
element.append("append html ", { html: true });
},
})
.transform(new Response("test
"));
expect(await res.text()).toBe(
[
"",
"prepend html ",
"<span>prepend</span>",
"test",
"<span>append</span>",
"append html ",
"
",
].join("")
);
// setInnerContent
res = new HTMLRewriter()
.on("p", {
element(element) {
element.setInnerContent("replace ");
},
})
.transform(new Response("test
"));
expect(await res.text()).toBe("<span>replace</span>
");
res = new HTMLRewriter()
.on("p", {
element(element) {
element.setInnerContent("replace ", { html: true });
},
})
.transform(new Response("test
"));
expect(await res.text()).toBe("replace
");
// removeAndKeepContent
res = new HTMLRewriter()
.on("p", {
element(element) {
element.removeAndKeepContent();
},
})
.transform(new Response("test
"));
expect(await res.text()).toBe("test");
});
it("handles element class properties", async () => {
class Handler {
constructor(content) {
this.content = content;
}
// noinspection JSUnusedGlobalSymbols
element(element) {
element.setInnerContent(this.content);
}
}
const res = new HTMLRewriter()
.on("p", new Handler("new"))
.transform(new Response("test
"));
expect(await res.text()).toBe("new
");
});
const commentsMutationsInput = "
";
const commentsMutationsExpected = {
beforeAfter: [
"",
"<span>before</span>",
"before html ",
"",
"after html ",
"<span>after</span>",
"
",
].join(""),
replace: "<span>replace</span>
",
replaceHtml: "replace
",
remove: "
",
};
const commentPropertiesMacro = async (func) => {
const res = func(new HTMLRewriter(), (comment) => {
expect(comment.removed).toBe(false);
expect(comment.text).toBe("test");
comment.text = "new";
expect(comment.text).toBe("new");
}).transform(new Response("
"));
expect(await res.text()).toBe("
");
};
it("HTMLRewriter: handles comment properties", () =>
commentPropertiesMacro((rw, comments) => {
rw.on("p", { comments });
return rw;
}));
it("selector tests", async () => {
const checkSelector = async (selector, input, expected) => {
const res = new HTMLRewriter()
.on(selector, {
element(element) {
element.setInnerContent("new");
},
})
.transform(new Response(input));
expect(await res.text()).toBe(expected);
};
await checkSelector("*", "1 2
", "new new
");
await checkSelector("p", "1 2
", "1 new
");
await checkSelector(
"p:nth-child(2)",
"",
""
);
await checkSelector(
"p:first-child",
"",
""
);
await checkSelector(
"p:nth-of-type(2)",
"",
""
);
await checkSelector(
"p:first-of-type",
"",
""
);
await checkSelector(
"p:not(:first-child)",
"",
""
);
await checkSelector(
"p.red",
'1
2
',
'new
2
'
);
await checkSelector(
"h1#header",
'2 ',
'2 '
);
await checkSelector(
"p[data-test]",
"1
2
",
"new
2
"
);
await checkSelector(
'p[data-test="one"]',
'1
2
',
'new
2
'
);
await checkSelector(
'p[data-test="one" i]',
'1
2
3
',
'new
new
3
'
);
await checkSelector(
'p[data-test="one" s]',
'1
2
3
',
'new
2
3
'
);
await checkSelector(
'p[data-test~="two"]',
'1
2
3
',
'new
new
3
'
);
await checkSelector(
'p[data-test^="a"]',
'1
2
3
',
'new
new
3
'
);
await checkSelector(
'p[data-test$="1"]',
'1
2
3
',
'new
2
new
'
);
await checkSelector(
'p[data-test*="b"]',
'1
2
3
',
'new
new
3
'
);
await checkSelector(
'p[data-test|="a"]',
'1
2
3
',
'new
new
3
'
);
await checkSelector(
"div span",
"
1 2 3 ",
"
new new 3 "
);
await checkSelector(
"div > span",
"
1 2 3 ",
"
1 new 3 "
);
});
});
jarred/precompile-linux-dependencies
jarred/prepare-for-libuv
jarred/profiled-call
jarred/read-tsconfig-jsx
jarred/redo-evaluation-order
jarred/redo-zigstring-for-utf16
jarred/relay
jarred/rename
jarred/repl
jarred/request-finalizer
jarred/rewrite-router
jarred/run
jarred/simdjson
jarred/simplify
jarred/some-fixes-for-eventsource
jarred/standalone-repro1
jarred/start
jarred/strong
jarred/subprocess
jarred/support-tee
jarred/tcc
jarred/throw-if
jarred/update-install-stuff
jarred/update-zig1
jarred/upgrade-zig-2
jarred/uws
jarred/webkit-upgrade-may-17
jarred/wip-more-reliable
jarred/workers
jarred/zlib
jarred/zls
lithdew/picohttp-mimalloc
main
move-templates
nestjs-guide
next-cleanup
origin/main
plugin/plugindata
plugin/resolvedir
postinstall_3
repl
request-body-stream
reserve-commands
revert-5167-dylan/decode-regex-if-needed
rfc/bun-bundler-api
rfc/bunfig-overhaul
save-in-update
sdl
test/action
types/mock
types/readable-stream-default
types/tty
u/vjpr/zig-0.10
xHyroM/types/expose-Bun-Env
Unnamed repository; edit this file 'description' to name the repository.
Age Commit message (Collapse ) Author Files Lines
* really lame prototype
* uses threads but badly
* it works i guess
* unwatchFile but lame
* it works
* test
* a
* aomitcs
* fix unwatching race condition
* use hasPendingActivity and GC stuff better
* test
* revert this
* emit close event on connection error
* re-review
* add test
* always use readable stream if it is available
* use bun sleep
* fix tests
* rm uws dep
* padding sucks
* this assertion is already done elsewhere
* remove test. will be covered alex's pr i believe?
* fix webkit submodule
* fix uws submodule
* `node` null for localhost getaddrinfo
* more test
* fix zlib deflate on fetch
* mention issue on test
* more tests
* oops
Close: #4377
* html rewriter response buffering
* pipe the data when marked as used
* fix empty response
* add some fetch tests
* deinit parent stream
* fix decompression
* keep byte_reader alive
* update builds
* remove nonsense
* was not nonsense after all
* protect tmp ret value from GC, fix readable strong ref deinit/init
* fmt
* if we detach the stream we cannot update the fetch stream
* detach checking source
* more tests, progress with javascript and Direct sink
* drop support for pure readable stream for now
* more fixes
---------
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
* fix(syscall): fix handling syscall errno
Close: #4198
* remove unused code
* add more tests
* remove unused code
Co-authored-by: Karl Böhlmark <karl.bohlmark@netinsight.net>
Replace
`key: [Bun.file('./key1.pem'), Bun.file('./key2.pem']`
with
`key: [Bun.file('./key1.pem'), Bun.file('./key2.pem')]`
* check sendfile ctx
* add test
* undo blob check
* undo undo and add assert
* fix incorrect c pointer
* format
* lets go
* random other test case fixed
* hanassagi patch
* Update dns_resolver.zig
* Revert "Update dns_resolver.zig"
This reverts commit 53eb338048583a338e7c01d2b351f1c679db3e15.
* See if the tests pass
---------
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
* yippee
* enable cpSync tests
* much better
* that doesnt actually do anything
* lose
* unset `set_breakpoint_on_first_line` on reload
* move to `module_loader.zig`
* use WTF to join registry strings
* show dependency error messages, better join error
We actually report errors when enqueuing dependencies now. I also made
the join URLs error message read better. It'd be cleaner to handle it
all in one place, but there's currently no way to propagate the data up.
* starting on registry URL tests
* added more registry URL tests
* [install] prevent optional/peer deps from failing builds
Couldn't get the peer dependency test to work, but the code is there.
* ran prettier
* changed error note to use realname, updated tests
* ran prettier again...
* get file name from blob if not provided
* add test
* another test
* format