1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial
3
4use std::error::Error;
5use std::{fs::File, io::Write, path::PathBuf};
6
7#[track_caller]
8fn check_output(o: std::process::Output) {
9 if !o.status.success() {
10 eprintln!(
11 "STDERR:\n{}\nSTDOUT:\n{}",
12 String::from_utf8_lossy(&o.stderr),
13 String::from_utf8_lossy(&o.stdout),
14 );
15 //panic!("Build Failed {:?}", o.status);
16 }
17}
18
19lazy_static::lazy_static! {
20 static ref NODE_API_JS_PATH: PathBuf = {
21 let node_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../../api/node");
22
23 // On Windows npm is 'npm.cmd', which Rust's process::Command doesn't look for as extension, because
24 // it tries to emulate CreateProcess.
25 let npm = which::which("npm").unwrap();
26
27 // installs the slint node package dependencies
28 let o = std::process::Command::new(npm.clone())
29 .arg("install")
30 .arg("--no-audit")
31 .arg("--ignore-scripts")
32 .current_dir(node_dir.clone())
33 .stdout(std::process::Stdio::piped())
34 .stderr(std::process::Stdio::piped())
35 .output()
36 .map_err(|err| format!("Could not launch npm install: {}", err)).unwrap();
37
38 check_output(o);
39
40 // builds the slint node package in debug
41 let o = std::process::Command::new(npm.clone())
42 .arg("run")
43 .arg("build:debug")
44 .current_dir(node_dir.clone())
45 .stdout(std::process::Stdio::piped())
46 .stderr(std::process::Stdio::piped())
47 .output()
48 .map_err(|err| format!("Could not launch npm install: {}", err)).unwrap();
49
50 check_output(o);
51
52 node_dir.join("index.js")
53 };
54}
55
56pub fn test(testcase: &test_driver_lib::TestCase) -> Result<(), Box<dyn Error>> {
57 let slintpath = NODE_API_JS_PATH.clone();
58
59 let dir = tempfile::tempdir()?;
60
61 let mut main_js = File::create(dir.path().join("main.js"))?;
62 write!(
63 main_js,
64 r#"
65 const assert = require('assert').strict;
66 let slintlib = require(String.raw`{slintpath}`);
67 let slint = slintlib.loadFile(String.raw`{path}`);
68 "#,
69 slintpath = slintpath.to_string_lossy(),
70 path = testcase.absolute_path.to_string_lossy()
71 )?;
72 let source = std::fs::read_to_string(&testcase.absolute_path)?;
73 let include_paths = test_driver_lib::extract_include_paths(&source);
74 let library_paths = test_driver_lib::extract_library_paths(&source)
75 .map(|(k, v)| {
76 let mut abs_path = testcase.absolute_path.clone();
77 abs_path.pop();
78 abs_path.push(v);
79 format!("{}={}", k, abs_path.to_string_lossy())
80 })
81 .collect::<Vec<_>>();
82 for x in test_driver_lib::extract_test_functions(&source).filter(|x| x.language_id == "js") {
83 write!(main_js, "{{\n {}\n}}\n", x.source.replace("\n", "\n "))?;
84 }
85
86 let output = std::process::Command::new("node")
87 .arg(dir.path().join("main.js"))
88 .current_dir(dir.path())
89 .env("SLINT_INCLUDE_PATH", std::env::join_paths(include_paths).unwrap())
90 .env("SLINT_LIBRARY_PATH", std::env::join_paths(library_paths).unwrap())
91 .env("SLINT_SCALE_FACTOR", "1") // We don't have a testing backend, but we can try to force a SF1 as the tests expect.
92 .env("SLINT_ENABLE_EXPERIMENTAL_FEATURES", "1")
93 .stdout(std::process::Stdio::piped())
94 .stderr(std::process::Stdio::piped())
95 .output()
96 .map_err(|err| format!("Could not launch npm start: {}", err))?;
97
98 if !output.status.success() {
99 print!("{}", String::from_utf8_lossy(output.stdout.as_ref()));
100 print!("{}", String::from_utf8_lossy(output.stderr.as_ref()));
101 return Err(String::from_utf8_lossy(output.stderr.as_ref()).to_owned().into());
102 }
103
104 Ok(())
105}
106