-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
aae83cb
commit 7d9257a
Showing
10 changed files
with
253 additions
and
3 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
117 changes: 117 additions & 0 deletions
117
packages/cli/test/cases/build.plugins.adapter/build.config.plugins-adapter.spec.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,117 @@ | ||
/* | ||
* Use Case | ||
* Run Greenwood with a custom adapter plugin with SSR pages and API routes. | ||
* | ||
* User Result | ||
* Should generate a Greenwood build with expected transformations applied from the plugin. | ||
* | ||
* User Command | ||
* greenwood build | ||
* | ||
* User Config | ||
* async function genericAdapter(compilation, options) { ... } | ||
* | ||
* { | ||
* plugins: [{ | ||
* type: 'adapter', | ||
* name: 'plugin-generic-adapter', | ||
* provider: (compilation, options) => genericAdapter | ||
* }] | ||
* } | ||
* | ||
* Custom Workspace | ||
* src/ | ||
* api/ | ||
* greeting.js | ||
* pages/ | ||
* index.js | ||
* components/ | ||
* card.js | ||
*/ | ||
import chai from 'chai'; | ||
import path from 'path'; | ||
import { getSetupFiles, getOutputTeardownFiles } from '../../../../../test/utils.js'; | ||
import { Runner } from 'gallinago'; | ||
import { fileURLToPath, pathToFileURL } from 'url'; | ||
import { JSDOM } from 'jsdom'; | ||
|
||
const expect = chai.expect; | ||
|
||
describe('Build Greenwood With: ', function() { | ||
const LABEL = 'Generic Adapter Plugin with SSR Pages + API Routes'; | ||
const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js'); | ||
const outputPath = fileURLToPath(new URL('.', import.meta.url)); | ||
let runner; | ||
|
||
before(function() { | ||
this.context = { | ||
publicDir: path.join(outputPath, 'public') | ||
}; | ||
runner = new Runner(); | ||
}); | ||
|
||
describe(LABEL, function() { | ||
before(async function() { | ||
await runner.setup(outputPath, getSetupFiles(outputPath)); | ||
await runner.runCommand(cliPath, 'build'); | ||
}); | ||
|
||
// test SSR page | ||
describe('Adapting an SSR Page', function() { | ||
let dom; | ||
|
||
before(async function() { | ||
const req = new Request(new URL('http://localhost:8080/index')); | ||
const { handler } = await import(new URL('./adapter-output/index.js', pathToFileURL(outputPath))); | ||
const response = await handler(req); | ||
const html = await response.text(); | ||
|
||
dom = new JSDOM(html); | ||
}); | ||
|
||
it('should have the expected number of <app-card> components on the page', function() { | ||
const cards = dom.window.document.querySelectorAll('body > app-card'); | ||
|
||
expect(cards).to.have.lengthOf(1); | ||
}); | ||
|
||
it('should have the expected static heading content rendered inside the <app-card> component on the page', function() { | ||
const heading = dom.window.document.querySelectorAll('app-card h2'); | ||
|
||
expect(heading).to.have.lengthOf(1); | ||
expect(heading[0].textContent).to.be.equal('Analog'); | ||
}); | ||
|
||
it('should have the expected static img content rendered inside the <app-card> component on the page', function() { | ||
const img = dom.window.document.querySelectorAll('app-card img'); | ||
|
||
expect(img).to.have.lengthOf(1); | ||
expect(img[0].getAttribute('src')).to.be.equal('https://www.analogstudios.net/images/analog.png'); | ||
}); | ||
}); | ||
|
||
describe('Adapting an API Route', function() { | ||
let data; | ||
|
||
before(async function() { | ||
const handler = (await import(new URL('./adapter-output/greeting.js', pathToFileURL(outputPath)))).handler; | ||
const req = new Request(new URL('http://localhost:8080/api/greeting?name=Greenwood')); | ||
const res = await handler(req); | ||
|
||
data = await res.json(); | ||
}); | ||
|
||
it('should have the expected message from the API when a query is passed', function() { | ||
expect(data.message).to.be.equal('Hello Greenwood!'); | ||
}); | ||
}); | ||
}); | ||
|
||
after(function() { | ||
runner.teardown([ | ||
...getOutputTeardownFiles(outputPath), | ||
path.join(outputPath, 'adapter-output') | ||
]); | ||
}); | ||
|
||
}); |
60 changes: 60 additions & 0 deletions
60
packages/cli/test/cases/build.plugins.adapter/generic-adapter.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,60 @@ | ||
import fs from 'fs/promises'; | ||
import { checkResourceExists } from '../../../../cli/src/lib/resource-utils.js'; | ||
|
||
function generateOutputFormat(id, type) { | ||
const path = type === 'page' | ||
? `__${id}` | ||
: `api/${id}`; | ||
|
||
return ` | ||
import { handler as ${id} } from '../public/${path}.js'; | ||
export async function handler (request) { | ||
const { url, headers } = request; | ||
const req = new Request(new URL(url, \`http://\${headers.host}\`), { | ||
headers: new Headers(headers) | ||
}); | ||
return await ${id}(req); | ||
} | ||
`; | ||
} | ||
|
||
async function genericAdapter(compilation) { | ||
const adapterOutputUrl = new URL('./adapter-output/', compilation.context.projectDirectory); | ||
const ssrPages = compilation.graph.filter(page => page.isSSR); | ||
const apiRoutes = compilation.manifest.apis; | ||
|
||
if (!await checkResourceExists(adapterOutputUrl)) { | ||
await fs.mkdir(adapterOutputUrl); | ||
} | ||
|
||
console.log({ ssrPages, apiRoutes }); | ||
|
||
for (const page of ssrPages) { | ||
const { id } = page; | ||
const outputFormat = generateOutputFormat(id, 'page'); | ||
|
||
await fs.writeFile(new URL(`./${id}.js`, adapterOutputUrl), outputFormat); | ||
} | ||
|
||
// public/api/ | ||
for (const [key] of apiRoutes) { | ||
const id = key.replace('/api/', ''); | ||
const outputFormat = generateOutputFormat(id, 'api'); | ||
|
||
await fs.writeFile(new URL(`./${id}.js`, adapterOutputUrl), outputFormat); | ||
} | ||
} | ||
|
||
const greenwoodPluginAdapterGeneric = (options = {}) => [{ | ||
type: 'adapter', | ||
name: 'plugin-adapter-generic', | ||
provider: (compilation) => { | ||
return async () => { | ||
await genericAdapter(compilation, options); | ||
}; | ||
} | ||
}]; | ||
|
||
export { greenwoodPluginAdapterGeneric }; |
7 changes: 7 additions & 0 deletions
7
packages/cli/test/cases/build.plugins.adapter/greenwood.config.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,7 @@ | ||
import { greenwoodPluginAdapterGeneric } from './generic-adapter.js'; | ||
|
||
export default { | ||
plugins: [ | ||
greenwoodPluginAdapterGeneric() | ||
] | ||
}; |
12 changes: 12 additions & 0 deletions
12
packages/cli/test/cases/build.plugins.adapter/src/api/greeting.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,12 @@ | ||
export async function handler(request) { | ||
const params = new URLSearchParams(request.url.slice(request.url.indexOf('?'))); | ||
const name = params.has('name') ? params.get('name') : 'World'; | ||
const body = { message: `Hello ${name}!` }; | ||
const headers = new Headers(); | ||
|
||
headers.append('Content-Type', 'application/json'); | ||
|
||
return new Response(JSON.stringify(body), { | ||
headers | ||
}); | ||
} |
22 changes: 22 additions & 0 deletions
22
packages/cli/test/cases/build.plugins.adapter/src/components/card.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,22 @@ | ||
export default class Card extends HTMLElement { | ||
|
||
selectArtist() { | ||
alert(`selected artist is => ${this.getAttribute('title')}!`); | ||
} | ||
|
||
connectedCallback() { | ||
const thumbnail = this.getAttribute('thumbnail'); | ||
const title = this.getAttribute('title'); | ||
|
||
this.innerHTML = ` | ||
<div> | ||
<h2>${title}</h2> | ||
<button onclick="this.parentNode.parentNode.selectArtist()">View Artist Details</button> | ||
<img src="${thumbnail}" loading="lazy" width="50%"> | ||
<hr/> | ||
</div> | ||
`; | ||
} | ||
} | ||
|
||
customElements.define('app-card', Card); |
24 changes: 24 additions & 0 deletions
24
packages/cli/test/cases/build.plugins.adapter/src/pages/index.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,24 @@ | ||
import '../components/card.js'; | ||
|
||
export default class ArtistsPage extends HTMLElement { | ||
async connectedCallback() { | ||
const artists = [{ name: 'Analog', imageUrl: 'https://www.analogstudios.net/images/analog.png' }]; | ||
const html = artists.map(artist => { | ||
const { name, imageUrl } = artist; | ||
|
||
return ` | ||
<app-card | ||
title="${name}" | ||
thumbnail="${imageUrl}" | ||
> | ||
</app-card> | ||
`; | ||
}).join(''); | ||
|
||
this.innerHTML = ` | ||
<a href="/">< Back</a> | ||
<h1>List of Artists: ${artists.length}</h1> | ||
${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