Skip to content
This repository was archived by the owner on Jun 12, 2024. It is now read-only.

Commit dd9a6a9

Browse files
committed
[New] forEachDescriptor: provide variationProvider info to callback
1 parent 303cceb commit dd9a6a9

3 files changed

Lines changed: 85 additions & 23 deletions

File tree

src/traversal/forEachDescriptor.js

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
import entries from 'object.entries';
2+
import path from 'path';
3+
import has from 'has';
24

35
import validateProject from '../helpers/validateProject';
46
import getComponents from '../helpers/getComponents';
57
import getVariationProviders from '../helpers/getVariationProviders';
68
import getDescriptorFromProvider from '../helpers/getDescriptorFromProvider';
79

10+
function stripExtension(actualPath) {
11+
return path.join(path.dirname(actualPath), path.basename(actualPath, path.extname(actualPath)));
12+
}
13+
814
export default function forEachDescriptor(
915
projectConfig,
1016
{
@@ -20,7 +26,7 @@ export default function forEachDescriptor(
2026
}
2127

2228
const Components = getComponents(projectConfig, projectRoot);
23-
const variations = getVariationProviders(projectConfig, projectRoot);
29+
const variations = getVariationProviders(projectConfig, projectRoot, { fileMapOnly: true });
2430

2531
if (Object.keys(Components).length === 0) {
2632
throw new RangeError('Zero components found');
@@ -29,22 +35,37 @@ export default function forEachDescriptor(
2935
throw new RangeError('Zero variations found');
3036
}
3137

38+
const {
39+
variationsRoot,
40+
} = projectConfig;
41+
const actualRoot = variationsRoot ? path.join(projectRoot, variationsRoot) : projectRoot;
42+
3243
return function traverseVariationDescriptors(callback) {
3344
if (typeof callback !== 'function' || callback.length < 1 || callback.length > 2) {
3445
throw new TypeError('a callback that accepts exactly 1 or 2 arguments is required');
3546
}
36-
entries(variations).forEach(([path, provider]) => {
47+
entries(variations).forEach(([filePath, { actualPath, Module }]) => {
48+
const provider = has(Module, 'default') ? Module.default : Module;
3749
if (typeof provider !== 'function') {
38-
throw new TypeError(`“${path}” does not export default a function; got ${typeof provider}`);
50+
throw new TypeError(`“${filePath}” does not export default a function; got ${typeof provider}`);
3951
}
52+
const hierarchy = path.relative(actualRoot, stripExtension(actualPath));
4053
const descriptor = getDescriptor(provider, {
4154
Components,
4255
variations,
4356
getExtras,
4457
projectConfig,
4558
});
4659
callback(descriptor, {
47-
variationPath: path,
60+
variationProvider: {
61+
path: filePath,
62+
resolvedPath: actualPath,
63+
hierarchy,
64+
},
65+
get variationPath() {
66+
console.warn('this property is deprecated in favor of the `variationProvider` object’s `path` property');
67+
return filePath;
68+
},
4869
});
4970
});
5071
};

test/traversal/forEachDescriptor.js

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import interopRequireDefault from 'babel-runtime/helpers/interopRequireDefault';
12
import forEachDescriptor from '../../src/traversal/forEachDescriptor';
23

34
let mockComponents, mockVariations;
@@ -7,19 +8,16 @@ jest.mock('../../src/helpers/getVariationProviders', () => jest.fn(() => mockVar
78

89
describe('forEachDescriptor', () => {
910
beforeEach(() => {
10-
mockComponents = {
11-
'path/to/component': { actualPath: 'path/to/component.js', Module: {} },
12-
};
13-
mockVariations = {
14-
'path/to/VariationProvider': jest.fn(),
15-
};
1611
require('../../src/helpers/getComponents').mockClear();
1712
require('../../src/helpers/getVariationProviders').mockClear();
1813
mockComponents = {
1914
'path/to/component': { actualPath: 'path/to/component.js', Module: {} },
2015
};
2116
mockVariations = {
22-
'path/to/VariationProvider': jest.fn(),
17+
'path/to/VariationProvider': {
18+
Module: interopRequireDefault(jest.fn()),
19+
actualPath: '/full/path/to/VariationProvider.jsx',
20+
},
2321
};
2422
});
2523

@@ -56,7 +54,13 @@ describe('forEachDescriptor', () => {
5654
expect(getComponents).toHaveBeenCalledWith(mockProjectConfig, expect.any(String));
5755

5856
expect(getVariationProviders).toHaveBeenCalledTimes(1);
59-
expect(getVariationProviders).toHaveBeenCalledWith(mockProjectConfig, expect.any(String));
57+
expect(getVariationProviders).toHaveBeenCalledWith(
58+
mockProjectConfig,
59+
expect.any(String),
60+
expect.objectContaining({
61+
fileMapOnly: true,
62+
}),
63+
);
6064
});
6165

6266
describe('traversal function', () => {
@@ -106,11 +110,17 @@ describe('forEachDescriptor', () => {
106110
it('iterates variations', () => {
107111
const a = jest.fn();
108112
const b = jest.fn();
109-
const variationPathA = 'path/to/a';
110-
const variationPathB = 'path/to/b';
113+
const variationPathA = `${projectRoot}/path/to/a`;
114+
const variationPathB = `${projectRoot}/path/to/b`;
111115
mockVariations = {
112-
[variationPathA]: a,
113-
[variationPathB]: b,
116+
[variationPathA]: {
117+
Module: interopRequireDefault(a),
118+
actualPath: `${variationPathA}.extA`,
119+
},
120+
[variationPathB]: {
121+
Module: interopRequireDefault(b),
122+
actualPath: `${variationPathB}.extB`,
123+
},
114124
};
115125
const traverse = forEachDescriptor(mockProjectConfig, {
116126
getExtras,
@@ -147,12 +157,30 @@ describe('forEachDescriptor', () => {
147157

148158
expect(callback).toHaveBeenCalledTimes(2);
149159
const [first, second] = callback.mock.calls;
150-
expect(first).toEqual([descriptor, { variationPath: variationPathA }]);
151-
expect(second).toEqual([descriptor, { variationPath: variationPathB }]);
160+
expect(first).toEqual([descriptor, {
161+
variationProvider: {
162+
hierarchy: 'path/to/a',
163+
path: variationPathA,
164+
resolvedPath: mockVariations[variationPathA].actualPath
165+
},
166+
variationPath: variationPathA,
167+
}]);
168+
expect(second).toEqual([descriptor, {
169+
variationProvider: {
170+
hierarchy: 'path/to/b',
171+
path: variationPathB,
172+
resolvedPath: mockVariations[variationPathB].actualPath
173+
},
174+
variationPath: variationPathB,
175+
}]);
152176
});
153177

154178
it('throws when the provider is not a function', () => {
155-
mockVariations = { 'path/to/a': true };
179+
mockVariations = {
180+
'path/to/a': {
181+
Module: interopRequireDefault(true),
182+
},
183+
};
156184
const traverse = forEachDescriptor(mockProjectConfig, {
157185
getExtras,
158186
getDescriptor,
@@ -165,7 +193,12 @@ describe('forEachDescriptor', () => {
165193

166194
it('provides a default `getExtras`', () => {
167195
const a = jest.fn();
168-
mockVariations = { 'path/to/a': a };
196+
mockVariations = {
197+
'path/to/a': {
198+
Module: interopRequireDefault(a),
199+
actualPath: 'path/to/a.extension',
200+
},
201+
};
169202
const traverse = forEachDescriptor(mockProjectConfig, {
170203
getDescriptor,
171204
projectRoot,

test/traversal/forEachProjectVariation.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
import interopRequireDefault from 'babel-runtime/helpers/interopRequireDefault';
2+
global.interopRequireDefault = interopRequireDefault;
3+
14
import forEachProjectVariation from '../../src/traversal/forEachProjectVariation';
25

36
const mockProjectConfig = {
4-
components: 'glob/path/to/components',
5-
variations: 'glob/path/to/variations',
7+
componentsRoot: 'glob/',
8+
components: './path/to/components/**',
9+
variationsRoot: 'glob/',
10+
variations: './path/to/variations/**',
611
};
712

813
const mockProjectName = 'some awesome project';
@@ -16,7 +21,10 @@ jest.mock('../../src/helpers/getComponents', () => jest.fn(() => ({
1621
'path/to/component': { actualPath: 'path/to/component.js', Module: {} },
1722
})));
1823
jest.mock('../../src/helpers/getVariationProviders', () => jest.fn(() => ({
19-
'path/to/VariationProvider': jest.fn(() => mockDescriptor),
24+
'path/to/VariationProvider': {
25+
actualPath: 'path/to/RealVariationProvider.js',
26+
Module: global.interopRequireDefault(jest.fn(() => mockDescriptor)),
27+
},
2028
})));
2129

2230
const mockProjectNames = [mockProjectName, mockProjectName2];

0 commit comments

Comments
 (0)