-
-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathdev_server_test.exs
More file actions
206 lines (171 loc) · 6.73 KB
/
Copy pathdev_server_test.exs
File metadata and controls
206 lines (171 loc) · 6.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
defmodule Volt.DevServerTest do
use ExUnit.Case, async: false
import Plug.Test
import Plug.Conn
@fixture_dir Path.expand("fixtures", __DIR__)
setup do
File.mkdir_p!(Path.join(@fixture_dir, "src"))
File.write!(Path.join(@fixture_dir, "src/app.ts"), "const x: number = 42")
File.write!(Path.join(@fixture_dir, "src/style.css"), ".foo { color: red }")
File.write!(Path.join(@fixture_dir, "src/App.vue"), """
<template><div>{{ msg }}</div></template>
<script setup>const msg = 'hi'</script>
""")
Volt.Cache.clear()
on_exit(fn -> File.rm_rf!(@fixture_dir) end)
:ok
end
defp call_dev_server(path, opts \\ []) do
init_opts =
Keyword.merge(
[root: Path.join(@fixture_dir, "src"), prefix: "/assets"],
opts
)
opts = Volt.DevServer.init(init_opts)
conn(:get, path) |> Volt.DevServer.call(opts)
end
describe "TypeScript files" do
test "serves compiled TypeScript" do
conn = call_dev_server("/assets/app.ts")
assert conn.status == 200
assert conn.resp_body =~ "const x = 42"
assert get_resp_header(conn, "content-type") |> hd() =~ "javascript"
end
test "includes inline sourcemap" do
conn = call_dev_server("/assets/app.ts")
assert conn.resp_body =~ "sourceMappingURL=data:application/json;base64,"
end
end
describe "Vue SFCs" do
test "serves compiled Vue SFC" do
conn = call_dev_server("/assets/App.vue")
assert conn.status == 200
assert conn.resp_body =~ "msg"
end
end
describe "CSS files" do
test "serves CSS with correct content type" do
conn = call_dev_server("/assets/style.css")
assert conn.status == 200
assert conn.resp_body =~ "color"
assert get_resp_header(conn, "content-type") |> hd() =~ "text/css"
end
test "serves CSS imports as JavaScript modules" do
conn = call_dev_server("/assets/style.css?import")
assert conn.status == 200
assert conn.resp_body =~ "__volt_updateStyle"
assert conn.resp_body =~ "color"
assert get_resp_header(conn, "content-type") |> hd() =~ "javascript"
end
test "serves CSS import requests with cache-busting params as JavaScript modules" do
conn = call_dev_server("/assets/style.css?import&t=123")
assert conn.status == 200
assert conn.resp_body =~ "__volt_updateStyle"
assert get_resp_header(conn, "content-type") |> hd() =~ "javascript"
end
test "serves raw CSS and CSS import modules from separate cache entries" do
import_conn = call_dev_server("/assets/style.css?import")
raw_conn = call_dev_server("/assets/style.css")
assert import_conn.resp_body =~ "__volt_updateStyle"
assert get_resp_header(import_conn, "content-type") |> hd() =~ "javascript"
assert raw_conn.resp_body =~ "color: red"
refute raw_conn.resp_body =~ "__volt_updateStyle"
assert get_resp_header(raw_conn, "content-type") |> hd() =~ "text/css"
end
test "serves CSS modules imported from JavaScript with styles and exports" do
File.write!(Path.join(@fixture_dir, "src/button.module.css"), ".btn { color: red }")
conn = call_dev_server("/assets/button.module.css?import")
assert conn.status == 200
assert conn.resp_body =~ "__volt_updateStyle"
assert conn.resp_body =~ "color: red"
assert conn.resp_body =~ "export default"
assert get_resp_header(conn, "content-type") |> hd() =~ "javascript"
end
test "serves CSS modules as JavaScript even without import query" do
File.write!(Path.join(@fixture_dir, "src/button.module.css"), ".btn { color: red }")
conn = call_dev_server("/assets/button.module.css")
assert conn.status == 200
assert conn.resp_body =~ "__volt_updateStyle"
assert conn.resp_body =~ "export default"
assert get_resp_header(conn, "content-type") |> hd() =~ "javascript"
end
end
describe "caching" do
test "serves from cache on second request" do
call_dev_server("/assets/app.ts")
conn = call_dev_server("/assets/app.ts")
assert conn.status == 200
assert conn.resp_body =~ "const x = 42"
end
end
describe "non-matching paths" do
test "passes through non-matching prefix" do
conn = call_dev_server("/other/app.ts")
refute conn.halted
end
test "serves static assets with correct MIME type" do
File.write!(Path.join(@fixture_dir, "src/image.png"), "binary")
conn = call_dev_server("/assets/image.png")
assert conn.status == 200
assert get_resp_header(conn, "content-type") |> hd() =~ "image/png"
end
test "passes through unknown extensions" do
File.write!(Path.join(@fixture_dir, "src/data.xyz"), "binary")
conn = call_dev_server("/assets/data.xyz")
refute conn.halted
end
test "passes through missing files" do
conn = call_dev_server("/assets/missing.ts")
refute conn.halted
end
end
describe "error handling" do
test "returns 500 with error overlay for invalid source" do
File.write!(Path.join(@fixture_dir, "src/bad.ts"), "const = ;")
conn = call_dev_server("/assets/bad.ts")
assert conn.status == 500
assert conn.resp_body =~ "[Volt] Compilation error"
end
end
describe "import rewriting" do
test "rewrites relative imports to absolute paths" do
File.write!(Path.join(@fixture_dir, "src/utils.ts"), "export const y = 1")
File.write!(Path.join(@fixture_dir, "src/entry.ts"), """
import { y } from './utils'
console.log(y)
""")
conn = call_dev_server("/assets/entry.ts")
assert conn.status == 200
assert conn.resp_body =~ "/assets/utils.ts"
refute conn.resp_body =~ "'./utils'"
end
test "rewrites CSS imports to import-mode URLs" do
File.write!(Path.join(@fixture_dir, "src/entry.ts"), "import './style.css'")
conn = call_dev_server("/assets/entry.ts")
assert conn.status == 200
assert conn.resp_body =~ "/assets/style.css?import"
refute conn.resp_body =~ "'./style.css'"
end
test "rewrites bare imports to vendor URLs" do
File.write!(Path.join(@fixture_dir, "src/vue_app.ts"), """
import { ref } from 'vue'
ref(0)
""")
conn = call_dev_server("/assets/vue_app.ts")
assert conn.status == 200
assert conn.resp_body =~ "/@vendor/vue.js"
refute conn.resp_body =~ "'vue'"
end
end
describe "HMR preamble" do
test "injects import.meta.hot into JS modules" do
conn = call_dev_server("/assets/app.ts")
assert conn.resp_body =~ "import.meta.hot"
assert conn.resp_body =~ "createHotContext"
end
test "does not inject HMR preamble into CSS" do
conn = call_dev_server("/assets/style.css")
refute conn.resp_body =~ "import.meta.hot"
end
end
end