forked from newrelic/newrelic-node-nextjs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request newrelic#176 from bizob2828/app-dir
feat: Added a test suite for App Router.
- Loading branch information
Showing
16 changed files
with
346 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
package-lock.json | ||
app/.next | ||
app-dir/.next |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
/* | ||
* Copyright 2022 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
'use strict' | ||
|
||
const tap = require('tap') | ||
const helpers = require('./helpers') | ||
const utils = require('@newrelic/test-utilities') | ||
const NEXT_TRANSACTION_PREFIX = 'WebTransaction/WebFrameworkUri/Nextjs/GET/' | ||
const DESTINATIONS = { | ||
NONE: 0x00, | ||
TRANS_EVENT: 0x01, | ||
TRANS_TRACE: 0x02, | ||
ERROR_EVENT: 0x04, | ||
BROWSER_EVENT: 0x08, | ||
SPAN_EVENT: 0x10, | ||
TRANS_SEGMENT: 0x20 | ||
} | ||
|
||
tap.Test.prototype.addAssert('nextCLMAttrs', 1, function ({ segments, clmEnabled }) { | ||
segments.forEach(({ segment, name, filepath }) => { | ||
const attrs = segment.getAttributes() | ||
if (clmEnabled) { | ||
this.match( | ||
attrs, | ||
{ | ||
'code.function': name, | ||
'code.filepath': filepath | ||
}, | ||
'should add code.function and code.filepath when CLM is enabled.' | ||
) | ||
} else { | ||
this.notOk(attrs['code.function'], 'should not add code.function when CLM is disabled.') | ||
this.notOk(attrs['code.filepath'], 'should not add code.filepath when CLM is disabled.') | ||
} | ||
}) | ||
}) | ||
|
||
tap.test('Next.js', (t) => { | ||
t.autoend() | ||
let agent | ||
let server | ||
|
||
t.before(async () => { | ||
await helpers.build(__dirname, 'app-dir') | ||
|
||
agent = utils.TestAgent.makeInstrumented({ | ||
attributes: { | ||
include: ['request.parameters.*'] | ||
} | ||
}) | ||
helpers.registerInstrumentation(agent) | ||
|
||
// TODO: would be nice to run a new server per test so there are not chained failures | ||
// but currently has issues. Potentially due to module caching. | ||
server = await helpers.start(__dirname, 'app-dir', '3002') | ||
}) | ||
|
||
t.teardown(async () => { | ||
await server.close() | ||
agent.unload() | ||
}) | ||
|
||
// since we setup agent in before we need to remove | ||
// the transactionFinished listener between tests to avoid | ||
// context leaking | ||
function setupTransactionHandler(t) { | ||
return new Promise((resolve) => { | ||
function txHandler(transaction) { | ||
resolve(transaction) | ||
} | ||
|
||
agent.agent.on('transactionFinished', txHandler) | ||
|
||
t.teardown(() => { | ||
agent.agent.removeListener('transactionFinished', txHandler) | ||
}) | ||
}) | ||
} | ||
|
||
t.test('should capture query params for static, non-dynamic route, page', async (t) => { | ||
const prom = setupTransactionHandler(t) | ||
|
||
const res = await helpers.makeRequest('/static/standard?first=one&second=two', 3002) | ||
t.equal(res.statusCode, 200) | ||
const tx = await prom | ||
|
||
const agentAttributes = getTransactionEventAgentAttributes(tx) | ||
|
||
t.match(agentAttributes, { | ||
'request.parameters.first': 'one', | ||
'request.parameters.second': 'two' | ||
}) | ||
t.equal(tx.name, `${NEXT_TRANSACTION_PREFIX}/static/standard`) | ||
}) | ||
|
||
t.test('should capture query and route params for static, dynamic route, page', async (t) => { | ||
const prom = setupTransactionHandler(t) | ||
|
||
const res = await helpers.makeRequest('/static/dynamic/testing?queryParam=queryValue', 3002) | ||
t.equal(res.statusCode, 200) | ||
const tx = await prom | ||
|
||
const agentAttributes = getTransactionEventAgentAttributes(tx) | ||
|
||
t.match(agentAttributes, { | ||
'request.parameters.route.value': 'testing', // route [value] param | ||
'request.parameters.queryParam': 'queryValue' | ||
}) | ||
|
||
t.notOk(agentAttributes['request.parameters.route.queryParam']) | ||
t.equal(tx.name, `${NEXT_TRANSACTION_PREFIX}/static/dynamic/[value]`) | ||
}) | ||
|
||
t.test( | ||
'should capture query params for server-side rendered, non-dynamic route, page', | ||
async (t) => { | ||
const prom = setupTransactionHandler(t) | ||
const res = await helpers.makeRequest('/person/1?first=one&second=two', 3002) | ||
t.equal(res.statusCode, 200) | ||
const tx = await prom | ||
|
||
const agentAttributes = getTransactionEventAgentAttributes(tx) | ||
|
||
t.match( | ||
agentAttributes, | ||
{ | ||
'request.parameters.first': 'one', | ||
'request.parameters.second': 'two' | ||
}, | ||
'should match transaction attributes' | ||
) | ||
|
||
t.notOk(agentAttributes['request.parameters.route.first']) | ||
t.notOk(agentAttributes['request.parameters.route.second']) | ||
t.equal(tx.name, `${NEXT_TRANSACTION_PREFIX}/person/[id]`) | ||
} | ||
) | ||
|
||
function getTransactionEventAgentAttributes(transaction) { | ||
return transaction.trace.attributes.get(DESTINATIONS.TRANS_EVENT) | ||
} | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
|
||
export default function Layout({ children }) { | ||
return ( | ||
<html lang="en"> | ||
<head /> | ||
<body> | ||
<header> | ||
<h1>This is my header</h1> | ||
</header> | ||
<main>{children}</main> | ||
<footer> | ||
<p>This is my footer</p> | ||
</footer> | ||
</body> | ||
</html> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/* | ||
* Copyright 2022 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
export default function MyApp() { | ||
return ( | ||
<section>This is the homepage</section> | ||
) | ||
} | ||
|
17 changes: 17 additions & 0 deletions
17
merged/nextjs/tests/versioned/app-dir/app/person/[id]/page.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/* | ||
* Copyright 2022 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
import { getPerson } from '../../../lib/functions' | ||
|
||
export default async function Person({ params }) { | ||
const user = await getPerson(params.id) | ||
|
||
return ( | ||
<div> | ||
<pre>{JSON.stringify(user, null, 4)}</pre> | ||
</div> | ||
) | ||
} | ||
|
33 changes: 33 additions & 0 deletions
33
merged/nextjs/tests/versioned/app-dir/app/static/dynamic/[value]/page.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* | ||
* Copyright 2022 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
import Head from 'next/head' | ||
|
||
export async function getProps(params) { | ||
return { | ||
title: 'This is a statically built dynamic route page.', | ||
value: params.value | ||
} | ||
} | ||
|
||
export async function generateStaticPaths() { | ||
return [ | ||
{ value: 'testing' } | ||
] | ||
} | ||
|
||
|
||
export default async function Standard({ params }) { | ||
const { title, value } = await getProps(params) | ||
return ( | ||
<> | ||
<Head> | ||
<title>{title}</title> | ||
</Head> | ||
<h1>{title}</h1> | ||
<div>Value: {value}</div> | ||
</> | ||
) | ||
} |
25 changes: 25 additions & 0 deletions
25
merged/nextjs/tests/versioned/app-dir/app/static/standard/page.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* Copyright 2022 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
import Head from 'next/head' | ||
|
||
export async function getProps() { | ||
return { | ||
title: 'This is a standard statically built page.' | ||
} | ||
} | ||
|
||
|
||
export default async function Standard() { | ||
const { title } = await getProps() | ||
return ( | ||
<> | ||
<Head> | ||
<title>{title}</title> | ||
</Head> | ||
<h1>{title}</h1> | ||
</> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* | ||
* Copyright 2022 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
export const data = [ | ||
{ | ||
id: 1, | ||
firstName: 'LeBron', | ||
middleName: 'Raymone', | ||
lastName: 'James', | ||
age: 36 | ||
}, | ||
{ | ||
id: 2, | ||
firstName: 'Lil', | ||
middleName: 'Nas', | ||
lastName: 'X', | ||
age: 22 | ||
}, | ||
{ | ||
id: 3, | ||
firstName: 'Beyoncé', | ||
middleName: 'Giselle', | ||
lastName: 'Knowles-Carter', | ||
age: 40 | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* | ||
* Copyright 2022 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
export const data = [ | ||
{ | ||
id: 1, | ||
firstName: 'LeBron', | ||
middleName: 'Raymone', | ||
lastName: 'James', | ||
age: 36 | ||
}, | ||
{ | ||
id: 2, | ||
firstName: 'Lil', | ||
middleName: 'Nas', | ||
lastName: 'X', | ||
age: 22 | ||
}, | ||
{ | ||
id: 3, | ||
firstName: 'Beyoncé', | ||
middleName: 'Giselle', | ||
lastName: 'Knowles-Carter', | ||
age: 40 | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { data } from '../data' | ||
export async function getPerson(id) { | ||
const person = data.find((datum) => datum.id.toString() === id) | ||
|
||
return person || `Could not find person with id of ${id}` | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/* | ||
* Copyright 2024 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
'use strict' | ||
|
||
module.exports = { | ||
eslint: { | ||
// Warning: This allows production builds to successfully complete even if | ||
// your project has ESLint errors. | ||
ignoreDuringBuilds: true | ||
}, | ||
experimental: { | ||
appDir: true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters