Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

What are the .spec descendants of game?

I ran a for loop through game like this:

for _,d in pairs(game:GetDescendants()) do
	print(d)
end

It gave me every descendant of game (over 1,800, apparently) and within that group were things ending in .spec. These "things" appear to be associated with an actual child. What exactly are these .spec things? (Example: Action.spec)

1 comment

0

I have tried this myself and also searched Google but nothing came up on Google either, I am guessing and going to say that .spec means specification?

3 answers

✓ Accepted answer

These are unit test modules using TestEZ. TestEZ will automatically execute any files suffixed with .spec.lua or Roblox modules suffixed with .spec.

The globals describe, it, and expect are inspired by busted.

1 comment

0

Yes. Thank you.

I ran a GetFullName on them, and they seem to be in Roblox's GUI

Here's the full dump if your curious

Also, I looked for one of them via CoreGui and they look to be ModuleScripts

CoreGui.RobloxGui.Modules.Settings.Pages.ShareGame.Analytics.InviteToGameAnalytics.spec
CoreGui.RobloxGui.Modules.Settings.Actions.GetRecentlyPlayedGames.spec
CoreGui.RobloxGui.Modules.Settings.Actions.SetRecentlyPlayedGames.spec
CoreGui.RobloxGui.Modules.Settings.Actions.SetRecentlyPlayedGamesFetching.spec
CoreGui.RobloxGui.Modules.DevConsole.Reducers.ScriptsData.spec
CoreGui.RobloxGui.Modules.DevConsole.Reducers.MicroProfiler.spec
CoreGui.RobloxGui.Modules.DevConsole.Reducers.MainView.spec
CoreGui.RobloxGui.Modules.DevConsole.Reducers.LogData.spec
CoreGui.RobloxGui.Modules.DevConsole.Reducers.DevConsoleReducer.spec
CoreGui.RobloxGui.Modules.DevConsole.Reducers.DataStoresData.spec
CoreGui.RobloxGui.Modules.DevConsole.Reducers.ActionBindingsData.spec
CoreGui.RobloxGui.Modules.DevConsole.Reducers.MemoryData.spec
CoreGui.RobloxGui.Modules.DevConsole.Reducers.ServerJobsData.spec
CoreGui.RobloxGui.Modules.DevConsole.Reducers.NetworkData.spec
CoreGui.RobloxGui.Modules.DevConsole.Reducers.ServerStatsData.spec
CoreGui.RobloxGui.Modules.DevConsole.Reducers.DevConsoleDisplayOptions.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.UtilAndTab.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.ServerStats.ServerStatsChart.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.ServerStats.MainViewServerStats.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.ServerJobs.ServerJobsChart.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.ServerJobs.MainViewServerJobs.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.SearchBar.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.ScrollingTextBox.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Scripts.ServerScripts.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Scripts.MainViewScripts.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Scripts.ServerScriptsEntry.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Network.ServerNetwork.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Network.NetworkView.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Network.NetworkChart.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Network.MainViewNetwork.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Network.ClientNetwork.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Network.NetworkSummary.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Network.NetworkChartEntry.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.MicroProfiler.MainViewMicroProfiler.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.MicroProfiler.ServerProfilerInterface.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Memory.ServerMemory.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Memory.MemoryView.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Memory.MainViewMemory.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Memory.MemoryViewEntry.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Memory.ClientMemory.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Log.ServerLog.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Log.MainViewLog.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Log.LogOutput.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Log.LogData.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Log.DevConsoleCommandLine.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.Log.ClientLog.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.LiveUpdateElement.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.DropDown.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.DevConsoleWindow.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.DevConsoleTopBar.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.DataStores.MainViewDataStores.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.DataStores.DataStoresChart.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.TabRowButton.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.CheckBoxDropDown.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.CheckBox.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.ActionBindings.MainViewActionBindings.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.ActionBindings.ActionBindingsChart.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.ClientServerButton.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.FullScreenDropDownButton.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.TabRowContainer.spec
CoreGui.RobloxGui.Modules.DevConsole.Components.CheckBoxContainer.spec
CoreGui.RobloxGui.Modules.DevConsole.CircularBuffer.spec

I also looked through the source of the "InviteToGameAnalystics.spec" module. Here's it's source. There is a lot of unknown variables though

return function()
	local CorePackages = game:GetService("CorePackages")
	local InviteToGameAnalytics = require(script.Parent.InviteToGameAnalytics)
	local Signal = require(CorePackages.AppTempCommon.Common.Signal)

	local function createMockEventStream()
		local eventStream = {
			onSetRBXEventStream = Signal.new(),
		}

		function eventStream:setRBXEventStream(...)
			self.onSetRBXEventStream:fire(...)
		end

		return eventStream
	end

	local function createMockDiag()
		local diag = {
			onReportCounter = Signal.new(),
		}

		function diag:reportCounter(...)
			self.onReportCounter:fire(...)
		end

		return diag
	end

	describe("new", function()
		it("SHOULD return an object", function()
			local analytics = InviteToGameAnalytics.new()
			expect(analytics).to.be.ok()
		end)
	end)

	describe("withEventStream", function()
		it("SHOULD return the original object", function()
			local analytics = InviteToGameAnalytics.new():withEventStream()

			expect(analytics).to.be.ok()
		end)
	end)

	describe("withDiag", function()
		it("SHOULD return the original object", function()
			local analytics = InviteToGameAnalytics.new():withDiag()

			expect(analytics).to.be.ok()
		end)
	end)

	describe("withButtonName", function()
		it("SHOULD return the original object", function()
			local analytics = InviteToGameAnalytics.new():withEventStream()

			expect(analytics).to.be.ok()
		end)
	end)

	describe("_getEventStream", function()
		it("SHOULD return the event stream when injected", function()
			local eventStreamMock = {}
			local analytics = InviteToGameAnalytics.new():withEventStream(eventStreamMock)

			expect(analytics).to.be.ok()
			expect(analytics:_getEventStream()).to.equal(eventStreamMock)
		end)

		it("SHOULD throw if not provided an EventStream", function()
			local analytics = InviteToGameAnalytics.new()

			expect(analytics).to.be.ok()
			expect(function()
				analytics:_getEventStream()
			end).to.throw()
		end)
	end)

	describe("_getButtonName", function()
		it("SHOULD return the context when injected", function()
			local buttonMock = "testing"
			local analytics = InviteToGameAnalytics.new():withButtonName(buttonMock)

			expect(analytics).to.be.ok()
			expect(analytics:_getButtonName()).to.equal(buttonMock)
		end)

		it("SHOULD throw if not provided a Context", function()
			local analytics = InviteToGameAnalytics.new()

			expect(analytics).to.be.ok()
			expect(function()
				analytics:_getButtonName()
			end).to.throw()
		end)
	end)

	describe("inputShareGameEntryPoint", function()
		it("SHOULD fire `EventName.EntryPoint` event", function()
			local mockButtonName = "testing123"
			local mockEventStream = createMockEventStream()

			local lastEventContext = nil
			local lastEventName = nil

			mockEventStream.onSetRBXEventStream:connect(function(_, eventName, additionalArgs)
				lastEventContext = additionalArgs.btn
				lastEventName = eventName
			end)

			local analytics = InviteToGameAnalytics.new()
				:withButtonName(mockButtonName)
				:withEventStream(mockEventStream)
				:withDiag(createMockDiag())

			analytics:inputShareGameEntryPoint()

			expect(lastEventContext).to.equal(mockButtonName)
			expect(lastEventName).to.equal(InviteToGameAnalytics.EventName.EntryPoint)
		end)
	end)

	describe("onActivatedInviteSent", function()
		it("SHOULD fire `EventName.InviteSent` event", function()
			local mockButtonName = "testing123"
			local mockEventStream = createMockEventStream()

			local lastEventContext = nil
			local lastEventName = nil

			mockEventStream.onSetRBXEventStream:connect(function(_, eventName, additionalArgs)
				lastEventContext = additionalArgs.btn
				lastEventName = eventName
			end)

			local analytics = InviteToGameAnalytics.new()
				:withButtonName(mockButtonName)
				:withEventStream(mockEventStream)
				:withDiag(createMockDiag())

			analytics:onActivatedInviteSent("senderId", "conversationId", {})

			expect(lastEventContext).to.equal(mockButtonName)
			expect(lastEventName).to.equal(InviteToGameAnalytics.EventName.InviteSent)
		end)

		it("SHOULD fire a diag counter", function()
			local mockDiag = createMockDiag()

			local diagSum = 0
			mockDiag.onReportCounter:connect(function()
				diagSum = diagSum + 1
			end)

			local analytics = InviteToGameAnalytics.new()
				:withButtonName(InviteToGameAnalytics.ButtonName.SettingsHub)
				:withEventStream(createMockEventStream())
				:withDiag(mockDiag)

			analytics:onActivatedInviteSent("senderId", "conversationId", {"recipientId"})

			expect(diagSum).to.equal(1)
		end)
	end)
end

3 comments

0

I already looked at the full dump. I just want to know what they are specifically.

0

they look like they run Roblox's GUI

0

idk specifically what each one does though

it appears to be a file that has to do with rpmbuild, some thing for developers i guess, im not too sure though, however what i think it is, is that its something internal thats used by the roblox devs that regular roblox users dont need to worry about

This discussion is preserved as it was. New answers, comments, and votes are closed.