Skip to content

Commit

Permalink
prepare jest-react for fast follow (#362)
Browse files Browse the repository at this point in the history
  • Loading branch information
RoFlection Bot committed Jan 24, 2023
1 parent 645b478 commit 71f5fbd
Show file tree
Hide file tree
Showing 13 changed files with 522 additions and 329 deletions.
8 changes: 8 additions & 0 deletions WorkspaceStatic/jest/.robloxrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"language": {
"mode": "strict"
},
"lint": {
"*": "enabled"
}
}
1 change: 1 addition & 0 deletions WorkspaceStatic/jest/matchers/createConsoleMatcher.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
--!nonstrict
-- ROBLOX upstream: https://github.com/facebook/react/blob/6d50a9d090a2a672fc3dea5ce77a3a05332a6caa/fixtures/legacy-jsx-runtimes/setupTests.js
local Packages = script.Parent.Parent.Parent.TestRunner
local JestDiff = require(Packages.Dev.JestDiff)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
--!nonstrict
-- ROBLOX upstream https://github.com/facebook/react/blob/v17.0.1/scripts/jest/matchers/interactionTracingMatchers.js
local Packages = script.Parent.Parent.Parent.TestRunner
local JestDiff = require(Packages.Dev.JestDiff)
Expand Down
108 changes: 108 additions & 0 deletions WorkspaceStatic/jest/matchers/reactTestMatchers.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
-- ROBLOX upstream: https://github.com/facebook/react/blob/v17.0.2/scripts/jest/matchers/reactTestMatchers.js
local Packages = script.Parent.Parent.Parent.TestRunner
-- ROBLOX deviation START: fix import
-- local LuauPolyfill = require(Packages.LuauPolyfill)
local LuauPolyfill = require(Packages.Dev.LuauPolyfill)
-- ROBLOX deviation END
-- ROBLOX deviation START: not used
-- local Error = LuauPolyfill.Error
-- ROBLOX deviation END
local Object = LuauPolyfill.Object
local JestGlobals = require(Packages.Dev.JestGlobals)
local expect = JestGlobals.expect
-- ROBLOX deviation START: fix import
-- local JestReact = require_("jest-react")
-- local SchedulerMatchers = require_("./schedulerTestMatchers")
local JestReact = require(Packages.Dev.JestReact)
local SchedulerMatchers = require(script.Parent.schedulerTestMatchers)
-- ROBLOX deviation END
-- ROBLOX deviation START: add return type
-- local function captureAssertion(fn)
local function captureAssertion(
fn
): { pass: false, message: () -> string } | { pass: true }
-- ROBLOX deviation END
-- Trick to use a Jest matcher inside another Jest matcher. `fn` contains an
-- assertion; if it throws, we capture the error and return it, so the stack
-- trace presented to the user points to the original assertion in the
-- test file.
do --[[ ROBLOX COMMENT: try-catch block conversion ]]
-- ROBLOX deviation START: use pcall, simplify
-- local ok, result, hasReturned = xpcall(function()
-- fn()
-- end, function(error_)
-- return {
-- pass = false,
-- message = function()
-- return error_.message
-- end,
-- },
-- true
-- end)
-- if hasReturned then
-- return result
-- end
local ok, result = pcall(fn)

if not ok then
return {
pass = false,
message = function()
return tostring(result)
end,
}
end
-- ROBLOX deviation END
end
return { pass = true }
end

local function assertYieldsWereCleared(Scheduler)
-- ROBLOX deviation START: use dot notation
-- local actualYields = Scheduler:unstable_clearYields()
local actualYields = Scheduler.unstable_clearYields()
-- ROBLOX deviation END
-- ROBLOX deviation START: fix .length
-- if actualYields.length ~= 0 then
if #actualYields ~= 0 then
-- ROBLOX deviation END
error(
-- ROBLOX deviation START: adapt error message, error with string
-- Error.new(
-- "Log of yielded values is not empty. "
-- .. "Call expect(Scheduler).toHaveYielded(...) first."
-- )
"Log of yielded values is not empty. "
.. "Call expectToHaveYielded(Scheduler, ...) first.",
3
-- ROBLOX deviation END
)
end
end
-- ROBLOX deviation START: add context argument
-- local function toMatchRenderedOutput(ReactNoop, expectedJSX)
local function toMatchRenderedOutput(_matcherContext, ReactNoop, expectedJSX)
-- ROBLOX deviation END
if typeof(ReactNoop.getChildrenAsJSX) == "function" then
local Scheduler = ReactNoop._Scheduler
assertYieldsWereCleared(Scheduler)
return captureAssertion(function()
-- ROBLOX deviation START: use dot notation
-- expect(ReactNoop:getChildrenAsJSX()).toEqual(expectedJSX)
expect(ReactNoop.getChildrenAsJSX()).toEqual(expectedJSX)
-- ROBLOX deviation END
end)
end
-- ROBLOX deviation START: use dot notation
-- return JestReact:unstable_toMatchRenderedOutput(ReactNoop, expectedJSX)
return JestReact.unstable_toMatchRenderedOutput(ReactNoop, expectedJSX)
-- ROBLOX deviation END
end
-- ROBLOX deviation START: replace module.exports
-- module.exports = Object.assign(
return Object.assign(
-- ROBLOX deviation END
{},
SchedulerMatchers,
{ toMatchRenderedOutput = toMatchRenderedOutput }
)
212 changes: 212 additions & 0 deletions WorkspaceStatic/jest/matchers/schedulerTestMatchers.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
-- ROBLOX upstream: https://github.com/facebook/react/blob/v17.0.2/scripts/jest/matchers/schedulerTestMatchers.js
local Packages = script.Parent.Parent.Parent.TestRunner
-- ROBLOX deviation START: fix import
-- local LuauPolyfill = require(Packages.LuauPolyfill)
local LuauPolyfill = require(Packages.Dev.LuauPolyfill)
-- ROBLOX deviation END
-- ROBLOX deviation START: not used
-- local Array = LuauPolyfill.Array
-- local Error = LuauPolyfill.Error
-- ROBLOX deviation END
local JestGlobals = require(Packages.Dev.JestGlobals)
local expect = JestGlobals.expect
-- ROBLOX deviation START: add import
type Array<T> = LuauPolyfill.Array<T>
-- ROBLOX deviation END
-- ROBLOX FIXME Luau: have to have explicit annotation as workaround for CLI-50002
-- ROBLOX deviation START: add return type
-- local function captureAssertion(fn)
local function captureAssertion(fn): { pass: boolean, message: (() -> string)? }
-- ROBLOX deviation END
-- Trick to use a Jest matcher inside another Jest matcher. `fn` contains an
-- assertion; if it throws, we capture the error and return it, so the stack
-- trace presented to the user points to the original assertion in the
-- test file.
do --[[ ROBLOX COMMENT: try-catch block conversion ]]
-- ROBLOX deviation START: replace xpcall, addapt message to something useful
-- local ok, result, hasReturned = xpcall(function()
-- fn()
-- end, function(error_)
-- return {
-- pass = false,
-- message = function()
-- return error_.message
-- end,
-- },
-- true
-- end)
-- if hasReturned then
-- return result
-- end
local ok, result = pcall(fn)
if not ok then
local stringResult = tostring(result)
local subMessageIndex = string.find(stringResult, " ")
assert(
subMessageIndex ~= nil,
"assertion failure text wasn't in expected format"
)
local message = string.sub(stringResult, subMessageIndex + 1)

return {
pass = false,
message = function()
return message
end,
}
end
-- ROBLOX deviation END
end
return { pass = true }
end
local function assertYieldsWereCleared(Scheduler)
-- ROBLOX deviation START: use dot notation
-- local actualYields = Scheduler:unstable_clearYields()
local actualYields = Scheduler.unstable_clearYields()
-- ROBLOX deviation END
-- ROBLOX deviation START: fix .length
-- if actualYields.length ~= 0 then
if #actualYields ~= 0 then
-- ROBLOX deviation END
error(
-- ROBLOX deviation START: adapt error message, error with string
-- Error.new(
-- "Log of yielded values is not empty. "
-- .. "Call expect(Scheduler).toHaveYielded(...) first."
-- )
"Log of yielded values is not empty. "
.. "Call expectToHaveYielded(Scheduler, ...) first.",
3
-- ROBLOX deviation END
)
end
end

-- ROBLOX FIXME Luau: Array<any> annotation here is so we don't have to put the annotation in many places due to mixed arrays
-- ROBLOX deviation START: add context argument
-- local function toFlushAndYield(Scheduler, expectedYields)
local function toFlushAndYield(_matcherContext, Scheduler, expectedYields: Array<any>)
-- ROBLOX deviation END
assertYieldsWereCleared(Scheduler)
-- ROBLOX deviation START: use dot notation
-- Scheduler:unstable_flushAllWithoutAsserting()
-- local actualYields = Scheduler:unstable_clearYields()
Scheduler.unstable_flushAllWithoutAsserting()
local actualYields = Scheduler.unstable_clearYields()
-- ROBLOX deviation END
return captureAssertion(function()
expect(actualYields).toEqual(expectedYields)
end)
end

-- ROBLOX FIXME Luau: Array<any> annotation here is so we don't have to put the annotation in many places due to mixed arrays
-- ROBLOX deviation START: add context argument
-- local function toFlushAndYieldThrough(Scheduler, expectedYields)
local function toFlushAndYieldThrough(
_matcherContext,
Scheduler,
expectedYields: Array<any>
)
-- ROBLOX deviation END
assertYieldsWereCleared(Scheduler)
-- ROBLOX deviation START: use dot notation
-- Scheduler:unstable_flushNumberOfYields(expectedYields.length)
-- local actualYields = Scheduler:unstable_clearYields()
Scheduler.unstable_flushNumberOfYields(#expectedYields)
local actualYields = Scheduler.unstable_clearYields()
-- ROBLOX deviation END
return captureAssertion(function()
expect(actualYields).toEqual(expectedYields)
end)
end
-- ROBLOX FIXME Luau: Array<any> annotation here is so we don't have to put the annotation in many places due to mixed arrays
-- ROBLOX deviation START: add context argument
-- local function toFlushUntilNextPaint(Scheduler, expectedYields)
local function toFlushUntilNextPaint(
_matcherContext,
Scheduler,
expectedYields: Array<any>
)
-- ROBLOX deviation END
assertYieldsWereCleared(Scheduler)
-- ROBLOX deviation START: use dot notation
-- Scheduler:unstable_flushUntilNextPaint()
-- local actualYields = Scheduler:unstable_clearYields()
Scheduler.unstable_flushUntilNextPaint()
local actualYields = Scheduler.unstable_clearYields()
-- ROBLOX deviation END
return captureAssertion(function()
expect(actualYields).toEqual(expectedYields)
end)
end
-- ROBLOX deviation START: add context argument
-- local function toFlushWithoutYielding(Scheduler)
local function toFlushWithoutYielding(_matcherContext, Scheduler)
-- ROBLOX deviation END
-- ROBLOX deviation START: add context argument
-- return toFlushAndYield(Scheduler, {})
return toFlushAndYield(_matcherContext, Scheduler, {})
-- ROBLOX deviation END
end

-- ROBLOX FIXME Luau: Array<any> annotation here is so we don't have to put the annotation in many places due to mixed arrays
-- ROBLOX deviation START: add context argument
-- local function toFlushExpired(Scheduler, expectedYields)
local function toFlushExpired(_matcherContext, Scheduler, expectedYields: Array<any>)
-- ROBLOX deviation END
assertYieldsWereCleared(Scheduler)
-- ROBLOX deviation START: use dot notation
-- Scheduler:unstable_flushExpired()
-- local actualYields = Scheduler:unstable_clearYields()
Scheduler.unstable_flushExpired()
local actualYields = Scheduler.unstable_clearYields()
-- ROBLOX deviation END
return captureAssertion(function()
expect(actualYields).toEqual(expectedYields)
end)
end

-- ROBLOX FIXME Luau: Array<any> annotation here is so we don't have to put the annotation in many places due to mixed arrays
-- ROBLOX deviation START: add context argument
-- local function toHaveYielded(Scheduler, expectedYields)
local function toHaveYielded(_matcherContext, Scheduler, expectedYields: Array<any>)
-- ROBLOX deviation END
return captureAssertion(function()
-- ROBLOX deviation START: use dot notation
-- local actualYields = Scheduler:unstable_clearYields()
local actualYields = Scheduler.unstable_clearYields()
-- ROBLOX deviation END
expect(actualYields).toEqual(expectedYields)
end)
end
-- ROBLOX deviation START: add context argument
-- local function toFlushAndThrow(
-- Scheduler,
-- ...: any --[[ ROBLOX CHECK: check correct type of elements. ]]
-- )
local function toFlushAndThrow(_matcherContext, Scheduler, ...)
-- ROBLOX deviation END
local rest = { ... }
assertYieldsWereCleared(Scheduler)
return captureAssertion(function()
-- ROBLOX TODO Luau: if we wrap this function, we get an odd analyze error: Type '() -> ()' could not be converted into '{| |}'
-- ROBLOX deviation START: use dot notation, fix spreading
-- expect(function()
-- Scheduler:unstable_flushAllWithoutAsserting()
-- end).toThrow(table.unpack(Array.spread(rest)))
expect(Scheduler.unstable_flushAllWithoutAsserting).toThrow(table.unpack(rest))
-- ROBLOX deviation END
end)
end
-- ROBLOX deviation START: replace module.exports
-- module.exports = {
return {
-- ROBLOX deviation END
toFlushAndYield = toFlushAndYield,
toFlushAndYieldThrough = toFlushAndYieldThrough,
toFlushUntilNextPaint = toFlushUntilNextPaint,
toFlushWithoutYielding = toFlushWithoutYielding,
toFlushExpired = toFlushExpired,
toHaveYielded = toHaveYielded,
toFlushAndThrow = toFlushAndThrow,
}
5 changes: 1 addition & 4 deletions WorkspaceStatic/jest/testSetupFile.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,10 @@ local Packages = script.Parent.Parent.TestRunner
local JestGlobals = require(Packages.Dev.JestGlobals)
local jestExpect = JestGlobals.expect

local getTestRendererJestMatchers = require(Packages.Dev.JestReact).getJestMatchers
local getSchedulerJestMatchers = require(Packages.Dev.Scheduler).getJestMatchers
local InteractionTracingMatchers =
require(script.Parent.matchers.interactionTracingMatchers)

jestExpect.extend(getTestRendererJestMatchers(jestExpect))
jestExpect.extend(getSchedulerJestMatchers(jestExpect))
jestExpect.extend(require(script.Parent.matchers.reactTestMatchers))
jestExpect.extend({
toErrorDev = require(script.Parent.matchers.toErrorDev),
toWarnDev = require(script.Parent.matchers.toWarnDev),
Expand Down
2 changes: 1 addition & 1 deletion bin/ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ find Packages/_Index -name "*.robloxrc" | xargs rm -f
echo "Run static analysis"
roblox-cli analyze tests.project.json
selene --version
selene --config selene.toml modules/
selene --config selene.toml modules/ WorkspaceStatic/
stylua --version
stylua -c modules bin WorkspaceStatic

Expand Down
Loading

0 comments on commit 71f5fbd

Please sign in to comment.