1use crate::{assert_js, assert_module_error, assert_ts_def};
2
3#[test]
4fn type_() {
5 assert_js!(r#"pub type Thing"#,);
6}
7
8#[test]
9fn module_fn() {
10 assert_js!(
11 r#"
12@external(javascript, "utils", "inspect")
13fn show(x: anything) -> Nil"#,
14 );
15}
16
17#[test]
18fn at_namespace_module() {
19 assert_js!(
20 r#"
21@external(javascript, "@namespace/package", "inspect")
22fn show(x: anything) -> Nil"#,
23 );
24}
25
26#[test]
27fn pub_module_fn() {
28 assert_js!(
29 r#"
30@external(javascript, "utils", "inspect")
31pub fn show(x: anything) -> Nil"#,
32 );
33}
34
35#[test]
36fn pub_module_fn_typescript() {
37 assert_ts_def!(
38 r#"
39@external(javascript, "utils", "inspect")
40pub fn show(x: anything) -> Nil"#,
41 );
42}
43
44#[test]
45fn same_name_external() {
46 assert_js!(
47 r#"
48@external(javascript, "thingy", "fetch")
49pub fn fetch(request: Nil) -> Nil"#,
50 );
51}
52
53#[test]
54fn same_module_multiple_imports() {
55 assert_js!(
56 r#"
57@external(javascript, "./the/module.mjs", "one")
58pub fn one() -> Nil
59
60@external(javascript, "./the/module.mjs", "two")
61pub fn two() -> Nil
62"#,
63 );
64}
65
66#[test]
67fn duplicate_import() {
68 assert_js!(
69 r#"
70@external(javascript, "./the/module.mjs", "dup")
71pub fn one() -> Nil
72
73@external(javascript, "./the/module.mjs", "dup")
74pub fn two() -> Nil
75"#,
76 );
77}
78
79#[test]
80fn name_to_escape() {
81 assert_js!(
82 r#"
83@external(javascript, "./the/module.mjs", "one")
84pub fn class() -> Nil
85"#,
86 );
87}
88
89#[test]
90fn external_type_typescript() {
91 assert_ts_def!(
92 r#"pub type Queue(a)
93
94@external(javascript, "queue", "new")
95pub fn new() -> Queue(a)
96"#,
97 );
98}
99
100// https://github.com/gleam-lang/gleam/issues/1636
101#[test]
102fn external_fn_escaping() {
103 assert_js!(
104 r#"
105@external(javascript, "./ffi.js", "then")
106pub fn then(a: a) -> b"#,
107 );
108}
109
110// https://github.com/gleam-lang/gleam/issues/1954
111#[test]
112fn pipe_variable_shadow() {
113 assert_js!(
114 r#"
115@external(javascript, "module", "string")
116fn name() -> String
117
118pub fn main() {
119 let name = name()
120 name
121}
122"#
123 );
124}
125
126// https://github.com/gleam-lang/gleam/issues/2090
127#[test]
128fn tf_type_name_usage() {
129 assert_ts_def!(
130 r#"
131pub type TESTitem
132
133@external(javascript, "it", "one")
134pub fn one(a: TESTitem) -> TESTitem
135"#
136 );
137}
138
139#[test]
140fn attribute_erlang() {
141 assert_js!(
142 r#"
143@external(erlang, "one", "one_erl")
144pub fn one(x: Int) -> Int {
145 todo
146}
147
148pub fn main() {
149 one(1)
150}
151"#
152 );
153}
154
155#[test]
156fn attribute_javascript() {
157 assert_js!(
158 r#"
159@external(javascript, "./one.mjs", "oneJs")
160pub fn one(x: Int) -> Int {
161 todo
162}
163
164pub fn main() {
165 one(1)
166}
167"#
168 );
169}
170
171#[test]
172fn erlang_and_javascript() {
173 assert_js!(
174 r#"
175@external(erlang, "one", "one")
176@external(javascript, "./one.mjs", "oneJs")
177pub fn one(x: Int) -> Int {
178 todo
179}
180
181pub fn main() {
182 one(1)
183}
184"#
185 );
186}
187
188#[test]
189fn private_attribute_erlang() {
190 assert_js!(
191 r#"
192@external(erlang, "one", "one_erl")
193fn one(x: Int) -> Int {
194 todo
195}
196
197pub fn main() {
198 one(1)
199}
200"#
201 );
202}
203
204#[test]
205fn private_attribute_javascript() {
206 assert_js!(
207 r#"
208@external(javascript, "./one.mjs", "oneJs")
209fn one(x: Int) -> Int {
210 todo
211}
212
213pub fn main() {
214 one(1)
215}
216"#
217 );
218}
219
220#[test]
221fn private_erlang_and_javascript() {
222 assert_js!(
223 r#"
224@external(erlang, "one", "one")
225@external(javascript, "./one.mjs", "oneJs")
226fn one(x: Int) -> Int {
227 todo
228}
229
230pub fn main() {
231 one(1)
232}
233"#
234 );
235}
236
237#[test]
238fn no_body() {
239 assert_js!(
240 r#"
241@external(javascript, "one", "one")
242pub fn one(x: Int) -> Int
243"#
244 );
245}
246
247#[test]
248fn no_module() {
249 assert_module_error!(
250 r#"
251@external(javascript, "", "one")
252pub fn one(x: Int) -> Int {
253 1
254}
255"#
256 );
257}
258
259#[test]
260fn inline_function() {
261 assert_module_error!(
262 r#"
263@external(javascript, "blah", "(x => x)")
264pub fn one(x: Int) -> Int {
265 1
266}
267"#
268 );
269}
270
271#[test]
272fn erlang_only() {
273 assert_js!(
274 r#"
275pub fn should_be_generated(x: Int) -> Int {
276 x
277}
278
279@external(erlang, "one", "one")
280pub fn should_not_be_generated(x: Int) -> Int
281"#
282 );
283}
284
285#[test]
286fn both_externals_no_valid_impl() {
287 assert_js!(
288 r#"
289@external(javascript, "one", "one")
290pub fn js() -> Nil
291
292@external(erlang, "one", "one")
293pub fn erl() -> Nil
294
295pub fn should_not_be_generated() {
296 js()
297 erl()
298}
299"#
300 );
301}
302
303#[test]
304fn discarded_names_in_external_are_passed_correctly() {
305 assert_js!(
306 r#"
307@external(javascript, "wibble", "wobble")
308pub fn woo(_ignored: a) -> Nil
309"#
310 );
311}