From 9b34a89d882909538e26ef96c2efd819f9b2320a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C5=91=20Tisza?= Date: Mon, 23 Oct 2017 17:41:28 -0700 Subject: [PATCH 1/5] Reading lists: add tests Bug: T184545 --- test/features/lists.js | 1182 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1182 insertions(+) create mode 100644 test/features/lists.js diff --git a/test/features/lists.js b/test/features/lists.js new file mode 100644 index 000000000..98449529b --- /dev/null +++ b/test/features/lists.js @@ -0,0 +1,1182 @@ +'use strict'; + +const nock = require('nock'); +const assert = require('../utils/assert.js'); +const server = require('../utils/server.js'); +const querystring = require('querystring'); +const preq = require('preq'); + + +describe('reading lists', function() { + const csrfToken = ''; + const sessionCookies = ''; + const config = { + domain: 'dev.wiki.local.wmftest.net', + baseURL: 'http://localhost:7231/dev.wiki.local.wmftest.net/v1', + apiDomain: 'http://localhost:10123', + apiPath: '/w/api.php', + }; + + function getApi() { + return nock(config.apiDomain, { + reqheaders: { + 'Cookie': sessionCookies, + 'Host': config.domain, + }, + }) + .defaultReplyHeaders({ + 'Content-Type': 'application/json; charset=utf-8', + }); + } + + // workaround for https://github.com/node-nock/nock/issues/852 + // also for object ordering issues + function nockDiff(expected) { + return (actual) => { + if (typeof actual === 'string' && typeof expected === 'object') { + actual = querystring.parse(actual); + } + try { + assert.deepEqual(actual, expected, 'nock failure'); + return true; + } catch (e) { + console.log(e); + return false; + } + } + } + + this.timeout(20000); + + before(function() { + //nock.recorder.rec(); + return server.start() + // Do a preparation request to force siteinfo fetch so that we don't need to mock it + .then(() => preq.get({ + uri: `${config.baseURL}/page/html/Main_Page`, + })) + // After this, there should be no unmocked requests other than those to /lists + .then(() => nock.emitter.on('no match', req => { + if (!req.href.startsWith(`${config.baseURL}/data/lists/`)) { + throw Error(`Unmocked request to ${req.href}`); + } + })); + }); + + afterEach(function() { + nock.cleanAll(); + }); + + describe('POST /lists/setup', function() { + it('forward call', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'readinglists', + command: 'setup', + token: csrfToken, + format: 'json', + formatversion: '2', + })) + .reply(200, {}); + + return preq.post({ + uri: `${config.baseURL}/data/lists/setup`, + query: { + csrf_token: csrfToken, + }, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => scope.done()) + .then(res => { + assert.deepEqual(res.status, 200); + }); + }); + + it('error handling', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'readinglists', + command: 'setup', + token: csrfToken, + format: 'json', + formatversion: '2', + })) + .reply(200, { + error: { + code: 'badtoken', + info: 'Invalid CSRF token.', + }, + }, { + 'MediaWiki-API-Error': 'badtoken', + }); + + return preq.post({ + uri: `${config.baseURL}/data/lists/setup`, + query: { + csrf_token: csrfToken, + }, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => scope.done()) + .tap(() => { + throw new Error('should not have succeeded'); + }) + .catch({ name: 'HTTPError' }, res => { + assert.deepEqual(res.status, 400); + assert.deepEqual(res.body.title, 'badtoken'); + assert.deepEqual(res.body.detail, 'Invalid CSRF token.'); + }); + }); + }); + + describe('POST /lists/teardown', function() { + it('forward call', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'readinglists', + command: 'teardown', + token: csrfToken, + format: 'json', + formatversion: '2', + })) + .reply(200, {}); + + return preq.post({ + uri: `${config.baseURL}/data/lists/teardown`, + query: { + csrf_token: csrfToken, + }, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => scope.done()) + .then(function (res) { + assert.deepEqual(res.status, 200); + }); + }); + }); + + describe('GET /lists/', function() { + const listEntry = { + id: 1, + name: 'default', + default: true, + description: '', + color: '', + image: '', + icon: '', + created: '2017-09-27T06:59:13Z', + updated: '2017-10-17T07:40:50Z', + order: [ 1, 2, 3 ], + listOrder: [ 1, 2 ], + }; + + it('forward call', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'query', + meta: 'readinglists', + rllimit: 'max', + format: 'json', + formatversion: '2', + })) + .reply(200, { + query: { + readinglists: [ listEntry ], + }, + }); + + return preq.get({ + uri: `${config.baseURL}/data/lists/`, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => scope.done()) + .then(function (res) { + assert.deepEqual(res.status, 200); + assert.deepEqual(res.body, { + lists: [ listEntry ], + }); + }); + }); + + it('paging', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'query', + meta: 'readinglists', + rllimit: 'max', + format: 'json', + formatversion: '2', + })) + .reply(200, { + query: { + readinglists: [ listEntry ], + }, + continue: { + rlcontinue: 1, + continue: '-||', + }, + }); + + return preq.get({ + uri: `${config.baseURL}/data/lists/`, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => scope.done()) + .then(function (res) { + assert.deepEqual(res.status, 200); + assert.deepEqual(res.body, { + lists: [ listEntry ], + next: '{"rlcontinue":1,"continue":"-||"}', + }); + }); + }); + + it('paging 2', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'query', + meta: 'readinglists', + rllimit: 'max', + rlcontinue: 1, + continue: '-||', + format: 'json', + formatversion: '2', + })) + .reply(200, { + query: { + readinglists: [ listEntry ], + }, + }); + + return preq.get({ + uri: `${config.baseURL}/data/lists/`, + query: { + next: '{"rlcontinue":1,"continue":"-||"}', + }, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => scope.done()) + .then(function (res) { + assert.deepEqual(res.status, 200); + assert.deepEqual(res.body, { + lists: [ listEntry ], + }); + }); + }); + + it('paging error', function() { + const scope = getApi(); + + return preq.get({ + uri: `${config.baseURL}/data/lists/`, + query: { + next: '{invalid}', + }, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => scope.done()) + .tap(() => { + throw new Error('should not have succeeded'); + }) + .catch({ name: 'HTTPError' }, res => { + assert.deepEqual(res.status, 400); + assert.deepEqual(res.body.type, + 'https://mediawiki.org/wiki/HyperSwitch/errors/server_error#invalid_paging_parameter'); + }); + }); + }); + + describe('POST /lists/', function() { + it('forward call', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'readinglists', + command: 'create', + name: 'Test list', + description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', + color: 'red', + image: 'Foo.png', + icon: 'foo', + token: csrfToken, + format: 'json', + formatversion: '2', + })) + .reply(200, { + create: { + id: 2, + }, + }); + + return preq.post({ + uri: `${config.baseURL}/data/lists/`, + query: { + csrf_token: csrfToken, + }, + body: { + name: 'Test list', + description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', + color: 'red', + image: 'Foo.png', + icon: 'foo', + }, + headers: { + 'Cookie': sessionCookies, + 'content-type': 'application/json', + }, + }) + .finally(() => scope.done()) + .then(function (res) { + assert.deepEqual(res.status, 200); + assert.deepEqual(res.body.id, 2); + }); + }); + }); + + describe('PUT /lists/{id}', function() { + it('forward call', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'readinglists', + command: 'update', + list: 2, + name: 'Test list!', + description: 'Lorem ipsum dolor sit amet, integre fabellas partiendo has ei.', + color: 'blue', + image: 'Bar.png', + icon: 'bar', + token: csrfToken, + format: 'json', + formatversion: '2', + })) + .reply(200, {}); + + return preq.put({ + uri: `${config.baseURL}/data/lists/2`, + query: { + csrf_token: csrfToken, + }, + body: { + name: 'Test list!', + description: 'Lorem ipsum dolor sit amet, integre fabellas partiendo has ei.', + color: 'blue', + image: 'Bar.png', + icon: 'bar', + }, + headers: { + 'Cookie': sessionCookies, + 'content-type': 'application/json', + }, + }) + .finally(() => scope.done()) + .then(function (res) { + assert.deepEqual(res.status, 200); + }); + }); + }); + + describe('DELETE /lists/{id}', function() { + it('forward call', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'readinglists', + command: 'delete', + list: 2, + token: csrfToken, + format: 'json', + formatversion: '2', + })) + .reply(200, {}); + + return preq.delete({ + uri: `${config.baseURL}/data/lists/2`, + query: { + csrf_token: csrfToken, + }, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => scope.done()) + .then(function (res) { + assert.deepEqual(res.status, 200); + }); + }); + }); + + describe('GET /lists/{id}/entries/', function() { + const entries = [ + { + id: 10, + listId: 4, + project: 'en.wikipedia.org', + title: 'Foo Bar', + created: '2017-09-27T06:59:13Z', + updated: '2017-10-17T07:40:50Z', + }, + { + id: 11, + listId: 4, + project: 'en.wikipedia.org', + title: 'Boo(m)?', + created: '2017-09-27T06:59:13Z', + updated: '2017-10-17T07:40:50Z', + }, + ]; + const expectedEntries = [ + { + id: 10, + listId: 4, + project: 'en.wikipedia.org', + title: 'Foo Bar', + summary: { + title: 'Foo_Bar', + normalizedtitle: 'Foo Bar', + summaryData: '', + }, + created: '2017-09-27T06:59:13Z', + updated: '2017-10-17T07:40:50Z', + }, + { + id: 11, + listId: 4, + project: 'en.wikipedia.org', + title: 'Boo(m)?', + summary: { + title: 'Boo(m)?', + normalizedtitle: 'Boo(m)?', + summaryData: '', + }, + created: '2017-09-27T06:59:13Z', + updated: '2017-10-17T07:40:50Z', + }, + ]; + function getEnwikiMock() { + return nock('https://en.wikipedia.org', { + // FIXME should not send cookies to a different domain + // badheaders: [ 'Cookie' ], + }) + .defaultReplyHeaders({ + 'Content-Type': 'application/json; charset=utf-8', + }) + .post(config.apiPath, query => { + const params = (typeof query === 'string') ? querystring.parse(query) : query; + return params.action === 'query' && params.meta === 'siteinfo|filerepoinfo' + && !params.list && !params.prop; + }) + .optionally() + // The siteinfo response is huge and /lists only uses it to verify the domain. + // Only mock enough of it to make ActionService.siteinfo not fail. + .reply(200, { + query: { + general: { + lang: 'en', + legaltitlechars: ' %!"$&\'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF+', + case: 'first-letter', + }, + namespaces: { + '0': { + id: 0, + case: 'first-letter', + content: '', + '*': '' + }, + }, + namespacealiases: [], + specialpagealiases: [], + repos: [ + { + name: 'shared', + descBaseUrl: 'https://commons.wikimedia.org/wiki/File:', + }, + ], + }, + }); + } + + it('forward call', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'query', + list: 'readinglistentries', + rlelists: 4, + rlelimit: 'max', + format: 'json', + formatversion: '2', + })) + .reply(200, { + query: { + readinglistentries: entries, + }, + }); + const scope2 = getEnwikiMock() + .get('/api/rest_v1/page/summary/Foo_Bar') + .reply(200, { title: 'Foo Bar', summaryData: '' }) + .get('/api/rest_v1/page/summary/Boo(m)%3F') + .reply(200, { title: 'Boo(m)?', summaryData: '' }); + + return preq.get({ + uri: `${config.baseURL}/data/lists/4/entries/`, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => { + scope.done(); + scope2.done(); + }) + .then(function (res) { + assert.deepEqual(res.status, 200); + assert.deepEqual(res.body, { + entries: expectedEntries, + }); + }); + }); + + it('paging', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'query', + list: 'readinglistentries', + rlelists: 4, + rlelimit: 'max', + format: 'json', + formatversion: '2', + })) + .reply(200, { + query: { + readinglistentries: entries.slice(0, 1), + }, + continue: { + rlecontinue: 1, + continue: '-||', + }, + }); + const scope2 = getEnwikiMock() + .get('/api/rest_v1/page/summary/Foo_Bar') + .reply(200, { title: 'Foo Bar', summaryData: '' }); + + return preq.get({ + uri: `${config.baseURL}/data/lists/4/entries/`, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => { + scope.done(); + scope2.done(); + }) + .then(function (res) { + assert.deepEqual(res.status, 200); + assert.deepEqual(res.body, { + entries: expectedEntries.slice(0, 1), + next: '{"rlecontinue":1,"continue":"-||"}', + }); + }); + }); + + it('paging2', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'query', + list: 'readinglistentries', + rlelists: 4, + rlelimit: 'max', + rlecontinue: 1, + continue: '-||', + format: 'json', + formatversion: '2', + })) + .reply(200, { + query: { + readinglistentries: entries.slice(1), + }, + }); + const scope2 = getEnwikiMock() + .get('/api/rest_v1/page/summary/Boo(m)%3F') + .reply(200, { title: 'Boo(m)?', summaryData: '' }); + + return preq.get({ + uri: `${config.baseURL}/data/lists/4/entries/`, + query: { + next: '{"rlecontinue":1,"continue":"-||"}', + }, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => { + scope.done(); + scope2.done(); + }) + .then(function (res) { + assert.deepEqual(res.status, 200); + assert.deepEqual(res.body, { + entries: expectedEntries.slice(1), + }); + }); + }); + + it('no cookie forwarding to unknown domains', function() { + const entries = [ + { + id: 1, + listId: 1, + project: 'de.wikipedia.org', + title: 'Barack Obama', + created: '2017-09-27T06:59:13Z', + updated: '2017-10-17T07:40:50Z', + }, + ]; + + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'query', + list: 'readinglistentries', + rlelists: 1, + rlelimit: 'max', + format: 'json', + formatversion: '2', + })) + .reply(200, { + query: { + readinglistentries: entries, + }, + }); + + return preq.get({ + uri: `${config.baseURL}/data/lists/1/entries/`, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => { + scope.done(); + }) + .then(function (res) { + assert.deepEqual(res.status, 200); + }); + }); + }); + + describe('POST /lists/{id}/entries/', function() { + it('forward call', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'readinglists', + command: 'createentry', + list: '3', + project: 'en.wikipedia.org', + title: 'Barack Obama', + token: csrfToken, + format: 'json', + formatversion: '2', + })) + .reply(200, { + createentry: { + id: 1, + }, + }); + + return preq.post({ + uri: `${config.baseURL}/data/lists/3/entries/`, + query: { + csrf_token: csrfToken, + }, + body: { + project: 'en.wikipedia.org', + title: 'Barack Obama', + }, + headers: { + 'Cookie': sessionCookies, + 'content-type': 'application/json', + }, + }) + .finally(() => scope.done()) + .then(function (res) { + assert.deepEqual(res.status, 200); + assert.deepEqual(res.body.id, 1); + }); + }); + + }); + + describe('DELETE /lists/{id}/entries/{entry_id}', function() { + it('forward call', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'readinglists', + command: 'deleteentry', + entry: 1, + token: csrfToken, + format: 'json', + formatversion: '2', + })) + .reply(200, {}); + + return preq.delete({ + uri: `${config.baseURL}/data/lists/3/entries/1`, + query: { + csrf_token: csrfToken, + }, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => scope.done()) + .then(function (res) { + assert.deepEqual(res.status, 200); + }); + }); + }); + + describe('GET /lists/order', function() { + it('forward call', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'query', + meta: 'readinglistorder', + rlolistorder: 1, + format: 'json', + formatversion: '2', + })) + .reply(200, { + query: { + readinglistorder: [ + { + type: 'lists', + order: [ 1, 2, 3 ], + }, + ], + }, + }); + + return preq.get({ + uri: `${config.baseURL}/data/lists/order`, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => scope.done()) + .then(function (res) { + assert.deepEqual(res.status, 200); + assert.deepEqual(res.body, { order: [ 1, 2, 3 ] }); + }); + }); + }); + + describe('PUT /lists/order', function() { + it('forward call', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'readinglists', + command: 'order', + order: '1|2|3', + token: csrfToken, + format: 'json', + formatversion: '2', + })) + .reply(200, {}); + + return preq.put({ + uri: `${config.baseURL}/data/lists/order`, + query: { + csrf_token: csrfToken, + }, + body: [ 1, 2, 3 ], + headers: { + 'Cookie': sessionCookies, + 'content-type': 'application/json', + }, + }) + .finally(() => scope.done()) + .then(function (res) { + assert.deepEqual(res.status, 200); + }); + }); + }); + + describe('GET /lists/{id}/order', function() { + it('forward call', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'query', + meta: 'readinglistorder', + rlolists: 1, + format: 'json', + formatversion: '2', + })) + .reply(200, { + query: { + readinglistorder: [ + { + type: 'entries', + list: 1, + order: [ 1, 2, 3 ], + }, + ], + }, + }); + + return preq.get({ + uri: `${config.baseURL}/data/lists/1/order`, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => scope.done()) + .then(function (res) { + assert.deepEqual(res.status, 200); + assert.deepEqual(res.body, { order: [ 1, 2, 3 ] }); + }); + }); + }); + + describe('PUT /lists/{id}/order', function() { + it('forward call', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'readinglists', + command: 'orderentry', + list: 1, + order: '1|2|3', + token: csrfToken, + format: 'json', + formatversion: '2', + })) + .reply(200, {}); + + return preq.put({ + uri: `${config.baseURL}/data/lists/1/order`, + query: { + csrf_token: csrfToken, + }, + body: [ 1, 2, 3 ], + headers: { + 'Cookie': sessionCookies, + 'content-type': 'application/json', + }, + }) + .finally(() => scope.done()) + .then(function (res) { + assert.deepEqual(res.status, 200); + }); + }); + }); + + describe('GET /lists/pages/{project}/{title}', function() { + const lists = [ + { + id: 1, + name: 'default', + default: true, + description: '', + color: '', + image: '', + icon: '', + created: '2017-09-27T06:59:13Z', + updated: '2017-10-17T07:40:50Z', + order: [ 1, 2, 3 ], + listOrder: [ 1, 2 ], + }, + { + id: 2, + name: 'other', + description: '', + color: '', + image: '', + icon: '', + created: '2017-09-27T06:59:13Z', + updated: '2017-10-17T07:40:50Z', + order: [ 5, 4 ], + }, + ]; + + it('forward call', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'query', + meta: 'readinglists', + rlproject: 'en.wikipedia.org', + rltitle: 'Foo_Bar', + rllimit: 'max', + format: 'json', + formatversion: '2', + })) + .reply(200, { + query: { + readinglists: lists, + }, + }); + + return preq.get({ + uri: `${config.baseURL}/data/lists/pages/en.wikipedia.org/Foo%20Bar`, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => scope.done()) + .then(function (res) { + assert.deepEqual(res.status, 200); + assert.deepEqual(res.body, { + lists: lists, + }); + }); + }); + + it('paging', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'query', + meta: 'readinglists', + rlproject: 'en.wikipedia.org', + rltitle: 'Foo_Bar', + rllimit: 'max', + format: 'json', + formatversion: '2', + })) + .reply(200, { + query: { + readinglists: lists.slice(0, 1), + }, + continue: { + rlcontinue: 1, + continue: '-||', + }, + }); + + return preq.get({ + uri: `${config.baseURL}/data/lists/pages/en.wikipedia.org/Foo%20Bar`, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => scope.done()) + .then(function (res) { + assert.deepEqual(res.status, 200); + assert.deepEqual(res.body, { + lists: lists.slice(0, 1), + next: '{"rlcontinue":1,"continue":"-||"}', + }); + }); + }); + + it('paging 2', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'query', + meta: 'readinglists', + rlproject: 'en.wikipedia.org', + rltitle: 'Foo_Bar', + rllimit: 'max', + rlcontinue: 1, + continue: '-||', + format: 'json', + formatversion: '2', + })) + .reply(200, { + query: { + readinglists: lists.slice(1), + }, + }); + + return preq.get({ + uri: `${config.baseURL}/data/lists/pages/en.wikipedia.org/Foo%20Bar`, + query: { + next: '{"rlcontinue":1,"continue":"-||"}', + }, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => scope.done()) + .then(function (res) { + assert.deepEqual(res.status, 200); + assert.deepEqual(res.body, { + lists: lists.slice(1), + }); + }); + }); + }); + + describe('GET /lists/changes/since/{date}', function() { + const lists = [ + { + id: 1, + name: 'default', + default: true, + description: '', + color: '', + image: '', + icon: '', + created: '2017-09-27T06:59:13Z', + updated: '2017-10-17T07:40:50Z', + order: [ 1, 2 ], + listOrder: [ 1, 2 ], + }, + { + id: 2, + name: 'deleted', + description: '', + color: '', + image: '', + icon: '', + created: '2017-09-27T06:59:13Z', + updated: '2017-10-17T07:40:50Z', + deleted: true, + }, + ]; + const entries = [ + { + id: 1, + listId: 1, + project: 'en.wikipedia.org', + title: 'Foo Bar', + created: '2017-09-27T06:59:13Z', + updated: '2017-10-17T07:40:50Z', + }, + { + id: 2, + listId: 1, + project: 'en.wikipedia.org', + title: 'Boom Baz', + created: '2017-09-27T06:59:13Z', + updated: '2017-10-17T07:40:50Z', + deleted: true, + }, + ]; + + it('forward call', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'query', + meta: 'readinglists', + list: 'readinglistentries', + rlchangedsince: '2017-10-15T00:00:00Z', + rlechangedsince: '2017-10-15T00:00:00Z', + rllimit: 'max', + rlelimit: 'max', + format: 'json', + formatversion: '2', + })) + .reply(200, { + query: { + readinglists: lists, + readinglistentries: entries, + }, + }); + + return preq.get({ + uri: `${config.baseURL}/data/lists/changes/since/2017-10-15T00%3A00%3A00Z`, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => scope.done()) + .then(function (res) { + assert.deepEqual(res.status, 200); + assert.deepEqual(res.body, { + lists: lists, + entries: entries, + }); + }); + }); + + it('paging', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'query', + meta: 'readinglists', + list: 'readinglistentries', + rlchangedsince: '2017-10-15T00:00:00Z', + rlechangedsince: '2017-10-15T00:00:00Z', + rllimit: 'max', + rlelimit: 'max', + format: 'json', + formatversion: '2', + })) + .reply(200, { + query: { + readinglists: lists.slice(0, 1), + readinglistentries: entries.slice(0, 1), + }, + continue: { + rlcontinue: 1, + rlecontinue: 1, + continue: '-||', + }, + }); + + return preq.get({ + uri: `${config.baseURL}/data/lists/changes/since/2017-10-15T00%3A00%3A00Z`, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => scope.done()) + .then(function (res) { + assert.deepEqual(res.status, 200); + assert.deepEqual(res.body, { + lists: lists.slice(0, 1), + entries: entries.slice(0, 1), + next: '{"rlcontinue":1,"rlecontinue":1,"continue":"-||"}', + }); + }); + }); + + it('paging 2', function() { + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'query', + meta: 'readinglists', + list: 'readinglistentries', + rlchangedsince: '2017-10-15T00:00:00Z', + rlechangedsince: '2017-10-15T00:00:00Z', + rllimit: 'max', + rlelimit: 'max', + rlcontinue: 1, + rlecontinue: 1, + continue: '-||', + format: 'json', + formatversion: '2', + })) + .reply(200, { + query: { + readinglists: lists.slice(1), + readinglistentries: entries.slice(1), + }, + }); + + return preq.get({ + uri: `${config.baseURL}/data/lists/changes/since/2017-10-15T00%3A00%3A00Z`, + query: { + next: '{"rlcontinue":1,"rlecontinue":1,"continue":"-||"}', + }, + headers: { + 'Cookie': sessionCookies, + }, + }) + .finally(() => scope.done()) + .then(function (res) { + assert.deepEqual(res.status, 200); + assert.deepEqual(res.body, { + lists: lists.slice(1), + entries: entries.slice(1), + }); + }); + }); + }); +}); From b06f1d09b344e0edd1c97c7ab9ead6a417dac85a Mon Sep 17 00:00:00 2001 From: Mateus Santos Date: Thu, 30 Aug 2018 15:22:51 -0300 Subject: [PATCH 2/5] Updating tests cases for ReadingLists 1) Making all tests work and removing outdated order endpoints 2) Adding test cases for batches endpoints Bug: T184545 --- test/features/lists.js | 316 ++++++++++++++++++++++++++--------------- 1 file changed, 202 insertions(+), 114 deletions(-) diff --git a/test/features/lists.js b/test/features/lists.js index 98449529b..7ea6efc8a 100644 --- a/test/features/lists.js +++ b/test/features/lists.js @@ -11,10 +11,11 @@ describe('reading lists', function() { const csrfToken = ''; const sessionCookies = ''; const config = { - domain: 'dev.wiki.local.wmftest.net', - baseURL: 'http://localhost:7231/dev.wiki.local.wmftest.net/v1', - apiDomain: 'http://localhost:10123', - apiPath: '/w/api.php', + // domain: 'dev.wiki.local.wmftest.net', + // baseURL: 'http://localhost:7231/dev.wiki.local.wmftest.net/v1', + baseURL: server.config.baseURL, + apiDomain: server.config.apiURL.replace(/^(.*)(\/w\/.+)$/, "$1"), + apiPath: server.config.apiURL.replace(/^(.*)(\/w\/.+)$/, "$2"), }; function getApi() { @@ -182,6 +183,8 @@ describe('reading lists', function() { action: 'query', meta: 'readinglists', rllimit: 'max', + rlsort: 'updated', + rldir: 'descending', format: 'json', formatversion: '2', })) @@ -199,9 +202,12 @@ describe('reading lists', function() { }) .finally(() => scope.done()) .then(function (res) { + // override continue-from timestamp + res.body['continue-from'] = '' assert.deepEqual(res.status, 200); assert.deepEqual(res.body, { lists: [ listEntry ], + 'continue-from': '', }); }); }); @@ -212,6 +218,8 @@ describe('reading lists', function() { action: 'query', meta: 'readinglists', rllimit: 'max', + rlsort: 'updated', + rldir: 'descending', format: 'json', formatversion: '2', })) @@ -233,10 +241,13 @@ describe('reading lists', function() { }) .finally(() => scope.done()) .then(function (res) { + // override continue-from timestamp + res.body['continue-from'] = '' assert.deepEqual(res.status, 200); assert.deepEqual(res.body, { lists: [ listEntry ], next: '{"rlcontinue":1,"continue":"-||"}', + 'continue-from': '', }); }); }); @@ -246,6 +257,8 @@ describe('reading lists', function() { .post(config.apiPath, nockDiff({ action: 'query', meta: 'readinglists', + rlsort: 'updated', + rldir: 'descending', rllimit: 'max', rlcontinue: 1, continue: '-||', @@ -269,9 +282,12 @@ describe('reading lists', function() { }) .finally(() => scope.done()) .then(function (res) { + // override continue-from timestamp + res.body['continue-from'] = '' assert.deepEqual(res.status, 200); assert.deepEqual(res.body, { lists: [ listEntry ], + 'continue-from': '', }); }); }); @@ -308,9 +324,6 @@ describe('reading lists', function() { command: 'create', name: 'Test list', description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', - color: 'red', - image: 'Foo.png', - icon: 'foo', token: csrfToken, format: 'json', formatversion: '2', @@ -355,14 +368,20 @@ describe('reading lists', function() { list: 2, name: 'Test list!', description: 'Lorem ipsum dolor sit amet, integre fabellas partiendo has ei.', - color: 'blue', - image: 'Bar.png', - icon: 'bar', token: csrfToken, format: 'json', formatversion: '2', })) - .reply(200, {}); + .reply(200, { + update:{ + id: 1, + list: { + id: 2, + name: 'Test list!', + description: 'Lorem ipsum dolor sit amet, integre fabellas partiendo has ei.', + } + } + }); return preq.put({ uri: `${config.baseURL}/data/lists/2`, @@ -417,6 +436,95 @@ describe('reading lists', function() { }); }); + describe('POST /lists/batch', function() { + it('forward call', function() { + const batchLists = [ + { + name: 'Test batch list item 1', + description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit unus.' + }, + { + name: 'Test batch list item 2', + description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit duo.' + }, + ] + const scope = getApi() + .post(config.apiPath, nockDiff({ + action: 'readinglists', + command: 'create', + batch: JSON.stringify(batchLists), + token: csrfToken, + format: 'json', + formatversion: '2', + })) + .reply(200, { + create: { + ids: [7,8], + lists: [ + { + id: 1, + name: 'Test batch list item 1', + description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit unus.', + created: '2018-08-30T13:44:04.242Z', + updated: '2018-08-30T13:44:04.242Z', + }, + { + id: 2, + name: 'Test batch list item 2', + description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit duo.', + created: '2018-08-30T13:44:04.242Z', + updated: '2018-08-30T13:44:04.242Z', + }, + ], + }, + }); + + return preq.post({ + uri: `${config.baseURL}/data/lists/batch`, + query: { + csrf_token: csrfToken, + }, + body: { + batch: batchLists, + }, + headers: { + 'Cookie': sessionCookies, + 'content-type': 'application/json', + }, + }) + .finally(() => scope.done()) + .then(function (res) { + assert.deepEqual(res.status, 200); + assert.deepEqual(res.body, { + batch: [ + { + 'id': 7 + }, + { + 'id': 8 + } + ], + lists: [ + { + id: 1, + name: 'Test batch list item 1', + description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit unus.', + created: '2018-08-30T13:44:04.242Z', + updated: '2018-08-30T13:44:04.242Z' + }, + { + id: 2, + name: 'Test batch list item 2', + description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit duo.', + created: '2018-08-30T13:44:04.242Z', + updated: '2018-08-30T13:44:04.242Z' + }, + ], + }); + }); + }); + }); + describe('GET /lists/{id}/entries/', function() { const entries = [ { @@ -513,6 +621,8 @@ describe('reading lists', function() { action: 'query', list: 'readinglistentries', rlelists: 4, + rlesort: 'updated', + rledir: 'descending', rlelimit: 'max', format: 'json', formatversion: '2', @@ -552,6 +662,8 @@ describe('reading lists', function() { action: 'query', list: 'readinglistentries', rlelists: 4, + rlesort: 'updated', + rledir: 'descending', rlelimit: 'max', format: 'json', formatversion: '2', @@ -594,6 +706,8 @@ describe('reading lists', function() { action: 'query', list: 'readinglistentries', rlelists: 4, + rlesort: 'updated', + rledir: 'descending', rlelimit: 'max', rlecontinue: 1, continue: '-||', @@ -647,6 +761,8 @@ describe('reading lists', function() { action: 'query', list: 'readinglistentries', rlelists: 1, + rlesort: 'updated', + rledir: 'descending', rlelimit: 'max', format: 'json', formatversion: '2', @@ -743,128 +859,58 @@ describe('reading lists', function() { }); }); - describe('GET /lists/order', function() { + describe('POST /lists/{id}/entries/batch', function() { it('forward call', function() { - const scope = getApi() - .post(config.apiPath, nockDiff({ - action: 'query', - meta: 'readinglistorder', - rlolistorder: 1, - format: 'json', - formatversion: '2', - })) - .reply(200, { - query: { - readinglistorder: [ - { - type: 'lists', - order: [ 1, 2, 3 ], - }, - ], + const batchEntries = [ + { + project: 'en.wikipedia.org', + title: 'Foobar', }, - }); - - return preq.get({ - uri: `${config.baseURL}/data/lists/order`, - headers: { - 'Cookie': sessionCookies, - }, - }) - .finally(() => scope.done()) - .then(function (res) { - assert.deepEqual(res.status, 200); - assert.deepEqual(res.body, { order: [ 1, 2, 3 ] }); - }); - }); - }); - - describe('PUT /lists/order', function() { - it('forward call', function() { + { + project: 'en.wikipedia.org', + title: 'Dog', + }, + ] const scope = getApi() .post(config.apiPath, nockDiff({ action: 'readinglists', - command: 'order', - order: '1|2|3', + command: 'createentry', + list: '3', + batch: JSON.stringify(batchEntries), token: csrfToken, format: 'json', formatversion: '2', })) - .reply(200, {}); - - return preq.put({ - uri: `${config.baseURL}/data/lists/order`, - query: { - csrf_token: csrfToken, - }, - body: [ 1, 2, 3 ], - headers: { - 'Cookie': sessionCookies, - 'content-type': 'application/json', - }, - }) - .finally(() => scope.done()) - .then(function (res) { - assert.deepEqual(res.status, 200); - }); - }); - }); - - describe('GET /lists/{id}/order', function() { - it('forward call', function() { - const scope = getApi() - .post(config.apiPath, nockDiff({ - action: 'query', - meta: 'readinglistorder', - rlolists: 1, - format: 'json', - formatversion: '2', - })) .reply(200, { - query: { - readinglistorder: [ + createentry: { + ids: [2,3], + entries: [ { - type: 'entries', - list: 1, - order: [ 1, 2, 3 ], + id: 2, + project: 'en.wikipedia.org', + title: 'Foobar', + created: '2018-08-30T13:44:04.276Z', + updated: '2018-08-30T13:44:04.276Z' + }, + { + id: 3, + project: 'en.wikipedia.org', + title: 'Dog', + created: '2018-08-30T13:44:04.276Z', + updated: '2018-08-30T13:44:04.276Z' }, ], }, }); - return preq.get({ - uri: `${config.baseURL}/data/lists/1/order`, - headers: { - 'Cookie': sessionCookies, - }, - }) - .finally(() => scope.done()) - .then(function (res) { - assert.deepEqual(res.status, 200); - assert.deepEqual(res.body, { order: [ 1, 2, 3 ] }); - }); - }); - }); - - describe('PUT /lists/{id}/order', function() { - it('forward call', function() { - const scope = getApi() - .post(config.apiPath, nockDiff({ - action: 'readinglists', - command: 'orderentry', - list: 1, - order: '1|2|3', - token: csrfToken, - format: 'json', - formatversion: '2', - })) - .reply(200, {}); - - return preq.put({ - uri: `${config.baseURL}/data/lists/1/order`, + return preq.post({ + uri: `${config.baseURL}/data/lists/3/entries/batch`, query: { csrf_token: csrfToken, }, - body: [ 1, 2, 3 ], + body: { + batch: batchEntries, + }, headers: { 'Cookie': sessionCookies, 'content-type': 'application/json', @@ -873,6 +919,32 @@ describe('reading lists', function() { .finally(() => scope.done()) .then(function (res) { assert.deepEqual(res.status, 200); + assert.deepEqual(res.body, { + batch: [ + { + id: 2, + }, + { + id: 3 + }, + ], + entries: [ + { + id: 2, + project: 'en.wikipedia.org', + title: 'Foobar', + created: '2018-08-30T13:44:04.276Z', + updated: '2018-08-30T13:44:04.276Z' + }, + { + id: 3, + project: 'en.wikipedia.org', + title: 'Dog', + created: '2018-08-30T13:44:04.276Z', + updated: '2018-08-30T13:44:04.276Z' + }, + ], + }); }); }); }); @@ -1067,6 +1139,10 @@ describe('reading lists', function() { list: 'readinglistentries', rlchangedsince: '2017-10-15T00:00:00Z', rlechangedsince: '2017-10-15T00:00:00Z', + rlsort: 'updated', + rlesort: 'updated', + rldir: 'ascending', + rledir: 'ascending', rllimit: 'max', rlelimit: 'max', format: 'json', @@ -1087,10 +1163,12 @@ describe('reading lists', function() { }) .finally(() => scope.done()) .then(function (res) { + res.body['continue-from'] = '' assert.deepEqual(res.status, 200); assert.deepEqual(res.body, { lists: lists, entries: entries, + 'continue-from': '', }); }); }); @@ -1103,6 +1181,10 @@ describe('reading lists', function() { list: 'readinglistentries', rlchangedsince: '2017-10-15T00:00:00Z', rlechangedsince: '2017-10-15T00:00:00Z', + rlsort: 'updated', + rlesort: 'updated', + rldir: 'ascending', + rledir: 'ascending', rllimit: 'max', rlelimit: 'max', format: 'json', @@ -1128,11 +1210,13 @@ describe('reading lists', function() { }) .finally(() => scope.done()) .then(function (res) { + res.body['continue-from'] = '' assert.deepEqual(res.status, 200); assert.deepEqual(res.body, { lists: lists.slice(0, 1), entries: entries.slice(0, 1), next: '{"rlcontinue":1,"rlecontinue":1,"continue":"-||"}', + 'continue-from': '', }); }); }); @@ -1145,6 +1229,10 @@ describe('reading lists', function() { list: 'readinglistentries', rlchangedsince: '2017-10-15T00:00:00Z', rlechangedsince: '2017-10-15T00:00:00Z', + rlsort: 'updated', + rlesort: 'updated', + rldir: 'ascending', + rledir: 'ascending', rllimit: 'max', rlelimit: 'max', rlcontinue: 1, From 26d1ebed681cba632d62f96559c58d03a48944f5 Mon Sep 17 00:00:00 2001 From: Mateus Santos Date: Thu, 30 Aug 2018 19:16:35 -0300 Subject: [PATCH 3/5] Finish tests for reading lists service Removing nock event after the the reading lists test is complete Bug: T184545 --- test/features/lists.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/features/lists.js b/test/features/lists.js index 7ea6efc8a..b9b2177d2 100644 --- a/test/features/lists.js +++ b/test/features/lists.js @@ -64,6 +64,10 @@ describe('reading lists', function() { })); }); + after(function() { + nock.emitter.removeAllListeners('no match'); + }); + afterEach(function() { nock.cleanAll(); }); From 53babb15cd7913883cb44e38206e5f750a65a4df Mon Sep 17 00:00:00 2001 From: Mateus Santos Date: Thu, 30 Aug 2018 19:40:08 -0300 Subject: [PATCH 4/5] Finish tests for reading lists service Changing removeAllListeners to removeListener Bug: T184545 --- test/features/lists.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/test/features/lists.js b/test/features/lists.js index b9b2177d2..5f3f3648c 100644 --- a/test/features/lists.js +++ b/test/features/lists.js @@ -49,6 +49,12 @@ describe('reading lists', function() { this.timeout(20000); + function unmockedListener(req) { + if (!req.href.startsWith(`${config.baseURL}/data/lists/`)) { + throw Error(`Unmocked request to ${req.href}`); + } + } + before(function() { //nock.recorder.rec(); return server.start() @@ -57,15 +63,11 @@ describe('reading lists', function() { uri: `${config.baseURL}/page/html/Main_Page`, })) // After this, there should be no unmocked requests other than those to /lists - .then(() => nock.emitter.on('no match', req => { - if (!req.href.startsWith(`${config.baseURL}/data/lists/`)) { - throw Error(`Unmocked request to ${req.href}`); - } - })); + .then(() => nock.emitter.on('no match', unmockedListener)); }); after(function() { - nock.emitter.removeAllListeners('no match'); + nock.emitter.removeListener('no match', unmockedListener); }); afterEach(function() { From 972e3686d293c854a4dd88860b3d73605a892760 Mon Sep 17 00:00:00 2001 From: Mateus Santos Date: Fri, 31 Aug 2018 09:49:24 -0300 Subject: [PATCH 5/5] Fixing lint issues Skiping console-log rules in one line --- test/features/lists.js | 252 ++++++++++++++++++++--------------------- 1 file changed, 126 insertions(+), 126 deletions(-) diff --git a/test/features/lists.js b/test/features/lists.js index 5f3f3648c..723cd7403 100644 --- a/test/features/lists.js +++ b/test/features/lists.js @@ -41,10 +41,11 @@ describe('reading lists', function() { assert.deepEqual(actual, expected, 'nock failure'); return true; } catch (e) { + // eslint-disable-next-line no-console console.log(e); return false; } - } + }; } this.timeout(20000); @@ -55,8 +56,7 @@ describe('reading lists', function() { } } - before(function() { - //nock.recorder.rec(); + before(() => { return server.start() // Do a preparation request to force siteinfo fetch so that we don't need to mock it .then(() => preq.get({ @@ -66,16 +66,16 @@ describe('reading lists', function() { .then(() => nock.emitter.on('no match', unmockedListener)); }); - after(function() { + after(() => { nock.emitter.removeListener('no match', unmockedListener); }); - afterEach(function() { + afterEach(() => { nock.cleanAll(); }); - describe('POST /lists/setup', function() { - it('forward call', function() { + describe('POST /lists/setup', () => { + it('forward call', () => { const scope = getApi() .post(config.apiPath, nockDiff({ action: 'readinglists', @@ -96,12 +96,12 @@ describe('reading lists', function() { }, }) .finally(() => scope.done()) - .then(res => { + .then((res) => { assert.deepEqual(res.status, 200); }); }); - it('error handling', function() { + it('error handling', () => { const scope = getApi() .post(config.apiPath, nockDiff({ action: 'readinglists', @@ -116,7 +116,7 @@ describe('reading lists', function() { info: 'Invalid CSRF token.', }, }, { - 'MediaWiki-API-Error': 'badtoken', + 'MediaWiki-API-Error': 'badtoken', }); return preq.post({ @@ -132,7 +132,7 @@ describe('reading lists', function() { .tap(() => { throw new Error('should not have succeeded'); }) - .catch({ name: 'HTTPError' }, res => { + .catch({ name: 'HTTPError' }, (res) => { assert.deepEqual(res.status, 400); assert.deepEqual(res.body.title, 'badtoken'); assert.deepEqual(res.body.detail, 'Invalid CSRF token.'); @@ -140,8 +140,8 @@ describe('reading lists', function() { }); }); - describe('POST /lists/teardown', function() { - it('forward call', function() { + describe('POST /lists/teardown', () => { + it('forward call', () => { const scope = getApi() .post(config.apiPath, nockDiff({ action: 'readinglists', @@ -162,13 +162,13 @@ describe('reading lists', function() { }, }) .finally(() => scope.done()) - .then(function (res) { + .then((res) => { assert.deepEqual(res.status, 200); }); }); }); - describe('GET /lists/', function() { + describe('GET /lists/', () => { const listEntry = { id: 1, name: 'default', @@ -183,7 +183,7 @@ describe('reading lists', function() { listOrder: [ 1, 2 ], }; - it('forward call', function() { + it('forward call', () => { const scope = getApi() .post(config.apiPath, nockDiff({ action: 'query', @@ -207,9 +207,9 @@ describe('reading lists', function() { }, }) .finally(() => scope.done()) - .then(function (res) { + .then((res) => { // override continue-from timestamp - res.body['continue-from'] = '' + res.body['continue-from'] = ''; assert.deepEqual(res.status, 200); assert.deepEqual(res.body, { lists: [ listEntry ], @@ -218,7 +218,7 @@ describe('reading lists', function() { }); }); - it('paging', function() { + it('paging', () => { const scope = getApi() .post(config.apiPath, nockDiff({ action: 'query', @@ -246,9 +246,9 @@ describe('reading lists', function() { }, }) .finally(() => scope.done()) - .then(function (res) { + .then((res) => { // override continue-from timestamp - res.body['continue-from'] = '' + res.body['continue-from'] = ''; assert.deepEqual(res.status, 200); assert.deepEqual(res.body, { lists: [ listEntry ], @@ -258,7 +258,7 @@ describe('reading lists', function() { }); }); - it('paging 2', function() { + it('paging 2', () => { const scope = getApi() .post(config.apiPath, nockDiff({ action: 'query', @@ -287,9 +287,9 @@ describe('reading lists', function() { }, }) .finally(() => scope.done()) - .then(function (res) { + .then((res) => { // override continue-from timestamp - res.body['continue-from'] = '' + res.body['continue-from'] = ''; assert.deepEqual(res.status, 200); assert.deepEqual(res.body, { lists: [ listEntry ], @@ -298,7 +298,7 @@ describe('reading lists', function() { }); }); - it('paging error', function() { + it('paging error', () => { const scope = getApi(); return preq.get({ @@ -314,7 +314,7 @@ describe('reading lists', function() { .tap(() => { throw new Error('should not have succeeded'); }) - .catch({ name: 'HTTPError' }, res => { + .catch({ name: 'HTTPError' }, (res) => { assert.deepEqual(res.status, 400); assert.deepEqual(res.body.type, 'https://mediawiki.org/wiki/HyperSwitch/errors/server_error#invalid_paging_parameter'); @@ -322,8 +322,8 @@ describe('reading lists', function() { }); }); - describe('POST /lists/', function() { - it('forward call', function() { + describe('POST /lists/', () => { + it('forward call', () => { const scope = getApi() .post(config.apiPath, nockDiff({ action: 'readinglists', @@ -358,22 +358,22 @@ describe('reading lists', function() { }, }) .finally(() => scope.done()) - .then(function (res) { + .then((res) => { assert.deepEqual(res.status, 200); assert.deepEqual(res.body.id, 2); }); }); }); - describe('PUT /lists/{id}', function() { - it('forward call', function() { + describe('PUT /lists/{id}', () => { + it('forward call', () => { const scope = getApi() .post(config.apiPath, nockDiff({ action: 'readinglists', command: 'update', list: 2, name: 'Test list!', - description: 'Lorem ipsum dolor sit amet, integre fabellas partiendo has ei.', + description: 'Lorem ipsum dolor sit amet', token: csrfToken, format: 'json', formatversion: '2', @@ -384,7 +384,7 @@ describe('reading lists', function() { list: { id: 2, name: 'Test list!', - description: 'Lorem ipsum dolor sit amet, integre fabellas partiendo has ei.', + description: 'Lorem ipsum dolor sit amet', } } }); @@ -396,7 +396,7 @@ describe('reading lists', function() { }, body: { name: 'Test list!', - description: 'Lorem ipsum dolor sit amet, integre fabellas partiendo has ei.', + description: 'Lorem ipsum dolor sit amet', color: 'blue', image: 'Bar.png', icon: 'bar', @@ -407,14 +407,14 @@ describe('reading lists', function() { }, }) .finally(() => scope.done()) - .then(function (res) { + .then((res) => { assert.deepEqual(res.status, 200); }); }); }); - describe('DELETE /lists/{id}', function() { - it('forward call', function() { + describe('DELETE /lists/{id}', () => { + it('forward call', () => { const scope = getApi() .post(config.apiPath, nockDiff({ action: 'readinglists', @@ -436,24 +436,24 @@ describe('reading lists', function() { }, }) .finally(() => scope.done()) - .then(function (res) { + .then((res) => { assert.deepEqual(res.status, 200); }); }); }); - describe('POST /lists/batch', function() { - it('forward call', function() { + describe('POST /lists/batch', () => { + it('forward call', () => { const batchLists = [ - { - name: 'Test batch list item 1', - description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit unus.' - }, - { - name: 'Test batch list item 2', - description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit duo.' - }, - ] + { + name: 'Test batch list item 1', + description: 'Lorem ipsum dolor sit amet unus.' + }, + { + name: 'Test batch list item 2', + description: 'Lorem ipsum dolor sit amet duo.' + }, + ]; const scope = getApi() .post(config.apiPath, nockDiff({ action: 'readinglists', @@ -470,14 +470,14 @@ describe('reading lists', function() { { id: 1, name: 'Test batch list item 1', - description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit unus.', + description: 'Lorem ipsum dolor sit amet unus.', created: '2018-08-30T13:44:04.242Z', updated: '2018-08-30T13:44:04.242Z', }, { id: 2, name: 'Test batch list item 2', - description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit duo.', + description: 'Lorem ipsum dolor sit amet duo.', created: '2018-08-30T13:44:04.242Z', updated: '2018-08-30T13:44:04.242Z', }, @@ -499,7 +499,7 @@ describe('reading lists', function() { }, }) .finally(() => scope.done()) - .then(function (res) { + .then((res) => { assert.deepEqual(res.status, 200); assert.deepEqual(res.body, { batch: [ @@ -514,14 +514,14 @@ describe('reading lists', function() { { id: 1, name: 'Test batch list item 1', - description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit unus.', + description: 'Lorem ipsum dolor sit amet unus.', created: '2018-08-30T13:44:04.242Z', updated: '2018-08-30T13:44:04.242Z' }, { id: 2, name: 'Test batch list item 2', - description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit duo.', + description: 'Lorem ipsum dolor sit amet duo.', created: '2018-08-30T13:44:04.242Z', updated: '2018-08-30T13:44:04.242Z' }, @@ -531,7 +531,7 @@ describe('reading lists', function() { }); }); - describe('GET /lists/{id}/entries/', function() { + describe('GET /lists/{id}/entries/', () => { const entries = [ { id: 10, @@ -586,7 +586,7 @@ describe('reading lists', function() { .defaultReplyHeaders({ 'Content-Type': 'application/json; charset=utf-8', }) - .post(config.apiPath, query => { + .post(config.apiPath, (query) => { const params = (typeof query === 'string') ? querystring.parse(query) : query; return params.action === 'query' && params.meta === 'siteinfo|filerepoinfo' && !params.list && !params.prop; @@ -621,7 +621,7 @@ describe('reading lists', function() { }); } - it('forward call', function() { + it('forward call', () => { const scope = getApi() .post(config.apiPath, nockDiff({ action: 'query', @@ -654,7 +654,7 @@ describe('reading lists', function() { scope.done(); scope2.done(); }) - .then(function (res) { + .then((res) => { assert.deepEqual(res.status, 200); assert.deepEqual(res.body, { entries: expectedEntries, @@ -662,7 +662,7 @@ describe('reading lists', function() { }); }); - it('paging', function() { + it('paging', () => { const scope = getApi() .post(config.apiPath, nockDiff({ action: 'query', @@ -697,7 +697,7 @@ describe('reading lists', function() { scope.done(); scope2.done(); }) - .then(function (res) { + .then((res) => { assert.deepEqual(res.status, 200); assert.deepEqual(res.body, { entries: expectedEntries.slice(0, 1), @@ -706,7 +706,7 @@ describe('reading lists', function() { }); }); - it('paging2', function() { + it('paging2', () => { const scope = getApi() .post(config.apiPath, nockDiff({ action: 'query', @@ -742,7 +742,7 @@ describe('reading lists', function() { scope.done(); scope2.done(); }) - .then(function (res) { + .then((res) => { assert.deepEqual(res.status, 200); assert.deepEqual(res.body, { entries: expectedEntries.slice(1), @@ -750,7 +750,7 @@ describe('reading lists', function() { }); }); - it('no cookie forwarding to unknown domains', function() { + it('no cookie forwarding to unknown domains', () => { const entries = [ { id: 1, @@ -788,14 +788,14 @@ describe('reading lists', function() { .finally(() => { scope.done(); }) - .then(function (res) { + .then((res) => { assert.deepEqual(res.status, 200); }); }); }); - describe('POST /lists/{id}/entries/', function() { - it('forward call', function() { + describe('POST /lists/{id}/entries/', () => { + it('forward call', () => { const scope = getApi() .post(config.apiPath, nockDiff({ action: 'readinglists', @@ -828,7 +828,7 @@ describe('reading lists', function() { }, }) .finally(() => scope.done()) - .then(function (res) { + .then((res) => { assert.deepEqual(res.status, 200); assert.deepEqual(res.body.id, 1); }); @@ -836,8 +836,8 @@ describe('reading lists', function() { }); - describe('DELETE /lists/{id}/entries/{entry_id}', function() { - it('forward call', function() { + describe('DELETE /lists/{id}/entries/{entry_id}', () => { + it('forward call', () => { const scope = getApi() .post(config.apiPath, nockDiff({ action: 'readinglists', @@ -859,24 +859,24 @@ describe('reading lists', function() { }, }) .finally(() => scope.done()) - .then(function (res) { + .then((res) => { assert.deepEqual(res.status, 200); }); }); }); - describe('POST /lists/{id}/entries/batch', function() { - it('forward call', function() { + describe('POST /lists/{id}/entries/batch', () => { + it('forward call', () => { const batchEntries = [ - { - project: 'en.wikipedia.org', - title: 'Foobar', - }, - { - project: 'en.wikipedia.org', - title: 'Dog', - }, - ] + { + project: 'en.wikipedia.org', + title: 'Foobar', + }, + { + project: 'en.wikipedia.org', + title: 'Dog', + }, + ]; const scope = getApi() .post(config.apiPath, nockDiff({ action: 'readinglists', @@ -923,39 +923,39 @@ describe('reading lists', function() { }, }) .finally(() => scope.done()) - .then(function (res) { + .then((res) => { assert.deepEqual(res.status, 200); assert.deepEqual(res.body, { - batch: [ - { - id: 2, - }, - { - id: 3 - }, - ], - entries: [ - { - id: 2, - project: 'en.wikipedia.org', - title: 'Foobar', - created: '2018-08-30T13:44:04.276Z', - updated: '2018-08-30T13:44:04.276Z' - }, - { - id: 3, - project: 'en.wikipedia.org', - title: 'Dog', - created: '2018-08-30T13:44:04.276Z', - updated: '2018-08-30T13:44:04.276Z' - }, - ], - }); + batch: [ + { + id: 2, + }, + { + id: 3 + }, + ], + entries: [ + { + id: 2, + project: 'en.wikipedia.org', + title: 'Foobar', + created: '2018-08-30T13:44:04.276Z', + updated: '2018-08-30T13:44:04.276Z' + }, + { + id: 3, + project: 'en.wikipedia.org', + title: 'Dog', + created: '2018-08-30T13:44:04.276Z', + updated: '2018-08-30T13:44:04.276Z' + }, + ], + }); }); }); }); - describe('GET /lists/pages/{project}/{title}', function() { + describe('GET /lists/pages/{project}/{title}', () => { const lists = [ { id: 1, @@ -983,7 +983,7 @@ describe('reading lists', function() { }, ]; - it('forward call', function() { + it('forward call', () => { const scope = getApi() .post(config.apiPath, nockDiff({ action: 'query', @@ -1007,15 +1007,15 @@ describe('reading lists', function() { }, }) .finally(() => scope.done()) - .then(function (res) { + .then((res) => { assert.deepEqual(res.status, 200); assert.deepEqual(res.body, { - lists: lists, + lists, }); }); }); - it('paging', function() { + it('paging', () => { const scope = getApi() .post(config.apiPath, nockDiff({ action: 'query', @@ -1043,7 +1043,7 @@ describe('reading lists', function() { }, }) .finally(() => scope.done()) - .then(function (res) { + .then((res) => { assert.deepEqual(res.status, 200); assert.deepEqual(res.body, { lists: lists.slice(0, 1), @@ -1052,7 +1052,7 @@ describe('reading lists', function() { }); }); - it('paging 2', function() { + it('paging 2', () => { const scope = getApi() .post(config.apiPath, nockDiff({ action: 'query', @@ -1081,7 +1081,7 @@ describe('reading lists', function() { }, }) .finally(() => scope.done()) - .then(function (res) { + .then((res) => { assert.deepEqual(res.status, 200); assert.deepEqual(res.body, { lists: lists.slice(1), @@ -1090,7 +1090,7 @@ describe('reading lists', function() { }); }); - describe('GET /lists/changes/since/{date}', function() { + describe('GET /lists/changes/since/{date}', () => { const lists = [ { id: 1, @@ -1137,7 +1137,7 @@ describe('reading lists', function() { }, ]; - it('forward call', function() { + it('forward call', () => { const scope = getApi() .post(config.apiPath, nockDiff({ action: 'query', @@ -1168,18 +1168,18 @@ describe('reading lists', function() { }, }) .finally(() => scope.done()) - .then(function (res) { - res.body['continue-from'] = '' + .then((res) => { + res.body['continue-from'] = ''; assert.deepEqual(res.status, 200); assert.deepEqual(res.body, { - lists: lists, - entries: entries, + lists, + entries, 'continue-from': '', }); }); }); - it('paging', function() { + it('paging', () => { const scope = getApi() .post(config.apiPath, nockDiff({ action: 'query', @@ -1215,8 +1215,8 @@ describe('reading lists', function() { }, }) .finally(() => scope.done()) - .then(function (res) { - res.body['continue-from'] = '' + .then((res) => { + res.body['continue-from'] = ''; assert.deepEqual(res.status, 200); assert.deepEqual(res.body, { lists: lists.slice(0, 1), @@ -1227,7 +1227,7 @@ describe('reading lists', function() { }); }); - it('paging 2', function() { + it('paging 2', () => { const scope = getApi() .post(config.apiPath, nockDiff({ action: 'query', @@ -1264,7 +1264,7 @@ describe('reading lists', function() { }, }) .finally(() => scope.done()) - .then(function (res) { + .then((res) => { assert.deepEqual(res.status, 200); assert.deepEqual(res.body, { lists: lists.slice(1),