### Define Roblox project structure with default.project.json Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/GettingStarted.md Sets up the basic project structure for your Roblox application using default.project.json, including the 'Packages' directory for Wally-managed dependencies and a 'src' directory for your main project code. ```json { "name": "YourProject", "tree": { "$className": "Folder", "Packages": { "$path": "Packages", "Project": { "$path": "src" } } } } ``` -------------------------------- ### Jest Configuration File Examples in Lua Source: https://github.com/jsdotlua/jest-lua/blob/main/Docs.md Provides examples for `jest.config.lua`, demonstrating how to configure Jest in a Lua project. It shows both synchronous object return and asynchronous Promise-based configuration setups. ```lua -- Sync object local config = { verbose = true, } return config -- Or async function return Promise.resolve():andThen(function() return { verbose = true, } end) ``` -------------------------------- ### Configure Jest Lua dev dependencies in wally.toml Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/GettingStarted.md Adds the Jest and JestGlobals packages as development dependencies to your wally.toml file, enabling their use within your Roblox project. ```yaml [dev-dependencies] Jest = "jsdotlua/jest@3.10.0" JestGlobals = "jsdotlua/jest-globals@3.10.0" ``` -------------------------------- ### Run Jest Lua tests via run-in-roblox command Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/GettingStarted.md Provides the command-line instruction to execute Jest Lua tests using the 'run-in-roblox' tool. It specifies the Roblox place file and the 'run-tests.lua' script as the entry point for the test execution. ```bash run-in-roblox --place test-place.rbxl --script scripts/run-tests.lua ``` -------------------------------- ### Configure Jest Lua test matching (jest.config.lua) Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/GettingStarted.md Provides a basic Jest Lua configuration file that specifies the pattern for identifying test files. In this example, it's configured to match any file ending with '.spec' within the project. ```lua return { testMatch = { "**/*.spec" } } ``` -------------------------------- ### Create Jest Lua test runner entrypoint (run-tests.lua) Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/GettingStarted.md Defines the entrypoint script for running Jest Lua tests. This Lua file initializes the test runner, specifies test directories, handles command-line interface options, and manages the process exit status based on test results. ```lua local ReplicatedStorage = game:GetService("ReplicatedStorage") local runCLI = require("@DevPackages/Jest").runCLI local processServiceExists, ProcessService = pcall(function() return game:GetService("ProcessService") end) local status, result = runCLI(ReplicatedStorage.Packages.Project, { verbose = false, ci = false }, { ReplicatedStorage.Packages.Project }):awaitStatus() if status == "Rejected" then print(result) end if status == "Resolved" and result.results.numFailedTestSuites == 0 and result.results.numFailedTests == 0 then if processServiceExists then ProcessService:ExitAsync(0) end end if processServiceExists then ProcessService:ExitAsync(1) end return nil ``` -------------------------------- ### Illustrating Jest Lua Describe and Test Block Execution Order Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/SetupAndTeardown.md This example demonstrates the execution sequence of `describe` blocks and `test` functions in Jest Lua. It shows that all `describe` handlers are executed completely before any `test` functions, and tests are then run serially in the order they were encountered during the collection phase. ```Lua describe('describe outer', function() print('describe outer-a') describe('describe inner 1', function() print('describe inner 1') test('test 1', function() print('test 1') end) end) print('describe outer-b') test('test 2', function() print('test 2') end) describe('describe inner 2', function() print('describe inner 2') test('test 3', function() print('test 3') end) end) print('describe outer-c') end) ``` -------------------------------- ### Example Usage of beforeAll in Jest Lua Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/GlobalAPI.md Illustrates how to use `beforeAll` to set up a global database state once before all tests run. This example shows an asynchronous setup where the database is cleared and populated with test data, and Jest Lua waits for this operation to complete before any test executes. ```Lua local globalDatabase = makeGlobalDatabase() beforeAll(function() -- Clears the database and adds some testing data. -- Jest Lua will wait for this promise to resolve before running tests. return globalDatabase:clear() :then(function() return globalDatabase:insert({testData = 'foo'}) end) end) -- Since we only set up the database once in this example, it's important -- that our tests don't modify it. test('can find things', function() return globalDatabase:find('thing', {}, function(results) expect(#results).toBeGreaterThan(0) end) end) ``` -------------------------------- ### Jest-Lua Shared Test Environment Setup Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/UpgradingToJest3.md Documentation for the `setupFilesAfterEnv` configuration option in Jest-Lua v3.0. This option allows specifying modules that execute setup code before each test file, facilitating shared configurations for custom matchers, serializers, or global hooks across the test suite. ```APIDOC setupFilesAfterEnv: array\n - Description: A list of paths to modules that run some code to configure or set up the testing framework before each test file in the suite is executed.\n - Usage: Set in `jest.config.lua`.\n - Purpose: Useful for adding custom matchers, custom serializers, or calling setup and teardown hooks that need to be shared across tests. ``` -------------------------------- ### Enable debug.loadmodule API in ClientAppSettings.json Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/GettingStarted.md Configures Roblox's ClientAppSettings.json to enable the FFlagEnableLoadModule flag, which is essential for Jest Lua to utilize the debug.loadmodule API for dynamic module loading. ```json { "FFlagEnableLoadModule": true } ``` -------------------------------- ### One-Time Setup and Teardown with beforeAll and afterAll Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/SetupAndTeardown.md Shows how to use `beforeAll` and `afterAll` hooks for setup and teardown operations that run only once before all tests in a file, or once after all tests. This is beneficial for expensive, reusable resources that don't need to be reset for every test. ```Lua beforeAll(function() return initializeCityDatabase() end) afterAll(function() return clearCityDatabase() end) test('city database has Vienna', function() expect(isCity('Vienna')).toBeTruthy() end) test('city database has San Juan', function() expect(isCity('San Juan')).toBeTruthy() end) ``` -------------------------------- ### Implement a simple sum function (sum.lua) Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/GettingStarted.md Creates a straightforward Lua module that exports a function to add two numbers. This module serves as a simple example for demonstrating how to write a test. ```lua return function(a, b) return a + b end ``` -------------------------------- ### Understanding Execution Order of Nested Jest Lua Hooks Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/SetupAndTeardown.md Provides a comprehensive example demonstrating the precise execution order of `beforeAll`, `afterAll`, `beforeEach`, and `afterEach` hooks, especially when nested within `describe` blocks. The accompanying comments clarify the sequence of operations. ```Lua beforeAll(function() print('1 - beforeAll') end) afterAll(function() print('1 - afterAll') end) beforeEach(function() print('1 - beforeEach') end) afterEach(function() print('1 - afterEach') end) test('', function() print('1 - test') end) describe('Scoped / Nested block', function() beforeAll(function() print('2 - beforeAll') end) afterAll(function() print('2 - afterAll') end) beforeEach(function() print('2 - beforeEach') end) afterEach(function() print('2 - afterEach') end) test('', function() print('2 - test') end) end) -- 1 - beforeAll -- 1 - beforeEach -- 1 - test -- 1 - afterEach -- 2 - beforeAll -- 1 - beforeEach -- 2 - beforeEach -- 2 - test -- 2 - afterEach -- 1 - afterEach -- 2 - afterAll -- 1 - afterAll ``` -------------------------------- ### Jest Lua Configuration: `setupFilesAfterEnv` Array and Examples Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/Configuration.md Specifies ModuleScripts to run code for configuring the testing framework before each test file. These scripts execute after the test framework is installed, allowing access to Jest globals, `jest` object, and `expect`. Useful for adding extra matchers or setting up/tearing down hooks. ```APIDOC setupFilesAfterEnv [array] Default: {} Description: A list of ModuleScripts that run some code to configure or set up the testing framework before each test file in the suite is executed. ``` ```Lua local JestGlobals = require("@DevPackages/JestGlobals") local jest = JestGlobals.jest local expect = JestGlobals.expect local afterEach = JestGlobals.afterEach expect.extend({ newMatcher = function(self, received, expected) -- ... end) }) afterEach(function() jest.useRealTimers() end) ``` ```Lua return { setupFilesAfterEnv = { Workspace.setupJest }, } ``` -------------------------------- ### Repeating Setup and Teardown with beforeEach and afterEach Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/SetupAndTeardown.md Demonstrates the use of `beforeEach` and `afterEach` hooks in Jest Lua to execute setup and teardown logic before and after every test, respectively. This pattern is ideal for ensuring a clean state for each individual test, such as database initialization and cleanup. ```Lua beforeEach(function() initializeCityDatabase() end) afterEach(function() clearCityDatabase() end) test('city database has Vienna', function() expect(isCity('Vienna')).toBeTruthy() end) test('city database has San Juan', function() expect(isCity('San Juan')).toBeTruthy() end) ``` -------------------------------- ### Handling Asynchronous beforeEach with Promises Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/SetupAndTeardown.md Illustrates how `beforeEach` can handle asynchronous setup by returning a promise. Jest Lua waits for the promise to resolve before proceeding with the test, ensuring that asynchronous setup operations, like database initialization, are completed. ```Lua beforeEach(function() return initializeCityDatabase() end) ``` -------------------------------- ### Write a Jest Lua test for the sum function (sum.spec.lua) Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/GettingStarted.md Demonstrates how to write a basic Jest Lua test. It imports the necessary JestGlobals, the 'sum' function, and uses 'it' and 'expect.toBe' to assert the correct behavior of the sum function. ```lua local JestGlobals = require("@DevPackages/JestGlobals") local it = JestGlobals.it local expect = JestGlobals.expect local sum = require("@Project/Sum") it('adds 1 + 2 to equal 3', function() expect(sum(1, 2)).toBe(3) end) ``` -------------------------------- ### Scoping Setup and Teardown Hooks with describe Blocks Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/SetupAndTeardown.md Explains how `beforeAll`, `afterAll`, `beforeEach`, and `afterEach` hooks can be scoped to specific test groups using `describe` blocks. This allows for modular and targeted setup/teardown logic, applying only to tests within a particular `describe` block. ```Lua -- Applies to all tests in this file beforeEach(function() return initializeCityDatabase() end) test('city database has Vienna', function() expect(isCity('Vienna')).toBeTruthy() end) test('city database has San Juan', function() expect(isCity('San Juan')).toBeTruthy() end) describe('matching cities to foods', function() -- Applies only to tests in this describe block beforeEach(function() return initializeFoodDatabase() end) test('Vienna <3 veal', function() expect(isValidCityFoodPair('Vienna', 'Wiener Schnitzel')).toBe(true) end) test('San Juan <3 plantains', function() expect(isValidCityFoodPair('San Juan', 'Mofongo')).toBe(true) end) end) ``` -------------------------------- ### Jest Lua Configuration Options Reference Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/Configuration.md Comprehensive reference for various configuration options available in `jest.config.lua`, including their types, default values, descriptions, and usage examples. ```APIDOC clearmocks [boolean] Default: false Description: Automatically clear mock calls, instances, contexts, and results before every test. Equivalent to calling `jest.clearAllMocks()` before each test. This does not remove any mock implementation that may have been provided. displayName [string, table] Default: nil Description: Allows for a label to be printed alongside a test while it is running. This is particularly useful in multi-project repositories to indicate which project a test belongs to. Usage (string): return { displayName = 'CLIENT', } Usage (table): return { displayName = { name = 'CLIENT', color = 'blue', } } Table Parameters: name: string - The display name. color: string - The color for the display name, using `chalk-lua` supported colors. projects [array] Default: nil Description: When provided with an array of instances, Jest Lua will run tests in all of the specified projects concurrently. This is beneficial for monorepos or working on multiple projects simultaneously. Usage example: return { projects = { Workspace.ProjectB, Workspace.ProjectB }, } rootDir [Instance] Default: The root of the directory containing your Jest Lua config file. Description: The root directory that Jest Lua should scan for tests and modules within. This is often set to the main workspace where the code is stored. ``` -------------------------------- ### Isolating Tests in Jest Lua with test.only Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/SetupAndTeardown.md This example demonstrates how to use `test.only` in Jest Lua to run a single, specific test. This feature is invaluable for debugging, as it allows developers to isolate a failing test and prevent other tests from running, which helps in identifying issues related to shared state or interference. ```Lua test.only('this will be the only test that runs', function() expect(true).toBe(false) end) test('this test will not run', function() expect('A').toBe('A') end) ``` -------------------------------- ### Using `beforeEach` for Test Setup in Jest Lua Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/GlobalAPI.md The `beforeEach` function runs a specified setup function before each test in a file. It supports asynchronous operations by waiting for promises or generators to resolve. An optional `timeout` can be provided to limit the waiting period, defaulting to 5 seconds. This is commonly used to reset global state, such as a database, for consistent test execution. ```Lua local globalDatabase = makeGlobalDatabase() beforeEach(function() -- Clears the database and adds some testing data. -- Jest Lua will wait for this promise to resolve before running tests. return globalDatabase:clear() :then(function() return globalDatabase:insert({testData = 'foo'}) end) end) test('can find things', function() return globalDatabase:find('thing', {}, function(results) expect(#results).toBeGreaterThan(0) end) end) test('can insert a thing', function() return globalDatabase:insert('thing', makeThing(), function(response) expect(response.success).toBeTruthy() end) end) ``` -------------------------------- ### Example of a generated Jest Lua snapshot file Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/SnapshotTesting.md Shows the structure and content of a snapshot file (`.snap`) generated by Jest Lua for a given test, illustrating how Lua tables are serialized into a human-readable format. ```lua exports[ [=[describe table 1]=] ] = [=[\n\nTable {\n "a": 1,\n "b": "test",\n "c": Table {\n\t"array",\n\t"of",\n\t"strings",\n },\n}\n]=] ``` -------------------------------- ### Example Lua Test Definition for Jest-Lua Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/UpgradingToJest3.md A basic Lua test snippet demonstrating the `test` function in Jest-Lua. This example is used to illustrate how test filtering options like `testMatch` and `testNamePattern` can target specific tests within a file or across the test suite. ```lua test('the data is peanut butter', function()\n -- ...\nend) ``` -------------------------------- ### Import JestBenchmark components in Luau Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/JestBenchmarkAPI.md This Luau snippet demonstrates how to import the `JestBenchmark` library and destructure its `benchmark` function and `CustomReporters` table for direct use. This setup is necessary to access the benchmarking functionalities. ```Luau local JestBenchmark = require(Packages.Dev.JestBenchmark) local benchmark = JestBenchmark.benchmark local CustomReporters = JestBenchmark.CustomReporters ``` -------------------------------- ### Jest Lua v2.x test file example Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/UpgradingToJest3.md This Lua snippet shows a typical test file structure in Jest Lua v2.x, where the test logic is wrapped within a function that the module returns. This pattern is no longer required in v3.0. ```lua return function() local JestGlobals = require("@DevPackages/JestGlobals") local expect = JestGlobals.expect it("1 does not equal 2", function() expect(1).toBe(2) end) end ``` -------------------------------- ### Asynchronous Jest Lua Configuration Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/Configuration.md Illustrates how to define Jest Lua configuration using an asynchronous function that returns a Promise resolving to a table. This method is useful for configurations that require dynamic loading or setup. ```Lua return Promise.resolve():andThen(function() return { verbose = true, } end) ``` -------------------------------- ### Data-Driven Testing with `describe.each` Examples in Jest Lua Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/GlobalAPI.md `describe.each` enables running the same test suite multiple times with different data, significantly reducing test duplication. These examples demonstrate its usage with both array-based and object-based data inputs for parameterized tests, showing how to define test data and access it within the test function. ```Lua describe.each({ {1, 1, 2}, {1, 2, 3}, {2, 1, 3} })('.add($a, $b)', function(a, b, expected) test('returns $expected', function() expect(a + b).toBe(expected) end) test('returned value not be greater than $expected', function() expect(a + b).never.toBeGreaterThan(expected) end) test('returned value not be less than $expected', function() expect(a + b).never.toBeLessThan(expected) end) end) ``` ```Lua describe.each({ {a = 1, b = 1, expected = 2}, {a = 1, b = 2, expected = 3}, {a = 2, b = 1, expected = 3} })('.add($a, $b)', function(ref) local a, b, expected = ref.a, ref.b, ref.expected test('returns $expected', function() expect(a + b).toBe(expected) end) test('returned value not be greater than $expected', function() expect(a + b).never.toBeGreaterThan(expected) end) test('returned value not be less than $expected', function() expect(a + b).never.toBeLessThan(expected) end) end) ``` -------------------------------- ### Jest Lua v3.0 test file example Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/UpgradingToJest3.md This Lua snippet illustrates the updated test file structure for Jest Lua v3.0. Test logic is no longer wrapped in a returned function, and `it` (along with `expect`) must be explicitly imported from `JestGlobals`. ```lua local JestGlobals = require("@DevPackages/JestGlobals") local expect = JestGlobals.expect local it = JestGlobals.it it("1 does not equal 2", function() expect(1).toBe(2) end) ``` -------------------------------- ### `test.failing` Examples in Jest Lua Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/GlobalAPI.md Illustrates the behavior of `test.failing`, showing a test that passes because it throws an error and one that fails because it does not. ```text ``` -------------------------------- ### Example Usage of afterAll in Jest Lua Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/GlobalAPI.md Illustrates how to use `afterAll` to clean up a global database state once all tests have finished running. This ensures that resources are properly released after the entire test suite or `describe` block completes. ```Lua local globalDatabase = makeGlobalDatabase() local function cleanUpDatabase(db) db:cleanUp() end afterAll(function() cleanUpDatabase(globalDatabase) end) test('can find things', function() return globalDatabase:find('thing', {}, function(results) expect(#results).toBeGreaterThan(0) end) end) test('can insert a thing', function() return globalDatabase:insert('thing', makeThing(), function(response) expect(response.success).toBeTruthy() end) end) ``` -------------------------------- ### Managing Resources with Jest Lua beforeEach and afterEach Hooks Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/SetupAndTeardown.md This snippet illustrates the execution order of `beforeEach` and `afterEach` hooks in Jest Lua. It highlights that hooks are called in their order of declaration, and importantly, `after*` hooks of the enclosing scope are called first during teardown, which is crucial for managing dependent resources. ```Lua beforeEach(function() print('connection setup') end) beforeEach(function() print('database setup') end) afterEach(function() print('database teardown') end) afterEach(function() print('connection teardown') end) test('test 1', function() print('test 1') end) describe('extra', function() beforeEach(function() print('extra database setup') end) afterEach(function() print('extra database teardown') end) test('test 2', function() print('test 2') end) end) ``` -------------------------------- ### JestBenchmark Profiler Object API and Usage Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/JestBenchmarkAPI.md The `Profiler` object in `JestBenchmark` manages a set of reporters and controls the collection and reporting of benchmark data. This documentation details its initialization and methods, along with practical Luau examples for defining profiling segments. ```APIDOC initializeProfiler(reporters, fn, prefix?) - Accepts a list of reporters and an output function to create a Profiler object. - Parameters: - reporters: A list of Reporter objects (table of Reporter). - fn: An output function that processes collected metric data (function). - prefix?: An optional string to append to all section names (string, optional). - Returns: A Profiler object. Profiler.start(sectionName: string) - Starts a new profiling segment. Calls reporter.start for each associated reporter. - Parameters: - sectionName: The label for the profiling segment (string). - Note: Each Profiler section must be concluded with a Profiler.stop() call. Profiler.stop() - Concludes the current profiling segment. ``` ```Luau local reporters = { initializeReporter("average", average), initializeReporter("sectionTime", sectionTime), } local outputFn = function(metricName: string, value: any) print(`{metricName}, {value}`) end local profiler = initializeProfiler(reporters, outputFn) ``` ```Luau Profiler.start("section1") Profiler.stop() ``` -------------------------------- ### JestBenchmark Reporter Object API and Usage Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/JestBenchmarkAPI.md The `Reporter` object in `JestBenchmark` is used for collecting and aggregating data during a benchmark run. This documentation details its initialization and methods, along with practical Luau examples for defining custom metrics and managing reporting segments. ```APIDOC initializeReporter(metricName, fn) - Accepts a metric name and a collector function to create a Reporter object. - Parameters: - metricName: The label for the collected data (string). - fn: A collector function that reduces a list of values to a single value (function). - Returns: A Reporter object. Reporter.start(sectionName: string) - Initializes a new reporting segment. All values reported within this segment are collected as a group. - Parameters: - sectionName: The label for the reporting segment (string). - Note: Segments can be nested and must be concluded with Reporter.stop(). Reporter.stop() - Concludes the current reporting segment at the top of the stack. Values are marked for collection. Reporter.report(value: T) - Adds a value to the current report queue. Values are reduced when Reporter.finish() is called. - Parameters: - value: The value to report (any type T). Reporter.finish() - Should be called at the end of the benchmark runtime. - Returns: - A list of section names (table of strings). - A list of section values generated by the collectorFn (table of any). - Note: Values are returned in order of completion. ``` ```Luau local function average(nums: { number }): num if #nums == 0 then return 0 end local sum = 0 for _, v in nums do sum += v end return sum / #nums end local averageReporter = initializeReporter("average", average) ``` ```Luau averageReporter.start("total") averageReporter.start("section1") avgReporter.report(1) avgReporter.report(3) avgReporter.stop() -- closes section1 averageReporter.start("section2") avgReporter.report(5) avgReporter.report(7) avgReporter.stop() -- closes section2 averageReporter.stop() -- closes total local sectionNames, sectionValues = averageReporter.finish() -- sectionNames: {"section1", "section2", "total"} -- sectionValues: {2, 6, 4} ``` -------------------------------- ### Creating a Custom Error Class with LuauPolyfill Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/ExpectAPI.md Demonstrates how to create a custom error class by extending `LuauPolyfill.Error` using the `extends` function, including an example of a function that throws this custom error. ```Lua local extends = LuauPolyfill.extends local OhNoError = extends(Error, 'OhNoError', function(self, message) self.message = message self.name = 'OhNoError' end) local function thisFunctionErrors() error(OhNoError('oh no')) end ``` -------------------------------- ### Define and use a custom snapshot serializer in Jest Lua Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/Configuration.md Illustrates the process of creating and integrating a custom snapshot serializer in `jest-lua`. This allows developers to define how specific custom types or objects are represented in snapshots, providing more readable and controlled output. The example includes defining the serializer, configuring it, and a test case. ```lua local function serialize(val, config, indentation, depth, refs, printer) return "Pretty foo: " .. printer(val.foo, config, indentation, depth, refs, printer) end local function test(val) return typeof(val) == "table" and val.foo ~= nil end return { serialize = serialize, test = test, } ``` ```lua return { snapshotSerializers = { Workspace.customSerializer } } ``` ```lua test('uses custom serializer', function() local bar = { foo = { x = 1, y = 2, } } expect(bar).toMatchSnapshot() end) ``` ```lua Pretty foo: Table { "x": 1, "y": 2, } ``` -------------------------------- ### Implement a forEach function in Lua Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/MockFunctions.md Defines a simple `forEach` function that iterates over a table (array) and applies a callback function to each element. This function serves as a basic example to demonstrate how mock functions can be used for testing its behavior. ```lua local function forEach(items, callback) for _, val in ipairs(items) do callback(val) end end ``` -------------------------------- ### Lua Module with Delayed Callback Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/TimerMocks.md This Lua module defines a function that simulates a game event. It prints a start message, then uses `task.delay` to asynchronously execute a provided callback after a short duration, mimicking a timer-based action in a Roblox environment. ```Lua return function(callback) print('Ready....go!') task.delay(0.01, function() print("Time's up -- stop!") if callback do callback() end end) end ``` -------------------------------- ### Skip Test Suites with describe.skip in Lua Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/GlobalAPI.md This section explains `describe.skip` (aliased as `xdescribe`), a function used to prevent a `describe` block from running its tests. It's a clean alternative to commenting out tests, though the `describe` block itself still executes. Any setup that should also be skipped must be placed in `beforeAll` or `beforeEach`. ```APIDOC describe.skip(name, fn) - Alias: xdescribe(name, fn) - name: String, the title of the test suite - fn: Function, the suite of tests to be skipped. - Purpose: Prevents the tests within this describe block from running. The describe block itself still executes. ``` ```lua describe('my beverage', function() test('is delicious', function() expect(myBeverage.delicious).toBeTruthy() end) test('is not sour', function() expect(myBeverage.sour).toBeFalsy() end) end) describe.skip('my other beverage', function() -- ... will be skipped end) ``` -------------------------------- ### Registering Custom Reporters for Jest-Lua Benchmarks Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/JestBenchmarkAPI.md This snippet demonstrates how to register a custom reporter using `CustomReporters.useCustomReporters` before a benchmark. It shows how to define a custom aggregation logic (e.g., 'sum') and how to report metrics within the benchmark function. The example also includes cleanup using `CustomReporters.useDefaultReporters`. ```Lua local MetricLogger = JestBenchmarks.CustomReporters beforeEach(function() CustomReporters.useCustomReporters({ sum = initializeReporter("sum", function(nums) local sum = 0 for _, v in nums do sum += v end return sum end) }) end) benchmark("Total renders", function(Profiler, reporters) local renderCount = getRenderCount() reporters.sum.report(renderCount) end) afterEach(function() CustomReporters.useDefaultReporters() end) ``` -------------------------------- ### Asserting Jest mock function properties in Lua Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/MockFunctions.md Provides examples of various assertions using the `.mock` property of a Jest mock function. It demonstrates how to check the total number of calls, specific arguments passed to calls, return values, and the number of times the mock was instantiated. ```lua -- The function was called exactly once expect(#someMockFunction.mock.calls).toBe(1) -- The first arg of the first call to the function was 'first arg' expect(someMockFunction.mock.calls[1][1]).toBe('first arg') -- The second arg of the first call to the function was 'second arg' expect(someMockFunction.mock.calls[1][3]).toBe('second arg') -- The return value of the first call to the function was 'return value' expect(someMockFunction.mock.results[1].value).toBe('return value') -- This function was instantiated exactly twice expect(#someMockFunction.mock.instances).toBe(2) ``` -------------------------------- ### Jest Lua Mock Function API Methods Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/MockFunctionAPI.md Detailed reference for the `mockFn` methods available in Jest Lua, including their purpose, parameters, return values, and usage examples. These methods allow for fine-grained control over mock function behavior, from resetting their state to defining custom implementations for single or multiple calls. ```APIDOC mockFn.mockReset() - Description: Resets a mock function to its initial state. This clears all recorded calls and instances (`mockFn.mock.calls`, `mockFn.mock.instances`) and removes any mocked return values or implementations set by `mockReturnValue`, `mockImplementation`, etc. It effectively replaces `mockFn.mock` with a new object. - Parameters: None - Returns: The mock function itself (for chaining). mockFn.mockImplementation(fn) - Description: Accepts a function `fn` that will be used as the actual implementation of the mock function. When the mock is called, `fn` will be executed. The mock will still record all calls and instances, allowing for assertions on its usage. - Parameters: - fn: (function) The function to use as the mock's implementation. This function will receive the same arguments as the mock function. - Returns: The mock function itself (for chaining). mockFn.mockImplementationOnce(fn) - Description: Accepts a function `fn` that will be used as the implementation of the mock for a single call. This method can be chained multiple times to define different behaviors for successive calls to the mock function. If the mock runs out of `mockImplementationOnce` definitions, it will fall back to any default implementation set by `jest.fn(defaultImpl)` or `mockImplementation`. - Parameters: - fn: (function) The function to use as the mock's implementation for one call. - Returns: The mock function itself (for chaining). mockFn.mockName(value) - Description: Assigns a descriptive name to the mock function. This name will be used in test failure output (e.g., in `expect` messages) instead of the default "jest.fn()", making test reports more readable and easier to debug. - Parameters: - value: (string) The name to assign to the mock function. - Returns: The mock function itself (for chaining). mockFn.mockReturnThis() - Description: Sets the mock function's implementation to always return `this` (the mock function itself) when called. This is particularly useful for mocking methods that are designed to be chained, allowing subsequent method calls on the same mocked object. - Parameters: None - Returns: The mock function itself (for chaining). ``` ```lua local mockFn = jest.fn().mockImplementation(function(scalar) return 42 + scalar end) -- or: jest.fn(function(scalar) return 42 + scalar end) local a = mockFn(0) local b = mockFn(1) a == 42 == true b == 43 == true mockFn.mock.calls[1][1] == 0 -- true mockFn.mock.calls[2][1] == 1 -- true ``` ```lua local myMockFn = jest.fn() .mockImplementationOnce(function(cb) return cb(nil, true) end) .mockImplementationOnce(function(cb) return cb(nil, false) end) myMockFn(function(err, val) print(val) end) -- true myMockFn(function(err, val) print(val) end) -- false ``` ```lua local myMockFn = jest.fn(function() return 'default' end) .mockImplementationOnce(function() return 'first call' end) .mockImplementationOnce(function() return 'second call' end) print(myMockFn()) -- 'first call' print(myMockFn()) -- 'second call' print(myMockFn()) -- 'default' print(myMockFn()) -- 'default ``` ```lua local mockFn = jest.fn().mockName('mockedFunction') -- mockFn() expect(mockFn).toHaveBeenCalled() ``` -------------------------------- ### Parameterized Testing with jest-each in Lua Source: https://github.com/jsdotlua/jest-lua/blob/main/src/jest-each/README.md This example demonstrates how to use `jest-each` in Lua for parameterized testing. Unlike JavaScript, Lua does not support tagged templates, so a heading string is used with a list of arrays for test data. Each array corresponds to a row of data, and the test function receives a `ref` table containing the named parameters defined in the heading string. ```lua each("a | b | expected", { 0, 0, 0 }, { 0, 1, 1 }, { 1, 1, 2 } ).it("returns $expected when given $a and $b", function(ref) local a: number, b: number, expected = ref.a, ref.b, ref.expected jestExpect(a + b).toBe(expected) end ) ``` -------------------------------- ### Basic spec.lua bootstrap script for Jest Lua v3.0 Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/UpgradingToJest3.md This Lua script demonstrates a basic bootstrap for `spec.lua` using `Jest.runCLI` as the main entry point, replacing `TestEZ.TestBootStrap:run`. It handles project root, CLI options, and processes test results, exiting with appropriate status codes. ```lua local YourProject = script.Parent.YourProject local runCLI = require("@DevPackages/Jest").runCLI local processServiceExists, ProcessService = pcall(function() return game:GetService("ProcessService") end) local status, result = runCLI(YourProject.Source, { verbose = false, ci = false }, { YourProject.Source }):awaitStatus() if status == "Rejected" then print(result) end if status == "Resolved" and result.results.numFailedTestSuites == 0 and result.results.numFailedTests == 0 then if processServiceExists then ProcessService:ExitAsync(0) end end if processServiceExists then ProcessService:ExitAsync(1) end return nil ``` -------------------------------- ### Jest Lua Configuration: `setupFiles` Array Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/Configuration.md Specifies ModuleScripts to run code for configuring the testing environment. Each script runs once per test file in its own environment, before `setupFilesAfterEnv` and test code. ```APIDOC setupFiles [array] Default: {} Description: A list of ModuleScripts that run some code to configure or set up the testing environment. Each setupFile will be run once per test file. ``` -------------------------------- ### Run Jest Lua Tests with runCLI Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/CLI.md Demonstrates a basic entrypoint script for running Jest Lua tests using `runCLI`. This script imports `runCLI`, sets up the project path, defines CLI options, executes the tests, and handles the test results, including exiting the process based on test outcomes. ```Lua local Packages = script.Parent.YourProject.Packages local runCLI = require("@Packages/Jest").runCLI local processServiceExists, ProcessService = pcall(function() return game:GetService("ProcessService") end) local status, result = runCLI(Packages.Project, { verbose = false, ci = false }, { Packages.Project }):awaitStatus() if status == "Rejected" then print(result) end if status == "Resolved" and result.results.numFailedTestSuites == 0 and result.results.numFailedTests == 0 then if processServiceExists then ProcessService:ExitAsync(0) end end if processServiceExists then ProcessService:ExitAsync(1) end return nil ``` -------------------------------- ### Basic Synchronous Jest Lua Configuration Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/Configuration.md Demonstrates the simplest way to configure Jest Lua by exporting a table directly from `jest.config.lua`. This approach is suitable for static configurations. ```Lua return { verbose = true, } ``` -------------------------------- ### Define a Jest-Lua mock function with an immediate implementation Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/MockFunctions.md Illustrates how to create a mock function using `jest.fn()` and provide an initial, synchronous implementation. This mock will execute the provided callback with specific arguments when called. ```Lua local myMockFn = jest.fn(function(cb) return cb(nil, true) end) myMockFn(function(err, val) print(val) end) -- > true ``` -------------------------------- ### `test.each` with Array of Arrays for Data-Driven Testing in Jest Lua Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/GlobalAPI.md Example of using `test.each` with a table of arrays, where each inner array provides arguments for the test function. ```lua test.each({ {1, 1, 2}, {1, 2, 3}, {2, 1, 3}, })('.add($a, $b)', function(a, b, expected) expect(a + b).toBe(expected) end) ``` -------------------------------- ### Jest Lua Configuration Options Reference Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/Configuration.md Comprehensive documentation for key configuration options in Jest Lua, including `snapshotFormat`, `snapshotSerializers`, and `testFailureExitCode`. These options allow users to customize snapshot behavior, define custom serialization logic, and control the exit code on test failures. ```APIDOC snapshotFormat [table] Default: nil Description: Allows overriding specific snapshot formatting options documented in the pretty-format readme, with the exceptions of `compareKeys` and `plugins`. Properties: printInstanceDefaults [boolean] Default: true Description: If false, only prints properties of a Roblox `Instance` that have been changed. redactStackTracesInStrings [boolean] Default: false Description: If true, configures the `RedactStackTraces` plugin to search through strings for stack traces to redact. snapshotSerializers [array] Default: {} Description: A list of snapshot serializers Jest Lua should use for snapshot testing. Jest Lua has default serializers for built-in Lua types, Roblox types and Instances, and React Roblox elements. Serializer Structure: serialize(val, config, indentation, depth, refs, printer) [function] Description: Function to serialize a value. 'printer' is a function that serializes a value using existing plugins. test(val) [function] Description: Function to determine if the serializer should be used for the given value. testFailureExitCode [number] Default: 1 Description: The exit code Jest Lua returns on test failure. Note: This does not change the exit code in the case of Jest Lua errors (e.g. invalid configuration). ``` -------------------------------- ### `test.each` with Table of Objects for Data-Driven Testing in Jest Lua Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/GlobalAPI.md Example of using `test.each` with a table of Lua tables (acting as objects), where named fields provide arguments for the test function. ```lua test.each({ {a = 1, b = 1, expected = 2}, {a = 1, b = 2, expected = 3}, {a = 2, b = 1, expected = 3}, })('.add($a, $b)', function(ref) local a, b, expected = ref.a, ref.b, ref.expected expect(a + b).toBe(expected) end) ``` -------------------------------- ### Configure Jest: `showConfig` CLI Option Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/CLI.md The `showConfig` option allows users to print their current Jest configuration to the console. After displaying the configuration, Jest will exit, making this a useful tool for debugging and verifying configuration settings. ```APIDOC showConfig [boolean] - Prints the Jest configuration to the console and then exits. ``` -------------------------------- ### Jest Lua Configuration Parameters Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/Configuration.md This section details the configuration options for Jest Lua, allowing users to customize test discovery, execution behavior, and reporting. These options are typically set in a configuration file. ```APIDOC testMatch: array - Default: { "**/__tests__/**/*", "**/?(*.)+(spec|test)" } - Description: Glob patterns Jest Lua uses to detect test files. By default, it looks for .spec or .test files inside __tests__ folders, as well as any files with a suffix of .test or .spec (e.g., Component.test.lua) or files named test.lua or spec.lua. - Notes: - Refer to the micromatch package for pattern details. - Cannot be specified simultaneously with `testRegex`. - Glob patterns are applied in the order they are specified. For negation to work, it must come after specific patterns (e.g., {"**/__tests__/**/*.spec", "!**/__fixtures__/**"}). testPathIgnorePatterns: array - Default: {} - Description: An array of regular expression pattern strings that are matched against all test paths before execution. If a test path matches any of the patterns, the test will be skipped. testRegex: string | array - Default: {} - Description: The pattern or patterns Jest Lua uses to detect test files. - Notes: - Cannot be specified simultaneously with `testMatch`. - `testRegex` detects test files using the absolute file path. A folder name matching the regex will cause all files within it to be run as tests. testTimeout: number - Default: 5000 - Description: The default timeout for a test in milliseconds. verbose: boolean - Default: false - Description: Indicates whether each individual test should be reported during the run. All errors will also be shown at the bottom after execution. If only one test file is being run, this defaults to `true`. ``` -------------------------------- ### Example Usage of afterEach in Jest Lua Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/GlobalAPI.md Illustrates how to use `afterEach` to clean up temporary state after each individual test runs. This is useful for resetting the environment to a known state before the next test executes, preventing test pollution. ```Lua local globalDatabase = makeGlobalDatabase() local function cleanUpDatabase(db) db:cleanUp() end afterEach(function() cleanUpDatabase(globalDatabase) end) test('can find things', function() return globalDatabase:find('thing', {}, function(results) expect(#results).toBeGreaterThan(0) end) end) test('can insert a thing', function() return globalDatabase:insert('thing', makeThing(), function(response) expect(response.success).toBeTruthy() end) end) ``` -------------------------------- ### Incorrect asynchronous test with callbacks in Jest Lua Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/TestingAsyncCode.md This example shows an incorrect way to test asynchronous code using callbacks in Jest Lua. The test completes before the callback is invoked, leading to an unreliable test. ```lua -- Don't do this! test('the data is peanut butter', function() local function callback(error_, data) if error_ then error(error_) end expect(data).toBe('peanut butter') end fetchData(callback) end) ``` -------------------------------- ### Jest Object Methods API Documentation Source: https://github.com/jsdotlua/jest-lua/blob/main/docs/docs/JestObjectAPI.md Comprehensive API documentation for the `jest` object methods, detailing their purpose, parameters, and return values for controlling Jest Lua's behavior and creating mocks. ```APIDOC jest.mock(module, factory) - Description: Mocks a module with a custom mocked version when it is required. The factory function defines the mocked module's value. This mock is local to the file calling `jest.mock`. - Parameters: - module: The module to mock (e.g., `Workspace.mockedModule`). - factory: A function that returns the mocked module's value. - Returns: The `jest` object for chaining. jest.unmock(module) - Description: Indicates that the module system should never return a mocked version of the specified module from `require()`, ensuring the real module is always returned. - Parameters: - module: The module to unmock. - Returns: The `jest` object for chaining. jest.requireActual(module) - Description: Returns the actual module instead of a mock, bypassing all checks on whether the module should receive a mock implementation or not. - Parameters: - module: The module to retrieve the actual implementation for. - Returns: The actual module implementation. jest.isolateModules(fn) - Description: Creates a sandbox registry for modules loaded inside the provided callback function, useful for isolating specific modules per test to prevent state conflicts. - Parameters: - fn: A callback function within which modules will be loaded into an isolated registry. - Returns: The `jest` object for chaining (implicitly). jest.resetModules() - Description: Resets the module registry (cache of all required modules). This is useful to isolate modules where local state might conflict between tests. - Parameters: None. - Returns: The `jest` object for chaining. jest.fn(implementation) - Description: Returns a new, unused mock function. Optionally takes a mock implementation. In Jest Lua, it returns a callable table as the first return value and a function as the second. - Parameters: - implementation (optional): A function that defines the mock function's behavior. - Returns: A tuple: (callable table, function) representing the mock function. ``` -------------------------------- ### Jest-Lua Configuration Deviations and Unsupported Global Options Source: https://github.com/jsdotlua/jest-lua/blob/main/src/jest-config/README.md Documents the specific deviations in configuration options for `jest-lua` compared to standard Jest, along with a comprehensive list of global configuration options that are not supported in the `jest-lua` environment. ```APIDOC API Deviations: - projects: Needs to receive a list of 'Instance' objects (deviates from standard Jest). - rootDir: Needs to receive an 'Instance' (deviates from standard Jest). Unsupported Global Configuration Options: - changedFilesWithAncestor - collectCoverage - collectCoverageFrom - collectCoverageOnlyFrom - coverageDirectory - coveragePathIgnorePatterns - coverageProvider - coverageReporters - coverageThreshold - detectLeaks - detectOpenHandles - findRelatedTests - forceExit - globalTeardown - lastCommit - logHeapUsage - noSCM - notifyMode - onlyChanged - onlyFailures - replname - reporters - snapshotFormat - errorOnDeprecated - testResultsProcessor - testSequencer - useStderr - watch - watchAll - watchman - watchPlugins - cache - cacheDirectory - cwd - dependencyExtractor - extensionsToTreatAsEsm - extraGlobals - forceCoverageMatch - globalSetup - globals - haste - moduleDirectories - moduleFileExtensions - moduleLoader - moduleNameMapper - modulePathIgnorePatterns - modulePaths - prettierPath - resolver - setupFiles - setupFilesAfterEnv - skipNodeResolution - snapshotResolver - testRunner - testURL - transform - transformIgnorePatterns - watchPathIgnorePatterns - unmockedModulePathPatterns ```