-- ROBLOX upstream: https://github.com/facebook/react/blob/d13f5b9538e48f74f7c571ef3cde652ca887cca0/packages/react/src/__tests__/ReactStrictMode-test.js
--  * Copyright (c) Facebook, Inc. and its affiliates.
--  *
--  * This source code is licensed under the MIT license found in the
--  * LICENSE file in the root directory of this source tree.
--  *
--  * @emails react-core
--!strict

local Packages = script.Parent.Parent.Parent
local ReactGlobals = require(Packages.ReactGlobals)
local React
local ReactNoop
-- local ReactDOM
-- local ReactDOMServer
local Scheduler
-- local PropTypes
local JestGlobals = require(Packages.Dev.JestGlobals)
local jest = JestGlobals.jest
local describe = JestGlobals.describe
local beforeEach = JestGlobals.beforeEach
local it = JestGlobals.it
local xit = JestGlobals.xit

-- ROBLOX TODO: split non-DOM test into separate file, make upstream PR for this division

local jestExpect = JestGlobals.expect

describe("ReactStrictMode", function()
	beforeEach(function()
		jest.resetModules()

		-- ROBLOX deviation: workaround because our flag is currently always set to false
		local ReactFeatureFlags = require(Packages.Shared).ReactFeatureFlags
		ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = true
		React = require(script.Parent.Parent)

		-- ROBLOX deviation: using ReactNoop in place of ReactDOM
		ReactNoop = require(Packages.Dev.ReactNoopRenderer)
		-- ReactDOM = require('react-dom')
		-- ReactDOMServer = require('react-dom/server')
		Scheduler = require(Packages.Dev.Scheduler)
	end)
	-- ROBLOX TODO: Untranslated ReactDOMInvalidARIAHook file throws the error this test checks
	-- xit('should appear in the client component stack', function()
	--     local function Foo()
	--         return React.createElement('div', {
	--             ariaTypo = '',
	--         })
	--     end

	--     jestExpect(function()
	--         -- ROBLOX deviation: use ReactNoop to render instead of ReactDOM
	--         ReactNoop.render(React.createElement(React.StrictMode, nil, React.createElement(Foo)))
	--     end).toErrorDev('Invalid ARIA attribute `ariaTypo`. ' .. 'ARIA attributes follow the pattern aria-* and must be lowercase.\n' .. '    in div (at **)\n' .. '    in Foo (at **)')
	-- end)
	-- ROBLOX TODO: Untranslated ReactDOMInvalidARIAHook file throws the error this test checks
	-- xit('should appear in the SSR component stack', function()
	--     local function Foo()
	--         return React.createElement('div', {
	--             ariaTypo = '',
	--         })
	--     end

	--     jestExpect(function()
	--         -- ROBLOX deviation: use ReactNoop.render to render instead of ReactDOMServer.renderToString
	--         ReactNoop.render(React.createElement(React.StrictMode, nil, React.createElement(Foo)))
	--     end).toErrorDev('Invalid ARIA attribute `ariaTypo`. ' .. 'ARIA attributes follow the pattern aria-* and must be lowercase.\n' .. '    in div (at **)\n' .. '    in Foo (at **)')
	-- end)
	it("should invoke precommit lifecycle methods twice", function()
		local log = {}
		local shouldComponentUpdate = false
		local ClassComponent = React.Component:extend("ClassComponent")

		function ClassComponent.getDerivedStateFromProps()
			table.insert(log, "getDerivedStateFromProps")

			return nil
		end
		function ClassComponent:init()
			-- ROBLOX deviation: silence analyze with explicit state
			self.state = {}
			table.insert(log, "constructor")
		end
		function ClassComponent:componentDidMount()
			table.insert(log, "componentDidMount")
		end
		function ClassComponent:componentDidUpdate()
			table.insert(log, "componentDidUpdate")
		end
		function ClassComponent:componentWillUnmount()
			table.insert(log, "componentWillUnmount")
		end
		function ClassComponent:shouldComponentUpdate()
			table.insert(log, "shouldComponentUpdate")

			return shouldComponentUpdate
		end
		function ClassComponent:render()
			table.insert(log, "render")

			return nil
		end

		-- ROBLOX deviation: use ReactNoop.render to render instead of ReactDOM.render
		ReactNoop.act(function()
			ReactNoop.render(
				React.createElement(
					React.StrictMode,
					nil,
					React.createElement(ClassComponent)
				)
			)
		end)

		if ReactGlobals.__DEV__ then
			jestExpect(log).toEqual({
				"constructor",
				"constructor",
				"getDerivedStateFromProps",
				"getDerivedStateFromProps",
				"render",
				"render",
				"componentDidMount",
			})
		else
			jestExpect(log).toEqual({
				"constructor",
				"getDerivedStateFromProps",
				"render",
				"componentDidMount",
			})
		end

		log = {}
		shouldComponentUpdate = true

		-- ROBLOX deviation: use ReactNoop.render to render instead of ReactDOM.render
		ReactNoop.act(function()
			ReactNoop.render(
				React.createElement(
					React.StrictMode,
					nil,
					React.createElement(ClassComponent)
				)
			)
		end)

		if ReactGlobals.__DEV__ then
			jestExpect(log).toEqual({
				"getDerivedStateFromProps",
				"getDerivedStateFromProps",
				"shouldComponentUpdate",
				"shouldComponentUpdate",
				"render",
				"render",
				"componentDidUpdate",
			})
		else
			jestExpect(log).toEqual({
				"getDerivedStateFromProps",
				"shouldComponentUpdate",
				"render",
				"componentDidUpdate",
			})
		end

		log = {}
		shouldComponentUpdate = false

		-- ROBLOX deviation: use ReactNoop.render to render instead of ReactDOM.render
		ReactNoop.act(function()
			ReactNoop.render(
				React.createElement(
					React.StrictMode,
					nil,
					React.createElement(ClassComponent)
				)
			)
		end)

		if ReactGlobals.__DEV__ then
			jestExpect(log).toEqual({
				"getDerivedStateFromProps",
				"getDerivedStateFromProps",
				"shouldComponentUpdate",
				"shouldComponentUpdate",
			})
		else
			jestExpect(log).toEqual({
				"getDerivedStateFromProps",
				"shouldComponentUpdate",
			})
		end
	end)
	it("should invoke setState callbacks twice", function()
		local instance
		local ClassComponent = React.Component:extend("ClassComponent")

		function ClassComponent:init()
			self.state = { count = 1 }
		end
		function ClassComponent:render()
			instance = self
			return nil
		end

		local setStateCount = 0

		-- ROBLOX deviation: use ReactNoop.render to render instead of ReactDOM.render
		ReactNoop.act(function()
			ReactNoop.render(
				React.createElement(
					React.StrictMode,
					nil,
					React.createElement(ClassComponent)
				)
			)
		end)

		-- ROBLOX deviation: using ReactNoop in place of ReactDOM, needs flushSync
		ReactNoop.flushSync(function()
			instance:setState(function(state: { count: number })
				setStateCount = setStateCount + 1
				return {
					count = state.count + 1,
				}
			end)
		end)
		-- Callback should be invoked twice in DEV
		jestExpect(setStateCount).toEqual((function()
			if ReactGlobals.__DEV__ then
				return 2
			end

			return 1
		end)())
		-- But each time `state` should be the previous value
		jestExpect(instance.state.count).toEqual(2)
	end)
	it("should invoke precommit lifecycle methods twice in DEV", function()
		local StrictMode = React.StrictMode
		local log = {}
		local shouldComponentUpdate = false

		local ClassComponent = React.Component:extend("ClassComponent")

		function ClassComponent:init(props)
			-- ROBLOX deviation: silence analyze with explicit state
			self.state = {}
			table.insert(log, "constructor")
		end
		function ClassComponent.getDerivedStateFromProps()
			table.insert(log, "getDerivedStateFromProps")
			return nil
		end
		function ClassComponent:componentDidMount()
			table.insert(log, "componentDidMount")
		end
		function ClassComponent:componentDidUpdate()
			table.insert(log, "componentDidUpdate")
		end
		function ClassComponent:componentWillUnmount()
			table.insert(log, "componentWillUnmount")
		end
		function ClassComponent:shouldComponentUpdate()
			table.insert(log, "shouldComponentUpdate")

			return shouldComponentUpdate
		end
		function ClassComponent:render()
			table.insert(log, "render")

			return nil
		end

		local function Root()
			return React.createElement(
				StrictMode,
				nil,
				React.createElement(ClassComponent)
			)
		end

		-- ROBLOX deviation: use ReactNoop.render to render instead of ReactDOM.render
		ReactNoop.act(function()
			ReactNoop.render(React.createElement(Root))
		end)

		if ReactGlobals.__DEV__ then
			jestExpect(log).toEqual({
				"constructor",
				"constructor",
				"getDerivedStateFromProps",
				"getDerivedStateFromProps",
				"render",
				"render",
				"componentDidMount",
			})
		else
			jestExpect(log).toEqual({
				"constructor",
				"getDerivedStateFromProps",
				"render",
				"componentDidMount",
			})
		end

		log = {}
		shouldComponentUpdate = true

		-- ROBLOX deviation: use ReactNoop.render to render instead of ReactDOM.render
		ReactNoop.act(function()
			ReactNoop.render(React.createElement(Root))
		end)

		if ReactGlobals.__DEV__ then
			jestExpect(log).toEqual({
				"getDerivedStateFromProps",
				"getDerivedStateFromProps",
				"shouldComponentUpdate",
				"shouldComponentUpdate",
				"render",
				"render",
				"componentDidUpdate",
			})
		else
			jestExpect(log).toEqual({
				"getDerivedStateFromProps",
				"shouldComponentUpdate",
				"render",
				"componentDidUpdate",
			})
		end

		log = {}
		shouldComponentUpdate = false

		-- ROBLOX deviation: use ReactNoop.render to render instead of ReactDOM.render
		ReactNoop.act(function()
			ReactNoop.render(React.createElement(Root))
		end)

		if ReactGlobals.__DEV__ then
			jestExpect(log).toEqual({
				"getDerivedStateFromProps",
				"getDerivedStateFromProps",
				"shouldComponentUpdate",
				"shouldComponentUpdate",
			})
		else
			jestExpect(log).toEqual({
				"getDerivedStateFromProps",
				"shouldComponentUpdate",
			})
		end
	end)
	it("should invoke setState callbacks twice in DEV", function()
		local StrictMode = React.StrictMode
		local instance
		local ClassComponent = React.Component:extend("ClassComponent")

		function ClassComponent:init()
			self.state = {
				count = 1,
			}
		end

		function ClassComponent:render()
			instance = self

			return nil
		end

		local setStateCount = 0

		-- ROBLOX deviation: using ReactNoop in place of ReactDOM
		ReactNoop.act(function()
			ReactNoop.render(
				React.createElement(StrictMode, nil, React.createElement(ClassComponent))
			)
		end)

		-- ROBLOX deviation: using ReactNoop in place of ReactDOM
		ReactNoop.flushSync(function()
			instance:setState(function(state: { count: number })
				setStateCount = setStateCount + 1

				return {
					count = state.count + 1,
				}
			end)
		end)
		-- Callback should be invoked twice (in DEV)
		jestExpect(setStateCount).toEqual((function()
			if ReactGlobals.__DEV__ then
				return 2
			end

			return 1
		end)())
		-- But each time `state` should be the previous value
		jestExpect(instance.state.count).toEqual(2)
	end)
end)
describe("Concurrent Mode", function()
	beforeEach(function()
		jest.resetModules()
		React = require(script.Parent.Parent)
		-- ROBLOX deviation: using ReactNoop in place of ReactDOM
		ReactNoop = require(Packages.Dev.ReactNoopRenderer)
		-- ReactDOM = require('react-dom')
		-- ReactDOMServer = require('react-dom/server')
		Scheduler = require(Packages.Dev.Scheduler)
	end)
	it(
		"should warn about unsafe legacy lifecycle methods anywhere in the tree",
		function()
			local function Wrapper(props)
				local children = props.children

				return React.createElement("div", nil, children)
			end

			local Foo = React.Component:extend("Foo")

			function Foo:UNSAFE_componentWillReceiveProps() end
			function Foo:render()
				return nil
			end

			local Bar = React.Component:extend("Bar")

			function Bar:UNSAFE_componentWillReceiveProps() end
			function Bar:render()
				return nil
			end

			local AsyncRoot = React.Component:extend("AsyncRoot")

			function AsyncRoot:UNSAFE_componentWillMount() end
			function AsyncRoot:UNSAFE_componentWillUpdate() end
			function AsyncRoot:render()
				return React.createElement(
					"div",
					nil,
					React.createElement(Wrapper, nil, React.createElement(Foo)),
					React.createElement(
						"div",
						nil,
						React.createElement(Bar),
						React.createElement(Foo)
					)
				)
			end

			-- ROBLOX deviation: using ReactNoop in place of ReactDOM
			local root = ReactNoop.createRoot()

			root.render(React.createElement(AsyncRoot))
			jestExpect(function()
				return Scheduler.unstable_flushAll()
			end).toErrorDev({

				[[Warning: Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. See https://reactjs.org/link/unsafe-component-lifecycles for details.

* Move code with side effects to componentDidMount, and set initial state in the constructor.

Please update the following components: AsyncRoot]],

				[[Warning: Using UNSAFE_componentWillReceiveProps in strict mode is not recommended and may indicate bugs in your code. See https://reactjs.org/link/unsafe-component-lifecycles for details.

* Move data fetching code or side effects to componentDidUpdate.
* If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state

Please update the following components: Bar, Foo]],

				[[Warning: Using UNSAFE_componentWillUpdate in strict mode is not recommended and may indicate bugs in your code. See https://reactjs.org/link/unsafe-component-lifecycles for details.

* Move data fetching code or side effects to componentDidUpdate.

Please update the following components: AsyncRoot]],
			}, { withoutStack = true })
			root.render(React.createElement(AsyncRoot))
			Scheduler.unstable_flushAll()
		end
	)
	it("should coalesce warnings by lifecycle name", function()
		local Child = React.Component:extend("Child")
		function Child:UNSAFE_componentWillReceiveProps() end
		function Child:render()
			return nil
		end

		local Parent = React.Component:extend("Parent")
		function Parent:componentWillMount() end
		function Parent:componentWillUpdate() end
		function Parent:componentWillReceiveProps() end
		function Parent:render()
			return React.createElement(Child)
		end

		local AsyncRoot = React.Component:extend("AsyncRoot")
		function AsyncRoot:UNSAFE_componentWillMount() end
		function AsyncRoot:UNSAFE_componentWillUpdate() end
		function AsyncRoot:render()
			return React.createElement(Parent)
		end

		-- ROBLOX deviation: using ReactNoop in place of ReactDOM
		local root = ReactNoop.createRoot()

		root.render(React.createElement(AsyncRoot))
		jestExpect(function()
			jestExpect(function()
				return Scheduler.unstable_flushAll()
			end).toErrorDev({
				-- ROBLOX deviation: below warnings all remove "To rename all deprecated lifecycles..." line which are unique instructions for Node.js

				[[Warning: Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. See https://reactjs.org/link/unsafe-component-lifecycles for details.

* Move code with side effects to componentDidMount, and set initial state in the constructor.

Please update the following components: AsyncRoot]],

				[[Warning: Using UNSAFE_componentWillReceiveProps in strict mode is not recommended and may indicate bugs in your code. See https://reactjs.org/link/unsafe-component-lifecycles for details.

* Move data fetching code or side effects to componentDidUpdate.
* If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state

Please update the following components: Child]],

				[[Warning: Using UNSAFE_componentWillUpdate in strict mode is not recommended and may indicate bugs in your code. See https://reactjs.org/link/unsafe-component-lifecycles for details.

* Move data fetching code or side effects to componentDidUpdate.

Please update the following components: AsyncRoot]],
			}, { withoutStack = true })
		end).toWarnDev({

			[[Warning: componentWillMount has been renamed, and is not recommended for use. See https://reactjs.org/link/unsafe-component-lifecycles for details.

* Move code with side effects to componentDidMount, and set initial state in the constructor.
* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work.

Please update the following components: Parent]],

			[[Warning: componentWillReceiveProps has been renamed, and is not recommended for use. See https://reactjs.org/link/unsafe-component-lifecycles for details.

* Move data fetching code or side effects to componentDidUpdate.
* If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state
* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work.

Please update the following components: Parent]],

			[[Warning: componentWillUpdate has been renamed, and is not recommended for use. See https://reactjs.org/link/unsafe-component-lifecycles for details.

* Move data fetching code or side effects to componentDidUpdate.
* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work.

Please update the following components: Parent]],
		}, { withoutStack = true })
		root.render(React.createElement(AsyncRoot))
		Scheduler.unstable_flushAll()
	end)
	it("should warn about components not present during the initial render", function()
		local Foo = React.Component:extend("Foo")

		function Foo:UNSAFE_componentWillMount() end
		function Foo:render()
			return nil
		end

		local Bar = React.Component:extend("Bar")

		function Bar:UNSAFE_componentWillMount() end
		function Bar:render()
			return nil
		end

		local AsyncRoot = React.Component:extend("AsyncRoot")

		function AsyncRoot:render()
			return (function()
				if self.props.foo then
					return React.createElement(Foo)
				end

				return React.createElement(Bar)
			end)()
		end

		-- ROBLOX deviation: using ReactNoop in place of ReactDOM
		local root = ReactNoop.createRoot()

		root.render(React.createElement(AsyncRoot, { foo = true }))
		jestExpect(function()
			return Scheduler.unstable_flushAll()
		end).toErrorDev(
			"Using UNSAFE_componentWillMount in strict mode is not recommended",
			{ withoutStack = true }
		)

		root.render(React.createElement(AsyncRoot, { foo = false }))
		jestExpect(function()
			return Scheduler.unstable_flushAll()
		end).toErrorDev(
			"Using UNSAFE_componentWillMount in strict mode is not recommended",
			{ withoutStack = true }
		)

		root.render(React.createElement(AsyncRoot, { foo = true }))
		Scheduler.unstable_flushAll()

		root.render(React.createElement(AsyncRoot, { foo = false }))
		Scheduler.unstable_flushAll()
	end)
	it('should also warn inside of "strict" mode trees', function()
		local StrictMode = React.StrictMode

		local Foo = React.Component:extend("Foo")
		function Foo:UNSAFE_componentWillReceiveProps() end
		function Foo:render()
			return nil
		end

		local Bar = React.Component:extend("Bar")
		function Bar:UNSAFE_componentWillReceiveProps() end
		function Bar:render()
			return nil
		end

		local function Wrapper(props)
			return React.createElement(
				"div",
				nil,
				React.createElement(Bar),
				React.createElement(Foo)
			)
		end

		local SyncRoot = React.Component:extend("SyncRoot")
		function SyncRoot:UNSAFE_componentWillMount() end
		function SyncRoot:UNSAFE_componentWillUpdate() end
		function SyncRoot:UNSAFE_componentWillReceiveProps() end
		function SyncRoot:render()
			return React.createElement(StrictMode, nil, React.createElement(Wrapper))
		end

		-- ROBLOX deviation: using ReactNoop in place of ReactDOM
		local root = ReactNoop.createLegacyRoot()

		jestExpect(function()
			return root.render(React.createElement(SyncRoot))
		end).toErrorDev(
			"Using UNSAFE_componentWillReceiveProps in strict mode is not recommended",
			{ withoutStack = true }
		)

		-- Dedupe
		root.render(React.createElement(SyncRoot))
	end)
end)
describe("symbol checks", function()
	beforeEach(function()
		jest.resetModules()
		React = require(script.Parent.Parent)
		-- ROBLOX deviation: using ReactNoop in place of ReactDOM
		ReactNoop = require(Packages.Dev.ReactNoopRenderer)
		-- ReactDOM = require('react-dom')
		-- ReactDOMServer = require('react-dom/server')
		Scheduler = require(Packages.Dev.Scheduler)
	end)
	it("should switch from StrictMode to a Fragment and reset state", function()
		local Fragment, StrictMode = React.Fragment, React.StrictMode

		local ChildComponent = React.Component:extend("ChildComponent")

		function ChildComponent:init()
			self.state = {
				count = 0,
			}
		end

		function ChildComponent.getDerivedStateFromProps(nextProps, prevState)
			return {
				count = prevState.count + 1,
			}
		end
		function ChildComponent:render()
			return string.format("count:%s", self.state.count)
		end

		local function ParentComponent(props)
			local useFragment = props.useFragment

			return (function()
				if useFragment then
					return React.createElement(
						Fragment,
						nil,
						React.createElement(ChildComponent)
					)
				end

				return React.createElement(
					StrictMode,
					nil,
					React.createElement(ChildComponent)
				)
			end)()
		end

		-- ROBLOX deviation: use ReactNoop.render to render instead of ReactDOM.render
		ReactNoop.act(function()
			ReactNoop.render(
				React.createElement(ParentComponent, { useFragment = false })
			)
		end)
		jestExpect(ReactNoop.getChildren()[1].text).toEqual("count:1")

		-- ROBLOX deviation: use ReactNoop.render to render instead of ReactDOM.render
		ReactNoop.act(function()
			ReactNoop.render(React.createElement(ParentComponent, { useFragment = true }))
		end)
		jestExpect(ReactNoop.getChildren()[1].text).toEqual("count:1")
	end)
	it("should switch from a Fragment to StrictMode and reset state", function()
		local Fragment, StrictMode = React.Fragment, React.StrictMode

		local ChildComponent = React.Component:extend("ChildComponent")

		function ChildComponent:init()
			self.state = {
				count = 0,
			}
		end
		function ChildComponent.getDerivedStateFromProps(nextProps, prevState)
			return {
				count = prevState.count + 1,
			}
		end
		function ChildComponent:render()
			return string.format("count:%s", self.state.count)
		end

		local function ParentComponent(props)
			local useFragment = props.useFragment

			return (function()
				if useFragment then
					return React.createElement(
						Fragment,
						nil,
						React.createElement(ChildComponent)
					)
				end

				return React.createElement(
					StrictMode,
					nil,
					React.createElement(ChildComponent)
				)
			end)()
		end

		-- ROBLOX deviation: use ReactNoop.render to render instead of ReactDOM.render
		ReactNoop.act(function()
			ReactNoop.render(
				React.createElement(ParentComponent, { useFragment = false })
			)
		end)
		jestExpect(ReactNoop.getChildren()[1].text).toEqual("count:1")

		-- ROBLOX deviation: use ReactNoop.render to render instead of ReactDOM.render
		ReactNoop.act(function()
			ReactNoop.render(React.createElement(ParentComponent, { useFragment = true }))
		end)
		jestExpect(ReactNoop.getChildren()[1].text).toEqual("count:1")
	end)
	it("should update with StrictMode without losing state", function()
		local StrictMode = React.StrictMode

		local ChildComponent = React.Component:extend("ChildComponent")

		function ChildComponent:init()
			self.state = {
				count = 0,
			}
		end
		function ChildComponent.getDerivedStateFromProps(nextProps, prevState)
			return {
				count = prevState.count + 1,
			}
		end
		function ChildComponent:render()
			return string.format("count:%s", self.state.count)
		end

		local function ParentComponent()
			return React.createElement(
				StrictMode,
				nil,
				React.createElement(ChildComponent)
			)
		end

		-- ROBLOX deviation: use ReactNoop.render to render instead of ReactDOM.render
		ReactNoop.act(function()
			ReactNoop.render(React.createElement(ParentComponent))
		end)
		jestExpect(ReactNoop.getChildren()[1].text).toEqual("count:1")

		-- ROBLOX deviation: use ReactNoop.render to render instead of ReactDOM.render
		ReactNoop.act(function()
			ReactNoop.render(React.createElement(ParentComponent))
		end)
		jestExpect(ReactNoop.getChildren()[1].text).toEqual("count:2")
	end)
end)
-- ROBLOX deviation START: we removed support for string refs, so skip test
describe("string refs", function()
	beforeEach(function()
		jest.resetModules()
		React = require(script.Parent.Parent)
		-- ROBLOX deviation: using ReactNoop in place of ReactDOM
		ReactNoop = require(Packages.Dev.ReactNoopRenderer)
		-- ReactDOM = require('react-dom')
		-- ReactDOMServer = require('react-dom/server')
		Scheduler = require(Packages.Dev.Scheduler)
	end)

	xit("should warn within a strict tree", function()
		-- local StrictMode = React.StrictMode
		-- local OuterComponent = React.Component:extend("OuterComponent")

		-- local InnerComponent = React.Component:extend("InnerComponent")

		-- function InnerComponent:render()
		--     return nil
		-- end

		-- function OuterComponent:render()
		--     return React.createElement(StrictMode, nil, React.createElement(InnerComponent, {
		--         ref = 'somestring',
		--     }))
		-- end

		-- jestExpect(function()
		--     -- ROBLOX deviation: using ReactNoop in place of ReactDOM
		--     ReactNoop.act(function()
		--         ReactNoop.render(React.createElement(OuterComponent))
		--     end)
		-- end).toErrorDev(
		--     'Warning: A string ref, "somestring", has been found within a strict mode tree. ' ..
		--         'String refs are a source of potential bugs and should be avoided. ' ..
		--         'We recommend using useRef() or createRef() instead. ' ..
		--         'Learn more about using refs safely here: ' ..
		--         'https://reactjs.org/link/strict-mode-string-ref\n' ..
		--         '    in OuterComponent (at **)'
		-- )

		-- -- Dedup
		-- -- ROBLOX deviation: using ReactNoop in place of ReactDOM
		-- ReactNoop.act(function()
		--     ReactNoop.render(React.createElement(OuterComponent))
		-- end)
	end)

	xit("should warn within a strict tree 2", function()
		-- local StrictMode = React.StrictMode

		-- local MiddleComponent = React.Component:extend("MiddleComponent")

		-- function MiddleComponent:render()
		--     return nil
		-- end

		-- local InnerComponent = React.Component:extend("InnerComponent")

		-- function InnerComponent:render()
		--     return React.createElement(MiddleComponent, {
		--         ref = 'somestring',
		--     })
		-- end

		-- local OuterComponent = React.Component:extend("OuterComponent")

		-- function OuterComponent:render()
		--     return React.createElement(StrictMode, nil, React.createElement(InnerComponent))
		-- end

		-- jestExpect(function()
		--     -- ROBLOX deviation: using ReactNoop in place of ReactDOM
		--     ReactNoop.act(function()
		--         ReactNoop.render(React.createElement(OuterComponent))
		--     end)
		-- end).toErrorDev(
		--     'Warning: A string ref, "somestring", has been found within a strict mode tree. ' ..
		--         'String refs are a source of potential bugs and should be avoided. ' ..
		--         'We recommend using useRef() or createRef() instead. ' ..
		--         'Learn more about using refs safely here: ' ..
		--         'https://reactjs.org/link/strict-mode-string-ref\n' ..
		--         '    in InnerComponent (at **)\n' ..
		--         '    in OuterComponent (at **)'
		-- )
		-- -- Dedup
		-- -- ROBLOX deviation: using ReactNoop in place of ReactDOM
		-- ReactNoop.act(function()
		--     ReactNoop.render(React.createElement(OuterComponent))
		-- end)
	end)
end)
-- ROBLOX deviation END
describe("context legacy", function()
	beforeEach(function()
		jest.resetModules()
		React = require(script.Parent.Parent)
		-- ROBLOX deviation: using ReactNoop in place of ReactDOM
		ReactNoop = require(Packages.Dev.ReactNoopRenderer)
		-- ReactDOM = require('react-dom')
		-- ReactDOMServer = require('react-dom/server')
		Scheduler = require(Packages.Dev.Scheduler)
		-- PropTypes = require('prop-types')
	end)
	-- ROBLOX TODO: Proptypes
	xit("should warn if the legacy context API have been used in strict mode", function()

		--     local function FunctionalLegacyContextConsumer()
		--         return nil
		--     end

		--     local LegacyContextConsumer = React.Component:extend("LegacyContextConsumer")

		--     function LegacyContextConsumer:render()
		--         return nil
		--     end

		--     local StrictMode = React.StrictMode

		--     LegacyContextConsumer.contextTypes = {
		--         color = PropTypes.string,
		--     }
		--     FunctionalLegacyContextConsumer.contextTypes = {
		--         color = PropTypes.string,
		--     }

		--     local LegacyContextProvider = React.Component:extend("LegacyContextProvider")

		--     function LegacyContextProvider:getChildContext()
		--         return{
		--             color = 'purple',
		--         }
		--     end
		--     function LegacyContextProvider:render()
		--         return React.createElement('div', nil, React.createElement(LegacyContextConsumer), React.createElement(FunctionalLegacyContextConsumer))
		--     end

		--     LegacyContextProvider.childContextTypes = {
		--         color = PropTypes.string,
		--     }

		--     local Root = React.Component:extend("Root")

		--     function Root:render()
		--         return React.createElement('div', nil, React.createElement(StrictMode, nil, React.createElement(LegacyContextProvider)))
		--     end

		--     jestExpect(function()
		--         ReactNoop.render(React.createElement(Root))
		--     end).toErrorDev('Warning: Legacy context API has been detected within a strict-mode tree.' .. '\n\nThe old API will be supported in all 16.x releases, but applications ' .. 'using it should migrate to the new version.' .. '\n\nPlease update the following components: ' .. 'FunctionalLegacyContextConsumer, LegacyContextConsumer, LegacyContextProvider' .. '\n\nLearn more about this warning here: ' .. 'https://reactjs.org/link/legacy-context' .. '\n    in LegacyContextProvider (at **)' .. '\n    in div (at **)' .. '\n    in Root (at **)')
		--     ReactNoop.render(React.createElement(Root))
	end)
end)
