Skip to content

Commit

Permalink
add example for testing with:
Browse files Browse the repository at this point in the history
- vitest
- jasmine
  • Loading branch information
monyedavid committed Dec 15, 2024
1 parent da37921 commit 14f9456
Show file tree
Hide file tree
Showing 11 changed files with 291 additions and 14 deletions.
11 changes: 11 additions & 0 deletions example/javascriptlib/testing/1-test-suite/baz/src/calculator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export class Calculator {
add(a, b) {
return a + b;
}
divide(a, b) {
if (b === 0) {
throw new Error("Division by zero is not allowed");
}
return a / b;
}
}
12 changes: 12 additions & 0 deletions example/javascriptlib/testing/1-test-suite/baz/src/calculator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export class Calculator {
add(a: number, b: number): number {
return a + b;
}

divide(a: number, b: number): number {
if (b === 0) {
throw new Error("Division by zero is not allowed");
}
return a / b;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { describe, it, expect } from 'vitest';
import { Calculator } from 'baz/calculator';
describe('Calculator', () => {
const calculator = new Calculator();
describe('Addition', () => {
test('should return the sum of two numbers', () => {
const result = calculator.add(2, 3);
expect(result).toEqual(5);
});
test('should return the correct sum for negative numbers', () => {
const result = calculator.add(-2, -3);
expect(result).toEqual(-5);
});
});
describe('Division', () => {
test('should return the quotient of two numbers', () => {
const result = calculator.divide(6, 3);
expect(result).toEqual(2);
});
it('should throw an error when dividing by zero', () => {
expect(() => calculator.divide(6, 0)).toThrow("Division by zero is not allowed");
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Calculator } from 'baz/calculator';

describe('Calculator', () => {
const calculator = new Calculator();

describe('Addition', () => {
test('should return the sum of two numbers', () => {
const result = calculator.add(2, 3);
expect(result).toEqual(5);
});

test('should return the correct sum for negative numbers', () => {
const result = calculator.add(-2, -3);
expect(result).toEqual(-5);
});
});

describe('Division', () => {
test('should return the quotient of two numbers', () => {
const result = calculator.divide(6, 3);
expect(result).toEqual(2);
});

it('should throw an error when dividing by zero', () => {
expect(() => calculator.divide(6, 0)).toThrow("Division by zero is not allowed");
});
});
});
18 changes: 18 additions & 0 deletions example/javascriptlib/testing/1-test-suite/build.mill
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,18 @@ object bar extends TypeScriptModule {
object test extends TypeScriptTests with TestModule.Jest
}

object baz extends TypeScriptModule {
object test extends TypeScriptTests with TestModule.Vitest
}

object foo extends TypeScriptModule {
object test extends TypeScriptTests with TestModule.Mocha
}

object qux extends TypeScriptModule {
object test extends TypeScriptTests with TestModule.Jasmine
}

// Documentation for mill.example.javascriptlib
// This build defines two modules bar and foo with test suites configured to use
// Mocha & Jest resepectively.
Expand All @@ -27,4 +35,14 @@ object foo extends TypeScriptModule {
Test Suites:...1 passed, 1 total...
Tests:...4 passed, 4 total...
...

> mill baz.test
.../calculator.test.ts...
...Test Files 1 passed...
...Tests 4 passed...
...

> mill qux.test
...
4 specs, 0 failures
*/
11 changes: 11 additions & 0 deletions example/javascriptlib/testing/1-test-suite/qux/src/calculator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export class Calculator {
add(a, b) {
return a + b;
}
divide(a, b) {
if (b === 0) {
throw new Error("Division by zero is not allowed");
}
return a / b;
}
}
12 changes: 12 additions & 0 deletions example/javascriptlib/testing/1-test-suite/qux/src/calculator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export class Calculator {
add(a: number, b: number): number {
return a + b;
}

divide(a: number, b: number): number {
if (b === 0) {
throw new Error("Division by zero is not allowed");
}
return a / b;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Calculator } from 'qux/calculator';

describe('Calculator', () => {
const calculator = new Calculator();

describe('Addition', () => {
it('should return the sum of two numbers', () => {
const result = calculator.add(2, 3);
expect(result).toEqual(5);
});

it('should return the correct sum for negative numbers', () => {
const result = calculator.add(-2, -3);
expect(result).toEqual(-5);
});
});

describe('Division', () => {
it('should return the quotient of two numbers', () => {
const result = calculator.divide(6, 3);
expect(result).toEqual(2);
});

it('should throw an error when dividing by zero', () => {
expect(() => calculator.divide(6, 0)).toThrowError("Division by zero is not allowed");
});
});
});
12 changes: 12 additions & 0 deletions example/javascriptlib/testing/1-test-suite/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/// <reference types="vitest" />
import { defineConfig } from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths';

export default defineConfig({
plugins: [tsconfigPaths()],
test: {
globals: true,
environment: 'node',
include: ['**/**/*.test.ts']
},
});
129 changes: 125 additions & 4 deletions javascriptlib/src/mill/javascriptlib/TestModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@ object TestModule {
def testConfigSource: T[PathRef] =
Task.Source(Task.workspace / "jest.config.ts")

override def allSources: T[IndexedSeq[PathRef]] = Task {
super.allSources() ++ IndexedSeq(testConfigSource())
}

override def compilerOptions: T[Map[String, ujson.Value]] =
Task { super.compilerOptions() + ("resolveJsonModule" -> ujson.Bool(true)) }

Expand Down Expand Up @@ -144,4 +140,129 @@ object TestModule {
}

}

trait Vitest extends TypeScriptModule with Shared with TestModule {
override def npmDevDeps: T[Seq[String]] =
Task {
Seq(
"@vitest/runner@2.1.8",
"vite@5.4.11",
"vite-tsconfig-paths@3.6.0",
"vitest@2.1.8"
)
}

def testConfigSource: T[PathRef] =
Task.Source(Task.workspace / "vite.config.ts")

override def compilerOptions: T[Map[String, ujson.Value]] =
Task {
super.compilerOptions() + (
"target" -> ujson.Str("ESNext"),
"module" -> ujson.Str("ESNext"),
"moduleResolution" -> ujson.Str("Node"),
"skipLibCheck" -> ujson.Bool(true),
"types" -> ujson.Arr(
s"${npmInstall().path}/node_modules/vitest/globals"
)
)
}

def getConfigFile: T[String] =
Task { (compile()._1.path / "vite.config.ts").toString }

private def copyConfig: Task[Unit] = Task.Anon {
os.copy.over(
testConfigSource().path,
compile()._1.path / "vite.config.ts"
)
}

private def runTest: T[TestResult] = Task {
copyConfig()
os.call(
(
"node",
npmInstall().path / "node_modules/.bin/vitest",
"--run",
"--config",
getConfigFile(),
getPathToTest()
),
stdout = os.Inherit,
env = mkENV(),
cwd = compile()._1.path
)
()
}

protected def testTask(args: Task[Seq[String]]): Task[TestResult] = Task.Anon {
runTest()
}

}

trait Jasmine extends TypeScriptModule with Shared with TestModule {
override def npmDevDeps: T[Seq[String]] =
Task {
Seq(
"@types/jasmine@5.1.2",
"jasmine@5.1.0",
"ts-node@10.9.1",
"tsconfig-paths@4.2.0",
"typescript@5.2.2"
)
}

override def compilerOptions: T[Map[String, ujson.Value]] =
Task {
super.compilerOptions() + (
"target" -> ujson.Str("ES5"),
"module" -> ujson.Str("commonjs"),
"moduleResolution" -> ujson.Str("node"),
"allowJs" -> ujson.Bool(true)
)
}

def configBuilder: T[PathRef] = Task {
val path = compile()._1.path / "jasmine.json"
os.write(
path,
ujson.write(
ujson.Obj(
"spec_dir" -> ujson.Str("typescript/src"),
"spec_files" -> ujson.Arr(ujson.Str("**/*.test.ts")),
"stopSpecOnExpectationFailure" -> ujson.Bool(false),
"random" -> ujson.Bool(false)
)
)
)
PathRef(path)
}

private def runTest: T[Unit] = Task {
configBuilder()
val jasmine = npmInstall().path / "node_modules/jasmine/bin/jasmine.js"
val tsnode = npmInstall().path / "node_modules/ts-node/register/transpile-only.js"
val tsconfigPath = npmInstall().path / "node_modules/tsconfig-paths/register.js"
os.call(
(
"node",
jasmine,
"--config=jasmine.json",
s"--require=$tsnode",
s"--require=$tsconfigPath"
),
stdout = os.Inherit,
env = mkENV(),
cwd = compile()._1.path
)
()
}

protected def testTask(args: Task[Seq[String]]): Task[TestResult] = Task.Anon {
runTest()
}

}
}
20 changes: 10 additions & 10 deletions javascriptlib/src/mill/javascriptlib/TypeScriptModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ trait TypeScriptModule extends Module { outer =>
Task.traverse(moduleDeps)(_.npmDevDeps)().flatten ++ npmDevDeps()
}

def npmInstall: Target[PathRef] = Task {
def npmInstall: T[PathRef] = Task {
os.call((
"npm",
"install",
"--save-dev",
"@types/node@22.7.8",
"typescript@5.6.3",
"@types/node@22.10.2",
"typescript@5.7.2",
"ts-node@^10.9.2",
"esbuild@0.24.0",
"@esbuild-plugins/tsconfig-paths@0.1.2",
Expand All @@ -36,13 +36,13 @@ trait TypeScriptModule extends Module { outer =>
PathRef(Task.dest)
}

def sources: Target[PathRef] = Task.Source(millSourcePath / "src")
def sources: T[PathRef] = Task.Source(millSourcePath / "src")

def allSources: Target[IndexedSeq[PathRef]] =
def allSources: T[IndexedSeq[PathRef]] =
Task { os.walk(sources().path).filter(_.ext == "ts").map(PathRef(_)) }

// specify tsconfig.compilerOptions
def compilerOptions: Task[Map[String, ujson.Value]] = Task {
def compilerOptions: Task[Map[String, ujson.Value]] = Task.Anon {
Map(
"esModuleInterop" -> ujson.Bool(true),
"declaration" -> ujson.Bool(true),
Expand Down Expand Up @@ -89,15 +89,15 @@ trait TypeScriptModule extends Module { outer =>
)
)

os.call(npmInstall().path / "node_modules/typescript/bin/tsc")
os.call(npmInstall().path / "node_modules/.bin/tsc")
os.copy.over(millSourcePath, Task.dest / "typescript")

(PathRef(Task.dest), PathRef(Task.dest / "typescript"))
}

def mainFileName: Target[String] = Task { s"${millSourcePath.last}.ts" }
def mainFileName: T[String] = Task { s"${millSourcePath.last}.ts" }

def mainFilePath: Target[Path] = Task { compile()._2.path / "src" / mainFileName() }
def mainFilePath: T[Path] = Task { compile()._2.path / "src" / mainFileName() }

def mkENV: T[Map[String, String]] =
Task {
Expand Down Expand Up @@ -158,7 +158,7 @@ trait TypeScriptModule extends Module { outer =>

}

def bundle: Target[PathRef] = Task {
def bundle: T[PathRef] = Task {
val env = mkENV()
val tsnode = npmInstall().path / "node_modules/.bin/ts-node"
val bundleScript = compile()._1.path / "build.ts"
Expand Down

0 comments on commit 14f9456

Please sign in to comment.