[{"data":1,"prerenderedAt":1810},["ShallowReactive",2],{"navigation":3,"\u002Fdocs\u002Fchannels-and-tests":135,"\u002Fdocs\u002Fchannels-and-tests-surround":1805},[4],{"title":5,"path":6,"stem":7,"children":8,"page":134},"Docs","\u002Fdocs","docs",[9,13,17,21,25,29,33,37,41,45,49,53,57,61,70,74,78,82,86,90,94,98,102,106,110,114,118,122,126,130],{"title":10,"path":11,"stem":12},"AI harnesses: LLM tools, MCP servers and agents","\u002Fdocs\u002Fai-tools","docs\u002Fai-tools",{"title":14,"path":15,"stem":16},"Architecture","\u002Fdocs\u002Farchitecture","docs\u002Farchitecture",{"title":18,"path":19,"stem":20},"Web \u002F native bridges","\u002Fdocs\u002Fbridges","docs\u002Fbridges",{"title":22,"path":23,"stem":24},"Broadcast channels and tests","\u002Fdocs\u002Fchannels-and-tests","docs\u002Fchannels-and-tests",{"title":26,"path":27,"stem":28},"CLI reference","\u002Fdocs\u002Fcli","docs\u002Fcli",{"title":30,"path":31,"stem":32},"Completeness: how far an answer reaches","\u002Fdocs\u002Fcompleteness","docs\u002Fcompleteness",{"title":34,"path":35,"stem":36},"Configuration","\u002Fdocs\u002Fconfiguration","docs\u002Fconfiguration",{"title":38,"path":39,"stem":40},"External systems","\u002Fdocs\u002Fexternal","docs\u002Fexternal",{"title":42,"path":43,"stem":44},"Generated, copied and vendored files","\u002Fdocs\u002Fgenerated","docs\u002Fgenerated",{"title":46,"path":47,"stem":48},"Installing and updating cg","\u002Fdocs\u002Finstall","docs\u002Finstall",{"title":50,"path":51,"stem":52},"Java","\u002Fdocs\u002Fjava","docs\u002Fjava",{"title":54,"path":55,"stem":56},"Kotlin","\u002Fdocs\u002Fkotlin","docs\u002Fkotlin",{"title":58,"path":59,"stem":60},"Known limitations","\u002Fdocs\u002Flimitations","docs\u002Flimitations",{"title":62,"path":63,"stem":64,"children":65},"MCP server","\u002Fdocs\u002Fmcp","docs\u002Fmcp",[66],{"title":67,"path":68,"stem":69},"code-graph MCP: sample outputs (real calls via the MCP Python SDK stdio client)","\u002Fdocs\u002Fmcp\u002Fsample_outputs","docs\u002Fmcp\u002Fsample_outputs",{"title":71,"path":72,"stem":73},"Rust, C and C++","\u002Fdocs\u002Fnative","docs\u002Fnative",{"title":75,"path":76,"stem":77},"Port gaps: cg parity","\u002Fdocs\u002Fparity","docs\u002Fparity",{"title":79,"path":80,"stem":81},"PHP","\u002Fdocs\u002Fphp","docs\u002Fphp",{"title":83,"path":84,"stem":85},"Planned changes","\u002Fdocs\u002Fplans","docs\u002Fplans",{"title":87,"path":88,"stem":89},"Platform-specific code","\u002Fdocs\u002Fplatforms","docs\u002Fplatforms",{"title":91,"path":92,"stem":93},"Protocol links","\u002Fdocs\u002Fprotocols","docs\u002Fprotocols",{"title":95,"path":96,"stem":97},"Python","\u002Fdocs\u002Fpython","docs\u002Fpython",{"title":99,"path":100,"stem":101},"Quick start","\u002Fdocs\u002Fquickstart","docs\u002Fquickstart",{"title":103,"path":104,"stem":105},"Graph schema","\u002Fdocs\u002Fschema","docs\u002Fschema",{"title":107,"path":108,"stem":109},"Attack surface","\u002Fdocs\u002Fsurface","docs\u002Fsurface",{"title":111,"path":112,"stem":113},"Swift","\u002Fdocs\u002Fswift","docs\u002Fswift",{"title":115,"path":116,"stem":117},"TypeScript \u002F JavaScript frameworks","\u002Fdocs\u002Fts-frameworks","docs\u002Fts-frameworks",{"title":119,"path":120,"stem":121},"How we validate","\u002Fdocs\u002Fvalidation","docs\u002Fvalidation",{"title":123,"path":124,"stem":125},"Validation log","\u002Fdocs\u002Fvalidation-log","docs\u002Fvalidation-log",{"title":127,"path":128,"stem":129},"Value facts and resolutions","\u002Fdocs\u002Fvalue-facts","docs\u002Fvalue-facts",{"title":131,"path":132,"stem":133},"Visual view","\u002Fdocs\u002Fviz","docs\u002Fviz",false,{"id":136,"title":22,"body":137,"description":1799,"extension":1800,"meta":1801,"navigation":1802,"path":23,"seo":1803,"stem":24,"__hash__":1804},"docs\u002Fdocs\u002Fchannels-and-tests.md",{"type":138,"value":139,"toc":1789},"minimark",[140,161,166,200,256,382,474,504,514,585,596,602,612,616,668,914,966,984,987,1069,1163,1238,1249,1383,1481,1498,1504,1560,1575,1580,1666,1709,1731,1742,1745],[141,142,143,144,148,149,152,153,156,157,160],"p",{},"Realtime channels (who may join, what publishes, which client listens) and test code (which\ntests exercise a symbol, route or table). Examples are the task-board fixture in\n",[145,146,147],"code",{},"tests\u002Fbroadcast_fixture"," (",[145,150,151],{},"api\u002F"," Laravel, ",[145,154,155],{},"web\u002F"," Nuxt, joined with ",[145,158,159],{},"cg link",").",[162,163,165],"h2",{"id":164},"broadcast-channels","Broadcast channels",[141,167,168,169,172,173,176,177,180,181,180,184,187,188,191,192,195,196,199],{},"Laravel ",[145,170,171],{},"Broadcast::channel('name.{param}', callback)"," in ",[145,174,175],{},"routes\u002Fchannels.php"," (and files\nloaded by ",[145,178,179],{},"Broadcast::routes()"," \u002F ",[145,182,183],{},"withBroadcasting()",[145,185,186],{},"require",") becomes ",[145,189,190],{},"channel:\u003Cpattern>","\n. The callback is entry kind ",[145,193,194],{},"channel_auth",". The auth route links to every channel with\n",[145,197,198],{},"AUTHORIZES_CHANNEL",".",[141,201,202,180,205,208,209,212,213,216,217,220,221,224,225,228,229,216,232,235,236,238,239,180,242,180,245,248,249,180,252,255],{},[145,203,204],{},"ShouldBroadcast",[145,206,207],{},"ShouldBroadcastNow",": ",[145,210,211],{},"broadcastOn()"," is evaluated (literals,\ninterpolation, concatenation, ",[145,214,215],{},"sprintf",", ",[145,218,219],{},"implode",", constants, helpers, constructor properties\nfilled at the dispatch site). ",[145,222,223],{},"BROADCASTS_ON"," carries the name, the type (",[145,226,227],{},"Channel",",\n",[145,230,231],{},"PrivateChannel",[145,233,234],{},"PresenceChannel",") and where the value came from. Publishers that all use\n",[145,237,234],{}," make a presence channel. ",[145,240,241],{},"event(new X)",[145,243,244],{},"X::dispatch()",[145,246,247],{},"broadcast(new X)","\nstay ordinary ",[145,250,251],{},"INSTANTIATES",[145,253,254],{},"DISPATCHES"," edges.",[141,257,258,259,180,262,180,265,180,268,271,272,180,275,278,279,180,282,285,286,289,290,293,294,297,298,301,302,305,306,180,309,216,312,315,316,319,320,180,323,326,327,148,329,332,333,336,337,216,340,343,344,216,347,350,351,354,355,358,359,362,363,366,367,370,371,374,375,216,378,381],{},"Client (TS \u002F JS \u002F Vue): Laravel Echo (",[145,260,261],{},".private",[145,263,264],{},".channel",[145,266,267],{},".join",[145,269,270],{},".listen"," \u002F\n",[145,273,274],{},".listenForWhisper",[145,276,277],{},".notification","), pusher-js (",[145,280,281],{},"subscribe",[145,283,284],{},"bind",") and ",[145,287,288],{},"useEcho"," become\n",[145,291,292],{},"channel_sub:\u003Cname>"," with ",[145,295,296],{},"SUBSCRIBES_CHANNEL",". ",[145,299,300],{},"`board.${id}`"," becomes ",[145,303,304],{},"board.{id}",".\nThe receiver may be ",[145,307,308],{},"Echo",[145,310,311],{},"new Echo(...)",[145,313,314],{},"window.Echo",", a name ending in ",[145,317,318],{},"echo",", a\n",[145,321,322],{},"ref()",[145,324,325],{},"shallowRef()"," whose type argument is ",[145,328,308],{},[145,330,331],{},"echo.value.private(...)",", including\nafter ",[145,334,335],{},"echo.value = new Echo(...)"," in the same file), or a store \u002F composable field typed or\ninitialised as an Echo client (",[145,338,339],{},"store.echo.private(...)",[145,341,342],{},"useEcho().client.private(...)",").\nThe same forms apply to pusher-js (",[145,345,346],{},"ref\u003CPusher>()",[145,348,349],{},".subscribe","). Listeners chained on the\nsubscription, or on a variable or property that holds it, are its events. ",[145,352,353],{},".leave()"," and\n",[145,356,357],{},".disconnect()"," are not subscriptions. A ",[145,360,361],{},".private(...)"," call with a channel literal whose\nreceiver stays unknown is counted as ",[145,364,365],{},"realtime_subscriptions_unresolved_receiver"," (file and\nline under ",[145,368,369],{},"cg coverage --details","). ",[145,372,373],{},"resources\u002Fjs"," (and ",[145,376,377],{},"resources\u002Fts",[145,379,380],{},"resources\u002Fassets\u002Fjs",")\nof a Laravel app are indexed as TypeScript.",[141,383,384,385,388,389,301,392,395,396,398,399,402,403,406,407,410,411,271,414,180,417,180,420,423,424,427,428,431,432,435,436,439,440,443,444,447,448,451,452,455,456,459,460,463,464,466,467,470,471,473],{},"Subscription wrappers: when the whole channel argument of an Echo call is a parameter of the enclosing\nfunction (",[145,386,387],{},"export function privateChannel(name: string) { return echo.private(name) }","), the\nchannel is resolved at each call site of that function, the same way as a direct call:\n",[145,390,391],{},"privateChannel(`store.${storeId}.orders`)",[145,393,394],{},"store.{storeId}.orders",", with the\nwrapper's visibility and one ",[145,397,296],{}," edge per call site (the edge's file and line\nare the call site). One level of nesting is followed: ",[145,400,401],{},"ordersChannel(id)"," calling\n",[145,404,405],{},"privateChannel(`store.${id}.orders`)"," is expanded at the callers of ",[145,408,409],{},"ordersChannel",". Wrappers\nexported from a composable or utility module and imported by callers (including Nuxt\nauto-imports, where the call edge resolves) are expanded the same way. ",[145,412,413],{},".listen()",[145,415,416],{},".listenToAll()",[145,418,419],{},".notification()",[145,421,422],{},".listenForWhisper()"," chained on the wrapper call, or on a\nconst holding its result, join the events chained inside the wrapper. Each expanded edge carries\n",[145,425,426],{},"via_helper = {fn, at}",": the wrapper called at that site and the ",[145,429,430],{},"file:line"," of its Echo call. When a\ncall site passes a template built from the caller's own parameter (",[145,433,434],{},"privateChannel(`store.${storeId}.desk`)","\ninside ",[145,437,438],{},"openDesk(storeId)",") and no caller of ",[145,441,442],{},"openDesk"," resolves it, the call site keeps its own name with the\nparameter as a placeholder (",[145,445,446],{},"store.{storeId}.desk","), like a direct ",[145,449,450],{},"echo.private(...)"," there. A call site whose whole\nchannel is a runtime value or the caller's parameter and that no outer call site resolves emits no ",[145,453,454],{},"channel_sub"," (no\n",[145,457,458],{},"{name}"," placeholder next to the expanded names). Each such call site is counted as\n",[145,461,462],{},"realtime_subscriptions_unresolved_wrapper"," (call-site locations under ",[145,465,369],{},"), even when the\nwrapper resolves at other sites; chains deeper than two wrappers are counted as\n",[145,468,469],{},"realtime_subscriptions_wrapper_too_deep",". pusher-js ",[145,472,281],{}," wrappers are not expanded.",[141,475,476,374,478,481,482,485,486,489,490,285,493,496,497,500,501,503],{},[145,477,159],{},[145,479,480],{},"cg index"," in one repo) adds ",[145,483,484],{},"MATCHES_CHANNEL"," by pattern shape (\n",[145,487,488],{},"board.{boardId}"," ↔ ",[145,491,492],{},"board.{board}",[145,494,495],{},"LISTENS_FOR"," by class name, ",[145,498,499],{},"broadcastAs()"," (leading\n",[145,502,199],{},") or the short class name.",[505,506,512],"pre",{"className":507,"code":509,"language":510,"meta":511},[508],"language-text","$ cg channels board.42 --no-source --db out\u002Fgraph.db\n== channel board.{board}  [private]  @ backend\u002Froutes\u002Fchannels.php:22\nWHO CAN JOIN\n  auth route route:POST \u002Fapi\u002Fbroadcasting\u002Fauth  middleware=['api', 'auth:sanctum']\n  HANDLED_BY Broadcasting\\BoardChannel::join  @ backend\u002Fapp\u002FBroadcasting\u002FBoardChannel.php:10 [exact]\nPUBLISHED BY (1)\n  event:App\\Events\\TaskMoved  name=board.{board_id}  [private]\nLISTENED TO BY (1)\n  board.{boardId}  [private]  events: TaskMoved  (exact)\n      subscribed in useBoardRealtime @ frontend\u002Fapp\u002Fcomposables\u002FuseBoardRealtime.ts:5\n","text","",[145,513,509],{"__ignoreMap":511},[515,516,517,530],"table",{},[518,519,520],"thead",{},[521,522,523,527],"tr",{},[524,525,526],"th",{},"flag",[524,528,529],{},"meaning",[531,532,533,546,564,577],"tbody",{},[521,534,535,539],{},[536,537,538],"td",{},"UNDECLARED",[536,540,541,542,545],{},"private or presence channel with no ",[145,543,544],{},"Broadcast::channel","; the auth route rejects every client",[521,547,548,551],{},[536,549,550],{},"PUBLIC PUBLISH",[536,552,553,554,556,557,180,560,563],{},"events use a public ",[145,555,227],{}," whose name also has an auth callback (the callback only guards ",[145,558,559],{},"private-",[145,561,562],{},"presence-",")",[521,565,566,569],{},[536,567,568],{},"visibility mismatch",[536,570,571,574,575],{},[145,572,573],{},"Echo.channel"," for a ",[145,576,231],{},[521,578,579,582],{},[536,580,581],{},"(end of listing)",[536,583,584],{},"client subscriptions that match no backend channel",[141,586,587,588,591,592,595],{},"A pattern, a concrete name (",[145,589,590],{},"board.42",") or a glob (",[145,593,594],{},"board.*",") prints one block. With no\npattern, one line per channel:",[505,597,600],{"className":598,"code":599,"language":510,"meta":511},[508],"$ cg channels --db out\u002Fgraph.db\nchannels: 6\n  board.{board}  [private]  auth: App\\Broadcasting\\BoardChannel  checks: BoardChannel::join, BoardAccess::visibleBoardIds\n      publishers: 1 (event:App\\Events\\TaskMoved)  subscribers: 1\n  status  [public, undeclared]  auth: public: no auth\n  team.{teamId}  [private]  auth: closure routes\u002Fchannels.php:11\n      ! PUBLIC PUBLISH: an event publishes on a public Channel with this name\nclient subscriptions without a backend channel: 1\n  board.{boardId}.archive.events  [private]  events: BoardArchived\n",[145,601,599],{"__ignoreMap":511},[141,603,604,605,608,609,199],{},"Without ",[145,606,607],{},"--no-source"," the auth callback source is printed under WHO CAN JOIN. MCP:\n",[145,610,611],{},"channels(pattern?, source?)",[162,613,615],{"id":614},"tests","Tests",[141,617,618,619,622,623,626,627,630,631,216,634,216,637,216,640,643,644,647,648,228,651,654,655,658,659,662,663,667],{},"Each test case is a ",[145,620,621],{},"test:"," node (",[145,624,625],{},"entry_kind"," ",[145,628,629],{},"test","). Edges from test code are rewritten so\ntests never count as callers and never widen ",[145,632,633],{},"reaches",[145,635,636],{},"impact",[145,638,639],{},"writers",[145,641,642],{},"routes"," or\nentry tagging. An app a TypeScript test builds for itself (",[145,645,646],{},"express()"," inside ",[145,649,650],{},"*.spec.ts",[145,652,653],{},"test\u002F"," or ",[145,656,657],{},"__tests__\u002F",") never becomes a ",[145,660,661],{},"route:",". A file or module spec covers every symbol defined in that file; ",[664,665,26],"a",{"href":666},"\u002Fdocs\u002Fcli#affected"," maps a changed file, or only its touched lines, to the tests and entry points that reach them.",[515,669,670,680],{},[518,671,672],{},[521,673,674,677],{},[524,675,676],{},"language",[524,678,679],{},"what counts",[531,681,682,712,759,824,865],{},[521,683,684,686],{},[536,685,79],{},[536,687,688,689,216,692,216,695,698,699,180,702,293,705,708,709],{},"PHPUnit ",[145,690,691],{},"test_*",[145,693,694],{},"@test",[145,696,697],{},"#[Test]","; Pest ",[145,700,701],{},"it()",[145,703,704],{},"test()",[145,706,707],{},"describe()"," prefixes; under ",[145,710,711],{},"tests\u002F",[521,713,714,717],{},[536,715,716],{},"TS \u002F JS",[536,718,719,720,216,723,216,726,728,729,216,732,216,734,216,736,216,739,742,743,746,747,654,749,751,752,755,756,758],{},"Vitest, Jest (",[145,721,722],{},"*.test.*",[145,724,725],{},"*.spec.*",[145,727,657],{},"), Playwright, Cypress. Test trees: top-level ",[145,730,731],{},"e2e\u002F",[145,733,653],{},[145,735,711],{},[145,737,738],{},"cypress\u002F",[145,740,741],{},"playwright\u002F"," (and under ",[145,744,745],{},"src\u002F","), plus a nested ",[145,748,741],{},[145,750,738],{}," anywhere (",[145,753,754],{},"help\u002Fplaywright\u002F",") and a nested ",[145,757,731],{}," outside the source dirs; their helper modules are test code too",[521,760,761,763],{},[536,762,95],{},[536,764,765,766,768,769,772,773,776,777,216,780,783,784,216,787,216,790,180,792,216,794,216,797,297,800,180,803,180,806,180,809,811,812,216,815,216,818,216,821],{},"pytest ",[145,767,691],{}," and ",[145,770,771],{},"Test*"," methods (inherited too); unittest \u002F Django \u002F DRF ",[145,774,775],{},"test*"," methods. Files: ",[145,778,779],{},"test_*.py",[145,781,782],{},"*_test.py",", Django ",[145,785,786],{},"tests.py",[145,788,789],{},"conftest.py",[145,791,711],{},[145,793,653],{},[145,795,796],{},"testpaths",[145,798,799],{},"pytest_plugins",[145,801,802],{},"python_files",[145,804,805],{},"python_classes",[145,807,808],{},"python_functions",[145,810,796],{}," come from ",[145,813,814],{},"pytest.ini",[145,816,817],{},"pyproject.toml",[145,819,820],{},"tox.ini",[145,822,823],{},"setup.cfg",[521,825,826,828],{},[536,827,111],{},[536,829,830,831,834,835,838,839,841,842,845,846,216,849,216,852,216,855,858,859,654,862],{},"Swift Testing ",[145,832,833],{},"@Test"," (one node per declaration, ",[145,836,837],{},"(parameterized)"," when it has arguments); XCTest ",[145,840,775],{}," instance methods on an ",[145,843,844],{},"XCTestCase"," subclass. Files under ",[145,847,848],{},"Tests\u002F",[145,850,851],{},"*Tests\u002F",[145,853,854],{},"*UITests\u002F",[145,856,857],{},"*Tests.swift",", or any file that imports ",[145,860,861],{},"XCTest",[145,863,864],{},"Testing",[521,866,867,869],{},[536,868,54],{},[536,870,871,216,873,216,876,216,879,216,882,172,885,216,888,216,891,894,895,898,899,216,902,216,905,216,908,216,911],{},[145,872,833],{},[145,874,875],{},"@ParameterizedTest",[145,877,878],{},"@RepeatedTest",[145,880,881],{},"@TestFactory",[145,883,884],{},"@TestTemplate",[145,886,887],{},"src\u002Ftest",[145,889,890],{},"src\u002FandroidTest",[145,892,893],{},"*Test"," source sets, ",[145,896,897],{},"*Test.kt",". Framework from imports: ",[145,900,901],{},"junit5",[145,903,904],{},"junit4",[145,906,907],{},"kotlin-test",[145,909,910],{},"testng",[145,912,913],{},"kotest",[141,915,916,917,920,921,924,925,271,928,180,931,180,934,180,937,940,941,944,945,948,949,952,953,955,956,958,959,961,962,965],{},"Swift Testing keeps the display name (",[145,918,919],{},"@Test(\"sums items\")","), ",[145,922,923],{},".tags",", and the ",[145,926,927],{},".disabled",[145,929,930],{},".enabled",[145,932,933],{},".bug",[145,935,936],{},".timeLimit",[145,938,939],{},".serialized"," traits on the node. ",[145,942,943],{},"@Suite"," types, nested\nsuites included, carry ",[145,946,947],{},"attrs.suite","; each test names its suite (",[145,950,951],{},"DiscountTests.Edge","). A\nhelper without ",[145,954,833],{}," is not a case. XCTest requires ",[145,957,775],{}," instance methods with no\nparameters, on a class whose superclass chain reaches ",[145,960,844],{}," (a project base class or an\nexternal ",[145,963,964],{},"*TestCase"," counts).",[141,967,968,971,972,975,976,979,980,160],{},[145,969,970],{},"androidTest"," counts as UI. A path through an ",[145,973,974],{},"*Activity"," is omitted unless ",[145,977,978],{},"--through-roots"," (\n",[664,981,983],{"href":982},"#what-the-list-leaves-out","Scope",[141,985,986],{},"Python details that change classification:",[988,989,990,1006,1029,1036],"ul",{},[991,992,993,996,997,999,1000,293,1002,1005],"li",{},[145,994,995],{},"testpaths = [\"app\"]"," contributes only the files pytest collects there. A ",[145,998,786],{}," that\napplication code imports and that defines no test case stays application code. A Django\n",[145,1001,786],{},[145,1003,1004],{},"TestCase"," classes stays test code.",[991,1007,1008,1011,1012,1014,1015,1017,1018,180,1021,1024,1025,1028],{},[145,1009,1010],{},"@pytest.fixture"," (module, class, ",[145,1013,789],{}," up the tree, ",[145,1016,799],{},") links to the\ntests that request it, to ",[145,1019,1020],{},"usefixtures",[145,1022,1023],{},"request.getfixturevalue",", and to ",[145,1026,1027],{},"autouse=True","\nfixtures. An override reaches the outer fixture.",[991,1030,1031,1032,1035],{},"A test directory outside a package is on the import path, so ",[145,1033,1034],{},"from helpers import build","\nresolves next to the test.",[991,1037,1038,180,1041,180,1044,180,1047,1050,1051,271,1054,1057,1058,1061,1062,1065,1066,199],{},[145,1039,1040],{},"setUp",[145,1042,1043],{},"setUpClass",[145,1045,1046],{},"setUpTestData",[145,1048,1049],{},"tearDown"," and pytest ",[145,1052,1053],{},"setup_method",[145,1055,1056],{},"setup_module"," run with each case. ",[145,1059,1060],{},"@pytest.mark.parametrize"," is ",[145,1063,1064],{},"attrs.params","; other marks\nare ",[145,1067,1068],{},"attrs.marks",[515,1070,1071,1081],{},[518,1072,1073],{},[521,1074,1075,1078],{},[524,1076,1077],{},"edge",[524,1079,1080],{},"from test code",[531,1082,1083,1100,1148],{},[521,1084,1085,1093],{},[536,1086,1087,180,1090],{},[145,1088,1089],{},"TEST_CALLS",[145,1091,1092],{},"TEST_USES",[536,1094,1095,1096,1099],{},"calls, instantiates or touches application code (",[145,1097,1098],{},"attrs.orig"," keeps the original kind)",[521,1101,1102,1107],{},[536,1103,1104],{},[145,1105,1106],{},"TEST_HTTP",[536,1108,1109,180,1112,1115,1116,1119,1120,216,1123,783,1126,1129,1130,1133,1134,1137,1138,216,1141,1144,1145],{},[145,1110,1111],{},"$this->getJson",[145,1113,1114],{},"patchJson(route(...))",", Pest ",[145,1117,1118],{},"get",", Playwright ",[145,1121,1122],{},"request.patch",[145,1124,1125],{},"cy.request",[145,1127,1128],{},"self.client.get(reverse(...))",", pytest-django ",[145,1131,1132],{},"client",", DRF ",[145,1135,1136],{},"APIClient",", FastAPI \u002F Starlette ",[145,1139,1140],{},"TestClient",[145,1142,1143],{},"httpx.AsyncClient",", Flask ",[145,1146,1147],{},"test_client()",[521,1149,1150,1155],{},[536,1151,1152],{},[145,1153,1154],{},"TEST_VISITS",[536,1156,1157,216,1160],{},[145,1158,1159],{},"page.goto",[145,1161,1162],{},"cy.visit",[141,1164,1165,1166,1169,1170,180,1173,271,1176,1179,1180,172,1183,1185,1186,1189,1190,180,1193,1196,1197,180,1200,180,1203,1206,1207,1210,1211,1214,1215,1218,1219,1218,1222,1225,1226,1229,1230,1233,1234,1237],{},"Python URLs come from literals, f-strings (literal ",[145,1167,1168],{},"parametrize"," values filled in), ",[145,1171,1172],{},"%",[145,1174,1175],{},"+",[145,1177,1178],{},".format",", locals, class attributes and ",[145,1181,1182],{},"self.url",[145,1184,1040],{},". Constant parts of\n",[145,1187,1188],{},"f\"{settings.API_V1_STR}\u002Fitems\u002F\""," are filled from module constants and settings attributes.\n",[145,1191,1192],{},"reverse()",[145,1194,1195],{},"reverse_lazy()"," use the Django names cg indexed (namespaces, DRF\n",[145,1198,1199],{},"\u003Cbasename>-list",[145,1201,1202],{},"-detail",[145,1204,1205],{},"-\u003Caction>","). Flask ",[145,1208,1209],{},"url_for('bp.view')"," uses blueprint\nendpoint names. Starlette \u002F FastAPI ",[145,1212,1213],{},"url_path_for"," uses route names. Helpers whose verb and URL\nare parameters (",[145,1216,1217],{},"$this->postAs"," → ",[145,1220,1221],{},"sendAs",[145,1223,1224],{},"json",") are followed to the call site. A URL that\nis entirely unknown, a ",[145,1227,1228],{},"url_for()"," whose ",[145,1231,1232],{},"add_url_rule(endpoint=...)"," names no view, or a route\nname shared by a whole group, matches nothing. Frontend tests match when the frontend is linked\nto its backend. HTTP endpoints that only tests call are tagged ",[145,1235,1236],{},"test_only"," and kept out of the\nfrontend → backend match rates.",[141,1239,1240,1241,1244,1245,1248],{},"Programs a test starts (",[145,1242,1243],{},"cg_code_graph\u002Fprocess_runs.py",", Python also ",[145,1246,1247],{},"plugins\u002Fpython\u002Fsubproc.py","):",[515,1250,1251,1264],{},[518,1252,1253],{},[521,1254,1255,1258,1261],{},[524,1256,1257],{},"runtime",[524,1259,1260],{},"recognised start",[524,1262,1263],{},"links to",[531,1265,1266,1294,1316,1342,1360],{},[521,1267,1268,1270,1285],{},[536,1269,95],{},[536,1271,1272,180,1275,180,1278,293,1281,1284],{},[145,1273,1274],{},"subprocess",[145,1276,1277],{},"asyncio.create_subprocess_*",[145,1279,1280],{},"os.system",[145,1282,1283],{},"[sys.executable, \"-m\", \"pkg.cli\"]",", a script path, or a console script",[536,1286,1287,1290,1291],{},[145,1288,1289],{},"script:pkg.cli",", the file's entry, or ",[145,1292,1293],{},"script:console_scripts:\u003Cname>",[521,1295,1296,1299,1307],{},[536,1297,1298],{},"Rust",[536,1300,1301,216,1304],{},[145,1302,1303],{},"CARGO_BIN_EXE_x",[145,1305,1306],{},"Command::cargo_bin(\"x\")",[536,1308,1309,1312,1313],{},[145,1310,1311],{},"main"," of bin ",[145,1314,1315],{},"x",[521,1317,1318,1321,1339],{},[536,1319,1320],{},"Node",[536,1322,1323,180,1326,180,1329,1332,1333,626,1336],{},[145,1324,1325],{},"spawn",[145,1327,1328],{},"execa",[145,1330,1331],{},"fork"," of a project script or ",[145,1334,1335],{},"package.json",[145,1337,1338],{},"bin",[536,1340,1341],{},"the script's module",[521,1343,1344,1346,1354],{},[536,1345,79],{},[536,1347,1348,216,1351],{},[145,1349,1350],{},"Process(['php', 'artisan', 'x'])",[145,1352,1353],{},"$this->artisan('x')",[536,1355,1356,1357,1359],{},"the command (",[145,1358,254],{}," when in-process)",[521,1361,1362,1365,1378],{},[536,1363,1364],{},"Dart",[536,1366,1367,180,1370,1373,1374,1377],{},[145,1368,1369],{},"Process.run",[145,1371,1372],{},"TestProcess.start"," of a project ",[145,1375,1376],{},".dart"," file",[536,1379,1380,1381],{},"that file's ",[145,1382,1311],{},[141,1384,1385,1386,1389,1390,1218,1393,1396,1397,180,1400,180,1403,180,1406,1409,1410,1413,1414,1417,1418,1421,1422,180,1425,180,1428,216,1431,1434,1435,1438,1439,1441,1442,1445,1446,1449,1450,1453,1454,216,1457,1460,1461,1464,1465,1468,1469,370,1472,216,1475,1478,1479,199],{},"A helper whose program is a parameter is followed through up to 5 helpers (",[145,1387,1388],{},"run_django_admin"," →\n",[145,1391,1392],{},"run_test",[145,1394,1395],{},"popen","), including ",[145,1398,1399],{},"append",[145,1401,1402],{},"extend",[145,1404,1405],{},"insert",[145,1407,1408],{},"+="," between the assignment\nand the call. A ",[145,1411,1412],{},"for"," over a known list contributes the loop items; any other loop adds one\nunknown item. ",[145,1415,1416],{},"CliRunner().invoke"," on a click or typer app, ",[145,1419,1420],{},"scripttest.TestFileEnvironment.run",", pytest ",[145,1423,1424],{},"Pytester.run",[145,1426,1427],{},"pytester",[145,1429,1430],{},"testdir",[145,1432,1433],{},"sh.mytool"," and plumbum ",[145,1436,1437],{},"local[\"mytool\"]","\nstand in for a direct ",[145,1440,1274],{},". A ",[145,1443,1444],{},"-c"," snippet links to what it calls (",[145,1447,1448],{},"how: -c","), or to\na project module it only imports (",[145,1451,1452],{},"how: -c import","). A script the same function copies first (\n",[145,1455,1456],{},"shutil.copy",[145,1458,1459],{},"dst.write_text(src.read_text())",") links to that source (",[145,1462,1463],{},"how: copied script","). A ",[145,1466,1467],{},"manage.py-tpl"," template is read as Python (",[145,1470,1471],{},"how: copied template",[145,1473,1474],{},"git",[145,1476,1477],{},"-m pip"," and\nunknown argument lists add nothing; the Python plugin counts them under ",[145,1480,1274],{},[141,1482,1483,1484,216,1487,1490,1491,1494,1495,1497],{},"Not linked: Go (",[145,1485,1486],{},"exec.Command",[145,1488,1489],{},"go run .\u002Fcmd\u002Fx",", no Go plugin); arguments built in another\nfunction or read from configuration. A script outside every source dir that a test runs (\n",[145,1492,1493],{},"node tools\u002Fgen.js"," beside ",[145,1496,745],{},") is still a source file, so it has a module node.",[505,1499,1502],{"className":1500,"code":1501,"language":510,"meta":511},[508],"$ cg tests 'App\\Support\\BoardAccess::visibleBoardIds' --db out\u002Fgraph.db\ntests: 2 direct, 0 nearby transitive (app depth \u003C= 3), 1 UI \u002F snapshot (of 10: phpunit 4, pest 3, playwright 2, vitest 1)\n== DIRECT: 2\n  board access > it lists the boards of the user teams  [pest]  depth=1 conf=exact\n      test:… -TEST_CALLS-> Support\\BoardAccess::visibleBoardIds\n== UI \u002F SNAPSHOT (through application code): 1\n  board page > shows the tasks of a board  [playwright]  depth=6 conf=exact  app_depth=3\n      test -TEST_VISITS-> page:… -USES_COMPOSABLE-> useBoardRealtime -SUBSCRIBES_CHANNEL-> … -CALLS-> visibleBoardIds\n\n$ cg tests catalog.api.get_book --db out\u002Fbookstore-django.db\ntests: 0 direct, 1 nearby transitive (of 10: pytest 5, unittest 5)\n== TRANSITIVE: 1\n  test_book_endpoints  [pytest] catalog\u002Ftests\u002Ftest_api.py:13  depth=3 conf=exact  app_depth=0\n      test -TEST_HTTP-> route:GET \u002Fapi\u002Fbooks\u002F{book_id}\u002F -ROUTES_TO-> catalog.api.get_book\n",[145,1503,1501],{"__ignoreMap":511},[141,1505,1506,1507,216,1510,216,1513,216,1516,216,1519,228,1522,1525,1526,1530,1531,1534,1535,1538,1539,1542,1543,1546,1547,626,1550,370,1553,1555,1556,1559],{},"Targets: ",[145,1508,1509],{},"Class::method",[145,1511,1512],{},"Class",[145,1514,1515],{},"route:VERB \u002Furi",[145,1517,1518],{},"`VERB \u002Fpath`",[145,1520,1521],{},"\u002Fpath",[145,1523,1524],{},"table.column",", or any node id. ",[1527,1528,1529],"strong",{},"Direct"," is the test itself. ",[1527,1532,1533],{},"Transitive"," is through\napplication code. Both lists start with the closest tests. ",[145,1536,1537],{},"--no-paths"," drops the chains.\n",[145,1540,1541],{},"--min-confidence"," filters by the weakest edge. A ",[145,1544,1545],{},"(candidate)"," line is a Swift or Kotlin call\nwhose receiver type is unknown, linked to each of two to five same-name methods (\n",[145,1548,1549],{},"attrs.binding",[145,1551,1552],{},"candidate",[145,1554,636],{}," and MCP ",[145,1557,1558],{},"callers"," mark those callers the same way.",[141,1561,1562,1565,1566,1569,1570,1572,1573,199],{},[145,1563,1564],{},"cg coverage"," prints the same framework counts (\n",[145,1567,1568],{},"python tests: 10 test cases (pytest 5, unittest 5) …","). A function that only tests call has no\ncallers in ",[145,1571,636],{},"; the answer points at ",[145,1574,614],{},[1576,1577,1579],"h3",{"id":1578},"what-the-list-leaves-out","What the list leaves out",[515,1581,1582,1592],{},[518,1583,1584],{},[521,1585,1586,1589],{},[524,1587,1588],{},"rule",[524,1590,1591],{},"default",[531,1593,1594,1617,1641],{},[521,1595,1596,1599],{},[536,1597,1598],{},"App depth",[536,1600,1601,1602,1605,1606,216,1609,1612,1613,1616],{},"at most ",[145,1603,1604],{},"--max-depth"," hops (default 3) through application code. Test edges and wiring (route → handler, ",[145,1607,1608],{},"MATCHES_*",[145,1610,1611],{},"HANDLED_BY",", middleware) do not count. ",[145,1614,1615],{},"--max-depth 0"," lists every depth",[521,1618,1619,1622],{},[536,1620,1621],{},"UI \u002F snapshot",[536,1623,1624,1625,216,1628,216,1630,216,1633,1636,1637,1640],{},"Playwright, Cypress, ",[145,1626,1627],{},"*UITests",[145,1629,970],{},[145,1631,1632],{},"uiTest",[145,1634,1635],{},"integration_test",", snapshot \u002F screenshot names. ",[145,1638,1639],{},"--unit-only"," drops them",[521,1642,1643,1646],{},[536,1644,1645],{},"App roots",[536,1647,1648,1649,180,1652,1655,1656,1658,1659,1662,1663,1665],{},"a path through ",[145,1650,1651],{},"@main",[145,1653,1654],{},"UIApplicationDelegate",", a Kotlin ",[145,1657,974],{},", or ",[145,1660,1661],{},"--exclude-root SPEC"," is omitted. ",[145,1664,978],{}," keeps them",[141,1667,1668,1671,1672,1675,1676,1679,1680,1683,1684,1687,1688,1691,1692,216,1695,148,1698,216,1701,216,1704,285,1706,199],{},[145,1669,1670],{},"test → route → controller → service → target"," has app depth 2. A line shows ",[145,1673,1674],{},"app_depth=N"," when\nit differs from ",[145,1677,1678],{},"depth",". The header and a ",[145,1681,1682],{},"not listed:"," line count what was left out (\n",[145,1685,1686],{},"1 more not listed (1 deeper, 1 through roots, 1 ui)","), with the options that bring it back.\n",[145,1689,1690],{},"--json"," carries ",[145,1693,1694],{},"ui",[145,1696,1697],{},"omitted",[145,1699,1700],{},"deeper",[145,1702,1703],{},"through_roots",[145,1705,1694],{},[145,1707,1708],{},"limits",[141,1710,1711,1712,148,1715,1718,1719,370,1721,1724,1725,1728,1729,199],{},"When no test reaches the target, the last line says why: the graph has no test code, it has test\nfiles but no recognised cases, or it has N cases and none call the target. On a base or\ninterface method the tests of its overrides count, marked ",[145,1713,1714],{},"(via override A.m)",[145,1716,1717],{},"via_override","\nin ",[145,1720,1690],{},[145,1722,1723],{},"Sub.method"," for an inherited method resolves to the definition it inherits. A\nroot that is itself the target is not excluded. An explicit ",[145,1726,1727],{},"--exclude-root"," still applies with\n",[145,1730,978],{},[141,1732,1733,1734,1737,1738,1741],{},"MCP:\n",[145,1735,1736],{},"tests_covering(target, min_confidence?, paths?, max_depth? = 3, unit_only?, exclude_roots?, through_roots?)","\n. ",[145,1739,1740],{},"max_depth"," 0 means any depth.",[162,1743,1744],{"id":1708},"Limits",[988,1746,1747,1758,1761,1768,1782],{},[991,1748,1749,1750,1753,1754,1757],{},"Channel names cg cannot evaluate keep ",[145,1751,1752],{},"{?}","; a fully dynamic name is skipped. Custom\nbroadcasters and Livewire ",[145,1755,1756],{},"echo-private:"," keys are not client subscriptions.",[991,1759,1760],{},"A channel callback's checks are the methods it calls. The query prints the source; it does not\ndecide whether the check limits access.",[991,1762,1763,1764,1767],{},"A browser test that stubs the API (",[145,1765,1766],{},"page.route",") still counts as reaching the backend\nthrough the page it visits.",[991,1769,1770,216,1773,1775,1776,768,1779,1781],{},[145,1771,1772],{},"test.each",[145,1774,1060],{},", Swift ",[145,1777,1778],{},"@Test(arguments:)",[145,1780,875],{},"\nare one node per declaration.",[991,1783,1784,1785,1788],{},"Python HTTP tests link to Django, DRF, django-ninja, FastAPI, Starlette and Flask. Other\nframeworks are counted in the index stats. ",[145,1786,1787],{},"pytest_generate_tests"," and fixtures from installed\nplugins are not graph nodes.",{"title":511,"searchDepth":1790,"depth":1791,"links":1792},4,2,[1793,1794,1798],{"id":164,"depth":1791,"text":165},{"id":614,"depth":1791,"text":615,"children":1795},[1796],{"id":1578,"depth":1797,"text":1579},3,{"id":1708,"depth":1791,"text":1744},"Realtime channels (who may join, what publishes, which client listens) and test code (which\ntests exercise a symbol, route or table). Examples are the task-board fixture in\ntests\u002Fbroadcast_fixture (api\u002F Laravel, web\u002F Nuxt, joined with cg link).","md",{},true,{"title":22,"description":1799},"OCP8jam5cLOcQ4CgNGtVkYYIe4DqPjMeyEhOOOV7qUQ",[1806,1808],{"title":18,"path":19,"stem":20,"description":1807,"children":-1},"A hybrid app calls native code by name. cg links each call to the Kotlin, Java, Swift or\nObjective-C handler on every platform, so impact, downstream, tests and --platform\ncross the bridge. Electron IPC and Tauri commands use the same endpoint model across processes.",{"title":26,"path":27,"stem":28,"description":1809,"children":-1},"cg \u003Ccommand> is python -m cg_code_graph.cli \u003Ccommand>. Query commands need --db. Flags not listed here: cg \u003Ccommand> -h.",1792170237278]