Skip to content

Commit

Permalink
fix(git): .gitignore fix
Browse files Browse the repository at this point in the history
  • Loading branch information
magnusriga committed May 5, 2019
1 parent df9b0ac commit 5314d0c
Show file tree
Hide file tree
Showing 7 changed files with 423 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ test-results.json
package-lock.json
yarn.lock

gatsby*
/gatsby*
!index.js
yarn.lock

Expand Down
67 changes: 67 additions & 0 deletions src/__tests__/gatsby-browser.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { onClientEntry } from '../gatsby-browser';
import GSCMock from '../.cache/GlobalStyleComponent';
import themeMock from '../.cache/GlobalStylePropsTheme';
import otherMock from '../.cache/GlobalStylePropsOther';

jest.mock(
`../.cache/GlobalStyleComponent`,
() => {
return {
globalStyle: {
renderStyles: jest.fn(),
elementId: 'GlobalStyle',
},
};
},
{ virtual: true }
);

jest.mock(
`../.cache/GlobalStylePropsTheme`,
() => {
return { typography: { fontFamily: 'Roboto' } };
},
{ virtual: true }
);

jest.mock(
`../.cache/GlobalStylePropsOther`,
() => {
return { light: true };
},
{ virtual: true }
);

describe(`onClientEntry`, () => {
beforeEach(() => {
process.env.BUILD_STAGE = `develop`;
});

afterAll(() => {
delete process.env.BUILD_STAGE;
});

beforeEach(() => {
// Completely restes mock back to initial value, including all information
// stored in mockFn.mock.calls and mockFn.mock.instances arrays,
// as well as any mocked return values or implementations.
// Replaces mockFn.mock (not just mockFn.mock.calls and mockFn.mock.instances)
jest.resetAllMocks();
});

it(`should inject CSS rules`, () => {
// onClientEntry comes from a different copy of gatsby-browser,
// compared to the other tests. This is due to jest.resetModules().
onClientEntry();

expect(GSCMock.globalStyle.renderStyles).toHaveBeenCalledWith(
expect.objectContaining({ theme: themeMock, ...otherMock })
);
});

it('should not run if BUILD_STAGE is not develop', () => {
process.env.BUILD_STAGE = `build-html`;
onClientEntry();
expect(GSCMock.globalStyle.renderStyles).not.toHaveBeenCalled();
});
});
79 changes: 79 additions & 0 deletions src/__tests__/gatsby-node.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import path from 'path';
import rimraf from 'rimraf';
import os from 'os';
import * as gatsbyNode from '../gatsby-node';

const onPreBootstrapMock = jest.spyOn(gatsbyNode, 'onPreBootstrap');

const rootDir = path.join(__dirname, '../..');
const store = { store: { getState: () => ({ program: { directory: rootDir } }) } };

jest.mock('os', () => {
return {
platform: jest.fn(() => 'win32'),
};
});

let options;
let emptyOptions;

describe('gatsby-node.js', () => {
beforeEach(() => {
jest.clearAllMocks();

options = {
pathToConfigModule: `src/styles/GlobalStyleComponent`,
props: {
theme: `src/styles/theme`,
other: {
light: true,
},
},
};

emptyOptions = {
pathToConfigModule: ``,
props: {},
};
});

afterAll(done => {
rimraf(path.join(rootDir, `/src/.cache`), () => {
done();
});
});

it('Can create cache when none exist', done => {
const dir = path.join(rootDir, `/src/.cache`);
rimraf(dir, () => {
onPreBootstrapMock(store, emptyOptions);
expect(onPreBootstrapMock).toHaveBeenCalledWith(store, emptyOptions);
done();
});
});

it('can create cache when options are passed in', () => {
onPreBootstrapMock(store, options);
expect(onPreBootstrapMock).toHaveBeenCalledWith(store, options);
});

it('options can use absolute paths', () => {
const configDir = path.join(rootDir, `src/styles/GlobalStyleComponent`);
const themeDir = path.join(rootDir, `src/styles/theme`);
options.pathToConfigModule = configDir;
options.props.theme = themeDir;
onPreBootstrapMock(store, options);
expect(onPreBootstrapMock).toHaveBeenCalledWith(store, options);
});

it('can run on different platforms', () => {
os.platform.mockReturnValue('linux');
onPreBootstrapMock(store, options);
expect(onPreBootstrapMock).toHaveBeenCalledWith(store, options);
});

it('can create cache when no options are passed in', () => {
onPreBootstrapMock(store, emptyOptions);
expect(onPreBootstrapMock).toHaveBeenCalledWith(store, emptyOptions);
});
});
150 changes: 150 additions & 0 deletions src/__tests__/gatsby-ssr.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import React from 'react';
import { onPreRenderHTML, onRenderBody } from '../gatsby-ssr';

jest.mock(
`../.cache/GlobalStyleComponent`,
() => {
return {
globalStyle: {
ReactStyleComponent: () => <style />,
elementId: 'GlobalStyle',
},
};
},
{ virtual: true }
);

jest.mock(
`../.cache/GlobalStylePropsTheme`,
() => {
return { typography: { fontFamily: 'Roboto' } };
},
{ virtual: true }
);

jest.mock(
`../.cache/GlobalStylePropsOther`,
() => {
return { light: true };
},
{ virtual: true }
);

// Clone and merge array of multiple arrays into one flat array (flattens array)
const clone = arr => [...arr];

describe(`onRenderBody`, () => {
const setup = (options = {}, env = `build-html`) => {
process.env.BUILD_STAGE = env;
const api = {
setHeadComponents: jest.fn(),
};
onRenderBody(api, options);
return api;
};

beforeEach(() => {
jest.resetAllMocks();
});

afterAll(() => {
delete process.env.BUILD_STAGE;
});

it(`invokes setHeadComponents with array containing GlobalStyleComponent`, () => {
const api = setup();

expect(api.setHeadComponents).toHaveBeenCalledWith([
expect.objectContaining({ key: expect.stringContaining('GlobalStyle') }),
]);
});

it(`only invokes setHeadComponents if BUILD_STAGE is build-html`, () => {
const api = setup({}, `develop`);

expect(api.setHeadComponents).not.toHaveBeenCalled();
});
});

describe(`onPreRenderHTML`, () => {
const setup = (components = []) => {
const api = {
getHeadComponents: jest.fn(() => components),
replaceHeadComponents: jest.fn(),
};
onPreRenderHTML(api);
return api;
};

it(`reorders GlobalStyle first`, () => {
const spies = setup([
{
key: `link-1234`,
},
{
key: `link-preload`,
},
{
key: `GlobalStyle`,
},
]);

expect(spies.replaceHeadComponents).toHaveBeenCalledTimes(1);
expect(spies.replaceHeadComponents).toHaveBeenCalledWith(
expect.arrayContaining([
{
key: `GlobalStyle`,
},
])
);
});

it(`leaves non-GlobalStyle head components as-is`, () => {
const components = [
{
key: `link-1234`,
},
{
key: `link-preload`,
},
{
key: `_____01234_____`,
},
];

const spies = setup(clone(components));

// Check that it did not reorder when GlobalStyle was not in list
// Component list Clone which we ran reorder on, should be identical to original component list
expect(spies.replaceHeadComponents).toHaveBeenCalledWith(components);
});

it(`does not fail when head components include null`, () => {
const components = [
{
key: `link-1234`,
},
{
key: `link-preload`,
},
{
key: `_____01234_____`,
},
null,
];

const spies = setup(clone(components));

expect(spies.replaceHeadComponents).toHaveBeenCalledWith(components);
expect(spies.replaceHeadComponents).toHaveReturned();
});
});

/*
describe(`onRenderBody`, () => {
it(`injects theme if theme is passed`);
it(`uses default theme if no theme is passed.`);
it(`injects other props if any are passed`);
});
*/
15 changes: 15 additions & 0 deletions src/gatsby-browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Hot reload gatsby-plugin-global-styles in development

import GlobalStyleComponent from './.cache/GlobalStyleComponent';
import GlobalStylePropsTheme from './.cache/GlobalStylePropsTheme';
import GlobalStylePropsOther from './.cache/GlobalStylePropsOther';

// eslint-disable-next-line import/prefer-default-export
export const onClientEntry = () => {
if (process.env.BUILD_STAGE === `develop`) {
GlobalStyleComponent.globalStyle.renderStyles({
theme: GlobalStylePropsTheme,
...GlobalStylePropsOther,
});
}
};
74 changes: 74 additions & 0 deletions src/gatsby-node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import fs from 'fs';
import path from 'path';
import os from 'os';

// Write out the GlobalStyleComponent module to .cache.
// Happens before webpack starts compiling page.
// .cache is available when gatsby-browser.js and gatsby-ssr.js runs.

// eslint-disable-next-line import/prefer-default-export
export const onPreBootstrap = ({ store }, pluginOptions) => {
const { program } = store.getState();

let module;
if (pluginOptions.pathToConfigModule) {
module = `import GlobalStyleComponent from "${
path.isAbsolute(pluginOptions.pathToConfigModule)
? pluginOptions.pathToConfigModule
: path.join(program.directory, pluginOptions.pathToConfigModule)
}";
export default GlobalStyleComponent;
`;

if (os.platform() === `win32`) {
module = module.split(`\\`).join(`\\\\`);
}
} else {
module = `import createGlobalStyle from 'global-styles';
const GlobalStyleComponent = createGlobalStyle\`\`;
export default GlobalStyleComponent;
`;
}

const dir = `${__dirname}/.cache`;

if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}

fs.writeFileSync(`${dir}/GlobalStyleComponent.js`, module);

// Write Props.theme to cache.
if (pluginOptions.props.theme) {
module = `import theme from "${
path.isAbsolute(pluginOptions.props.theme)
? pluginOptions.props.theme
: path.join(program.directory, pluginOptions.props.theme)
}";
export default theme;
`;

if (os.platform() === `win32`) {
module = module.split(`\\`).join(`\\\\`);
}
} else {
module = `const defaultTheme = { typography: { fontFamily: 'Arial' } };
export default defaultTheme;
`;
}

fs.writeFileSync(`${dir}/GlobalStylePropsTheme.js`, module);

// Write Props.other to cache.
if (pluginOptions.props.other) {
module = `const otherProps = ${JSON.stringify(pluginOptions.props.other)};
export default otherProps;
`;
} else {
module = `const emptyOtherProps = {};
export default emptyOtherProps;
`;
}

fs.writeFileSync(`${dir}/GlobalStylePropsOther.js`, module);
};
Loading

0 comments on commit 5314d0c

Please sign in to comment.