diff --git a/.mocharc.js b/.mocharc.js index d4405360c..61504b775 100644 --- a/.mocharc.js +++ b/.mocharc.js @@ -1,7 +1,6 @@ const path = require('path'); module.exports = { - // TODO spec: path.join(__dirname, 'packages/**/test/**/**/**/*.spec.js'), - spec: path.join(__dirname, 'packages/**/test/cases/**/**/*.spec.js'), + spec: path.join(__dirname, 'packages/**/test/**/**/**/*.spec.js'), timeout: 30000 }; \ No newline at end of file diff --git a/greenwood.config.js b/greenwood.config.js index 3b0aaf883..d9eb4f88c 100644 --- a/greenwood.config.js +++ b/greenwood.config.js @@ -1,5 +1,7 @@ const path = require('path'); +// const pluginImportCommonjs = require('./packages/plugin-import-commonjs/src/index'); const pluginGoogleAnalytics = require('./packages/plugin-google-analytics/src/index'); +const pluginGraphQL = require('./packages/plugin-graphql/src/index'); const pluginImportCss = require('./packages/plugin-import-css/src/index'); const pluginPolyfills = require('./packages/plugin-polyfills/src/index'); const pluginPostCss = require('./packages/plugin-postcss/src/index'); @@ -23,9 +25,11 @@ module.exports = { { name: 'google-site-verification', content: '4rYd8k5aFD0jDnN0CCFgUXNe4eakLP4NnA18mNnK5P0' } ], plugins: [ + // ...pluginImportCommonjs(), pluginGoogleAnalytics({ analyticsId: 'UA-147204327-1' }), + ...pluginGraphQL(), pluginPolyfills(), pluginPostCss(), ...pluginImportCss() diff --git a/packages/cli/src/commands/build.js b/packages/cli/src/commands/build.js index 940a4af53..069b88fb8 100644 --- a/packages/cli/src/commands/build.js +++ b/packages/cli/src/commands/build.js @@ -1,9 +1,10 @@ const bundleCompilation = require('../lifecycles/bundle'); const copyAssets = require('../lifecycles/copy'); +const { devServer } = require('../lifecycles/serve'); const fs = require('fs'); const generateCompilation = require('../lifecycles/compile'); const serializeCompilation = require('../lifecycles/serialize'); -const { devServer } = require('../lifecycles/serve'); +const { ServerInterface } = require('../lib/server-interface'); module.exports = runProductionBuild = async () => { @@ -14,17 +15,38 @@ module.exports = runProductionBuild = async () => { const port = compilation.config.devServer.port; const outputDir = compilation.context.outputDir; - devServer(compilation).listen(port); - - if (!fs.existsSync(outputDir)) { - fs.mkdirSync(outputDir); - } - - await serializeCompilation(compilation); - await bundleCompilation(compilation); - await copyAssets(compilation); + devServer(compilation).listen(port, async () => { + console.info(`Started local development server at localhost:${port}`); + + // custom user server plugins + const servers = [...compilation.config.plugins.filter((plugin) => { + return plugin.type === 'server'; + }).map((plugin) => { + const provider = plugin.provider(compilation); + + if (!(provider instanceof ServerInterface)) { + console.warn(`WARNING: ${plugin.name}'s provider is not an instance of ServerInterface.`); + } + + return provider; + })]; + + await Promise.all(servers.map(async (server) => { + server.start(); + + return Promise.resolve(server); + })); + + if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir); + } + + await serializeCompilation(compilation); + await bundleCompilation(compilation); + await copyAssets(compilation); - resolve(); + resolve(); + }); } catch (err) { reject(err); } diff --git a/packages/cli/src/config/rollup.config.js b/packages/cli/src/config/rollup.config.js index a2110f7db..43e2d7df4 100644 --- a/packages/cli/src/config/rollup.config.js +++ b/packages/cli/src/config/rollup.config.js @@ -116,16 +116,17 @@ function greenwoodHtmlPlugin(compilation) { case '.html': return Promise.resolve(''); default: - customResources.filter((resource) => { - const shouldServe = Promise.resolve(resource.shouldServe(id)); + const resourceHandler = (await Promise.all(customResources.map(async (resource) => { + const shouldServe = await resource.shouldServe(id); - if (shouldServe) { - return resource; - } - }); + return shouldServe + ? resource + : null; + }))).filter(resource => resource); - if (customResources.length) { - const response = await customResources[0].serve(id); + // TODO should reduce here instead + if (resourceHandler.length) { + const response = await resourceHandler[0].serve(id); return Promise.resolve(response.body); } diff --git a/packages/cli/src/data/common.js b/packages/cli/src/data/common.js deleted file mode 100644 index 278a7370e..000000000 --- a/packages/cli/src/data/common.js +++ /dev/null @@ -1,46 +0,0 @@ -// https://gist.github.com/hyamamoto/fd435505d29ebfa3d9716fd2be8d42f0#gistcomment-2775538 -function hashString(queryKeysString) { - let h = 0; - - for (let i = 0; i < queryKeysString.length; i += 1) { - h = Math.imul(31, h) + queryKeysString.charCodeAt(i) | 0; // eslint-disable-line no-bitwise - } - - return Math.abs(h).toString(); -} - -function getQueryKeysFromSelectionSet(selectionSet) { - let queryKeys = ''; - - for (let key in selectionSet) { - - if (key === 'selections') { - queryKeys += selectionSet[key] - .filter(selection => selection.name.value !== '__typename') // __typename is added by server.js - .map(selection => selection.name.value).join(''); - } - } - - if (selectionSet.kind === 'SelectionSet') { - selectionSet.selections.forEach(selection => { - if (selection.selectionSet) { - queryKeys += getQueryKeysFromSelectionSet(selection.selectionSet); - } - }); - } - - return queryKeys; -} - -function getQueryHash(query, variables = {}) { - const queryKeys = getQueryKeysFromSelectionSet(query.definitions[0].selectionSet); - const variableValues = Object.keys(variables).length > 0 - ? `_${Object.values(variables).join('').replace(/\//g, '')}` // handle / which will translate to filepaths - : ''; - - return hashString(`${queryKeys}${variableValues}`); -} - -module.exports = { - getQueryHash -}; \ No newline at end of file diff --git a/packages/cli/src/data/queries/children.gql b/packages/cli/src/data/queries/children.gql deleted file mode 100644 index 3f7303b29..000000000 --- a/packages/cli/src/data/queries/children.gql +++ /dev/null @@ -1,10 +0,0 @@ -query($parent: String!) { - children(parent: $parent) { - id, - title, - link, - filePath, - fileName, - template - } -} \ No newline at end of file diff --git a/packages/cli/src/data/queries/graph.gql b/packages/cli/src/data/queries/graph.gql deleted file mode 100644 index 7aaf1fd02..000000000 --- a/packages/cli/src/data/queries/graph.gql +++ /dev/null @@ -1,10 +0,0 @@ -query { - graph { - id, - title, - link, - filePath, - fileName, - template - } -} \ No newline at end of file diff --git a/packages/cli/src/lifecycles/config.js b/packages/cli/src/lifecycles/config.js index c938b38a3..7e931844e 100644 --- a/packages/cli/src/lifecycles/config.js +++ b/packages/cli/src/lifecycles/config.js @@ -7,7 +7,7 @@ let defaultConfig = { devServer: { port: 1984 }, - // TODO optimization: 'spa', + optimization: '', title: 'My App', meta: [], plugins: [], diff --git a/packages/cli/src/lifecycles/graph.js b/packages/cli/src/lifecycles/graph.js index 06ae222df..dde8db77a 100644 --- a/packages/cli/src/lifecycles/graph.js +++ b/packages/cli/src/lifecycles/graph.js @@ -24,7 +24,11 @@ module.exports = generateGraph = async (compilation) => { const relativeWorkspacePath = directory.replace(process.cwd(), '').replace('/', ''); const template = attributes.template || 'page'; const title = attributes.title || compilation.config.title || ''; - const label = attributes.label || filename.split('/')[filename.split('/').length - 1].replace('.md', '').replace('.html', ''); + const id = attributes.label || filename.split('/')[filename.split('/').length - 1].replace('.md', '').replace('.html', ''); + const label = id.split('-') + .map((idPart) => { + return `${idPart.charAt(0).toUpperCase()}${idPart.substring(1)}`; + }).join(' '); let route = relativePagePath.replace('.md', '').replace('.html', ''); /* @@ -37,7 +41,7 @@ module.exports = generateGraph = async (compilation) => { */ if (relativePagePath.lastIndexOf('/') > 0) { // https://github.com/ProjectEvergreen/greenwood/issues/455 - route = label === 'index' || route.replace('/index', '') === `/${label}` + route = id === 'index' || route.replace('/index', '') === `/${id}` ? route.replace('index', '') : `${route}/`; } else { @@ -91,7 +95,8 @@ module.exports = generateGraph = async (compilation) => { *---------------------- * data: custom page frontmatter * filename: name of the file - * label: text representation of the filename + * id: filename without the extension + * label: "pretty" text representation of the filename * path: path to the file relative to the workspace * route: URL route for a given page on outputFilePath * template: page template to use as a base for a generated component @@ -100,6 +105,7 @@ module.exports = generateGraph = async (compilation) => { pages.push({ data: customData || {}, filename, + id, label, path: route === '/' || relativePagePath.lastIndexOf('/') === 0 ? `${relativeWorkspacePath}${filename}` diff --git a/packages/cli/src/lifecycles/serve.js b/packages/cli/src/lifecycles/serve.js index ff6493158..24619e6d0 100644 --- a/packages/cli/src/lifecycles/serve.js +++ b/packages/cli/src/lifecycles/serve.js @@ -189,7 +189,7 @@ function getProdServer(compilation) { } if (url.endsWith('.json')) { - const contents = await fs.promises.readFile(path.join(outputDir, 'graph.json'), 'utf-8'); + const contents = await fs.promises.readFile(path.join(outputDir, url), 'utf-8'); ctx.set('Content-Type', 'application/json'); ctx.body = JSON.parse(contents); diff --git a/packages/cli/src/plugins/resource/plugin-node-modules.js b/packages/cli/src/plugins/resource/plugin-node-modules.js index cb5557249..836a25bea 100644 --- a/packages/cli/src/plugins/resource/plugin-node-modules.js +++ b/packages/cli/src/plugins/resource/plugin-node-modules.js @@ -179,7 +179,14 @@ class NodeModulesResource extends ResourceInterface { async serve(url) { return new Promise(async(resolve, reject) => { try { - const fullUrl = path.extname(url) === '' ? `${url}.js` : url; + const fullUrl = path.extname(url) === '' + ? `${url}.js` + : url; + // const fullUrl = path.extname(url) === '' + // ? fs.existsSync(`${url}.mjs`) // test for .mjs first + // ? `${url}.mjs` + // : `${url}.js` + // : url; const body = await fs.promises.readFile(fullUrl); resolve({ diff --git a/packages/cli/src/plugins/server/plugin-livereload.js b/packages/cli/src/plugins/server/plugin-livereload.js index 4c8f9051d..75da0eb94 100644 --- a/packages/cli/src/plugins/server/plugin-livereload.js +++ b/packages/cli/src/plugins/server/plugin-livereload.js @@ -1,5 +1,4 @@ const livereload = require('livereload'); -const path = require('path'); const { ResourceInterface } = require('../../lib/resource-interface'); const { ServerInterface } = require('../../lib/server-interface'); @@ -25,8 +24,10 @@ class LiveReloadServer extends ServerInterface { class LiveReloadResource extends ResourceInterface { - async shouldIntercept(url) { - return Promise.resolve(path.extname(url) === '' && process.env.__GWD_COMMAND__ === 'develop'); // eslint-disable-line no-underscore-dangle + async shouldIntercept(url, body, headers) { + const { accept } = headers.request; + + return Promise.resolve(accept && accept.indexOf('text/html') >= 0 && process.env.__GWD_COMMAND__ === 'develop'); // eslint-disable-line no-underscore-dangle } async intercept(url, body) { diff --git a/packages/cli/test/cases/build.data.graph-custom-frontmatter/build.data.graph-custom-frontmatter.spec.js b/packages/cli/test/cases/build.data.graph-custom-frontmatter/build.data.graph-custom-frontmatter.spec.js deleted file mode 100644 index 1290dc20d..000000000 --- a/packages/cli/test/cases/build.data.graph-custom-frontmatter/build.data.graph-custom-frontmatter.spec.js +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Use Case - * Run Greenwood build command with GraphQL calls to get data about the projects graph. - * - * User Result - * Should generate a Greenwood build that specifically tests for custom frontmatter set by individual pages. - * - * User Command - * greenwood build - * - * Default Config - * - * Custom Workspace - * src/ - * pages/ - * blog/ - * first-post.md - * second-post.md - * index.md - * templates/ - * blog-template.js - */ -const expect = require('chai').expect; -const fs = require('fs'); -const glob = require('glob-promise'); -const { JSDOM } = require('jsdom'); -const path = require('path'); -const TestBed = require('../../../../../test/test-bed'); - -const mainBundleScriptRegex = /index.*.bundle\.js/; - -xdescribe('Build Greenwood With: ', function() { - const LABEL = 'Data from GraphQL and using Custom Frontmatter Data'; - const apolloStateRegex = /window.__APOLLO_STATE__ = true/; - let setup; - - before(async function() { - setup = new TestBed(); - this.context = await setup.setupTestBed(__dirname); - }); - - describe(LABEL, function() { - - before(async function() { - await setup.runGreenwoodCommand('build'); - }); - - runSmokeTest(['public', 'not-found'], LABEL); - - describe('Blog Page (Template) w/ custom date', function() { - beforeEach(async function() { - dom = await JSDOM.fromFile(path.resolve(this.context.publicDir, 'blog', 'first-post', 'index.html')); - }); - - it('should output an index.html file (first post page)', function() { - expect(fs.existsSync(path.join(this.context.publicDir, 'blog', 'first-post', 'index.html'))).to.be.true; - }); - - it('should output a (partial) *-cache.json file, one per each query made', async function() { - expect(await glob.promise(path.join(this.context.publicDir, './*-cache.json'))).to.have.lengthOf(3); - }); - - it('should output a (partial) *-cache.json files, one per each query made, that are all defined', async function() { - const cacheFiles = await glob.promise(path.join(this.context.publicDir, './*-cache.json')); - - cacheFiles.forEach(file => { - const cache = require(file); - - expect(cache).to.not.be.undefined; - }); - }); - - it('should have one + + `); + + resolve(body); + } catch (e) { + reject(e); + } + }); + } +} + +class GraphQLServer extends ServerInterface { + constructor(compilation, options = {}) { + super(compilation, options); + } + + async start() { + return graphqlServer(this.compilation).listen().then((server) => { + console.log(`GraphQLServer started at ${server.url}`); + }); + } +} + +module.exports = (options = {}) => { + return [{ + type: 'server', + name: 'plugin-graphql:server', + provider: (compilation) => new GraphQLServer(compilation, options) + }, { + type: 'resource', + name: 'plugin-graphql:resource', + provider: (compilation) => new GraphQLResource(compilation, options) + }, { + type: 'rollup', + name: 'plugin-graphql:rollup', + provider: () => [ + rollupPluginAlias({ + entries: [ + { find: '@greenwood/plugin-graphql/core/client', replacement: '@greenwood/plugin-graphql/src/core/client.js' }, + { find: '@greenwood/plugin-graphql/core/common', replacement: '@greenwood/plugin-graphql/src/core/common.client.js' }, + { find: '@greenwood/plugin-graphql/queries/menu', replacement: '@greenwood/plugin-graphql/src/queries/menu.gql' }, + { find: '@greenwood/plugin-graphql/queries/config', replacement: '@greenwood/plugin-graphql/src/queries/config.gql' }, + { find: '@greenwood/plugin-graphql/queries/children', replacement: '@greenwood/plugin-graphql/src/queries/children.gql' }, + { find: '@greenwood/plugin-graphql/queries/graph', replacement: '@greenwood/plugin-graphql/src/queries/graph.gql' } + ] + }) + ] + }]; +}; \ No newline at end of file diff --git a/packages/plugin-graphql/src/queries/children.gql b/packages/plugin-graphql/src/queries/children.gql new file mode 100644 index 000000000..295a70a64 --- /dev/null +++ b/packages/plugin-graphql/src/queries/children.gql @@ -0,0 +1,11 @@ +query($parent: String!) { + children(parent: $parent) { + id, + filename, + label, + path, + route, + template, + title + } +} \ No newline at end of file diff --git a/packages/cli/src/data/queries/config.gql b/packages/plugin-graphql/src/queries/config.gql similarity index 100% rename from packages/cli/src/data/queries/config.gql rename to packages/plugin-graphql/src/queries/config.gql diff --git a/packages/plugin-graphql/src/queries/graph.gql b/packages/plugin-graphql/src/queries/graph.gql new file mode 100644 index 000000000..99201dbc6 --- /dev/null +++ b/packages/plugin-graphql/src/queries/graph.gql @@ -0,0 +1,11 @@ +query { + graph { + id, + filename, + label, + path, + route, + template, + title + } +} \ No newline at end of file diff --git a/packages/cli/src/data/queries/menu.gql b/packages/plugin-graphql/src/queries/menu.gql similarity index 86% rename from packages/cli/src/data/queries/menu.gql rename to packages/plugin-graphql/src/queries/menu.gql index 101c77ece..ad205cec3 100644 --- a/packages/cli/src/data/queries/menu.gql +++ b/packages/plugin-graphql/src/queries/menu.gql @@ -2,17 +2,17 @@ query($name: String, $route: String, $order: MenuOrderBy) { menu(name: $name, pathname: $route, orderBy: $order) { item { label, - link + route } children { item { label, - link + route }, children { item { label, - link + route } } } diff --git a/packages/cli/src/data/schema/config.js b/packages/plugin-graphql/src/schema/config.js similarity index 100% rename from packages/cli/src/data/schema/config.js rename to packages/plugin-graphql/src/schema/config.js diff --git a/packages/cli/src/data/schema/graph.js b/packages/plugin-graphql/src/schema/graph.js similarity index 62% rename from packages/cli/src/data/schema/graph.js rename to packages/plugin-graphql/src/schema/graph.js index f5a74b73d..3c7f2a4f8 100644 --- a/packages/cli/src/data/schema/graph.js +++ b/packages/plugin-graphql/src/schema/graph.js @@ -6,7 +6,7 @@ const getMenuFromGraph = async (root, { name, pathname, orderBy }, context) => { graph .forEach((page) => { - const { route, data, title } = page; + const { route, data, label } = page; const { menu, index, tableOfContents, linkheadings } = data; let children = getParsedHeadingsFromPage(tableOfContents, linkheadings); @@ -20,17 +20,19 @@ const getMenuFromGraph = async (root, { name, pathname, orderBy }, context) => { } if (route.includes(baseRoute)) { - items.push({ item: { link: route, label: title, index }, children }); + items.push({ item: { route, label, index }, children }); } } else { - items.push({ item: { link: route, label: title, index }, children }); + items.push({ item: { route, label, index }, children }); } } }); + if (orderBy !== '') { items = sortMenuItems(items, orderBy); } - return { item: { label: name, link: 'na' }, children: items }; + + return Promise.resolve({ item: { label: name }, children: items }); }; const sortMenuItems = (menuItems, order) => { @@ -70,52 +72,15 @@ const getParsedHeadingsFromPage = (tableOfContents, headingLevel) => { tableOfContents.forEach(({ content, slug, lvl }) => { // make sure we only add heading elements of the same level (h1, h2, h3) if (lvl === headingLevel) { - children.push({ item: { label: content, link: '#' + slug }, children: [] }); + children.push({ item: { label: content, route: '#' + slug }, children: [] }); } }); } return children; }; -const getDeriveMetaFromRoute = (route) => { - const root = route.split('/')[1] || ''; - const label = root - .replace('/', '') - .replace('-', ' ') - .split(' ') - .map((word) => `${word.charAt(0).toUpperCase()}${word.substring(1)}`) - .join(' '); - - return { - label, - root - }; -}; - const getPagesFromGraph = async (root, query, context) => { - const pages = []; - const { graph } = context; - - graph - .forEach((page) => { - const { route, mdFile, fileName, template, title, data } = page; - const { label } = getDeriveMetaFromRoute(route); - const id = page.label; - - pages.push({ - id, - filePath: mdFile, - fileName, - template, - title: title !== '' ? title : label, - link: route, - data: { - ...data - } - }); - }); - - return pages; + return Promise.resolve(context.graph); }; const getChildrenFromParentRoute = async (root, query, context) => { @@ -125,44 +90,32 @@ const getChildrenFromParentRoute = async (root, query, context) => { graph .forEach((page) => { - const { route, mdFile, fileName, template, title, data } = page; - const { label } = getDeriveMetaFromRoute(route); + const { route, path } = page; const root = route.split('/')[1]; - if (root.indexOf(parent) >= 0 && mdFile !== `./${parent}/index.md`) { - const id = page.label; - - pages.push({ - id, - filePath: mdFile, - fileName, - template, - title: title !== '' ? title : label, - link: route, - data: { - ...data - } - }); + if (root === parent && path.indexOf(`${parent}/index.md`) < 0) { + pages.push(page); } }); - return pages; + return Promise.resolve(pages); }; const graphTypeDefs = gql` type Page { data: Data, + filename: String, id: String, - filePath: String, - fileName: String, + label: String, + path: String, + route: String, template: String, - link: String, title: String } type Link { label: String, - link: String + route: String } type Menu { diff --git a/packages/cli/src/data/schema/schema.js b/packages/plugin-graphql/src/schema/schema.js similarity index 100% rename from packages/cli/src/data/schema/schema.js rename to packages/plugin-graphql/src/schema/schema.js diff --git a/packages/plugin-graphql/test/cases/query-children/greenwood.config.js b/packages/plugin-graphql/test/cases/query-children/greenwood.config.js new file mode 100644 index 000000000..edb1b78c3 --- /dev/null +++ b/packages/plugin-graphql/test/cases/query-children/greenwood.config.js @@ -0,0 +1,10 @@ +const pluginGraphQL = require('../../../src/index'); + +module.exports = { + title: 'GraphQL ConfigQuery Spec', + + plugins: [ + ...pluginGraphQL() + ] + +}; \ No newline at end of file diff --git a/packages/plugin-graphql/test/cases/query-children/package.json b/packages/plugin-graphql/test/cases/query-children/package.json new file mode 100644 index 000000000..75d12a9b7 --- /dev/null +++ b/packages/plugin-graphql/test/cases/query-children/package.json @@ -0,0 +1,6 @@ +{ + "name": "plugin-graphql-test-children-query", + "dependencies": { + "lit-element": "^2.4.0" + } +} \ No newline at end of file diff --git a/packages/plugin-graphql/test/cases/query-children/src/components/posts-list.js b/packages/plugin-graphql/test/cases/query-children/src/components/posts-list.js new file mode 100644 index 000000000..87a688d27 --- /dev/null +++ b/packages/plugin-graphql/test/cases/query-children/src/components/posts-list.js @@ -0,0 +1,55 @@ +import { html, LitElement } from 'lit-element'; +import client from '@greenwood/plugin-graphql/core/client'; +import ChildrenQuery from '@greenwood/plugin-graphql/queries/children'; + +class PostsListTemplate extends LitElement { + + static get properties() { + return { + posts: { + type: Array + } + }; + } + + constructor() { + super(); + this.posts = []; + } + + async connectedCallback() { + super.connectedCallback(); + const response = await client.query({ + query: ChildrenQuery, + variables: { + parent: 'blog' + } + }); + + this.posts = response.data.children; + } + + /* eslint-disable indent */ + render() { + const { posts } = this; + + return html` +

My Posts

+ +
+ +
+ `; + } + /* eslint-enable */ +} + +customElements.define('posts-list', PostsListTemplate); \ No newline at end of file diff --git a/packages/plugin-graphql/test/cases/query-children/src/pages/blog/first-post/index.md b/packages/plugin-graphql/test/cases/query-children/src/pages/blog/first-post/index.md new file mode 100644 index 000000000..8af878ee7 --- /dev/null +++ b/packages/plugin-graphql/test/cases/query-children/src/pages/blog/first-post/index.md @@ -0,0 +1,8 @@ +--- +title: 'First' +--- + +## My First Blog Post +Lorem Ipsum + +[back](/) \ No newline at end of file diff --git a/packages/plugin-graphql/test/cases/query-children/src/pages/blog/second-post/index.md b/packages/plugin-graphql/test/cases/query-children/src/pages/blog/second-post/index.md new file mode 100644 index 000000000..d64aad85e --- /dev/null +++ b/packages/plugin-graphql/test/cases/query-children/src/pages/blog/second-post/index.md @@ -0,0 +1,8 @@ +--- +title: 'Second' +--- + +## My Second Blog Post +Lorem Ipsum + +[back](/) \ No newline at end of file diff --git a/packages/plugin-graphql/test/cases/query-children/src/pages/index.html b/packages/plugin-graphql/test/cases/query-children/src/pages/index.html new file mode 100644 index 000000000..4400ac0eb --- /dev/null +++ b/packages/plugin-graphql/test/cases/query-children/src/pages/index.html @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/plugin-graphql/test/cases/query-config/greenwood.config.js b/packages/plugin-graphql/test/cases/query-config/greenwood.config.js new file mode 100644 index 000000000..edb1b78c3 --- /dev/null +++ b/packages/plugin-graphql/test/cases/query-config/greenwood.config.js @@ -0,0 +1,10 @@ +const pluginGraphQL = require('../../../src/index'); + +module.exports = { + title: 'GraphQL ConfigQuery Spec', + + plugins: [ + ...pluginGraphQL() + ] + +}; \ No newline at end of file diff --git a/packages/plugin-graphql/test/cases/query-config/query-config.spec.js b/packages/plugin-graphql/test/cases/query-config/query-config.spec.js new file mode 100644 index 000000000..9f7749bc0 --- /dev/null +++ b/packages/plugin-graphql/test/cases/query-config/query-config.spec.js @@ -0,0 +1,110 @@ +/* + * Use Case + * Run Greenwood build command with GraphQL calls to get data from the project configuration. + * + * User Result + * Should generate a Greenwood build that dynamically serializes data from the config in the footer. + * + * User Command + * greenwood build + * + * Default Config (+ plugin-graphql) + * + * Custom Workspace + * greenwood.config.js + * src/ + * components/ + * footer.js + * pages/ + * index.html + */ +const expect = require('chai').expect; +const fs = require('fs'); +const greenwoodConfig = require('./greenwood.config'); +const glob = require('glob-promise'); +const { JSDOM } = require('jsdom'); +const path = require('path'); +const TestBed = require('../../../../../test/test-bed'); + +describe('Build Greenwood With: ', function() { + const LABEL = 'ConfigQuery from GraphQL'; + const apolloStateRegex = /window.__APOLLO_STATE__ = true/; + let setup; + + before(async function() { + setup = new TestBed(); + + const greenwoodGraphqlCoreLibs = (await glob(`${process.cwd()}/packages/plugin-graphql/src/core/*.js`)).map((lib) => { + return { + dir: 'node_modules/@greenwood/plugin-graphql/src/core/', + name: path.basename(lib) + }; + }); + + const greenwoodGraphqlQueryLibs = (await glob(`${process.cwd()}/packages/plugin-graphql/src/queries/*.gql`)).map((lib) => { + return { + dir: 'node_modules/@greenwood/plugin-graphql/src/queries/', + name: path.basename(lib) + }; + }); + + this.context = await setup.setupTestBed(__dirname, [ + ...greenwoodGraphqlCoreLibs, + ...greenwoodGraphqlQueryLibs + ]); + }); + + describe(LABEL, function() { + + before(async function() { + await setup.runGreenwoodCommand('build'); + }); + + describe('displaying config title in the footer using ConfigQuery', function() { + beforeEach(async function() { + dom = await JSDOM.fromFile(path.resolve(this.context.publicDir, 'index.html')); + }); + + it('should output an index.html file', function() { + expect(fs.existsSync(path.join(this.context.publicDir, './index.html'))).to.be.true; + }); + + it('should have a