grafana/toolkit: Add default mock for stylesheet imports for Jest (#18955)

Up until now one had to manually specify module name mapper for stylesheet files in order for Jest not to fail when running tests that import stylesheet files.

This adds default mock for stylesheet file and some tests
This commit is contained in:
Dominik Prokop
2019-09-09 08:43:15 +02:00
committed by GitHub
parent e2b1cdd7ac
commit 205c0a58ac
15 changed files with 84 additions and 17 deletions

View File

@@ -60,6 +60,7 @@ const copyFiles = () => {
'src/config/tsconfig.plugin.json',
'src/config/tsconfig.plugin.local.json',
'src/config/tslint.plugin.json',
'src/config/styles.mock.js',
// plugin test file
'src/plugins/e2e/commonPluginTests.ts',

View File

@@ -0,0 +1,34 @@
import { jestConfig, allowedJestConfigOverrides } from './jest.plugin.config';
describe('Jest config', () => {
it('should throw if not supported overrides provided', () => {
const getConfig = () => jestConfig(`${__dirname}/mocks/jestSetup/unsupportedOverrides`);
expect(getConfig).toThrow('Provided Jest config is not supported');
});
it(`should allow ${allowedJestConfigOverrides} settings overrides`, () => {
const config = jestConfig(`${__dirname}/mocks/jestSetup/overrides`);
const configKeys = Object.keys(config);
for (const whitelistedOption of allowedJestConfigOverrides) {
expect(configKeys).toContain(whitelistedOption);
}
});
describe('stylesheets support', () => {
it('should provide module name mapper for stylesheets by default', () => {
const config = jestConfig(`${__dirname}/mocks/jestSetup/noOverrides`);
expect(config.moduleNameMapper).toBeDefined();
expect(Object.keys(config.moduleNameMapper)).toContain('\\.(css|sass|scss)$');
});
it('should preserve mapping for stylesheets when moduleNameMapper overrides provided', () => {
const config = jestConfig(`${__dirname}/mocks/jestSetup/overrides`);
expect(config.moduleNameMapper).toBeDefined();
expect(Object.keys(config.moduleNameMapper)).toHaveLength(2);
expect(Object.keys(config.moduleNameMapper)).toContain('\\.(css|sass|scss)$');
expect(Object.keys(config.moduleNameMapper)).toContain('someOverride');
});
});
});

View File

@@ -1,21 +1,35 @@
import path = require('path');
import fs from 'fs';
const whitelistedJestConfigOverrides = ['snapshotSerializers', 'moduleNameMapper'];
export const allowedJestConfigOverrides = ['snapshotSerializers', 'moduleNameMapper'];
export const jestConfig = () => {
const jestConfigOverrides = require(path.resolve(process.cwd(), 'package.json')).jest;
const blacklistedOverrides = jestConfigOverrides
? Object.keys(jestConfigOverrides).filter(override => whitelistedJestConfigOverrides.indexOf(override) === -1)
interface EnabledJestConfigOverrides {
snapshotSerializers: string[];
moduleNameMapper: { [key: string]: string };
}
export const jestConfig = (baseDir: string = process.cwd()) => {
const jestConfigOverrides = (require(path.resolve(baseDir, 'package.json')).jest || {}) as EnabledJestConfigOverrides;
const deniedOverrides = jestConfigOverrides
? Object.keys(jestConfigOverrides).filter(override => allowedJestConfigOverrides.indexOf(override) === -1)
: [];
if (blacklistedOverrides.length > 0) {
console.error("\ngrafana-toolkit doesn't support following Jest options: ", blacklistedOverrides);
console.log('Supported Jest options are: ', JSON.stringify(whitelistedJestConfigOverrides));
if (deniedOverrides.length > 0) {
console.error("\ngrafana-toolkit doesn't support following Jest options: ", deniedOverrides);
console.log('Supported Jest options are: ', JSON.stringify(allowedJestConfigOverrides));
throw new Error('Provided Jest config is not supported');
}
const shimsFilePath = path.resolve(process.cwd(), 'config/jest-shim.ts');
const setupFilePath = path.resolve(process.cwd(), 'config/jest-setup.ts');
const shimsFilePath = path.resolve(baseDir, 'config/jest-shim.ts');
const setupFilePath = path.resolve(baseDir, 'config/jest-setup.ts');
// Mock css imports for tests. Otherwise Jest will have troubles understanding SASS/CSS imports
const { moduleNameMapper, ...otherOverrides } = jestConfigOverrides;
const moduleNameMapperConfig = {
'\\.(css|sass|scss)$': `${__dirname}/styles.mock.js`,
...moduleNameMapper,
};
const setupFile = fs.existsSync(setupFilePath) ? setupFilePath : undefined;
const shimsFile = fs.existsSync(shimsFilePath) ? shimsFilePath : undefined;
@@ -29,7 +43,6 @@ export const jestConfig = () => {
globals: { 'ts-jest': { isolatedModules: true } },
coverageReporters: ['json-summary', 'text', 'lcov'],
collectCoverageFrom: ['src/**/*.{ts,tsx}', '!**/node_modules/**', '!**/vendor/**'],
testMatch: [
'<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}',
'<rootDir>/src/**/*.{spec,test,jest}.{js,jsx,ts,tsx}',
@@ -38,10 +51,11 @@ export const jestConfig = () => {
'[/\\\\\\\\]node_modules[/\\\\\\\\].+\\\\.(js|jsx|ts|tsx)$',
'^.+\\\\.module\\\\.(css|sass|scss)$',
],
moduleNameMapper: moduleNameMapperConfig,
};
return {
...defaultJestConfig,
...jestConfigOverrides,
...otherOverrides,
};
};

View File

@@ -0,0 +1,8 @@
{
"jest": {
"moduleNameMapper": {
"someOverride": "somePath"
},
"snapshotSerializers": "serializers"
}
}

View File

@@ -0,0 +1,5 @@
{
"jest": {
"runner": "some-runner"
}
}

View File

@@ -0,0 +1,4 @@
// Mock for handling stylesheet file imports in tests
// https://jestjs.io/docs/en/webpack.html#handling-static-assets
module.exports = {};

View File

@@ -11,12 +11,12 @@ describe('Loaders', () => {
describe('getStylesheetEntries', () => {
it('returns entries for dark and light theme', () => {
const result = getStylesheetEntries(`${__dirname}/mocks/ok`);
const result = getStylesheetEntries(`${__dirname}/../mocks/stylesheetsSupport/ok`);
expect(Object.keys(result)).toHaveLength(2);
});
it('throws on theme files duplicates', () => {
const result = () => {
getStylesheetEntries(`${__dirname}/mocks/duplicates`);
getStylesheetEntries(`${__dirname}/../mocks/stylesheetsSupport/duplicates`);
};
expect(result).toThrow();
});
@@ -25,19 +25,19 @@ describe('Loaders', () => {
describe('hasThemeStylesheets', () => {
it('throws when only one theme file is defined', () => {
const result = () => {
hasThemeStylesheets(`${__dirname}/mocks/missing-theme-file`);
hasThemeStylesheets(`${__dirname}/../mocks/stylesheetsSupport/missing-theme-file`);
};
expect(result).toThrow();
});
it('returns false when no theme files present', () => {
const result = hasThemeStylesheets(`${__dirname}/mocks/no-theme-files`);
const result = hasThemeStylesheets(`${__dirname}/../mocks/stylesheetsSupport/no-theme-files`);
expect(result).toBeFalsy();
});
it('returns true when theme files present', () => {
const result = hasThemeStylesheets(`${__dirname}/mocks/ok`);
const result = hasThemeStylesheets(`${__dirname}/../mocks/stylesheetsSupport/ok`);
expect(result).toBeTruthy();
});