• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

source-academy / js-slang / 19080105112

04 Nov 2025 07:13PM UTC coverage: 76.655% (-1.5%) from 78.192%
19080105112

push

github

web-flow
Migrate to Vitest (#1815)

* Upgrade TS to 5.8

* Remove deprecated tsconfig option

* Remove duplicate properties

* Upgrade TS to v5.9

* Add types for mathjs

* Fix some type errors

* Update tsconfig

* Fix more type errors

* Fix remaining errors

* Update GitHub workflows

* Fix type error

* Update scm-slang to latest

* Add newline to EOF

* Fix cse-machine types and utils to use fewer type assertions

* Migrate to vitest tests

* Migrate tests to vitest

* Relocate base error files and types

* Get modules tests working

* run format

* Sort tsconfig compiler options

* Update eslint packages to match typescript version

* Small linting change

* Use function names instead of strings for describe blocks

* Include scripts in linting

* Move tests and replace describe titles with functions

* Add type modifiers and reformat tests

* Simplify isEnvDependent code

* Instruct tsc to ignore py-slang's tests during build

* Move walkers to be under utils/ast

* Update tests failing due to timeout

* Update cse-machine typings

* Incorporate import assertions into docs importer

* Add context property to error result

* Update test timeout and add no-restricted-import rule for commander imports

* Update snapshots

* Run format

* Update snapshots again....

* Run format

* Change to use the test.each

* Disable the svmc snapshot test cause it doesn't work

* Add a new test for properties when loading modules

* Run format

* Convert stdlib parser to use nodetypetonode helper type

* A working version of the statementSeqTransform

* More compact version of seq transform

* Remove unnecessary type assertions

* Clean up some documentation bits and pieces

* Use type imports for tracer

* Swap the list library to use generics

* Fix some error messages and tests

* Fix list tests

* Run format

* Update stream library and tests

* Running format

* Add some documentation for the scripts

* Remove unnecessary packages

* Remove even more unnecessary ty... (continued)

3501 of 4761 branches covered (73.53%)

Branch coverage included in aggregate %.

429 of 636 new or added lines in 54 files covered. (67.45%)

34 existing lines in 12 files now uncovered.

7085 of 9049 relevant lines covered (78.3%)

193248.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

66.67
/src/utils/testing/misc.ts
1
import { describe, expect, test, type TestContext as VitestTestContext } from 'vitest'
2
import type { Result } from '../..'
3
import type { Finished, Value, Node, NodeTypeToNode } from '../../types'
4
import { Chapter } from '../../langs'
5
import { getChapterName } from '../misc'
6
import type { TestBuiltins, TestOptions } from './types'
7

8
/**
9
 * Convert the options provided by the user for each test into the full options
10
 * used by the testing system
11
 */
12
export function processTestOptions(rawOptions: TestOptions): Exclude<TestOptions, Chapter> {
13
  return typeof rawOptions === 'number'
808✔
14
    ? {
15
        chapter: rawOptions
16
      }
17
    : rawOptions
18
}
19

20
/**
21
 * Utility type for removing the `this` parameter from a function's type
22
 */
23
type RemoveThis<T extends (this: any, ...args: any[]) => any> = T extends (
24
  this: any,
25
  ...args: infer U
26
) => any
27
  ? U
28
  : Parameters<T>
29

30
interface FuncWithSkipAndOnly<T extends (...args: any[]) => any> {
31
  (...args: RemoveThis<T>): ReturnType<T>
32
  skip: (...args: RemoveThis<T>) => ReturnType<T>
33
  only: (...args: RemoveThis<T>) => ReturnType<T>
34
}
35

36
/**
37
 * Refers to the three `describe` operations
38
 */
39
export type DescribeFunctions =
40
  | typeof describe
41
  | (typeof describe)['only']
42
  | (typeof describe)['skip']
43

44
/**
45
 * Refers to the three `test` operations
46
 */
47
export type TestFunctions = typeof test | (typeof test)['only'] | (typeof test)['skip']
48

49
/**
50
 * For functions that are designed to wrap around a `describe` or `test` block. Adds the `.only` and `.skip`
51
 * properties to them. The wrapped functions should use the `this` object to access the `test` or `describe` function
52
 * they are supposed to call.
53
 */
54
export function wrapWithSkipAndOnly<T extends (this: DescribeFunctions, ...args: any[]) => any>(
55
  type: 'describe',
56
  f: T
57
): FuncWithSkipAndOnly<T>
58
export function wrapWithSkipAndOnly<T extends (this: TestFunctions, ...args: any[]) => any>(
59
  type: 'test',
60
  f: T
61
): FuncWithSkipAndOnly<T>
62
export function wrapWithSkipAndOnly<
63
  T extends (this: TestFunctions | DescribeFunctions, ...args: any[]) => any
64
>(type: 'test' | 'describe', f: T) {
65
  function func(...args: Parameters<T>): ReturnType<T> {
66
    return f.call(type === 'test' ? test : describe, ...args)
6!
67
  }
68

69
  func.skip = (...args: Parameters<T>) => {
36✔
NEW
70
    return f.call((type === 'test' ? test : describe).skip, ...args)
×
71
  }
72

73
  func.only = (...args: Parameters<T>) => {
36✔
NEW
74
    return f.call((type === 'test' ? test : describe).only, ...args)
×
75
  }
76

77
  return func as FuncWithSkipAndOnly<T>
36✔
78
}
79

80
/**
81
 * Asserts that the given value is true
82
 */
83
export function assertTruthy(cond: boolean): asserts cond {
84
  expect(cond).toBeTruthy()
18✔
85
}
86

87
/**
88
 * Convenience wrapper for testing multiple cases with the same
89
 * test function
90
 */
91
export const testMultipleCases = wrapWithSkipAndOnly('test', function <
35✔
92
  T extends Array<any>
93
>(this: TestFunctions, cases: [string, ...T][], tester: (args: T, i: number) => void | Promise<void>, includeIndex?: boolean, timeout?: number) {
94
  const withIndex = cases.map(([desc, ...c], i) => {
×
95
    const newDesc = includeIndex ? `${i + 1}. ${desc}` : desc
×
96
    return [newDesc, i, ...c] as [string, number, ...T]
×
97
  })
NEW
98
  this.each(withIndex)('%s', (_, i, ...args) => tester(args, i), timeout)
×
99
})
100

101
type ChapterTestingFunction = (chapter: Chapter, context: VitestTestContext) => void | Promise<void>
102

103
/**
104
 * Convenience wrapper for testing a case with multiple chapters. Tests with source chapters 1-4 and the library parser
105
 */
106
export function testWithChapters(func: ChapterTestingFunction): void
107

108
/**
109
 * Convenience wrapper for testing a case with multiple chapters. Tests with the given chapters. Returns a function
110
 * that should be called in the same way `test.each` is
111
 */
112
export function testWithChapters(...chapters: Chapter[]): (f: ChapterTestingFunction) => void
113
export function testWithChapters(arg0: ChapterTestingFunction | Chapter, ...chapters: Chapter[]) {
114
  const tester = (chapters: Chapter[], func: ChapterTestingFunction) =>
10✔
115
    test.for(chapters.map(chapter => [getChapterName(chapter), chapter] as [string, Chapter]))(
34✔
116
      'Testing %s',
117
      ([, chapter], context) => func(chapter, context)
34✔
118
    )
119

120
  if (typeof arg0 === 'function') {
10✔
121
    return tester(
1✔
122
      [
123
        Chapter.SOURCE_1,
124
        Chapter.SOURCE_2,
125
        Chapter.SOURCE_3,
126
        Chapter.SOURCE_4,
127
        Chapter.LIBRARY_PARSER
128
      ],
129
      arg0
130
    )
131
  }
132

133
  return (func: ChapterTestingFunction) => tester([arg0, ...chapters], func)
9✔
134
}
135

136
/**
137
 * Asserts that the provided result is a `Finished`
138
 */
139
export function assertIsFinished(result: Result): asserts result is Finished {
140
  expect(result.status).toEqual('finished')
480✔
141
}
142

143
/**
144
 * Asserts that the provided result is both `Finished` and is equal to the given value
145
 */
146
export function assertFinishedResultValue(result: Result, value: Value) {
147
  assertIsFinished(result)
13✔
148
  expect(result.value).toEqual(value)
13✔
149
}
150

151
/**
152
 * Type safe assertion. Expects the given Node to have the provided type
153
 */
154
export function assertNodeType<T extends Node['type']>(
155
  typeStr: T,
156
  node: Node
157
): asserts node is NodeTypeToNode<T> {
158
  expect(node.type).toEqual(typeStr)
2✔
159
}
160

161
/**
162
 * Calls `eval` on the provided code with the provided builtins
163
 */
164
export function evalWithBuiltins(code: string, testBuiltins: TestBuiltins = {}) {
16✔
165
  // Ugly, but if you know how to `eval` code with some builtins attached, please change this.
166
  const builtins = Object.keys(testBuiltins).map(key => `const ${key} = testBuiltins.${key};`)
16✔
167
  const evalstring = builtins.join('\n') + code
16✔
168

169
  // tslint:disable-next-line:no-eval
170
  return eval(evalstring + code)
16✔
171
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc