UNPKG

5.71 kBJavaScriptView Raw
1var util = require("util");
2var BaseClient = require("./client");
3var extend = require("./extend");
4
5function ApiBaseClient(settings) {
6 this.server = {
7 host: "api.browserstack.com"
8 };
9 BaseClient.call(this, settings);
10}
11
12util.inherits(ApiBaseClient, BaseClient);
13
14// public API
15extend(ApiBaseClient.prototype, {
16 getBrowsers: function(fn) {
17 this._getBrowsers(function(error, browsers) {
18 if (!error) {
19 this.updateLatest(browsers);
20 }
21
22 fn(error, browsers);
23 }.bind(this));
24 },
25
26 createWorker: function(options, fn) {
27 if (options[this.versionField] === "latest") {
28 return this.getLatest(options, function(error, version) {
29 if (error) {
30 return fn(error);
31 }
32
33 options = extend({}, options);
34 options[this.versionField] = version;
35 this.createWorker(options, fn);
36 }.bind(this));
37 }
38
39 var data = JSON.stringify(options);
40 this.request({
41 path: this.path("/worker"),
42 method: "POST"
43 }, data, fn);
44 },
45
46 getWorker: function(id, fn) {
47 this.request({
48 path: this.path("/worker/" + id)
49 }, fn);
50 },
51
52 changeUrl: function(id, options, fn) {
53 var data = JSON.stringify(options);
54 this.request({
55 path: this.path("/worker/" + id + "/url.json"),
56 method: "PUT"
57 }, data, fn);
58 },
59
60 terminateWorker: function(id, fn) {
61 this.request({
62 path: this.path("/worker/" + id),
63 method: "DELETE"
64 }, fn);
65 },
66
67 getWorkers: function(fn) {
68 this.request({
69 path: this.path("/workers")
70 }, fn);
71 },
72
73 getLatest: function(browser, fn) {
74 var latest = this.latest;
75
76 if (typeof browser === "function") {
77 fn = browser;
78 browser = null;
79 }
80
81 // there may be a lot of createWorker() calls with "latest" version
82 // so minimize the number of calls to getBrowsers()
83 if (this.latestPending) {
84 return setTimeout(function() {
85 this.getLatest(browser, fn);
86 }.bind(this), 50);
87 }
88
89 // only cache browsers for one day
90 if (!latest || this.latestUpdate < (new Date() - 864e5)) {
91 this.latestPending = true;
92 return this.getBrowsers(function(error) {
93 this.latestPending = false;
94
95 if (error) {
96 return fn(error);
97 }
98
99 this.getLatest(browser, fn);
100 }.bind(this));
101 }
102
103 process.nextTick(function() {
104 fn(null, browser ? latest[this.getBrowserId(browser)] : extend({}, latest));
105 }.bind(this));
106 },
107
108 takeScreenshot: function(id, fn) {
109 this.request({
110 path: this.path("/worker/" + id + "/screenshot.json")
111 }, fn);
112 }
113});
114
115// internal API
116extend(ApiBaseClient.prototype, {
117 latest: null,
118 latestUpdate: 0,
119 latestPending: false,
120
121 path: function(path) {
122 return "/" + this.version + path;
123 },
124
125 updateLatest: function(browsers) {
126 var latest = this.latest = {};
127 var getBrowserId = this.getBrowserId.bind(this);
128 var versionField = this.versionField;
129
130 this.latestUpdate = new Date();
131 browsers.forEach(function(browser) {
132 var version = browser[versionField];
133 var browserId = getBrowserId(browser);
134
135 // ignore devices that don't have versions
136 if (!version) {
137 return;
138 }
139
140 // ignore pre-release versions
141 if (/\s/.test(version)) {
142 return;
143 }
144
145 if (parseFloat(version) > (parseFloat(latest[browserId]) || 0)) {
146 latest[browserId] = version;
147 }
148 });
149 },
150
151 getBrowserId: function(browser) {
152 return this._getBrowserId(browser).toLowerCase();
153 }
154});
155
156// Versions
157
158ApiBaseClient.versions = {};
159ApiBaseClient.latestVersion = 0;
160ApiBaseClient.createVersion = function(version, prototype) {
161 function ApiClient(settings) {
162 ApiBaseClient.call(this, settings);
163 }
164
165 util.inherits(ApiClient, ApiBaseClient);
166
167 ApiClient.prototype.version = version;
168 extend(ApiClient.prototype, prototype);
169
170 ApiBaseClient.versions[version] = ApiClient;
171 ApiBaseClient.latestVersion = Math.max(ApiBaseClient.latestVersion, version);
172};
173
174ApiBaseClient.createVersion(1, {
175 useHttp: true,
176
177 versionField: "version",
178
179 _getBrowsers: function(fn) {
180 this.request({
181 path: this.path("/browsers")
182 }, fn);
183 },
184
185 _getBrowserId: function(browser) {
186 return browser.browser;
187 }
188});
189
190ApiBaseClient.createVersion(2, {
191 useHttp: true,
192
193 versionField: "version",
194
195 _getBrowsers: function(fn) {
196 this.request({
197 path: this.path("/browsers")
198 }, function(error, osBrowsers) {
199 if (error) {
200 return fn(error);
201 }
202
203 fn(null, [].concat.apply([],
204 Object.keys(osBrowsers).map(function(os) {
205 return osBrowsers[os].map(function(browser) {
206 browser.os = os;
207 return browser;
208 });
209 })
210 ));
211 });
212 },
213
214 _getBrowserId: function(browser) {
215 return browser.os + ":" + (browser.browser || browser.device);
216 }
217});
218
219ApiBaseClient.createVersion(3, {
220 useHttp: true,
221
222 versionField: "browser_version",
223
224 _getBrowsers: function(fn) {
225 this.request({
226 path: this.path("/browsers?flat=true")
227 }, fn);
228 },
229
230 _getBrowserId: function(browser) {
231 var id = browser.os + ":" + browser.os_version + ":" + browser.browser;
232 if (browser.device) {
233 id += ":" + browser.device;
234 }
235
236 return id;
237 },
238
239 getApiStatus: function(fn) {
240 this.request({
241 path: this.path("/status")
242 }, fn);
243 }
244});
245
246ApiBaseClient.createVersion(4, {
247 versionField: "browser_version",
248
249 _getBrowsers: function(fn) {
250 this.request({
251 path: this.path("/browsers?flat=true")
252 }, fn);
253 },
254
255 _getBrowserId: function(browser) {
256 var id = browser.os + ":" + browser.os_version + ":" + browser.browser;
257 if (browser.device) {
258 id += ":" + browser.device;
259 }
260
261 return id;
262 },
263
264 getApiStatus: function(fn) {
265 this.request({
266 path: this.path("/status")
267 }, fn);
268 }
269});
270
271module.exports = {
272 createClient: function(settings) {
273 var ApiClient = ApiBaseClient.versions[settings.version || ApiBaseClient.latestVersion];
274 if (!ApiClient) {
275 throw new Error("Invalid version");
276 }
277
278 return new ApiClient(settings);
279 }
280};