Skip to content

Commit f060cb1

Browse files
committed
AC-15461: Migration New Relic from REST v2 to NerdGraph (GraphQL)
1 parent a66918a commit f060cb1

File tree

11 files changed

+721
-15
lines changed

11 files changed

+721
-15
lines changed

app/code/Magento/NewRelicReporting/Console/Command/DeployMarker.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
namespace Magento\NewRelicReporting\Console\Command;
77

8+
use Magento\Framework\Exception\LocalizedException;
89
use Symfony\Component\Console\Command\Command;
910
use Symfony\Component\Console\Input\InputInterface;
1011
use Symfony\Component\Console\Output\OutputInterface;
@@ -132,7 +133,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
132133
return 1;
133134
}
134135

135-
} catch (\Magento\Framework\Exception\LocalizedException $e) {
136+
} catch (LocalizedException $e) {
136137
$output->writeln('<error>✗ Configuration Error!</error>');
137138
$output->writeln('<error>' . $e->getMessage() . '</error>');
138139
$output->writeln('');

app/code/Magento/NewRelicReporting/Model/Apm/Deployments.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,10 @@ public function setDeployment(
9494
string $description,
9595
bool|string $change = false,
9696
bool|string $user = false,
97-
string $revision = null,
98-
string $commit = null,
99-
string $deepLink = null,
100-
string $groupId = null
97+
?string $revision = null,
98+
?string $commit = null,
99+
?string $deepLink = null,
100+
?string $groupId = null
101101
) {
102102
// Check API mode configuration
103103
$apiMode = $this->config->getApiMode();

app/code/Magento/NewRelicReporting/Model/NerdGraph/DeploymentTracker.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ public function __construct(
5959
* @param string|null $deepLink Deep link to deployment details
6060
* @param string|null $groupId Group ID for organizing deployments
6161
* @return array|false Deployment data on success, false on failure
62-
* @throws LocalizedException
6362
*/
6463
public function createDeployment(
6564
string $description,
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\NewRelicReporting\Test\Unit\ViewModel;
9+
10+
use Magento\NewRelicReporting\Model\NewRelicWrapper;
11+
use Magento\NewRelicReporting\ViewModel\BrowserMonitoringFooterJs;
12+
use Magento\NewRelicReporting\ViewModel\ContentProviderInterface;
13+
use PHPUnit\Framework\MockObject\MockObject;
14+
use PHPUnit\Framework\TestCase;
15+
16+
/**
17+
* Test for BrowserMonitoringFooterJs ViewModel
18+
*/
19+
class BrowserMonitoringFooterJsTest extends TestCase
20+
{
21+
/**
22+
* @var NewRelicWrapper|MockObject
23+
*/
24+
private $newRelicWrapperMock;
25+
26+
/**
27+
* @var BrowserMonitoringFooterJs
28+
*/
29+
private $viewModel;
30+
31+
protected function setUp(): void
32+
{
33+
$this->newRelicWrapperMock = $this->createMock(NewRelicWrapper::class);
34+
$this->viewModel = new BrowserMonitoringFooterJs($this->newRelicWrapperMock);
35+
}
36+
37+
/**
38+
* Test getContent when New Relic is enabled
39+
*/
40+
public function testGetContentEnabled()
41+
{
42+
$this->newRelicWrapperMock->expects($this->once())
43+
->method('isAutoInstrumentEnabled')
44+
->willReturn(true);
45+
46+
$this->newRelicWrapperMock->expects($this->atLeastOnce())
47+
->method('getBrowserTimingFooter')
48+
->willReturn('<script>test</script>');
49+
50+
$this->newRelicWrapperMock->expects($this->once())
51+
->method('getBrowserTimingFooter')
52+
->with(false)
53+
->willReturn('<script>test</script>');
54+
55+
$content = $this->viewModel->getContent();
56+
57+
$this->assertEquals('<script>test</script>', $content);
58+
}
59+
60+
/**
61+
* Test getContent when New Relic is disabled
62+
*/
63+
public function testGetContentDisabled()
64+
{
65+
$this->newRelicWrapperMock->expects($this->once())
66+
->method('isAutoInstrumentEnabled')
67+
->willReturn(false);
68+
69+
// No getBrowserTimingFooter/Header call when disabled
70+
71+
$content = $this->viewModel->getContent();
72+
73+
$this->assertNull($content);
74+
}
75+
76+
/**
77+
* Test that ViewModel implements ContentProviderInterface
78+
*/
79+
public function testImplementsContentProviderInterface()
80+
{
81+
$this->assertInstanceOf(
82+
\Magento\NewRelicReporting\ViewModel\ContentProviderInterface::class,
83+
$this->viewModel
84+
);
85+
}
86+
87+
/**
88+
* Test multiple calls return consistent results
89+
*/
90+
public function testMultipleCallsConsistency()
91+
{
92+
$this->newRelicWrapperMock->expects($this->exactly(3))
93+
->method('isAutoInstrumentEnabled')
94+
->willReturn(true);
95+
96+
$this->newRelicWrapperMock->expects($this->atLeastOnce())
97+
->method('getBrowserTimingFooter')
98+
->willReturn('<script>test</script>');
99+
100+
$this->newRelicWrapperMock->expects($this->exactly(3))
101+
->method('getBrowserTimingFooter')
102+
->with(false)
103+
->willReturn('<script>test</script>');
104+
105+
// Call multiple times
106+
$content1 = $this->viewModel->getContent();
107+
$content2 = $this->viewModel->getContent();
108+
$content3 = $this->viewModel->getContent();
109+
110+
// All should return the same result
111+
$this->assertEquals('<script>test</script>', $content1);
112+
$this->assertEquals('<script>test</script>', $content2);
113+
$this->assertEquals('<script>test</script>', $content3);
114+
$this->assertEquals($content1, $content2);
115+
$this->assertEquals($content2, $content3);
116+
}
117+
118+
/**
119+
* Test that generated script is valid JavaScript
120+
*/
121+
public function testGeneratedScriptIsValidJavaScript()
122+
{
123+
$this->newRelicWrapperMock->expects($this->once())
124+
->method('isAutoInstrumentEnabled')
125+
->willReturn(true);
126+
127+
$mockScript = '<script type="text/javascript">if (typeof newrelic !== "undefined") { newrelic.finished(); }</script>';
128+
129+
$this->newRelicWrapperMock->expects($this->once())
130+
->method('getBrowserTimingFooter')
131+
->with(false)
132+
->willReturn($mockScript);
133+
134+
$content = $this->viewModel->getContent();
135+
136+
// Check that the script contains expected JavaScript elements
137+
$this->assertStringContainsString('<script type="text/javascript">', $content);
138+
$this->assertStringContainsString('newrelic.finished();', $content);
139+
$this->assertStringContainsString('typeof newrelic !== "undefined"', $content);
140+
$this->assertStringContainsString('</script>', $content);
141+
}
142+
143+
/**
144+
* Test that script includes safety check for newrelic object
145+
*/
146+
public function testScriptIncludesSafetyCheck()
147+
{
148+
$this->newRelicWrapperMock->expects($this->once())
149+
->method('isAutoInstrumentEnabled')
150+
->willReturn(true);
151+
152+
$mockScript = '<script type="text/javascript">if (typeof newrelic !== "undefined") { newrelic.finished(); }</script>';
153+
154+
$this->newRelicWrapperMock->expects($this->atLeastOnce())
155+
->method('getBrowserTimingFooter')
156+
->willReturn($mockScript);
157+
158+
$this->newRelicWrapperMock->expects($this->once())
159+
->method('getBrowserTimingFooter')
160+
->with(false)
161+
->willReturn($mockScript);
162+
163+
$content = $this->viewModel->getContent();
164+
165+
// Verify the safety check exists
166+
$this->assertStringContainsString('if (typeof newrelic !== "undefined")', $content);
167+
}
168+
169+
/**
170+
* Test that disabled state returns empty string consistently
171+
*/
172+
public function testDisabledStateReturnsEmptyString()
173+
{
174+
$this->newRelicWrapperMock->expects($this->exactly(2))
175+
->method('isAutoInstrumentEnabled')
176+
->willReturn(false);
177+
178+
// No getBrowserTimingFooter/Header call when disabled
179+
180+
$content1 = $this->viewModel->getContent();
181+
$content2 = $this->viewModel->getContent();
182+
183+
$this->assertNull($content1);
184+
$this->assertNull($content2);
185+
}
186+
187+
/**
188+
* Test ViewModel class structure
189+
*/
190+
public function testViewModelStructure()
191+
{
192+
$reflection = new \ReflectionClass($this->viewModel);
193+
194+
// Check class exists and is properly structured
195+
$this->assertTrue($reflection->implementsInterface(ContentProviderInterface::class));
196+
197+
// Check it has the required method
198+
$this->assertTrue($reflection->hasMethod('getContent'));
199+
200+
// Check method is public
201+
$getContentMethod = $reflection->getMethod('getContent');
202+
$this->assertTrue($getContentMethod->isPublic());
203+
204+
// Check return type
205+
$returnType = $getContentMethod->getReturnType();
206+
$this->assertNotNull($returnType);
207+
$this->assertEquals('string', $returnType->getName());
208+
}
209+
210+
/**
211+
* Test constructor dependencies
212+
*/
213+
public function testConstructorDependencies()
214+
{
215+
$reflection = new \ReflectionClass($this->viewModel);
216+
$constructor = $reflection->getConstructor();
217+
218+
$this->assertNotNull($constructor);
219+
220+
$parameters = $constructor->getParameters();
221+
$this->assertCount(1, $parameters);
222+
223+
$configParam = $parameters[0];
224+
$this->assertEquals('newRelicWrapper', $configParam->getName());
225+
$this->assertEquals(NewRelicWrapper::class, $configParam->getType()->getName());
226+
}
227+
}

0 commit comments

Comments
 (0)