Skip to content

Commit

Permalink
Added nuxt.js and next.js samples and related integration tests (#365)
Browse files Browse the repository at this point in the history
  • Loading branch information
arroyc authored and kichalla committed Oct 1, 2019
1 parent abb08ae commit f50e51b
Show file tree
Hide file tree
Showing 37 changed files with 1,638 additions and 0 deletions.
127 changes: 127 additions & 0 deletions tests/Oryx.Integration.Tests/Node/NodeNextJsAppTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// --------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
// --------------------------------------------------------------------------------------------

using Microsoft.Oryx.BuildScriptGenerator.Node;
using Microsoft.Oryx.Common;
using Microsoft.Oryx.Tests.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;

namespace Microsoft.Oryx.Integration.Tests
{
[Trait("category", "node")]
public class NodeNextJsAppTest : NodeEndToEndTestsBase
{
public const string AppName = "blog-starter";
public const int ContainerAppPort = 3000;
public NodeNextJsAppTest(ITestOutputHelper output, TestTempDirTestFixture testTempDirTestFixture)
: base(output, testTempDirTestFixture)
{
}

[Theory]
[InlineData("10")]
[InlineData("12")]
public async Task CanBuildAndRun_BlogStarterNextJsApp_WithoutZippingNodeModules(string nodeVersion)
{
// Arrange
var volume = CreateAppVolume(AppName);
var appDir = volume.ContainerDir;
var buildScript = new ShellScriptBuilder()
.AddCommand($"oryx build {appDir} --platform nodejs --platform-version {nodeVersion}")
.ToString();
var runScript = new ShellScriptBuilder()
.AddCommand($"export PORT={ContainerAppPort}")
.AddCommand($"oryx -appPath {appDir}")
.AddCommand(DefaultStartupFilePath)
.ToString();

await EndToEndTestHelper.BuildRunAndAssertAppAsync(
AppName,
_output,
volume,
"/bin/sh",
new[]
{
"-c",
buildScript
},
$"oryxdevmcr.azurecr.io/public/oryx/node-{nodeVersion}",
ContainerAppPort,
"/bin/sh",
new[]
{
"-c",
runScript
},
async (hostPort) =>
{
var data = await _httpClient.GetStringAsync($"http://localhost:{hostPort}/");
Assert.Contains("Welcome to your new blog built with Next.js", data);
});
}

[Theory]
[InlineData("10")]
[InlineData("12")]
public async Task CanBuildAndRun_BlogStarterNextJsApp_UsingZippedNodeModules(string nodeVersion)
{
string compressFormat = "tar-gz";
// NOTE:
// 1. Use intermediate directory(which here is local to container) to avoid errors like
// "tar: node_modules/form-data: file changed as we read it"
// related to zipping files on a folder which is volume mounted.
// 2. Use output directory within the container due to 'rsync'
// having issues with volume mounted directories

// Arrange
var appOutputDirPath = Directory.CreateDirectory(Path.Combine(_tempRootDir, Guid.NewGuid().ToString("N")))
.FullName;
var appOutputDirVolume = DockerVolume.CreateMirror(appOutputDirPath);
var appOutputDir = appOutputDirVolume.ContainerDir;
var volume = CreateAppVolume(AppName);
var appDir = volume.ContainerDir;
var runAppScript = new ShellScriptBuilder()
.AddCommand($"export PORT={ContainerAppPort}")
.AddCommand($"oryx -appPath {appOutputDir}")
.AddCommand(DefaultStartupFilePath)
.ToString();
var buildScript = new ShellScriptBuilder()
.AddCommand(
$"oryx build {appDir} -i /tmp/int -o /tmp/out --platform nodejs " +
$"--platform-version {nodeVersion} -p compress_node_modules={compressFormat}")
.AddCommand($"cp -rf /tmp/out/* {appOutputDir}")
.ToString();

await EndToEndTestHelper.BuildRunAndAssertAppAsync(
AppName,
_output,
new List<DockerVolume> { appOutputDirVolume, volume },
"/bin/sh",
new[]
{
"-c",
buildScript
},
$"oryxdevmcr.azurecr.io/public/oryx/node-{nodeVersion}",
ContainerAppPort,
"/bin/sh",
new[]
{
"-c",
runAppScript
},
async (hostPort) =>
{
var data = await _httpClient.GetStringAsync($"http://localhost:{hostPort}/");
Assert.Contains("Welcome to your new blog built with Next.js", data);
});
}
}
}
128 changes: 128 additions & 0 deletions tests/Oryx.Integration.Tests/Node/NodeNuxtJsAppTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// --------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
// --------------------------------------------------------------------------------------------

using Microsoft.Oryx.BuildScriptGenerator.Node;
using Microsoft.Oryx.Common;
using Microsoft.Oryx.Tests.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;

namespace Microsoft.Oryx.Integration.Tests
{
[Trait("category", "node")]
public class NodeNuxtJsAppTest : NodeEndToEndTestsBase
{
public const string AppName = "hackernews";
public const int ContainerAppPort = 3000;

public NodeNuxtJsAppTest(ITestOutputHelper output, TestTempDirTestFixture testTempDirTestFixture)
: base(output, testTempDirTestFixture)
{
}

[Theory]
[InlineData("10")]
[InlineData("12")]
public async Task CanBuildAndRun_HackerNewsNuxtJsApp_WithoutZippingNodeModules(string nodeVersion)
{
// Arrange
var volume = CreateAppVolume(AppName);
var appDir = volume.ContainerDir;
var buildScript = new ShellScriptBuilder()
.AddCommand($"oryx build {appDir} --platform nodejs --platform-version {nodeVersion}")
.ToString();
var runScript = new ShellScriptBuilder()
.AddCommand($"export PORT={ContainerAppPort}")
.AddCommand($"oryx -appPath {appDir}")
.AddCommand(DefaultStartupFilePath)
.ToString();

await EndToEndTestHelper.BuildRunAndAssertAppAsync(
AppName,
_output,
volume,
"/bin/sh",
new[]
{
"-c",
buildScript
},
$"oryxdevmcr.azurecr.io/public/oryx/node-{nodeVersion}",
ContainerAppPort,
"/bin/sh",
new[]
{
"-c",
runScript
},
async (hostPort) =>
{
var data = await _httpClient.GetStringAsync($"http://localhost:{hostPort}/");
Assert.Contains("WeWork and Counterfeit Capitalism", data);
});
}

[Theory]
[InlineData("10")]
[InlineData("12")]
public async Task CanBuildAndRun_HackerNewsNuxtJsApp_UsingZippedNodeModules(string nodeVersion)
{
string compressFormat = "zip";
// NOTE:
// 1. Use intermediate directory(which here is local to container) to avoid errors like
// "tar: node_modules/form-data: file changed as we read it"
// related to zipping files on a folder which is volume mounted.
// 2. Use output directory within the container due to 'rsync'
// having issues with volume mounted directories

// Arrange
var appOutputDirPath = Directory.CreateDirectory(Path.Combine(_tempRootDir, Guid.NewGuid().ToString("N")))
.FullName;
var appOutputDirVolume = DockerVolume.CreateMirror(appOutputDirPath);
var appOutputDir = appOutputDirVolume.ContainerDir;
var volume = CreateAppVolume(AppName);
var appDir = volume.ContainerDir;
var runAppScript = new ShellScriptBuilder()
.AddCommand($"export PORT={ContainerAppPort}")
.AddCommand($"oryx -appPath {appOutputDir}")
.AddCommand(DefaultStartupFilePath)
.ToString();
var buildScript = new ShellScriptBuilder()
.AddCommand(
$"oryx build {appDir} -i /tmp/int -o /tmp/out --platform nodejs " +
$"--platform-version {nodeVersion} -p compress_node_modules={compressFormat}")
.AddCommand($"cp -rf /tmp/out/. {appOutputDir}")
.ToString();

await EndToEndTestHelper.BuildRunAndAssertAppAsync(
AppName,
_output,
new List<DockerVolume> { appOutputDirVolume, volume },
"/bin/sh",
new[]
{
"-c",
buildScript
},
$"oryxdevmcr.azurecr.io/public/oryx/node-{nodeVersion}",
ContainerAppPort,
"/bin/sh",
new[]
{
"-c",
runAppScript
},
async (hostPort) =>
{
var data = await _httpClient.GetStringAsync($"http://localhost:{hostPort}/");
Assert.Contains("WeWork and Counterfeit Capitalism", data);
});
}
}
}
4 changes: 4 additions & 0 deletions tests/SampleApps/nodejs/blog-starter/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"presets": ["next/babel"],
"plugins": ["preval", "macros"]
}
46 changes: 46 additions & 0 deletions tests/SampleApps/nodejs/blog-starter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Blog starter example

## How to use

### Using `create-next-app`

Download [`create-next-app`](https://github.com/segmentio/create-next-app) to bootstrap the example:

```
npm i -g create-next-app
create-next-app --example blog-starter
```

### Download manually

Download the example [or clone the repo](https://github.com/zeit/next.js):

```bash
curl https://codeload.github.com/zeit/next.js/tar.gz/canary | tar -xz --strip=2 next.js-canary/examples/blog-starter
cd blog-starter
```

### Run locally

Install and run the development server:

```bash
yarn install
now dev
```

### Deploy

Deploy it to the cloud with [now](https://zeit.co/now) ([download](https://zeit.co/download))

```bash
now
```

## The idea behind the example

This is an example of a blog built with Next.js. [Read more about the motivation and how it is built](https://jolvera.dev/posts/rebuilding-my-blog-with-nextjs).

The blog is still barebones and need more improvements and styling, but this should be enough to get you started.

[Demo deployed in Now](https://nextjs-blog-starter.now.sh/)
13 changes: 13 additions & 0 deletions tests/SampleApps/nodejs/blog-starter/blog.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module.exports = {
siteMeta: {
title: 'Next.js Starter Blog',
author: 'Juan Olvera',
image: '/static/site-feature.png',
description: 'Next.js starter blog',
siteUrl: 'https://nextjs-blog-starter.now.sh',
social: {
twitter: '_jolvera'
},
postsPerPage: 5
}
}
32 changes: 32 additions & 0 deletions tests/SampleApps/nodejs/blog-starter/components/blog-index-item.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import Link from 'next/link'
import PublishedAt from './utils/published-at'

const Post = ({ title, summary, date, path }) => (
<article>
<header>
<h2>
<Link href={path}>
<a>{title}</a>
</Link>
</h2>

<PublishedAt link={path} date={date} />
</header>
<div className='post-summary'>{summary}</div>
<style jsx>{`
article {
margin-bottom: 2em;
}
a {
text-decoration: none;
}
.post-summary {
margin-top: 1em;
}
`}</style>
</article>
)

export default Post
12 changes: 12 additions & 0 deletions tests/SampleApps/nodejs/blog-starter/components/container.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const Container = ({ children }) => (
<>
<div>{children}</div>
<style jsx>{`
max-width: 45rem;
margin: 0 auto;
padding: 0 1em;
`}</style>
</>
)

export default Container
25 changes: 25 additions & 0 deletions tests/SampleApps/nodejs/blog-starter/components/footer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import Profile from './profile'

function Footer () {
return (
<footer>
<Profile className='profile-footer' />

<p>
Proudly built with <a href='https://nextjs.org'>Next.js</a> -{' '}
<a href='/feed.json'>RSS Feed</a>
</p>
<style jsx>{`
footer {
padding: 1em 0;
}
p {
margin-top: 2em;
}
`}</style>
</footer>
)
}

export default Footer
Loading

0 comments on commit f50e51b

Please sign in to comment.