local M=script.Parent.Parent local P=require(M.Dev.JestGlobals)local V=P.expect local b=require(M.Promise)local K=(require(script.Parent.properties)).testMethodProperty return function()local M beforeEach(function()M=_G.Observable end)describe("\115\117\098\115\099\114\105\098\101",function()it("\105\115 \097 \109\101\116\104\111\100 \111\102 \079\098\115\101\114\118\097\098\108\101\046\112\114\111\116\111\116\121\112\101",function()K(M,"\115\117\098\115\099\114\105\098\101",{configurable=true;writable=true;length=4})end)it("\097\099\099\101\112\116\115 \097\110 \111\098\115\101\114\118\101\114 \097\114\103\117\109\101\110\116",function()local P local b;(M.new(function(M)P=M end)):subscribe({next=function(M,P)b=P end})P:next(1);(V(b)).toBe(1)end)it("\097\099\099\101\112\116\115 \097 \110\101\120\116 \102\117\110\099\116\105\111\110 \097\114\103\117\109\101\110\116",function()local P local b;(M.new(function(M)P=M end)):subscribe(function(M,P)b=P end)P:next(1);(V(b)).toBe(1)end)it("\097\099\099\101\112\116\115 \097\110 \101\114\114\111\114 \102\117\110\099\116\105\111\110 \097\114\103\117\109\101\110\116",function()local P local b local K={};(M.new(function(M)P=M end)):subscribe(nil,function(M,P)b=P end)P:error(K);(V(b)).toBe(K)end)it("\097\099\099\101\112\116\115 \097 \099\111\109\112\108\101\116\101 \102\117\110\099\116\105\111\110 \097\114\103\117\109\101\110\116",function()local P local b=false;(M.new(function(M)P=M end)):subscribe(nil,nil,function(M)b=true return b end)P:complete();(V(b)).toBe(true)end)it("\117\115\101\115 \102\117\110\099\116\105\111\110 \111\118\101\114\108\111\097\100 \105\102 \102\105\114\115\116 \097\114\103\117\109\101\110\116 \105\115 \110\117\108\108",function()local P local b=false;(M.new(function(M)P=M end)):subscribe(nil,nil,function(M)b=true return b end)P:complete();(V(b)).toBe(true)end)it("\117\115\101\115 \102\117\110\099\116\105\111\110 \111\118\101\114\108\111\097\100 \105\102 \102\105\114\115\116 \097\114\103\117\109\101\110\116 \105\115 \097 \112\114\105\109\105\116\105\118\101",function()local P local b=false;(M.new(function(M)P=M end)):subscribe("\097\098\099",nil,function(M)b=true return b end)P:complete();(V(b)).toBe(true)end)it("\101\110\113\117\101\117\101\115 \097 \106\111\098 \116\111 \115\101\110\100 \101\114\114\111\114 \105\102 \115\117\098\115\099\114\105\098\101\114 \116\104\114\111\119\115",function()local P={}local K=nil;(M.new(function()error(P)end)):subscribe({error=function(M,P)K=P end});(V(K)).toBe(nil);(b.delay(0)):expect();(V(K)).toBe(P)end)it("\100\111\101\115 \110\111\116 \115\101\110\100 \101\114\114\111\114 \105\102 \117\110\115\117\098\115\099\114\105\098\101\100",function()local P={}local b=nil local K=(M.new(function()error(P)end)):subscribe({error=function(M,P)b=P end})K:unsubscribe();(V(b)).toBe(nil)wait();(V(b)).toBe(nil)end)it("\097\099\099\101\112\116\115 \097 \099\108\101\097\110\117\112 \102\117\110\099\116\105\111\110 \102\114\111\109 \116\104\101 \115\117\098\115\099\114\105\098\101\114 \102\117\110\099\116\105\111\110",function()local P=false local b=(M.new(function()return function()P=true end end)):subscribe()b:unsubscribe();(V(P)).toBe(true)end)it("\097\099\099\101\112\116\115 \097 \115\117\098\115\099\114\105\112\116\105\111\110 \116\097\098\108\101 \102\114\111\109 \116\104\101 \115\117\098\115\099\114\105\098\101\114 \102\117\110\099\116\105\111\110",function()local P=false local b=(M.new(function()return{unsubscribe=function(M)P=true end}end)):subscribe()b:unsubscribe();(V(P)).toBe(true)end)end)end
-- ROBLOX upstream https://github.com/zenparsing/zen-observable/blob/v0.8.15/test/subscribe.js
local rootWorkspace = script.Parent.Parent

local JestGlobals = require(rootWorkspace.Dev.JestGlobals)
local jestExpect = JestGlobals.expect

local Promise = require(rootWorkspace.Promise)

local testMethodProperty = require(script.Parent.properties).testMethodProperty

return function()
	-- ROBLOX deviation: upstream a global variable is created in the test setup.
	-- A local variable is created to avoid using _G.Observable in every test
	local Observable
	beforeEach(function()
		Observable = _G.Observable
	end)
	describe("subscribe", function()
		it("is a method of Observable.prototype", function()
			testMethodProperty(
				--ROBLOX deviation, no prototype
				Observable,
				"subscribe",
				{
					configurable = true,
					writable = true,
					length = 4, --[[ in JS, only there's only 1 arg , but the implementation uses arguments to get optional params, in Lua these are explicit  ]]
				}
			)
		end)

		it("accepts an observer argument", function()
			local observer
			local nextValue

			Observable.new(function(x)
				observer = x
			end):subscribe({
				next = function(self, v)
					nextValue = v
				end,
			})
			observer:next(1)
			jestExpect(nextValue).toBe(1)
		end)

		it("accepts a next function argument", function()
			local observer
			local nextValue
			Observable.new(function(x)
				observer = x
			end):subscribe(function(self, v)
				nextValue = v
			end)
			observer:next(1)
			jestExpect(nextValue).toBe(1)
		end)

		it("accepts an error function argument", function()
			local observer
			local errorValue
			local error = {}
			Observable.new(function(x)
				observer = x
			end):subscribe(nil, function(self, e)
				errorValue = e
			end)
			observer:error(error)
			jestExpect(errorValue).toBe(error)
		end)

		it("accepts a complete function argument", function()
			local observer
			local completed = false
			Observable.new(function(x)
				observer = x
			end):subscribe(nil, nil, function(self)
				completed = true
				return completed
			end)
			observer:complete()
			jestExpect(completed).toBe(true)
		end)

		it("uses function overload if first argument is null", function()
			local observer
			local completed = false
			Observable.new(function(x)
				observer = x
			end):subscribe(nil, nil, function(self)
				completed = true
				return completed
			end)
			observer:complete()
			jestExpect(completed).toBe(true)
		end)

		it("uses function overload if first argument is a primitive", function()
			local observer
			local completed = false
			Observable.new(function(x)
				observer = x
			end):subscribe("abc", nil, function(self)
				completed = true
				return completed
			end)
			observer:complete()
			jestExpect(completed).toBe(true)
		end)

		it("enqueues a job to send error if subscriber throws", function()
			local anError = {}
			local errorValue = nil
			Observable.new(function()
				error(anError)
			end):subscribe({
				error = function(self, e)
					errorValue = e
				end,
			})

			jestExpect(errorValue).toBe(nil)
			Promise.delay(0):expect()
			jestExpect(errorValue).toBe(anError)
		end)

		it("does not send error if unsubscribed", function()
			local anError = {}
			local errorValue = nil
			local subscription = Observable.new(function()
				error(anError)
			end):subscribe({
				error = function(self, e)
					errorValue = e
				end,
			})

			subscription:unsubscribe()
			jestExpect(errorValue).toBe(nil)
			wait()
			jestExpect(errorValue).toBe(nil)
		end)

		it("accepts a cleanup function from the subscriber function", function()
			local cleanupCalled = false
			local subscription = Observable.new(function()
				return function()
					cleanupCalled = true
				end
			end):subscribe()

			subscription:unsubscribe()
			jestExpect(cleanupCalled).toBe(true)
		end)

		it("accepts a subscription table from the subscriber function", function()
			local cleanupCalled = false
			local subscription = Observable.new(function()
				return {
					unsubscribe = function(self)
						cleanupCalled = true
					end,
				}
			end):subscribe()
			subscription:unsubscribe()
			jestExpect(cleanupCalled).toBe(true)
		end)
	end)
end
