forked from glutinum-org/cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSpecs.fs
207 lines (166 loc) · 6.61 KB
/
Specs.fs
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
207
module Build.Commands.Test.Specs
open BlackFox.CommandLine
open SimpleExec
open Build.Utils.Pnpm
open System.IO
open Spectre.Console.Cli
open System.ComponentModel
let private testFile (hiearchyLevel: int) (content: string) =
let generateFilePath =
[
for _ in 1..hiearchyLevel do
".."
"src"
"Glutinum.Converter"
"Generate.fs.js"
]
|> String.concat "/"
$"""
//------------------------------------------------------------------------------
// This code was generated by `./build.sh test specs`
// Changes to this file will be lost when the code is regenerated.
//------------------------------------------------------------------------------
import {{ expect, test }} from 'vitest'
import {{ generateBindingFile }} from '%s{generateFilePath}'
import {{ dirname }} from "dirname-filename-esm";
import path from 'node:path';
const __dirname = dirname(import.meta)
%s{content}
"""
let private generatedSpecsTestDestination = "tests/specs/generated/"
let private generateSpecsTestFile () =
// Ensure we start from a clean state
if Directory.Exists(generatedSpecsTestDestination) then
Directory.Delete(generatedSpecsTestDestination, true)
Directory.CreateDirectory(generatedSpecsTestDestination) |> ignore
let specFiles =
Directory.GetFiles(
"tests/specs/references",
"*.d.ts",
SearchOption.AllDirectories
)
specFiles
// Normalize the path
|> Seq.map _.Replace('\\', '/')
|> Seq.filter (fun file -> not (file.Contains("/disabled.")))
|> Seq.map _.Replace("tests/specs/references/", "")
// Group by folder
|> Seq.groupBy (fun specFile ->
if specFile.Split('/').Length <= 1 then
failwithf "Spec files should be inside a folder: %s" specFile
else
// Normalize the dir path
(Path.GetDirectoryName specFile).Replace('\\', '/')
)
|> Seq.iter (fun (folder, specFiles) ->
let destinationFolder = generatedSpecsTestDestination + folder
// Ensure destination folder exists
if not (Directory.Exists(destinationFolder)) then
Directory.CreateDirectory(destinationFolder) |> ignore
let hiearchyLevel = folder.Split('/').Length + 1
let tests =
specFiles
|> Seq.map (fun specFile ->
let testName = specFile.Replace(".d.ts", "")
let refereneFilePath =
[
for _ in 1..hiearchyLevel do
".."
"references"
specFile
]
|> String.concat "/"
let expectedFilePath =
refereneFilePath.Replace(".d.ts", ".fsx")
$"""test('%s{testName}', async () => {{
// Click the link below to go to the respective file
// Reference: file://./%s{refereneFilePath}
// Expected: file://./%s{expectedFilePath}
const filePath = path.join(__dirname, '%s{refereneFilePath}');
let result = generateBindingFile(filePath);
result += `
(***)
#r "nuget: Fable.Core"
(***)
`;
const expectedFile = filePath.split('.').slice(0, -2).join('.') + '.fsx'
await expect(result).toMatchFileSnapshot(expectedFile)
}})
"""
)
|> String.concat "\n"
File.WriteAllText(
destinationFolder + "/index.test.js",
testFile (hiearchyLevel + 2) tests
)
)
type SpecSettings() =
inherit CommandSettings()
[<CommandOption("-w|--watch")>]
[<Description("Watch for changes and re-run the tests
You can pass additional arguments to 'vitest' by using '--' followed by the arguments
For example:
./build.sh test specs --watch -- --ui
./build.sh test specs --watch -- -t date")>]
member val IsWatch: bool = false with get, set
[<CommandOption("--generate-only")>]
[<Description("Only generate the tests files based on the `references` folder
This is the preferred way to generate the tests files of
you want to use the Test Explorer UI from your IDE.
You need to combine this options with `--watch` if you want
Fable to watch for changes and re-generate the files.
IMPORTANT: When adding or removing a file from the `references` folder,
you need to re-run this command. (Will be improved in the future)")>]
member val GenerateOnly: bool = false with get, set
type SpecCommand() =
inherit Command<SpecSettings>()
interface ICommandLimiter<SpecSettings>
override _.Execute(context, settings) =
// We always need to generate the specs test files
generateSpecsTestFile ()
Pnpm.install ()
if settings.GenerateOnly then
let fableCmd =
CmdLine.empty
|> CmdLine.appendRaw "fable"
|> CmdLine.appendIf settings.IsWatch "watch"
|> CmdLine.appendRaw "src/Glutinum.Converter"
|> CmdLine.appendRaw "--sourceMaps"
|> CmdLine.appendRaw "--test:MSBuildCracker"
|> CmdLine.toString
Command.Run("dotnet", fableCmd)
0
else
let additionalArgs =
if settings.IsWatch then
let candidates =
context.Arguments
|> Seq.skipWhile (fun x -> x <> "--")
|> Seq.toList
if List.isEmpty candidates then
null
else
candidates |> List.skip 1 |> String.concat " "
else
"run"
let vitestCmd =
CmdLine.empty
|> CmdLine.appendRaw "npx"
|> CmdLine.appendRaw "vitest"
|> CmdLine.appendPrefix "--clearScreen" "false"
|> CmdLine.appendRaw additionalArgs
|> CmdLine.toString
let fableCmd =
CmdLine.empty
|> CmdLine.appendRaw "fable"
|> CmdLine.appendIf settings.IsWatch "watch"
|> CmdLine.appendRaw "../../src/Glutinum.Converter"
|> CmdLine.appendRaw "--sourceMaps"
|> CmdLine.appendRaw "--test:MSBuildCracker"
// Avoid strange logs because both Fable and Vitest rewrite the console
|> CmdLine.appendRaw "--verbose"
|> CmdLine.appendRaw "--run"
|> CmdLine.appendRaw vitestCmd
|> CmdLine.toString
Command.Run("dotnet", fableCmd, workingDirectory = "tests/specs")
0