Skip to content

Commit

Permalink
WIP remove proxyquire
Browse files Browse the repository at this point in the history
  • Loading branch information
Anand Thakker committed Mar 1, 2018
1 parent 90ace8e commit f2912dc
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 117 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@
"pngjs": "^3.0.0",
"prismjs": "^1.8.1",
"prop-types": "^15.6.0",
"proxyquire": "^1.7.9",
"raw-loader": "^0.5.1",
"react": "^16.0.0",
"react-dom": "^16.0.0",
Expand Down
11 changes: 9 additions & 2 deletions src/render/glyph_manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ class GlyphManager {
entries: {[string]: Entry};
url: ?string;

// exposed as statics to enable stubbing in unit tests
static loadGlyphRange: typeof loadGlyphRange;
static TinySDF: Class<TinySDF>;

constructor(requestTransform: RequestTransformFunction, localIdeographFontFamily: ?string) {
this.requestTransform = requestTransform;
this.localIdeographFontFamily = localIdeographFontFamily;
Expand Down Expand Up @@ -73,7 +77,7 @@ class GlyphManager {
let requests = entry.requests[range];
if (!requests) {
requests = entry.requests[range] = [];
loadGlyphRange(stack, range, (this.url: any), this.requestTransform,
GlyphManager.loadGlyphRange(stack, range, (this.url: any), this.requestTransform,
(err, response: ?{[number]: StyleGlyph | null}) => {
if (response) {
for (const id in response) {
Expand Down Expand Up @@ -134,7 +138,7 @@ class GlyphManager {
} else if (/light/i.test(stack)) {
fontWeight = '200';
}
tinySDF = entry.tinySDF = new TinySDF(24, 3, 8, .25, family, fontWeight);
tinySDF = entry.tinySDF = new GlyphManager.TinySDF(24, 3, 8, .25, family, fontWeight);
}

return {
Expand All @@ -151,4 +155,7 @@ class GlyphManager {
}
}

GlyphManager.loadGlyphRange = loadGlyphRange;
GlyphManager.TinySDF = TinySDF;

export default GlyphManager;
15 changes: 12 additions & 3 deletions src/style/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ class Style extends Evented {
placement: Placement;
z: number;

// exposed to allow stubbing by unit tests
static getSourceType: typeof getSourceType;
static setSourceType: typeof setSourceType;
static registerForPluginAvailability: typeof registerForPluginAvailability;

constructor(map: Map, options: StyleOptions = {}) {
super();

Expand All @@ -119,7 +124,7 @@ class Style extends Evented {
this._resetUpdates();

const self = this;
this._rtlTextPluginCallback = registerForPluginAvailability((args) => {
this._rtlTextPluginCallback = Style.registerForPluginAvailability((args) => {
self.dispatcher.broadcast('loadRTLTextPlugin', args.pluginURL, args.errorCallback);
for (const id in self.sourceCaches) {
self.sourceCaches[id].reload(); // Should be a no-op if the plugin loads before any tiles load
Expand Down Expand Up @@ -840,11 +845,11 @@ class Style extends Evented {
}

addSourceType(name: string, SourceType: Class<Source>, callback: Callback<void>) {
if (getSourceType(name)) {
if (Style.getSourceType(name)) {
return callback(new Error(`A source type called "${name}" already exists.`));
}

setSourceType(name, SourceType);
Style.setSourceType(name, SourceType);

if (!SourceType.workerSourceURL) {
return callback(null, null);
Expand Down Expand Up @@ -1005,4 +1010,8 @@ class Style extends Evented {
}
}

Style.getSourceType = getSourceType;
Style.setSourceType = setSourceType;
Style.registerForPluginAvailability = registerForPluginAvailability;

export default Style;
4 changes: 4 additions & 0 deletions src/util/web_worker_transfer.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ function serialize(input: mixed, transferables?: Array<Transferable>): Serialize
property :
serialize(property, transferables);
}

if (input instanceof Error) {
properties.message = input.message;
}
}

return {name, properties};
Expand Down
36 changes: 16 additions & 20 deletions test/unit/render/glyph_manager.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { test } from 'mapbox-gl-js-test';
import proxyquire from 'proxyquire';
import parseGlyphPBF from '../../../src/style/parse_glyph_pbf';
import GlyphManager from '../../../src/render/glyph_manager';
import fs from 'fs';

const glyphs = {};
Expand All @@ -10,15 +10,13 @@ for (const glyph of parseGlyphPBF(fs.readFileSync('./test/fixtures/0-255.pbf')))

test('GlyphManager requests 0-255 PBF', (t) => {
const identityTransform = (url) => ({url});
const GlyphManager = proxyquire('../../../src/render/glyph_manager', {
'../style/load_glyph_range': (stack, range, urlTemplate, transform, callback) => {
t.equal(stack, 'Arial Unicode MS');
t.equal(range, 0);
t.equal(urlTemplate, 'https://localhost/fonts/v1/{fontstack}/{range}.pbf');
t.equal(transform, identityTransform);
setImmediate(() => callback(null, glyphs));
}
}).default;
t.stub(GlyphManager, 'loadGlyphRange').callsFake((stack, range, urlTemplate, transform, callback) => {
t.equal(stack, 'Arial Unicode MS');
t.equal(range, 0);
t.equal(urlTemplate, 'https://localhost/fonts/v1/{fontstack}/{range}.pbf');
t.equal(transform, identityTransform);
setImmediate(() => callback(null, glyphs));
});

const manager = new GlyphManager(identityTransform);
manager.setURL('https://localhost/fonts/v1/{fontstack}/{range}.pbf');
Expand All @@ -31,11 +29,9 @@ test('GlyphManager requests 0-255 PBF', (t) => {
});

test('GlyphManager requests remote CJK PBF', (t) => {
const GlyphManager = proxyquire('../../../src/render/glyph_manager', {
'../style/load_glyph_range': (stack, range, urlTemplate, transform, callback) => {
setImmediate(() => callback(null, glyphs));
}
}).default;
t.stub(GlyphManager, 'loadGlyphRange').callsFake((stack, range, urlTemplate, transform, callback) => {
setImmediate(() => callback(null, glyphs));
});

const manager = new GlyphManager((url) => ({url}));
manager.setURL('https://localhost/fonts/v1/{fontstack}/{range}.pbf');
Expand All @@ -48,12 +44,12 @@ test('GlyphManager requests remote CJK PBF', (t) => {
});

test('GlyphManager generates CJK PBF locally', (t) => {
const GlyphManager = proxyquire('../../../src/render/glyph_manager', {
'@mapbox/tiny-sdf': class {
// Return empty 30x30 bitmap (24 fontsize + 3 * 2 buffer)
draw() { return new Uint8ClampedArray(900); }
t.stub(GlyphManager, 'TinySDF').value(class {
// Return empty 30x30 bitmap (24 fontsize + 3 * 2 buffer)
draw() {
return new Uint8ClampedArray(900);
}
}).default;
});

const manager = new GlyphManager((url) => ({url}), 'sans-serif');
manager.setURL('https://localhost/fonts/v1/{fontstack}/{range}.pbf');
Expand Down
42 changes: 29 additions & 13 deletions test/unit/style/load_glyph_range.test.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,41 @@
import { test } from 'mapbox-gl-js-test';
import proxyquire from 'proxyquire';
import fs from 'fs';
import path from 'path';
import window from '../../../src/util/window';
import loadGlyphRange from '../../../src/style/load_glyph_range';

test('loadGlyphRange', (t) => {
window.useFakeXMLHttpRequest();

t.tearDown(() => {
window.restore();
});

const transform = t.stub().callsFake((url) => ({url}));
const data = {};
const getArrayBuffer = t.stub().yields(null, {data});
const parseGlyphPBF = t.stub().returns([]);

const loadGlyphRange = proxyquire('../../../src/style/load_glyph_range', {
'../util/ajax': {getArrayBuffer},
'./parse_glyph_pbf': parseGlyphPBF
}).default;
let request;
window.XMLHttpRequest.onCreate = (req) => { request = req; };

loadGlyphRange('Arial Unicode MS', 0, 'https://localhost/fonts/v1/{fontstack}/{range}.pbf', transform, (err) => {
loadGlyphRange('Arial Unicode MS', 0, 'https://localhost/fonts/v1/{fontstack}/{range}.pbf', transform, (err, result) => {
t.ifError(err);
t.ok(transform.calledOnce);
t.deepEqual(transform.getCall(0).args, ['https://localhost/fonts/v1/Arial Unicode MS/0-255.pbf', 'Glyphs']);
t.ok(getArrayBuffer.calledOnce);
t.deepEqual(getArrayBuffer.getCall(0).args[0], {url: 'https://localhost/fonts/v1/Arial Unicode MS/0-255.pbf'});
t.ok(parseGlyphPBF.calledOnce);
t.deepEqual(parseGlyphPBF.getCall(0).args, [data]);

t.equal(Object.keys(result).length, 223);
for (const id in result) {
t.equal(result[id].id, Number(id));
t.ok(result[id].metrics);
t.equal(typeof result[id].metrics.width, 'number');
t.equal(typeof result[id].metrics.height, 'number');
t.equal(typeof result[id].metrics.top, 'number');
t.equal(typeof result[id].metrics.advance, 'number');
}
t.end();
});

t.equal(request.url, 'https://localhost/fonts/v1/Arial Unicode MS/0-255.pbf');
request.setStatus(200);
request.response = fs.readFileSync(path.join(__dirname, '../../fixtures/0-255.pbf'));
request.onload();

});
109 changes: 56 additions & 53 deletions test/unit/style/style.test.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { test } from 'mapbox-gl-js-test';
import proxyquire from 'proxyquire';
import Style from '../../../src/style/style';
import SourceCache from '../../../src/source/source_cache';
import StyleLayer from '../../../src/style/style_layer';
import Transform from '../../../src/geo/transform';
import { extend } from '../../../src/util/util';
import { Event, Evented } from '../../../src/util/evented';
import window from '../../../src/util/window';
import rtlTextPlugin from '../../../src/source/rtl_text_plugin';
import { setRTLTextPlugin, clearRTLTextPlugin } from '../../../src/source/rtl_text_plugin';
import ajax from '../../../src/util/ajax';
import browser from '../../../src/util/browser';
import { OverscaledTileID } from '../../../src/source/tile_id';

function createStyleJSON(properties) {
return extend({
Expand Down Expand Up @@ -57,30 +57,29 @@ test('Style', (t) => {
});

t.test('registers plugin listener', (t) => {
rtlTextPlugin.clearRTLTextPlugin();
clearRTLTextPlugin();

t.spy(rtlTextPlugin, 'registerForPluginAvailability');
t.spy(Style, 'registerForPluginAvailability');

const style = new Style(new StubMap());
t.spy(style.dispatcher, 'broadcast');
t.ok(rtlTextPlugin.registerForPluginAvailability.calledOnce);
t.ok(Style.registerForPluginAvailability.calledOnce);

rtlTextPlugin.setRTLTextPlugin("some bogus url");
setRTLTextPlugin("some bogus url");
t.ok(style.dispatcher.broadcast.calledWith('loadRTLTextPlugin', "some bogus url"));
t.end();
});

t.test('loads plugin immediately if already registered', (t) => {
rtlTextPlugin.clearRTLTextPlugin();
t.stub(rtlTextPlugin, 'createBlobURL').returns("data:text/javascript;base64,abc");
clearRTLTextPlugin();
window.useFakeXMLHttpRequest();
window.server.respondWith('/plugin.js', "doesn't matter");
let firstError = true;
rtlTextPlugin.setRTLTextPlugin("/plugin.js", (error) => {
setRTLTextPlugin("/plugin.js", (error) => {
// Getting this error message shows the bogus URL was succesfully passed to the worker
// We'll get the error from all workers, only pay attention to the first one
if (firstError) {
t.deepEquals(error, new Error('RTL Text Plugin failed to import scripts from data:text/javascript;base64,abc'));
t.equals(error.message, 'RTL Text Plugin failed to import scripts from /plugin.js');
t.end();
firstError = false;
}
Expand Down Expand Up @@ -1618,48 +1617,41 @@ test('Style#setLayerZoomRange', (t) => {

test('Style#queryRenderedFeatures', (t) => {
let style; // eslint-disable-line prefer-const
const Style = proxyquire('../../../src/style/style', {
'../source/query_features': {
rendered: function(source, layers, queryGeom, params) {
if (source.id !== 'mapbox') {
return [];
}

const features = {
'land': [{
type: 'Feature',
layer: style._layers.land.serialize(),
geometry: {
type: 'Polygon'
}
}, {
type: 'Feature',
layer: style._layers.land.serialize(),
geometry: {
type: 'Point'
}
}],
'landref': [{
type: 'Feature',
layer: style._layers.landref.serialize(),
geometry: {
type: 'Line'
}
}]
};

if (params.layers) {
for (const l in features) {
if (params.layers.indexOf(l) < 0) {
delete features[l];
}
}
function queryMapboxSourceFeatures(layers, queryGeom, scale, params, bearing, id, collisionIndex) {
const features = {
'land': [{
type: 'Feature',
layer: style._layers.land.serialize(),
geometry: {
type: 'Polygon'
}
}, {
type: 'Feature',
layer: style._layers.land.serialize(),
geometry: {
type: 'Point'
}
}],
'landref': [{
type: 'Feature',
layer: style._layers.landref.serialize(),
geometry: {
type: 'Line'
}
}]
};

return features;
if (params.layers) {
for (const l in features) {
if (params.layers.indexOf(l) < 0) {
delete features[l];
}
}
}
}).default;

return features;
}

style = new Style(new StubMap());
style.loadJSON({
Expand Down Expand Up @@ -1712,6 +1704,18 @@ test('Style#queryRenderedFeatures', (t) => {
});

style.on('style.load', () => {
style.sourceCaches.mapbox.tilesIn = () => {
return [{
tile: { queryRenderedFeatures: queryMapboxSourceFeatures },
tileID: new OverscaledTileID(0, 0, 0, 0, 0),
queryGeometry: [],
scale: 1
}];
};
style.sourceCaches.other.tilesIn = () => {
return [];
};

style.update(0, 0);

t.test('returns feature type', (t) => {
Expand Down Expand Up @@ -1876,12 +1880,11 @@ test('Style#query*Features', (t) => {

test('Style#addSourceType', (t) => {
const _types = { 'existing': function () {} };
const Style = proxyquire('../../../src/style/style', {
'../source/source': {
getType: function (name) { return _types[name]; },
setType: function (name, create) { _types[name] = create; }
}
}).default;

t.stub(Style, 'getSourceType').callsFake(name => _types[name]);
t.stub(Style, 'setSourceType').callsFake((name, create) => {
_types[name] = create;
});

t.test('adds factory function', (t) => {
const style = new Style(new StubMap());
Expand Down
Loading

0 comments on commit f2912dc

Please sign in to comment.